LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v3 0/15] Those patches is used for dw_hdmi audio support
@ 2015-02-03 14:56 Yakir Yang
  2015-02-03 15:01 ` [PATCH v3 01/15] drm: bridge/dw_hdmi: add irq control to suspend/resume Yakir Yang
                   ` (14 more replies)
  0 siblings, 15 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 14:56 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	Yakir Yang, dri-devel, linux-kernel, Arnd Bergmann, Sean Cross,
	Jyri Sarha, Ben Zhang, alsa-devel, Heiko Stuebner,
	linux-arm-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree, djkurtz, dbehr, mmind00,
	dianders, marcheu, linux-rockchip


We found Designware hdmi driver only support audio clock config, we can not play sound through it.
To add Designware HDMI Audio support, we make those patch set:
1): fixed dw_hdmi irq bug, add irq control to suspend/resume interfaces.
2): add suspend/resume callback for dw_hdmi rockchip driver.
3): Warp irq control in functions.
4): Combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
5): Adjust n/cts config order.
6): Set ncts_atomic_write & cts_manual, according to dw_hdmi document.
7): Add audio support for more display resolutions(eg. 800x600).
8): Add audio support for No-CEA display resolutions.
9): Add Audio Sample Channel Status config interfaces to dw_hdmi driver.
10): add audio clock control interfaces o dw_hdmi driver.
11): creat "dw_hdmi-audio" platform device in dw_hdmi driver.
12): add codec driver for hdmi audio, callback dw_hdmi audio config functions.
13): add sound driver for hdmi audio, creat hdmi audio sound card.
14): add dt-bings file and add hdmi_audio node to corresponding dt file.


Changes in v3:
- Clear Hotplug interrupts before dw_hdmi_fb_register
- Wrap irq control in fucntions
- Setting the .pm member instead of suspend/resume
- Add ID registers parse and record
- Combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
- Only adjust the n/cts setting order
- Set ncts_atomic_write & cts_manual
- Determine whether sample channel should set by desig_id.
- Delete hdmi_audio_config interface and modify audio clock control functions
- Remove audio_config & get_connect_status callback functions
  and add write/read/mod register callback functions
- Keep audio format config function in dw-hdmi-audio driver
  and remove audio_config & get_connect_status functions,
  move jack control to dw-hdmi-audio completely.
- Delete the operation of jack in rockchip-hdmi-audio driver,
  get ready to switch to simple-audio-card driver.
- modify cpu-of-node to i2s-controller

Changes in v2:
- Add irq control to suspend/resume interfaces
- Add suspend/resume support for dw_hdmi_rockchip driver
- add more n/cts combinations for more display resolutions
- enable audio support for No-CEA display mode
- Add audio sample channel status setting
- Add audio config interfaces to dw_hdmi driver
- Update the audio control interfaces
- Update dw_hdmi audio control interfaces, and adjust jack report process
- give "codec-name" & "codec-dai-name" an const name
- remove codec-name and codec-dai-name
- rename rockchip,rockchip-hdmi-audio.txt to rockchip,rockchip-dw-hdmi-audio.txt

Yakir Yang (15):
  drm: bridge/dw_hdmi: add irq control to suspend/resume
  drm: bridge/dw_hdmi: wrap irq control in fucntions
  drm: rockchip/dw_hdmi_rockchip: add resume/suspend support
  drm: bridge/dw_hdmi: add indentification registers parse and record
  drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and
    hdmi_regenerate_cts()
  drm: bridge/dw_hdmi: adjust n/cts setting order
  drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual
  drm: bridge/dw_hdmi: add audio support for more display resolutions
  drm: bridge/dw_hdmi: enable audio support for No-CEA display
    resolutions
  drm: bridge/dw_hdmi: add audio sample channel status setting
  drm: bridge/dw_hdmi: add audio clock control interfaces
  drm: bridge/dw_hdmi: creat dw-hdmi-audio platform device
  ASoC: dw-hdmi-audio: add codec driver for dw hdmi audio
  ASoC: rockchip-hdmi-audio: add sound driver for hdmi audio
  dt-bindings: Add documentation for Rockchip dw-hdmi-audio

 .../sound/rockchip,rockchip-dw-hdmi-audio.txt      |  12 +
 drivers/gpu/drm/bridge/dw_hdmi.c                   | 361 ++++++++++++++++++---
 drivers/gpu/drm/bridge/dw_hdmi.h                   |  49 +++
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        |  16 +
 include/drm/bridge/dw_hdmi.h                       |  17 +
 sound/soc/codecs/Kconfig                           |   4 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/dw-hdmi-audio.c                   | 333 +++++++++++++++++++
 sound/soc/codecs/dw-hdmi-audio.h                   |  79 +++++
 sound/soc/rockchip/Kconfig                         |   9 +
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip_hdmi_audio.c           | 168 ++++++++++
 12 files changed, 1013 insertions(+), 39 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
 create mode 100644 sound/soc/codecs/dw-hdmi-audio.c
 create mode 100644 sound/soc/codecs/dw-hdmi-audio.h
 create mode 100644 sound/soc/rockchip/rockchip_hdmi_audio.c

-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 01/15] drm: bridge/dw_hdmi: add irq control to suspend/resume
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
@ 2015-02-03 15:01 ` Yakir Yang
  2015-02-03 15:02 ` [PATCH v3 02/15] drm: bridge/dw_hdmi: wrap irq control in fucntions Yakir Yang
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:01 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	Yakir Yang, dri-devel, linux-kernel, Arnd Bergmann, Sean Cross,
	Jyri Sarha, Ben Zhang, alsa-devel, Heiko Stuebner,
	linux-arm-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree, djkurtz, dbehr, mmind00,
	dianders, marcheu, linux-rockchip

when kernel enter into suspend, cpus will shutdown, hdmi registers
will reset invisibly. After kernel resume, drm core will call the
bridge enable function. All of hdmi registers will be setup again
except the interrupt registers. In that case we should mute all the
interrupt in suspend stage, and umnute the interrupt we need in the
resume stage.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Clear Hotplug interrupts before dw_hdmi_fb_register

Changes in v2:
- Add irq control to suspend/resume interfaces

 drivers/gpu/drm/bridge/dw_hdmi.c | 41 ++++++++++++++++++++++++++++++++++++++++
 include/drm/bridge/dw_hdmi.h     |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index cd6a706..dc314f5 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1699,6 +1699,47 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
 
+int dw_hdmi_suspend(struct device *dev)
+{
+	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+	u8 ih_mute;
+
+	/* Disable all interrupts */
+	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	 /* Disable top level interrupt bits in HDMI block */
+	ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
+		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_suspend);
+
+int dw_hdmi_resume(struct device *dev)
+{
+	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+
+	/*
+	 * Configure registers related to HDMI interrupt
+	 * generation before registering IRQ.
+	 */
+	hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
+
+	/* Clear Hotplug interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+	dw_hdmi_fb_registered(hdmi);
+
+	/* Unmute interrupts */
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_resume);
+
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 5a4f490..e8cfe1c 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -53,6 +53,8 @@ struct dw_hdmi_plat_data {
 					   struct drm_display_mode *mode);
 };
 
+int dw_hdmi_resume(struct device *dev);
+int dw_hdmi_suspend(struct device *dev);
 void dw_hdmi_unbind(struct device *dev, struct device *master, void *data);
 int dw_hdmi_bind(struct device *dev, struct device *master,
 		 void *data, struct drm_encoder *encoder,
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 02/15] drm: bridge/dw_hdmi: wrap irq control in fucntions
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
  2015-02-03 15:01 ` [PATCH v3 01/15] drm: bridge/dw_hdmi: add irq control to suspend/resume Yakir Yang
@ 2015-02-03 15:02 ` Yakir Yang
  2015-02-03 15:08 ` [PATCH v3 03/15] drm: rockchip/dw_hdmi_rockchip: add resume/suspend support Yakir Yang
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:02 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	Yakir Yang, dri-devel, linux-kernel, Arnd Bergmann, Sean Cross,
	Jyri Sarha, Ben Zhang, alsa-devel, Heiko Stuebner,
	linux-arm-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree, djkurtz, dbehr, mmind00,
	dianders, marcheu, linux-rockchip

Wrap irq control in functions, and then we can call in dw_hdmi_bind /
dw_hdmi_unbind / dw_hdmi_resume / dw_hdmi_suspend functions.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Wrap irq control in fucntions

Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 75 ++++++++++++++++++++--------------------
 1 file changed, 37 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index dc314f5..08f10da 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1330,6 +1330,40 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
 	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
 }
 
+static void hdmi_mute_interrupts(struct dw_hdmi *hdmi)
+{
+	u8 ih_mute;
+
+	/* Disable all interrupts */
+	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+
+	 /* Disable top level interrupt bits in HDMI block */
+	ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
+		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+}
+
+static void hdmi_unmute_interrupts(struct dw_hdmi *hdmi)
+{
+	initialize_hdmi_ih_mutes(hdmi);
+
+	/*
+	 * Configure registers related to HDMI interrupt
+	 * generation before registering IRQ.
+	 */
+	hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
+
+	/* Clear Hotplug interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+	dw_hdmi_fb_registered(hdmi);
+
+	/* Unmute interrupts */
+	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+}
+
 static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
 {
 	dw_hdmi_setup(hdmi, &hdmi->previous_mode);
@@ -1650,25 +1684,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	 */
 	hdmi_init_clk_regenerator(hdmi);
 
-	/*
-	 * Configure registers related to HDMI interrupt
-	 * generation before registering IRQ.
-	 */
-	hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
-
-	/* Clear Hotplug interrupts */
-	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
-
-	ret = dw_hdmi_fb_registered(hdmi);
-	if (ret)
-		goto err_iahb;
-
 	ret = dw_hdmi_register(drm, hdmi);
 	if (ret)
 		goto err_iahb;
 
-	/* Unmute interrupts */
-	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+	hdmi_unmute_interrupts(hdmi);
 
 	dev_set_drvdata(dev, hdmi);
 
@@ -1702,17 +1722,8 @@ EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
 int dw_hdmi_suspend(struct device *dev)
 {
 	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
-	u8 ih_mute;
-
-	/* Disable all interrupts */
-	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
-
-	 /* Disable top level interrupt bits in HDMI block */
-	ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
-		  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
-		  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
 
-	hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+	hdmi_mute_interrupts(hdmi);
 
 	return 0;
 }
@@ -1722,19 +1733,7 @@ int dw_hdmi_resume(struct device *dev)
 {
 	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
 
-	/*
-	 * Configure registers related to HDMI interrupt
-	 * generation before registering IRQ.
-	 */
-	hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
-
-	/* Clear Hotplug interrupts */
-	hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
-
-	dw_hdmi_fb_registered(hdmi);
-
-	/* Unmute interrupts */
-	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+	hdmi_unmute_interrupts(hdmi);
 
 	return 0;
 }
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 03/15] drm: rockchip/dw_hdmi_rockchip: add resume/suspend support
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
  2015-02-03 15:01 ` [PATCH v3 01/15] drm: bridge/dw_hdmi: add irq control to suspend/resume Yakir Yang
  2015-02-03 15:02 ` [PATCH v3 02/15] drm: bridge/dw_hdmi: wrap irq control in fucntions Yakir Yang
@ 2015-02-03 15:08 ` Yakir Yang
  2015-02-03 15:11 ` [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record Yakir Yang
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:08 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Setting the .pm member instead of suspend/resume

Changes in v2:
- Add suspend/resume support for dw_hdmi_rockchip driver

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index d236faa..fc1d02e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -323,11 +323,27 @@ static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int dw_hdmi_rockchip_suspend(struct device *dev)
+{
+	return dw_hdmi_suspend(dev);
+}
+
+static int dw_hdmi_rockchip_resume(struct device *dev)
+{
+	return dw_hdmi_resume(dev);
+}
+
+static const struct dev_pm_ops dw_hdmi_rockchip_pm = {
+	.resume = dw_hdmi_rockchip_resume,
+	.suspend = dw_hdmi_rockchip_suspend,
+};
+
 static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
 	.probe  = dw_hdmi_rockchip_probe,
 	.remove = dw_hdmi_rockchip_remove,
 	.driver = {
 		.name = "dwhdmi-rockchip",
+		.pm = &dw_hdmi_rockchip_pm,
 		.of_match_table = dw_hdmi_rockchip_dt_ids,
 	},
 };
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (2 preceding siblings ...)
  2015-02-03 15:08 ` [PATCH v3 03/15] drm: rockchip/dw_hdmi_rockchip: add resume/suspend support Yakir Yang
@ 2015-02-03 15:11 ` Yakir Yang
  2015-02-05 15:46   ` Daniel Kurtz
  2015-02-03 15:12 ` [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts() Yakir Yang
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:11 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

By parsing the indentification registers we can know what functions
are present on the hdmi ip.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Add ID registers parse and record

Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 59 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi.h | 23 ++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 08f10da..7b5b664 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -79,6 +79,23 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
 	{ 0x6756, 0x78ab, 0x2000, 0x0200 }
 };
 
+struct hdmi_id {
+	u8 design;
+	u8 revision;
+
+	bool prepen;
+	bool audspdif;
+	bool audi2s;
+	bool hdmi14;
+	bool csc;
+	bool hdcp;
+	bool hdmi20;
+	bool confapb;
+	bool ahbauddma;
+	bool gpaud;
+	u8 phy_type;
+};
+
 struct hdmi_vmode {
 	bool mdvi;
 	bool mhsyncpolarity;
@@ -111,6 +128,8 @@ struct dw_hdmi {
 	struct clk *isfr_clk;
 	struct clk *iahb_clk;
 
+	struct hdmi_id id;
+
 	struct hdmi_data_info hdmi_data;
 	const struct dw_hdmi_plat_data *plat_data;
 
@@ -1259,6 +1278,36 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	return 0;
 }
 
+static void hdmi_parse_id(struct dw_hdmi *hdmi)
+{
+	u8 config0_id, config1_id, config2_id, config3_id;
+
+	config0_id = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
+	config1_id = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
+	config2_id = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
+	config3_id = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
+
+	hdmi->id.prepen = config0_id & HDMI_CONFIG0_ID_PREPEN ? true : false;
+	hdmi->id.audi2s = config0_id & HDMI_CONFIG0_ID_AUDI2S ? true : false;
+	hdmi->id.hdmi14 = config0_id & HDMI_CONFIG0_ID_HDMI14 ? true : false;
+	hdmi->id.hdcp = config0_id & HDMI_CONFIG0_ID_HDCP ? true : false;
+	hdmi->id.csc = config0_id & HDMI_CONFIG0_ID_CSC ? true : false;
+	hdmi->id.audspdif = config0_id & HDMI_CONFIG0_ID_AUDSPDIF ?
+			    true : false;
+
+	hdmi->id.confapb = config1_id & HDMI_CONFIG1_ID_CONFAPB ? true : false;
+	hdmi->id.hdmi20 = config1_id & HDMI_CONFIG1_ID_HDMI20 ? true : false;
+
+	hdmi->id.phy_type = config2_id & HDMI_CONFIG2_ID;
+
+	hdmi->id.gpaud = config3_id & HDMI_CONFIG3_ID_GPAUD ? true : false;
+	hdmi->id.ahbauddma = config3_id & HDMI_CONFIG3_ID_AHBAUDDMA ?
+			     true : false;
+
+	hdmi->id.design = hdmi_readb(hdmi, HDMI_DESIGN_ID);
+	hdmi->id.revision = hdmi_readb(hdmi, HDMI_REVISION_ID);
+}
+
 /* Wait until we are registered to enable interrupts */
 static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
 {
@@ -1670,6 +1719,16 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
 		 hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
 
+	/* Config IDs */
+	dev_info(dev,
+		 "Detected HDMI config_id 0x%x:0x%x:0x%x:0x%x\n",
+		 hdmi_readb(hdmi, HDMI_CONFIG0_ID),
+		 hdmi_readb(hdmi, HDMI_CONFIG1_ID),
+		 hdmi_readb(hdmi, HDMI_CONFIG2_ID),
+		 hdmi_readb(hdmi, HDMI_CONFIG3_ID));
+
+	hdmi_parse_id(hdmi);
+
 	initialize_hdmi_ih_mutes(hdmi);
 
 	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 175dbc8..e4ba634 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -545,6 +545,29 @@
 #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
 
 enum {
+/* HDMI_CONFIG0_ID */
+	HDMI_CONFIG0_ID_PREPEN = 0x80,
+	HDMI_CONFIG0_ID_AUDSPDIF = 0x20,
+	HDMI_CONFIG0_ID_AUDI2S = 0x10,
+	HDMI_CONFIG0_ID_HDMI14 = 0x08,
+	HDMI_CONFIG0_ID_CSC = 0x04,
+	HDMI_CONFIG0_ID_HDCP = 0x01,
+
+/* HDMI_CONFIG1_ID */
+	HDMI_CONFIG1_ID_HDMI20 = 0x20,
+	HDMI_CONFIG1_ID_CONFAPB = 0x02,
+
+/* HDMI_CONFIG2_ID */
+	HDMI_CONFIG2_ID_PHY_GEN2 = 0xf2,
+	HDMI_CONFIG2_ID_PHY_GEN2_HECA = 0xe2,
+	HDMI_CONFIG2_ID_PHY_HDMI_MHL = 0xc2,
+	HDMI_CONFIG2_ID_PHY_HDMI_MHL_HECA = 0xb2,
+	HDMI_CONFIG2_ID_LEGACY_PHY = 0x00,
+
+/* HDMI_CONFIG3_ID */
+	HDMI_CONFIG3_ID_AHBAUDDMA = 0x02,
+	HDMI_CONFIG3_ID_GPAUD = 0x01,
+
 /* IH_FC_INT2 field values */
 	HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
 	HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (3 preceding siblings ...)
  2015-02-03 15:11 ` [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record Yakir Yang
@ 2015-02-03 15:12 ` Yakir Yang
  2015-02-05 15:54   ` Daniel Kurtz
  2015-02-03 15:13 ` [PATCH v3 06/15] drm: bridge/dw_hdmi: adjust n/cts setting order Yakir Yang
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:12 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()

Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 7b5b664..262163f 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -196,19 +196,16 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
 	hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
-static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi,
-					 unsigned int value)
+static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
+				       unsigned int n, unsigned int cts)
 {
-	hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
-	hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
-	hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
+	hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
+	hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
+	hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
 
 	/* nshift factor = 0 */
 	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
-}
 
-static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts)
-{
 	/* Must be set/cleared first */
 	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
@@ -374,8 +371,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 		__func__, hdmi->sample_rate, hdmi->ratio,
 		pixel_clk, clk_n, clk_cts);
 
-	hdmi_set_clock_regenerator_n(hdmi, clk_n);
-	hdmi_regenerate_cts(hdmi, clk_cts);
+	hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 06/15] drm: bridge/dw_hdmi: adjust n/cts setting order
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (4 preceding siblings ...)
  2015-02-03 15:12 ` [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts() Yakir Yang
@ 2015-02-03 15:13 ` Yakir Yang
  2015-02-03 15:13 ` [PATCH v3 07/15] drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual Yakir Yang
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:13 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

This patch changes the order to:
- write CTS3 CTS_manual = 0
- write CTS3 N_shift = 0
- write CTS3 CTS value
- write CTS2 CTS value
- write CTS1 CTS value
- write N3 N value
- write N2 N value
- write N1 N value

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Only adjust the n/cts setting order

Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 262163f..81309df 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -199,20 +199,20 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
 				       unsigned int n, unsigned int cts)
 {
-	hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
-	hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
-	hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
+	/* Must be set/cleared first */
+	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
 	/* nshift factor = 0 */
 	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 
-	/* Must be set/cleared first */
-	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
-
-	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
-	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
 	hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
 		    HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+
+	hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
+	hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
+	hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
 }
 
 static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 07/15] drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (5 preceding siblings ...)
  2015-02-03 15:13 ` [PATCH v3 06/15] drm: bridge/dw_hdmi: adjust n/cts setting order Yakir Yang
@ 2015-02-03 15:13 ` Yakir Yang
  2015-02-03 15:14 ` [PATCH v3 08/15] drm: bridge/dw_hdmi: add audio support for more display resolutions Yakir Yang
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:13 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

The ncts_atomic_write & cts_manual bits are present when design id
equal to 0x20. After set the ncts_atomic_write, then the new N and
CTS values are only used when aud_n1 register is updated. After set
cts_manual bit, the new CTS value can set by AudCTS registers.

- write N3 ncts_atomic_write = 1
- write CTS3 CTS_manual = 1

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Set ncts_atomic_write & cts_manual

Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 13 +++++++++++--
 drivers/gpu/drm/bridge/dw_hdmi.h |  6 ++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 81309df..b0b2605 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -199,8 +199,15 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
 				       unsigned int n, unsigned int cts)
 {
+	if (hdmi->id.design == 0x20) {
+		/* set ncts_atomic_write */
+		hdmi_writeb(hdmi, HDMI_AUD_N3_NCTS_ATOMIC_WRITE_SET,
+			    HDMI_AUD_N3);
+	}
+
 	/* Must be set/cleared first */
-	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+	hdmi_modb(hdmi, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3_CTS_MANUAL,
+		  HDMI_AUD_CTS3);
 
 	/* nshift factor = 0 */
 	hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
@@ -210,7 +217,9 @@ static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
 	hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
 	hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 
-	hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
+	/* set n values */
+	hdmi_modb(hdmi, (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK,
+		  HDMI_AUD_N3_AUDN19_16_MASK, HDMI_AUD_N3);
 	hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
 	hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
 }
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index e4ba634..29e4bee 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -907,6 +907,12 @@ enum {
 	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
 	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
 
+/* AUD_N3 field values */
+	HDMI_AUD_N3_NCTS_ATOMIC_WRITE_MASK = 0x80,
+	HDMI_AUD_N3_NCTS_ATOMIC_WRITE_SET = 0x80,
+	HDMI_AUD_N3_NCTS_ATOMIC_WRITE_CLEAR = 0x00,
+	HDMI_AUD_N3_AUDN19_16_MASK = 0x0f,
+
 /* AUD_CTS3 field values */
 	HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
 	HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 08/15] drm: bridge/dw_hdmi: add audio support for more display resolutions
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (6 preceding siblings ...)
  2015-02-03 15:13 ` [PATCH v3 07/15] drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual Yakir Yang
@ 2015-02-03 15:14 ` Yakir Yang
  2015-02-03 15:15 ` [PATCH v3 09/15] drm: bridge/dw_hdmi: enable audio support for No-CEA " Yakir Yang
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:14 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Add more n/cts values, in that case we can support audio for more
display resolutions (128 * SampleRate = PixelClock * N / CTS).

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3: None
Changes in v2:
- add more n/cts combinations for more display resolutions

 drivers/gpu/drm/bridge/dw_hdmi.c | 58 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index b0b2605..1c0515f 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -244,8 +244,24 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
 	case 44100:
 		if (pixel_clk == 25170000)
 			n = 7007;
+		else if (pixel_clk == 25175000)
+			n = 28224;
+		else if (pixel_clk == 40000000)
+			n = 7056;
+		else if (pixel_clk == 54000000)
+			n = 6272;
+		else if (pixel_clk == 65000000)
+			n = 7056;
 		else if (pixel_clk == 74170000)
 			n = 17836;
+		else if (pixel_clk == 74250000)
+			n = 6272;
+		else if (pixel_clk == 83500000)
+			n = 7056;
+		else if (pixel_clk == 106500000)
+			n = 4074;
+		else if (pixel_clk == 108000000)
+			n = 4018;
 		else if (pixel_clk == 148350000)
 			n = (ratio == 150) ? 17836 : 8918;
 		else
@@ -255,10 +271,26 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
 	case 48000:
 		if (pixel_clk == 25170000)
 			n = (ratio == 150) ? 9152 : 6864;
+		else if (pixel_clk == 25175000)
+			n = 12288;
 		else if (pixel_clk == 27020000)
 			n = (ratio == 150) ? 8192 : 6144;
+		else if (pixel_clk == 40000000)
+			n = 6144;
+		else if (pixel_clk == 54000000)
+			n = 6144;
+		else if (pixel_clk == 65000000)
+			n = 6144;
 		else if (pixel_clk == 74170000)
 			n = 11648;
+		else if (pixel_clk == 74250000)
+			n = 6144;
+		else if (pixel_clk == 83500000)
+			n = 6144;
+		else if (pixel_clk == 106500000)
+			n = 6144;
+		else if (pixel_clk == 108000000)
+			n = 6144;
 		else if (pixel_clk == 148350000)
 			n = (ratio == 150) ? 11648 : 5824;
 		else
@@ -306,10 +338,18 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 	case 96000:
 	case 192000:
 		switch (pixel_clk) {
+		case 25175000:
+			cts = 50350;
+			break;
 		case 25200000:
 		case 27000000:
+		case 40000000:
 		case 54000000:
+		case 65000000:
 		case 74250000:
+		case 83500000:
+		case 106500000:
+		case 108000000:
 		case 148500000:
 			cts = pixel_clk / 1000;
 			break;
@@ -330,18 +370,36 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 	case 88200:
 	case 176400:
 		switch (pixel_clk) {
+		case 25175000:
+			cts = 125875;
+			break;
 		case 25200000:
 			cts = 28000;
 			break;
 		case 27000000:
 			cts = 30000;
 			break;
+		case 40000000:
+			cts = 50000;
+			break;
 		case 54000000:
 			cts = 60000;
 			break;
+		case 65000000:
+			cts = 81250;
+			break;
 		case 74250000:
 			cts = 82500;
 			break;
+		case 83500000:
+			cts = 104375;
+			break;
+		case 106500000:
+			cts = 88750;
+			break;
+		case 108000000:
+			cts = 76875;
+			break;
 		case 148500000:
 			cts = 165000;
 			break;
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 09/15] drm: bridge/dw_hdmi: enable audio support for No-CEA display resolutions
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (7 preceding siblings ...)
  2015-02-03 15:14 ` [PATCH v3 08/15] drm: bridge/dw_hdmi: add audio support for more display resolutions Yakir Yang
@ 2015-02-03 15:15 ` Yakir Yang
  2015-02-03 15:16 ` [PATCH v3 10/15] drm: bridge/dw_hdmi: add audio sample channel status setting Yakir Yang
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:15 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

If the monitor support audio, so we should support audio for it, even if
the display resolution is No-CEA mode.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3: None
Changes in v2:
- enable audio support for No-CEA display mode

 drivers/gpu/drm/bridge/dw_hdmi.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 1c0515f..0bee5ea 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1264,13 +1264,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 
 	hdmi->vic = drm_match_cea_mode(mode);
 
-	if (!hdmi->vic) {
+	if (hdmi->hdmi_data.video_mode.mdvi)
 		dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
-		hdmi->hdmi_data.video_mode.mdvi = true;
-	} else {
+	else
 		dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
-		hdmi->hdmi_data.video_mode.mdvi = false;
-	}
 
 	if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
 	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
@@ -1538,6 +1535,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 {
 	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
 					     connector);
+	struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
 	struct edid *edid;
 	int ret;
 
@@ -1549,6 +1547,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 		dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
 			edid->width_cm, edid->height_cm);
 
+		vmode->mdvi = !drm_detect_hdmi_monitor(edid);
+
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
 		kfree(edid);
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 10/15] drm: bridge/dw_hdmi: add audio sample channel status setting
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (8 preceding siblings ...)
  2015-02-03 15:15 ` [PATCH v3 09/15] drm: bridge/dw_hdmi: enable audio support for No-CEA " Yakir Yang
@ 2015-02-03 15:16 ` Yakir Yang
  2015-02-03 15:16 ` [PATCH v3 11/15] drm: bridge/dw_hdmi: add audio clock control interfaces Yakir Yang
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:16 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

When transmitting IEC60985 linear PCM audio, we configure the
Aduio Sample Channel Status information of all the channel
status bits in the IEC60958 frame.
(am from https://patchwork.kernel.org/patch/5749101/)

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Determine whether sample channel should set by desig_id.

Changes in v2:
- Add audio sample channel status setting

 drivers/gpu/drm/bridge/dw_hdmi.c | 44 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi.h | 20 ++++++++++++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0bee5ea..44e95f3 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -196,6 +196,47 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
 	hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
+static void hdmi_set_schnl(struct dw_hdmi *hdmi)
+{
+	u8 aud_schnl_samplerate;
+
+	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:
+		aud_schnl_samplerate = HDMI_FC_AUDSCHNLS7_SMPRATE_44K1;
+		break;
+	}
+
+	/* set channel status register */
+	hdmi_modb(hdmi, aud_schnl_samplerate,
+		  HDMI_FC_AUDSCHNLS7_SMPRATE_MASK, HDMI_FC_AUDSCHNLS7);
+	hdmi_writeb(hdmi, ((~aud_schnl_samplerate) << 4) | 0x2,
+		    HDMI_FC_AUDSCHNLS8);
+}
+
 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
 				       unsigned int n, unsigned int cts)
 {
@@ -439,6 +480,9 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 		pixel_clk, clk_n, clk_cts);
 
 	hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
+
+	if (hdmi->id.design == 0x20)
+		hdmi_set_schnl(hdmi);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 29e4bee..c2d210f 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -162,6 +162,17 @@
 #define HDMI_FC_SPDDEVICEINF                    0x1062
 #define HDMI_FC_AUDSCONF                        0x1063
 #define HDMI_FC_AUDSSTAT                        0x1064
+#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
@@ -754,6 +765,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,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_768K = 0x9,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_88K2 = 0x8,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_32K = 0x3,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_48K = 0x2,
+	HDMI_FC_AUDSCHNLS7_SMPRATE_44K1 = 0x0,
 
 /* HDMI_FC_AUDSCHNLS8 field values */
 	HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 11/15] drm: bridge/dw_hdmi: add audio clock control interfaces
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (9 preceding siblings ...)
  2015-02-03 15:16 ` [PATCH v3 10/15] drm: bridge/dw_hdmi: add audio sample channel status setting Yakir Yang
@ 2015-02-03 15:16 ` Yakir Yang
  2015-02-03 15:17 ` [PATCH v3 12/15] drm: bridge/dw_hdmi: creat dw-hdmi-audio platform device Yakir Yang
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:16 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Add audio clock enable/disable/restore interfacess, those functions
can be called concurrently on multiple different threads of execution
to change the hdmi audio enable state.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Delete hdmi_audio_config interface and modify audio clock control functions

Changes in v2:
- Add audio config interfaces to dw_hdmi driver

 drivers/gpu/drm/bridge/dw_hdmi.c | 60 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 44e95f3..92fc12d 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/hdmi.h>
+#include <linux/mutex.h>
 #include <linux/of_device.h>
 
 #include <drm/drm_of.h>
@@ -146,6 +147,9 @@ struct dw_hdmi {
 	void __iomem *regs;
 
 	unsigned int sample_rate;
+	struct mutex audio_mutex;
+	bool audio_enable;
+
 	int ratio;
 
 	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
@@ -1234,6 +1238,53 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 	hdmi->phy_enabled = false;
 }
 
+static void dw_hdmi_audio_clk_enable(struct dw_hdmi *hdmi)
+{
+	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
+}
+
+static void dw_hdmi_audio_clk_disable(struct dw_hdmi *hdmi)
+{
+	hdmi_modb(hdmi, HDMI_MC_CLKDIS_AUDCLK_DISABLE,
+			HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
+}
+
+static void hdmi_audio_restore(struct dw_hdmi *hdmi)
+{
+	mutex_lock(&hdmi->audio_mutex);
+
+	if (hdmi->audio_enable)
+		dw_hdmi_audio_clk_enable(hdmi);
+	else
+		dw_hdmi_audio_clk_disable(hdmi);
+
+	mutex_unlock(&hdmi->audio_mutex);
+}
+
+static void hdmi_audio_enable(struct dw_hdmi *hdmi)
+{
+	mutex_lock(&hdmi->audio_mutex);
+
+	if (!hdmi->audio_enable) {
+		hdmi->audio_enable = true;
+		dw_hdmi_audio_clk_enable(hdmi);
+	}
+
+	mutex_unlock(&hdmi->audio_mutex);
+}
+
+static void hdmi_audio_disable(struct dw_hdmi *hdmi)
+{
+	mutex_lock(&hdmi->audio_mutex);
+
+	if (hdmi->audio_enable) {
+		hdmi->audio_enable = false;
+		dw_hdmi_audio_clk_disable(hdmi);
+	}
+
+	mutex_unlock(&hdmi->audio_mutex);
+}
+
 /* HDMI Initialization Step B.4 */
 static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
@@ -1264,11 +1315,6 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 	}
 }
 
-static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
-{
-	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
-}
-
 /* Workaround to clear the overflow condition */
 static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
 {
@@ -1364,7 +1410,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);
+		hdmi_audio_restore(hdmi);
 
 		/* HDMI Initialization Step F - Configure AVI InfoFrame */
 		hdmi_config_AVI(hdmi);
@@ -1758,6 +1804,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	hdmi->sample_rate = 48000;
 	hdmi->ratio = 100;
 	hdmi->encoder = encoder;
+	hdmi->audio_enable = false;
+	mutex_init(&hdmi->audio_mutex);
 
 	of_property_read_u32(np, "reg-io-width", &val);
 
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 12/15] drm: bridge/dw_hdmi: creat dw-hdmi-audio platform device
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (10 preceding siblings ...)
  2015-02-03 15:16 ` [PATCH v3 11/15] drm: bridge/dw_hdmi: add audio clock control interfaces Yakir Yang
@ 2015-02-03 15:17 ` Yakir Yang
  2015-02-03 15:18 ` [PATCH v3 13/15] ASoC: dw-hdmi-audio: add codec driver for dw hdmi audio Yakir Yang
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:17 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

creat dw-hdmi-audio device dynamically in probe function,
and transfer some interfaces to dw-hdmi-audio driver for
setting hdmi audio format & control hdmi audio clock.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Remove audio_config & get_connect_status callback functions
  and add write/read/mod register callback functions

Changes in v2:
- Update the audio control interfaces

 drivers/gpu/drm/bridge/dw_hdmi.c | 29 +++++++++++++++++++++++++++++
 include/drm/bridge/dw_hdmi.h     | 15 +++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 92fc12d..9734532 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -124,6 +124,8 @@ struct dw_hdmi {
 	struct drm_encoder *encoder;
 	struct drm_bridge *bridge;
 
+	struct platform_device *audio_pdev;
+
 	enum dw_hdmi_devtype dev_type;
 	struct device *dev;
 	struct clk *isfr_clk;
@@ -499,6 +501,12 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
 	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
 }
 
+static void hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int sample_rate)
+{
+	hdmi->sample_rate = sample_rate;
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
+}
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -1787,6 +1795,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 struct resource *iores, int irq,
 		 const struct dw_hdmi_plat_data *plat_data)
 {
+	struct platform_device_info pdevinfo;
+	struct dw_hdmi_audio_data audio;
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
 	struct device_node *ddc_node;
@@ -1906,6 +1916,25 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 
 	dev_set_drvdata(dev, hdmi);
 
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	pdevinfo.parent = dev;
+	pdevinfo.id = PLATFORM_DEVID_NONE;
+
+	audio.irq = irq;
+	audio.dw = hdmi;
+	audio.mod = hdmi_modb;
+	audio.read = hdmi_readb;
+	audio.write = hdmi_writeb;
+	audio.enable = hdmi_audio_enable;
+	audio.disable = hdmi_audio_disable;
+	audio.set_sample_rate = hdmi_set_sample_rate;
+
+	pdevinfo.name = "dw-hdmi-audio";
+	pdevinfo.data = &audio;
+	pdevinfo.size_data = sizeof(audio);
+	pdevinfo.dma_mask = DMA_BIT_MASK(32);
+	hdmi->audio_pdev = platform_device_register_full(&pdevinfo);
+
 	return 0;
 
 err_iahb:
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index e8cfe1c..23ca491 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -12,6 +12,8 @@
 
 #include <drm/drmP.h>
 
+struct dw_hdmi;
+
 enum {
 	DW_HDMI_RES_8,
 	DW_HDMI_RES_10,
@@ -44,6 +46,19 @@ struct dw_hdmi_sym_term {
 	u16 term;       /*transmission termination value*/
 };
 
+struct dw_hdmi_audio_data {
+	int irq;
+	struct dw_hdmi *dw;
+
+	u8 (*read)(struct dw_hdmi *hdmi, int offset);
+	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
+	void (*mod)(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg);
+
+	void (*enable)(struct dw_hdmi *hdmi);
+	void (*disable)(struct dw_hdmi *hdmi);
+	void (*set_sample_rate)(struct dw_hdmi *hdmi, unsigned int rate);
+};
+
 struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
 	const struct dw_hdmi_mpll_config *mpll_cfg;
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 13/15] ASoC: dw-hdmi-audio: add codec driver for dw hdmi audio
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (11 preceding siblings ...)
  2015-02-03 15:17 ` [PATCH v3 12/15] drm: bridge/dw_hdmi: creat dw-hdmi-audio platform device Yakir Yang
@ 2015-02-03 15:18 ` Yakir Yang
  2015-02-03 15:19 ` [PATCH v3 14/15] ASoC: rockchip-hdmi-audio: add sound driver for " Yakir Yang
  2015-02-03 15:19 ` [PATCH v3 15/15] dt-bindings: Add documentation for Rockchip dw-hdmi-audio Yakir Yang
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:18 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

codec driver creat an standard alsa device, than config audio
and report jack status through some callback interfaces that
dw_hdmi driver support.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Keep audio format config function in dw-hdmi-audio driver
  and remove audio_config & get_connect_status functions,
  move jack control to dw-hdmi-audio completely.

Changes in v2:
- Update dw_hdmi audio control interfaces, and adjust jack report process

 sound/soc/codecs/Kconfig         |   4 +
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/dw-hdmi-audio.c | 333 +++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/dw-hdmi-audio.h |  79 ++++++++++
 4 files changed, 418 insertions(+)
 create mode 100644 sound/soc/codecs/dw-hdmi-audio.c
 create mode 100644 sound/soc/codecs/dw-hdmi-audio.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8349f98..b34dd12 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
 	select SND_SOC_HDMI_CODEC
+	select SND_SOC_DW_HDMI_AUDIO
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM1792A if SPI_MASTER
 	select SND_SOC_PCM3008
@@ -459,6 +460,9 @@ config SND_SOC_MAX98095
 config SND_SOC_MAX9850
 	tristate
 
+config SND_SOC_DW_HDMI_AUDIO
+       tristate
+
 config SND_SOC_PCM1681
 	tristate "Texas Instruments PCM1681 CODEC"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bbdfd1e..0ebb664 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -68,6 +68,7 @@ snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-hdmi-codec-objs := hdmi.o
+snd-soc-dw-hdmi-audio-objs := dw-hdmi-audio.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -249,6 +250,7 @@ obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
 obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
+obj-$(CONFIG_SND_SOC_DW_HDMI_AUDIO) += snd-soc-dw-hdmi-audio.o
 obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/dw-hdmi-audio.c b/sound/soc/codecs/dw-hdmi-audio.c
new file mode 100644
index 0000000..57d1ca1
--- /dev/null
+++ b/sound/soc/codecs/dw-hdmi-audio.c
@@ -0,0 +1,333 @@
+/*
+ * dw-hdmi-codec.c
+ *
+ * DesignerWare ALSA SoC DAI driver for DW HDMI audio.
+ * Copyright (c) 2014,  CORPORATION. All rights reserved.
+ * Authors: Yakir Yang <ykk@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.*
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+
+#include <drm/bridge/dw_hdmi.h>
+#include "dw-hdmi-audio.h"
+
+struct snd_dw_hdmi {
+	struct device *dev;
+	struct dw_hdmi_audio_data data;
+
+	u8 jack_status;
+	bool is_jack_ready;
+	struct snd_soc_jack jack;
+};
+
+int snd_dw_hdmi_jack_detect(struct snd_dw_hdmi *hdmi)
+{
+	u8 status, jack_status;
+
+	if (!hdmi->is_jack_ready)
+		return -EINVAL;
+
+	status = hdmi->data.read(hdmi->data.dw, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
+	jack_status = status ? SND_JACK_LINEOUT : 0;
+	if (jack_status != hdmi->jack_status) {
+		snd_soc_jack_report(&hdmi->jack, jack_status,
+				    SND_JACK_LINEOUT);
+		hdmi->jack_status = jack_status;
+
+		dev_info(hdmi->dev, "jack report [%d]\n", hdmi->jack_status);
+	}
+
+	return 0;
+}
+
+static irqreturn_t snd_dw_hdmi_hardirq(int irq, void *dev_id)
+{
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t snd_dw_hdmi_irq(int irq, void *dev_id)
+{
+	struct snd_dw_hdmi *hdmi = dev_id;
+
+	snd_dw_hdmi_jack_detect(hdmi);
+
+	return IRQ_HANDLED;
+}
+
+static void dw_hdmi_audio_set_fmt(struct snd_dw_hdmi *hdmi,
+				  const struct hdmi_audio_fmt *fmt)
+{
+	hdmi->data.mod(hdmi->data.dw, AUDIO_INPUTTYPE_IIS,
+		       AUDIO_CONF0_INTERFACE_MSK, HDMI_AUD_CONF0);
+
+	hdmi->data.mod(hdmi->data.dw, fmt->chan_num, AUDIO_CONF0_I2SINEN_MSK,
+		       HDMI_AUD_CONF0);
+
+	hdmi->data.mod(hdmi->data.dw, fmt->word_length, AUDIO_CONF1_DATWIDTH_MSK,
+		       HDMI_AUD_CONF1);
+
+	hdmi->data.mod(hdmi->data.dw, fmt->dai_fmt, AUDIO_CONF1_DATAMODE_MSK,
+		       HDMI_AUD_CONF1);
+
+	hdmi->data.write(hdmi->data.dw, 0, HDMI_AUD_INPUTCLKFS);
+
+	hdmi->data.set_sample_rate(hdmi->data.dw, fmt->sample_rate);
+}
+
+static int snd_dw_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *hdmi = snd_soc_dai_get_drvdata(codec_dai);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct hdmi_audio_fmt hdmi_fmt;
+	unsigned int fmt, rate, chan, width;
+
+	fmt = rtd->dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	switch (fmt) {
+	case SND_SOC_DAIFMT_I2S:
+		hdmi_fmt.dai_fmt = AUDIO_DAIFMT_IIS;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		hdmi_fmt.dai_fmt = AUDIO_DAIFMT_LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		hdmi_fmt.dai_fmt = AUDIO_DAIFMT_RIGHT_J;
+		break;
+	default:
+		dev_err(codec_dai->dev, "DAI format unsupported");
+		return -EINVAL;
+	}
+	dev_dbg(codec_dai->dev, "[codec_dai]: dai_fmt = %d.\n", fmt);
+
+	width = params_width(params);
+	switch (width) {
+	case 16:
+	case 24:
+		hdmi_fmt.word_length = width;
+		break;
+	default:
+		dev_err(codec_dai->dev, "width[%d] not support!\n", width);
+		return -EINVAL;
+	}
+	dev_dbg(codec_dai->dev, "[codec_dai]: word_length = %d.\n", width);
+
+	chan = params_channels(params);
+	switch (chan) {
+	case 2:
+		hdmi_fmt.chan_num = AUDIO_CHANNELNUM_2;
+		break;
+	case 4:
+		hdmi_fmt.chan_num = AUDIO_CHANNELNUM_4;
+		break;
+	case 6:
+		hdmi_fmt.chan_num = AUDIO_CHANNELNUM_6;
+		break;
+	case 8:
+		hdmi_fmt.chan_num = AUDIO_CHANNELNUM_8;
+		break;
+	default:
+		dev_err(codec_dai->dev, "channel[%d] not support!\n", chan);
+		return -EINVAL;
+	}
+	dev_dbg(codec_dai->dev, "[codec_dai]: chan_num = %d.\n", chan);
+
+	rate = params_rate(params);
+	switch (rate) {
+	case 32000:
+	case 44100:
+	case 48000:
+	case 88200:
+	case 96000:
+	case 176400:
+	case 192000:
+		hdmi_fmt.sample_rate = rate;
+		break;
+	default:
+		dev_err(codec_dai->dev, "rate[%d] not support!\n", rate);
+		return -EINVAL;
+	}
+	dev_dbg(codec_dai->dev, "[codec_dai]: sample_rate = %d.\n", rate);
+
+	dw_hdmi_audio_set_fmt(hdmi, &hdmi_fmt);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_dai_trigger(struct snd_pcm_substream *substream,
+				   int cmd, struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *hdmi = snd_soc_dai_get_drvdata(codec_dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		hdmi->data.enable(hdmi->data.dw);
+		dev_dbg(codec_dai->dev, "[codec_dai]: trigger enable.\n");
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		hdmi->data.disable(hdmi->data.dw);
+		dev_dbg(codec_dai->dev, "[codec_dai]: trigger disable.\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int snd_dw_hdmi_audio_probe(struct snd_soc_codec *codec)
+{
+	struct snd_dw_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = snd_soc_jack_new(codec, "HDMI Jack", SND_JACK_LINEOUT,
+			       &hdmi->jack);
+	if (ret) {
+		dev_err(hdmi->dev, "jack new failed (%d)\n", ret);
+		hdmi->is_jack_ready = false;
+		return ret;
+	}
+
+	hdmi->is_jack_ready = true;
+
+	return snd_dw_hdmi_jack_detect(hdmi);
+}
+
+static const struct snd_soc_dapm_widget snd_dw_hdmi_audio_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TX"),
+};
+
+static const struct snd_soc_dapm_route snd_dw_hdmi_audio_routes[] = {
+	{ "TX", NULL, "Playback" },
+};
+
+static const struct snd_soc_dai_ops dw_hdmi_dai_ops = {
+	.hw_params = snd_dw_hdmi_dai_hw_params,
+	.trigger = snd_dw_hdmi_dai_trigger,
+};
+
+static struct snd_soc_dai_driver dw_hdmi_audio_dai = {
+	.name = "dw-hdmi-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+			 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+			 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+	},
+	.ops = &dw_hdmi_dai_ops,
+};
+
+static const struct snd_soc_codec_driver dw_hdmi_audio = {
+	.probe = snd_dw_hdmi_audio_probe,
+	.dapm_widgets = snd_dw_hdmi_audio_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(snd_dw_hdmi_audio_widgets),
+	.dapm_routes = snd_dw_hdmi_audio_routes,
+	.num_dapm_routes = ARRAY_SIZE(snd_dw_hdmi_audio_routes),
+};
+
+static int dw_hdmi_audio_probe(struct platform_device *pdev)
+{
+	struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
+	struct snd_dw_hdmi *hdmi;
+	int ret;
+
+	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	hdmi->data = *data;
+	hdmi->dev = &pdev->dev;
+	platform_set_drvdata(pdev, hdmi);
+
+	ret = devm_request_threaded_irq(&pdev->dev, hdmi->data.irq,
+					snd_dw_hdmi_hardirq,
+					snd_dw_hdmi_irq, IRQF_SHARED,
+					"dw-hdmi-audio", hdmi);
+	if (ret) {
+		dev_err(&pdev->dev, "request irq failed (%d)\n", ret);
+		goto free_hdmi_data;
+	}
+
+	ret = snd_soc_register_codec(&pdev->dev, &dw_hdmi_audio,
+				     &dw_hdmi_audio_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "register codec failed (%d)\n", ret);
+		goto free_irq;
+	}
+
+	dev_info(&pdev->dev, "hdmi audio init success.\n");
+
+	return 0;
+
+free_irq:
+	devm_free_irq(&pdev->dev, hdmi->data.irq, hdmi);
+free_hdmi_data:
+	devm_kfree(&pdev->dev, hdmi);
+
+	return ret;
+}
+
+static int dw_hdmi_audio_remove(struct platform_device *pdev)
+{
+	struct snd_dw_hdmi *hdmi = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_codec(&pdev->dev);
+	devm_free_irq(&pdev->dev, hdmi->data.irq, hdmi);
+	devm_kfree(&pdev->dev, hdmi);
+
+	return 0;
+}
+
+static const struct of_device_id dw_hdmi_audio_ids[] = {
+	{ .compatible = "dw-hdmi-audio", },
+	{ }
+};
+
+static struct platform_driver dw_hdmi_audio_driver = {
+	.driver = {
+		.name = "dw-hdmi-audio",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(dw_hdmi_audio_ids),
+	},
+	.probe = dw_hdmi_audio_probe,
+	.remove = dw_hdmi_audio_remove,
+};
+module_platform_driver(dw_hdmi_audio_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("DW HDMI Audio ASoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" "dw-hdmi-audio");
+MODULE_DEVICE_TABLE(of, dw_hdmi_audio_ids);
diff --git a/sound/soc/codecs/dw-hdmi-audio.h b/sound/soc/codecs/dw-hdmi-audio.h
new file mode 100644
index 0000000..f41f519
--- /dev/null
+++ b/sound/soc/codecs/dw-hdmi-audio.h
@@ -0,0 +1,79 @@
+/*
+ * dw-hdmi-audio.h -- DW HDMI ALSA SoC Audio driver
+ *
+ * Copyright 2011-2012 DesignerWare Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DW_HDMI_AUDIO_H
+#define _DW_HDMI_AUDIO_H
+
+enum hdmi_audio_reg {
+	HDMI_PHY_STAT0 = 0x3004,
+	HDMI_AUD_CONF0 = 0x3100,
+	HDMI_AUD_CONF1 = 0x3101,
+	HDMI_AUD_INPUTCLKFS = 0x3206,
+	HDMI_MC_CLKDIS = 0x4001,
+};
+
+enum {
+	HDMI_PHY_HPD = 0x2,
+	HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+};
+
+enum hdmi_audio_samplerate {
+	AUDIO_SAMPLERATE_32K = 32000,
+	AUDIO_SAMPLERATE_44K1 = 44100,
+	AUDIO_SAMPLERATE_48K = 48000,
+	AUDIO_SAMPLERATE_88K2 = 88200,
+	AUDIO_SAMPLERATE_96K = 96000,
+	AUDIO_SAMPLERATE_176K4 = 176400,
+	AUDIO_SAMPLERATE_192K = 192000,
+};
+
+#define AUDIO_CONF1_DATWIDTH_MSK	0x1F
+enum hdmi_audio_wordlength {
+	AUDIO_WORDLENGTH_16BIT = 16,
+	AUDIO_WORDLENGTH_24BIT = 24,
+};
+
+#define AUDIO_CONF1_DATAMODE_MSK	0xE0
+enum hdmi_audio_daifmt {
+	AUDIO_DAIFMT_IIS = 0x00,
+	AUDIO_DAIFMT_RIGHT_J = 0x20,
+	AUDIO_DAIFMT_LEFT_J = 0x40,
+	AUDIO_DAIFMT_BURST_1 = 0x60,
+	AUDIO_DAIFMT_BURST_2 = 0x80,
+};
+
+#define AUDIO_CONF0_INTERFACE_MSK	0x20
+enum hdmi_audio_inputtype {
+	AUDIO_INPUTTYPE_IIS = 0x20,
+	AUDIO_INPUTTYPE_SPDIF = 0x00,
+};
+
+#define AUDIO_CONF0_I2SINEN_MSK		0x0F
+enum hdmi_audio_channelnum {
+	AUDIO_CHANNELNUM_2 = 0x01,
+	AUDIO_CHANNELNUM_4 = 0x03,
+	AUDIO_CHANNELNUM_6 = 0x07,
+	AUDIO_CHANNELNUM_8 = 0x0F,
+};
+
+enum hdmi_jack_status {
+	JACK_LINEOUT,
+	JACK_NO_LINEOUT,
+};
+
+struct hdmi_audio_fmt {
+	enum hdmi_audio_inputtype input_type;
+	enum hdmi_audio_channelnum chan_num;
+	enum hdmi_audio_samplerate sample_rate;
+	enum hdmi_audio_wordlength word_length;
+	enum hdmi_audio_daifmt dai_fmt;
+};
+
+#endif
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 14/15] ASoC: rockchip-hdmi-audio: add sound driver for hdmi audio
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (12 preceding siblings ...)
  2015-02-03 15:18 ` [PATCH v3 13/15] ASoC: dw-hdmi-audio: add codec driver for dw hdmi audio Yakir Yang
@ 2015-02-03 15:19 ` Yakir Yang
  2015-02-03 15:19 ` [PATCH v3 15/15] dt-bindings: Add documentation for Rockchip dw-hdmi-audio Yakir Yang
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:19 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Add a sound driver that combines rockchip-i2s cpu_dai and dw-hdmi-codec
as codec_dai to provide hdmi audio output on rk3288 platforms.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- Delete the operation of jack in rockchip-hdmi-audio driver,
  get ready to switch to simple-audio-card driver.

Changes in v2:
- give "codec-name" & "codec-dai-name" an const name

 sound/soc/rockchip/Kconfig               |   9 ++
 sound/soc/rockchip/Makefile              |   2 +
 sound/soc/rockchip/rockchip_hdmi_audio.c | 168 +++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 sound/soc/rockchip/rockchip_hdmi_audio.c

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index e181826..ed2b7f0 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -14,3 +14,12 @@ config SND_SOC_ROCKCHIP_I2S
 	  Say Y or M if you want to add support for I2S driver for
 	  Rockchip I2S device. The device supports upto maximum of
 	  8 channels each for play and record.
+
+config SND_SOC_ROCKCHIP_HDMI_AUDIO
+	tristate "ASoC support for Rockchip HDMI audio"
+	depends on SND_SOC_ROCKCHIP
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_DW_HDMI_AUDIO
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  HDMI, such as rk3288 hdmi.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index b921909..b9185b3 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -1,4 +1,6 @@
 # ROCKCHIP Platform Support
 snd-soc-i2s-objs := rockchip_i2s.o
+snd-soc-rockchip-hdmi-audio-objs := rockchip_hdmi_audio.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_HDMI_AUDIO) += snd-soc-rockchip-hdmi-audio.o
diff --git a/sound/soc/rockchip/rockchip_hdmi_audio.c b/sound/soc/rockchip/rockchip_hdmi_audio.c
new file mode 100644
index 0000000..4744c36
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_hdmi_audio.c
@@ -0,0 +1,168 @@
+/*
+ * rockchip-hdmi-card.c
+ *
+ * ROCKCHIP ALSA SoC DAI driver for HDMI audio on rockchip processors.
+ * Copyright (c) 2014, ROCKCHIP CORPORATION. All rights reserved.
+ * Authors: Yakir Yang <ykk@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.*
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+
+#include "rockchip_i2s.h"
+
+#define DRV_NAME "rockchip-hdmi-audio"
+
+static int rockchip_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	unsigned int dai_fmt = rtd->dai_link->dai_fmt;
+	int mclk, ret;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 24000:
+	case 32000:
+	case 48000:
+	case 64000:
+	case 96000:
+		mclk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+	case 88200:
+		mclk = 11289600;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to set cpu_dai fmt.\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to set cpu_dai sysclk.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops hdmi_audio_dai_ops = {
+	.hw_params = rockchip_hdmi_audio_hw_params,
+};
+
+static struct snd_soc_dai_link hdmi_audio_dai = {
+	.name = "RockchipHDMI",
+	.stream_name = "RockchipHDMI",
+	.codec_name = "dw-hdmi-audio",
+	.codec_dai_name = "dw-hdmi-hifi",
+	.ops = &hdmi_audio_dai_ops,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card rockchip_hdmi_audio_card = {
+	.name = "RockchipHDMI",
+	.owner = THIS_MODULE,
+	.dai_link = &hdmi_audio_dai,
+	.num_links = 1,
+};
+
+static int rockchip_hdmi_audio_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_hdmi_audio_card;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	hdmi_audio_dai.cpu_of_node = of_parse_phandle(np, "i2s-controller", 0);
+	if (!hdmi_audio_dai.cpu_of_node) {
+		dev_err(&pdev->dev, "Property 'i2s-controller' missing !\n");
+		goto free_priv_data;
+	}
+
+	hdmi_audio_dai.platform_of_node = hdmi_audio_dai.cpu_of_node;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "register card failed (%d)\n", ret);
+		card->dev = NULL;
+		goto free_cpu_of_node;
+	}
+
+	dev_info(&pdev->dev, "hdmi audio init success.\n");
+
+	return 0;
+
+free_cpu_of_node:
+	hdmi_audio_dai.cpu_of_node = NULL;
+	hdmi_audio_dai.platform_of_node = NULL;
+free_priv_data:
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return ret;
+}
+
+static int rockchip_hdmi_audio_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return 0;
+}
+
+static const struct of_device_id rockchip_hdmi_audio_of_match[] = {
+	{ .compatible = "rockchip,rk3288-hdmi-audio", },
+	{},
+};
+
+static struct platform_driver rockchip_hdmi_audio_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = rockchip_hdmi_audio_of_match,
+	},
+	.probe = rockchip_hdmi_audio_probe,
+	.remove = rockchip_hdmi_audio_remove,
+};
+module_platform_driver(rockchip_hdmi_audio_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip HDMI Audio ASoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_hdmi_audio_of_match);
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 15/15] dt-bindings: Add documentation for Rockchip dw-hdmi-audio
  2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
                   ` (13 preceding siblings ...)
  2015-02-03 15:19 ` [PATCH v3 14/15] ASoC: rockchip-hdmi-audio: add sound driver for " Yakir Yang
@ 2015-02-03 15:19 ` Yakir Yang
  14 siblings, 0 replies; 20+ messages in thread
From: Yakir Yang @ 2015-02-03 15:19 UTC (permalink / raw)
  To: David Airlie, Russell King, Philipp Zabel
  Cc: Fabio Estevam, Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter,
	dri-devel, linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha,
	Ben Zhang, alsa-devel, Heiko Stuebner, linux-arm-kernel,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree, djkurtz, mmind00, dianders, marcheu, linux-rockchip,
	Yakir Yang

Required properties:
- compatible: platform specific
- i2s-controller: the i2s controller device node

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
---
Changes in v3:
- modify cpu-of-node to i2s-controller

Changes in v2:
- remove codec-name and codec-dai-name
- rename rockchip,rockchip-hdmi-audio.txt to rockchip,rockchip-dw-hdmi-audio.txt

 .../bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt       | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt

diff --git a/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt b/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
new file mode 100644
index 0000000..f0d23c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
@@ -0,0 +1,12 @@
+Rockchip hdmi audio bindings
+
+Required properties:
+- compatible: platform specific
+- i2s-controller: the i2s controller device node
+
+Example:
+
+sound {
+	compatible = "rockchip,rk3288-hdmi-audio";
+	i2s-controller = <&i2s>;
+};
-- 
2.1.2



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record
  2015-02-03 15:11 ` [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record Yakir Yang
@ 2015-02-05 15:46   ` Daniel Kurtz
  2015-02-07  3:33     ` yakir
  0 siblings, 1 reply; 20+ messages in thread
From: Daniel Kurtz @ 2015-02-05 15:46 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Russell King, Philipp Zabel, Fabio Estevam,
	Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter, dri-devel,
	linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha, Ben Zhang,
	alsa-devel, Heiko Stuebner, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND...,
	Heiko Stübner, Douglas Anderson, Stéphane Marchesin,
	open list:ARM/Rockchip SoC...

On Tue, Feb 3, 2015 at 11:11 PM, Yakir Yang <ykk@rock-chips.com> wrote:
> By parsing the indentification registers we can know what functions
> are present on the hdmi ip.
>
> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> ---
> Changes in v3:
> - Add ID registers parse and record
>
> Changes in v2: None
>
>  drivers/gpu/drm/bridge/dw_hdmi.c | 59 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/bridge/dw_hdmi.h | 23 ++++++++++++++++
>  2 files changed, 82 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 08f10da..7b5b664 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -79,6 +79,23 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
>         { 0x6756, 0x78ab, 0x2000, 0x0200 }
>  };
>
> +struct hdmi_id {
> +       u8 design;
> +       u8 revision;
> +
> +       bool prepen;
> +       bool audspdif;
> +       bool audi2s;
> +       bool hdmi14;
> +       bool csc;
> +       bool hdcp;
> +       bool hdmi20;
> +       bool confapb;
> +       bool ahbauddma;
> +       bool gpaud;
> +       u8 phy_type;
> +};
> +
>  struct hdmi_vmode {
>         bool mdvi;
>         bool mhsyncpolarity;
> @@ -111,6 +128,8 @@ struct dw_hdmi {
>         struct clk *isfr_clk;
>         struct clk *iahb_clk;
>
> +       struct hdmi_id id;
> +
>         struct hdmi_data_info hdmi_data;
>         const struct dw_hdmi_plat_data *plat_data;
>
> @@ -1259,6 +1278,36 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>         return 0;
>  }
>
> +static void hdmi_parse_id(struct dw_hdmi *hdmi)
> +{
> +       u8 config0_id, config1_id, config2_id, config3_id;
> +
> +       config0_id = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
> +       config1_id = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
> +       config2_id = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
> +       config3_id = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
> +
> +       hdmi->id.prepen = config0_id & HDMI_CONFIG0_ID_PREPEN ? true : false;

These could all be "!!(A & B)", but perhaps that is just a matter of
personal preference.

> +       hdmi->id.audi2s = config0_id & HDMI_CONFIG0_ID_AUDI2S ? true : false;
> +       hdmi->id.hdmi14 = config0_id & HDMI_CONFIG0_ID_HDMI14 ? true : false;
> +       hdmi->id.hdcp = config0_id & HDMI_CONFIG0_ID_HDCP ? true : false;
> +       hdmi->id.csc = config0_id & HDMI_CONFIG0_ID_CSC ? true : false;
> +       hdmi->id.audspdif = config0_id & HDMI_CONFIG0_ID_AUDSPDIF ?
> +                           true : false;
> +
> +       hdmi->id.confapb = config1_id & HDMI_CONFIG1_ID_CONFAPB ? true : false;
> +       hdmi->id.hdmi20 = config1_id & HDMI_CONFIG1_ID_HDMI20 ? true : false;
> +
> +       hdmi->id.phy_type = config2_id & HDMI_CONFIG2_ID;

HDMI_CONFIG2_ID is a register offset, not a mask.

> +
> +       hdmi->id.gpaud = config3_id & HDMI_CONFIG3_ID_GPAUD ? true : false;
> +       hdmi->id.ahbauddma = config3_id & HDMI_CONFIG3_ID_AHBAUDDMA ?
> +                            true : false;
> +
> +       hdmi->id.design = hdmi_readb(hdmi, HDMI_DESIGN_ID);
> +       hdmi->id.revision = hdmi_readb(hdmi, HDMI_REVISION_ID);
> +}
> +
>  /* Wait until we are registered to enable interrupts */
>  static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
>  {
> @@ -1670,6 +1719,16 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>                  hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
>                  hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
>
> +       /* Config IDs */
> +       dev_info(dev,
> +                "Detected HDMI config_id 0x%x:0x%x:0x%x:0x%x\n",
> +                hdmi_readb(hdmi, HDMI_CONFIG0_ID),
> +                hdmi_readb(hdmi, HDMI_CONFIG1_ID),
> +                hdmi_readb(hdmi, HDMI_CONFIG2_ID),
> +                hdmi_readb(hdmi, HDMI_CONFIG3_ID));
> +
> +       hdmi_parse_id(hdmi);

It seems a bit silly to read the regs once to print them, and then
again in hdmi_parse_id().
Perhaps move the dev_info() inside hdmi_parse_id().
It would also be nice to print a full summary of all of the parsed fields.

> +
>         initialize_hdmi_ih_mutes(hdmi);
>
>         ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
> index 175dbc8..e4ba634 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.h
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.h
> @@ -545,6 +545,29 @@
>  #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
>
>  enum {
> +/* HDMI_CONFIG0_ID */
> +       HDMI_CONFIG0_ID_PREPEN = 0x80,
> +       HDMI_CONFIG0_ID_AUDSPDIF = 0x20,
> +       HDMI_CONFIG0_ID_AUDI2S = 0x10,
> +       HDMI_CONFIG0_ID_HDMI14 = 0x08,
> +       HDMI_CONFIG0_ID_CSC = 0x04,
> +       HDMI_CONFIG0_ID_HDCP = 0x01,
> +
> +/* HDMI_CONFIG1_ID */
> +       HDMI_CONFIG1_ID_HDMI20 = 0x20,
> +       HDMI_CONFIG1_ID_CONFAPB = 0x02,
> +
> +/* HDMI_CONFIG2_ID */
> +       HDMI_CONFIG2_ID_PHY_GEN2 = 0xf2,
> +       HDMI_CONFIG2_ID_PHY_GEN2_HECA = 0xe2,
> +       HDMI_CONFIG2_ID_PHY_HDMI_MHL = 0xc2,
> +       HDMI_CONFIG2_ID_PHY_HDMI_MHL_HECA = 0xb2,
> +       HDMI_CONFIG2_ID_LEGACY_PHY = 0x00,
> +
> +/* HDMI_CONFIG3_ID */
> +       HDMI_CONFIG3_ID_AHBAUDDMA = 0x02,
> +       HDMI_CONFIG3_ID_GPAUD = 0x01,
> +
>  /* IH_FC_INT2 field values */
>         HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
>         HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
> --
> 2.1.2
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
  2015-02-03 15:12 ` [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts() Yakir Yang
@ 2015-02-05 15:54   ` Daniel Kurtz
  2015-02-07  3:33     ` yakir
  0 siblings, 1 reply; 20+ messages in thread
From: Daniel Kurtz @ 2015-02-05 15:54 UTC (permalink / raw)
  To: Yakir Yang
  Cc: David Airlie, Russell King, Philipp Zabel, Fabio Estevam,
	Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter, dri-devel,
	linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha, Ben Zhang,
	alsa-devel, Heiko Stuebner, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND...,
	Heiko Stübner, Douglas Anderson, Stéphane Marchesin,
	open list:ARM/Rockchip SoC...

On Tue, Feb 3, 2015 at 11:12 PM, Yakir Yang <ykk@rock-chips.com> wrote:
> Signed-off-by: Yakir Yang <ykk@rock-chips.com>

Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>

> ---
> Changes in v3:
> - Combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
>
> Changes in v2: None
>
>  drivers/gpu/drm/bridge/dw_hdmi.c | 16 ++++++----------
>  1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 7b5b664..262163f 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -196,19 +196,16 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
>         hdmi_modb(hdmi, data << shift, mask, reg);
>  }
>
> -static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi,
> -                                        unsigned int value)
> +static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
> +                                      unsigned int n, unsigned int cts)
>  {
> -       hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
> -       hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
> -       hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
> +       hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
> +       hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
> +       hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
>
>         /* nshift factor = 0 */
>         hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
> -}
>
> -static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts)
> -{
>         /* Must be set/cleared first */
>         hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
>
> @@ -374,8 +371,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>                 __func__, hdmi->sample_rate, hdmi->ratio,
>                 pixel_clk, clk_n, clk_cts);
>
> -       hdmi_set_clock_regenerator_n(hdmi, clk_n);
> -       hdmi_regenerate_cts(hdmi, clk_cts);
> +       hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
>  }
>
>  static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> --
> 2.1.2
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
  2015-02-05 15:54   ` Daniel Kurtz
@ 2015-02-07  3:33     ` yakir
  0 siblings, 0 replies; 20+ messages in thread
From: yakir @ 2015-02-07  3:33 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: David Airlie, Russell King, Philipp Zabel, Fabio Estevam,
	Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter, dri-devel,
	linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha, Ben Zhang,
	alsa-devel, Heiko Stuebner, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND...,
	Heiko Stübner, Douglas Anderson, Stéphane Marchesin,
	open list:ARM/Rockchip SoC...


On 02/05/2015 11:54 PM, Daniel Kurtz wrote:
> On Tue, Feb 3, 2015 at 11:12 PM, Yakir Yang <ykk@rock-chips.com> wrote:
>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>

Okay, add in next verson4.

Thanks.  : )
>
>> ---
>> Changes in v3:
>> - Combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/bridge/dw_hdmi.c | 16 ++++++----------
>>   1 file changed, 6 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
>> index 7b5b664..262163f 100644
>> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
>> @@ -196,19 +196,16 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
>>          hdmi_modb(hdmi, data << shift, mask, reg);
>>   }
>>
>> -static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi,
>> -                                        unsigned int value)
>> +static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi,
>> +                                      unsigned int n, unsigned int cts)
>>   {
>> -       hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
>> -       hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
>> -       hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
>> +       hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
>> +       hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
>> +       hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
>>
>>          /* nshift factor = 0 */
>>          hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
>> -}
>>
>> -static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts)
>> -{
>>          /* Must be set/cleared first */
>>          hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
>>
>> @@ -374,8 +371,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>>                  __func__, hdmi->sample_rate, hdmi->ratio,
>>                  pixel_clk, clk_n, clk_cts);
>>
>> -       hdmi_set_clock_regenerator_n(hdmi, clk_n);
>> -       hdmi_regenerate_cts(hdmi, clk_cts);
>> +       hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
>>   }
>>
>>   static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>> --
>> 2.1.2
>>
>>
>
>



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record
  2015-02-05 15:46   ` Daniel Kurtz
@ 2015-02-07  3:33     ` yakir
  0 siblings, 0 replies; 20+ messages in thread
From: yakir @ 2015-02-07  3:33 UTC (permalink / raw)
  To: Daniel Kurtz
  Cc: David Airlie, Russell King, Philipp Zabel, Fabio Estevam,
	Shawn Guo, Rob Clark, Mark Yao, Daniel Vetter, dri-devel,
	linux-kernel, Arnd Bergmann, Sean Cross, Jyri Sarha, Ben Zhang,
	alsa-devel, Heiko Stuebner, linux-arm-kernel, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	open list:OPEN FIRMWARE AND...,
	Heiko Stübner, Douglas Anderson, Stéphane Marchesin,
	open list:ARM/Rockchip SoC...


On 02/05/2015 11:46 PM, Daniel Kurtz wrote:
> On Tue, Feb 3, 2015 at 11:11 PM, Yakir Yang <ykk@rock-chips.com> wrote:
>> By parsing the indentification registers we can know what functions
>> are present on the hdmi ip.
>>
>> Signed-off-by: Yakir Yang <ykk@rock-chips.com>
>> ---
>> Changes in v3:
>> - Add ID registers parse and record
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/bridge/dw_hdmi.c | 59 ++++++++++++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/bridge/dw_hdmi.h | 23 ++++++++++++++++
>>   2 files changed, 82 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
>> index 08f10da..7b5b664 100644
>> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
>> @@ -79,6 +79,23 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
>>          { 0x6756, 0x78ab, 0x2000, 0x0200 }
>>   };
>>
>> +struct hdmi_id {
>> +       u8 design;
>> +       u8 revision;
>> +
>> +       bool prepen;
>> +       bool audspdif;
>> +       bool audi2s;
>> +       bool hdmi14;
>> +       bool csc;
>> +       bool hdcp;
>> +       bool hdmi20;
>> +       bool confapb;
>> +       bool ahbauddma;
>> +       bool gpaud;
>> +       u8 phy_type;
>> +};
>> +
>>   struct hdmi_vmode {
>>          bool mdvi;
>>          bool mhsyncpolarity;
>> @@ -111,6 +128,8 @@ struct dw_hdmi {
>>          struct clk *isfr_clk;
>>          struct clk *iahb_clk;
>>
>> +       struct hdmi_id id;
>> +
>>          struct hdmi_data_info hdmi_data;
>>          const struct dw_hdmi_plat_data *plat_data;
>>
>> @@ -1259,6 +1278,36 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>          return 0;
>>   }
>>
>> +static void hdmi_parse_id(struct dw_hdmi *hdmi)
>> +{
>> +       u8 config0_id, config1_id, config2_id, config3_id;
>> +
>> +       config0_id = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
>> +       config1_id = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
>> +       config2_id = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
>> +       config3_id = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
>> +
>> +       hdmi->id.prepen = config0_id & HDMI_CONFIG0_ID_PREPEN ? true : false;
> These could all be "!!(A & B)", but perhaps that is just a matter of
> personal preference.
Okay, "!!(A & B)" looks good, I will modify it.

Thanks.  : )
>> +       hdmi->id.audi2s = config0_id & HDMI_CONFIG0_ID_AUDI2S ? true : false;
>> +       hdmi->id.hdmi14 = config0_id & HDMI_CONFIG0_ID_HDMI14 ? true : false;
>> +       hdmi->id.hdcp = config0_id & HDMI_CONFIG0_ID_HDCP ? true : false;
>> +       hdmi->id.csc = config0_id & HDMI_CONFIG0_ID_CSC ? true : false;
>> +       hdmi->id.audspdif = config0_id & HDMI_CONFIG0_ID_AUDSPDIF ?
>> +                           true : false;
>> +
>> +       hdmi->id.confapb = config1_id & HDMI_CONFIG1_ID_CONFAPB ? true : false;
>> +       hdmi->id.hdmi20 = config1_id & HDMI_CONFIG1_ID_HDMI20 ? true : false;
>> +
>> +       hdmi->id.phy_type = config2_id & HDMI_CONFIG2_ID;
> HDMI_CONFIG2_ID is a register offset, not a mask.

Thanks, I will correct it.

>> +
>> +       hdmi->id.gpaud = config3_id & HDMI_CONFIG3_ID_GPAUD ? true : false;
>> +       hdmi->id.ahbauddma = config3_id & HDMI_CONFIG3_ID_AHBAUDDMA ?
>> +                            true : false;
>> +
>> +       hdmi->id.design = hdmi_readb(hdmi, HDMI_DESIGN_ID);
>> +       hdmi->id.revision = hdmi_readb(hdmi, HDMI_REVISION_ID);
>> +}
>> +
>>   /* Wait until we are registered to enable interrupts */
>>   static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
>>   {
>> @@ -1670,6 +1719,16 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>>                   hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
>>                   hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
>>
>> +       /* Config IDs */
>> +       dev_info(dev,
>> +                "Detected HDMI config_id 0x%x:0x%x:0x%x:0x%x\n",
>> +                hdmi_readb(hdmi, HDMI_CONFIG0_ID),
>> +                hdmi_readb(hdmi, HDMI_CONFIG1_ID),
>> +                hdmi_readb(hdmi, HDMI_CONFIG2_ID),
>> +                hdmi_readb(hdmi, HDMI_CONFIG3_ID));
>> +
>> +       hdmi_parse_id(hdmi);
> It seems a bit silly to read the regs once to print them, and then
> again in hdmi_parse_id().
> Perhaps move the dev_info() inside hdmi_parse_id().
> It would also be nice to print a full summary of all of the parsed fields.
Okay, I will warp them into hdmi_parse_id().

Thanks.  : )

>> +
>>          initialize_hdmi_ih_mutes(hdmi);
>>
>>          ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
>> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
>> index 175dbc8..e4ba634 100644
>> --- a/drivers/gpu/drm/bridge/dw_hdmi.h
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi.h
>> @@ -545,6 +545,29 @@
>>   #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
>>
>>   enum {
>> +/* HDMI_CONFIG0_ID */
>> +       HDMI_CONFIG0_ID_PREPEN = 0x80,
>> +       HDMI_CONFIG0_ID_AUDSPDIF = 0x20,
>> +       HDMI_CONFIG0_ID_AUDI2S = 0x10,
>> +       HDMI_CONFIG0_ID_HDMI14 = 0x08,
>> +       HDMI_CONFIG0_ID_CSC = 0x04,
>> +       HDMI_CONFIG0_ID_HDCP = 0x01,
>> +
>> +/* HDMI_CONFIG1_ID */
>> +       HDMI_CONFIG1_ID_HDMI20 = 0x20,
>> +       HDMI_CONFIG1_ID_CONFAPB = 0x02,
>> +
>> +/* HDMI_CONFIG2_ID */
>> +       HDMI_CONFIG2_ID_PHY_GEN2 = 0xf2,
>> +       HDMI_CONFIG2_ID_PHY_GEN2_HECA = 0xe2,
>> +       HDMI_CONFIG2_ID_PHY_HDMI_MHL = 0xc2,
>> +       HDMI_CONFIG2_ID_PHY_HDMI_MHL_HECA = 0xb2,
>> +       HDMI_CONFIG2_ID_LEGACY_PHY = 0x00,
>> +
>> +/* HDMI_CONFIG3_ID */
>> +       HDMI_CONFIG3_ID_AHBAUDDMA = 0x02,
>> +       HDMI_CONFIG3_ID_GPAUD = 0x01,
>> +
>>   /* IH_FC_INT2 field values */
>>          HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
>>          HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
>> --
>> 2.1.2
>>
>>
>
>



^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2015-02-07  3:33 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-03 14:56 [PATCH v3 0/15] Those patches is used for dw_hdmi audio support Yakir Yang
2015-02-03 15:01 ` [PATCH v3 01/15] drm: bridge/dw_hdmi: add irq control to suspend/resume Yakir Yang
2015-02-03 15:02 ` [PATCH v3 02/15] drm: bridge/dw_hdmi: wrap irq control in fucntions Yakir Yang
2015-02-03 15:08 ` [PATCH v3 03/15] drm: rockchip/dw_hdmi_rockchip: add resume/suspend support Yakir Yang
2015-02-03 15:11 ` [PATCH v3 04/15] drm: bridge/dw_hdmi: add indentification registers parse and record Yakir Yang
2015-02-05 15:46   ` Daniel Kurtz
2015-02-07  3:33     ` yakir
2015-02-03 15:12 ` [PATCH v3 05/15] drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts() Yakir Yang
2015-02-05 15:54   ` Daniel Kurtz
2015-02-07  3:33     ` yakir
2015-02-03 15:13 ` [PATCH v3 06/15] drm: bridge/dw_hdmi: adjust n/cts setting order Yakir Yang
2015-02-03 15:13 ` [PATCH v3 07/15] drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual Yakir Yang
2015-02-03 15:14 ` [PATCH v3 08/15] drm: bridge/dw_hdmi: add audio support for more display resolutions Yakir Yang
2015-02-03 15:15 ` [PATCH v3 09/15] drm: bridge/dw_hdmi: enable audio support for No-CEA " Yakir Yang
2015-02-03 15:16 ` [PATCH v3 10/15] drm: bridge/dw_hdmi: add audio sample channel status setting Yakir Yang
2015-02-03 15:16 ` [PATCH v3 11/15] drm: bridge/dw_hdmi: add audio clock control interfaces Yakir Yang
2015-02-03 15:17 ` [PATCH v3 12/15] drm: bridge/dw_hdmi: creat dw-hdmi-audio platform device Yakir Yang
2015-02-03 15:18 ` [PATCH v3 13/15] ASoC: dw-hdmi-audio: add codec driver for dw hdmi audio Yakir Yang
2015-02-03 15:19 ` [PATCH v3 14/15] ASoC: rockchip-hdmi-audio: add sound driver for " Yakir Yang
2015-02-03 15:19 ` [PATCH v3 15/15] dt-bindings: Add documentation for Rockchip dw-hdmi-audio Yakir Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).