diff options
author | Arnaud Pouliquen <arnaud.pouliquen@st.com> | 2016-05-30 09:31:37 -0400 |
---|---|---|
committer | Benjamin Gaignard <benjamin.gaignard@linaro.org> | 2016-07-01 03:12:49 -0400 |
commit | 2c348e5053281555604233a66a633f7165665156 (patch) | |
tree | 06b297de8e9049d4e4c4e2025608143c8d7b71de /drivers/gpu/drm | |
parent | 4d7037708a357f5dbe9a51cc1aacf4dcb65b7192 (diff) |
drm: sti: Add ASoC generic hdmi codec support.
Add the interface needed by audio hdmi-codec driver.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/sti/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.c | 294 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.h | 13 |
3 files changed, 291 insertions, 17 deletions
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index 5ad43a1bb260..494ab257f77c 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig | |||
@@ -7,5 +7,6 @@ config DRM_STI | |||
7 | select DRM_KMS_CMA_HELPER | 7 | select DRM_KMS_CMA_HELPER |
8 | select DRM_PANEL | 8 | select DRM_PANEL |
9 | select FW_LOADER | 9 | select FW_LOADER |
10 | select SND_SOC_HDMI_CODEC if SND_SOC | ||
10 | help | 11 | help |
11 | Choose this option to enable DRM on STM stiH41x chipset | 12 | Choose this option to enable DRM on STM stiH41x chipset |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 8d1402b245bf..927e2b2e5af2 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <drm/drm_crtc_helper.h> | 18 | #include <drm/drm_crtc_helper.h> |
19 | #include <drm/drm_edid.h> | 19 | #include <drm/drm_edid.h> |
20 | 20 | ||
21 | #include <sound/hdmi-codec.h> | ||
22 | |||
21 | #include "sti_hdmi.h" | 23 | #include "sti_hdmi.h" |
22 | #include "sti_hdmi_tx3g4c28phy.h" | 24 | #include "sti_hdmi_tx3g4c28phy.h" |
23 | #include "sti_hdmi_tx3g0c55phy.h" | 25 | #include "sti_hdmi_tx3g0c55phy.h" |
@@ -35,6 +37,8 @@ | |||
35 | #define HDMI_DFLT_CHL0_DAT 0x0110 | 37 | #define HDMI_DFLT_CHL0_DAT 0x0110 |
36 | #define HDMI_DFLT_CHL1_DAT 0x0114 | 38 | #define HDMI_DFLT_CHL1_DAT 0x0114 |
37 | #define HDMI_DFLT_CHL2_DAT 0x0118 | 39 | #define HDMI_DFLT_CHL2_DAT 0x0118 |
40 | #define HDMI_AUDIO_CFG 0x0200 | ||
41 | #define HDMI_SPDIF_FIFO_STATUS 0x0204 | ||
38 | #define HDMI_SW_DI_1_HEAD_WORD 0x0210 | 42 | #define HDMI_SW_DI_1_HEAD_WORD 0x0210 |
39 | #define HDMI_SW_DI_1_PKT_WORD0 0x0214 | 43 | #define HDMI_SW_DI_1_PKT_WORD0 0x0214 |
40 | #define HDMI_SW_DI_1_PKT_WORD1 0x0218 | 44 | #define HDMI_SW_DI_1_PKT_WORD1 0x0218 |
@@ -44,6 +48,9 @@ | |||
44 | #define HDMI_SW_DI_1_PKT_WORD5 0x0228 | 48 | #define HDMI_SW_DI_1_PKT_WORD5 0x0228 |
45 | #define HDMI_SW_DI_1_PKT_WORD6 0x022C | 49 | #define HDMI_SW_DI_1_PKT_WORD6 0x022C |
46 | #define HDMI_SW_DI_CFG 0x0230 | 50 | #define HDMI_SW_DI_CFG 0x0230 |
51 | #define HDMI_SAMPLE_FLAT_MASK 0x0244 | ||
52 | #define HDMI_AUDN 0x0400 | ||
53 | #define HDMI_AUD_CTS 0x0404 | ||
47 | #define HDMI_SW_DI_2_HEAD_WORD 0x0600 | 54 | #define HDMI_SW_DI_2_HEAD_WORD 0x0600 |
48 | #define HDMI_SW_DI_2_PKT_WORD0 0x0604 | 55 | #define HDMI_SW_DI_2_PKT_WORD0 0x0604 |
49 | #define HDMI_SW_DI_2_PKT_WORD1 0x0608 | 56 | #define HDMI_SW_DI_2_PKT_WORD1 0x0608 |
@@ -103,6 +110,7 @@ | |||
103 | #define HDMI_INT_DLL_LCK BIT(5) | 110 | #define HDMI_INT_DLL_LCK BIT(5) |
104 | #define HDMI_INT_NEW_FRAME BIT(6) | 111 | #define HDMI_INT_NEW_FRAME BIT(6) |
105 | #define HDMI_INT_GENCTRL_PKT BIT(7) | 112 | #define HDMI_INT_GENCTRL_PKT BIT(7) |
113 | #define HDMI_INT_AUDIO_FIFO_XRUN BIT(8) | ||
106 | #define HDMI_INT_SINK_TERM_PRESENT BIT(11) | 114 | #define HDMI_INT_SINK_TERM_PRESENT BIT(11) |
107 | 115 | ||
108 | #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \ | 116 | #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \ |
@@ -111,6 +119,7 @@ | |||
111 | | HDMI_INT_GLOBAL) | 119 | | HDMI_INT_GLOBAL) |
112 | 120 | ||
113 | #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \ | 121 | #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \ |
122 | | HDMI_INT_AUDIO_FIFO_XRUN \ | ||
114 | | HDMI_INT_GENCTRL_PKT \ | 123 | | HDMI_INT_GENCTRL_PKT \ |
115 | | HDMI_INT_NEW_FRAME \ | 124 | | HDMI_INT_NEW_FRAME \ |
116 | | HDMI_INT_DLL_LCK \ | 125 | | HDMI_INT_DLL_LCK \ |
@@ -121,6 +130,27 @@ | |||
121 | 130 | ||
122 | #define HDMI_STA_SW_RST BIT(1) | 131 | #define HDMI_STA_SW_RST BIT(1) |
123 | 132 | ||
133 | #define HDMI_AUD_CFG_8CH BIT(0) | ||
134 | #define HDMI_AUD_CFG_SPDIF_DIV_2 BIT(1) | ||
135 | #define HDMI_AUD_CFG_SPDIF_DIV_3 BIT(2) | ||
136 | #define HDMI_AUD_CFG_SPDIF_CLK_DIV_4 (BIT(1) | BIT(2)) | ||
137 | #define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12) | ||
138 | #define HDMI_AUD_CFG_DTS_INVALID BIT(16) | ||
139 | #define HDMI_AUD_CFG_ONE_BIT_INVALID (BIT(18) | BIT(19) | BIT(20) | BIT(21)) | ||
140 | #define HDMI_AUD_CFG_CH12_VALID BIT(28) | ||
141 | #define HDMI_AUD_CFG_CH34_VALID BIT(29) | ||
142 | #define HDMI_AUD_CFG_CH56_VALID BIT(30) | ||
143 | #define HDMI_AUD_CFG_CH78_VALID BIT(31) | ||
144 | |||
145 | /* sample flat mask */ | ||
146 | #define HDMI_SAMPLE_FLAT_NO 0 | ||
147 | #define HDMI_SAMPLE_FLAT_SP0 BIT(0) | ||
148 | #define HDMI_SAMPLE_FLAT_SP1 BIT(1) | ||
149 | #define HDMI_SAMPLE_FLAT_SP2 BIT(2) | ||
150 | #define HDMI_SAMPLE_FLAT_SP3 BIT(3) | ||
151 | #define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\ | ||
152 | HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3) | ||
153 | |||
124 | #define HDMI_INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) | 154 | #define HDMI_INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) |
125 | #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) | 155 | #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) |
126 | #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16) | 156 | #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16) |
@@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg) | |||
171 | wake_up_interruptible(&hdmi->wait_event); | 201 | wake_up_interruptible(&hdmi->wait_event); |
172 | } | 202 | } |
173 | 203 | ||
204 | /* Audio FIFO underrun IRQ */ | ||
205 | if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN) | ||
206 | DRM_INFO("Warning: audio FIFO underrun occurs!"); | ||
207 | |||
174 | return IRQ_HANDLED; | 208 | return IRQ_HANDLED; |
175 | } | 209 | } |
176 | 210 | ||
@@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) | |||
441 | */ | 475 | */ |
442 | static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi) | 476 | static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi) |
443 | { | 477 | { |
444 | struct hdmi_audio_infoframe infofame; | 478 | struct hdmi_audio_params *audio = &hdmi->audio; |
445 | u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)]; | 479 | u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)]; |
446 | int ret; | 480 | int ret, val; |
447 | 481 | ||
448 | ret = hdmi_audio_infoframe_init(&infofame); | 482 | DRM_DEBUG_DRIVER("enter %s, AIF %s\n", __func__, |
449 | if (ret < 0) { | 483 | audio->enabled ? "enable" : "disable"); |
450 | DRM_ERROR("failed to setup audio infoframe: %d\n", ret); | 484 | if (audio->enabled) { |
451 | return ret; | 485 | /* set audio parameters stored*/ |
452 | } | 486 | ret = hdmi_audio_infoframe_pack(&audio->cea, buffer, |
453 | 487 | sizeof(buffer)); | |
454 | infofame.channels = 2; | 488 | if (ret < 0) { |
455 | 489 | DRM_ERROR("failed to pack audio infoframe: %d\n", ret); | |
456 | ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer)); | 490 | return ret; |
457 | if (ret < 0) { | 491 | } |
458 | DRM_ERROR("failed to pack audio infoframe: %d\n", ret); | 492 | hdmi_infoframe_write_infopack(hdmi, buffer, ret); |
459 | return ret; | 493 | } else { |
494 | /*disable audio info frame transmission */ | ||
495 | val = hdmi_read(hdmi, HDMI_SW_DI_CFG); | ||
496 | val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, | ||
497 | HDMI_IFRAME_SLOT_AUDIO); | ||
498 | hdmi_write(hdmi, val, HDMI_SW_DI_CFG); | ||
460 | } | 499 | } |
461 | 500 | ||
462 | hdmi_infoframe_write_infopack(hdmi, buffer, ret); | ||
463 | |||
464 | return 0; | 501 | return 0; |
465 | } | 502 | } |
466 | 503 | ||
@@ -650,6 +687,10 @@ static int hdmi_dbg_show(struct seq_file *s, void *data) | |||
650 | DBGFS_DUMP("", HDMI_SW_DI_CFG); | 687 | DBGFS_DUMP("", HDMI_SW_DI_CFG); |
651 | hdmi_dbg_sw_di_cfg(s, hdmi_read(hdmi, HDMI_SW_DI_CFG)); | 688 | hdmi_dbg_sw_di_cfg(s, hdmi_read(hdmi, HDMI_SW_DI_CFG)); |
652 | 689 | ||
690 | DBGFS_DUMP("\n", HDMI_AUDIO_CFG); | ||
691 | DBGFS_DUMP("\n", HDMI_SPDIF_FIFO_STATUS); | ||
692 | DBGFS_DUMP("\n", HDMI_AUDN); | ||
693 | |||
653 | seq_printf(s, "\n AVI Infoframe (Data Island slot N=%d):", | 694 | seq_printf(s, "\n AVI Infoframe (Data Island slot N=%d):", |
654 | HDMI_IFRAME_SLOT_AVI); | 695 | HDMI_IFRAME_SLOT_AVI); |
655 | DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AVI); | 696 | DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AVI); |
@@ -854,6 +895,7 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector) | |||
854 | 895 | ||
855 | count = drm_add_edid_modes(connector, edid); | 896 | count = drm_add_edid_modes(connector, edid); |
856 | drm_mode_connector_update_edid_property(connector, edid); | 897 | drm_mode_connector_update_edid_property(connector, edid); |
898 | drm_edid_to_eld(connector, edid); | ||
857 | 899 | ||
858 | kfree(edid); | 900 | kfree(edid); |
859 | return count; | 901 | return count; |
@@ -1036,6 +1078,206 @@ static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev) | |||
1036 | return NULL; | 1078 | return NULL; |
1037 | } | 1079 | } |
1038 | 1080 | ||
1081 | /** | ||
1082 | * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent | ||
1083 | * clocks. None-coherent clocks means that audio and TMDS clocks have not the | ||
1084 | * same source (drifts between clocks). In this case assumption is that CTS is | ||
1085 | * automatically calculated by hardware. | ||
1086 | * | ||
1087 | * @audio_fs: audio frame clock frequency in Hz | ||
1088 | * | ||
1089 | * Values computed are based on table described in HDMI specification 1.4b | ||
1090 | * | ||
1091 | * Returns n value. | ||
1092 | */ | ||
1093 | static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs) | ||
1094 | { | ||
1095 | unsigned int n; | ||
1096 | |||
1097 | switch (audio_fs) { | ||
1098 | case 32000: | ||
1099 | n = 4096; | ||
1100 | break; | ||
1101 | case 44100: | ||
1102 | n = 6272; | ||
1103 | break; | ||
1104 | case 48000: | ||
1105 | n = 6144; | ||
1106 | break; | ||
1107 | case 88200: | ||
1108 | n = 6272 * 2; | ||
1109 | break; | ||
1110 | case 96000: | ||
1111 | n = 6144 * 2; | ||
1112 | break; | ||
1113 | case 176400: | ||
1114 | n = 6272 * 4; | ||
1115 | break; | ||
1116 | case 192000: | ||
1117 | n = 6144 * 4; | ||
1118 | break; | ||
1119 | default: | ||
1120 | /* Not pre-defined, recommended value: 128 * fs / 1000 */ | ||
1121 | n = (audio_fs * 128) / 1000; | ||
1122 | } | ||
1123 | |||
1124 | return n; | ||
1125 | } | ||
1126 | |||
1127 | static int hdmi_audio_configure(struct sti_hdmi *hdmi, | ||
1128 | struct hdmi_audio_params *params) | ||
1129 | { | ||
1130 | int audio_cfg, n; | ||
1131 | struct hdmi_audio_infoframe *info = ¶ms->cea; | ||
1132 | |||
1133 | DRM_DEBUG_DRIVER("\n"); | ||
1134 | |||
1135 | if (!hdmi->enabled) | ||
1136 | return 0; | ||
1137 | |||
1138 | /* update N parameter */ | ||
1139 | n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate); | ||
1140 | |||
1141 | DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n", | ||
1142 | params->sample_rate, hdmi->mode.clock * 1000, n); | ||
1143 | hdmi_write(hdmi, n, HDMI_AUDN); | ||
1144 | |||
1145 | /* update HDMI registers according to configuration */ | ||
1146 | audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID | | ||
1147 | HDMI_AUD_CFG_ONE_BIT_INVALID; | ||
1148 | |||
1149 | switch (info->channels) { | ||
1150 | case 8: | ||
1151 | audio_cfg |= HDMI_AUD_CFG_CH78_VALID; | ||
1152 | case 6: | ||
1153 | audio_cfg |= HDMI_AUD_CFG_CH56_VALID; | ||
1154 | case 4: | ||
1155 | audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH; | ||
1156 | case 2: | ||
1157 | audio_cfg |= HDMI_AUD_CFG_CH12_VALID; | ||
1158 | break; | ||
1159 | default: | ||
1160 | DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n", | ||
1161 | info->channels); | ||
1162 | return -EINVAL; | ||
1163 | } | ||
1164 | |||
1165 | hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG); | ||
1166 | |||
1167 | hdmi->audio = *params; | ||
1168 | |||
1169 | return hdmi_audio_infoframe_config(hdmi); | ||
1170 | } | ||
1171 | |||
1172 | static void hdmi_audio_shutdown(struct device *dev) | ||
1173 | { | ||
1174 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); | ||
1175 | int audio_cfg; | ||
1176 | |||
1177 | DRM_DEBUG_DRIVER("\n"); | ||
1178 | |||
1179 | /* disable audio */ | ||
1180 | audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID | | ||
1181 | HDMI_AUD_CFG_ONE_BIT_INVALID; | ||
1182 | hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG); | ||
1183 | |||
1184 | hdmi->audio.enabled = 0; | ||
1185 | hdmi_audio_infoframe_config(hdmi); | ||
1186 | } | ||
1187 | |||
1188 | static int hdmi_audio_hw_params(struct device *dev, | ||
1189 | struct hdmi_codec_daifmt *daifmt, | ||
1190 | struct hdmi_codec_params *params) | ||
1191 | { | ||
1192 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); | ||
1193 | int ret; | ||
1194 | struct hdmi_audio_params audio = { | ||
1195 | .sample_width = params->sample_width, | ||
1196 | .sample_rate = params->sample_rate, | ||
1197 | .cea = params->cea, | ||
1198 | }; | ||
1199 | |||
1200 | DRM_DEBUG_DRIVER("\n"); | ||
1201 | |||
1202 | if (!hdmi->enabled) | ||
1203 | return 0; | ||
1204 | |||
1205 | if ((daifmt->fmt != HDMI_I2S) || daifmt->bit_clk_inv || | ||
1206 | daifmt->frame_clk_inv || daifmt->bit_clk_master || | ||
1207 | daifmt->frame_clk_master) { | ||
1208 | dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__, | ||
1209 | daifmt->bit_clk_inv, daifmt->frame_clk_inv, | ||
1210 | daifmt->bit_clk_master, | ||
1211 | daifmt->frame_clk_master); | ||
1212 | return -EINVAL; | ||
1213 | } | ||
1214 | |||
1215 | audio.enabled = 1; | ||
1216 | |||
1217 | ret = hdmi_audio_configure(hdmi, &audio); | ||
1218 | if (ret < 0) | ||
1219 | return ret; | ||
1220 | |||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | static int hdmi_audio_digital_mute(struct device *dev, bool enable) | ||
1225 | { | ||
1226 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); | ||
1227 | |||
1228 | DRM_DEBUG_DRIVER("%s\n", enable ? "enable" : "disable"); | ||
1229 | |||
1230 | if (enable) | ||
1231 | hdmi_write(hdmi, HDMI_SAMPLE_FLAT_ALL, HDMI_SAMPLE_FLAT_MASK); | ||
1232 | else | ||
1233 | hdmi_write(hdmi, HDMI_SAMPLE_FLAT_NO, HDMI_SAMPLE_FLAT_MASK); | ||
1234 | |||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | static int hdmi_audio_get_eld(struct device *dev, uint8_t *buf, size_t len) | ||
1239 | { | ||
1240 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); | ||
1241 | struct drm_connector *connector = hdmi->drm_connector; | ||
1242 | |||
1243 | DRM_DEBUG_DRIVER("\n"); | ||
1244 | memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); | ||
1245 | |||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | static const struct hdmi_codec_ops audio_codec_ops = { | ||
1250 | .hw_params = hdmi_audio_hw_params, | ||
1251 | .audio_shutdown = hdmi_audio_shutdown, | ||
1252 | .digital_mute = hdmi_audio_digital_mute, | ||
1253 | .get_eld = hdmi_audio_get_eld, | ||
1254 | }; | ||
1255 | |||
1256 | static int sti_hdmi_register_audio_driver(struct device *dev, | ||
1257 | struct sti_hdmi *hdmi) | ||
1258 | { | ||
1259 | struct hdmi_codec_pdata codec_data = { | ||
1260 | .ops = &audio_codec_ops, | ||
1261 | .max_i2s_channels = 8, | ||
1262 | .i2s = 1, | ||
1263 | }; | ||
1264 | |||
1265 | DRM_DEBUG_DRIVER("\n"); | ||
1266 | |||
1267 | hdmi->audio.enabled = 0; | ||
1268 | |||
1269 | hdmi->audio_pdev = platform_device_register_data( | ||
1270 | dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, | ||
1271 | &codec_data, sizeof(codec_data)); | ||
1272 | |||
1273 | if (IS_ERR(hdmi->audio_pdev)) | ||
1274 | return PTR_ERR(hdmi->audio_pdev); | ||
1275 | |||
1276 | DRM_INFO("%s Driver bound %s\n", HDMI_CODEC_DRV_NAME, dev_name(dev)); | ||
1277 | |||
1278 | return 0; | ||
1279 | } | ||
1280 | |||
1039 | static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) | 1281 | static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) |
1040 | { | 1282 | { |
1041 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); | 1283 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); |
@@ -1082,12 +1324,27 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) | |||
1082 | /* initialise property */ | 1324 | /* initialise property */ |
1083 | sti_hdmi_connector_init_property(drm_dev, drm_connector); | 1325 | sti_hdmi_connector_init_property(drm_dev, drm_connector); |
1084 | 1326 | ||
1327 | hdmi->drm_connector = drm_connector; | ||
1328 | |||
1085 | err = drm_mode_connector_attach_encoder(drm_connector, encoder); | 1329 | err = drm_mode_connector_attach_encoder(drm_connector, encoder); |
1086 | if (err) { | 1330 | if (err) { |
1087 | DRM_ERROR("Failed to attach a connector to a encoder\n"); | 1331 | DRM_ERROR("Failed to attach a connector to a encoder\n"); |
1088 | goto err_sysfs; | 1332 | goto err_sysfs; |
1089 | } | 1333 | } |
1090 | 1334 | ||
1335 | err = sti_hdmi_register_audio_driver(dev, hdmi); | ||
1336 | if (err) { | ||
1337 | DRM_ERROR("Failed to attach an audio codec\n"); | ||
1338 | goto err_sysfs; | ||
1339 | } | ||
1340 | |||
1341 | /* Initialize audio infoframe */ | ||
1342 | err = hdmi_audio_infoframe_init(&hdmi->audio.cea); | ||
1343 | if (err) { | ||
1344 | DRM_ERROR("Failed to init audio infoframe\n"); | ||
1345 | goto err_sysfs; | ||
1346 | } | ||
1347 | |||
1091 | /* Enable default interrupts */ | 1348 | /* Enable default interrupts */ |
1092 | hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN); | 1349 | hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN); |
1093 | 1350 | ||
@@ -1095,6 +1352,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) | |||
1095 | 1352 | ||
1096 | err_sysfs: | 1353 | err_sysfs: |
1097 | drm_bridge_remove(bridge); | 1354 | drm_bridge_remove(bridge); |
1355 | hdmi->drm_connector = NULL; | ||
1098 | return -EINVAL; | 1356 | return -EINVAL; |
1099 | } | 1357 | } |
1100 | 1358 | ||
@@ -1244,6 +1502,8 @@ static int sti_hdmi_remove(struct platform_device *pdev) | |||
1244 | struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); | 1502 | struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); |
1245 | 1503 | ||
1246 | i2c_put_adapter(hdmi->ddc_adapt); | 1504 | i2c_put_adapter(hdmi->ddc_adapt); |
1505 | if (hdmi->audio_pdev) | ||
1506 | platform_device_unregister(hdmi->audio_pdev); | ||
1247 | component_del(&pdev->dev, &sti_hdmi_ops); | 1507 | component_del(&pdev->dev, &sti_hdmi_ops); |
1248 | 1508 | ||
1249 | return 0; | 1509 | return 0; |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index ef3a94583bbd..119bc3582ac7 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h | |||
@@ -23,6 +23,13 @@ struct hdmi_phy_ops { | |||
23 | void (*stop)(struct sti_hdmi *hdmi); | 23 | void (*stop)(struct sti_hdmi *hdmi); |
24 | }; | 24 | }; |
25 | 25 | ||
26 | struct hdmi_audio_params { | ||
27 | bool enabled; | ||
28 | unsigned int sample_width; | ||
29 | unsigned int sample_rate; | ||
30 | struct hdmi_audio_infoframe cea; | ||
31 | }; | ||
32 | |||
26 | /* values for the framing mode property */ | 33 | /* values for the framing mode property */ |
27 | enum sti_hdmi_modes { | 34 | enum sti_hdmi_modes { |
28 | HDMI_MODE_HDMI, | 35 | HDMI_MODE_HDMI, |
@@ -67,6 +74,9 @@ static const struct drm_prop_enum_list colorspace_mode_names[] = { | |||
67 | * @ddc_adapt: i2c ddc adapter | 74 | * @ddc_adapt: i2c ddc adapter |
68 | * @colorspace: current colorspace selected | 75 | * @colorspace: current colorspace selected |
69 | * @hdmi_mode: select framing for HDMI or DVI | 76 | * @hdmi_mode: select framing for HDMI or DVI |
77 | * @audio_pdev: ASoC hdmi-codec platform device | ||
78 | * @audio: hdmi audio parameters. | ||
79 | * @drm_connector: hdmi connector | ||
70 | */ | 80 | */ |
71 | struct sti_hdmi { | 81 | struct sti_hdmi { |
72 | struct device dev; | 82 | struct device dev; |
@@ -89,6 +99,9 @@ struct sti_hdmi { | |||
89 | struct i2c_adapter *ddc_adapt; | 99 | struct i2c_adapter *ddc_adapt; |
90 | enum hdmi_colorspace colorspace; | 100 | enum hdmi_colorspace colorspace; |
91 | enum sti_hdmi_modes hdmi_mode; | 101 | enum sti_hdmi_modes hdmi_mode; |
102 | struct platform_device *audio_pdev; | ||
103 | struct hdmi_audio_params audio; | ||
104 | struct drm_connector *drm_connector; | ||
92 | }; | 105 | }; |
93 | 106 | ||
94 | u32 hdmi_read(struct sti_hdmi *hdmi, int offset); | 107 | u32 hdmi_read(struct sti_hdmi *hdmi, int offset); |