aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-05-11 08:38:23 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-05-11 08:38:23 -0400
commit037983e61b61e82fa28fea38d02e354d74c66bab (patch)
tree8d502829f3b27b5d8b587fb965919260d832497a
parent38137c8f0ce8dfaea467884cb2eb45de8df1bdfc (diff)
parentf3a97491f2c54e5239663f8f147b34c280cf7db5 (diff)
Merge branch 'omapdss-hdmi-audio'
Merge OMAP DSS HDMI audio patches from Ricardo Neri
-rw-r--r--Documentation/arm/OMAP/DSS45
-rw-r--r--drivers/video/omap2/dss/Kconfig4
-rw-r--r--drivers/video/omap2/dss/dss.h8
-rw-r--r--drivers/video/omap2/dss/dss_features.c8
-rw-r--r--drivers/video/omap2/dss/hdmi.c359
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c236
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h32
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c316
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h104
-rw-r--r--include/video/omapdss.h34
10 files changed, 710 insertions, 436 deletions
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
index d0aea9192204..a564ceea9e98 100644
--- a/Documentation/arm/OMAP/DSS
+++ b/Documentation/arm/OMAP/DSS
@@ -47,6 +47,51 @@ flexible way to enable non-common multi-display configuration. In addition to
47modelling the hardware overlays, omapdss supports virtual overlays and overlay 47modelling the hardware overlays, omapdss supports virtual overlays and overlay
48managers. These can be used when updating a display with CPU or system DMA. 48managers. These can be used when updating a display with CPU or system DMA.
49 49
50omapdss driver support for audio
51--------------------------------
52There exist several display technologies and standards that support audio as
53well. Hence, it is relevant to update the DSS device driver to provide an audio
54interface that may be used by an audio driver or any other driver interested in
55the functionality.
56
57The audio_enable function is intended to prepare the relevant
58IP for playback (e.g., enabling an audio FIFO, taking in/out of reset
59some IP, enabling companion chips, etc). It is intended to be called before
60audio_start. The audio_disable function performs the reverse operation and is
61intended to be called after audio_stop.
62
63While a given DSS device driver may support audio, it is possible that for
64certain configurations audio is not supported (e.g., an HDMI display using a
65VESA video timing). The audio_supported function is intended to query whether
66the current configuration of the display supports audio.
67
68The audio_config function is intended to configure all the relevant audio
69parameters of the display. In order to make the function independent of any
70specific DSS device driver, a struct omap_dss_audio is defined. Its purpose
71is to contain all the required parameters for audio configuration. At the
72moment, such structure contains pointers to IEC-60958 channel status word
73and CEA-861 audio infoframe structures. This should be enough to support
74HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958.
75
76The audio_enable/disable, audio_config and audio_supported functions could be
77implemented as functions that may sleep. Hence, they should not be called
78while holding a spinlock or a readlock.
79
80The audio_start/audio_stop function is intended to effectively start/stop audio
81playback after the configuration has taken place. These functions are designed
82to be used in an atomic context. Hence, audio_start should return quickly and be
83called only after all the needed resources for audio playback (audio FIFOs,
84DMA channels, companion chips, etc) have been enabled to begin data transfers.
85audio_stop is designed to only stop the audio transfers. The resources used
86for playback are released using audio_disable.
87
88The enum omap_dss_audio_state may be used to help the implementations of
89the interface to keep track of the audio state. The initial state is _DISABLED;
90then, the state transitions to _CONFIGURED, and then, when it is ready to
91play audio, to _ENABLED. The state _PLAYING is used when the audio is being
92rendered.
93
94
50Panel and controller drivers 95Panel and controller drivers
51---------------------------- 96----------------------------
52 97
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 9aaf3246f821..43324e5ed25f 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -68,6 +68,10 @@ config OMAP4_DSS_HDMI
68 HDMI Interface. This adds the High Definition Multimedia Interface. 68 HDMI Interface. This adds the High Definition Multimedia Interface.
69 See http://www.hdmi.org/ for HDMI specification. 69 See http://www.hdmi.org/ for HDMI specification.
70 70
71config OMAP4_DSS_HDMI_AUDIO
72 bool
73 depends on OMAP4_DSS_HDMI
74
71config OMAP2_DSS_SDI 75config OMAP2_DSS_SDI
72 bool "SDI support" 76 bool "SDI support"
73 depends on ARCH_OMAP3 77 depends on ARCH_OMAP3
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index d5cb19fe7e8b..4aa9529a4768 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -464,6 +464,14 @@ int omapdss_hdmi_read_edid(u8 *buf, int len);
464bool omapdss_hdmi_detect(void); 464bool omapdss_hdmi_detect(void);
465int hdmi_panel_init(void); 465int hdmi_panel_init(void);
466void hdmi_panel_exit(void); 466void hdmi_panel_exit(void);
467#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
468int hdmi_audio_enable(void);
469void hdmi_audio_disable(void);
470int hdmi_audio_start(void);
471void hdmi_audio_stop(void);
472bool hdmi_mode_has_audio(void);
473int hdmi_audio_config(struct omap_dss_audio *audio);
474#endif
467 475
468/* RFBI */ 476/* RFBI */
469int rfbi_init_platform_driver(void) __init; 477int rfbi_init_platform_driver(void) __init;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 1d10a014bc55..2627441731b1 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -568,13 +568,17 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
568 .pll_enable = ti_hdmi_4xxx_pll_enable, 568 .pll_enable = ti_hdmi_4xxx_pll_enable,
569 .pll_disable = ti_hdmi_4xxx_pll_disable, 569 .pll_disable = ti_hdmi_4xxx_pll_disable,
570 .video_enable = ti_hdmi_4xxx_wp_video_start, 570 .video_enable = ti_hdmi_4xxx_wp_video_start,
571 .video_disable = ti_hdmi_4xxx_wp_video_stop,
571 .dump_wrapper = ti_hdmi_4xxx_wp_dump, 572 .dump_wrapper = ti_hdmi_4xxx_wp_dump,
572 .dump_core = ti_hdmi_4xxx_core_dump, 573 .dump_core = ti_hdmi_4xxx_core_dump,
573 .dump_pll = ti_hdmi_4xxx_pll_dump, 574 .dump_pll = ti_hdmi_4xxx_pll_dump,
574 .dump_phy = ti_hdmi_4xxx_phy_dump, 575 .dump_phy = ti_hdmi_4xxx_phy_dump,
575#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 576#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
576 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
577 .audio_enable = ti_hdmi_4xxx_wp_audio_enable, 577 .audio_enable = ti_hdmi_4xxx_wp_audio_enable,
578 .audio_disable = ti_hdmi_4xxx_wp_audio_disable,
579 .audio_start = ti_hdmi_4xxx_audio_start,
580 .audio_stop = ti_hdmi_4xxx_audio_stop,
581 .audio_config = ti_hdmi_4xxx_audio_config,
578#endif 582#endif
579 583
580}; 584};
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 5f2e2f677bef..8195c7166d20 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -33,12 +33,6 @@
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <video/omapdss.h> 35#include <video/omapdss.h>
36#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
37 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
38#include <sound/soc.h>
39#include <sound/pcm_params.h>
40#include "ti_hdmi_4xxx_ip.h"
41#endif
42 36
43#include "ti_hdmi.h" 37#include "ti_hdmi.h"
44#include "dss.h" 38#include "dss.h"
@@ -324,7 +318,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
324 318
325 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 319 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
326 320
327 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 321 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
328 322
329 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 323 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
330 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 324 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
@@ -358,7 +352,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
358 /* tv size */ 352 /* tv size */
359 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 353 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
360 354
361 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); 355 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
356 if (r)
357 goto err_vid_enable;
362 358
363 r = dss_mgr_enable(dssdev->manager); 359 r = dss_mgr_enable(dssdev->manager);
364 if (r) 360 if (r)
@@ -367,7 +363,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
367 return 0; 363 return 0;
368 364
369err_mgr_enable: 365err_mgr_enable:
370 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 366 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
367err_vid_enable:
371 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 368 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
372 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 369 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
373err: 370err:
@@ -379,7 +376,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
379{ 376{
380 dss_mgr_disable(dssdev->manager); 377 dss_mgr_disable(dssdev->manager);
381 378
382 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 379 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
383 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 380 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
384 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 381 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
385 hdmi_runtime_put(); 382 hdmi_runtime_put();
@@ -536,241 +533,171 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
536 mutex_unlock(&hdmi.lock); 533 mutex_unlock(&hdmi.lock);
537} 534}
538 535
539#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 536static int hdmi_get_clocks(struct platform_device *pdev)
540 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
541
542static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
543 struct snd_soc_dai *dai)
544{ 537{
545 struct snd_soc_pcm_runtime *rtd = substream->private_data; 538 struct clk *clk;
546 struct snd_soc_codec *codec = rtd->codec;
547 struct platform_device *pdev = to_platform_device(codec->dev);
548 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
549 int err = 0;
550 539
551 if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) { 540 clk = clk_get(&pdev->dev, "sys_clk");
552 dev_err(&pdev->dev, "Cannot enable/disable audio\n"); 541 if (IS_ERR(clk)) {
553 return -ENODEV; 542 DSSERR("can't get sys_clk\n");
543 return PTR_ERR(clk);
554 } 544 }
555 545
556 switch (cmd) { 546 hdmi.sys_clk = clk;
557 case SNDRV_PCM_TRIGGER_START: 547
558 case SNDRV_PCM_TRIGGER_RESUME: 548 return 0;
559 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 549}
560 ip_data->ops->audio_enable(ip_data, true); 550
561 break; 551static void hdmi_put_clocks(void)
562 case SNDRV_PCM_TRIGGER_STOP: 552{
563 case SNDRV_PCM_TRIGGER_SUSPEND: 553 if (hdmi.sys_clk)
564 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 554 clk_put(hdmi.sys_clk);
565 ip_data->ops->audio_enable(ip_data, false); 555}
566 break; 556
567 default: 557#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
568 err = -EINVAL; 558int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
569 } 559{
570 return err; 560 u32 deep_color;
571} 561 bool deep_color_correct = false;
572 562 u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
573static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, 563
574 struct snd_pcm_hw_params *params, 564 if (n == NULL || cts == NULL)
575 struct snd_soc_dai *dai)
576{
577 struct snd_soc_pcm_runtime *rtd = substream->private_data;
578 struct snd_soc_codec *codec = rtd->codec;
579 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
580 struct hdmi_audio_format audio_format;
581 struct hdmi_audio_dma audio_dma;
582 struct hdmi_core_audio_config core_cfg;
583 struct hdmi_core_infoframe_audio aud_if_cfg;
584 int err, n, cts;
585 enum hdmi_core_audio_sample_freq sample_freq;
586
587 switch (params_format(params)) {
588 case SNDRV_PCM_FORMAT_S16_LE:
589 core_cfg.i2s_cfg.word_max_length =
590 HDMI_AUDIO_I2S_MAX_WORD_20BITS;
591 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
592 core_cfg.i2s_cfg.in_length_bits =
593 HDMI_AUDIO_I2S_INPUT_LENGTH_16;
594 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
595 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
596 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
597 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
598 audio_dma.transfer_size = 0x10;
599 break;
600 case SNDRV_PCM_FORMAT_S24_LE:
601 core_cfg.i2s_cfg.word_max_length =
602 HDMI_AUDIO_I2S_MAX_WORD_24BITS;
603 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
604 core_cfg.i2s_cfg.in_length_bits =
605 HDMI_AUDIO_I2S_INPUT_LENGTH_24;
606 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
607 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
608 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
609 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
610 audio_dma.transfer_size = 0x20;
611 break;
612 default:
613 return -EINVAL; 565 return -EINVAL;
614 }
615 566
616 switch (params_rate(params)) { 567 /* TODO: When implemented, query deep color mode here. */
568 deep_color = 100;
569
570 /*
571 * When using deep color, the default N value (as in the HDMI
572 * specification) yields to an non-integer CTS. Hence, we
573 * modify it while keeping the restrictions described in
574 * section 7.2.1 of the HDMI 1.4a specification.
575 */
576 switch (sample_freq) {
617 case 32000: 577 case 32000:
618 sample_freq = HDMI_AUDIO_FS_32000; 578 case 48000:
579 case 96000:
580 case 192000:
581 if (deep_color == 125)
582 if (pclk == 27027 || pclk == 74250)
583 deep_color_correct = true;
584 if (deep_color == 150)
585 if (pclk == 27027)
586 deep_color_correct = true;
619 break; 587 break;
620 case 44100: 588 case 44100:
621 sample_freq = HDMI_AUDIO_FS_44100; 589 case 88200:
622 break; 590 case 176400:
623 case 48000: 591 if (deep_color == 125)
624 sample_freq = HDMI_AUDIO_FS_48000; 592 if (pclk == 27027)
593 deep_color_correct = true;
625 break; 594 break;
626 default: 595 default:
627 return -EINVAL; 596 return -EINVAL;
628 } 597 }
629 598
630 err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); 599 if (deep_color_correct) {
631 if (err < 0) 600 switch (sample_freq) {
632 return err; 601 case 32000:
633 602 *n = 8192;
634 /* Audio wrapper config */ 603 break;
635 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; 604 case 44100:
636 audio_format.active_chnnls_msk = 0x03; 605 *n = 12544;
637 audio_format.type = HDMI_AUDIO_TYPE_LPCM; 606 break;
638 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; 607 case 48000:
639 /* Disable start/stop signals of IEC 60958 blocks */ 608 *n = 8192;
640 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; 609 break;
641 610 case 88200:
642 audio_dma.block_size = 0xC0; 611 *n = 25088;
643 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; 612 break;
644 audio_dma.fifo_threshold = 0x20; /* in number of samples */ 613 case 96000:
645 614 *n = 16384;
646 hdmi_wp_audio_config_dma(ip_data, &audio_dma); 615 break;
647 hdmi_wp_audio_config_format(ip_data, &audio_format); 616 case 176400:
648 617 *n = 50176;
649 /* 618 break;
650 * I2S config 619 case 192000:
651 */ 620 *n = 32768;
652 core_cfg.i2s_cfg.en_high_bitrate_aud = false; 621 break;
653 /* Only used with high bitrate audio */ 622 default:
654 core_cfg.i2s_cfg.cbit_order = false; 623 return -EINVAL;
655 /* Serial data and word select should change on sck rising edge */ 624 }
656 core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
657 core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
658 /* Set I2S word select polarity */
659 core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
660 core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
661 /* Set serial data to word select shift. See Phillips spec. */
662 core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
663 /* Enable one of the four available serial data channels */
664 core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
665
666 /* Core audio config */
667 core_cfg.freq_sample = sample_freq;
668 core_cfg.n = n;
669 core_cfg.cts = cts;
670 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
671 core_cfg.aud_par_busclk = 0;
672 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
673 core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
674 } else { 625 } else {
675 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); 626 switch (sample_freq) {
676 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; 627 case 32000:
677 core_cfg.use_mclk = true; 628 *n = 4096;
629 break;
630 case 44100:
631 *n = 6272;
632 break;
633 case 48000:
634 *n = 6144;
635 break;
636 case 88200:
637 *n = 12544;
638 break;
639 case 96000:
640 *n = 12288;
641 break;
642 case 176400:
643 *n = 25088;
644 break;
645 case 192000:
646 *n = 24576;
647 break;
648 default:
649 return -EINVAL;
650 }
678 } 651 }
652 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
653 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
679 654
680 if (core_cfg.use_mclk)
681 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
682 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
683 core_cfg.en_spdif = false;
684 /* Use sample frequency from channel status word */
685 core_cfg.fs_override = true;
686 /* Enable ACR packets */
687 core_cfg.en_acr_pkt = true;
688 /* Disable direct streaming digital audio */
689 core_cfg.en_dsd_audio = false;
690 /* Use parallel audio interface */
691 core_cfg.en_parallel_aud_input = true;
692
693 hdmi_core_audio_config(ip_data, &core_cfg);
694
695 /*
696 * Configure packet
697 * info frame audio see doc CEA861-D page 74
698 */
699 aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
700 aud_if_cfg.db1_channel_count = 2;
701 aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
702 aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
703 aud_if_cfg.db4_channel_alloc = 0x00;
704 aud_if_cfg.db5_downmix_inh = false;
705 aud_if_cfg.db5_lsv = 0;
706
707 hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
708 return 0; 655 return 0;
709} 656}
710 657
711static int hdmi_audio_startup(struct snd_pcm_substream *substream, 658int hdmi_audio_enable(void)
712 struct snd_soc_dai *dai)
713{ 659{
714 if (!hdmi.ip_data.cfg.cm.mode) { 660 DSSDBG("audio_enable\n");
715 pr_err("Current video settings do not support audio.\n"); 661
716 return -EIO; 662 return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
717 }
718 return 0;
719} 663}
720 664
721static int hdmi_audio_codec_probe(struct snd_soc_codec *codec) 665void hdmi_audio_disable(void)
722{ 666{
723 struct hdmi_ip_data *priv = &hdmi.ip_data; 667 DSSDBG("audio_disable\n");
724 668
725 snd_soc_codec_set_drvdata(codec, priv); 669 hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
726 return 0;
727} 670}
728 671
729static struct snd_soc_codec_driver hdmi_audio_codec_drv = { 672int hdmi_audio_start(void)
730 .probe = hdmi_audio_codec_probe, 673{
731}; 674 DSSDBG("audio_start\n");
732
733static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
734 .hw_params = hdmi_audio_hw_params,
735 .trigger = hdmi_audio_trigger,
736 .startup = hdmi_audio_startup,
737};
738 675
739static struct snd_soc_dai_driver hdmi_codec_dai_drv = { 676 return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
740 .name = "hdmi-audio-codec", 677}
741 .playback = {
742 .channels_min = 2,
743 .channels_max = 2,
744 .rates = SNDRV_PCM_RATE_32000 |
745 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
746 .formats = SNDRV_PCM_FMTBIT_S16_LE |
747 SNDRV_PCM_FMTBIT_S24_LE,
748 },
749 .ops = &hdmi_audio_codec_ops,
750};
751#endif
752 678
753static int hdmi_get_clocks(struct platform_device *pdev) 679void hdmi_audio_stop(void)
754{ 680{
755 struct clk *clk; 681 DSSDBG("audio_stop\n");
756 682
757 clk = clk_get(&pdev->dev, "sys_clk"); 683 hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
758 if (IS_ERR(clk)) { 684}
759 DSSERR("can't get sys_clk\n");
760 return PTR_ERR(clk);
761 }
762
763 hdmi.sys_clk = clk;
764 685
765 return 0; 686bool hdmi_mode_has_audio(void)
687{
688 if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
689 return true;
690 else
691 return false;
766} 692}
767 693
768static void hdmi_put_clocks(void) 694int hdmi_audio_config(struct omap_dss_audio *audio)
769{ 695{
770 if (hdmi.sys_clk) 696 return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
771 clk_put(hdmi.sys_clk);
772} 697}
773 698
699#endif
700
774static void __init hdmi_probe_pdata(struct platform_device *pdev) 701static void __init hdmi_probe_pdata(struct platform_device *pdev)
775{ 702{
776 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 703 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
@@ -838,17 +765,6 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
838 765
839 hdmi_probe_pdata(pdev); 766 hdmi_probe_pdata(pdev);
840 767
841#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
842 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
843
844 /* Register ASoC codec DAI */
845 r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
846 &hdmi_codec_dai_drv, 1);
847 if (r) {
848 DSSERR("can't register ASoC HDMI audio codec\n");
849 return r;
850 }
851#endif
852 return 0; 768 return 0;
853} 769}
854 770
@@ -858,11 +774,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
858 774
859 hdmi_panel_exit(); 775 hdmi_panel_exit();
860 776
861#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
862 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
863 snd_soc_unregister_codec(&pdev->dev);
864#endif
865
866 pm_runtime_disable(&pdev->dev); 777 pm_runtime_disable(&pdev->dev);
867 778
868 hdmi_put_clocks(); 779 hdmi_put_clocks();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 533d5dc634d2..1179e3c4b1c7 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -30,7 +30,12 @@
30#include "dss.h" 30#include "dss.h"
31 31
32static struct { 32static struct {
33 struct mutex hdmi_lock; 33 /* This protects the panel ops, mainly when accessing the HDMI IP. */
34 struct mutex lock;
35#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
36 /* This protects the audio ops, specifically. */
37 spinlock_t audio_lock;
38#endif
34} hdmi; 39} hdmi;
35 40
36 41
@@ -54,12 +59,168 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev)
54 59
55} 60}
56 61
62#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
63static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
64{
65 unsigned long flags;
66 int r;
67
68 mutex_lock(&hdmi.lock);
69 spin_lock_irqsave(&hdmi.audio_lock, flags);
70
71 /* enable audio only if the display is active and supports audio */
72 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
73 !hdmi_mode_has_audio()) {
74 DSSERR("audio not supported or display is off\n");
75 r = -EPERM;
76 goto err;
77 }
78
79 r = hdmi_audio_enable();
80
81 if (!r)
82 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
83
84err:
85 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
86 mutex_unlock(&hdmi.lock);
87 return r;
88}
89
90static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
91{
92 unsigned long flags;
93
94 spin_lock_irqsave(&hdmi.audio_lock, flags);
95
96 hdmi_audio_disable();
97
98 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
99
100 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
101}
102
103static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
104{
105 unsigned long flags;
106 int r;
107
108 spin_lock_irqsave(&hdmi.audio_lock, flags);
109 /*
110 * No need to check the panel state. It was checked when trasitioning
111 * to AUDIO_ENABLED.
112 */
113 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
114 DSSERR("audio start from invalid state\n");
115 r = -EPERM;
116 goto err;
117 }
118
119 r = hdmi_audio_start();
120
121 if (!r)
122 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
123
124err:
125 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
126 return r;
127}
128
129static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
130{
131 unsigned long flags;
132
133 spin_lock_irqsave(&hdmi.audio_lock, flags);
134
135 hdmi_audio_stop();
136 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
137
138 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
139}
140
141static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
142{
143 bool r = false;
144
145 mutex_lock(&hdmi.lock);
146
147 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
148 goto err;
149
150 if (!hdmi_mode_has_audio())
151 goto err;
152
153 r = true;
154err:
155 mutex_unlock(&hdmi.lock);
156 return r;
157}
158
159static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
160 struct omap_dss_audio *audio)
161{
162 unsigned long flags;
163 int r;
164
165 mutex_lock(&hdmi.lock);
166 spin_lock_irqsave(&hdmi.audio_lock, flags);
167
168 /* config audio only if the display is active and supports audio */
169 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
170 !hdmi_mode_has_audio()) {
171 DSSERR("audio not supported or display is off\n");
172 r = -EPERM;
173 goto err;
174 }
175
176 r = hdmi_audio_config(audio);
177
178 if (!r)
179 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
180
181err:
182 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
183 mutex_unlock(&hdmi.lock);
184 return r;
185}
186
187#else
188static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
189{
190 return -EPERM;
191}
192
193static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
194{
195}
196
197static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
198{
199 return -EPERM;
200}
201
202static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
203{
204}
205
206static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
207{
208 return false;
209}
210
211static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
212 struct omap_dss_audio *audio)
213{
214 return -EPERM;
215}
216#endif
217
57static int hdmi_panel_enable(struct omap_dss_device *dssdev) 218static int hdmi_panel_enable(struct omap_dss_device *dssdev)
58{ 219{
59 int r = 0; 220 int r = 0;
60 DSSDBG("ENTER hdmi_panel_enable\n"); 221 DSSDBG("ENTER hdmi_panel_enable\n");
61 222
62 mutex_lock(&hdmi.hdmi_lock); 223 mutex_lock(&hdmi.lock);
63 224
64 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 225 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
65 r = -EINVAL; 226 r = -EINVAL;
@@ -75,40 +236,52 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
75 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 236 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
76 237
77err: 238err:
78 mutex_unlock(&hdmi.hdmi_lock); 239 mutex_unlock(&hdmi.lock);
79 240
80 return r; 241 return r;
81} 242}
82 243
83static void hdmi_panel_disable(struct omap_dss_device *dssdev) 244static void hdmi_panel_disable(struct omap_dss_device *dssdev)
84{ 245{
85 mutex_lock(&hdmi.hdmi_lock); 246 mutex_lock(&hdmi.lock);
86 247
87 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 248 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
249 /*
250 * TODO: notify audio users that the display was disabled. For
251 * now, disable audio locally to not break our audio state
252 * machine.
253 */
254 hdmi_panel_audio_disable(dssdev);
88 omapdss_hdmi_display_disable(dssdev); 255 omapdss_hdmi_display_disable(dssdev);
256 }
89 257
90 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 258 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
91 259
92 mutex_unlock(&hdmi.hdmi_lock); 260 mutex_unlock(&hdmi.lock);
93} 261}
94 262
95static int hdmi_panel_suspend(struct omap_dss_device *dssdev) 263static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
96{ 264{
97 int r = 0; 265 int r = 0;
98 266
99 mutex_lock(&hdmi.hdmi_lock); 267 mutex_lock(&hdmi.lock);
100 268
101 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 269 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
102 r = -EINVAL; 270 r = -EINVAL;
103 goto err; 271 goto err;
104 } 272 }
105 273
106 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 274 /*
275 * TODO: notify audio users that the display was suspended. For now,
276 * disable audio locally to not break our audio state machine.
277 */
278 hdmi_panel_audio_disable(dssdev);
107 279
280 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
108 omapdss_hdmi_display_disable(dssdev); 281 omapdss_hdmi_display_disable(dssdev);
109 282
110err: 283err:
111 mutex_unlock(&hdmi.hdmi_lock); 284 mutex_unlock(&hdmi.lock);
112 285
113 return r; 286 return r;
114} 287}
@@ -117,7 +290,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
117{ 290{
118 int r = 0; 291 int r = 0;
119 292
120 mutex_lock(&hdmi.hdmi_lock); 293 mutex_lock(&hdmi.lock);
121 294
122 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { 295 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
123 r = -EINVAL; 296 r = -EINVAL;
@@ -129,11 +302,12 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
129 DSSERR("failed to power on\n"); 302 DSSERR("failed to power on\n");
130 goto err; 303 goto err;
131 } 304 }
305 /* TODO: notify audio users that the panel resumed. */
132 306
133 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 307 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
134 308
135err: 309err:
136 mutex_unlock(&hdmi.hdmi_lock); 310 mutex_unlock(&hdmi.lock);
137 311
138 return r; 312 return r;
139} 313}
@@ -141,11 +315,11 @@ err:
141static void hdmi_get_timings(struct omap_dss_device *dssdev, 315static void hdmi_get_timings(struct omap_dss_device *dssdev,
142 struct omap_video_timings *timings) 316 struct omap_video_timings *timings)
143{ 317{
144 mutex_lock(&hdmi.hdmi_lock); 318 mutex_lock(&hdmi.lock);
145 319
146 *timings = dssdev->panel.timings; 320 *timings = dssdev->panel.timings;
147 321
148 mutex_unlock(&hdmi.hdmi_lock); 322 mutex_unlock(&hdmi.lock);
149} 323}
150 324
151static void hdmi_set_timings(struct omap_dss_device *dssdev, 325static void hdmi_set_timings(struct omap_dss_device *dssdev,
@@ -153,12 +327,18 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
153{ 327{
154 DSSDBG("hdmi_set_timings\n"); 328 DSSDBG("hdmi_set_timings\n");
155 329
156 mutex_lock(&hdmi.hdmi_lock); 330 mutex_lock(&hdmi.lock);
331
332 /*
333 * TODO: notify audio users that there was a timings change. For
334 * now, disable audio locally to not break our audio state machine.
335 */
336 hdmi_panel_audio_disable(dssdev);
157 337
158 dssdev->panel.timings = *timings; 338 dssdev->panel.timings = *timings;
159 omapdss_hdmi_display_set_timing(dssdev); 339 omapdss_hdmi_display_set_timing(dssdev);
160 340
161 mutex_unlock(&hdmi.hdmi_lock); 341 mutex_unlock(&hdmi.lock);
162} 342}
163 343
164static int hdmi_check_timings(struct omap_dss_device *dssdev, 344static int hdmi_check_timings(struct omap_dss_device *dssdev,
@@ -168,11 +348,11 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
168 348
169 DSSDBG("hdmi_check_timings\n"); 349 DSSDBG("hdmi_check_timings\n");
170 350
171 mutex_lock(&hdmi.hdmi_lock); 351 mutex_lock(&hdmi.lock);
172 352
173 r = omapdss_hdmi_display_check_timing(dssdev, timings); 353 r = omapdss_hdmi_display_check_timing(dssdev, timings);
174 354
175 mutex_unlock(&hdmi.hdmi_lock); 355 mutex_unlock(&hdmi.lock);
176 return r; 356 return r;
177} 357}
178 358
@@ -180,7 +360,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
180{ 360{
181 int r; 361 int r;
182 362
183 mutex_lock(&hdmi.hdmi_lock); 363 mutex_lock(&hdmi.lock);
184 364
185 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 365 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
186 r = omapdss_hdmi_display_enable(dssdev); 366 r = omapdss_hdmi_display_enable(dssdev);
@@ -194,7 +374,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
194 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 374 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
195 omapdss_hdmi_display_disable(dssdev); 375 omapdss_hdmi_display_disable(dssdev);
196err: 376err:
197 mutex_unlock(&hdmi.hdmi_lock); 377 mutex_unlock(&hdmi.lock);
198 378
199 return r; 379 return r;
200} 380}
@@ -203,7 +383,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
203{ 383{
204 int r; 384 int r;
205 385
206 mutex_lock(&hdmi.hdmi_lock); 386 mutex_lock(&hdmi.lock);
207 387
208 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 388 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
209 r = omapdss_hdmi_display_enable(dssdev); 389 r = omapdss_hdmi_display_enable(dssdev);
@@ -217,7 +397,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
217 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 397 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
218 omapdss_hdmi_display_disable(dssdev); 398 omapdss_hdmi_display_disable(dssdev);
219err: 399err:
220 mutex_unlock(&hdmi.hdmi_lock); 400 mutex_unlock(&hdmi.lock);
221 401
222 return r; 402 return r;
223} 403}
@@ -234,6 +414,12 @@ static struct omap_dss_driver hdmi_driver = {
234 .check_timings = hdmi_check_timings, 414 .check_timings = hdmi_check_timings,
235 .read_edid = hdmi_read_edid, 415 .read_edid = hdmi_read_edid,
236 .detect = hdmi_detect, 416 .detect = hdmi_detect,
417 .audio_enable = hdmi_panel_audio_enable,
418 .audio_disable = hdmi_panel_audio_disable,
419 .audio_start = hdmi_panel_audio_start,
420 .audio_stop = hdmi_panel_audio_stop,
421 .audio_supported = hdmi_panel_audio_supported,
422 .audio_config = hdmi_panel_audio_config,
237 .driver = { 423 .driver = {
238 .name = "hdmi_panel", 424 .name = "hdmi_panel",
239 .owner = THIS_MODULE, 425 .owner = THIS_MODULE,
@@ -242,7 +428,11 @@ static struct omap_dss_driver hdmi_driver = {
242 428
243int hdmi_panel_init(void) 429int hdmi_panel_init(void)
244{ 430{
245 mutex_init(&hdmi.hdmi_lock); 431 mutex_init(&hdmi.lock);
432
433#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
434 spin_lock_init(&hdmi.audio_lock);
435#endif
246 436
247 omap_dss_register_driver(&hdmi_driver); 437 omap_dss_register_driver(&hdmi_driver);
248 438
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 1f58b84d6901..e734cb444bc7 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -96,7 +96,9 @@ struct ti_hdmi_ip_ops {
96 96
97 void (*pll_disable)(struct hdmi_ip_data *ip_data); 97 void (*pll_disable)(struct hdmi_ip_data *ip_data);
98 98
99 void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); 99 int (*video_enable)(struct hdmi_ip_data *ip_data);
100
101 void (*video_disable)(struct hdmi_ip_data *ip_data);
100 102
101 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); 103 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
102 104
@@ -106,9 +108,17 @@ struct ti_hdmi_ip_ops {
106 108
107 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); 109 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
108 110
109#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 111#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
110 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 112 int (*audio_enable)(struct hdmi_ip_data *ip_data);
111 void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start); 113
114 void (*audio_disable)(struct hdmi_ip_data *ip_data);
115
116 int (*audio_start)(struct hdmi_ip_data *ip_data);
117
118 void (*audio_stop)(struct hdmi_ip_data *ip_data);
119
120 int (*audio_config)(struct hdmi_ip_data *ip_data,
121 struct omap_dss_audio *audio);
112#endif 122#endif
113 123
114}; 124};
@@ -173,7 +183,8 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
173void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); 183void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
174int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); 184int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
175bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); 185bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
176void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); 186int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data);
187void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data);
177int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); 188int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
178void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); 189void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
179void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); 190void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
@@ -181,8 +192,13 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
181void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 192void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
182void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 193void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
183void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 194void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
184#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 195#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
185 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 196int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts);
186void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable); 197int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
198void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
199int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
200void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
201int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
202 struct omap_dss_audio *audio);
187#endif 203#endif
188#endif 204#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index 35f59e47d7fe..667c960e10b9 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -29,9 +29,14 @@
29#include <linux/string.h> 29#include <linux/string.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/gpio.h> 31#include <linux/gpio.h>
32#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
33#include <sound/asound.h>
34#include <sound/asoundef.h>
35#endif
32 36
33#include "ti_hdmi_4xxx_ip.h" 37#include "ti_hdmi_4xxx_ip.h"
34#include "dss.h" 38#include "dss.h"
39#include "dss_features.h"
35 40
36static inline void hdmi_write_reg(void __iomem *base_addr, 41static inline void hdmi_write_reg(void __iomem *base_addr,
37 const u16 idx, u32 val) 42 const u16 idx, u32 val)
@@ -699,9 +704,15 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
699 704
700} 705}
701 706
702void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) 707int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data)
708{
709 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31);
710 return 0;
711}
712
713void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data)
703{ 714{
704 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); 715 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31);
705} 716}
706 717
707static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, 718static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
@@ -1014,9 +1025,8 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
1014 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); 1025 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
1015} 1026}
1016 1027
1017#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 1028#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1018 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 1029static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1019void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1020 struct hdmi_audio_format *aud_fmt) 1030 struct hdmi_audio_format *aud_fmt)
1021{ 1031{
1022 u32 r; 1032 u32 r;
@@ -1035,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1035 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); 1045 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
1036} 1046}
1037 1047
1038void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, 1048static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1039 struct hdmi_audio_dma *aud_dma) 1049 struct hdmi_audio_dma *aud_dma)
1040{ 1050{
1041 u32 r; 1051 u32 r;
@@ -1053,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1053 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); 1063 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
1054} 1064}
1055 1065
1056void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, 1066static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data,
1057 struct hdmi_core_audio_config *cfg) 1067 struct hdmi_core_audio_config *cfg)
1058{ 1068{
1059 u32 r; 1069 u32 r;
@@ -1104,27 +1114,33 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1104 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, 1114 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
1105 cfg->fs_override, 1, 1); 1115 cfg->fs_override, 1, 1);
1106 1116
1107 /* I2S parameters */ 1117 /*
1108 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, 1118 * Set IEC-60958-3 channel status word. It is passed to the IP
1109 cfg->freq_sample, 3, 0); 1119 * just as it is received. The user of the driver is responsible
1110 1120 * for its contents.
1121 */
1122 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
1123 cfg->iec60958_cfg->status[0]);
1124 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
1125 cfg->iec60958_cfg->status[1]);
1126 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
1127 cfg->iec60958_cfg->status[2]);
1128 /* yes, this is correct: status[3] goes to CHST4 register */
1129 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
1130 cfg->iec60958_cfg->status[3]);
1131 /* yes, this is correct: status[4] goes to CHST5 register */
1132 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
1133 cfg->iec60958_cfg->status[4]);
1134
1135 /* set I2S parameters */
1111 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); 1136 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
1112 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1113 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); 1137 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1114 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1115 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); 1138 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1116 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1117 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); 1139 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1118 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); 1140 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1119 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); 1141 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1120 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); 1142 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
1121 1143
1122 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5);
1123 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1124 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1125 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1126 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r);
1127
1128 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, 1144 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
1129 cfg->i2s_cfg.in_length_bits, 3, 0); 1145 cfg->i2s_cfg.in_length_bits, 3, 0);
1130 1146
@@ -1136,12 +1152,19 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1136 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); 1152 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1137 r = FLD_MOD(r, cfg->en_spdif, 1, 1); 1153 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1138 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); 1154 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
1155
1156 /* Audio channel mappings */
1157 /* TODO: Make channel mapping dynamic. For now, map channels
1158 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
1159 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
1160 */
1161 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
1162 REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
1139} 1163}
1140 1164
1141void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, 1165static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data,
1142 struct hdmi_core_infoframe_audio *info_aud) 1166 struct snd_cea_861_aud_if *info_aud)
1143{ 1167{
1144 u8 val;
1145 u8 sum = 0, checksum = 0; 1168 u8 sum = 0, checksum = 0;
1146 void __iomem *av_base = hdmi_av_base(ip_data); 1169 void __iomem *av_base = hdmi_av_base(ip_data);
1147 1170
@@ -1155,24 +1178,23 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
1155 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); 1178 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1156 sum += 0x84 + 0x001 + 0x00a; 1179 sum += 0x84 + 0x001 + 0x00a;
1157 1180
1158 val = (info_aud->db1_coding_type << 4) 1181 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
1159 | (info_aud->db1_channel_count - 1); 1182 info_aud->db1_ct_cc);
1160 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); 1183 sum += info_aud->db1_ct_cc;
1161 sum += val;
1162 1184
1163 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; 1185 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
1164 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); 1186 info_aud->db2_sf_ss);
1165 sum += val; 1187 sum += info_aud->db2_sf_ss;
1166 1188
1167 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); 1189 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
1190 sum += info_aud->db3;
1168 1191
1169 val = info_aud->db4_channel_alloc; 1192 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
1170 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); 1193 sum += info_aud->db4_ca;
1171 sum += val;
1172 1194
1173 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); 1195 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
1174 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); 1196 info_aud->db5_dminh_lsv);
1175 sum += val; 1197 sum += info_aud->db5_dminh_lsv;
1176 1198
1177 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); 1199 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1178 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); 1200 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
@@ -1190,70 +1212,212 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
1190 */ 1212 */
1191} 1213}
1192 1214
1193int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, 1215int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
1194 u32 sample_freq, u32 *n, u32 *cts) 1216 struct omap_dss_audio *audio)
1195{ 1217{
1196 u32 r; 1218 struct hdmi_audio_format audio_format;
1197 u32 deep_color = 0; 1219 struct hdmi_audio_dma audio_dma;
1198 u32 pclk = ip_data->cfg.timings.pixel_clock; 1220 struct hdmi_core_audio_config core;
1199 1221 int err, n, cts, channel_count;
1200 if (n == NULL || cts == NULL) 1222 unsigned int fs_nr;
1223 bool word_length_16b = false;
1224
1225 if (!audio || !audio->iec || !audio->cea || !ip_data)
1201 return -EINVAL; 1226 return -EINVAL;
1227
1228 core.iec60958_cfg = audio->iec;
1229 /*
1230 * In the IEC-60958 status word, check if the audio sample word length
1231 * is 16-bit as several optimizations can be performed in such case.
1232 */
1233 if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
1234 if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
1235 word_length_16b = true;
1236
1237 /* I2S configuration. See Phillips' specification */
1238 if (word_length_16b)
1239 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1240 else
1241 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1202 /* 1242 /*
1203 * Obtain current deep color configuration. This needed 1243 * The I2S input word length is twice the lenght given in the IEC-60958
1204 * to calculate the TMDS clock based on the pixel clock. 1244 * status word. If the word size is greater than
1245 * 20 bits, increment by one.
1205 */ 1246 */
1206 r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); 1247 core.i2s_cfg.in_length_bits = audio->iec->status[4]
1207 switch (r) { 1248 & IEC958_AES4_CON_WORDLEN;
1208 case 1: /* No deep color selected */ 1249 if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
1209 deep_color = 100; 1250 core.i2s_cfg.in_length_bits++;
1251 core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
1252 core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
1253 core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
1254 core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
1255
1256 /* convert sample frequency to a number */
1257 switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
1258 case IEC958_AES3_CON_FS_32000:
1259 fs_nr = 32000;
1260 break;
1261 case IEC958_AES3_CON_FS_44100:
1262 fs_nr = 44100;
1263 break;
1264 case IEC958_AES3_CON_FS_48000:
1265 fs_nr = 48000;
1210 break; 1266 break;
1211 case 2: /* 10-bit deep color selected */ 1267 case IEC958_AES3_CON_FS_88200:
1212 deep_color = 125; 1268 fs_nr = 88200;
1213 break; 1269 break;
1214 case 3: /* 12-bit deep color selected */ 1270 case IEC958_AES3_CON_FS_96000:
1215 deep_color = 150; 1271 fs_nr = 96000;
1272 break;
1273 case IEC958_AES3_CON_FS_176400:
1274 fs_nr = 176400;
1275 break;
1276 case IEC958_AES3_CON_FS_192000:
1277 fs_nr = 192000;
1216 break; 1278 break;
1217 default: 1279 default:
1218 return -EINVAL; 1280 return -EINVAL;
1219 } 1281 }
1220 1282
1221 switch (sample_freq) { 1283 err = hdmi_compute_acr(fs_nr, &n, &cts);
1222 case 32000: 1284
1223 if ((deep_color == 125) && ((pclk == 54054) 1285 /* Audio clock regeneration settings */
1224 || (pclk == 74250))) 1286 core.n = n;
1225 *n = 8192; 1287 core.cts = cts;
1226 else 1288 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
1227 *n = 4096; 1289 core.aud_par_busclk = 0;
1290 core.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
1291 core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
1292 } else {
1293 core.aud_par_busclk = (((128 * 31) - 1) << 8);
1294 core.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
1295 core.use_mclk = true;
1296 }
1297
1298 if (core.use_mclk)
1299 core.mclk_mode = HDMI_AUDIO_MCLK_128FS;
1300
1301 /* Audio channels settings */
1302 channel_count = (audio->cea->db1_ct_cc &
1303 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
1304
1305 switch (channel_count) {
1306 case 2:
1307 audio_format.active_chnnls_msk = 0x03;
1308 break;
1309 case 3:
1310 audio_format.active_chnnls_msk = 0x07;
1311 break;
1312 case 4:
1313 audio_format.active_chnnls_msk = 0x0f;
1314 break;
1315 case 5:
1316 audio_format.active_chnnls_msk = 0x1f;
1228 break; 1317 break;
1229 case 44100: 1318 case 6:
1230 *n = 6272; 1319 audio_format.active_chnnls_msk = 0x3f;
1231 break; 1320 break;
1232 case 48000: 1321 case 7:
1233 if ((deep_color == 125) && ((pclk == 54054) 1322 audio_format.active_chnnls_msk = 0x7f;
1234 || (pclk == 74250))) 1323 break;
1235 *n = 8192; 1324 case 8:
1236 else 1325 audio_format.active_chnnls_msk = 0xff;
1237 *n = 6144;
1238 break; 1326 break;
1239 default: 1327 default:
1240 *n = 0;
1241 return -EINVAL; 1328 return -EINVAL;
1242 } 1329 }
1243 1330
1244 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ 1331 /*
1245 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); 1332 * the HDMI IP needs to enable four stereo channels when transmitting
1333 * more than 2 audio channels
1334 */
1335 if (channel_count == 2) {
1336 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
1337 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
1338 core.layout = HDMI_AUDIO_LAYOUT_2CH;
1339 } else {
1340 audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
1341 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
1342 HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
1343 HDMI_AUDIO_I2S_SD3_EN;
1344 core.layout = HDMI_AUDIO_LAYOUT_8CH;
1345 }
1346
1347 core.en_spdif = false;
1348 /* use sample frequency from channel status word */
1349 core.fs_override = true;
1350 /* enable ACR packets */
1351 core.en_acr_pkt = true;
1352 /* disable direct streaming digital audio */
1353 core.en_dsd_audio = false;
1354 /* use parallel audio interface */
1355 core.en_parallel_aud_input = true;
1356
1357 /* DMA settings */
1358 if (word_length_16b)
1359 audio_dma.transfer_size = 0x10;
1360 else
1361 audio_dma.transfer_size = 0x20;
1362 audio_dma.block_size = 0xC0;
1363 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
1364 audio_dma.fifo_threshold = 0x20; /* in number of samples */
1365
1366 /* audio FIFO format settings */
1367 if (word_length_16b) {
1368 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
1369 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
1370 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1371 } else {
1372 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
1373 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
1374 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1375 }
1376 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
1377 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
1378 /* disable start/stop signals of IEC 60958 blocks */
1379 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
1380
1381 /* configure DMA and audio FIFO format*/
1382 ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
1383 ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);
1384
1385 /* configure the core*/
1386 ti_hdmi_4xxx_core_audio_config(ip_data, &core);
1246 1387
1388 /* configure CEA 861 audio infoframe*/
1389 ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea);
1390
1391 return 0;
1392}
1393
1394int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data)
1395{
1396 REG_FLD_MOD(hdmi_wp_base(ip_data),
1397 HDMI_WP_AUDIO_CTRL, true, 31, 31);
1247 return 0; 1398 return 0;
1248} 1399}
1249 1400
1250void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable) 1401void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data)
1402{
1403 REG_FLD_MOD(hdmi_wp_base(ip_data),
1404 HDMI_WP_AUDIO_CTRL, false, 31, 31);
1405}
1406
1407int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data)
1251{ 1408{
1252 REG_FLD_MOD(hdmi_av_base(ip_data), 1409 REG_FLD_MOD(hdmi_av_base(ip_data),
1253 HDMI_CORE_AV_AUD_MODE, enable, 0, 0); 1410 HDMI_CORE_AV_AUD_MODE, true, 0, 0);
1254 REG_FLD_MOD(hdmi_wp_base(ip_data), 1411 REG_FLD_MOD(hdmi_wp_base(ip_data),
1255 HDMI_WP_AUDIO_CTRL, enable, 31, 31); 1412 HDMI_WP_AUDIO_CTRL, true, 30, 30);
1413 return 0;
1414}
1415
1416void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
1417{
1418 REG_FLD_MOD(hdmi_av_base(ip_data),
1419 HDMI_CORE_AV_AUD_MODE, false, 0, 0);
1256 REG_FLD_MOD(hdmi_wp_base(ip_data), 1420 REG_FLD_MOD(hdmi_wp_base(ip_data),
1257 HDMI_WP_AUDIO_CTRL, enable, 30, 30); 1421 HDMI_WP_AUDIO_CTRL, false, 30, 30);
1258} 1422}
1259#endif 1423#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index b724bc68307a..8366ae19e82e 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -24,11 +24,6 @@
24#include <linux/string.h> 24#include <linux/string.h>
25#include <video/omapdss.h> 25#include <video/omapdss.h>
26#include "ti_hdmi.h" 26#include "ti_hdmi.h"
27#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
28 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
29#include <sound/soc.h>
30#include <sound/pcm_params.h>
31#endif
32 27
33/* HDMI Wrapper */ 28/* HDMI Wrapper */
34 29
@@ -279,35 +274,6 @@ enum hdmi_core_infoframe {
279 HDMI_INFOFRAME_AVI_DB5PR_8 = 7, 274 HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
280 HDMI_INFOFRAME_AVI_DB5PR_9 = 8, 275 HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
281 HDMI_INFOFRAME_AVI_DB5PR_10 = 9, 276 HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
282 HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
283 HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
284 HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
285 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
286 HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
287 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
288 HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
289 HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
290 HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
291 HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
292 HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
293 HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
294 HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
295 HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
296 HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
297 HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
298 HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
299 HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
300 HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
301 HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
302 HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
303 HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
304 HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
305 HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
306 HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
307 HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
308 HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
309 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
310 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
311}; 277};
312 278
313enum hdmi_packing_mode { 279enum hdmi_packing_mode {
@@ -317,17 +283,6 @@ enum hdmi_packing_mode {
317 HDMI_PACK_ALREADYPACKED = 7 283 HDMI_PACK_ALREADYPACKED = 7
318}; 284};
319 285
320enum hdmi_core_audio_sample_freq {
321 HDMI_AUDIO_FS_32000 = 0x3,
322 HDMI_AUDIO_FS_44100 = 0x0,
323 HDMI_AUDIO_FS_48000 = 0x2,
324 HDMI_AUDIO_FS_88200 = 0x8,
325 HDMI_AUDIO_FS_96000 = 0xA,
326 HDMI_AUDIO_FS_176400 = 0xC,
327 HDMI_AUDIO_FS_192000 = 0xE,
328 HDMI_AUDIO_FS_NOT_INDICATED = 0x1
329};
330
331enum hdmi_core_audio_layout { 286enum hdmi_core_audio_layout {
332 HDMI_AUDIO_LAYOUT_2CH = 0, 287 HDMI_AUDIO_LAYOUT_2CH = 0,
333 HDMI_AUDIO_LAYOUT_8CH = 1 288 HDMI_AUDIO_LAYOUT_8CH = 1
@@ -382,37 +337,12 @@ enum hdmi_audio_blk_strt_end_sig {
382}; 337};
383 338
384enum hdmi_audio_i2s_config { 339enum hdmi_audio_i2s_config {
385 HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
386 HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
387 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, 340 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
388 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, 341 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
389 HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
390 HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
391 HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
392 HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
393 HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
394 HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
395 HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
396 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
397 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
398 HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
399 HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
400 HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
401 HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
402 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, 342 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
403 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, 343 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
404 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, 344 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
405 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, 345 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
406 HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
407 HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
408 HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
409 HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
410 HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
411 HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
412 HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
413 HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
414 HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
415 HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
416 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, 346 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
417 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, 347 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
418 HDMI_AUDIO_I2S_SD0_EN = 1, 348 HDMI_AUDIO_I2S_SD0_EN = 1,
@@ -441,20 +371,6 @@ struct hdmi_core_video_config {
441 enum hdmi_core_tclkselclkmult tclk_sel_clkmult; 371 enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
442}; 372};
443 373
444/*
445 * Refer to section 8.2 in HDMI 1.3 specification for
446 * details about infoframe databytes
447 */
448struct hdmi_core_infoframe_audio {
449 u8 db1_coding_type;
450 u8 db1_channel_count;
451 u8 db2_sample_freq;
452 u8 db2_sample_size;
453 u8 db4_channel_alloc;
454 bool db5_downmix_inh;
455 u8 db5_lsv; /* Level shift values for downmix */
456};
457
458struct hdmi_core_packet_enable_repeat { 374struct hdmi_core_packet_enable_repeat {
459 u32 audio_pkt; 375 u32 audio_pkt;
460 u32 audio_pkt_repeat; 376 u32 audio_pkt_repeat;
@@ -491,15 +407,10 @@ struct hdmi_audio_dma {
491}; 407};
492 408
493struct hdmi_core_audio_i2s_config { 409struct hdmi_core_audio_i2s_config {
494 u8 word_max_length;
495 u8 word_length;
496 u8 in_length_bits; 410 u8 in_length_bits;
497 u8 justification; 411 u8 justification;
498 u8 en_high_bitrate_aud;
499 u8 sck_edge_mode; 412 u8 sck_edge_mode;
500 u8 cbit_order;
501 u8 vbit; 413 u8 vbit;
502 u8 ws_polarity;
503 u8 direction; 414 u8 direction;
504 u8 shift; 415 u8 shift;
505 u8 active_sds; 416 u8 active_sds;
@@ -507,7 +418,7 @@ struct hdmi_core_audio_i2s_config {
507 418
508struct hdmi_core_audio_config { 419struct hdmi_core_audio_config {
509 struct hdmi_core_audio_i2s_config i2s_cfg; 420 struct hdmi_core_audio_i2s_config i2s_cfg;
510 enum hdmi_core_audio_sample_freq freq_sample; 421 struct snd_aes_iec958 *iec60958_cfg;
511 bool fs_override; 422 bool fs_override;
512 u32 n; 423 u32 n;
513 u32 cts; 424 u32 cts;
@@ -522,17 +433,4 @@ struct hdmi_core_audio_config {
522 bool en_spdif; 433 bool en_spdif;
523}; 434};
524 435
525#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
526 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
527int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
528 u32 sample_freq, u32 *n, u32 *cts);
529void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
530 struct hdmi_core_infoframe_audio *info_aud);
531void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
532 struct hdmi_core_audio_config *cfg);
533void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
534 struct hdmi_audio_dma *aud_dma);
535void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
536 struct hdmi_audio_format *aud_fmt);
537#endif
538#endif 436#endif
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 1217df40cb7e..bb30242eeea1 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -51,6 +51,8 @@
51 51
52struct omap_dss_device; 52struct omap_dss_device;
53struct omap_overlay_manager; 53struct omap_overlay_manager;
54struct snd_aes_iec958;
55struct snd_cea_861_aud_if;
54 56
55enum omap_display_type { 57enum omap_display_type {
56 OMAP_DISPLAY_TYPE_NONE = 0, 58 OMAP_DISPLAY_TYPE_NONE = 0,
@@ -158,6 +160,13 @@ enum omap_dss_display_state {
158 OMAP_DSS_DISPLAY_SUSPENDED, 160 OMAP_DSS_DISPLAY_SUSPENDED,
159}; 161};
160 162
163enum omap_dss_audio_state {
164 OMAP_DSS_AUDIO_DISABLED = 0,
165 OMAP_DSS_AUDIO_ENABLED,
166 OMAP_DSS_AUDIO_CONFIGURED,
167 OMAP_DSS_AUDIO_PLAYING,
168};
169
161/* XXX perhaps this should be removed */ 170/* XXX perhaps this should be removed */
162enum omap_dss_overlay_managers { 171enum omap_dss_overlay_managers {
163 OMAP_DSS_OVL_MGR_LCD, 172 OMAP_DSS_OVL_MGR_LCD,
@@ -583,6 +592,8 @@ struct omap_dss_device {
583 592
584 enum omap_dss_display_state state; 593 enum omap_dss_display_state state;
585 594
595 enum omap_dss_audio_state audio_state;
596
586 /* platform specific */ 597 /* platform specific */
587 int (*platform_enable)(struct omap_dss_device *dssdev); 598 int (*platform_enable)(struct omap_dss_device *dssdev);
588 void (*platform_disable)(struct omap_dss_device *dssdev); 599 void (*platform_disable)(struct omap_dss_device *dssdev);
@@ -595,6 +606,11 @@ struct omap_dss_hdmi_data
595 int hpd_gpio; 606 int hpd_gpio;
596}; 607};
597 608
609struct omap_dss_audio {
610 struct snd_aes_iec958 *iec;
611 struct snd_cea_861_aud_if *cea;
612};
613
598struct omap_dss_driver { 614struct omap_dss_driver {
599 struct device_driver driver; 615 struct device_driver driver;
600 616
@@ -642,6 +658,24 @@ struct omap_dss_driver {
642 658
643 int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); 659 int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
644 bool (*detect)(struct omap_dss_device *dssdev); 660 bool (*detect)(struct omap_dss_device *dssdev);
661
662 /*
663 * For display drivers that support audio. This encompasses
664 * HDMI and DisplayPort at the moment.
665 */
666 /*
667 * Note: These functions might sleep. Do not call while
668 * holding a spinlock/readlock.
669 */
670 int (*audio_enable)(struct omap_dss_device *dssdev);
671 void (*audio_disable)(struct omap_dss_device *dssdev);
672 bool (*audio_supported)(struct omap_dss_device *dssdev);
673 int (*audio_config)(struct omap_dss_device *dssdev,
674 struct omap_dss_audio *audio);
675 /* Note: These functions may not sleep */
676 int (*audio_start)(struct omap_dss_device *dssdev);
677 void (*audio_stop)(struct omap_dss_device *dssdev);
678
645}; 679};
646 680
647int omap_dss_register_driver(struct omap_dss_driver *); 681int omap_dss_register_driver(struct omap_dss_driver *);