aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Neri <ricardo.neri@ti.com>2011-04-05 17:05:18 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-19 08:18:04 -0400
commit82335c4cc2edf57afece9399441a7480c2a1b055 (patch)
treef01ab452f41ef8bd2b6d6206a9052d9548bdd001
parent5d8dbe4aa986526f9096bcdb27679c37f5c7b194 (diff)
OMAP4: DSS2: HDMI: Add functionality for audio configuration
Add functionality for relevant audio configuration. Functions to configure the audio FIFO and DMA as well as functions for the audio core and Audio Info frame are included. This functionality is to be used by the ASoC HDMI audio codec. Signed-off-by: Ricardo Neri <ricardo.neri@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/dss/hdmi.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 76e1142e4b6f..0b209d38a106 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1274,6 +1274,221 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
1274 mutex_unlock(&hdmi.lock); 1274 mutex_unlock(&hdmi.lock);
1275} 1275}
1276 1276
1277#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1278 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1279static void hdmi_wp_audio_config_format(
1280 struct hdmi_audio_format *aud_fmt)
1281{
1282 u32 r;
1283
1284 DSSDBG("Enter hdmi_wp_audio_config_format\n");
1285
1286 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
1287 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
1288 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
1289 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
1290 r = FLD_MOD(r, aud_fmt->type, 4, 4);
1291 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
1292 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
1293 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
1294 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
1295 hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
1296}
1297
1298static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
1299{
1300 u32 r;
1301
1302 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
1303
1304 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
1305 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1306 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1307 hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
1308
1309 r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
1310 r = FLD_MOD(r, aud_dma->mode, 9, 9);
1311 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
1312 hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
1313}
1314
1315static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
1316{
1317 u32 r;
1318
1319 /* audio clock recovery parameters */
1320 r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
1321 r = FLD_MOD(r, cfg->use_mclk, 2, 2);
1322 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1323 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1324 hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
1325
1326 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1327 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1328 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1329
1330 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1331 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1332 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1333 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1334 } else {
1335 /*
1336 * HDMI IP uses this configuration to divide the MCLK to
1337 * update CTS value.
1338 */
1339 REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1340
1341 /* Configure clock for audio packets */
1342 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1343 cfg->aud_par_busclk, 7, 0);
1344 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1345 (cfg->aud_par_busclk >> 8), 7, 0);
1346 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1347 (cfg->aud_par_busclk >> 16), 7, 0);
1348 }
1349
1350 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1351 REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
1352
1353 /* I2S parameters */
1354 REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
1355
1356 r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
1357 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1358 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1359 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1360 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1361 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1362 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1363 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1364 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1365 hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
1366
1367 r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
1368 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1369 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1370 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1371 hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
1372
1373 REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
1374
1375 /* Audio channels and mode parameters */
1376 REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1377 r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
1378 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1379 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1380 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1381 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1382 hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
1383}
1384
1385static void hdmi_core_audio_infoframe_config(
1386 struct hdmi_core_infoframe_audio *info_aud)
1387{
1388 u8 val;
1389 u8 sum = 0, checksum = 0;
1390
1391 /*
1392 * Set audio info frame type, version and length as
1393 * described in HDMI 1.4a Section 8.2.2 specification.
1394 * Checksum calculation is defined in Section 5.3.5.
1395 */
1396 hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1397 hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
1398 hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1399 sum += 0x84 + 0x001 + 0x00a;
1400
1401 val = (info_aud->db1_coding_type << 4)
1402 | (info_aud->db1_channel_count - 1);
1403 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
1404 sum += val;
1405
1406 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
1407 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
1408 sum += val;
1409
1410 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
1411
1412 val = info_aud->db4_channel_alloc;
1413 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
1414 sum += val;
1415
1416 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
1417 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
1418 sum += val;
1419
1420 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1421 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1422 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1423 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1424 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
1425
1426 checksum = 0x100 - sum;
1427 hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
1428
1429 /*
1430 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1431 * is available.
1432 */
1433}
1434
1435static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
1436{
1437 u32 r;
1438 u32 deep_color = 0;
1439 u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
1440
1441 if (n == NULL || cts == NULL)
1442 return -EINVAL;
1443 /*
1444 * Obtain current deep color configuration. This needed
1445 * to calculate the TMDS clock based on the pixel clock.
1446 */
1447 r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
1448 switch (r) {
1449 case 1: /* No deep color selected */
1450 deep_color = 100;
1451 break;
1452 case 2: /* 10-bit deep color selected */
1453 deep_color = 125;
1454 break;
1455 case 3: /* 12-bit deep color selected */
1456 deep_color = 150;
1457 break;
1458 default:
1459 return -EINVAL;
1460 }
1461
1462 switch (sample_freq) {
1463 case 32000:
1464 if ((deep_color == 125) && ((pclk == 54054)
1465 || (pclk == 74250)))
1466 *n = 8192;
1467 else
1468 *n = 4096;
1469 break;
1470 case 44100:
1471 *n = 6272;
1472 break;
1473 case 48000:
1474 if ((deep_color == 125) && ((pclk == 54054)
1475 || (pclk == 74250)))
1476 *n = 8192;
1477 else
1478 *n = 6144;
1479 break;
1480 default:
1481 *n = 0;
1482 return -EINVAL;
1483 }
1484
1485 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
1486 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
1487
1488 return 0;
1489}
1490#endif
1491
1277/* HDMI HW IP initialisation */ 1492/* HDMI HW IP initialisation */
1278static int omapdss_hdmihw_probe(struct platform_device *pdev) 1493static int omapdss_hdmihw_probe(struct platform_device *pdev)
1279{ 1494{