diff options
Diffstat (limited to 'drivers/video/omap2/dss/hdmi.c')
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 461 |
1 files changed, 446 insertions, 15 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index a981def8099a..b0555f4f0a78 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -29,10 +29,16 @@ | |||
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <plat/display.h> | 32 | #include <video/omapdss.h> |
33 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
34 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
35 | #include <sound/soc.h> | ||
36 | #include <sound/pcm_params.h> | ||
37 | #endif | ||
33 | 38 | ||
34 | #include "dss.h" | 39 | #include "dss.h" |
35 | #include "hdmi.h" | 40 | #include "hdmi.h" |
41 | #include "dss_features.h" | ||
36 | 42 | ||
37 | static struct { | 43 | static struct { |
38 | struct mutex lock; | 44 | struct mutex lock; |
@@ -1052,25 +1058,26 @@ static void update_hdmi_timings(struct hdmi_config *cfg, | |||
1052 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | 1058 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; |
1053 | } | 1059 | } |
1054 | 1060 | ||
1055 | static void hdmi_compute_pll(unsigned long clkin, int phy, | 1061 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, |
1056 | int n, struct hdmi_pll_info *pi) | 1062 | struct hdmi_pll_info *pi) |
1057 | { | 1063 | { |
1058 | unsigned long refclk; | 1064 | unsigned long clkin, refclk; |
1059 | u32 mf; | 1065 | u32 mf; |
1060 | 1066 | ||
1067 | clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; | ||
1061 | /* | 1068 | /* |
1062 | * Input clock is predivided by N + 1 | 1069 | * Input clock is predivided by N + 1 |
1063 | * out put of which is reference clk | 1070 | * out put of which is reference clk |
1064 | */ | 1071 | */ |
1065 | refclk = clkin / (n + 1); | 1072 | pi->regn = dssdev->clocks.hdmi.regn; |
1066 | pi->regn = n; | 1073 | refclk = clkin / (pi->regn + 1); |
1067 | 1074 | ||
1068 | /* | 1075 | /* |
1069 | * multiplier is pixel_clk/ref_clk | 1076 | * multiplier is pixel_clk/ref_clk |
1070 | * Multiplying by 100 to avoid fractional part removal | 1077 | * Multiplying by 100 to avoid fractional part removal |
1071 | */ | 1078 | */ |
1072 | pi->regm = (phy * 100/(refclk))/100; | 1079 | pi->regm = (phy * 100 / (refclk)) / 100; |
1073 | pi->regm2 = 1; | 1080 | pi->regm2 = dssdev->clocks.hdmi.regm2; |
1074 | 1081 | ||
1075 | /* | 1082 | /* |
1076 | * fractional multiplier is remainder of the difference between | 1083 | * fractional multiplier is remainder of the difference between |
@@ -1078,14 +1085,14 @@ static void hdmi_compute_pll(unsigned long clkin, int phy, | |||
1078 | * multiplied by 2^18(262144) divided by the reference clock | 1085 | * multiplied by 2^18(262144) divided by the reference clock |
1079 | */ | 1086 | */ |
1080 | mf = (phy - pi->regm * refclk) * 262144; | 1087 | mf = (phy - pi->regm * refclk) * 262144; |
1081 | pi->regmf = mf/(refclk); | 1088 | pi->regmf = mf / (refclk); |
1082 | 1089 | ||
1083 | /* | 1090 | /* |
1084 | * Dcofreq should be set to 1 if required pixel clock | 1091 | * Dcofreq should be set to 1 if required pixel clock |
1085 | * is greater than 1000MHz | 1092 | * is greater than 1000MHz |
1086 | */ | 1093 | */ |
1087 | pi->dcofreq = phy > 1000 * 100; | 1094 | pi->dcofreq = phy > 1000 * 100; |
1088 | pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; | 1095 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; |
1089 | 1096 | ||
1090 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | 1097 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); |
1091 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 1098 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
@@ -1106,7 +1113,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1106 | int r, code = 0; | 1113 | int r, code = 0; |
1107 | struct hdmi_pll_info pll_data; | 1114 | struct hdmi_pll_info pll_data; |
1108 | struct omap_video_timings *p; | 1115 | struct omap_video_timings *p; |
1109 | int clkin, n, phy; | 1116 | unsigned long phy; |
1110 | 1117 | ||
1111 | hdmi_enable_clocks(1); | 1118 | hdmi_enable_clocks(1); |
1112 | 1119 | ||
@@ -1126,11 +1133,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1126 | dssdev->panel.timings = cea_vesa_timings[code].timings; | 1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; |
1127 | update_hdmi_timings(&hdmi.cfg, p, code); | 1134 | update_hdmi_timings(&hdmi.cfg, p, code); |
1128 | 1135 | ||
1129 | clkin = 3840; /* 38.4 MHz */ | ||
1130 | n = 15; /* this is a constant for our math */ | ||
1131 | phy = p->pixel_clock; | 1136 | phy = p->pixel_clock; |
1132 | 1137 | ||
1133 | hdmi_compute_pll(clkin, phy, n, &pll_data); | 1138 | hdmi_compute_pll(dssdev, phy, &pll_data); |
1134 | 1139 | ||
1135 | hdmi_wp_video_start(0); | 1140 | hdmi_wp_video_start(0); |
1136 | 1141 | ||
@@ -1160,7 +1165,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
1160 | * dynamically by user. This can be moved to single location , say | 1165 | * dynamically by user. This can be moved to single location , say |
1161 | * Boardfile. | 1166 | * Boardfile. |
1162 | */ | 1167 | */ |
1163 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | 1168 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
1164 | 1169 | ||
1165 | /* bypass TV gamma table */ | 1170 | /* bypass TV gamma table */ |
1166 | dispc_enable_gamma_table(0); | 1171 | dispc_enable_gamma_table(0); |
@@ -1275,10 +1280,420 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
1275 | mutex_unlock(&hdmi.lock); | 1280 | mutex_unlock(&hdmi.lock); |
1276 | } | 1281 | } |
1277 | 1282 | ||
1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1285 | static void hdmi_wp_audio_config_format( | ||
1286 | struct hdmi_audio_format *aud_fmt) | ||
1287 | { | ||
1288 | u32 r; | ||
1289 | |||
1290 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
1291 | |||
1292 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); | ||
1293 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
1294 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
1295 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
1296 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
1297 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
1298 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
1299 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
1300 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
1301 | hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); | ||
1302 | } | ||
1303 | |||
1304 | static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) | ||
1305 | { | ||
1306 | u32 r; | ||
1307 | |||
1308 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
1309 | |||
1310 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); | ||
1311 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
1312 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
1313 | hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); | ||
1314 | |||
1315 | r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); | ||
1316 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
1317 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
1318 | hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); | ||
1319 | } | ||
1320 | |||
1321 | static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) | ||
1322 | { | ||
1323 | u32 r; | ||
1324 | |||
1325 | /* audio clock recovery parameters */ | ||
1326 | r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); | ||
1327 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
1328 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
1329 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
1330 | hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); | ||
1331 | |||
1332 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
1333 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
1334 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
1335 | |||
1336 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
1337 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
1338 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
1339 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
1340 | } else { | ||
1341 | /* | ||
1342 | * HDMI IP uses this configuration to divide the MCLK to | ||
1343 | * update CTS value. | ||
1344 | */ | ||
1345 | REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
1346 | |||
1347 | /* Configure clock for audio packets */ | ||
1348 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
1349 | cfg->aud_par_busclk, 7, 0); | ||
1350 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
1351 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
1352 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
1353 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
1354 | } | ||
1355 | |||
1356 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
1357 | REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); | ||
1358 | |||
1359 | /* I2S parameters */ | ||
1360 | REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); | ||
1361 | |||
1362 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); | ||
1363 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
1364 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
1365 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
1366 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
1367 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
1368 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
1369 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
1370 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
1371 | hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
1372 | |||
1373 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); | ||
1374 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
1375 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
1376 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
1377 | hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); | ||
1378 | |||
1379 | REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); | ||
1380 | |||
1381 | /* Audio channels and mode parameters */ | ||
1382 | REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
1383 | r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); | ||
1384 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
1385 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
1386 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
1387 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
1388 | hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); | ||
1389 | } | ||
1390 | |||
1391 | static void hdmi_core_audio_infoframe_config( | ||
1392 | struct hdmi_core_infoframe_audio *info_aud) | ||
1393 | { | ||
1394 | u8 val; | ||
1395 | u8 sum = 0, checksum = 0; | ||
1396 | |||
1397 | /* | ||
1398 | * Set audio info frame type, version and length as | ||
1399 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
1400 | * Checksum calculation is defined in Section 5.3.5. | ||
1401 | */ | ||
1402 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
1403 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
1404 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
1405 | sum += 0x84 + 0x001 + 0x00a; | ||
1406 | |||
1407 | val = (info_aud->db1_coding_type << 4) | ||
1408 | | (info_aud->db1_channel_count - 1); | ||
1409 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
1410 | sum += val; | ||
1411 | |||
1412 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
1413 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
1414 | sum += val; | ||
1415 | |||
1416 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
1417 | |||
1418 | val = info_aud->db4_channel_alloc; | ||
1419 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
1420 | sum += val; | ||
1421 | |||
1422 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
1423 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
1424 | sum += val; | ||
1425 | |||
1426 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
1427 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
1428 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
1429 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
1430 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
1431 | |||
1432 | checksum = 0x100 - sum; | ||
1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | ||
1434 | |||
1435 | /* | ||
1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
1437 | * is available. | ||
1438 | */ | ||
1439 | } | ||
1440 | |||
1441 | static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) | ||
1442 | { | ||
1443 | u32 r; | ||
1444 | u32 deep_color = 0; | ||
1445 | u32 pclk = hdmi.cfg.timings.timings.pixel_clock; | ||
1446 | |||
1447 | if (n == NULL || cts == NULL) | ||
1448 | return -EINVAL; | ||
1449 | /* | ||
1450 | * Obtain current deep color configuration. This needed | ||
1451 | * to calculate the TMDS clock based on the pixel clock. | ||
1452 | */ | ||
1453 | r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); | ||
1454 | switch (r) { | ||
1455 | case 1: /* No deep color selected */ | ||
1456 | deep_color = 100; | ||
1457 | break; | ||
1458 | case 2: /* 10-bit deep color selected */ | ||
1459 | deep_color = 125; | ||
1460 | break; | ||
1461 | case 3: /* 12-bit deep color selected */ | ||
1462 | deep_color = 150; | ||
1463 | break; | ||
1464 | default: | ||
1465 | return -EINVAL; | ||
1466 | } | ||
1467 | |||
1468 | switch (sample_freq) { | ||
1469 | case 32000: | ||
1470 | if ((deep_color == 125) && ((pclk == 54054) | ||
1471 | || (pclk == 74250))) | ||
1472 | *n = 8192; | ||
1473 | else | ||
1474 | *n = 4096; | ||
1475 | break; | ||
1476 | case 44100: | ||
1477 | *n = 6272; | ||
1478 | break; | ||
1479 | case 48000: | ||
1480 | if ((deep_color == 125) && ((pclk == 54054) | ||
1481 | || (pclk == 74250))) | ||
1482 | *n = 8192; | ||
1483 | else | ||
1484 | *n = 6144; | ||
1485 | break; | ||
1486 | default: | ||
1487 | *n = 0; | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | |||
1491 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
1492 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
1498 | struct snd_pcm_hw_params *params, | ||
1499 | struct snd_soc_dai *dai) | ||
1500 | { | ||
1501 | struct hdmi_audio_format audio_format; | ||
1502 | struct hdmi_audio_dma audio_dma; | ||
1503 | struct hdmi_core_audio_config core_cfg; | ||
1504 | struct hdmi_core_infoframe_audio aud_if_cfg; | ||
1505 | int err, n, cts; | ||
1506 | enum hdmi_core_audio_sample_freq sample_freq; | ||
1507 | |||
1508 | switch (params_format(params)) { | ||
1509 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1510 | core_cfg.i2s_cfg.word_max_length = | ||
1511 | HDMI_AUDIO_I2S_MAX_WORD_20BITS; | ||
1512 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS; | ||
1513 | core_cfg.i2s_cfg.in_length_bits = | ||
1514 | HDMI_AUDIO_I2S_INPUT_LENGTH_16; | ||
1515 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1516 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; | ||
1517 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; | ||
1518 | audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; | ||
1519 | audio_dma.transfer_size = 0x10; | ||
1520 | break; | ||
1521 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1522 | core_cfg.i2s_cfg.word_max_length = | ||
1523 | HDMI_AUDIO_I2S_MAX_WORD_24BITS; | ||
1524 | core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS; | ||
1525 | core_cfg.i2s_cfg.in_length_bits = | ||
1526 | HDMI_AUDIO_I2S_INPUT_LENGTH_24; | ||
1527 | audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; | ||
1528 | audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; | ||
1529 | audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1530 | core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; | ||
1531 | audio_dma.transfer_size = 0x20; | ||
1532 | break; | ||
1533 | default: | ||
1534 | return -EINVAL; | ||
1535 | } | ||
1536 | |||
1537 | switch (params_rate(params)) { | ||
1538 | case 32000: | ||
1539 | sample_freq = HDMI_AUDIO_FS_32000; | ||
1540 | break; | ||
1541 | case 44100: | ||
1542 | sample_freq = HDMI_AUDIO_FS_44100; | ||
1543 | break; | ||
1544 | case 48000: | ||
1545 | sample_freq = HDMI_AUDIO_FS_48000; | ||
1546 | break; | ||
1547 | default: | ||
1548 | return -EINVAL; | ||
1549 | } | ||
1550 | |||
1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | ||
1552 | if (err < 0) | ||
1553 | return err; | ||
1554 | |||
1555 | /* Audio wrapper config */ | ||
1556 | audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; | ||
1557 | audio_format.active_chnnls_msk = 0x03; | ||
1558 | audio_format.type = HDMI_AUDIO_TYPE_LPCM; | ||
1559 | audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; | ||
1560 | /* Disable start/stop signals of IEC 60958 blocks */ | ||
1561 | audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; | ||
1562 | |||
1563 | audio_dma.block_size = 0xC0; | ||
1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | ||
1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | ||
1566 | |||
1567 | hdmi_wp_audio_config_dma(&audio_dma); | ||
1568 | hdmi_wp_audio_config_format(&audio_format); | ||
1569 | |||
1570 | /* | ||
1571 | * I2S config | ||
1572 | */ | ||
1573 | core_cfg.i2s_cfg.en_high_bitrate_aud = false; | ||
1574 | /* Only used with high bitrate audio */ | ||
1575 | core_cfg.i2s_cfg.cbit_order = false; | ||
1576 | /* Serial data and word select should change on sck rising edge */ | ||
1577 | core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; | ||
1578 | core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; | ||
1579 | /* Set I2S word select polarity */ | ||
1580 | core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT; | ||
1581 | core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; | ||
1582 | /* Set serial data to word select shift. See Phillips spec. */ | ||
1583 | core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; | ||
1584 | /* Enable one of the four available serial data channels */ | ||
1585 | core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; | ||
1586 | |||
1587 | /* Core audio config */ | ||
1588 | core_cfg.freq_sample = sample_freq; | ||
1589 | core_cfg.n = n; | ||
1590 | core_cfg.cts = cts; | ||
1591 | if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { | ||
1592 | core_cfg.aud_par_busclk = 0; | ||
1593 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; | ||
1594 | core_cfg.use_mclk = false; | ||
1595 | } else { | ||
1596 | core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); | ||
1597 | core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; | ||
1598 | core_cfg.use_mclk = true; | ||
1599 | core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; | ||
1600 | } | ||
1601 | core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; | ||
1602 | core_cfg.en_spdif = false; | ||
1603 | /* Use sample frequency from channel status word */ | ||
1604 | core_cfg.fs_override = true; | ||
1605 | /* Enable ACR packets */ | ||
1606 | core_cfg.en_acr_pkt = true; | ||
1607 | /* Disable direct streaming digital audio */ | ||
1608 | core_cfg.en_dsd_audio = false; | ||
1609 | /* Use parallel audio interface */ | ||
1610 | core_cfg.en_parallel_aud_input = true; | ||
1611 | |||
1612 | hdmi_core_audio_config(&core_cfg); | ||
1613 | |||
1614 | /* | ||
1615 | * Configure packet | ||
1616 | * info frame audio see doc CEA861-D page 74 | ||
1617 | */ | ||
1618 | aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM; | ||
1619 | aud_if_cfg.db1_channel_count = 2; | ||
1620 | aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM; | ||
1621 | aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM; | ||
1622 | aud_if_cfg.db4_channel_alloc = 0x00; | ||
1623 | aud_if_cfg.db5_downmix_inh = false; | ||
1624 | aud_if_cfg.db5_lsv = 0; | ||
1625 | |||
1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | ||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
1631 | struct snd_soc_dai *dai) | ||
1632 | { | ||
1633 | int err = 0; | ||
1634 | switch (cmd) { | ||
1635 | case SNDRV_PCM_TRIGGER_START: | ||
1636 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1637 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1638 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
1639 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
1640 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
1641 | break; | ||
1642 | |||
1643 | case SNDRV_PCM_TRIGGER_STOP: | ||
1644 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1645 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1646 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
1647 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
1648 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
1649 | break; | ||
1650 | default: | ||
1651 | err = -EINVAL; | ||
1652 | } | ||
1653 | return err; | ||
1654 | } | ||
1655 | |||
1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | ||
1657 | struct snd_soc_dai *dai) | ||
1658 | { | ||
1659 | if (!hdmi.mode) { | ||
1660 | pr_err("Current video settings do not support audio.\n"); | ||
1661 | return -EIO; | ||
1662 | } | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static struct snd_soc_codec_driver hdmi_audio_codec_drv = { | ||
1667 | }; | ||
1668 | |||
1669 | static struct snd_soc_dai_ops hdmi_audio_codec_ops = { | ||
1670 | .hw_params = hdmi_audio_hw_params, | ||
1671 | .trigger = hdmi_audio_trigger, | ||
1672 | .startup = hdmi_audio_startup, | ||
1673 | }; | ||
1674 | |||
1675 | static struct snd_soc_dai_driver hdmi_codec_dai_drv = { | ||
1676 | .name = "hdmi-audio-codec", | ||
1677 | .playback = { | ||
1678 | .channels_min = 2, | ||
1679 | .channels_max = 2, | ||
1680 | .rates = SNDRV_PCM_RATE_32000 | | ||
1681 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
1682 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
1683 | SNDRV_PCM_FMTBIT_S24_LE, | ||
1684 | }, | ||
1685 | .ops = &hdmi_audio_codec_ops, | ||
1686 | }; | ||
1687 | #endif | ||
1688 | |||
1278 | /* HDMI HW IP initialisation */ | 1689 | /* HDMI HW IP initialisation */ |
1279 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 1690 | static int omapdss_hdmihw_probe(struct platform_device *pdev) |
1280 | { | 1691 | { |
1281 | struct resource *hdmi_mem; | 1692 | struct resource *hdmi_mem; |
1693 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1694 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1695 | int ret; | ||
1696 | #endif | ||
1282 | 1697 | ||
1283 | hdmi.pdata = pdev->dev.platform_data; | 1698 | hdmi.pdata = pdev->dev.platform_data; |
1284 | hdmi.pdev = pdev; | 1699 | hdmi.pdev = pdev; |
@@ -1300,6 +1715,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1300 | 1715 | ||
1301 | hdmi_panel_init(); | 1716 | hdmi_panel_init(); |
1302 | 1717 | ||
1718 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1719 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1720 | |||
1721 | /* Register ASoC codec DAI */ | ||
1722 | ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, | ||
1723 | &hdmi_codec_dai_drv, 1); | ||
1724 | if (ret) { | ||
1725 | DSSERR("can't register ASoC HDMI audio codec\n"); | ||
1726 | return ret; | ||
1727 | } | ||
1728 | #endif | ||
1303 | return 0; | 1729 | return 0; |
1304 | } | 1730 | } |
1305 | 1731 | ||
@@ -1307,6 +1733,11 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1307 | { | 1733 | { |
1308 | hdmi_panel_exit(); | 1734 | hdmi_panel_exit(); |
1309 | 1735 | ||
1736 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
1737 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
1738 | snd_soc_unregister_codec(&pdev->dev); | ||
1739 | #endif | ||
1740 | |||
1310 | iounmap(hdmi.base_wp); | 1741 | iounmap(hdmi.base_wp); |
1311 | 1742 | ||
1312 | return 0; | 1743 | return 0; |