[PATCH 0/7] Add HDMI audio support on RK3288 veyron board

2019-06-02 Thread Cheng-Yi Chiang
This patch series is to support HDMI audio on RK3288 veyron board.

To support jack reporting, there are two old patches:

video: add HDMI state notifier support

<https://lore.kernel.org/linux-media/20161213150813.37966-2-hverk...@xs4all.nl/>

ASoC: hdmi-codec: use HDMI state notifier to add jack support

<https://patchwork.kernel.org/patch/9430355/>

They are modified to pass checkpatch checking based on latest ASoC tree

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

for-next branch.

With these two patches at hand, hdmi-notifier support is then added to dw-hdmi
driver so the plug/unplug event can be passed to codec driver.

The rest patches are about machine driver rockchip_max98090.
A HDMI DAI link is added for HDMI playback so there will be two devices on
this sound card. One for max98090 and one for HDMI.
The HDMI node is passed from DTS so machine driver can set the correct
hdmi-notifier on codec driver.

Cheng-Yi Chiang (5):
  drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip: rockchip-max98090: Add node for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support
  ARM: dts: rockchip: Specify HDMI node to sound card node

Hans Verkuil (1):
  video: add HDMI state notifier support

Philipp Zabel (1):
  ASoC: hdmi-codec: use HDMI state notifier to add jack support

 .../bindings/sound/rockchip-max98090.txt  |   2 +
 MAINTAINERS   |   6 +
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
 drivers/gpu/drm/bridge/synopsys/Kconfig   |   1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  28 +++-
 drivers/video/Kconfig |   3 +
 drivers/video/Makefile|   1 +
 drivers/video/hdmi-notifier.c | 145 ++
 include/linux/hdmi-notifier.h | 112 ++
 include/sound/hdmi-codec.h|   7 +
 sound/soc/codecs/Kconfig  |   1 +
 sound/soc/codecs/hdmi-codec.c | 104 -
 sound/soc/rockchip/rockchip_max98090.c| 123 ---
 13 files changed, 508 insertions(+), 26 deletions(-)
 create mode 100644 drivers/video/hdmi-notifier.c
 create mode 100644 include/linux/hdmi-notifier.h

-- 
2.22.0.rc1.257.g3120a18244-goog



[PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support

2019-06-02 Thread Cheng-Yi Chiang
From: Philipp Zabel 

Use HDMI connection / disconnection notifications to update an ALSA
jack object. Also make a copy of the ELD block after every change.

This was posted by Philipp Zabel at

https://patchwork.kernel.org/patch/9430747/

Modified by Cheng-Yi Chiang:
- Fix the conflict of removed hdmi_codec_remove ops.
- Other minor fix for the conflict with latest hdmi-codec on ASoC
  for-next tree.

Signed-off-by: Philipp Zabel 
Signed-off-by: Cheng-Yi Chiang 
---
The original patch is at https://patchwork.kernel.org/patch/9430747/
I could not find the LKML link for the patch.

 include/sound/hdmi-codec.h|   7 +++
 sound/soc/codecs/Kconfig  |   1 +
 sound/soc/codecs/hdmi-codec.c | 104 +-
 3 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 9483c55f871b..4fa39c93363f 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -107,6 +107,13 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack,
+  struct device *dev);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8f577258080b..f5f6dd04234c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -639,6 +639,7 @@ config SND_SOC_HDMI_CODEC
select SND_PCM_ELD
select SND_PCM_IEC958
select HDMI
+   select HDMI_NOTIFIERS
 
 config SND_SOC_ES7134
tristate "Everest Semi ES7134 CODEC"
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 6a0cc8d7e141..fe796a7475a5 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -12,9 +12,12 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * General Public License for more details.
  */
+#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -282,6 +285,13 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   /* Lock to protect setting and getting eld. */
+   struct mutex eld_lock;
+   struct device *dev;
+   struct hdmi_notifier *notifier;
+   struct notifier_block nb;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -308,7 +318,9 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
 
+   mutex_lock(&hcp->eld_lock);
memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld));
+   mutex_unlock(&hcp->eld_lock);
 
return 0;
 }
@@ -393,7 +405,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream 
*substream,
  struct snd_soc_dai *dai)
 {
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
-   int ret = 0;
+   int ret;
 
ret = mutex_trylock(&hcp->lock);
if (!ret) {
@@ -408,9 +420,9 @@ static int hdmi_codec_startup(struct snd_pcm_substream 
*substream,
}
 
if (hcp->hcd.ops->get_eld) {
+   mutex_lock(&hcp->eld_lock);
ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
hcp->eld, sizeof(hcp->eld));
-
if (!ret) {
ret = snd_pcm_hw_constraint_eld(substream->runtime,
hcp->eld);
@@ -419,6 +431,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream 
*substream,
}
/* Select chmap supported */
hdmi_codec_eld_chmap(hcp);
+   mutex_unlock(&hcp->eld_lock);
}
return 0;
 
@@ -747,6 +760,77 @@ static const struct snd_soc_component_driver hdmi_driver = 
{
.non_legacy_dai_naming  = 1,
 };
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (!hcp->jack)
+   return;
+
+   if (jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static int hdmi_codec_notify(struct notifier_block *nb, unsigned long event,
+void *data)
+{
+   struct hdmi_codec_priv *hcp = container_of(nb, struct hdmi_codec_priv,
+

[PATCH 6/7] ASoC: rockchip_max98090: Add HDMI jack support

2019-06-02 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 41 ++
 1 file changed, 41 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 2dd247670c7a..17c50d9fbac1 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -18,6 +18,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "rockchip_i2s.h"
 #include "../codecs/ts3a227e.h"
@@ -131,6 +133,26 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   struct device *hdmi_dev = snd_soc_card_get_drvdata(card);
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack, hdmi_dev);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -148,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
}
 };
 
@@ -200,6 +223,8 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct device_node *np_cpu;
struct of_phandle_args args;
+   struct device_node *np_hdmi;
+   struct platform_device *hdmi_pdev;
 
/* register the soc card */
card->dev = &pdev->dev;
@@ -248,6 +273,22 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
return -EINVAL;
}
 
+   /* The hdmi device handles HDMI hotplug detection */
+   np_hdmi = of_parse_phandle(np, "rockchip,hdmi", 0);
+   if (!np_hdmi) {
+   dev_err(&pdev->dev, "Failed to find HDMI node\n");
+   return -EINVAL;
+   }
+
+   hdmi_pdev = of_find_device_by_node(np_hdmi);
+   if (!hdmi_pdev) {
+   dev_err(&pdev->dev, "Waiting for HDMI device %s\n",
+   np_hdmi->full_name);
+   return -EPROBE_DEFER;
+   }
+
+   snd_soc_card_set_drvdata(card, &hdmi_pdev->dev);
+
ret = snd_soc_of_parse_card_name(card, "rockchip,model");
if (ret) {
dev_err(&pdev->dev,
-- 
2.22.0.rc1.257.g3120a18244-goog



[PATCH 1/7] video: add HDMI state notifier support

2019-06-02 Thread Cheng-Yi Chiang
From: Hans Verkuil 

Add support for HDMI hotplug and EDID notifiers, which is used to convey
information from HDMI drivers to their CEC and audio counterparts.

Based on an earlier version from Russell King:

https://patchwork.kernel.org/patch/9277043/

The hdmi_notifier is a reference counted object containing the HDMI state
of an HDMI device.

When a new notifier is registered the current state will be reported to
that notifier at registration time.

Based on Hans Verkuil's patch:

https://patchwork.kernel.org/patch/9472521/

Modified by Cheng-Yi Chiang:
 - Add a section in MAINTAINER.
 - Changes connected and has_eld to bitfield of unsigned int.
 - Other minor fixes to pass checkpatch.pl --strict checks.

Signed-off-by: Hans Verkuil 
Acked-by: Philipp Zabel 
Signed-off-by: Cheng-Yi Chiang 
---
The original patch is at
https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverk...@xs4all.nl

 MAINTAINERS   |   6 ++
 drivers/video/Kconfig |   3 +
 drivers/video/Makefile|   1 +
 drivers/video/hdmi-notifier.c | 145 ++
 include/linux/hdmi-notifier.h | 112 ++
 5 files changed, 267 insertions(+)
 create mode 100644 drivers/video/hdmi-notifier.c
 create mode 100644 include/linux/hdmi-notifier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5cfbea4ce575..ffb7376f9509 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16676,6 +16676,12 @@ W: https://linuxtv.org
 S: Maintained
 F: drivers/media/platform/vicodec/*
 
+VIDEO FRAMEWORK
+M: Hans Verkuil 
+L: linux-me...@vger.kernel.org
+F: drivers/video/hdmi-notifier.*
+S: Maintained
+
 VIDEO MULTIPLEXER DRIVER
 M: Philipp Zabel 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 83d3d271ca15..000ba9bc0ae7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
 config HDMI
bool
 
+config HDMI_NOTIFIERS
+   bool
+
 endif # HAS_IOMEM
 
 if VT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index df7650adede9..eff4736102ca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_VGASTATE)+= vgastate.o
 obj-$(CONFIG_HDMI)+= hdmi.o
+obj-$(CONFIG_HDMI_NOTIFIERS)  += hdmi-notifier.o
 
 obj-$(CONFIG_VT) += console/
 obj-$(CONFIG_FB_STI) += console/
diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
new file mode 100644
index ..d1eedf661648
--- /dev/null
+++ b/drivers/video/hdmi-notifier.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
+ * events
+ *
+ * Copyright 2016 Russell King 
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static LIST_HEAD(hdmi_notifiers);
+static DEFINE_MUTEX(hdmi_notifiers_lock);
+
+struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
+{
+   struct hdmi_notifier *n;
+
+   mutex_lock(&hdmi_notifiers_lock);
+   list_for_each_entry(n, &hdmi_notifiers, head) {
+   if (n->dev == dev) {
+   mutex_unlock(&hdmi_notifiers_lock);
+   kref_get(&n->kref);
+   return n;
+   }
+   }
+   n = kzalloc(sizeof(*n), GFP_KERNEL);
+   if (!n)
+   goto unlock;
+   n->dev = dev;
+   mutex_init(&n->lock);
+   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
+   kref_init(&n->kref);
+   list_add_tail(&n->head, &hdmi_notifiers);
+unlock:
+   mutex_unlock(&hdmi_notifiers_lock);
+   return n;
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_get);
+
+static void hdmi_notifier_release(struct kref *kref)
+{
+   struct hdmi_notifier *n =
+   container_of(kref, struct hdmi_notifier, kref);
+
+   mutex_lock(&hdmi_notifiers_lock);
+   list_del(&n->head);
+   mutex_unlock(&hdmi_notifiers_lock);
+   kfree(n->edid);
+   kfree(n);
+}
+
+void hdmi_notifier_put(struct hdmi_notifier *n)
+{
+   kref_put(&n->kref, hdmi_notifier_release);
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_put);
+
+int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
+{
+   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
+
+   if (ret)
+   return ret;
+   kref_get(&n->kref);
+   mutex_lock(&n->lock);
+   if (n->connected) {
+   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
+   if (n->edid_size)
+   blocking_notifier_call_chain(&n->notifiers,
+ 

[PATCH 3/7] drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support

2019-06-02 Thread Cheng-Yi Chiang
Use hdmi-notifier to notify codec driver that there is HDMI plug/unplug
event.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/Kconfig   |  1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 +--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig 
b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 3cc53b44186e..43192d9d7357 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -3,6 +3,7 @@ config DRM_DW_HDMI
select DRM_KMS_HELPER
select REGMAP_MMIO
select CEC_CORE if CEC_NOTIFIER
+   select HDMI_NOTIFIERS
 
 config DRM_DW_HDMI_AHB_AUDIO
tristate "Synopsys Designware AHB Audio interface"
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ab7968c8f6a2..53701921eb1f 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -190,6 +191,7 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+   struct hdmi_notifier *hdmi_notifier;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -2301,8 +2303,15 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
}
 
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
-   dev_dbg(hdmi->dev, "EVENT=%s\n",
-   phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
+   if (phy_int_pol & HDMI_PHY_HPD) {
+   dev_dbg(hdmi->dev, "EVENT=plugin\n");
+   if (hdmi->hdmi_notifier)
+   hdmi_event_connect(hdmi->hdmi_notifier);
+   } else {
+   dev_dbg(hdmi->dev, "EVENT=plugout\n");
+   if (hdmi->hdmi_notifier)
+   hdmi_event_disconnect(hdmi->hdmi_notifier);
+   }
if (hdmi->bridge.dev)
drm_helper_hpd_irq_event(hdmi->bridge.dev);
}
@@ -2606,6 +2615,12 @@ __dw_hdmi_probe(struct platform_device *pdev,
goto err_iahb;
}
 
+   hdmi->hdmi_notifier = hdmi_notifier_get(dev);
+   if (!hdmi->hdmi_notifier) {
+   ret = -ENOMEM;
+   goto err_iahb;
+   }
+
/*
 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
 * N and cts values before enabling phy
@@ -2696,6 +2711,9 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (hdmi->cec_notifier)
cec_notifier_put(hdmi->cec_notifier);
 
+   if (hdmi->hdmi_notifier)
+   hdmi_notifier_put(hdmi->hdmi_notifier);
+
clk_disable_unprepare(hdmi->iahb_clk);
if (hdmi->cec_clk)
clk_disable_unprepare(hdmi->cec_clk);
@@ -2709,6 +2727,9 @@ __dw_hdmi_probe(struct platform_device *pdev,
 
 static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 {
+   if (hdmi->hdmi_notifier)
+   hdmi_event_disconnect(hdmi->hdmi_notifier);
+
if (hdmi->audio && !IS_ERR(hdmi->audio))
platform_device_unregister(hdmi->audio);
if (!IS_ERR(hdmi->cec))
@@ -2720,6 +2741,9 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
if (hdmi->cec_notifier)
cec_notifier_put(hdmi->cec_notifier);
 
+   if (hdmi->hdmi_notifier)
+   hdmi_notifier_put(hdmi->hdmi_notifier);
+
clk_disable_unprepare(hdmi->iahb_clk);
clk_disable_unprepare(hdmi->isfr_clk);
if (hdmi->cec_clk)
-- 
2.22.0.rc1.257.g3120a18244-goog



[PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node for HDMI

2019-06-02 Thread Cheng-Yi Chiang
Let user specify HDMI node so machine driver can use it to let codec
driver register callback on correct hdmi-notifier.

Signed-off-by: Cheng-Yi Chiang 
---
 Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt 
b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
index a805aa99ad75..dae57c14864e 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
@@ -7,6 +7,7 @@ Required properties:
   connected to the CODEC
 - rockchip,audio-codec: The phandle of the MAX98090 audio codec
 - rockchip,headset-codec: The phandle of Ext chip for jack detection
+- rockchip,hdmi: The phandle of HDMI node for HDMI jack detection
 
 Example:
 
@@ -16,4 +17,5 @@ sound {
rockchip,i2s-controller = <&i2s>;
rockchip,audio-codec = <&max98090>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi= <&hdmi>;
 };
-- 
2.22.0.rc1.257.g3120a18244-goog



[PATCH 7/7] ARM: dts: rockchip: Specify HDMI node to sound card node

2019-06-02 Thread Cheng-Yi Chiang
Sound card needs HDMI node in order to register jack callback on HDMI
notifier.

Signed-off-by: Cheng-Yi Chiang 
---
 arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi 
b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
index 445270aa136e..096ba4e96db2 100644
--- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
@@ -14,6 +14,7 @@
rockchip,model = "VEYRON-I2S";
rockchip,i2s-controller = <&i2s>;
rockchip,audio-codec = <&max98090>;
+   rockchip,hdmi= <&hdmi>;
rockchip,hp-det-gpios = <&gpio6 RK_PA5 GPIO_ACTIVE_HIGH>;
rockchip,mic-det-gpios = <&gpio6 RK_PB3 GPIO_ACTIVE_LOW>;
rockchip,headset-codec = <&headsetcodec>;
-- 
2.22.0.rc1.257.g3120a18244-goog



[PATCH 4/7] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-06-02 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 82 +++---
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 789d6f1e2b5f..2dd247670c7a 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -53,6 +53,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -64,6 +65,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -71,6 +73,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -104,33 +107,48 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret && ret != -ENOTSUPP) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret && ret != -ENOTSUPP) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .codec_dai_name = "HiFi",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .codec_name = "hdmi-audio-codec.3.auto",
+   .codec_dai_name = "i2s-hifi",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   }
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -143,8 +161,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
-   .dai_link = &rk_dailink,
-   .num_links = 1,
+   .dai_link = rk_dailinks,
+   .num_links = ARRAY_SIZE(rk_dailinks),
.aux_dev = &rk_98090_headset_dev,
.num_aux_devs = 1,
.dapm_widgets = rk_dapm_widgets,
@@ -180,27 +198,47 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
int ret = 0;
struct snd_soc_card *card = &snd_soc_card_rk;
struct device_node *np = pdev->dev.of_node;
+   struct device_node *np_cpu;
+   struct of_phandle_args args;
 
/* register the soc card */
card->dev = &pdev->dev;
 
-   rk_dailink.codec_of_node = of_parse_phandle(np,
-   "rockchip,audio-codec", 0);
-   if (!rk_dailink.codec_of_node) {
+   rk_dailinks[DAILINK_MAX98090].codec_of_node =
+   of_parse_phandle(np, "r

Re: [alsa-devel] [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support

2019-06-03 Thread Cheng-yi Chiang
On Mon, Jun 3, 2019 at 3:59 PM Amadeusz Sławiński
 wrote:
>
> On Mon,  3 Jun 2019 12:32:46 +0800
> Cheng-Yi Chiang  wrote:
>
> > From: Philipp Zabel 
> >
> > Use HDMI connection / disconnection notifications to update an ALSA
> > jack object. Also make a copy of the ELD block after every change.
> >
> > This was posted by Philipp Zabel at
> >
> > https://patchwork.kernel.org/patch/9430747/
> >
> > Modified by Cheng-Yi Chiang:
> > - Fix the conflict of removed hdmi_codec_remove ops.
> > - Other minor fix for the conflict with latest hdmi-codec on ASoC
> >   for-next tree.
> >
> > Signed-off-by: Philipp Zabel 
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> > The original patch is at https://patchwork.kernel.org/patch/9430747/
> > I could not find the LKML link for the patch.
> >
> >  include/sound/hdmi-codec.h|   7 +++
> >  sound/soc/codecs/Kconfig  |   1 +
> >  sound/soc/codecs/hdmi-codec.c | 104
> > +- 3 files changed, 110
> > insertions(+), 2 deletions(-)
> >
> > diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> > index 9483c55f871b..4fa39c93363f 100644
> > --- a/include/sound/hdmi-codec.h
> > +++ b/include/sound/hdmi-codec.h
> > @@ -107,6 +107,13 @@ struct hdmi_codec_pdata {
> >   void *data;
> >  };
> >
> > +struct snd_soc_component;
> > +struct snd_soc_jack;
> > +
> > +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> > +struct snd_soc_jack *jack,
> > +struct device *dev);
> > +
> >  #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
> >
> >  #endif /* __HDMI_CODEC_H__ */
> > diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> > index 8f577258080b..f5f6dd04234c 100644
> > --- a/sound/soc/codecs/Kconfig
> > +++ b/sound/soc/codecs/Kconfig
> > @@ -639,6 +639,7 @@ config SND_SOC_HDMI_CODEC
> >   select SND_PCM_ELD
> >   select SND_PCM_IEC958
> >   select HDMI
> > + select HDMI_NOTIFIERS
> >
> >  config SND_SOC_ES7134
> > tristate "Everest Semi ES7134 CODEC"
> > diff --git a/sound/soc/codecs/hdmi-codec.c
> > b/sound/soc/codecs/hdmi-codec.c index 6a0cc8d7e141..fe796a7475a5
> > 100644 --- a/sound/soc/codecs/hdmi-codec.c
> > +++ b/sound/soc/codecs/hdmi-codec.c
> > @@ -12,9 +12,12 @@
> >   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See
> > the GNU
> >   * General Public License for more details.
> >   */
> > +#include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -282,6 +285,13 @@ struct hdmi_codec_priv {
> >   struct snd_pcm_chmap *chmap_info;
> >   unsigned int chmap_idx;
> >   struct mutex lock;
> > + struct snd_soc_jack *jack;
> > + /* Lock to protect setting and getting eld. */
> > + struct mutex eld_lock;
> > + struct device *dev;
> > + struct hdmi_notifier *notifier;
> > + struct notifier_block nb;
> > + unsigned int jack_status;
> >  };
> >
> >  static const struct snd_soc_dapm_widget hdmi_widgets[] = {
> > @@ -308,7 +318,9 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol
> > *kcontrol, struct snd_soc_component *component =
> > snd_kcontrol_chip(kcontrol); struct hdmi_codec_priv *hcp =
> > snd_soc_component_get_drvdata(component);
> > + mutex_lock(&hcp->eld_lock);
> >   memcpy(ucontrol->value.bytes.data, hcp->eld,
> > sizeof(hcp->eld));
> > + mutex_unlock(&hcp->eld_lock);
> >
> >   return 0;
> >  }
> > @@ -393,7 +405,7 @@ static int hdmi_codec_startup(struct
> > snd_pcm_substream *substream, struct snd_soc_dai *dai)
> >  {
> >   struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
> > - int ret = 0;
> > + int ret;
> >
> >   ret = mutex_trylock(&hcp->lock);
> >   if (!ret) {
> > @@ -408,9 +420,9 @@ static int hdmi_codec_startup(struct
> > snd_pcm_substream *substream, }
> >
> >   if (hcp->hcd.ops->get_eld) {
> > + mutex_lock(&hcp->eld_lock);
> >   ret = hcp->hcd.ops->get_eld(dai->dev->parent,
> > hcp->hcd.data, hcp->eld, sizeof(hcp->eld));
> > -
> >   if (!ret) {
> >   ret =
> > snd_pcm

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-03 Thread Cheng-yi Chiang
On Mon, Jun 3, 2019 at 3:46 PM Hans Verkuil  wrote:
>
> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > From: Hans Verkuil 
> >
> > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > information from HDMI drivers to their CEC and audio counterparts.
> >
> > Based on an earlier version from Russell King:
> >
> > https://patchwork.kernel.org/patch/9277043/
> >
> > The hdmi_notifier is a reference counted object containing the HDMI state
> > of an HDMI device.
> >
> > When a new notifier is registered the current state will be reported to
> > that notifier at registration time.
> >
> > Based on Hans Verkuil's patch:
> >
> > https://patchwork.kernel.org/patch/9472521/
>
> Erm, you are aware that this patch morphed into a CEC-specific notifier
> found in drivers/media/cec/cec-notifier.c?
>
> I don't think it makes sense to have two notifier implementations in the 
> kernel.
> The original intention was to have the notifier deal with both CEC and ASoC
> notifications, but there was not enough interest for the ASoC bits at the time
> and it was dropped.
>
> I am planning changes to the cec-notifier API, I hope to work on that this
> week. I'll CC you when I post those. Those might be a good starting point
> to convert the cec-notifier to an hdmi-notifier as was originally intended.
>
> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> working on some nice cec-notifier improvements as well.

Hi Hans, thank you for quick reply.
I am not aware of the history of cec-notifier and hdmi-notifier.
The reason I took this patch is because its different versions were
used extensively in rockchip tree and chromium tree for years.
And hdmi-notifier patch posted at
https://patchwork.kernel.org/patch/9472521/ did not get objection at
that time.
If you think jack reporting should be supported on cec-notifier
instead, I can look into it after you post the new changes on
cec-notifier.
Thanks!

>
> Regards,
>
> Hans
>
> >
> > Modified by Cheng-Yi Chiang:
> >  - Add a section in MAINTAINER.
> >  - Changes connected and has_eld to bitfield of unsigned int.
> >  - Other minor fixes to pass checkpatch.pl --strict checks.
> >
> > Signed-off-by: Hans Verkuil 
> > Acked-by: Philipp Zabel 
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> > The original patch is at
> > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverk...@xs4all.nl
> >
> >  MAINTAINERS   |   6 ++
> >  drivers/video/Kconfig |   3 +
> >  drivers/video/Makefile|   1 +
> >  drivers/video/hdmi-notifier.c | 145 ++
> >  include/linux/hdmi-notifier.h | 112 ++
> >  5 files changed, 267 insertions(+)
> >  create mode 100644 drivers/video/hdmi-notifier.c
> >  create mode 100644 include/linux/hdmi-notifier.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 5cfbea4ce575..ffb7376f9509 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -16676,6 +16676,12 @@ W:   https://linuxtv.org
> >  S:   Maintained
> >  F:   drivers/media/platform/vicodec/*
> >
> > +VIDEO FRAMEWORK
> > +M:   Hans Verkuil 
> > +L:   linux-me...@vger.kernel.org
> > +F:   drivers/video/hdmi-notifier.*
> > +S:   Maintained
> > +
> >  VIDEO MULTIPLEXER DRIVER
> >  M:   Philipp Zabel 
> >  L:   linux-me...@vger.kernel.org
> > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > index 83d3d271ca15..000ba9bc0ae7 100644
> > --- a/drivers/video/Kconfig
> > +++ b/drivers/video/Kconfig
> > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> >  config HDMI
> >   bool
> >
> > +config HDMI_NOTIFIERS
> > + bool
> > +
> >  endif # HAS_IOMEM
> >
> >  if VT
> > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > index df7650adede9..eff4736102ca 100644
> > --- a/drivers/video/Makefile
> > +++ b/drivers/video/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  obj-$(CONFIG_VGASTATE)+= vgastate.o
> >  obj-$(CONFIG_HDMI)+= hdmi.o
> > +obj-$(CONFIG_HDMI_NOTIFIERS)  += hdmi-notifier.o
> >
> >  obj-$(CONFIG_VT)   += console/
> >  obj-$(CONFIG_FB_STI)   += console/
> > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > new file mode 100644
> > index ..d1eedf661648
> > --- /dev/null
> > +++ b/drivers/video/hdmi-notif

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-03 Thread Cheng-yi Chiang
On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  wrote:
>
> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > From: Hans Verkuil 
> > >
> > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > information from HDMI drivers to their CEC and audio counterparts.
> > >
> > > Based on an earlier version from Russell King:
> > >
> > > https://patchwork.kernel.org/patch/9277043/
> > >
> > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > of an HDMI device.
> > >
> > > When a new notifier is registered the current state will be reported to
> > > that notifier at registration time.
> > >
> > > Based on Hans Verkuil's patch:
> > >
> > > https://patchwork.kernel.org/patch/9472521/
> >
> > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > found in drivers/media/cec/cec-notifier.c?
> >
> > I don't think it makes sense to have two notifier implementations in the 
> > kernel.
> > The original intention was to have the notifier deal with both CEC and ASoC
> > notifications, but there was not enough interest for the ASoC bits at the 
> > time
> > and it was dropped.
> >
> > I am planning changes to the cec-notifier API, I hope to work on that this
> > week. I'll CC you when I post those. Those might be a good starting point
> > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> >
> > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's 
> > been
> > working on some nice cec-notifier improvements as well.
>
> We also have some interfaces for drm/alsa interactions around hdmi
> already in drm/drm_audio_component.h, but it's not used by anything
> outside of i915. Imo we should extend that, not reinvent a new wheel.
>
Hi Daniel,
Thank you for the pointer. Looking at the ops, it seems that it is
specific to HDA.
I am not familiar with drm and HDA. I am not sure how applicable it
would be to report jack status to ASoC.
There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
should be possible.

> Another note: notifiers considered evil, imo. Gets the job done for one
> case, as soon as you have multiple devices and need to make sure you get
> the update for the right one it all comes crashing down. Please create an
> api which registers for updates from a specific device only, plus
> something that has real callbacks (like the drm_audio_component.h thing we
> started already).

To clarify a bit, this hdmi-notifier indeed supports updating from a
specific device only.
hdmi_notifier_get takes a device and return the notifier.

It seems that a major difference between drm_audio_components and
hdmi-notifier is that
drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
On the other hand, hdmi-notifier passes different events using an enum
like HDMI_CONNECTED and let listener handle different events.
In this regard I agree with you that drm_audio_component is cleaner.
Anyway, I will look into it a bit more and see how it works.

Thanks again!

> -Daniel
>
> >
> > Regards,
> >
> >   Hans
> >
> > >
> > > Modified by Cheng-Yi Chiang:
> > >  - Add a section in MAINTAINER.
> > >  - Changes connected and has_eld to bitfield of unsigned int.
> > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > >
> > > Signed-off-by: Hans Verkuil 
> > > Acked-by: Philipp Zabel 
> > > Signed-off-by: Cheng-Yi Chiang 
> > > ---
> > > The original patch is at
> > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverk...@xs4all.nl
> > >
> > >  MAINTAINERS   |   6 ++
> > >  drivers/video/Kconfig |   3 +
> > >  drivers/video/Makefile|   1 +
> > >  drivers/video/hdmi-notifier.c | 145 ++
> > >  include/linux/hdmi-notifier.h | 112 ++
> > >  5 files changed, 267 insertions(+)
> > >  create mode 100644 drivers/video/hdmi-notifier.c
> > >  create mode 100644 include/linux/hdmi-notifier.h
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 5cfbea4ce575..ffb7376f9509 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > >  S: Maintained
> > >  F: drivers/media/platform/vicodec/*
> > >
> > > +VIDEO FRAMEW

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-11 Thread Cheng-yi Chiang
On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter  wrote:
>
> On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  wrote:
> > >
> > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > From: Hans Verkuil 
> > > > >
> > > > > Add support for HDMI hotplug and EDID notifiers, which is used to 
> > > > > convey
> > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > >
> > > > > Based on an earlier version from Russell King:
> > > > >
> > > > > https://patchwork.kernel.org/patch/9277043/
> > > > >
> > > > > The hdmi_notifier is a reference counted object containing the HDMI 
> > > > > state
> > > > > of an HDMI device.
> > > > >
> > > > > When a new notifier is registered the current state will be reported 
> > > > > to
> > > > > that notifier at registration time.
> > > > >
> > > > > Based on Hans Verkuil's patch:
> > > > >
> > > > > https://patchwork.kernel.org/patch/9472521/
> > > >
> > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > found in drivers/media/cec/cec-notifier.c?
> > > >
> > > > I don't think it makes sense to have two notifier implementations in 
> > > > the kernel.
> > > > The original intention was to have the notifier deal with both CEC and 
> > > > ASoC
> > > > notifications, but there was not enough interest for the ASoC bits at 
> > > > the time
> > > > and it was dropped.
> > > >
> > > > I am planning changes to the cec-notifier API, I hope to work on that 
> > > > this
> > > > week. I'll CC you when I post those. Those might be a good starting 
> > > > point
> > > > to convert the cec-notifier to an hdmi-notifier as was originally 
> > > > intended.
> > > >
> > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since 
> > > > he's been
> > > > working on some nice cec-notifier improvements as well.
> > >
> > > We also have some interfaces for drm/alsa interactions around hdmi
> > > already in drm/drm_audio_component.h, but it's not used by anything
> > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > >
> > Hi Daniel,
> > Thank you for the pointer. Looking at the ops, it seems that it is
> > specific to HDA.
> > I am not familiar with drm and HDA. I am not sure how applicable it
> > would be to report jack status to ASoC.
> > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > should be possible.
>
> Currently hda is the only user, but the idea was to make it more generic.
> Jack status in alsa is what drm calls connector status btw.
>
> So if we can take that as a baseline and extend it (probably needs some
> registration boilerplate and helpers to look up the right endpoint using
> of/dt for soc systems, we use component.c in i915/hda for this), that
> would be great I think.
>
> > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > case, as soon as you have multiple devices and need to make sure you get
> > > the update for the right one it all comes crashing down. Please create an
> > > api which registers for updates from a specific device only, plus
> > > something that has real callbacks (like the drm_audio_component.h thing we
> > > started already).
> >
> > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > specific device only.
> > hdmi_notifier_get takes a device and return the notifier.
>
> Hm I missed that, I thought it's global, so one of my usual notifier
> concerns addressed.
>
> > It seems that a major difference between drm_audio_components and
> > hdmi-notifier is that
> > drm_audio_components defines all supported ops in 
> > drm_audio_component_audio_ops.
> > On the other hand, hdmi-notifier passes different events using an enum
> > like HDMI_CONNECTED and let listener handle different events.
> > In this regard I agree with you that drm_audio_component is cleaner.
> > Anyway, I will look into it a bit more and see how it works.
>
> Yeah I think if we could combine the a

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-18 Thread Cheng-yi Chiang
On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter  wrote:
>
> On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter  wrote:
> > >
> > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  wrote:
> > > > >
> > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > From: Hans Verkuil 
> > > > > > >
> > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to 
> > > > > > > convey
> > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > >
> > > > > > > Based on an earlier version from Russell King:
> > > > > > >
> > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > >
> > > > > > > The hdmi_notifier is a reference counted object containing the 
> > > > > > > HDMI state
> > > > > > > of an HDMI device.
> > > > > > >
> > > > > > > When a new notifier is registered the current state will be 
> > > > > > > reported to
> > > > > > > that notifier at registration time.
> > > > > > >
> > > > > > > Based on Hans Verkuil's patch:
> > > > > > >
> > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > >
> > > > > > Erm, you are aware that this patch morphed into a CEC-specific 
> > > > > > notifier
> > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > >
> > > > > > I don't think it makes sense to have two notifier implementations 
> > > > > > in the kernel.
> > > > > > The original intention was to have the notifier deal with both CEC 
> > > > > > and ASoC
> > > > > > notifications, but there was not enough interest for the ASoC bits 
> > > > > > at the time
> > > > > > and it was dropped.
> > > > > >
> > > > > > I am planning changes to the cec-notifier API, I hope to work on 
> > > > > > that this
> > > > > > week. I'll CC you when I post those. Those might be a good starting 
> > > > > > point
> > > > > > to convert the cec-notifier to an hdmi-notifier as was originally 
> > > > > > intended.
> > > > > >
> > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list 
> > > > > > since he's been
> > > > > > working on some nice cec-notifier improvements as well.
> > > > >
> > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > >
> > > > Hi Daniel,
> > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > specific to HDA.
> > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > would be to report jack status to ASoC.
> > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > should be possible.
> > >
> > > Currently hda is the only user, but the idea was to make it more generic.
> > > Jack status in alsa is what drm calls connector status btw.
> > >
> > > So if we can take that as a baseline and extend it (probably needs some
> > > registration boilerplate and helpers to look up the right endpoint using
> > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > would be great I think.
> > >
> > > > > Another note: notifiers considered evil, imo. Gets the job done for 
> > > > > one
> > > > > case, as soon as you have multiple devices and need to make sure you 
> > > > > get
> > > > > the update for the right one it all comes crashing down. Please 
> > > > > create an
> > > > > api which registers for updates from a specific device only, plus

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-18 Thread Cheng-yi Chiang
On Tue, Jun 11, 2019 at 9:11 PM Hans Verkuil  wrote:
>
> On 6/11/19 2:10 PM, Cheng-yi Chiang wrote:
> > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter  wrote:
> >>
> >> On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> >>> On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  wrote:
> >>>>
> >>>> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> >>>>> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> >>>>>> From: Hans Verkuil 
> >>>>>>
> >>>>>> Add support for HDMI hotplug and EDID notifiers, which is used to 
> >>>>>> convey
> >>>>>> information from HDMI drivers to their CEC and audio counterparts.
> >>>>>>
> >>>>>> Based on an earlier version from Russell King:
> >>>>>>
> >>>>>> https://patchwork.kernel.org/patch/9277043/
> >>>>>>
> >>>>>> The hdmi_notifier is a reference counted object containing the HDMI 
> >>>>>> state
> >>>>>> of an HDMI device.
> >>>>>>
> >>>>>> When a new notifier is registered the current state will be reported to
> >>>>>> that notifier at registration time.
> >>>>>>
> >>>>>> Based on Hans Verkuil's patch:
> >>>>>>
> >>>>>> https://patchwork.kernel.org/patch/9472521/
> >>>>>
> >>>>> Erm, you are aware that this patch morphed into a CEC-specific notifier
> >>>>> found in drivers/media/cec/cec-notifier.c?
> >>>>>
> >>>>> I don't think it makes sense to have two notifier implementations in 
> >>>>> the kernel.
> >>>>> The original intention was to have the notifier deal with both CEC and 
> >>>>> ASoC
> >>>>> notifications, but there was not enough interest for the ASoC bits at 
> >>>>> the time
> >>>>> and it was dropped.
> >>>>>
> >>>>> I am planning changes to the cec-notifier API, I hope to work on that 
> >>>>> this
> >>>>> week. I'll CC you when I post those. Those might be a good starting 
> >>>>> point
> >>>>> to convert the cec-notifier to an hdmi-notifier as was originally 
> >>>>> intended.
> >>>>>
> >>>>> I've added your colleague Dariusz Marcinkiewicz to the CC list since 
> >>>>> he's been
> >>>>> working on some nice cec-notifier improvements as well.
> >>>>
> >>>> We also have some interfaces for drm/alsa interactions around hdmi
> >>>> already in drm/drm_audio_component.h, but it's not used by anything
> >>>> outside of i915. Imo we should extend that, not reinvent a new wheel.
> >>>>
> >>> Hi Daniel,
> >>> Thank you for the pointer. Looking at the ops, it seems that it is
> >>> specific to HDA.
> >>> I am not familiar with drm and HDA. I am not sure how applicable it
> >>> would be to report jack status to ASoC.
> >>> There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> >>> should be possible.
> >>
> >> Currently hda is the only user, but the idea was to make it more generic.
> >> Jack status in alsa is what drm calls connector status btw.
> >>
> >> So if we can take that as a baseline and extend it (probably needs some
> >> registration boilerplate and helpers to look up the right endpoint using
> >> of/dt for soc systems, we use component.c in i915/hda for this), that
> >> would be great I think.
> >>
> >>>> Another note: notifiers considered evil, imo. Gets the job done for one
> >>>> case, as soon as you have multiple devices and need to make sure you get
> >>>> the update for the right one it all comes crashing down. Please create an
> >>>> api which registers for updates from a specific device only, plus
> >>>> something that has real callbacks (like the drm_audio_component.h thing 
> >>>> we
> >>>> started already).
> >>>
> >>> To clarify a bit, this hdmi-notifier indeed supports updating from a
> >>> specific device only.
> >>> hdmi_notifier_get takes a device and return the notifier.
> >>
> >> Hm I mi

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-19 Thread Cheng-yi Chiang
On Tue, Jun 18, 2019 at 8:12 PM Daniel Vetter  wrote:
>
> On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter  wrote:
> > >
> > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter  wrote:
> > > > >
> > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  
> > > > > > wrote:
> > > > > > >
> > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > > From: Hans Verkuil 
> > > > > > > > >
> > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is 
> > > > > > > > > used to convey
> > > > > > > > > information from HDMI drivers to their CEC and audio 
> > > > > > > > > counterparts.
> > > > > > > > >
> > > > > > > > > Based on an earlier version from Russell King:
> > > > > > > > >
> > > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > > >
> > > > > > > > > The hdmi_notifier is a reference counted object containing 
> > > > > > > > > the HDMI state
> > > > > > > > > of an HDMI device.
> > > > > > > > >
> > > > > > > > > When a new notifier is registered the current state will be 
> > > > > > > > > reported to
> > > > > > > > > that notifier at registration time.
> > > > > > > > >
> > > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > > >
> > > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > > >
> > > > > > > > Erm, you are aware that this patch morphed into a CEC-specific 
> > > > > > > > notifier
> > > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > > >
> > > > > > > > I don't think it makes sense to have two notifier 
> > > > > > > > implementations in the kernel.
> > > > > > > > The original intention was to have the notifier deal with both 
> > > > > > > > CEC and ASoC
> > > > > > > > notifications, but there was not enough interest for the ASoC 
> > > > > > > > bits at the time
> > > > > > > > and it was dropped.
> > > > > > > >
> > > > > > > > I am planning changes to the cec-notifier API, I hope to work 
> > > > > > > > on that this
> > > > > > > > week. I'll CC you when I post those. Those might be a good 
> > > > > > > > starting point
> > > > > > > > to convert the cec-notifier to an hdmi-notifier as was 
> > > > > > > > originally intended.
> > > > > > > >
> > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list 
> > > > > > > > since he's been
> > > > > > > > working on some nice cec-notifier improvements as well.
> > > > > > >
> > > > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > > > already in drm/drm_audio_component.h, but it's not used by 
> > > > > > > anything
> > > > > > > outside of i915. Imo we should extend that, not reinvent a new 
> > > > > > > wheel.
> > > > > > >
> > > > > > Hi Daniel,
> > > > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > > > specific to HDA.
> > > > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > > > would be to report jack status to ASoC.
> > > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > > > should be possible.
> > > > >
> >

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-20 Thread Cheng-yi Chiang
On Thu, Jun 20, 2019 at 5:25 PM Daniel Vetter  wrote:
>
> On Wed, Jun 19, 2019 at 07:48:11PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 18, 2019 at 8:12 PM Daniel Vetter  wrote:
> > >
> > > On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> > > > On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter  wrote:
> > > > >
> > > > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > > > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter  
> > > > > > wrote:
> > > > > > >
> > > > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter  
> > > > > > > > wrote:
> > > > > > > > >
> > > > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > > > > From: Hans Verkuil 
> > > > > > > > > > >
> > > > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is 
> > > > > > > > > > > used to convey
> > > > > > > > > > > information from HDMI drivers to their CEC and audio 
> > > > > > > > > > > counterparts.
> > > > > > > > > > >
> > > > > > > > > > > Based on an earlier version from Russell King:
> > > > > > > > > > >
> > > > > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > > > > >
> > > > > > > > > > > The hdmi_notifier is a reference counted object 
> > > > > > > > > > > containing the HDMI state
> > > > > > > > > > > of an HDMI device.
> > > > > > > > > > >
> > > > > > > > > > > When a new notifier is registered the current state will 
> > > > > > > > > > > be reported to
> > > > > > > > > > > that notifier at registration time.
> > > > > > > > > > >
> > > > > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > > > > >
> > > > > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > > > > >
> > > > > > > > > > Erm, you are aware that this patch morphed into a 
> > > > > > > > > > CEC-specific notifier
> > > > > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > > > > >
> > > > > > > > > > I don't think it makes sense to have two notifier 
> > > > > > > > > > implementations in the kernel.
> > > > > > > > > > The original intention was to have the notifier deal with 
> > > > > > > > > > both CEC and ASoC
> > > > > > > > > > notifications, but there was not enough interest for the 
> > > > > > > > > > ASoC bits at the time
> > > > > > > > > > and it was dropped.
> > > > > > > > > >
> > > > > > > > > > I am planning changes to the cec-notifier API, I hope to 
> > > > > > > > > > work on that this
> > > > > > > > > > week. I'll CC you when I post those. Those might be a good 
> > > > > > > > > > starting point
> > > > > > > > > > to convert the cec-notifier to an hdmi-notifier as was 
> > > > > > > > > > originally intended.
> > > > > > > > > >
> > > > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC 
> > > > > > > > > > list since he's been
> > > > > > > > > > working on some nice cec-notifier improvements as well.
> > > > > > > > >
> > > > > > > > > We also have some interfaces for drm/alsa interactions around 
> > > > > > > > > hdmi
> > > > > > >

Re: [PATCH 1/7] video: add HDMI state notifier support

2019-06-21 Thread Cheng-yi Chiang
On Fri, Jun 21, 2019 at 5:12 AM Daniel Vetter  wrote:
>
> Massively cutting this thread, since halfway through in my previous reply
> I realized that maybe hdmi_codec is a much better starting point.
>
ACK
> On Thu, Jun 20, 2019 at 09:23:23PM +0800, Cheng-yi Chiang wrote:
> > On Thu, Jun 20, 2019 at 5:25 PM Daniel Vetter  wrote:
> > > Yeah fully agreeing that hdmi_audio_code is probably a better starting
> > > point. Problem is that becuase hdmi_codec is built on top of platform
> > > device it's quite a bit harder to extend with callbacks and things like
> > > that, without breaking the driver model.
> > >
> > > I need to think about this more, but if all we need to look at is
> > > hdmi_codec, then I think this becomes a lot easier. And we can ignore
> > > drm_audio_component.h completely.
> >
> >
> > It is surprising that you think this way.
> > Maybe the original patch before hdmi-notifier was introduced is the
> > better way to solve this issue, if we only need to look at hdmi_codec.
> >
> > The history of hdmi_codec driver is in this patch series:
> >
> > https://lore.kernel.org/patchwork/patch/539656/
>
> Hm, this doesn't seem to be the hdmi_codec driver I meant, but another,
> new one. I was talking about SND_SOC_HDMI_CODEC.
>
Yes you are right. They are different codec drivers.
Sorry for the confusion. What I meant was that my use case on RK3288
was using dw-hdmi-audio.c codec driver,
which was later replaced by a more general version hdmi-codec.c.

> > There was a callback mechanism implemented between dw-hdmi and hdmi
> > codec driver.
> > It was later consolidated by Doug in this patch for better jack status
> > reporting:
> >
> > https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/303573/
>
> Hm that still seems entirely separate hdmi-codec specific to dw-hdmi only
> ...
>
Again you are right. Sorry for the confusion. What I meant is that
this callback mechanism should work on hdmi-codec.c driver as well.

> > I am not sure why the original patch series did not get fully accepted
> > in the upstream.
> > It was quite long time ago.
> >
> > But if you think this might be the right way to do, then it is even
> > better for us because the patch series and Doug's patch had been quite
> > stable
> > on our RK3288 products for about four years with plenty of users, so
> > we have much higher confidence in them.
> > I can rebase and clean up them and post another patch for review.
> >
> > Please let me know what approach you feel is better.
> > Thanks again!
>
> Not sure we're talking about the same. What I had in mind is to add jack
> status to the hdmi-codec.c stuff, which is used by multiple soc drm
> display drivers already. Looking at git grep output, there seems to be
> already some support for dw-hdmi synopsys drm_bridge driver. I thought of
> extending that. Does that not work for you?
>
I think extending current interface will work.
There is a struct hdmi_codec_pdata to let ALSA codec driver access
some ops through platform data.
And after this patch

https://lore.kernel.org/patchwork/patch/692324/

ALSA codec driver can get access to the struct on DRM side.
Based on this I can add a new ops to register callback function for jack status.
It will be similar to Doug's chromium patch above.
I think that is quite a feasible way, and can benefit all boards using
hdmi-codec.c.

Thanks a lot!!

> Thanks, Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch


[PATCH 0/4] Add HDMI jack support on RK3288

2019-07-04 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

Cheng-Yi Chiang (4):
  ASoC: hdmi-codec: Add an op to set callback function for plug event
  drm: bridge: dw-hdmi: Report connector status using callback
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |   3 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  10 ++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  32 -
 include/sound/hdmi-codec.h|  16 +++
 sound/soc/codecs/hdmi-codec.c |  52 
 sound/soc/rockchip/rockchip_max98090.c| 112 ++
 6 files changed, 201 insertions(+), 24 deletions(-)

-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH 2/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-04 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi implements set_plugged_cb op so platform device can register the
callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |  3 ++
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 10 ++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 34 ++-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
index 63b5756f463b..f523c590984e 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
@@ -2,6 +2,8 @@
 #ifndef DW_HDMI_AUDIO_H
 #define DW_HDMI_AUDIO_H
 
+#include 
+
 struct dw_hdmi;
 
 struct dw_hdmi_audio_data {
@@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
 
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read)(struct dw_hdmi *hdmi, int offset);
+   int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn);
 };
 
 #endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..7b93cf05c985 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return audio->set_plugged_cb(hdmi, fn);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 045b1b13fd0e..c69a399fc7ca 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -26,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -185,6 +187,9 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -209,6 +214,17 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static int hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn)
+{
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   if (hdmi->audio && !IS_ERR(hdmi->audio))
+   fn(hdmi->audio,
+  hdmi->last_connector_result == connector_status_connected);
+   mutex_unlock(&hdmi->mutex);
+   return 0;
+}
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2044,6 +2060,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2051,7 +2068,20 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   if (hdmi->plugged_cb && hdmi->audio && !IS_ERR(hdmi->audio)) {
+   hdmi->plugged_cb(hdmi->audio,
+result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static i

[PATCH 1/4] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-04 Thread Cheng-Yi Chiang
Add an op in hdmi_codec_ops so codec driver can register callback
function to handle plug event.

Driver in DRM can use this callback function to report connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 include/sound/hdmi-codec.h| 16 +++
 sound/soc/codecs/hdmi-codec.c | 52 +++
 2 files changed, 68 insertions(+)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 7fea496f1f34..26c02abb8eba 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels;
 };
 
+typedef void (*hdmi_codec_plugged_cb)(struct platform_device *dev,
+ bool plugged);
+
 struct hdmi_codec_pdata;
 struct hdmi_codec_ops {
/*
@@ -88,6 +91,13 @@ struct hdmi_codec_ops {
 */
int (*get_dai_id)(struct snd_soc_component *comment,
  struct device_node *endpoint);
+
+   /*
+* Hook callback function to handle connector plug event.
+* Optional
+*/
+   int (*hook_plugged_cb)(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn);
 };
 
 /* HDMI codec initalization data */
@@ -99,6 +109,12 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0bf1c8cad108..5e7075f78c38 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -663,6 +666,55 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0;
 }
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (!hcp->jack)
+   return;
+
+   if (jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static void plugged_cb(struct platform_device *pdev, bool plugged)
+{
+   struct platform_device *codec_pdev = platform_get_drvdata(pdev);
+   struct hdmi_codec_priv *hcp = platform_get_drvdata(codec_pdev);
+
+   if (plugged)
+   hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+   else
+   hdmi_codec_jack_report(hcp, 0);
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI plugged callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack)
+{
+   struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+   int ret;
+
+   if (hcp->hcd.ops->hook_plugged_cb) {
+   hcp->jack = jack;
+   ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+   hcp->hcd.data,
+   plugged_cb);
+   if (ret) {
+   hcp->jack = NULL;
+   return ret;
+   }
+   return 0;
+   }
+   return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
 {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-04 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 91 +++---
 1 file changed, 68 insertions(+), 23 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..195309d1225a 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -41,6 +41,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +53,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +61,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +95,59 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret && ret != -ENOTSUPP) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret && ret != -ENOTSUPP) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC("hdmi-audio-codec.3.auto", "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(hdmi),
+   }
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -136,8 +160,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
-   .dai_link = &rk_dailink,
-   .num_links = 1,
+   .dai_link = rk_dailinks,
+   .num_links = ARRAY_SIZE(rk_dailinks),
.aux_dev = &rk_98090_headset_dev,
.num_aux_devs = 1,
.dapm_widgets = rk_dapm_widgets,
@@ -173,27 +197,48 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
int ret = 0;
struct snd_soc_card *card = &snd_soc_card_rk;
struct device_node *np = pdev->dev.of_n

[PATCH 4/4] ASoC: rockchip_max98090: Add HDMI jack support

2019-07-04 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 195309d1225a..c0e430ca4d12 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "rockchip_i2s.h"
 #include "../codecs/ts3a227e.h"
@@ -129,6 +130,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -146,6 +166,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.22.0.410.gd8fdbe21b5-goog



Re: [alsa-devel] [PATCH 2/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-05 Thread Cheng-yi Chiang
On Fri, Jul 5, 2019 at 1:45 PM Jonas Karlman  wrote:
>
> On 2019-07-05 06:26, Cheng-Yi Chiang wrote:
> > Allow codec driver register callback function for plug event.
> >
> > The callback registration flow:
> > dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec
> >
> > dw-hdmi-i2s-audio implements hook_plugged_cb op
> > so codec driver can register the callback.
> >
> > dw-hdmi implements set_plugged_cb op so platform device can register the
> > callback.
> >
> > When connector plug/unplug event happens, report this event using the
> > callback.
> >
> > Make sure that audio and drm are using the single source of truth for
> > connector status.
>
> I have a similar notification need for making a snd_ctl_notify() call from 
> hdmi-codec when ELD changes,
> see [1] for work in progress patches (part of a dw-hdmi multi-channel lpcm 
> series I am preparing).
>
> Any suggestions on how to handle a ELD change notification?
> Should I use a similar pattern as in this series?

Hi Jonas, I think we are using a very similar pattern.
The difference is that in my series the function is not exposed on hdmi-codec.h.
I think your method makes sense for your case because
dw-hdmi-i2s-audio.c needs to access and update data inside
dw_hdmi_i2s_audio_data,
while in my use case it is only a thin layer setting up the callback
for jack status.

> (I lost track of the hdmi-notifier/drm_audio_component discussion)
>

It was a long discussion.
I think the conclusion was that if we are only talking about
hdmi-codec, then we just need to extend the ops exposed in hdmi-codec
and don't need to use
hdmi-notifier or drm_audio_component.

> [1] 
> https://github.com/Kwiboo/linux-rockchip/compare/54b40fdd264c7ed96017271eb6524cca4ff755ab...9c17284e8a8657e8b1da53a1c7ff056cbd8ce43c
>
> Best regards,
> Jonas
>
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |  3 ++
> >  .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 10 ++
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 34 ++-
> >  3 files changed, 46 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > index 63b5756f463b..f523c590984e 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > @@ -2,6 +2,8 @@
> >  #ifndef DW_HDMI_AUDIO_H
> >  #define DW_HDMI_AUDIO_H
> >
> > +#include 
> > +
> >  struct dw_hdmi;
> >
> >  struct dw_hdmi_audio_data {
> > @@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
> >
> >   void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
> >   u8 (*read)(struct dw_hdmi *hdmi, int offset);
> > + int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn);
> >  };
> >
> >  #endif
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > index 5cbb71a866d5..7b93cf05c985 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > @@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
> > snd_soc_component *component,
> >   return -EINVAL;
> >  }
> >
> > +static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
> > +hdmi_codec_plugged_cb fn)
> > +{
> > + struct dw_hdmi_i2s_audio_data *audio = data;
> > + struct dw_hdmi *hdmi = audio->hdmi;
> > +
> > + return audio->set_plugged_cb(hdmi, fn);
> > +}
> > +
> >  static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
> >   .hw_params  = dw_hdmi_i2s_hw_params,
> >   .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
> >   .get_dai_id = dw_hdmi_i2s_get_dai_id,
> > + .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
> >  };
> >
> >  static int snd_dw_hdmi_probe(struct platform_device *pdev)
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index 045b1b13fd0e..c69a399fc7ca 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -26,6 +26,8 @@
> >  #include 
> >  #include 
> >
> > +#include 
> > +
> >  #include 
> >  #include 
> >
> > @@ -185,6 +187,9 @@ struct dw_hdmi {
> >   void (*disable_audio)(str

Re: [PATCH 2/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-05 Thread Cheng-yi Chiang
On Fri, Jul 5, 2019 at 3:09 PM Tzung-Bi Shih  wrote:
>
> On Fri, Jul 5, 2019 at 12:26 PM Cheng-Yi Chiang  wrote:
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > index 63b5756f463b..f523c590984e 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > @@ -2,6 +2,8 @@
> >  #ifndef DW_HDMI_AUDIO_H
> >  #define DW_HDMI_AUDIO_H
> >
> > +#include 
> > +
> >  struct dw_hdmi;
> >
> >  struct dw_hdmi_audio_data {
> > @@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
> >
> > void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
> > u8 (*read)(struct dw_hdmi *hdmi, int offset);
> > +   int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb 
> > fn);
> >  };
> >
> >  #endif
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > index 5cbb71a866d5..7b93cf05c985 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > @@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
> > snd_soc_component *component,
> > return -EINVAL;
> >  }
> >
> > +static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
> > +  hdmi_codec_plugged_cb fn)
> > +{
> > +   struct dw_hdmi_i2s_audio_data *audio = data;
> > +   struct dw_hdmi *hdmi = audio->hdmi;
> > +
> > +   return audio->set_plugged_cb(hdmi, fn);
> > +}
> > +
> The first parameter dev could be removed.  Not used.
>
Hi Tzungbi, thanks for the review.

I am not sure about this one.
I think it depends on the DRM driver so I need to keep both..
E.g.
drivers/gpu/drm/rockchip/cdn-dp-core.c
it needs dev to access the required data.
You can check this patch:

"efc9194bcff8  ASoC: hdmi-codec: callback function will be called with
private data"

It explains that some cases use *dev, some cases use *data.

> >  static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
> > .hw_params  = dw_hdmi_i2s_hw_params,
> > .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
> > .get_dai_id = dw_hdmi_i2s_get_dai_id,
> > +   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
> >  };
> >
> >  static int snd_dw_hdmi_probe(struct platform_device *pdev)
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index 045b1b13fd0e..c69a399fc7ca 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -26,6 +26,8 @@
> >  #include 
> >  #include 
> >
> > +#include 
> > +
> >  #include 
> >  #include 
> >
> > @@ -185,6 +187,9 @@ struct dw_hdmi {
> > void (*disable_audio)(struct dw_hdmi *hdmi);
> >
> > struct cec_notifier *cec_notifier;
> > +
> > +   hdmi_codec_plugged_cb plugged_cb;
> > +   enum drm_connector_status last_connector_result;
> >  };
> >
> >  #define HDMI_IH_PHY_STAT0_RX_SENSE \
> > @@ -209,6 +214,17 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
> > offset)
> > return val;
> >  }
> >
> > +static int hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb 
> > fn)
> > +{
> > +   mutex_lock(&hdmi->mutex);
> > +   hdmi->plugged_cb = fn;
> > +   if (hdmi->audio && !IS_ERR(hdmi->audio))
> I would expect if IS_ERR(hdmi->audio), then this should not be called
> (i.e. should exit somewhere earlier).
>
ACK. I should fix that.
Thanks!
> > +   fn(hdmi->audio,
> > +  hdmi->last_connector_result == 
> > connector_status_connected);
> > +   mutex_unlock(&hdmi->mutex);
> > +   return 0;
> > +}
> > +
> >  static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
> >  {
> > regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
> > @@ -2044,6 +2060,7 @@ dw_hdmi_connector_detect(struct drm_connector 
> > *connector, bool force)
> >  {
> > struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> >  connector);
> > +   enum drm_connector_status result;
> >
> > mutex_lock(&hdmi->mutex);
> > hdmi->force = DRM_FORCE_UNSPECIFIED;
> > @@ -2051,7 +2068,20 @@ dw_hdmi_connector_detect(struct drm_connector 
> > *connector, bool force)
> > dw_hdmi_update_phy_mask(hdmi);
> > mutex_unlock(&hdmi->mutex);
> >
> > -   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
> > +   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
> > +
> > +   mutex_lock(&hdmi->mutex);
> > +   if (result != hdmi->last_connector_result) {
> > +   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
> > +   if (hdmi->plugged_cb && hdmi->audio && 
> > !IS_ERR(hdmi->audio)) {
> Share the same concern above.
ACK


Re: [PATCH 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-06 Thread Cheng-yi Chiang
On Fri, Jul 5, 2019 at 3:10 PM Tzung-Bi Shih  wrote:
>
> On Fri, Jul 5, 2019 at 12:26 PM Cheng-Yi Chiang  wrote:
> > diff --git a/sound/soc/rockchip/rockchip_max98090.c 
> > b/sound/soc/rockchip/rockchip_max98090.c
> > index c5fc24675a33..195309d1225a 100644
> > --- a/sound/soc/rockchip/rockchip_max98090.c
> > +++ b/sound/soc/rockchip/rockchip_max98090.c
> >  static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
> > @@ -92,38 +95,59 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
> > *substream,
> >
> > ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
> >  SND_SOC_CLOCK_OUT);
> > -   if (ret < 0) {
> > -   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
> > +   if (ret && ret != -ENOTSUPP) {
> > +   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
I should remove this change because cpu dai should support sysclk ops.

> > return ret;
> > }
> >
> > ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
> >  SND_SOC_CLOCK_IN);
> > -   if (ret < 0) {
> > -   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
> > +   if (ret && ret != -ENOTSUPP) {
> > +   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", 
> > ret);
> > return ret;
> > }
> Does it imply: it is acceptable even if they are "not supported"?
Thank you for this good catch.
Here machine driver has the knowledge of deciding whether it is
expected to see the ops is not supported.
For HDMI path using hdmi-codec driver, it is expected to see -ENOTSUPP.
But it is not expected for codec DAI of max98090.
I should distinguish them.

>
>
> >
> > -   return ret;
> > +   return 0;
> >  }
> >
> >  static const struct snd_soc_ops rk_aif1_ops = {
> > .hw_params = rk_aif1_hw_params,
> >  };
> >
> > -SND_SOC_DAILINK_DEFS(hifi,
> > +SND_SOC_DAILINK_DEFS(analog,
> > DAILINK_COMP_ARRAY(COMP_EMPTY()),
> > DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
> > DAILINK_COMP_ARRAY(COMP_EMPTY()));
> >
> > -static struct snd_soc_dai_link rk_dailink = {
> > -   .name = "max98090",
> > -   .stream_name = "Audio",
> > -   .ops = &rk_aif1_ops,
> > -   /* set max98090 as slave */
> > -   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> > -   SND_SOC_DAIFMT_CBS_CFS,
> > -   SND_SOC_DAILINK_REG(hifi),
> > +SND_SOC_DAILINK_DEFS(hdmi,
> > +   DAILINK_COMP_ARRAY(COMP_EMPTY()),
> > +   DAILINK_COMP_ARRAY(COMP_CODEC("hdmi-audio-codec.3.auto", 
> > "i2s-hifi")),
> > +   DAILINK_COMP_ARRAY(COMP_EMPTY()));
> > +
> > +enum {
> > +   DAILINK_MAX98090,
> > +   DAILINK_HDMI,
> > +};
> > +
> > +/* max98090 and HDMI codec dai_link */
> > +static struct snd_soc_dai_link rk_dailinks[] = {
> > +   [DAILINK_MAX98090] = {
> > +   .name = "max98090",
> > +   .stream_name = "Analog",
> > +   .ops = &rk_aif1_ops,
> > +   /* set max98090 as slave */
> > +   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> > +   SND_SOC_DAIFMT_CBS_CFS,
> > +   SND_SOC_DAILINK_REG(analog),
> > +   },
> > +   [DAILINK_HDMI] = {
> > +   .name = "HDMI",
> > +   .stream_name = "HDMI",
> > +   .ops = &rk_aif1_ops,
> > +   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> > +   SND_SOC_DAIFMT_CBS_CFS,
> > +   SND_SOC_DAILINK_REG(hdmi),
> > +   }
> >  };
> >
> >  static int rk_98090_headset_init(struct snd_soc_component *component);
> > @@ -136,8 +160,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
> >  static struct snd_soc_card snd_soc_card_rk = {
> > .name = "ROCKCHIP-I2S",
> > .owner = THIS_MODULE,
> > -   .dai_link = &rk_dailink,
> > -   .num_links = 1,
> > +   .dai_link = rk_dailinks,
> > +   .num_links = ARRAY_SIZE(rk_dailinks),
> > .aux_dev = &rk_98090_headset_dev,
> > .num_aux_devs = 1,
> > .dapm_widgets = rk_dapm_wi

Re: [alsa-devel] [PATCH 2/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-06 Thread Cheng-yi Chiang
On Sat, Jul 6, 2019 at 1:16 AM Mark Brown  wrote:
>
> On Fri, Jul 05, 2019 at 03:31:24PM +0800, Cheng-yi Chiang wrote:
>
> > It was a long discussion.
> > I think the conclusion was that if we are only talking about
> > hdmi-codec, then we just need to extend the ops exposed in hdmi-codec
> > and don't need to use
> > hdmi-notifier or drm_audio_component.
>
> What I'd picked up from the bits of that discussion that I
> followed was that there was some desire to come up with a unified
> approach to ELD notification rather than having to go through
> this discussion repeatedly?  That would certianly seem more
> sensible.  Admittedly it was a long thread with lots of enormous
> mails so I didn't follow the whole thing.

Hi Mark, thanks for following the long thread.
The end of the discussion was at
https://lkml.org/lkml/2019/6/20/1397

Quoted from Daniel's suggestion:
"
I need to think about this more, but if all we need to look at is
hdmi_codec, then I think this becomes a lot easier. And we can ignore
drm_audio_component.h completely.
"

My thought is that the codec driver under ASoC are only these two:
hdac_hdmi.c and hdmi-codec.c  ( forgive me if I missed others. I just
grep "hdmi" under sound/soc/codecs/ )
hdac_hdmi.c is like a wrapper for HDA and drm_audio_components.
hdmi-codec.c is the only other codec driver that cares HDMI under ASoC.
So adding the jack/eld support at hdmi-codec driver can cover the
existing use cases for HDMI codec driver in ASoC.
That said, adding a new unified approach for Jack/ELD notification
that will only be used by hdmi-codec seems not a high priority.
Hope this explanation helps your decision.
Thanks!


Re: [PATCH 1/4] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-07 Thread Cheng-yi Chiang
On Fri, Jul 5, 2019 at 8:12 PM Mark Brown  wrote:
>
> On Fri, Jul 05, 2019 at 03:08:37PM +0800, Tzung-Bi Shih wrote:
> > On Fri, Jul 5, 2019 at 12:26 PM Cheng-Yi Chiang  
> > wrote:
>
> > > +typedef void (*hdmi_codec_plugged_cb)(struct platform_device *dev,
> > > + bool plugged);
> > > +
>
> > The callback prototype is "weird" by struct platform_device.  Is it
> > possible to having snd_soc_component instead of platform_device?
>
> Or if it's got to be a device why not just a generic device so
> we're not tied to a particular bus here?

My intention was to invoke the call in dw-hdmi.c like this:

hdmi->plugged_cb(hdmi->audio,
   result == connector_status_connected);

Here hdmi->audio is a platform_device.
I think dw-hdmi can not get  snd_soc_component easily.
I can use a generic device here so the ops is more general.
The calling will be like
hdmi->plugged_cb(&hdmi->audio->dev,
   result == connector_status_connected);
I will update this in v2.
Thanks!


Re: [PATCH 1/4] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-09 Thread Cheng-yi Chiang
On Tue, Jul 9, 2019 at 7:47 PM Cezary Rojewski
 wrote:
>
> On 2019-07-05 06:26, Cheng-Yi Chiang wrote:
> > +static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
> > +unsigned int jack_status)
> > +{
> > + if (!hcp->jack)
> > + return;
> > +
> > + if (jack_status != hcp->jack_status) {
> > + snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
> > + hcp->jack_status = jack_status;
> > + }
> > +}
>
> Single "if" statement instead? The first "if" does not even cover all
> cases - if the secondary check fails, you'll "return;" too.
>
ACK.
I will fix in v2.
> > +/**
> > + * hdmi_codec_set_jack_detect - register HDMI plugged callback
> > + * @component: the hdmi-codec instance
> > + * @jack: ASoC jack to report (dis)connection events on
> > + */
> > +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> > +struct snd_soc_jack *jack)
> > +{
> > + struct hdmi_codec_priv *hcp = 
> > snd_soc_component_get_drvdata(component);
> > + int ret;
> > +
> > + if (hcp->hcd.ops->hook_plugged_cb) {
> > + hcp->jack = jack;
> > + ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
> > + hcp->hcd.data,
> > + plugged_cb);
> > + if (ret) {
> > + hcp->jack = NULL;
> > + return ret;
> > + }
> > + return 0;
> > + }
> > + return -EOPNOTSUPP;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
>
> int ret = -EOPNOTSUPP;
> (...)
>
> return ret;
>
> In consequence, you can reduce the number of "return(s)" and also remove
> the redundant parenthesis for the if-statement used to set jack to NULL.
>
> Czarek
ACK
will fix in v2.

Thanks a lot for the review!


Re: [PATCH 1/4] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-09 Thread Cheng-yi Chiang
On Mon, Jul 8, 2019 at 1:03 PM Cheng-yi Chiang  wrote:
>
> On Fri, Jul 5, 2019 at 8:12 PM Mark Brown  wrote:
> >
> > On Fri, Jul 05, 2019 at 03:08:37PM +0800, Tzung-Bi Shih wrote:
> > > On Fri, Jul 5, 2019 at 12:26 PM Cheng-Yi Chiang  
> > > wrote:
> >
> > > > +typedef void (*hdmi_codec_plugged_cb)(struct platform_device *dev,
> > > > + bool plugged);
> > > > +
> >
> > > The callback prototype is "weird" by struct platform_device.  Is it
> > > possible to having snd_soc_component instead of platform_device?
> >
> > Or if it's got to be a device why not just a generic device so
> > we're not tied to a particular bus here?
>
> My intention was to invoke the call in dw-hdmi.c like this:
>
> hdmi->plugged_cb(hdmi->audio,
>result == connector_status_connected);
>
> Here hdmi->audio is a platform_device.
> I think dw-hdmi can not get  snd_soc_component easily.
> I can use a generic device here so the ops is more general.
> The calling will be like
> hdmi->plugged_cb(&hdmi->audio->dev,
>result == connector_status_connected);
> I will update this in v2.
> Thanks!

I have thought about this a bit more. And I think the more proper
interface is to pass in a generic struct device* for codec.
This way, the user of hdmi-codec driver on the DRM side is not limited
to the relation chain of
audio platform device -> codec platform device, which is just a
special case in dw-hdmi driver.
As long as DRM side can get hdmi-codec device pointer through
drv_data, it can use this callback.
Hope this makes the interface more generic.


Re: [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node for HDMI

2019-07-09 Thread Cheng-yi Chiang
On Wed, Jul 10, 2019 at 4:01 AM Rob Herring  wrote:
>
> On Mon, Jun 03, 2019 at 12:32:49PM +0800, Cheng-Yi Chiang wrote:
> > Let user specify HDMI node so machine driver can use it to let codec
> > driver register callback on correct hdmi-notifier.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt 
> > b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > index a805aa99ad75..dae57c14864e 100644
> > --- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > +++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > @@ -7,6 +7,7 @@ Required properties:
> >connected to the CODEC
> >  - rockchip,audio-codec: The phandle of the MAX98090 audio codec
> >  - rockchip,headset-codec: The phandle of Ext chip for jack detection
> > +- rockchip,hdmi: The phandle of HDMI node for HDMI jack detection
> >
> >  Example:
> >
> > @@ -16,4 +17,5 @@ sound {
> >   rockchip,i2s-controller = <&i2s>;
> >   rockchip,audio-codec = <&max98090>;
> >   rockchip,headset-codec = <&headsetcodec>;
> > + rockchip,hdmi= <&hdmi>;
>
> space^
>
> With that,
>
> Acked-by: Rob Herring 
>
Hi Rob,
Thank you for the review.
But I have changed the approach in v2 so there is no need for machine
driver to expose this property.
Thanks!
> >  };
> > --
> > 2.22.0.rc1.257.g3120a18244-goog
> >


[PATCH v2 0/4] Add HDMI jack support on RK3288

2019-07-10 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

Changes from v1 to v2:
- hdmi-codec.c: cleanup the sequence of hdmi_codec_jack_report and
  hdmi_codec_set_jack_detect.
- dw-hdmi.c: change argument of hdmi_codec_plugged_cb so it takes a generic
  device which has hdmi_codec_priv in its drvdata.
- dw-hdmi.c: add a helper function handle_plugged_change to check audio
  platform device and codec platform device before calling callback.
- dw-hdmi-c: avoid setting callback function if audio platform device or
  codec platform device is missing.
- rockchip_max98090: fix the checking of return code when setting sysclk
  on cpu_dai and codec_dai. cpu_dai error should be reported. For HDMI
  codec_dai, there is no need to set sysclk.

Cheng-Yi Chiang (4):
  ASoC: hdmi-codec: Add an op to set callback function for plug event
  drm: bridge: dw-hdmi: Report connector status using callback
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |   3 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  10 ++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  55 -
 include/sound/hdmi-codec.h|  16 +++
 sound/soc/codecs/hdmi-codec.c |  45 +++
 sound/soc/rockchip/rockchip_max98090.c| 116 ++
 6 files changed, 221 insertions(+), 24 deletions(-)

-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH v2 1/4] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-10 Thread Cheng-Yi Chiang
Add an op in hdmi_codec_ops so codec driver can register callback
function to handle plug event.

Driver in DRM can use this callback function to report connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 include/sound/hdmi-codec.h| 16 +
 sound/soc/codecs/hdmi-codec.c | 45 +++
 2 files changed, 61 insertions(+)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 7fea496f1f34..9a8661680256 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels;
 };
 
+typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
+ bool plugged);
+
 struct hdmi_codec_pdata;
 struct hdmi_codec_ops {
/*
@@ -88,6 +91,13 @@ struct hdmi_codec_ops {
 */
int (*get_dai_id)(struct snd_soc_component *comment,
  struct device_node *endpoint);
+
+   /*
+* Hook callback function to handle connector plug event.
+* Optional
+*/
+   int (*hook_plugged_cb)(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn);
 };
 
 /* HDMI codec initalization data */
@@ -99,6 +109,12 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0bf1c8cad108..32bf7441be5c 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -663,6 +666,48 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0;
 }
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (hcp->jack && jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static void plugged_cb(struct device *dev, bool plugged)
+{
+   struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
+
+   if (plugged)
+   hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+   else
+   hdmi_codec_jack_report(hcp, 0);
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI plugged callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack)
+{
+   struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+   int ret = -EOPNOTSUPP;
+
+   if (hcp->hcd.ops->hook_plugged_cb) {
+   hcp->jack = jack;
+   ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+   hcp->hcd.data,
+   plugged_cb);
+   if (ret)
+   hcp->jack = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
 {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH v2 2/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-10 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi implements set_plugged_cb op so platform device can register the
callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |  3 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 10 
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 55 ++-
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
index 63b5756f463b..f523c590984e 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
@@ -2,6 +2,8 @@
 #ifndef DW_HDMI_AUDIO_H
 #define DW_HDMI_AUDIO_H
 
+#include 
+
 struct dw_hdmi;
 
 struct dw_hdmi_audio_data {
@@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
 
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read)(struct dw_hdmi *hdmi, int offset);
+   int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn);
 };
 
 #endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..7b93cf05c985 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return audio->set_plugged_cb(hdmi, fn);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 045b1b13fd0e..ce6646067472 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -26,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -185,6 +187,9 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -209,6 +214,40 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   struct platform_device *codec_pdev;
+
+   if (!hdmi->audio || IS_ERR(hdmi->audio))
+   return;
+   codec_pdev = platform_get_drvdata(hdmi->audio);
+   if (!codec_pdev || IS_ERR(codec_pdev))
+   return;
+   if (!hdmi->plugged_cb)
+   return;
+
+   hdmi->plugged_cb(&codec_pdev->dev, plugged);
+}
+
+static int hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn)
+{
+   bool plugged;
+   struct platform_device *codec_pdev;
+
+   if (!hdmi->audio || IS_ERR(hdmi->audio))
+   return -EINVAL;
+   codec_pdev = platform_get_drvdata(hdmi->audio);
+   if (!codec_pdev || IS_ERR(codec_pdev))
+   return -EINVAL;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+   return 0;
+}
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2044,6 +2083,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2051,7 +2091,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops

[PATCH v2 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-10 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 95 +++---
 1 file changed, 72 insertions(+), 23 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..3617012692ea 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -41,6 +41,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +53,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +61,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +95,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC("hdmi-audio-codec.3.auto", "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(hdmi),
+   }
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -136,8 +164,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
-   .dai_link = &rk_dailink,
-   .num_links = 1,
+   .dai_link = rk_dailinks,
+   .num_links = ARRAY_SIZE(rk_dailinks),
.aux_dev = &rk_98090_headset_dev,
.num_aux_devs = 1,
.dapm_widgets = rk_dapm_widgets,
@@ -173,27 +201,48 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
int ret = 0;
struct snd_

[PATCH v2 4/4] ASoC: rockchip_max98090: Add HDMI jack support

2019-07-10 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 3617012692ea..177c8a7ec8de 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "rockchip_i2s.h"
 #include "../codecs/ts3a227e.h"
@@ -133,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -150,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH v3 2/5] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-12 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi implements set_plugged_cb op so platform device can register the
callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |  3 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 10 
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 55 ++-
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
index 63b5756f463b..f523c590984e 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
@@ -2,6 +2,8 @@
 #ifndef DW_HDMI_AUDIO_H
 #define DW_HDMI_AUDIO_H
 
+#include 
+
 struct dw_hdmi;
 
 struct dw_hdmi_audio_data {
@@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
 
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read)(struct dw_hdmi *hdmi, int offset);
+   int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn);
 };
 
 #endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..7b93cf05c985 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return audio->set_plugged_cb(hdmi, fn);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 045b1b13fd0e..ce6646067472 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -26,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -185,6 +187,9 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -209,6 +214,40 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   struct platform_device *codec_pdev;
+
+   if (!hdmi->audio || IS_ERR(hdmi->audio))
+   return;
+   codec_pdev = platform_get_drvdata(hdmi->audio);
+   if (!codec_pdev || IS_ERR(codec_pdev))
+   return;
+   if (!hdmi->plugged_cb)
+   return;
+
+   hdmi->plugged_cb(&codec_pdev->dev, plugged);
+}
+
+static int hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn)
+{
+   bool plugged;
+   struct platform_device *codec_pdev;
+
+   if (!hdmi->audio || IS_ERR(hdmi->audio))
+   return -EINVAL;
+   codec_pdev = platform_get_drvdata(hdmi->audio);
+   if (!codec_pdev || IS_ERR(codec_pdev))
+   return -EINVAL;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+   return 0;
+}
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2044,6 +2083,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2051,7 +2091,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops

[PATCH v3 0/5] Add HDMI jack support on RK3288

2019-07-12 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

Changes from v2 to v3:
- dw-hdmi-i2s-audio.c: Use fixed ID instead of auto ID.
- rk3288_hdmi_analog.c: Use the fixed name hdmi-audio-codec for codec device.
- rockchip_max98090: Use the fixed name hdmi-audio-codec for codec device.
- rockchip_max98090: Fix the dependency of hdmi-codec in Kconfig.

Cheng-Yi Chiang (5):
  ASoC: hdmi-codec: Add an op to set callback function for plug event
  drm: bridge: dw-hdmi: Report connector status using callback
  drm: dw-hdmi-i2s: Use fixed id for codec device
  ASoC: rockchip_max98090: Add dai_link for HDMI
  FROMLIST: ASoC: rockchip_max98090: Add HDMI jack support

 .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |   3 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  12 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  55 -
 include/sound/hdmi-codec.h|  16 +++
 sound/soc/codecs/hdmi-codec.c |  45 +++
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c   |   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 116 ++
 8 files changed, 226 insertions(+), 27 deletions(-)

-- 
2.22.0.510.g264f2c817a-goog



[PATCH v3 3/5] drm: dw-hdmi-i2s: Use fixed id for codec device

2019-07-12 Thread Cheng-Yi Chiang
The problem of using auto ID is that the device name will be like
hdmi-audio-codec..auto.

The number might be changed when there are other platform devices being
created before hdmi-audio-codec device.
Use a fixed name so machine driver can set codec name on the DAI link.

Using the fixed name should be fine because there will only be one
hdmi-audio-codec device.

Fix the codec name in rockchip rk3288_hdmi_analog machine driver.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 7b93cf05c985..4974a32af31f 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -134,7 +134,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
 
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = pdev->dev.parent;
-   pdevinfo.id = PLATFORM_DEVID_AUTO;
+   pdevinfo.id = PLATFORM_DEVID_NONE;
pdevinfo.name   = HDMI_CODEC_DRV_NAME;
pdevinfo.data   = &pdata;
pdevinfo.size_data  = sizeof(pdata);
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c 
b/sound/soc/rockchip/rk3288_hdmi_analog.c
index 767700c34ee2..8286025a8747 100644
--- a/sound/soc/rockchip/rk3288_hdmi_analog.c
+++ b/sound/soc/rockchip/rk3288_hdmi_analog.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -142,7 +143,7 @@ static const struct snd_soc_ops rk_ops = {
 SND_SOC_DAILINK_DEFS(audio,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL),
-  COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")),
+  COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link rk_dailink = {
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v3 1/5] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-12 Thread Cheng-Yi Chiang
Add an op in hdmi_codec_ops so codec driver can register callback
function to handle plug event.

Driver in DRM can use this callback function to report connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 include/sound/hdmi-codec.h| 16 +
 sound/soc/codecs/hdmi-codec.c | 45 +++
 2 files changed, 61 insertions(+)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 7fea496f1f34..9a8661680256 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels;
 };
 
+typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
+ bool plugged);
+
 struct hdmi_codec_pdata;
 struct hdmi_codec_ops {
/*
@@ -88,6 +91,13 @@ struct hdmi_codec_ops {
 */
int (*get_dai_id)(struct snd_soc_component *comment,
  struct device_node *endpoint);
+
+   /*
+* Hook callback function to handle connector plug event.
+* Optional
+*/
+   int (*hook_plugged_cb)(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn);
 };
 
 /* HDMI codec initalization data */
@@ -99,6 +109,12 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0bf1c8cad108..32bf7441be5c 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -663,6 +666,48 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0;
 }
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (hcp->jack && jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static void plugged_cb(struct device *dev, bool plugged)
+{
+   struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
+
+   if (plugged)
+   hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+   else
+   hdmi_codec_jack_report(hcp, 0);
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI plugged callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack)
+{
+   struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+   int ret = -EOPNOTSUPP;
+
+   if (hcp->hcd.ops->hook_plugged_cb) {
+   hcp->jack = jack;
+   ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+   hcp->hcd.data,
+   plugged_cb);
+   if (ret)
+   hcp->jack = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
 {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v3 5/5] FROMLIST: ASoC: rockchip_max98090: Add HDMI jack support

2019-07-12 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c82948e383da..c81c4acda917 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -134,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v3 4/5] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-12 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 +-
 sound/soc/rockchip/rockchip_max98090.c | 96 --
 2 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..c82948e383da 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .

Re: [PATCH v3 5/5] FROMLIST: ASoC: rockchip_max98090: Add HDMI jack support

2019-07-12 Thread Cheng-yi Chiang
On Fri, Jul 12, 2019 at 6:06 PM Cheng-Yi Chiang  wrote:
>
> In machine driver, create a jack and let hdmi-codec report jack status.
>
> Signed-off-by: Cheng-Yi Chiang 
> ---
>  sound/soc/rockchip/rockchip_max98090.c | 20 
>  1 file changed, 20 insertions(+)
>
> diff --git a/sound/soc/rockchip/rockchip_max98090.c 
> b/sound/soc/rockchip/rockchip_max98090.c
> index c82948e383da..c81c4acda917 100644
> --- a/sound/soc/rockchip/rockchip_max98090.c
> +++ b/sound/soc/rockchip/rockchip_max98090.c
> @@ -134,6 +134,25 @@ enum {
> DAILINK_HDMI,
>  };
>
> +static struct snd_soc_jack rk_hdmi_jack;
> +
> +static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +   struct snd_soc_card *card = runtime->card;
> +   struct snd_soc_component *component = runtime->codec_dai->component;
> +   int ret;
> +
> +   /* enable jack detection */
> +   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
> +   &rk_hdmi_jack, NULL, 0);
> +   if (ret) {
> +   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
> +   return ret;
> +   }
> +
> +   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
> +}
> +
>  /* max98090 and HDMI codec dai_link */
>  static struct snd_soc_dai_link rk_dailinks[] = {
> [DAILINK_MAX98090] = {
> @@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
> .ops = &rk_aif1_ops,
> .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> SND_SOC_DAIFMT_CBS_CFS,
> +   .init = rk_hdmi_init,
> SND_SOC_DAILINK_REG(hdmi),
> }
>  };
> --
> 2.22.0.510.g264f2c817a-goog
>

Sorry for the wrong title.
I forgot to remove FROMLIST in the title.
I'll wait for comments on other patches and fix the title in v4.
Thanks!


Re: [PATCH v3 1/5] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-16 Thread Cheng-yi Chiang
On Mon, Jul 15, 2019 at 11:56 PM Tzung-Bi Shih  wrote:
>
> On Fri, Jul 12, 2019 at 6:58 PM Russell King - ARM Linux admin
>  wrote:
> >
> > On Fri, Jul 12, 2019 at 06:04:39PM +0800, Cheng-Yi Chiang wrote:
> > > Add an op in hdmi_codec_ops so codec driver can register callback
> > > function to handle plug event.
> > >
> > > Driver in DRM can use this callback function to report connector status.
> > >
> > > Signed-off-by: Cheng-Yi Chiang 
> > > ---
> > >  include/sound/hdmi-codec.h| 16 +
> > >  sound/soc/codecs/hdmi-codec.c | 45 +++
> > >  2 files changed, 61 insertions(+)
> > >
> > > diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> > > index 7fea496f1f34..9a8661680256 100644
> > > --- a/include/sound/hdmi-codec.h
> > > +++ b/include/sound/hdmi-codec.h
> > > @@ -47,6 +47,9 @@ struct hdmi_codec_params {
> > >   int channels;
> > >  };
> > >
> > > +typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
> > > +   bool plugged);
> > > +
> >
> > I'd like to pose a question for people to think about.
> >
> > Firstly, typedefs are generally shunned in the kernel.  However, for
> > these cases it seems to make sense.
> >
> > However, should the "pointer"-ness be part of the typedef or not?  To
> > see what I mean, consider:
> >
> > typedef void (*hdmi_foo)(void);
> >
> > int register_foo(hdmi_foo foo);
> >
> > vs
> >
> > typedef void hdmi_foo(void);
> >
> > int register_foo(hdmi_foo *foo);
> >
> > which is more in keeping with how we code non-typedef'd code - it's
> > obvious that foo is a pointer while reading the code.
> I have a different opinion.  Its suffix "_cb" self-described it is a
> callback function.  Since function and function pointer are equivalent
> in the language, I think we don't need to emphasize that it is a
> function "pointer".
>
>

Hi Russell and Tzungbi, thank you for the review.
Regarding this typedef of callback function, I found a thread
discussing this very long time ago:

https://yarchive.net/comp/linux/typedefs.html

>From that thread, Linus gave an example of using typedef for function
pointer that is following to this pattern.
I also looked around how other driver use it:
$ git grep typedef | grep _cb | less | wc -l
138
$ git grep typedef | grep _cb | grep "(\*" | wc -l
115
Most of the typedef of callback function use this pattern.
So I think this should be fine.
Thanks!


> > It seems to me that the latter better matches what is in the kernel's
> > coding style, which states:
> >
> >   In general, a pointer, or a struct that has elements that can
> >   reasonably be directly accessed should **never** be a typedef.
> >
> > or maybe Documentation/process/coding-style.rst needs updating?


[PATCH v4 2/5] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-16 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Change the Kconfig of DRM_DW_HDMI so it selects SND_SOC_HDMI_CODEC.
This is for the typedef of hdmi_codec_plugged_cb to be used in dw-hdmi.c.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/Kconfig   |  2 +-
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig 
b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 21a1be3ced0f..309da052db97 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -4,6 +4,7 @@ config DRM_DW_HDMI
select DRM_KMS_HELPER
select REGMAP_MMIO
select CEC_CORE if CEC_NOTIFIER
+   select SND_SOC_HDMI_CODEC
 
 config DRM_DW_HDMI_AHB_AUDIO
tristate "Synopsys Designware AHB Audio interface"
@@ -20,7 +21,6 @@ config DRM_DW_HDMI_I2S_AUDIO
tristate "Synopsys Designware I2S Audio interface"
depends on SND_SOC
depends on DRM_DW_HDMI
-   select SND_SOC_HDMI_CODEC
help
  Support the I2S Audio interface which is part of the Synopsys
  Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..ca56783fae47 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -104,10 +104,21 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 045b1b13fd0e..f32c66a6873d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -185,6 +185,10 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -209,6 +213,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2044,6 +2070,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2051,7 +2078,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi-&g

[PATCH v4 3/5] drm: dw-hdmi-i2s: Use fixed id for codec device

2019-07-16 Thread Cheng-Yi Chiang
The problem of using auto ID is that the device name will be like
hdmi-audio-codec..auto.

The number might be changed when there are other platform devices being
created before hdmi-audio-codec device.
Use a fixed name so machine driver can set codec name on the DAI link.

Using the fixed name should be fine because there will only be one
hdmi-audio-codec device.

Fix the codec name in rockchip rk3288_hdmi_analog machine driver.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index ca56783fae47..bc608f9258be 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -135,7 +135,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
 
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = pdev->dev.parent;
-   pdevinfo.id = PLATFORM_DEVID_AUTO;
+   pdevinfo.id = PLATFORM_DEVID_NONE;
pdevinfo.name   = HDMI_CODEC_DRV_NAME;
pdevinfo.data   = &pdata;
pdevinfo.size_data  = sizeof(pdata);
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c 
b/sound/soc/rockchip/rk3288_hdmi_analog.c
index 767700c34ee2..8286025a8747 100644
--- a/sound/soc/rockchip/rk3288_hdmi_analog.c
+++ b/sound/soc/rockchip/rk3288_hdmi_analog.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -142,7 +143,7 @@ static const struct snd_soc_ops rk_ops = {
 SND_SOC_DAILINK_DEFS(audio,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL),
-  COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")),
+  COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link rk_dailink = {
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v4 0/5] Add HDMI jack support on RK3288

2019-07-16 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

Changes from v3 to v4:
- hdmi-codec.h: Modify the hook_plugged_cb ops to take an additional argument,
  that is, the pointer to struct device for codec device.
- dw-hdmi-i2s-audio.c: Simplify the registration of callback so it uses
  dw_hdmi_set_plugged_cb exported by dw-hdmi.c.
- dw-hdmi.c: Simplify the flow to invoke callback since now dw_hdmi has a
  pointer to codec device as callback argument. There is no need to rely
  on driver data of other driver.
- dw-hdmi.c: Minor change for readability.
- synopsys/Kconfig: Fix the dependency of hdmi-codec in Kconfig.
- Fixed the incorrect FROMLIST title of patch 5/5.

Cheng-Yi Chiang (5):
  ASoC: hdmi-codec: Add an op to set callback function for plug event
  drm: bridge: dw-hdmi: Report connector status using callback
  drm: dw-hdmi-i2s: Use fixed id for codec device
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 drivers/gpu/drm/bridge/synopsys/Kconfig   |   2 +-
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  13 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 ++-
 include/drm/bridge/dw_hdmi.h  |   4 +
 include/sound/hdmi-codec.h|  17 +++
 sound/soc/codecs/hdmi-codec.c |  46 +++
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c   |   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 116 ++
 9 files changed, 217 insertions(+), 28 deletions(-)

-- 
2.22.0.510.g264f2c817a-goog



[PATCH v4 1/5] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-16 Thread Cheng-Yi Chiang
Add an op in hdmi_codec_ops so codec driver can register callback
function to handle plug event.

Driver in DRM can use this callback function to report connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 include/sound/hdmi-codec.h| 17 +
 sound/soc/codecs/hdmi-codec.c | 46 +++
 2 files changed, 63 insertions(+)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 7fea496f1f34..83b17682e01c 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels;
 };
 
+typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
+ bool plugged);
+
 struct hdmi_codec_pdata;
 struct hdmi_codec_ops {
/*
@@ -88,6 +91,14 @@ struct hdmi_codec_ops {
 */
int (*get_dai_id)(struct snd_soc_component *comment,
  struct device_node *endpoint);
+
+   /*
+* Hook callback function to handle connector plug event.
+* Optional
+*/
+   int (*hook_plugged_cb)(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev);
 };
 
 /* HDMI codec initalization data */
@@ -99,6 +110,12 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0bf1c8cad108..b5fd8f08726e 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -663,6 +666,49 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0;
 }
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (hcp->jack && jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static void plugged_cb(struct device *dev, bool plugged)
+{
+   struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
+
+   if (plugged)
+   hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+   else
+   hdmi_codec_jack_report(hcp, 0);
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI plugged callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack)
+{
+   struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+   int ret = -EOPNOTSUPP;
+
+   if (hcp->hcd.ops->hook_plugged_cb) {
+   hcp->jack = jack;
+   ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+   hcp->hcd.data,
+   plugged_cb,
+   component->dev);
+   if (ret)
+   hcp->jack = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
 {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v4 4/5] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-16 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 +-
 sound/soc/rockchip/rockchip_max98090.c | 96 --
 2 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..c82948e383da 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .

[PATCH v4 5/5] ASoC: rockchip_max98090: Add HDMI jack support

2019-07-16 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c82948e383da..c81c4acda917 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -134,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.22.0.510.g264f2c817a-goog



Re: [PATCH v4 2/5] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-16 Thread Cheng-yi Chiang
On Tue, Jul 16, 2019 at 10:13 PM Tzung-Bi Shih  wrote:
>
> On Tue, Jul 16, 2019 at 7:57 PM Cheng-Yi Chiang  wrote:
> >
> > Change the Kconfig of DRM_DW_HDMI so it selects SND_SOC_HDMI_CODEC.
> > This is for the typedef of hdmi_codec_plugged_cb to be used in dw-hdmi.c.
> Not sure why you select SND_SOC_HDMI_CODEC in this patch.  To have
> definition of hdmi_codec_plugged_cb, include hdmi-codec.h should be
> sufficient.
>
Thank you for the review!
I misunderstood when to change Kconfig.
Will fix in v5.
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig 
> > b/drivers/gpu/drm/bridge/synopsys/Kconfig
> > index 21a1be3ced0f..309da052db97 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
> > +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
> > @@ -4,6 +4,7 @@ config DRM_DW_HDMI
> > select DRM_KMS_HELPER
> > select REGMAP_MMIO
> > select CEC_CORE if CEC_NOTIFIER
> > +   select SND_SOC_HDMI_CODEC
> So that it is weird to select this option.
>
Will be removed in v5.
Thanks!
> >
> >  config DRM_DW_HDMI_AHB_AUDIO
> > tristate "Synopsys Designware AHB Audio interface"
> > @@ -20,7 +21,6 @@ config DRM_DW_HDMI_I2S_AUDIO
> > tristate "Synopsys Designware I2S Audio interface"
> > depends on SND_SOC
> > depends on DRM_DW_HDMI
> > -   select SND_SOC_HDMI_CODEC
> Also strange for deselecting the option.  Should be in another commit
> for another reason?
Will be removed in v5.
Thanks!


Re: [PATCH v3 2/5] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-17 Thread Cheng-yi Chiang
On Fri, Jul 12, 2019 at 6:48 PM Russell King - ARM Linux admin
 wrote:
>
> On Fri, Jul 12, 2019 at 06:04:40PM +0800, Cheng-Yi Chiang wrote:
> > Allow codec driver register callback function for plug event.
> >
> > The callback registration flow:
> > dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec
> >
> > dw-hdmi-i2s-audio implements hook_plugged_cb op
> > so codec driver can register the callback.
> >
> > dw-hdmi implements set_plugged_cb op so platform device can register the
> > callback.
> >
> > When connector plug/unplug event happens, report this event using the
> > callback.
> >
> > Make sure that audio and drm are using the single source of truth for
> > connector status.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  .../gpu/drm/bridge/synopsys/dw-hdmi-audio.h   |  3 +
> >  .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 10 
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 55 ++-
> >  3 files changed, 67 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > index 63b5756f463b..f523c590984e 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
> > @@ -2,6 +2,8 @@
> >  #ifndef DW_HDMI_AUDIO_H
> >  #define DW_HDMI_AUDIO_H
> >
> > +#include 
> > +
> >  struct dw_hdmi;
> >
> >  struct dw_hdmi_audio_data {
> > @@ -17,6 +19,7 @@ struct dw_hdmi_i2s_audio_data {
> >
> >   void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
> >   u8 (*read)(struct dw_hdmi *hdmi, int offset);
> > + int (*set_plugged_cb)(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn);
> >  };
> >
> >  #endif
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > index 5cbb71a866d5..7b93cf05c985 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > @@ -104,10 +104,20 @@ static int dw_hdmi_i2s_get_dai_id(struct 
> > snd_soc_component *component,
> >   return -EINVAL;
> >  }
> >
> > +static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
> > +hdmi_codec_plugged_cb fn)
> > +{
> > + struct dw_hdmi_i2s_audio_data *audio = data;
> > + struct dw_hdmi *hdmi = audio->hdmi;
> > +
> > + return audio->set_plugged_cb(hdmi, fn);
> > +}
> > +
> >  static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
> >   .hw_params  = dw_hdmi_i2s_hw_params,
> >   .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
> >   .get_dai_id = dw_hdmi_i2s_get_dai_id,
> > + .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
> >  };
> >
> >  static int snd_dw_hdmi_probe(struct platform_device *pdev)
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index 045b1b13fd0e..ce6646067472 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -26,6 +26,8 @@
> >  #include 
> >  #include 
> >
> > +#include 
> > +
> >  #include 
> >  #include 
> >
> > @@ -185,6 +187,9 @@ struct dw_hdmi {
> >   void (*disable_audio)(struct dw_hdmi *hdmi);
> >
> >   struct cec_notifier *cec_notifier;
> > +
> > + hdmi_codec_plugged_cb plugged_cb;
> > + enum drm_connector_status last_connector_result;
> >  };
> >
> >  #define HDMI_IH_PHY_STAT0_RX_SENSE \
> > @@ -209,6 +214,40 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
> > offset)
> >   return val;
> >  }
> >
> > +static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
> > +{
> > + struct platform_device *codec_pdev;
> > +
> > + if (!hdmi->audio || IS_ERR(hdmi->audio))
> > + return;
> > + codec_pdev = platform_get_drvdata(hdmi->audio);
> > + if (!codec_pdev || IS_ERR(codec_pdev))
> > + return;
>
> This looks fragile to me, poking about in another device's driver data
> from another driver is really not a good design decision.  I think this
> can be simplified if the registration function took the function
> pointer and the struct device pointer, and then you only need one test
> below:
>
Hi Russell,

Re: [PATCH v4 4/5] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-17 Thread Cheng-yi Chiang
On Tue, Jul 16, 2019 at 10:14 PM Tzung-Bi Shih  wrote:
>
> On Tue, Jul 16, 2019 at 7:58 PM Cheng-Yi Chiang  wrote:
> >
> > diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
> > index b43657e6e655..d610b553ea3b 100644
> > --- a/sound/soc/rockchip/Kconfig
> > +++ b/sound/soc/rockchip/Kconfig
> > @@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
> > select SND_SOC_ROCKCHIP_I2S
> > select SND_SOC_MAX98090
> > select SND_SOC_TS3A227E
> > +   select SND_SOC_HDMI_CODEC
> > help
> >   Say Y or M here if you want to add support for SoC audio on 
> > Rockchip
> > - boards using the MAX98090 codec, such as Veyron.
> > + boards using the MAX98090 codec and HDMI codec, such as Veyron.
> You should not need to select the option in this patch (but in next
> patch), because this patch does not depend on anything from
> hdmi-codec.c.
Thanks for the explanation.
I'll fix in v5.


Re: [PATCH v4 5/5] ASoC: rockchip_max98090: Add HDMI jack support

2019-07-17 Thread Cheng-yi Chiang
On Tue, Jul 16, 2019 at 10:16 PM Tzung-Bi Shih  wrote:
>
> On Tue, Jul 16, 2019 at 7:58 PM Cheng-Yi Chiang  wrote:
> >
> > diff --git a/sound/soc/rockchip/rockchip_max98090.c 
> > b/sound/soc/rockchip/rockchip_max98090.c
> > index c82948e383da..c81c4acda917 100644
> > --- a/sound/soc/rockchip/rockchip_max98090.c
> > +++ b/sound/soc/rockchip/rockchip_max98090.c
> > +static struct snd_soc_jack rk_hdmi_jack;
> > +
> > +static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
> > +{
> > +   struct snd_soc_card *card = runtime->card;
> > +   struct snd_soc_component *component = runtime->codec_dai->component;
> > +   int ret;
> > +
> > +   /* enable jack detection */
> > +   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
> > +   &rk_hdmi_jack, NULL, 0);
> > +   if (ret) {
> > +   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
> > +   return ret;
> > +   }
> > +
> > +   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
> > +}
> In the patch, you should select SND_SOC_HDMI_CODEC, because the patch
> uses hdmi_codec_set_jack_detect which depends on hdmi-codec.c.
Thanks! I'll fix in v5.


[PATCH v5 1/5] ASoC: hdmi-codec: Add an op to set callback function for plug event

2019-07-17 Thread Cheng-Yi Chiang
Add an op in hdmi_codec_ops so codec driver can register callback
function to handle plug event.

Driver in DRM can use this callback function to report connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 include/sound/hdmi-codec.h| 17 +
 sound/soc/codecs/hdmi-codec.c | 46 +++
 2 files changed, 63 insertions(+)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 7fea496f1f34..83b17682e01c 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -47,6 +47,9 @@ struct hdmi_codec_params {
int channels;
 };
 
+typedef void (*hdmi_codec_plugged_cb)(struct device *dev,
+ bool plugged);
+
 struct hdmi_codec_pdata;
 struct hdmi_codec_ops {
/*
@@ -88,6 +91,14 @@ struct hdmi_codec_ops {
 */
int (*get_dai_id)(struct snd_soc_component *comment,
  struct device_node *endpoint);
+
+   /*
+* Hook callback function to handle connector plug event.
+* Optional
+*/
+   int (*hook_plugged_cb)(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev);
 };
 
 /* HDMI codec initalization data */
@@ -99,6 +110,12 @@ struct hdmi_codec_pdata {
void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0bf1c8cad108..b5fd8f08726e 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,8 @@ struct hdmi_codec_priv {
struct snd_pcm_chmap *chmap_info;
unsigned int chmap_idx;
struct mutex lock;
+   struct snd_soc_jack *jack;
+   unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -663,6 +666,49 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai)
return 0;
 }
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+  unsigned int jack_status)
+{
+   if (hcp->jack && jack_status != hcp->jack_status) {
+   snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+   hcp->jack_status = jack_status;
+   }
+}
+
+static void plugged_cb(struct device *dev, bool plugged)
+{
+   struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
+
+   if (plugged)
+   hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+   else
+   hdmi_codec_jack_report(hcp, 0);
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI plugged callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+  struct snd_soc_jack *jack)
+{
+   struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+   int ret = -EOPNOTSUPP;
+
+   if (hcp->hcd.ops->hook_plugged_cb) {
+   hcp->jack = jack;
+   ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+   hcp->hcd.data,
+   plugged_cb,
+   component->dev);
+   if (ret)
+   hcp->jack = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)
 {
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 0/5] Add HDMI jack support on RK3288

2019-07-17 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

Changes from v4 to v5:
- synopsys/Kconfig: Remove the incorrect dependency change in v4.
- rockchip/Kconfig: Add dependency of hdmi-codec when it is really need
  for jack support.

Cheng-Yi Chiang (5):
  ASoC: hdmi-codec: Add an op to set callback function for plug event
  drm: bridge: dw-hdmi: Report connector status using callback
  drm: dw-hdmi-i2s: Use fixed id for codec device
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  13 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 ++-
 include/drm/bridge/dw_hdmi.h  |   4 +
 include/sound/hdmi-codec.h|  17 +++
 sound/soc/codecs/hdmi-codec.c |  46 +++
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c   |   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 116 ++
 8 files changed, 216 insertions(+), 27 deletions(-)

-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 2/5] drm: bridge: dw-hdmi: Report connector status using callback

2019-07-17 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..ca56783fae47 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -104,10 +104,21 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 045b1b13fd0e..f32c66a6873d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -185,6 +185,10 @@ struct dw_hdmi {
void (*disable_audio)(struct dw_hdmi *hdmi);
 
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -209,6 +213,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2044,6 +2070,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2051,7 +2078,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   handle_plugged_change(hdmi,
+ result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -2460,6 +2498,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
hdmi->mc_clkdis = 0x7f;
+   hdmi->last_connector_result = connector_status_disconnected;
 
mutex_init(&hdmi->mutex);
mutex_init(&hdmi->audio_mutex);
diff --git a/i

[PATCH v5 5/5] ASoC: rockchip_max98090: Add HDMI jack support

2019-07-17 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 ++-
 sound/soc/rockchip/rockchip_max98090.c | 20 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c82948e383da..c81c4acda917 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -134,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 3/5] drm: dw-hdmi-i2s: Use fixed id for codec device

2019-07-17 Thread Cheng-Yi Chiang
The problem of using auto ID is that the device name will be like
hdmi-audio-codec..auto.

The number might be changed when there are other platform devices being
created before hdmi-audio-codec device.
Use a fixed name so machine driver can set codec name on the DAI link.

Using the fixed name should be fine because there will only be one
hdmi-audio-codec device.

Fix the codec name in rockchip rk3288_hdmi_analog machine driver.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index ca56783fae47..bc608f9258be 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -135,7 +135,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
 
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = pdev->dev.parent;
-   pdevinfo.id = PLATFORM_DEVID_AUTO;
+   pdevinfo.id = PLATFORM_DEVID_NONE;
pdevinfo.name   = HDMI_CODEC_DRV_NAME;
pdevinfo.data   = &pdata;
pdevinfo.size_data  = sizeof(pdata);
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c 
b/sound/soc/rockchip/rk3288_hdmi_analog.c
index 767700c34ee2..8286025a8747 100644
--- a/sound/soc/rockchip/rk3288_hdmi_analog.c
+++ b/sound/soc/rockchip/rk3288_hdmi_analog.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -142,7 +143,7 @@ static const struct snd_soc_ops rk_ops = {
 SND_SOC_DAILINK_DEFS(audio,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL),
-  COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")),
+  COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link rk_dailink = {
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 4/5] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-07-17 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 96 --
 1 file changed, 73 insertions(+), 23 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..c82948e383da 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(hdmi),
+   }
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -136,8 +165,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
-   .dai_link = &rk_dailink,
-   .num_links = 1,
+   .dai_link = rk_dailinks,
+   .num_links = ARRAY_SIZE(rk_dailinks),
.aux_dev = &rk_98090_headset_dev,
.num_aux_devs = 1,
.dapm_widgets = rk_dapm_widgets,
@@ -173,27 +202,48 @@ 

[PATCH v8 0/6] Add HDMI jack support on RK3288

2019-10-28 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

The dependent change on hdmi-codec.c

6fa5963c37a2 ASoC: hdmi-codec: Add an op to set callback function for plug event

has been merged to upstream.

Changes from v7 to v8:

1. rockchip_max98090: Allow three different use cases:
   max98090-only: For backward compatibility where DTS does not specify HDMI 
node.
   HDMI-only: For HDMI-only board like veyron-mickey.
   max98090 + HDMI: For other veyron boards.
   Pass different compatible string to specify the use case.

2. Add more maintainers to cc-list for new device property reviewing.

Cheng-Yi Chiang (6):
  drm: bridge: dw-hdmi: Report connector status using callback
  ASoC: rockchip-max98090: Support usage with and without HDMI
  ASoC: rockchip_max98090: Optionally support HDMI use case
  ASoC: rockchip_max98090: Add HDMI jack support
  ARM: dts: rockchip: Add HDMI support to rk3288-veyron-analog-audio
  ARM: dts: rockchip: Add HDMI audio support to rk3288-veyron-mickey.dts

 .../bindings/sound/rockchip-max98090.txt  |  38 +-
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   3 +-
 arch/arm/boot/dts/rk3288-veyron-mickey.dts|   7 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 +-
 include/drm/bridge/dw_hdmi.h  |   4 +
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 392 +++---
 8 files changed, 425 insertions(+), 74 deletions(-)

-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v8 5/6] ARM: dts: rockchip: Add HDMI support to rk3288-veyron-analog-audio

2019-10-28 Thread Cheng-Yi Chiang
All boards using rk3288-veyron-analog-audio.dtsi have HDMI audio.
Specify the support of HDMI audio on machine driver using compatible
string so machine driver creates HDMI audio device.

Signed-off-by: Cheng-Yi Chiang 
---
 arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi 
b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
index 445270aa136e..92ea623401e9 100644
--- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
@@ -8,7 +8,7 @@
 
 / {
sound {
-   compatible = "rockchip,rockchip-audio-max98090";
+   compatible = "rockchip,rockchip-audio-max98090-hdmi";
pinctrl-names = "default";
pinctrl-0 = <&mic_det>, <&hp_det>;
rockchip,model = "VEYRON-I2S";
@@ -17,6 +17,7 @@
rockchip,hp-det-gpios = <&gpio6 RK_PA5 GPIO_ACTIVE_HIGH>;
rockchip,mic-det-gpios = <&gpio6 RK_PB3 GPIO_ACTIVE_LOW>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
};
 };
 
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v8 1/6] drm: bridge: dw-hdmi: Report connector status using callback

2019-10-28 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 1d15cf9b6821..6c2c44d0bdee 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -151,11 +151,22 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld= dw_hdmi_i2s_get_eld,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 521d689413c8..2102872bf43c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -191,6 +191,10 @@ struct dw_hdmi {
 
struct mutex cec_notifier_mutex;
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -215,6 +219,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2161,6 +2187,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2168,7 +2195,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   handle_plugged_change(hdmi,
+ result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -2619,6 +2657,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
hdmi->mc_clkdis = 0x7f;
+   hdmi->last_connector_result = connector_status_disconnected;
 
mutex_init(&hdmi->mutex);
mutex_init(&hd

[PATCH v9 5/6] ARM: dts: rockchip: Add HDMI support to rk3288-veyron-analog-audio

2019-10-28 Thread Cheng-Yi Chiang
All boards using rk3288-veyron-analog-audio.dtsi have HDMI audio.
Specify the support of HDMI audio on machine driver using
rockchip,hdmi-codec property so machine driver creates HDMI audio device.

Signed-off-by: Cheng-Yi Chiang 
---
 arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi 
b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
index 445270aa136e..51208d161d65 100644
--- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
@@ -17,6 +17,7 @@
rockchip,hp-det-gpios = <&gpio6 RK_PA5 GPIO_ACTIVE_HIGH>;
rockchip,mic-det-gpios = <&gpio6 RK_PB3 GPIO_ACTIVE_LOW>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
};
 };
 
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v9 4/6] ASoC: rockchip_max98090: Add HDMI jack support

2019-10-28 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 ++-
 sound/soc/rockchip/rockchip_max98090.c | 22 ++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 50ef9b8e7ce4..5c2504a465f4 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -218,6 +219,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 dai_link */
 static struct snd_soc_dai_link rk_max98090_dailinks[] = {
{
@@ -237,6 +257,7 @@ static struct snd_soc_dai_link rk_hdmi_dailinks[] = {
{
.name = "HDMI",
.stream_name = "HDMI",
+   .init = rk_hdmi_init,
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
@@ -259,6 +280,7 @@ static struct snd_soc_dai_link rk_max98090_hdmi_dailinks[] 
= {
[DAILINK_HDMI] = {
.name = "HDMI",
.stream_name = "HDMI",
+   .init = rk_hdmi_init,
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v9 2/6] ASoC: rockchip-max98090: Support usage with and without HDMI

2019-10-28 Thread Cheng-Yi Chiang
Add one optional property "rockchip,hdmi-codec" to let user specify HDMI
device node in DTS so machine driver can find hdmi-codec device node for
HDMI codec DAI.

Use the presence of rockchip,audio-codec and rockchip,hdmi-codec to
specify the use case.

Use max98090 only : specify rockchip,audio-codec.
Use HDMI only: specify rockchip,hdmi-codec.
Use both max98090 and HDMI: specify rockchip,audio-codec and
rockchip,hdmi-codec.

Move these properties to optional because they are not needed for
HDMI-only use case.
"rockchip,audio-codec": The phandle of the MAX98090 audio codec
"rockchip,headset-codec": The phandle of Ext chip for jack detection

Signed-off-by: Cheng-Yi Chiang 
---
 .../bindings/sound/rockchip-max98090.txt  | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt 
b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
index a805aa99ad75..e9c58b204399 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
@@ -5,15 +5,38 @@ Required properties:
 - rockchip,model: The user-visible name of this sound complex
 - rockchip,i2s-controller: The phandle of the Rockchip I2S controller that's
   connected to the CODEC
-- rockchip,audio-codec: The phandle of the MAX98090 audio codec
-- rockchip,headset-codec: The phandle of Ext chip for jack detection
+
+Optional properties:
+- rockchip,audio-codec: The phandle of the MAX98090 audio codec.
+- rockchip,headset-codec: The phandle of Ext chip for jack detection. This is
+  required if there is rockchip,audio-codec.
+- rockchip,hdmi-codec: The phandle of HDMI device for HDMI codec.
 
 Example:
 
+/* For max98090-only board. */
+sound {
+   compatible = "rockchip,rockchip-audio-max98090";
+   rockchip,model = "ROCKCHIP-I2S";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,audio-codec = <&max98090>;
+   rockchip,headset-codec = <&headsetcodec>;
+};
+
+/* For HDMI-only board. */
+sound {
+   compatible = "rockchip,rockchip-audio-max98090";
+   rockchip,model = "ROCKCHIP-I2S";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,hdmi-codec = <&hdmi>;
+};
+
+/* For max98090 plus HDMI board. */
 sound {
compatible = "rockchip,rockchip-audio-max98090";
rockchip,model = "ROCKCHIP-I2S";
rockchip,i2s-controller = <&i2s>;
rockchip,audio-codec = <&max98090>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
 };
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v8 2/6] ASoC: rockchip-max98090: Support usage with and without HDMI

2019-10-28 Thread Cheng-Yi Chiang
There will be multiple boards sharing this machine driver.
Use compatible string to specify the use case.

"rockchip,rockchip-audio-max98090" for max98090-only.
"rockchip,rockchip-audio-hdmi" for HDMI-only
"rockchip,rockchip-audio-max98090-hdmi" for max98090 plus

Move these properties to optional because they are not needed for
HDMI-only use case.
"rockchip,audio-codec": The phandle of the MAX98090 audio codec
"rockchip,headset-codec": The phandle of Ext chip for jack detection

The machine driver change will add support for HDMI codec in
rockchip-max98090.
Add one optional property "rockchip,hdmi-codec" to let user specify HDMI
device node in DTS so machine driver can find hdmi-codec device node for
codec DAI.

Signed-off-by: Cheng-Yi Chiang 
---
 .../bindings/sound/rockchip-max98090.txt  | 38 +--
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt 
b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
index a805aa99ad75..75f438741ca6 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
@@ -1,15 +1,29 @@
 ROCKCHIP with MAX98090 CODEC
 
 Required properties:
-- compatible: "rockchip,rockchip-audio-max98090"
+- compatible: Set this property to one of the strings below depending on the
+  usage on the board:
+  "rockchip,rockchip-audio-max98090" for max98090-only.
+  "rockchip,rockchip-audio-hdmi" for HDMI-only
+  "rockchip,rockchip-audio-max98090-hdmi" for max98090 plus HDMI.
 - rockchip,model: The user-visible name of this sound complex
 - rockchip,i2s-controller: The phandle of the Rockchip I2S controller that's
   connected to the CODEC
-- rockchip,audio-codec: The phandle of the MAX98090 audio codec
-- rockchip,headset-codec: The phandle of Ext chip for jack detection
+
+Optional properties:
+- rockchip,audio-codec: The phandle of the MAX98090 audio codec. This is
+required if compatible string is set to the one
+with max98090.
+- rockchip,headset-codec: The phandle of Ext chip for jack detection. This is
+  required if compatible string is set to the one
+  with max98090.
+- rockchip,hdmi-codec: The phandle of HDMI device for HDMI codec. This is
+   required if compatible string is set to the one with
+   HDMI.
 
 Example:
 
+/* For max98090-only board. */
 sound {
compatible = "rockchip,rockchip-audio-max98090";
rockchip,model = "ROCKCHIP-I2S";
@@ -17,3 +31,21 @@ sound {
rockchip,audio-codec = <&max98090>;
rockchip,headset-codec = <&headsetcodec>;
 };
+
+/* For HDMI-only board. */
+sound {
+   compatible = "rockchip,rockchip-audio-hdmi";
+   rockchip,model = "ROCKCHIP-I2S";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,hdmi-codec = <&hdmi>;
+};
+
+/* For max98090 plus HDMI board. */
+sound {
+   compatible = "rockchip,rockchip-audio-max98090-hdmi";
+   rockchip,model = "ROCKCHIP-I2S";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,audio-codec = <&max98090>;
+   rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
+};
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v9 6/6] ARM: dts: rockchip: Add HDMI audio support to rk3288-veyron-mickey.dts

2019-10-28 Thread Cheng-Yi Chiang
Add HDMI audio support to veyron-mickey. The sound card should expose
one audio device for HDMI.

Signed-off-by: Cheng-Yi Chiang 
---
 arch/arm/boot/dts/rk3288-veyron-mickey.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron-mickey.dts 
b/arch/arm/boot/dts/rk3288-veyron-mickey.dts
index aa352d40c991..cf53cb4594c4 100644
--- a/arch/arm/boot/dts/rk3288-veyron-mickey.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-mickey.dts
@@ -28,6 +28,13 @@
regulator-boot-on;
vin-supply = <&vcc33_sys>;
};
+
+   sound {
+   compatible = "rockchip,rockchip-audio-max98090";
+   rockchip,model = "VEYRON-HDMI";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,hdmi-codec = <&hdmi>;
+   };
 };
 
 &cpu_thermal {
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v9 1/6] drm: bridge: dw-hdmi: Report connector status using callback

2019-10-28 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 1d15cf9b6821..6c2c44d0bdee 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -151,11 +151,22 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld= dw_hdmi_i2s_get_eld,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 521d689413c8..2102872bf43c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -191,6 +191,10 @@ struct dw_hdmi {
 
struct mutex cec_notifier_mutex;
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -215,6 +219,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2161,6 +2187,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2168,7 +2195,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   handle_plugged_change(hdmi,
+ result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -2619,6 +2657,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
hdmi->mc_clkdis = 0x7f;
+   hdmi->last_connector_result = connector_status_disconnected;
 
mutex_init(&hdmi->mutex);
mutex_init(&hd

Re: [PATCH v8 2/6] ASoC: rockchip-max98090: Support usage with and without HDMI

2019-10-28 Thread Cheng-yi Chiang
On Sat, Oct 26, 2019 at 12:22 AM Rob Herring  wrote:
>
> On Fri, Oct 25, 2019 at 09:30:03PM +0800, Cheng-Yi Chiang wrote:
> > There will be multiple boards sharing this machine driver.
> > Use compatible string to specify the use case.
> >
> > "rockchip,rockchip-audio-max98090" for max98090-only.
> > "rockchip,rockchip-audio-hdmi" for HDMI-only
> > "rockchip,rockchip-audio-max98090-hdmi" for max98090 plus
> >
> > Move these properties to optional because they are not needed for
> > HDMI-only use case.
> > "rockchip,audio-codec": The phandle of the MAX98090 audio codec
> > "rockchip,headset-codec": The phandle of Ext chip for jack detection
> >
> > The machine driver change will add support for HDMI codec in
> > rockchip-max98090.
> > Add one optional property "rockchip,hdmi-codec" to let user specify HDMI
> > device node in DTS so machine driver can find hdmi-codec device node for
> > codec DAI.
>
> Why not just use the presence of rockchip,hdmi-codec to enable HDMI or
> not. Maybe you still add rockchip,rockchip-audio-hdmi for HDMI only.
>
> Really, the same should have been done for which codec is used too, but
> I guess someone wanted 2 machine drivers.

Hi Rob,
Thanks for the quick reply.
I can make change in machine driver so that
- The presence of rockchip,audio-codec enable max98090
- The presence of rockchip,hdmi-codec enable HDMI.

With that, we don't need the three properties added in this patch:
"rockchip,rockchip-audio-max98090" for max98090-only.
"rockchip,rockchip-audio-hdmi" for HDMI-only
"rockchip,rockchip-audio-max98090-hdmi" for max98090 plus HDMI.

I will post an update soon. Thanks!

>
>
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  .../bindings/sound/rockchip-max98090.txt  | 38 +--
> >  1 file changed, 35 insertions(+), 3 deletions(-)
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v8 3/6] ASoC: rockchip_max98090: Optionally support HDMI use case

2019-10-28 Thread Cheng-Yi Chiang
Support three different use cases with rockchip_max98090 driver:

- max98090 only: Current usage, where HDMI link is missing.
- HDMI only: Needed use case for veyron_mickey board.
- max98090 + HDMI: Ideal use case for veyron_jerry, veyron_minnie..etc.

Note that we keep max98090 only usage for backward compatibility.
From devicetree, different compatible string can be passed to configure
the usage.

Signed-off-by: Cheng-Yi Chiang 
---
The checkpatch error
"Macros with complex values should be enclosed in parentheses"
seems not suitable for the macro usage for DAPM widget, route, and controls.

 sound/soc/rockchip/rockchip_max98090.c | 371 -
 1 file changed, 303 insertions(+), 68 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 0097df1fae66..550e57789719 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -6,11 +6,13 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -21,6 +23,17 @@
 
 #define DRV_NAME "rockchip-snd-max98090"
 
+enum rk_snd_usage {
+   RK_USE_MAX98090, /* Only use max98090. */
+   RK_USE_HDMI, /* Only use HDMI. */
+   RK_USE_MAX98090_HDMI, /* Use both max98090 and HDMI. */
+};
+
+struct rk_card_config {
+   enum rk_snd_usage usage;
+   struct snd_soc_card *card;
+};
+
 static struct snd_soc_jack headset_jack;
 
 /* Headset jack detection DAPM pins */
@@ -36,28 +49,73 @@ static struct snd_soc_jack_pin headset_jack_pins[] = {
 
 };
 
-static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
-   SND_SOC_DAPM_HP("Headphone", NULL),
-   SND_SOC_DAPM_MIC("Headset Mic", NULL),
-   SND_SOC_DAPM_MIC("Int Mic", NULL),
-   SND_SOC_DAPM_SPK("Speaker", NULL),
+#define RK_MAX98090_WIDGETS \
+   SND_SOC_DAPM_HP("Headphone", NULL), \
+   SND_SOC_DAPM_MIC("Headset Mic", NULL), \
+   SND_SOC_DAPM_MIC("Int Mic", NULL), \
+   SND_SOC_DAPM_SPK("Speaker", NULL)
+
+#define RK_HDMI_WIDGETS \
+   SND_SOC_DAPM_LINE("HDMI", NULL)
+
+static const struct snd_soc_dapm_widget rk_max98090_dapm_widgets[] = {
+   RK_MAX98090_WIDGETS,
+};
+
+static const struct snd_soc_dapm_widget rk_hdmi_dapm_widgets[] = {
+   RK_HDMI_WIDGETS,
+};
+
+static const struct snd_soc_dapm_widget rk_max98090_hdmi_dapm_widgets[] = {
+   RK_MAX98090_WIDGETS,
+   RK_HDMI_WIDGETS,
+};
+
+#define RK_MAX98090_AUDIO_MAP \
+   {"IN34", NULL, "Headset Mic"}, \
+   {"Headset Mic", NULL, "MICBIAS"}, \
+   {"DMICL", NULL, "Int Mic"}, \
+   {"Headphone", NULL, "HPL"}, \
+   {"Headphone", NULL, "HPR"}, \
+   {"Speaker", NULL, "SPKL"}, \
+   {"Speaker", NULL, "SPKR"}
+
+#define RK_HDMI_AUDIO_MAP \
+   {"HDMI", NULL, "TX"}
+
+static const struct snd_soc_dapm_route rk_max98090_audio_map[] = {
+   RK_MAX98090_AUDIO_MAP,
+};
+
+static const struct snd_soc_dapm_route rk_hdmi_audio_map[] = {
+   RK_HDMI_AUDIO_MAP,
+};
+
+static const struct snd_soc_dapm_route rk_max98090_hdmi_audio_map[] = {
+   RK_MAX98090_AUDIO_MAP,
+   RK_HDMI_AUDIO_MAP,
+};
+
+#define RK_MAX98090_CONTROLS \
+   SOC_DAPM_PIN_SWITCH("Headphone"), \
+   SOC_DAPM_PIN_SWITCH("Headset Mic"), \
+   SOC_DAPM_PIN_SWITCH("Int Mic"), \
+   SOC_DAPM_PIN_SWITCH("Speaker")
+
+#define RK_HDMI_CONTROLS \
+   SOC_DAPM_PIN_SWITCH("HDMI")
+
+static const struct snd_kcontrol_new rk_max98090_controls[] = {
+   RK_MAX98090_CONTROLS,
 };
 
-static const struct snd_soc_dapm_route rk_audio_map[] = {
-   {"IN34", NULL, "Headset Mic"},
-   {"Headset Mic", NULL, "MICBIAS"},
-   {"DMICL", NULL, "Int Mic"},
-   {"Headphone", NULL, "HPL"},
-   {"Headphone", NULL, "HPR"},
-   {"Speaker", NULL, "SPKL"},
-   {"Speaker", NULL, "SPKR"},
+static const struct snd_kcontrol_new rk_hdmi_controls[] = {
+   RK_HDMI_CONTROLS,
 };
 
-static const struct snd_kcontrol_new rk_mc_controls[] = {
-   SOC_DAPM_PIN_SWITCH("Headphone"),
-   SOC_DAPM_PIN_SWITCH("Headset Mic"),
-   SOC_DAPM_PIN_SWITCH("Int Mic"),
-   SOC_DAPM_PIN_SWITCH("Speaker"),
+static const struct snd_kcontrol_new rk_max98090_hdmi_controls[] = {
+   RK_MAX98090_CONTROLS,
+   RK_HDMI_CONTROLS,
 };
 
 static int rk_jack_event(struct notifier_block *nb, unsigned long event,
@@ -122,15 +180,20 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
 

[PATCH v8 6/6] ARM: dts: rockchip: Add HDMI audio support to rk3288-veyron-mickey.dts

2019-10-28 Thread Cheng-Yi Chiang
Add HDMI audio support to veyron-mickey. The sound card should expose
one audio device for HDMI.

Signed-off-by: Cheng-Yi Chiang 
---
 arch/arm/boot/dts/rk3288-veyron-mickey.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron-mickey.dts 
b/arch/arm/boot/dts/rk3288-veyron-mickey.dts
index aa352d40c991..98a2aee240f1 100644
--- a/arch/arm/boot/dts/rk3288-veyron-mickey.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-mickey.dts
@@ -28,6 +28,13 @@
regulator-boot-on;
vin-supply = <&vcc33_sys>;
};
+
+   sound {
+   compatible = "rockchip,rockchip-audio-hdmi";
+   rockchip,model = "VEYRON-HDMI";
+   rockchip,i2s-controller = <&i2s>;
+   rockchip,hdmi-codec = <&hdmi>;
+   };
 };
 
 &cpu_thermal {
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v8 4/6] ASoC: rockchip_max98090: Add HDMI jack support

2019-10-28 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 ++-
 sound/soc/rockchip/rockchip_max98090.c | 21 +
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 550e57789719..fdd1d9921a4e 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -230,6 +230,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 dai_link */
 static struct snd_soc_dai_link rk_max98090_dailinks[] = {
{
@@ -249,6 +268,7 @@ static struct snd_soc_dai_link rk_hdmi_dailinks[] = {
{
.name = "HDMI",
.stream_name = "HDMI",
+   .init = rk_hdmi_init,
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
@@ -271,6 +291,7 @@ static struct snd_soc_dai_link rk_max98090_hdmi_dailinks[] 
= {
[DAILINK_HDMI] = {
.name = "HDMI",
.stream_name = "HDMI",
+   .init = rk_hdmi_init,
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v9 3/6] ASoC: rockchip_max98090: Optionally support HDMI use case

2019-10-28 Thread Cheng-Yi Chiang
Support three different use cases with rockchip_max98090 driver.

The three use cases:
- max98090 only: Current usage, where HDMI link is missing.
- HDMI only: Needed use case for veyron_mickey board.
- max98090 + HDMI: Ideal use case for veyron_jerry, veyron_minnie..etc.

The presence of max98090 is determined by the presence of
rockchip,audio-codec device property.

The presence of HDMI is determined by the presence of
rockchip,hdmi-codec device property.

Create different sound card based on the configuration.
Note that we keep max98090 only usage for backward compatibility.

Signed-off-by: Cheng-Yi Chiang 
---
 The checkpatch reported error
 "Macros with complex values should be enclosed in parentheses".
 It is ignored because it does not suit the usage in this patch.

 sound/soc/rockchip/rockchip_max98090.c | 291 +++--
 1 file changed, 226 insertions(+), 65 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 0097df1fae66..50ef9b8e7ce4 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -6,6 +6,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,28 +37,73 @@ static struct snd_soc_jack_pin headset_jack_pins[] = {
 
 };
 
-static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
-   SND_SOC_DAPM_HP("Headphone", NULL),
-   SND_SOC_DAPM_MIC("Headset Mic", NULL),
-   SND_SOC_DAPM_MIC("Int Mic", NULL),
-   SND_SOC_DAPM_SPK("Speaker", NULL),
+#define RK_MAX98090_WIDGETS \
+   SND_SOC_DAPM_HP("Headphone", NULL), \
+   SND_SOC_DAPM_MIC("Headset Mic", NULL), \
+   SND_SOC_DAPM_MIC("Int Mic", NULL), \
+   SND_SOC_DAPM_SPK("Speaker", NULL)
+
+#define RK_HDMI_WIDGETS \
+   SND_SOC_DAPM_LINE("HDMI", NULL)
+
+static const struct snd_soc_dapm_widget rk_max98090_dapm_widgets[] = {
+   RK_MAX98090_WIDGETS,
+};
+
+static const struct snd_soc_dapm_widget rk_hdmi_dapm_widgets[] = {
+   RK_HDMI_WIDGETS,
+};
+
+static const struct snd_soc_dapm_widget rk_max98090_hdmi_dapm_widgets[] = {
+   RK_MAX98090_WIDGETS,
+   RK_HDMI_WIDGETS,
+};
+
+#define RK_MAX98090_AUDIO_MAP \
+   {"IN34", NULL, "Headset Mic"}, \
+   {"Headset Mic", NULL, "MICBIAS"}, \
+   {"DMICL", NULL, "Int Mic"}, \
+   {"Headphone", NULL, "HPL"}, \
+   {"Headphone", NULL, "HPR"}, \
+   {"Speaker", NULL, "SPKL"}, \
+   {"Speaker", NULL, "SPKR"}
+
+#define RK_HDMI_AUDIO_MAP \
+   {"HDMI", NULL, "TX"}
+
+static const struct snd_soc_dapm_route rk_max98090_audio_map[] = {
+   RK_MAX98090_AUDIO_MAP,
+};
+
+static const struct snd_soc_dapm_route rk_hdmi_audio_map[] = {
+   RK_HDMI_AUDIO_MAP,
 };
 
-static const struct snd_soc_dapm_route rk_audio_map[] = {
-   {"IN34", NULL, "Headset Mic"},
-   {"Headset Mic", NULL, "MICBIAS"},
-   {"DMICL", NULL, "Int Mic"},
-   {"Headphone", NULL, "HPL"},
-   {"Headphone", NULL, "HPR"},
-   {"Speaker", NULL, "SPKL"},
-   {"Speaker", NULL, "SPKR"},
+static const struct snd_soc_dapm_route rk_max98090_hdmi_audio_map[] = {
+   RK_MAX98090_AUDIO_MAP,
+   RK_HDMI_AUDIO_MAP,
+};
+
+#define RK_MAX98090_CONTROLS \
+   SOC_DAPM_PIN_SWITCH("Headphone"), \
+   SOC_DAPM_PIN_SWITCH("Headset Mic"), \
+   SOC_DAPM_PIN_SWITCH("Int Mic"), \
+   SOC_DAPM_PIN_SWITCH("Speaker")
+
+#define RK_HDMI_CONTROLS \
+   SOC_DAPM_PIN_SWITCH("HDMI")
+
+static const struct snd_kcontrol_new rk_max98090_controls[] = {
+   RK_MAX98090_CONTROLS,
 };
 
-static const struct snd_kcontrol_new rk_mc_controls[] = {
-   SOC_DAPM_PIN_SWITCH("Headphone"),
-   SOC_DAPM_PIN_SWITCH("Headset Mic"),
-   SOC_DAPM_PIN_SWITCH("Int Mic"),
-   SOC_DAPM_PIN_SWITCH("Speaker"),
+static const struct snd_kcontrol_new rk_hdmi_controls[] = {
+   RK_HDMI_CONTROLS,
+};
+
+static const struct snd_kcontrol_new rk_max98090_hdmi_controls[] = {
+   RK_MAX98090_CONTROLS,
+   RK_HDMI_CONTROLS,
 };
 
 static int rk_jack_event(struct notifier_block *nb, unsigned long event,
@@ -122,15 +168,20 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n

[PATCH v9 0/6] Add HDMI jack support on RK3288

2019-10-28 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

The dependent change on hdmi-codec.c

commit 6fa5963c37a2 ("ASoC: hdmi-codec: Add an op to set callback function for 
plug event")

has been merged to upstream.

Changes from v8 to v9:

1. rockchip_max98090:
   Use the presence of rockchip,audio-codec to determine the presense of 
max98090
   in sound card.
   Use the presence of rockchip,hdmi-codec to determine the presence of HDMI in
   sound card.
   Remove the compatible strings added in v8.

2. #include  should be in the patch of adding HDMI jack 
support.

Cheng-Yi Chiang (6):
  drm: bridge: dw-hdmi: Report connector status using callback
  ASoC: rockchip-max98090: Support usage with and without HDMI
  ASoC: rockchip_max98090: Optionally support HDMI use case
  ASoC: rockchip_max98090: Add HDMI jack support
  ARM: dts: rockchip: Add HDMI support to rk3288-veyron-analog-audio
  ARM: dts: rockchip: Add HDMI audio support to rk3288-veyron-mickey.dts

 .../bindings/sound/rockchip-max98090.txt  |  27 +-
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
 arch/arm/boot/dts/rk3288-veyron-mickey.dts|   7 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 ++-
 include/drm/bridge/dw_hdmi.h  |   4 +
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 313 ++
 8 files changed, 338 insertions(+), 69 deletions(-)

-- 
2.24.0.rc0.303.g954a862665-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v8 3/6] ASoC: rockchip_max98090: Optionally support HDMI use case

2019-10-30 Thread Cheng-yi Chiang
On Tue, Oct 29, 2019 at 3:10 AM kbuild test robot  wrote:
>
> Hi Cheng-Yi,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on rockchip/for-next]
> [also build test ERROR on v5.4-rc5 next-20191028]
> [if your patch is applied to the wrong git tree, please drop us a note to help
> improve the system. BTW, we also suggest to use '--base' option to specify the
> base tree in git format-patch, please see 
> https://stackoverflow.com/a/37406982]
>
> url:
> https://github.com/0day-ci/linux/commits/Cheng-Yi-Chiang/Add-HDMI-jack-support-on-RK3288/20191028-212502
> base:   
> https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git 
> for-next
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=i386
>
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot 
>
> All errors (new ones prefixed by >>):
>
>sound/soc/rockchip/snd-soc-rockchip-max98090: struct of_device_id is 196 
> bytes.  The last of 3 is:
>0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x72 0x6f 0x63 0x6b 0x63 0x68 0x69 0x70 0x2c 0x72 0x6f 
> 0x63 0x6b 0x63 0x68 0x69 0x70 0x2d 0x61 0x75 0x64 0x69 0x6f 0x2d 0x6d 0x61 
> 0x78 0x39 0x38 0x30 0x39 0x30 0x2d 0x68 0x64 0x6d 0x69 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
> 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x00 
> 0x00
> >> FATAL: sound/soc/rockchip/snd-soc-rockchip-max98090: struct of_device_id 
> >> is not terminated with a NULL entry!

Please ignore this error for v8 patch series because the change in
rockchip_max98090.c of of_device_id is removed in v9 patch series.
Thanks!

>
> ---
> 0-DAY kernel test infrastructureOpen Source Technology Center
> https://lists.01.org/pipermail/kbuild-all   Intel Corporation
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 RESEND] drm/bridge: dw-hdmi: Restore audio when setting a mode

2019-10-07 Thread Cheng-yi Chiang
On Mon, Oct 7, 2019 at 7:57 PM Neil Armstrong  wrote:
>
> Hi,
>
> On 03/10/2019 06:14, Cheng-Yi Chiang wrote:
> > From: Daniel Kurtz 
> >
> > When setting a new display mode, dw_hdmi_setup() calls
> > dw_hdmi_enable_video_path(), which disables all hdmi clocks, including
> > the audio clock.
> >
> > We should only (re-)enable the audio clock if audio was already enabled
> > when setting the new mode.
> >
> > Without this patch, on RK3288, there will be HDMI audio on some monitors
> > if i2s was played to headphone when the monitor was plugged.
> > ACER H277HU and ASUS PB278 are two of the monitors showing this issue.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > Signed-off-by: Daniel Kurtz 
> > Signed-off-by: Yakir Yang 
> > ---
> >  Change from v1 to v2:
> >   - Use audio_lock to protect audio clock.
> >   - Fix the patch title.
> >
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 13 -
> >  1 file changed, 12 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index aa7efd4da1c8..749d8e4c535b 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -1982,6 +1982,17 @@ static void hdmi_disable_overflow_interrupts(struct 
> > dw_hdmi *hdmi)
> >   HDMI_IH_MUTE_FC_STAT2);
> >  }
> >
> > +static void dw_hdmi_audio_restore(struct dw_hdmi *hdmi)
> > +{
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&hdmi->audio_lock, flags);
> > +
> > + hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
> > +
> > + spin_unlock_irqrestore(&hdmi->audio_lock, flags);
>
> Dumb question, why is this protected by a spinlock ?
>
> Neil
>

Hi Neil,
Thanks for the review.
Good catch. I found that the spinlock audio_lock was introduced in

b90120a96608 drm: bridge/dw_hdmi: introduce interfaces to enable and
disable audio

to protect N/CTS value.
Actually it was not used to protect audio clock.
So we don't need this spinlock.

Hi Daniel Kurtz,
If this rings any bell in your memory as for why this is protected,
please let me know.
I would like to remove this spinlock and simplify this patch in v3.

Thanks!


> > +}
> > +
> >  static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode 
> > *mode)
> >  {
> >   int ret;
> > @@ -2045,7 +2056,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
> > drm_display_mode *mode)
> >
> >   /* HDMI Initialization Step E - Configure audio */
> >   hdmi_clk_regenerator_update_pixel_clock(hdmi);
> > - hdmi_enable_audio_clk(hdmi, true);
> > + dw_hdmi_audio_restore(hdmi);
> >   }
> >
> >   /* not for DVI mode */
> >
>


[PATCH v3] drm/bridge: dw-hdmi: Restore audio when setting a mode

2019-10-08 Thread Cheng-Yi Chiang
From: Daniel Kurtz 

When setting a new display mode, dw_hdmi_setup() calls
dw_hdmi_enable_video_path(), which disables all hdmi clocks, including
the audio clock.

We should only (re-)enable the audio clock if audio was already enabled
when setting the new mode.

Without this patch, on RK3288, there will be HDMI audio on some monitors
if i2s was played to headphone when the monitor was plugged.
ACER H277HU and ASUS PB278 are two of the monitors showing this issue.

Signed-off-by: Cheng-Yi Chiang 
Signed-off-by: Daniel Kurtz 
Signed-off-by: Yakir Yang 
---
 Change from v2 to v3:
 - Remove spinlock around setting clock.

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a15fbf71b9d7..af060162b0af 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2054,7 +2054,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
 
/* HDMI Initialization Step E - Configure audio */
hdmi_clk_regenerator_update_pixel_clock(hdmi);
-   hdmi_enable_audio_clk(hdmi, true);
+   hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
}
 
/* not for DVI mode */
-- 
2.23.0.581.g78d2f28ef7-goog



Re: [PATCH v5 0/5] Add HDMI jack support on RK3288

2019-09-18 Thread Cheng-yi Chiang
On Fri, Sep 13, 2019 at 5:33 PM Neil Armstrong  wrote:
>
> Hi,
>
> On 09/09/2019 15:53, Mark Brown wrote:
> > On Mon, Sep 09, 2019 at 09:37:14AM +0200, Neil Armstrong wrote:
> >
> >> I'd like some review from ASoC people and other drm bridge reviewers,
> >> Jernej, Jonas & Andrzej.
> >
> >> Jonas could have some comments on the overall patchset.
> >
> > The ASoC bits look basically fine, I've gone ahead and applied
> > patch 1 as is since we're just before the merge window and that
> > way we reduce potential cross tree issues.  I know there's a lot
> > of discussion on the DRM side about how they want to handle
> > things with jacks, I'm not 100% sure what the latest thinking is
> > there.
> >
>
> Thanks Mark.
>
>
> Cheng-Yi can you resent this serie without the already applied
> first patch with Jernej, Jonas, and Jerome Brunet  CCed 
> ?

Hi Neil,
Got it. Sorry for the late reply.
I will resend this series without the first patch, based on latest
drm-misc-next, and cc the folks.
Thanks!

>
> Thanks,
> Neil
>


[PATCH v6 1/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-09-18 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 20f4f92dd866..d7e65c869415 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -160,12 +160,23 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_startup  = dw_hdmi_i2s_audio_startup,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld= dw_hdmi_i2s_get_eld,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index aa7efd4da1c8..7ffe8ed675ff 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -193,6 +193,10 @@ struct dw_hdmi {
 
struct mutex cec_notifier_mutex;
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -217,6 +221,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2183,6 +2209,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2190,7 +2217,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   handle_plugged_change(hdmi,
+ result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -2641,6 +2679,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
hdmi->mc_clkdis = 0x7f;
+   hdmi->last_connector_result = connector_status_disconnected;
 

[PATCH v6 0/4] Add HDMI jack support on RK3288

2019-09-18 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

The dependent change on hdmi-codec.c

https://patchwork.kernel.org/patch/11047447

has been picked up by Mark Brown in ASoC tree for-5.4 branch.

Changes from v5 to v6:

1. Remove the patch for sound/soc/codecs/hdmi-codec.c because it is accepted.
2. Rebase the rest of patches based on drm-misc-next tree.

Cheng-Yi Chiang (4):
  drm: bridge: dw-hdmi: Report connector status using callback
  drm: dw-hdmi-i2s: Use fixed id for codec device
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  13 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 ++-
 include/drm/bridge/dw_hdmi.h  |   4 +
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c   |   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 116 ++
 6 files changed, 153 insertions(+), 27 deletions(-)

-- 
2.23.0.237.gc6a4ce50a0-goog



[PATCH v6 2/4] drm: dw-hdmi-i2s: Use fixed id for codec device

2019-09-18 Thread Cheng-Yi Chiang
The problem of using auto ID is that the device name will be like
hdmi-audio-codec..auto.

The number might be changed when there are other platform devices being
created before hdmi-audio-codec device.
Use a fixed name so machine driver can set codec name on the DAI link.

Using the fixed name should be fine because there will only be one
hdmi-audio-codec device.

Fix the codec name in rockchip rk3288_hdmi_analog machine driver.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +-
 sound/soc/rockchip/rk3288_hdmi_analog.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index d7e65c869415..86bd482b9f94 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -193,7 +193,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
 
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = pdev->dev.parent;
-   pdevinfo.id = PLATFORM_DEVID_AUTO;
+   pdevinfo.id = PLATFORM_DEVID_NONE;
pdevinfo.name   = HDMI_CODEC_DRV_NAME;
pdevinfo.data   = &pdata;
pdevinfo.size_data  = sizeof(pdata);
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c 
b/sound/soc/rockchip/rk3288_hdmi_analog.c
index 767700c34ee2..8286025a8747 100644
--- a/sound/soc/rockchip/rk3288_hdmi_analog.c
+++ b/sound/soc/rockchip/rk3288_hdmi_analog.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -142,7 +143,7 @@ static const struct snd_soc_ops rk_ops = {
 SND_SOC_DAILINK_DEFS(audio,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL),
-  COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")),
+  COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
 static struct snd_soc_dai_link rk_dailink = {
-- 
2.23.0.237.gc6a4ce50a0-goog



Re: [PATCH v6 2/4] drm: dw-hdmi-i2s: Use fixed id for codec device

2019-09-18 Thread Cheng-yi Chiang
On Wed, Sep 18, 2019 at 4:43 PM Jerome Brunet  wrote:
>
>
> On Wed 18 Sep 2019 at 10:24, Cheng-Yi Chiang  wrote:
>
> > The problem of using auto ID is that the device name will be like
> > hdmi-audio-codec..auto.
> >
> > The number might be changed when there are other platform devices being
> > created before hdmi-audio-codec device.
> > Use a fixed name so machine driver can set codec name on the DAI link.
> >
> > Using the fixed name should be fine because there will only be one
> > hdmi-audio-codec device.
>
> While this is true all platforms we know of (I suppose), It might not be
> the case later on. I wonder if making such assumption is really
> desirable in a code which is used by quite a few different platforms.
>
> Instead of trying to predict what the device name will be, can't you just
> query it in your machine driver ? Using a device tree phandle maybe ?
>
> It is quite usual to set the dai links this way, "simple-card" is a good
> example of this.
>

Hi Jerome,
Thanks for the quick reply!
And thanks for pointing this out.
I found that
soc_component_to_node searches upward for one layer so it can find the
node which creates hdmi-audio-codec in runtime. This works even that
hdmi-audio-codec does not have its own node in dts.
I will change accordingly in v7.
Thanks!



> >
> > Fix the codec name in rockchip rk3288_hdmi_analog machine driver.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +-
> >  sound/soc/rockchip/rk3288_hdmi_analog.c | 3 ++-
> >  2 files changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > index d7e65c869415..86bd482b9f94 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > @@ -193,7 +193,7 @@ static int snd_dw_hdmi_probe(struct platform_device 
> > *pdev)
> >
> >   memset(&pdevinfo, 0, sizeof(pdevinfo));
> >   pdevinfo.parent = pdev->dev.parent;
> > - pdevinfo.id = PLATFORM_DEVID_AUTO;
> > + pdevinfo.id = PLATFORM_DEVID_NONE;
> >   pdevinfo.name   = HDMI_CODEC_DRV_NAME;
> >   pdevinfo.data   = &pdata;
> >   pdevinfo.size_data  = sizeof(pdata);
> > diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c 
> > b/sound/soc/rockchip/rk3288_hdmi_analog.c
> > index 767700c34ee2..8286025a8747 100644
> > --- a/sound/soc/rockchip/rk3288_hdmi_analog.c
> > +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c
> > @@ -15,6 +15,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -142,7 +143,7 @@ static const struct snd_soc_ops rk_ops = {
> >  SND_SOC_DAILINK_DEFS(audio,
> >   DAILINK_COMP_ARRAY(COMP_EMPTY()),
> >   DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL),
> > -COMP_CODEC("hdmi-audio-codec.2.auto", "i2s-hifi")),
> > +COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
> >   DAILINK_COMP_ARRAY(COMP_EMPTY()));
> >
> >  static struct snd_soc_dai_link rk_dailink = {
>


[PATCH v6 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-09-19 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/rockchip_max98090.c | 96 --
 1 file changed, 73 insertions(+), 23 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..c82948e383da 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
+SND_SOC_DAILINK_DEFS(analog,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
 
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(hdmi,
+   DAILINK_COMP_ARRAY(COMP_EMPTY()),
+   DAILINK_COMP_ARRAY(COMP_CODEC(HDMI_CODEC_DRV_NAME, "i2s-hifi")),
+   DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+   .name = "HDMI",
+   .stream_name = "HDMI",
+   .ops = &rk_aif1_ops,
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(hdmi),
+   }
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -136,8 +165,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
-   .dai_link = &rk_dailink,
-   .num_links = 1,
+   .dai_link = rk_dailinks,
+   .num_links = ARRAY_SIZE(rk_dailinks),
.aux_dev = &rk_98090_headset_dev,
.num_aux_devs = 1,
.dapm_widgets = rk_dapm_widgets,
@@ -173,27 +202,48 @@ 

[PATCH v6 4/4] ASoC: rockchip_max98090: Add HDMI jack support

2019-09-19 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 ++-
 sound/soc/rockchip/rockchip_max98090.c | 20 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c82948e383da..c81c4acda917 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -134,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.23.0.237.gc6a4ce50a0-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v7 2/4] ASoC: rockchip-max98090: Add description for rockchip,hdmi-codec

2019-09-19 Thread Cheng-Yi Chiang
Add support for HDMI codec in rockchip-max98090.
Let user specify HDMI device node in DTS so machine driver can find
hdmi-codec device node for codec DAI.

Signed-off-by: Cheng-Yi Chiang 
---
 Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt 
b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
index a805aa99ad75..97fc838458f7 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
@@ -7,6 +7,7 @@ Required properties:
   connected to the CODEC
 - rockchip,audio-codec: The phandle of the MAX98090 audio codec
 - rockchip,headset-codec: The phandle of Ext chip for jack detection
+- rockchip,hdmi-codec: The phandle of HDMI device for HDMI codec.
 
 Example:
 
@@ -16,4 +17,5 @@ sound {
rockchip,i2s-controller = <&i2s>;
rockchip,audio-codec = <&max98090>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
 };
-- 
2.23.0.237.gc6a4ce50a0-goog



[PATCH v7 4/4] ASoC: rockchip_max98090: Add HDMI jack support

2019-09-19 Thread Cheng-Yi Chiang
In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang 
---
 sound/soc/rockchip/Kconfig |  3 ++-
 sound/soc/rockchip/rockchip_max98090.c | 20 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index b43657e6e655..d610b553ea3b 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -40,9 +40,10 @@ config SND_SOC_ROCKCHIP_MAX98090
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
+   select SND_SOC_HDMI_CODEC
help
  Say Y or M here if you want to add support for SoC audio on Rockchip
- boards using the MAX98090 codec, such as Veyron.
+ boards using the MAX98090 codec and HDMI codec, such as Veyron.
 
 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index 6c217492bb30..11cf252e8391 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -134,6 +134,25 @@ enum {
DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+   struct snd_soc_card *card = runtime->card;
+   struct snd_soc_component *component = runtime->codec_dai->component;
+   int ret;
+
+   /* enable jack detection */
+   ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+   &rk_hdmi_jack, NULL, 0);
+   if (ret) {
+   dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+   return ret;
+   }
+
+   return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
[DAILINK_MAX98090] = {
@@ -151,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
.ops = &rk_aif1_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
+   .init = rk_hdmi_init,
SND_SOC_DAILINK_REG(hdmi),
}
 };
-- 
2.23.0.237.gc6a4ce50a0-goog



[PATCH v7 0/4] Add HDMI jack support on RK3288

2019-09-20 Thread Cheng-Yi Chiang
This patch series supports HDMI jack reporting on RK3288, which uses
DRM dw-hdmi driver and hdmi-codec codec driver.

The previous discussion about reporting jack status using hdmi-notifier
and drm_audio_component is at

https://lore.kernel.org/patchwork/patch/1083027/

The new approach is to use a callback mechanism that is
specific to hdmi-codec.

The dependent change on hdmi-codec.c

https://patchwork.kernel.org/patch/11047447

has been picked up by Mark Brown in ASoC tree for-5.4 branch.

Changes from v6 to v7:

1. rockchip_max98090: Use phandle of HDMI from DTS to find
   codec_dai. With this we don't need to set fixed id for the
   created hdmi-audio-codec device.

Cheng-Yi Chiang (4):
  drm: bridge: dw-hdmi: Report connector status using callback
  ASoC: rockchip-max98090: Add description for rockchip,hdmi-codec
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support

 .../bindings/sound/rockchip-max98090.txt  |   2 +
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   |  11 ++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  41 -
 include/drm/bridge/dw_hdmi.h  |   4 +
 sound/soc/rockchip/Kconfig|   3 +-
 sound/soc/rockchip/rockchip_max98090.c| 149 ++
 7 files changed, 182 insertions(+), 29 deletions(-)

-- 
2.23.0.237.gc6a4ce50a0-goog

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v7 1/4] drm: bridge: dw-hdmi: Report connector status using callback

2019-09-20 Thread Cheng-Yi Chiang
Allow codec driver register callback function for plug event.

The callback registration flow:
dw-hdmi <--- hw-hdmi-i2s-audio <--- hdmi-codec

dw-hdmi-i2s-audio implements hook_plugged_cb op
so codec driver can register the callback.

dw-hdmi exports a function dw_hdmi_set_plugged_cb so platform device
can register the callback.

When connector plug/unplug event happens, report this event using the
callback.

Make sure that audio and drm are using the single source of truth for
connector status.

Signed-off-by: Cheng-Yi Chiang 
---
 .../drm/bridge/synopsys/dw-hdmi-i2s-audio.c   | 11 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++-
 include/drm/bridge/dw_hdmi.h  |  4 ++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 20f4f92dd866..d7e65c869415 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -160,12 +160,23 @@ static int dw_hdmi_i2s_get_dai_id(struct 
snd_soc_component *component,
return -EINVAL;
 }
 
+static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
+  hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
+   return dw_hdmi_set_plugged_cb(hdmi, fn, codec_dev);
+}
+
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_startup  = dw_hdmi_i2s_audio_startup,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld= dw_hdmi_i2s_get_eld,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
+   .hook_plugged_cb = dw_hdmi_i2s_hook_plugged_cb,
 };
 
 static int snd_dw_hdmi_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index aa7efd4da1c8..7ffe8ed675ff 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -193,6 +193,10 @@ struct dw_hdmi {
 
struct mutex cec_notifier_mutex;
struct cec_notifier *cec_notifier;
+
+   hdmi_codec_plugged_cb plugged_cb;
+   struct device *codec_dev;
+   enum drm_connector_status last_connector_result;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -217,6 +221,28 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int 
offset)
return val;
 }
 
+static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+{
+   if (hdmi->plugged_cb && hdmi->codec_dev)
+   hdmi->plugged_cb(hdmi->codec_dev, plugged);
+}
+
+int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
+  struct device *codec_dev)
+{
+   bool plugged;
+
+   mutex_lock(&hdmi->mutex);
+   hdmi->plugged_cb = fn;
+   hdmi->codec_dev = codec_dev;
+   plugged = hdmi->last_connector_result == connector_status_connected;
+   handle_plugged_change(hdmi, plugged);
+   mutex_unlock(&hdmi->mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_plugged_cb);
+
 static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
@@ -2183,6 +2209,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 connector);
+   enum drm_connector_status result;
 
mutex_lock(&hdmi->mutex);
hdmi->force = DRM_FORCE_UNSPECIFIED;
@@ -2190,7 +2217,18 @@ dw_hdmi_connector_detect(struct drm_connector 
*connector, bool force)
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
 
-   return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+   result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
+
+   mutex_lock(&hdmi->mutex);
+   if (result != hdmi->last_connector_result) {
+   dev_dbg(hdmi->dev, "read_hpd result: %d", result);
+   handle_plugged_change(hdmi,
+ result == connector_status_connected);
+   hdmi->last_connector_result = result;
+   }
+   mutex_unlock(&hdmi->mutex);
+
+   return result;
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -2641,6 +2679,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
hdmi->mc_clkdis = 0x7f;
+   hdmi->last_connector_result = connector_status_disconnected;
 

[PATCH v7 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-09-20 Thread Cheng-Yi Chiang
Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang 
---
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
 sound/soc/rockchip/rockchip_max98090.c| 129 ++
 2 files changed, 103 insertions(+), 27 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi 
b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
index 445270aa136e..51208d161d65 100644
--- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
@@ -17,6 +17,7 @@
rockchip,hp-det-gpios = <&gpio6 RK_PA5 GPIO_ACTIVE_HIGH>;
rockchip,mic-det-gpios = <&gpio6 RK_PB3 GPIO_ACTIVE_LOW>;
rockchip,headset-codec = <&headsetcodec>;
+   rockchip,hdmi-codec = <&hdmi>;
};
 };
 
diff --git a/sound/soc/rockchip/rockchip_max98090.c 
b/sound/soc/rockchip/rockchip_max98090.c
index c5fc24675a33..6c217492bb30 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+   SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
{"Headphone", NULL, "HPR"},
{"Speaker", NULL, "SPKL"},
{"Speaker", NULL, "SPKR"},
+   {"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+   SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream 
*substream,
 
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
return ret;
}
 
+   /* HDMI codec dai does not need to set sysclk. */
+   if (!strcmp(rtd->dai_link->name, "HDMI"))
+   return 0;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 SND_SOC_CLOCK_IN);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+   if (ret) {
+   dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
return ret;
}
 
-   return ret;
+   return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params,
 };
 
-SND_SOC_DAILINK_DEFS(hifi,
-   DAILINK_COMP_ARRAY(COMP_EMPTY()),
-   DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
-   DAILINK_COMP_ARRAY(COMP_EMPTY()));
-
-static struct snd_soc_dai_link rk_dailink = {
-   .name = "max98090",
-   .stream_name = "Audio",
-   .ops = &rk_aif1_ops,
-   /* set max98090 as slave */
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-   SND_SOC_DAIFMT_CBS_CFS,
-   SND_SOC_DAILINK_REG(hifi),
+SND_SOC_DAILINK_DEFS(analog,
+DAILINK_COMP_ARRAY(COMP_EMPTY()),
+DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
+DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(hdmi,
+DAILINK_COMP_ARRAY(COMP_EMPTY()),
+DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
+DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+enum {
+   DAILINK_MAX98090,
+   DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+   [DAILINK_MAX98090] = {
+   .name = "max98090",
+   .stream_name = "Analog",
+   .ops = &rk_aif1_ops,
+   /* set max98090 as slave */
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+   SND_SOC_DAIFMT_CBS_CFS,
+   SND_SOC_DAILINK_REG(analog),
+   },
+   [DAILINK_HDMI] = {
+ 

Re: [PATCH v7 3/4] ASoC: rockchip_max98090: Add dai_link for HDMI

2019-09-20 Thread Cheng-yi Chiang
On Thu, Sep 19, 2019 at 11:08 PM Jernej Škrabec  wrote:
>
> Hi!
>
> Dne četrtek, 19. september 2019 ob 15:54:49 CEST je Cheng-Yi Chiang
> napisal(a):
> > Use two dai_links. One for HDMI and one for max98090.
> > With this setup, audio can play to speaker and HDMI selectively.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
> >  sound/soc/rockchip/rockchip_max98090.c| 129 ++
> >  2 files changed, 103 insertions(+), 27 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
> > b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi index
> > 445270aa136e..51208d161d65 100644
> > --- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
> > +++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
> > @@ -17,6 +17,7 @@
> >   rockchip,hp-det-gpios = <&gpio6 RK_PA5
> GPIO_ACTIVE_HIGH>;
> >   rockchip,mic-det-gpios = <&gpio6 RK_PB3
> GPIO_ACTIVE_LOW>;
> >   rockchip,headset-codec = <&headsetcodec>;
> > + rockchip,hdmi-codec = <&hdmi>;
> >   };
> >  };
> >
> > diff --git a/sound/soc/rockchip/rockchip_max98090.c
> > b/sound/soc/rockchip/rockchip_max98090.c index c5fc24675a33..6c217492bb30
> > 100644
> > --- a/sound/soc/rockchip/rockchip_max98090.c
> > +++ b/sound/soc/rockchip/rockchip_max98090.c
> > @@ -11,6 +11,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -41,6 +42,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[]
> > = { SND_SOC_DAPM_MIC("Headset Mic", NULL),
> >   SND_SOC_DAPM_MIC("Int Mic", NULL),
> >   SND_SOC_DAPM_SPK("Speaker", NULL),
> > + SND_SOC_DAPM_LINE("HDMI", NULL),
> >  };
> >
> >  static const struct snd_soc_dapm_route rk_audio_map[] = {
> > @@ -52,6 +54,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
> >   {"Headphone", NULL, "HPR"},
> >   {"Speaker", NULL, "SPKL"},
> >   {"Speaker", NULL, "SPKR"},
> > + {"HDMI", NULL, "TX"},
> >  };
> >
> >  static const struct snd_kcontrol_new rk_mc_controls[] = {
> > @@ -59,6 +62,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
> >   SOC_DAPM_PIN_SWITCH("Headset Mic"),
> >   SOC_DAPM_PIN_SWITCH("Int Mic"),
> >   SOC_DAPM_PIN_SWITCH("Speaker"),
> > + SOC_DAPM_PIN_SWITCH("HDMI"),
> >  };
> >
> >  static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
> > @@ -92,38 +96,63 @@ static int rk_aif1_hw_params(struct snd_pcm_substream
> > *substream,
> >
> >   ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
> >SND_SOC_CLOCK_OUT);
> > - if (ret < 0) {
> > - dev_err(codec_dai->dev, "Can't set codec clock %d\n",
> ret);
> > + if (ret) {
> > + dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n",
> ret);
> >   return ret;
> >   }
> >
> > + /* HDMI codec dai does not need to set sysclk. */
> > + if (!strcmp(rtd->dai_link->name, "HDMI"))
> > + return 0;
> > +
> >   ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
> >SND_SOC_CLOCK_IN);
> > - if (ret < 0) {
> > - dev_err(codec_dai->dev, "Can't set codec clock %d\n",
> ret);
> > + if (ret) {
> > + dev_err(codec_dai->dev, "Can't set codec dai clock
> %d\n", ret);
> >   return ret;
> >   }
> >
> > - return ret;
> > + return 0;
> >  }
> >
> >  static const struct snd_soc_ops rk_aif1_ops = {
> >   .hw_params = rk_aif1_hw_params,
> >  };
> >
> > -SND_SOC_DAILINK_DEFS(hifi,
> > - DAILINK_COMP_ARRAY(COMP_EMPTY()),
> > - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
> > - DAILINK_COMP_ARRAY(COMP_EMPTY()));
> > -
> > -static struct snd_soc_dai_link rk_dailink = {
> > - .name = "max98090",
> > - .stream_name = "Audio",
> > - .ops = &rk_aif1_ops,
> > - /* set max98090 as slave */
> > - .dai_fmt = SND_SOC_DAIFMT_I

[PATCH] drm/bridge: dw-hdmi: Restore audio when setting a mode

2019-09-30 Thread Cheng-Yi Chiang
From: Daniel Kurtz 

When setting a new display mode, dw_hdmi_setup() calls
dw_hdmi_enable_video_path(), which disables all hdmi clocks, including
the audio clock.

We should only (re-)enable the audio clock if audio was already enabled
when setting the new mode.

Without this patch, on RK3288, there will be HDMI audio on some monitors
if i2s was played to headphone when the monitor was plugged.
ACER H277HU and ASUS PB278 are two of the monitors showing this issue.

Signed-off-by: Cheng-Yi Chiang 
Signed-off-by: Daniel Kurtz 
Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index aa7efd4da1c8..c60e951122c9 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1982,6 +1982,15 @@ static void hdmi_disable_overflow_interrupts(struct 
dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
 }
 
+static void dw_hdmi_audio_restore(struct dw_hdmi *hdmi)
+{
+   mutex_lock(&hdmi->audio_mutex);
+
+   hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
+
+   mutex_unlock(&hdmi->audio_mutex);
+}
+
 static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 {
int ret;
@@ -2045,7 +2054,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
 
/* HDMI Initialization Step E - Configure audio */
hdmi_clk_regenerator_update_pixel_clock(hdmi);
-   hdmi_enable_audio_clk(hdmi, true);
+   dw_hdmi_audio_restore(hdmi);
}
 
/* not for DVI mode */
-- 
2.23.0.444.g18eeb5a265-goog



[PATCH v2] FROMLIST: drm/bridge: dw-hdmi: Restore audio when setting a mode

2019-10-02 Thread Cheng-Yi Chiang
From: Daniel Kurtz 

When setting a new display mode, dw_hdmi_setup() calls
dw_hdmi_enable_video_path(), which disables all hdmi clocks, including
the audio clock.

We should only (re-)enable the audio clock if audio was already enabled
when setting the new mode.

Without this patch, on RK3288, there will be HDMI audio on some monitors
if i2s was played to headphone when the monitor was plugged.
ACER H277HU and ASUS PB278 are two of the monitors showing this issue.

Signed-off-by: Cheng-Yi Chiang 
Signed-off-by: Daniel Kurtz 
Signed-off-by: Yakir Yang 
---
 Change from v1 to v2:
 - Use audio_lock to protect audio clock.

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index aa7efd4da1c8..749d8e4c535b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1982,6 +1982,17 @@ static void hdmi_disable_overflow_interrupts(struct 
dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
 }
 
+static void dw_hdmi_audio_restore(struct dw_hdmi *hdmi)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&hdmi->audio_lock, flags);
+
+   hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
+
+   spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+
 static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 {
int ret;
@@ -2045,7 +2056,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
 
/* HDMI Initialization Step E - Configure audio */
hdmi_clk_regenerator_update_pixel_clock(hdmi);
-   hdmi_enable_audio_clk(hdmi, true);
+   dw_hdmi_audio_restore(hdmi);
}
 
/* not for DVI mode */
-- 
2.23.0.444.g18eeb5a265-goog



[PATCH v2 RESEND] drm/bridge: dw-hdmi: Restore audio when setting a mode

2019-10-02 Thread Cheng-Yi Chiang
From: Daniel Kurtz 

When setting a new display mode, dw_hdmi_setup() calls
dw_hdmi_enable_video_path(), which disables all hdmi clocks, including
the audio clock.

We should only (re-)enable the audio clock if audio was already enabled
when setting the new mode.

Without this patch, on RK3288, there will be HDMI audio on some monitors
if i2s was played to headphone when the monitor was plugged.
ACER H277HU and ASUS PB278 are two of the monitors showing this issue.

Signed-off-by: Cheng-Yi Chiang 
Signed-off-by: Daniel Kurtz 
Signed-off-by: Yakir Yang 
---
 Change from v1 to v2:
  - Use audio_lock to protect audio clock.
  - Fix the patch title.

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index aa7efd4da1c8..749d8e4c535b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1982,6 +1982,17 @@ static void hdmi_disable_overflow_interrupts(struct 
dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
 }
 
+static void dw_hdmi_audio_restore(struct dw_hdmi *hdmi)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&hdmi->audio_lock, flags);
+
+   hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
+
+   spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+
 static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 {
int ret;
@@ -2045,7 +2056,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
 
/* HDMI Initialization Step E - Configure audio */
hdmi_clk_regenerator_update_pixel_clock(hdmi);
-   hdmi_enable_audio_clk(hdmi, true);
+   dw_hdmi_audio_restore(hdmi);
}
 
/* not for DVI mode */
-- 
2.23.0.444.g18eeb5a265-goog



[PATCH] drm: dw-hdmi-i2s: enable audio clock in audio_startup

2019-08-28 Thread Cheng-Yi Chiang
In the designware databook, the sequence of enabling audio clock and
setting format is not clearly specified.
Currently, audio clock is enabled in the end of hw_param ops after
setting format.

On some monitors, there is a possibility that audio does not come out.
Fix this by enabling audio clock in audio_startup ops
before hw_param ops setting format.

Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 5cbb71a866d5..08b4adbb1ddc 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -69,6 +69,14 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void 
*data,
hdmi_write(audio, conf0, HDMI_AUD_CONF0);
hdmi_write(audio, conf1, HDMI_AUD_CONF1);
 
+   return 0;
+}
+
+static int dw_hdmi_i2s_audio_startup(struct device *dev, void *data)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
dw_hdmi_audio_enable(hdmi);
 
return 0;
@@ -105,6 +113,7 @@ static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component 
*component,
 }
 
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
+   .audio_startup = dw_hdmi_i2s_audio_startup,
.hw_params  = dw_hdmi_i2s_hw_params,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
-- 
2.23.0.187.g17f5b7556c-goog



Re: [PATCH v5 0/5] Add HDMI jack support on RK3288

2019-08-29 Thread Cheng-yi Chiang
On Wed, Jul 17, 2019 at 6:28 PM Tzung-Bi Shih  wrote:
>
> On Wed, Jul 17, 2019 at 4:33 PM Cheng-Yi Chiang  wrote:
> >
> > This patch series supports HDMI jack reporting on RK3288, which uses
> > DRM dw-hdmi driver and hdmi-codec codec driver.
> >
> > The previous discussion about reporting jack status using hdmi-notifier
> > and drm_audio_component is at
> >
> > https://lore.kernel.org/patchwork/patch/1083027/
> >
> > The new approach is to use a callback mechanism that is
> > specific to hdmi-codec.
> >
> > Changes from v4 to v5:
> > - synopsys/Kconfig: Remove the incorrect dependency change in v4.
> > - rockchip/Kconfig: Add dependency of hdmi-codec when it is really need
> >   for jack support.
> >
> > Cheng-Yi Chiang (5):
> >   ASoC: hdmi-codec: Add an op to set callback function for plug event
> >   drm: bridge: dw-hdmi: Report connector status using callback
> >   drm: dw-hdmi-i2s: Use fixed id for codec device
> >   ASoC: rockchip_max98090: Add dai_link for HDMI
> >   ASoC: rockchip_max98090: Add HDMI jack support
> >
> LGTM.
>
> Reviewed-by: Tzung-Bi Shih 

Hi Daniel,
Do you have further concern on this patch series related to hdmi-codec
and drm part ?
We would like to merge this patch series if possible.
They will be needed in many future chrome projects for HDMI audio jack
detection.
Thanks a lot!


Re: [PATCH] drm: dw-hdmi-i2s: enable audio clock in audio_startup

2019-09-01 Thread Cheng-yi Chiang
On Sun, Sep 1, 2019 at 6:04 PM Jonas Karlman  wrote:
>
> On 2019-08-29 06:29, Cheng-Yi Chiang wrote:
> > In the designware databook, the sequence of enabling audio clock and
> > setting format is not clearly specified.
> > Currently, audio clock is enabled in the end of hw_param ops after
> > setting format.
> >
> > On some monitors, there is a possibility that audio does not come out.
> > Fix this by enabling audio clock in audio_startup ops
> > before hw_param ops setting format.
> >
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 9 +
> >  1 file changed, 9 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > index 5cbb71a866d5..08b4adbb1ddc 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
> > @@ -69,6 +69,14 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, 
> > void *data,
> >   hdmi_write(audio, conf0, HDMI_AUD_CONF0);
> >   hdmi_write(audio, conf1, HDMI_AUD_CONF1);
> >
> > + return 0;
> > +}
> > +
> > +static int dw_hdmi_i2s_audio_startup(struct device *dev, void *data)
> > +{
> > + struct dw_hdmi_i2s_audio_data *audio = data;
> > + struct dw_hdmi *hdmi = audio->hdmi;
> > +
> >   dw_hdmi_audio_enable(hdmi);
> >
> >   return 0;
> > @@ -105,6 +113,7 @@ static int dw_hdmi_i2s_get_dai_id(struct 
> > snd_soc_component *component,
> >  }
> >
> >  static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
> > + .audio_startup = dw_hdmi_i2s_audio_startup,
>
> A small white space nit, there should be a tab and not space to align the 
> equal sign above.

ACK. Will fix in v2.
>
> Also this patch do not cleanly apply to drm-misc-next or linux-next after
> fc1ca6e01d0a "drm/bridge: dw-hdmi-i2s: add .get_eld support" was merged.

ACK. Will rebase in v2.
>
>
>
>
> This patch does fix an issue I have observed on my Rockchip devices where 
> audio would not always
> came out after switching between audio streams having different rate and 
> channels parameters.
> I used to carry [1] to fix that issue, but this seems like a more sane fix.
>
> [1] 
> https://github.com/Kwiboo/linux-rockchip/commit/4862e4044532b8b480fa3a0faddc197586623808
>
> With above fixed,
>
> Reviewed-by: Jonas Karlman 


Thanks a lot!

>
>
> Regards,
> Jonas
>
> >   .hw_params  = dw_hdmi_i2s_hw_params,
> >   .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
> >   .get_dai_id = dw_hdmi_i2s_get_dai_id,
>


[PATCH v2] drm: dw-hdmi-i2s: enable audio clock in audio_startup

2019-09-01 Thread Cheng-Yi Chiang
In the designware databook, the sequence of enabling audio clock and
setting format is not clearly specified.
Currently, audio clock is enabled in the end of hw_param ops after
setting format.

On some monitors, there is a possibility that audio does not come out.
Fix this by enabling audio clock in audio_startup ops
before hw_param ops setting format.

Signed-off-by: Cheng-Yi Chiang 
Reviewed-by: Douglas Anderson 
Reviewed-by: Jonas Karlman 
Tested-by: Douglas Anderson 
---
 Changes from v1:
 1. Move audio_startup to the front of audio_shutdown.
 2. Fix the indentation of audio_startup equal sign using tab.
 3. Rebase the patch on linux-next/master.
 4. Add Reviewed-by and Tested-by fields from diand...@chromium.org.
 5. Add Reviewed-by field from jo...@kwiboo.se.

 drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 1d15cf9b6821..34d8e837555f 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -109,6 +109,14 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void 
*data,
hdmi_write(audio, conf0, HDMI_AUD_CONF0);
hdmi_write(audio, conf1, HDMI_AUD_CONF1);
 
+   return 0;
+}
+
+static int dw_hdmi_i2s_audio_startup(struct device *dev, void *data)
+{
+   struct dw_hdmi_i2s_audio_data *audio = data;
+   struct dw_hdmi *hdmi = audio->hdmi;
+
dw_hdmi_audio_enable(hdmi);
 
return 0;
@@ -153,6 +161,7 @@ static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component 
*component,
 
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
.hw_params  = dw_hdmi_i2s_hw_params,
+   .audio_startup  = dw_hdmi_i2s_audio_startup,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld= dw_hdmi_i2s_get_eld,
.get_dai_id = dw_hdmi_i2s_get_dai_id,
-- 
2.23.0.187.g17f5b7556c-goog



[PATCH] drm: bridge/dw_hdmi: add audio sample channel status setting

2019-09-02 Thread Cheng-Yi Chiang
From: Yakir Yang 

When transmitting IEC60985 linear PCM audio, we configure the
Audio Sample Channel Status information of all the channel
status bits in the IEC60958 frame.
Refer to 60958-3 page 10 for frequency, original frequency, and
wordlength setting.

This fix the issue that audio does not come out on some monitors
(e.g. LG 22CV241)

Signed-off-by: Yakir Yang 
Signed-off-by: Cheng-Yi Chiang 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 
 2 files changed, 79 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bd65d0479683..34d46e25d610 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, 
unsigned long pixel_clk)
return n;
 }
 
+static void hdmi_set_schnl(struct dw_hdmi *hdmi)
+{
+   u8 aud_schnl_samplerate;
+   u8 aud_schnl_8;
+
+   /* These registers are on RK3288 using version 2.0a. */
+   if (hdmi->version != 0x200a)
+   return;
+
+   switch (hdmi->sample_rate) {
+   case 32000:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
+   break;
+   case 44100:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
+   break;
+   case 48000:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
+   break;
+   case 88200:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
+   break;
+   case 96000:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
+   break;
+   case 176400:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
+   break;
+   case 192000:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
+   break;
+   case 768000:
+   aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
+   break;
+   default:
+   dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
+hdmi->sample_rate);
+   return;
+   }
+
+   /* set channel status register */
+   hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
+ HDMI_FC_AUDSCHNLS7);
+
+   /*
+* Set original frequency to be the same as frequency.
+* Use one-complement value as stated in IEC60958-3 page 13.
+*/
+   aud_schnl_8 = (~aud_schnl_samplerate) <<
+   HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
+
+   /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
+   aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
+
+   hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
+}
+
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
unsigned long pixel_clk, unsigned int sample_rate)
 {
@@ -620,6 +677,8 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
hdmi->audio_cts = cts;
hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
spin_unlock_irq(&hdmi->audio_lock);
+
+   hdmi_set_schnl(hdmi);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index 6988f12d89d9..619ebc1c8354 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -158,6 +158,17 @@
 #define HDMI_FC_SPDDEVICEINF0x1062
 #define HDMI_FC_AUDSCONF0x1063
 #define HDMI_FC_AUDSSTAT0x1064
+#define HDMI_FC_AUDSV   0x1065
+#define HDMI_FC_AUDSU   0x1066
+#define HDMI_FC_AUDSCHNLS0  0x1067
+#define HDMI_FC_AUDSCHNLS1  0x1068
+#define HDMI_FC_AUDSCHNLS2  0x1069
+#define HDMI_FC_AUDSCHNLS3  0x106a
+#define HDMI_FC_AUDSCHNLS4  0x106b
+#define HDMI_FC_AUDSCHNLS5  0x106c
+#define HDMI_FC_AUDSCHNLS6  0x106d
+#define HDMI_FC_AUDSCHNLS7  0x106e
+#define HDMI_FC_AUDSCHNLS8  0x106f
 #define HDMI_FC_DATACH0FILL 0x1070
 #define HDMI_FC_DATACH1FILL 0x1071
 #define HDMI_FC_DATACH2FILL 0x1072
@@ -706,6 +717,15 @@ enum {
 /* HDMI_FC_AUDSCHNLS7 field values */
HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+   HDMI_FC_AUDSCHNLS7_SMPRATE_MASK = 0x0f,
+   HDMI_FC_AUDSCHNLS7_SMPRATE_192K = 0xe,
+   HDMI_FC_AUDSCHNLS7_SMPRATE_176K4 = 0xc,
+   HDMI_FC_AUDSCHNLS7_SMPRATE_96K = 0xa

Re: [PATCH] drm: bridge/dw_hdmi: add audio sample channel status setting

2019-09-04 Thread Cheng-yi Chiang
Hi,

On Tue, Sep 3, 2019 at 5:53 PM Neil Armstrong  wrote:
>
> Hi,
>
> On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> > From: Yakir Yang 
> >
> > When transmitting IEC60985 linear PCM audio, we configure the
> > Audio Sample Channel Status information of all the channel
> > status bits in the IEC60958 frame.
> > Refer to 60958-3 page 10 for frequency, original frequency, and
> > wordlength setting.
> >
> > This fix the issue that audio does not come out on some monitors
> > (e.g. LG 22CV241)
> >
> > Signed-off-by: Yakir Yang 
> > Signed-off-by: Cheng-Yi Chiang 
> > ---
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++
> >  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 
> >  2 files changed, 79 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > index bd65d0479683..34d46e25d610 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> > @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, 
> > unsigned long pixel_clk)
> >   return n;
> >  }
> >
> > +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> > +{
> > + u8 aud_schnl_samplerate;
> > + u8 aud_schnl_8;
> > +
> > + /* These registers are on RK3288 using version 2.0a. */
> > + if (hdmi->version != 0x200a)
> > + return;
>
> Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> SoCs ?
>

In the original patch by Yakir,

https://lore.kernel.org/patchwork/patch/539653/   (sorry, I should
have added this link in the "after the cut" note)

The fix is limited to version 2.0.
Since I am only testing on RK3288 with 2.0a, I change the check to 2.0a only.
I can not test 2.0a version on other SoCs.
The databook I have at hand is 2.0a (not specific to RK3288) so I
think all 2.0a should have this register.

As for other version like version 1.3 on iMX6, there is no such
register, as stated by Russell

http://lkml.iu.edu/hypermail/linux/kernel/1501.3/06268.html.

So at least we should check the version.
Maybe we can set the criteria as version 2.0 or above to make it a safe patch ?
If there is the same need on other SoC with version < 2.0, it can be
added later.
Presumably, there will be databook of that version to help confirming
this setting.

Thanks!
> > +
> > + switch (hdmi->sample_rate) {
> > + case 32000:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> > + break;
> > + case 44100:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> > + break;
> > + case 48000:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> > + break;
> > + case 88200:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> > + break;
> > + case 96000:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> > + break;
> > + case 176400:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> > + break;
> > + case 192000:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> > + break;
> > + case 768000:
> > + aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> > + break;
> > + default:
> > + dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> > +  hdmi->sample_rate);
> > + return;
> > + }
> > +
> > + /* set channel status register */
> > + hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> > +   HDMI_FC_AUDSCHNLS7);
> > +
> > + /*
> > +  * Set original frequency to be the same as frequency.
> > +  * Use one-complement value as stated in IEC60958-3 page 13.
> > +  */
> > + aud_schnl_8 = (~aud_schnl_samplerate) <<
> > + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET;
> > +
> > + /* This means word length is 16 bit. Refer to IEC60958-3 page 12. */
> > + aud_schnl_8 |= 2 << HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET;
> > +
> > + hdmi_writeb(hdmi, aud_schnl_8, HDMI_FC_AUDSCHNLS8);
> > +}
> > +
> >  static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> >   unsigned long pixel_clk, unsigned int sample_rate)
> >  {
&g

Re: [PATCH] drm: bridge/dw_hdmi: add audio sample channel status setting

2019-09-04 Thread Cheng-yi Chiang
On Wed, Sep 4, 2019 at 2:00 AM Neil Armstrong  wrote:
>
> Hi,
>
> Le 03/09/2019 à 11:53, Neil Armstrong a écrit :
> > Hi,
> >
> > On 03/09/2019 07:51, Cheng-Yi Chiang wrote:
> >> From: Yakir Yang 
> >>
> >> When transmitting IEC60985 linear PCM audio, we configure the
> >> Audio Sample Channel Status information of all the channel
> >> status bits in the IEC60958 frame.
> >> Refer to 60958-3 page 10 for frequency, original frequency, and
> >> wordlength setting.
> >>
> >> This fix the issue that audio does not come out on some monitors
> >> (e.g. LG 22CV241)
> >>
> >> Signed-off-by: Yakir Yang 
> >> Signed-off-by: Cheng-Yi Chiang 
> >> ---
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 59 +++
> >>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 20 
> >>  2 files changed, 79 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
> >> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> index bd65d0479683..34d46e25d610 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> @@ -582,6 +582,63 @@ static unsigned int hdmi_compute_n(unsigned int freq, 
> >> unsigned long pixel_clk)
> >>  return n;
> >>  }
> >>
> >> +static void hdmi_set_schnl(struct dw_hdmi *hdmi)
> >> +{
> >> +u8 aud_schnl_samplerate;
> >> +u8 aud_schnl_8;
> >> +
> >> +/* These registers are on RK3288 using version 2.0a. */
> >> +if (hdmi->version != 0x200a)
> >> +return;
> >
> > Are these limited to the 2.0a version *in* RK3288, or 2.0a version on all
> > SoCs ?
>
> After investigations, Amlogic sets these registers on their 2.0a version
> aswell, and Jernej (added in Cc) reported me Allwinner sets them on their
> < 2.0a and > 2.0a IPs versions.
>
> Can you check on the Rockchip IP versions in RK3399 ?
>
Sorry, the RK3399 board I am using is using DP, not HDMI.
But I found that on rockchip's tree at

https://github.com/rockchip-linux/kernel/commit/924f480383c982da9908fb96d6bbb580b25545a5#diff-f74b4cfb23436a137a9338a5af3fbb3dR172

There is such register setting, so I think RK3399 should have the same register.


> For reference, the HDMI 1.4a IP version allwinner setups is:
> https://github.com/Allwinner-Homlet/H3-BSP4.4-linux/blob/master/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_bsp_sun8iw7.c#L531-L539
> (registers a "scrambled" but a custom bit can reset to the original mapping,
> 0x1066 ... 0x106f)

I see.. so 1.4 has this register.
I can modify the check to be >= 1.4 then.
Will fix in v2.

Thanks!

>
> Neil
>
> >
> >> +
> >> +switch (hdmi->sample_rate) {
> >> +case 32000:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_32K;
> >> +break;
> >> +case 44100:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
> >> +break;
> >> +case 48000:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_48K;
> >> +break;
> >> +case 88200:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_88K2;
> >> +break;
> >> +case 96000:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_96K;
> >> +break;
> >> +case 176400:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_176K4;
> >> +break;
> >> +case 192000:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_192K;
> >> +break;
> >> +case 768000:
> >> +aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_768K;
> >> +break;
> >> +default:
> >> +dev_warn(hdmi->dev, "Unsupported audio sample rate (%u)\n",
> >> + hdmi->sample_rate);
> >> +return;
> >> +}
> >> +
> >> +/* set channel status register */
> >> +hdmi_modb(hdmi, aud_schnl_samplerate, HDMI_FC_AUDSCHNLS7_SMPRATE_MASK,
> >> +  HDMI_FC_AUDSCHNLS7);
> >> +
> >> +/*
> >> + * Set original frequency to be the same as frequency.
> >> + * Use one-complement value as stated in IEC60958-3 page 13.
> >> + */
> >> +aud_schnl_8 = (~aud_schnl_samplerate) <<
&

  1   2   >