aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-09-12 20:28:17 -0400
committerDave Airlie <airlied@redhat.com>2016-09-12 20:28:17 -0400
commit8506912b969b60aacc733315eeeb46b014d920a4 (patch)
tree42a786a5e6d20470f9eec8cd2614d9e827505a9c
parentb4eac5465b23a9bcb4a66376a5664086b4913288 (diff)
parentdf0bd1e8f3c508bf4c3445f94b12e38289b65f13 (diff)
Merge branch 'drm-tda998x-devel' of git://git.armlinux.org.uk/~rmk/linux-arm into drm-next
This adds the ASoC codec interfaces for TDA998x HDMI audio from Jyri Sarha. * 'drm-tda998x-devel' of git://git.armlinux.org.uk/~rmk/linux-arm: ARM: dts: am335x-boneblack: Add HDMI audio support drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata
-rw-r--r--Documentation/devicetree/bindings/display/bridge/tda998x.txt18
-rw-r--r--arch/arm/boot/dts/am335x-boneblack.dts71
-rw-r--r--drivers/gpu/drm/i2c/Kconfig1
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c297
-rw-r--r--include/drm/i2c/tda998x.h29
-rw-r--r--include/dt-bindings/display/tda998x.h7
6 files changed, 368 insertions, 55 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/tda998x.txt b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
index e178e6b9f9ee..24cc2466185a 100644
--- a/Documentation/devicetree/bindings/display/bridge/tda998x.txt
+++ b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
@@ -21,8 +21,19 @@ Optional properties:
21 - video-ports: 24 bits value which defines how the video controller 21 - video-ports: 24 bits value which defines how the video controller
22 output is wired to the TDA998x input - default: <0x230145> 22 output is wired to the TDA998x input - default: <0x230145>
23 23
24 - audio-ports: array of 8-bit values, 2 values per one DAI[1].
25 The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2].
26 The second value defines the tda998x AP_ENA reg content when the DAI
27 in question is used. The implementation allows one or two DAIs. If two
28 DAIs are defined, they must be of different type.
29
30[1] Documentation/sound/alsa/soc/DAI.txt
31[2] include/dt-bindings/display/tda998x.h
32
24Example: 33Example:
25 34
35#include <dt-bindings/display/tda998x.h>
36
26 tda998x: hdmi-encoder { 37 tda998x: hdmi-encoder {
27 compatible = "nxp,tda998x"; 38 compatible = "nxp,tda998x";
28 reg = <0x70>; 39 reg = <0x70>;
@@ -30,4 +41,11 @@ Example:
30 interrupts = <27 2>; /* falling edge */ 41 interrupts = <27 2>; /* falling edge */
31 pinctrl-0 = <&pmx_camera>; 42 pinctrl-0 = <&pmx_camera>;
32 pinctrl-names = "default"; 43 pinctrl-names = "default";
44 video-ports = <0x230145>;
45
46 #sound-dai-cells = <2>;
47 /* DAI-format AP_ENA reg value */
48 audio-ports = < TDA998x_SPDIF 0x04
49 TDA998x_I2S 0x03>;
50
33 }; 51 };
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index ca721670bd91..528559b33d8a 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -9,6 +9,7 @@
9 9
10#include "am33xx.dtsi" 10#include "am33xx.dtsi"
11#include "am335x-bone-common.dtsi" 11#include "am335x-bone-common.dtsi"
12#include <dt-bindings/display/tda998x.h>
12 13
13/ { 14/ {
14 model = "TI AM335x BeagleBone Black"; 15 model = "TI AM335x BeagleBone Black";
@@ -75,6 +76,16 @@
75 AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */ 76 AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
76 >; 77 >;
77 }; 78 };
79
80 mcasp0_pins: mcasp0_pins {
81 pinctrl-single,pins = <
82 AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
83 AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
84 AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
85 AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
86 AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
87 >;
88 };
78}; 89};
79 90
80&lcdc { 91&lcdc {
@@ -87,16 +98,22 @@
87}; 98};
88 99
89&i2c0 { 100&i2c0 {
90 tda19988 { 101 tda19988: tda19988 {
91 compatible = "nxp,tda998x"; 102 compatible = "nxp,tda998x";
92 reg = <0x70>; 103 reg = <0x70>;
104
93 pinctrl-names = "default", "off"; 105 pinctrl-names = "default", "off";
94 pinctrl-0 = <&nxp_hdmi_bonelt_pins>; 106 pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
95 pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; 107 pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
96 108
97 port { 109 #sound-dai-cells = <0>;
98 hdmi_0: endpoint@0 { 110 audio-ports = < TDA998x_I2S 0x03>;
99 remote-endpoint = <&lcdc_0>; 111
112 ports {
113 port@0 {
114 hdmi_0: endpoint@0 {
115 remote-endpoint = <&lcdc_0>;
116 };
100 }; 117 };
101 }; 118 };
102 }; 119 };
@@ -105,3 +122,49 @@
105&rtc { 122&rtc {
106 system-power-controller; 123 system-power-controller;
107}; 124};
125
126&mcasp0 {
127 #sound-dai-cells = <0>;
128 pinctrl-names = "default";
129 pinctrl-0 = <&mcasp0_pins>;
130 status = "okay";
131 op-mode = <0>; /* MCASP_IIS_MODE */
132 tdm-slots = <2>;
133 serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
134 0 0 1 0
135 >;
136 tx-num-evt = <32>;
137 rx-num-evt = <32>;
138};
139
140/ {
141 clk_mcasp0_fixed: clk_mcasp0_fixed {
142 #clock-cells = <0>;
143 compatible = "fixed-clock";
144 clock-frequency = <24576000>;
145 };
146
147 clk_mcasp0: clk_mcasp0 {
148 #clock-cells = <0>;
149 compatible = "gpio-gate-clock";
150 clocks = <&clk_mcasp0_fixed>;
151 enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
152 };
153
154 sound {
155 compatible = "simple-audio-card";
156 simple-audio-card,name = "TI BeagleBone Black";
157 simple-audio-card,format = "i2s";
158 simple-audio-card,bitclock-master = <&dailink0_master>;
159 simple-audio-card,frame-master = <&dailink0_master>;
160
161 dailink0_master: simple-audio-card,cpu {
162 sound-dai = <&mcasp0>;
163 clocks = <&clk_mcasp0>;
164 };
165
166 simple-audio-card,codec {
167 sound-dai = <&tda19988>;
168 };
169 };
170};
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 4d341db462a2..a6c92beb410a 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -22,6 +22,7 @@ config DRM_I2C_SIL164
22config DRM_I2C_NXP_TDA998X 22config DRM_I2C_NXP_TDA998X
23 tristate "NXP Semiconductors TDA998X HDMI encoder" 23 tristate "NXP Semiconductors TDA998X HDMI encoder"
24 default m if DRM_TILCDC 24 default m if DRM_TILCDC
25 select SND_SOC_HDMI_CODEC if SND_SOC
25 help 26 help
26 Support for NXP Semiconductors TDA998X HDMI encoders. 27 Support for NXP Semiconductors TDA998X HDMI encoders.
27 28
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index f4315bc8d471..9798d400d817 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -20,6 +20,7 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <sound/asoundef.h> 22#include <sound/asoundef.h>
23#include <sound/hdmi-codec.h>
23 24
24#include <drm/drmP.h> 25#include <drm/drmP.h>
25#include <drm/drm_atomic_helper.h> 26#include <drm/drm_atomic_helper.h>
@@ -30,6 +31,11 @@
30 31
31#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 32#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
32 33
34struct tda998x_audio_port {
35 u8 format; /* AFMT_xxx */
36 u8 config; /* AP value */
37};
38
33struct tda998x_priv { 39struct tda998x_priv {
34 struct i2c_client *cec; 40 struct i2c_client *cec;
35 struct i2c_client *hdmi; 41 struct i2c_client *hdmi;
@@ -41,7 +47,10 @@ struct tda998x_priv {
41 u8 vip_cntrl_0; 47 u8 vip_cntrl_0;
42 u8 vip_cntrl_1; 48 u8 vip_cntrl_1;
43 u8 vip_cntrl_2; 49 u8 vip_cntrl_2;
44 struct tda998x_encoder_params params; 50 struct tda998x_audio_params audio_params;
51
52 struct platform_device *audio_pdev;
53 struct mutex audio_mutex;
45 54
46 wait_queue_head_t wq_edid; 55 wait_queue_head_t wq_edid;
47 volatile int wq_edid_wait; 56 volatile int wq_edid_wait;
@@ -53,6 +62,8 @@ struct tda998x_priv {
53 62
54 struct drm_encoder encoder; 63 struct drm_encoder encoder;
55 struct drm_connector connector; 64 struct drm_connector connector;
65
66 struct tda998x_audio_port audio_port[2];
56}; 67};
57 68
58#define conn_to_tda998x_priv(x) \ 69#define conn_to_tda998x_priv(x) \
@@ -666,26 +677,16 @@ tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
666 reg_set(priv, REG_DIP_IF_FLAGS, bit); 677 reg_set(priv, REG_DIP_IF_FLAGS, bit);
667} 678}
668 679
669static void 680static int tda998x_write_aif(struct tda998x_priv *priv,
670tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) 681 struct hdmi_audio_infoframe *cea)
671{ 682{
672 union hdmi_infoframe frame; 683 union hdmi_infoframe frame;
673 684
674 hdmi_audio_infoframe_init(&frame.audio); 685 frame.audio = *cea;
675
676 frame.audio.channels = p->audio_frame[1] & 0x07;
677 frame.audio.channel_allocation = p->audio_frame[4];
678 frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3;
679 frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7;
680
681 /*
682 * L-PCM and IEC61937 compressed audio shall always set sample
683 * frequency to "refer to stream". For others, see the HDMI
684 * specification.
685 */
686 frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2;
687 686
688 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame); 687 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
688
689 return 0;
689} 690}
690 691
691static void 692static void
@@ -710,20 +711,21 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
710 } 711 }
711} 712}
712 713
713static void 714static int
714tda998x_configure_audio(struct tda998x_priv *priv, 715tda998x_configure_audio(struct tda998x_priv *priv,
715 struct drm_display_mode *mode, struct tda998x_encoder_params *p) 716 struct tda998x_audio_params *params,
717 unsigned mode_clock)
716{ 718{
717 u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv; 719 u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
718 u32 n; 720 u32 n;
719 721
720 /* Enable audio ports */ 722 /* Enable audio ports */
721 reg_write(priv, REG_ENA_AP, p->audio_cfg); 723 reg_write(priv, REG_ENA_AP, params->config);
722 reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
723 724
724 /* Set audio input source */ 725 /* Set audio input source */
725 switch (p->audio_format) { 726 switch (params->format) {
726 case AFMT_SPDIF: 727 case AFMT_SPDIF:
728 reg_write(priv, REG_ENA_ACLK, 0);
727 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF); 729 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
728 clksel_aip = AIP_CLKSEL_AIP_SPDIF; 730 clksel_aip = AIP_CLKSEL_AIP_SPDIF;
729 clksel_fs = AIP_CLKSEL_FS_FS64SPDIF; 731 clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
@@ -731,15 +733,29 @@ tda998x_configure_audio(struct tda998x_priv *priv,
731 break; 733 break;
732 734
733 case AFMT_I2S: 735 case AFMT_I2S:
736 reg_write(priv, REG_ENA_ACLK, 1);
734 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); 737 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
735 clksel_aip = AIP_CLKSEL_AIP_I2S; 738 clksel_aip = AIP_CLKSEL_AIP_I2S;
736 clksel_fs = AIP_CLKSEL_FS_ACLK; 739 clksel_fs = AIP_CLKSEL_FS_ACLK;
737 cts_n = CTS_N_M(3) | CTS_N_K(3); 740 switch (params->sample_width) {
741 case 16:
742 cts_n = CTS_N_M(3) | CTS_N_K(1);
743 break;
744 case 18:
745 case 20:
746 case 24:
747 cts_n = CTS_N_M(3) | CTS_N_K(2);
748 break;
749 default:
750 case 32:
751 cts_n = CTS_N_M(3) | CTS_N_K(3);
752 break;
753 }
738 break; 754 break;
739 755
740 default: 756 default:
741 BUG(); 757 dev_err(&priv->hdmi->dev, "Unsupported I2S format\n");
742 return; 758 return -EINVAL;
743 } 759 }
744 760
745 reg_write(priv, REG_AIP_CLKSEL, clksel_aip); 761 reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
@@ -755,11 +771,11 @@ tda998x_configure_audio(struct tda998x_priv *priv,
755 * assume 100MHz requires larger divider. 771 * assume 100MHz requires larger divider.
756 */ 772 */
757 adiv = AUDIO_DIV_SERCLK_8; 773 adiv = AUDIO_DIV_SERCLK_8;
758 if (mode->clock > 100000) 774 if (mode_clock > 100000)
759 adiv++; /* AUDIO_DIV_SERCLK_16 */ 775 adiv++; /* AUDIO_DIV_SERCLK_16 */
760 776
761 /* S/PDIF asks for a larger divider */ 777 /* S/PDIF asks for a larger divider */
762 if (p->audio_format == AFMT_SPDIF) 778 if (params->format == AFMT_SPDIF)
763 adiv++; /* AUDIO_DIV_SERCLK_16 or _32 */ 779 adiv++; /* AUDIO_DIV_SERCLK_16 or _32 */
764 780
765 reg_write(priv, REG_AUDIO_DIV, adiv); 781 reg_write(priv, REG_AUDIO_DIV, adiv);
@@ -768,7 +784,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
768 * This is the approximate value of N, which happens to be 784 * This is the approximate value of N, which happens to be
769 * the recommended values for non-coherent clocks. 785 * the recommended values for non-coherent clocks.
770 */ 786 */
771 n = 128 * p->audio_sample_rate / 1000; 787 n = 128 * params->sample_rate / 1000;
772 788
773 /* Write the CTS and N values */ 789 /* Write the CTS and N values */
774 buf[0] = 0x44; 790 buf[0] = 0x44;
@@ -786,20 +802,21 @@ tda998x_configure_audio(struct tda998x_priv *priv,
786 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 802 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
787 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 803 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
788 804
789 /* Write the channel status */ 805 /* Write the channel status
790 buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT; 806 * The REG_CH_STAT_B-registers skip IEC958 AES2 byte, because
791 buf[1] = 0x00; 807 * there is a separate register for each I2S wire.
792 buf[2] = IEC958_AES3_CON_FS_NOTID; 808 */
793 buf[3] = IEC958_AES4_CON_ORIGFS_NOTID | 809 buf[0] = params->status[0];
794 IEC958_AES4_CON_MAX_WORDLEN_24; 810 buf[1] = params->status[1];
811 buf[2] = params->status[3];
812 buf[3] = params->status[4];
795 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4); 813 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
796 814
797 tda998x_audio_mute(priv, true); 815 tda998x_audio_mute(priv, true);
798 msleep(20); 816 msleep(20);
799 tda998x_audio_mute(priv, false); 817 tda998x_audio_mute(priv, false);
800 818
801 /* Write the audio information packet */ 819 return tda998x_write_aif(priv, &params->cea);
802 tda998x_write_aif(priv, p);
803} 820}
804 821
805/* DRM encoder functions */ 822/* DRM encoder functions */
@@ -820,7 +837,7 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,
820 VIP_CNTRL_2_SWAP_F(p->swap_f) | 837 VIP_CNTRL_2_SWAP_F(p->swap_f) |
821 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); 838 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
822 839
823 priv->params = *p; 840 priv->audio_params = p->audio_params;
824} 841}
825 842
826static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) 843static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
@@ -1057,9 +1074,13 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
1057 1074
1058 tda998x_write_avi(priv, adjusted_mode); 1075 tda998x_write_avi(priv, adjusted_mode);
1059 1076
1060 if (priv->params.audio_cfg) 1077 if (priv->audio_params.format != AFMT_UNUSED) {
1061 tda998x_configure_audio(priv, adjusted_mode, 1078 mutex_lock(&priv->audio_mutex);
1062 &priv->params); 1079 tda998x_configure_audio(priv,
1080 &priv->audio_params,
1081 adjusted_mode->clock);
1082 mutex_unlock(&priv->audio_mutex);
1083 }
1063 } 1084 }
1064} 1085}
1065 1086
@@ -1159,6 +1180,8 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
1159 drm_mode_connector_update_edid_property(connector, edid); 1180 drm_mode_connector_update_edid_property(connector, edid);
1160 n = drm_add_edid_modes(connector, edid); 1181 n = drm_add_edid_modes(connector, edid);
1161 priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); 1182 priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
1183 drm_edid_to_eld(connector, edid);
1184
1162 kfree(edid); 1185 kfree(edid);
1163 1186
1164 return n; 1187 return n;
@@ -1180,6 +1203,9 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1180 cec_write(priv, REG_CEC_RXSHPDINTENA, 0); 1203 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1181 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 1204 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1182 1205
1206 if (priv->audio_pdev)
1207 platform_device_unregister(priv->audio_pdev);
1208
1183 if (priv->hdmi->irq) 1209 if (priv->hdmi->irq)
1184 free_irq(priv->hdmi->irq, priv); 1210 free_irq(priv->hdmi->irq, priv);
1185 1211
@@ -1189,8 +1215,189 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1189 i2c_unregister_device(priv->cec); 1215 i2c_unregister_device(priv->cec);
1190} 1216}
1191 1217
1218static int tda998x_audio_hw_params(struct device *dev, void *data,
1219 struct hdmi_codec_daifmt *daifmt,
1220 struct hdmi_codec_params *params)
1221{
1222 struct tda998x_priv *priv = dev_get_drvdata(dev);
1223 int i, ret;
1224 struct tda998x_audio_params audio = {
1225 .sample_width = params->sample_width,
1226 .sample_rate = params->sample_rate,
1227 .cea = params->cea,
1228 };
1229
1230 if (!priv->encoder.crtc)
1231 return -ENODEV;
1232
1233 memcpy(audio.status, params->iec.status,
1234 min(sizeof(audio.status), sizeof(params->iec.status)));
1235
1236 switch (daifmt->fmt) {
1237 case HDMI_I2S:
1238 if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
1239 daifmt->bit_clk_master || daifmt->frame_clk_master) {
1240 dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1241 daifmt->bit_clk_inv, daifmt->frame_clk_inv,
1242 daifmt->bit_clk_master,
1243 daifmt->frame_clk_master);
1244 return -EINVAL;
1245 }
1246 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
1247 if (priv->audio_port[i].format == AFMT_I2S)
1248 audio.config = priv->audio_port[i].config;
1249 audio.format = AFMT_I2S;
1250 break;
1251 case HDMI_SPDIF:
1252 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
1253 if (priv->audio_port[i].format == AFMT_SPDIF)
1254 audio.config = priv->audio_port[i].config;
1255 audio.format = AFMT_SPDIF;
1256 break;
1257 default:
1258 dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
1259 return -EINVAL;
1260 }
1261
1262 if (audio.config == 0) {
1263 dev_err(dev, "%s: No audio configutation found\n", __func__);
1264 return -EINVAL;
1265 }
1266
1267 mutex_lock(&priv->audio_mutex);
1268 ret = tda998x_configure_audio(priv,
1269 &audio,
1270 priv->encoder.crtc->hwmode.clock);
1271
1272 if (ret == 0)
1273 priv->audio_params = audio;
1274 mutex_unlock(&priv->audio_mutex);
1275
1276 return ret;
1277}
1278
1279static void tda998x_audio_shutdown(struct device *dev, void *data)
1280{
1281 struct tda998x_priv *priv = dev_get_drvdata(dev);
1282
1283 mutex_lock(&priv->audio_mutex);
1284
1285 reg_write(priv, REG_ENA_AP, 0);
1286
1287 priv->audio_params.format = AFMT_UNUSED;
1288
1289 mutex_unlock(&priv->audio_mutex);
1290}
1291
1292int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
1293{
1294 struct tda998x_priv *priv = dev_get_drvdata(dev);
1295
1296 mutex_lock(&priv->audio_mutex);
1297
1298 tda998x_audio_mute(priv, enable);
1299
1300 mutex_unlock(&priv->audio_mutex);
1301 return 0;
1302}
1303
1304static int tda998x_audio_get_eld(struct device *dev, void *data,
1305 uint8_t *buf, size_t len)
1306{
1307 struct tda998x_priv *priv = dev_get_drvdata(dev);
1308 struct drm_mode_config *config = &priv->encoder.dev->mode_config;
1309 struct drm_connector *connector;
1310 int ret = -ENODEV;
1311
1312 mutex_lock(&config->mutex);
1313 list_for_each_entry(connector, &config->connector_list, head) {
1314 if (&priv->encoder == connector->encoder) {
1315 memcpy(buf, connector->eld,
1316 min(sizeof(connector->eld), len));
1317 ret = 0;
1318 }
1319 }
1320 mutex_unlock(&config->mutex);
1321
1322 return ret;
1323}
1324
1325static const struct hdmi_codec_ops audio_codec_ops = {
1326 .hw_params = tda998x_audio_hw_params,
1327 .audio_shutdown = tda998x_audio_shutdown,
1328 .digital_mute = tda998x_audio_digital_mute,
1329 .get_eld = tda998x_audio_get_eld,
1330};
1331
1332static int tda998x_audio_codec_init(struct tda998x_priv *priv,
1333 struct device *dev)
1334{
1335 struct hdmi_codec_pdata codec_data = {
1336 .ops = &audio_codec_ops,
1337 .max_i2s_channels = 2,
1338 };
1339 int i;
1340
1341 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
1342 if (priv->audio_port[i].format == AFMT_I2S &&
1343 priv->audio_port[i].config != 0)
1344 codec_data.i2s = 1;
1345 if (priv->audio_port[i].format == AFMT_SPDIF &&
1346 priv->audio_port[i].config != 0)
1347 codec_data.spdif = 1;
1348 }
1349
1350 priv->audio_pdev = platform_device_register_data(
1351 dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1352 &codec_data, sizeof(codec_data));
1353
1354 return PTR_ERR_OR_ZERO(priv->audio_pdev);
1355}
1356
1192/* I2C driver functions */ 1357/* I2C driver functions */
1193 1358
1359static int tda998x_get_audio_ports(struct tda998x_priv *priv,
1360 struct device_node *np)
1361{
1362 const u32 *port_data;
1363 u32 size;
1364 int i;
1365
1366 port_data = of_get_property(np, "audio-ports", &size);
1367 if (!port_data)
1368 return 0;
1369
1370 size /= sizeof(u32);
1371 if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
1372 dev_err(&priv->hdmi->dev,
1373 "Bad number of elements in audio-ports dt-property\n");
1374 return -EINVAL;
1375 }
1376
1377 size /= 2;
1378
1379 for (i = 0; i < size; i++) {
1380 u8 afmt = be32_to_cpup(&port_data[2*i]);
1381 u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
1382
1383 if (afmt != AFMT_SPDIF && afmt != AFMT_I2S) {
1384 dev_err(&priv->hdmi->dev,
1385 "Bad audio format %u\n", afmt);
1386 return -EINVAL;
1387 }
1388
1389 priv->audio_port[i].format = afmt;
1390 priv->audio_port[i].config = ena_ap;
1391 }
1392
1393 if (priv->audio_port[0].format == priv->audio_port[1].format) {
1394 dev_err(&priv->hdmi->dev,
1395 "There can only be on I2S port and one SPDIF port\n");
1396 return -EINVAL;
1397 }
1398 return 0;
1399}
1400
1194static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) 1401static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1195{ 1402{
1196 struct device_node *np = client->dev.of_node; 1403 struct device_node *np = client->dev.of_node;
@@ -1304,7 +1511,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1304 if (!np) 1511 if (!np)
1305 return 0; /* non-DT */ 1512 return 0; /* non-DT */
1306 1513
1307 /* get the optional video properties */ 1514 /* get the device tree parameters */
1308 ret = of_property_read_u32(np, "video-ports", &video); 1515 ret = of_property_read_u32(np, "video-ports", &video);
1309 if (ret == 0) { 1516 if (ret == 0) {
1310 priv->vip_cntrl_0 = video >> 16; 1517 priv->vip_cntrl_0 = video >> 16;
@@ -1312,8 +1519,16 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1312 priv->vip_cntrl_2 = video; 1519 priv->vip_cntrl_2 = video;
1313 } 1520 }
1314 1521
1315 return 0; 1522 mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
1316 1523
1524 ret = tda998x_get_audio_ports(priv, np);
1525 if (ret)
1526 goto fail;
1527
1528 if (priv->audio_port[0].format != AFMT_UNUSED)
1529 tda998x_audio_codec_init(priv, &client->dev);
1530
1531 return 0;
1317fail: 1532fail:
1318 /* if encoder_init fails, the encoder slave is never registered, 1533 /* if encoder_init fails, the encoder slave is never registered,
1319 * so cleanup here: 1534 * so cleanup here:
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 3e419d92cf5a..a25483090cd5 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -1,6 +1,24 @@
1#ifndef __DRM_I2C_TDA998X_H__ 1#ifndef __DRM_I2C_TDA998X_H__
2#define __DRM_I2C_TDA998X_H__ 2#define __DRM_I2C_TDA998X_H__
3 3
4#include <linux/hdmi.h>
5#include <dt-bindings/display/tda998x.h>
6
7enum {
8 AFMT_UNUSED = 0,
9 AFMT_SPDIF = TDA998x_SPDIF,
10 AFMT_I2S = TDA998x_I2S,
11};
12
13struct tda998x_audio_params {
14 u8 config;
15 u8 format;
16 unsigned sample_width;
17 unsigned sample_rate;
18 struct hdmi_audio_infoframe cea;
19 u8 status[5];
20};
21
4struct tda998x_encoder_params { 22struct tda998x_encoder_params {
5 u8 swap_b:3; 23 u8 swap_b:3;
6 u8 mirr_b:1; 24 u8 mirr_b:1;
@@ -15,16 +33,7 @@ struct tda998x_encoder_params {
15 u8 swap_e:3; 33 u8 swap_e:3;
16 u8 mirr_e:1; 34 u8 mirr_e:1;
17 35
18 u8 audio_cfg; 36 struct tda998x_audio_params audio_params;
19 u8 audio_clk_cfg;
20 u8 audio_frame[6];
21
22 enum {
23 AFMT_SPDIF,
24 AFMT_I2S
25 } audio_format;
26
27 unsigned audio_sample_rate;
28}; 37};
29 38
30#endif 39#endif
diff --git a/include/dt-bindings/display/tda998x.h b/include/dt-bindings/display/tda998x.h
new file mode 100644
index 000000000000..34757a3847ef
--- /dev/null
+++ b/include/dt-bindings/display/tda998x.h
@@ -0,0 +1,7 @@
1#ifndef _DT_BINDINGS_TDA998X_H
2#define _DT_BINDINGS_TDA998X_H
3
4#define TDA998x_SPDIF 1
5#define TDA998x_I2S 2
6
7#endif /*_DT_BINDINGS_TDA998X_H */