aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/hdmi.c')
-rw-r--r--drivers/video/omap2/dss/hdmi.c461
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
37static struct { 43static 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
1055static void hdmi_compute_pll(unsigned long clkin, int phy, 1061static 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)
1285static 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
1304static 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
1321static 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
1391static 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
1441static 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
1497static 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
1630static 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
1656static 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
1666static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
1667};
1668
1669static 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
1675static 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 */
1279static int omapdss_hdmihw_probe(struct platform_device *pdev) 1690static 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;