Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310360
b: refs/heads/master
c: 6ec355d
h: refs/heads/master
v: v3
  • Loading branch information
Ricardo Neri authored and Tomi Valkeinen committed May 11, 2012
1 parent 1075e74 commit 1b87100
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 25a653597ee63119a477e9bdeb6b41bd7cd56140
refs/heads/master: 6ec355d6c79e811a3b7f85ca6b22fa4bd7b1bbfc
1 change: 1 addition & 0 deletions trunk/drivers/video/omap2/dss/dss_features.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.audio_disable = ti_hdmi_4xxx_wp_audio_disable,
.audio_start = ti_hdmi_4xxx_audio_start,
.audio_stop = ti_hdmi_4xxx_audio_stop,
.audio_config = ti_hdmi_4xxx_audio_config,
#endif

};
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/video/omap2/dss/ti_hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ struct ti_hdmi_ip_ops {
int (*audio_start)(struct hdmi_ip_data *ip_data);

void (*audio_stop)(struct hdmi_ip_data *ip_data);

int (*audio_config)(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
#endif

};
Expand Down Expand Up @@ -195,5 +198,7 @@ int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
#endif
#endif
189 changes: 185 additions & 4 deletions trunk/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
#include <linux/gpio.h>
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#include <sound/asound.h>
#include <sound/asoundef.h>
#endif

#include "ti_hdmi_4xxx_ip.h"
#include "dss.h"
#include "dss_features.h"

static inline void hdmi_write_reg(void __iomem *base_addr,
const u16 idx, u32 val)
Expand Down Expand Up @@ -1024,7 +1026,7 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
}

#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data,
struct hdmi_audio_format *aud_fmt)
{
u32 r;
Expand All @@ -1043,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
}

void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
struct hdmi_audio_dma *aud_dma)
{
u32 r;
Expand All @@ -1061,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
}

void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_audio_config *cfg)
{
u32 r;
Expand Down Expand Up @@ -1152,7 +1154,7 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
}

void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data,
struct snd_cea_861_aud_if *info_aud)
{
u8 sum = 0, checksum = 0;
Expand Down Expand Up @@ -1202,6 +1204,185 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
*/
}

int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio)
{
struct hdmi_audio_format audio_format;
struct hdmi_audio_dma audio_dma;
struct hdmi_core_audio_config core;
int err, n, cts, channel_count;
unsigned int fs_nr;
bool word_length_16b = false;

if (!audio || !audio->iec || !audio->cea || !ip_data)
return -EINVAL;

core.iec60958_cfg = audio->iec;
/*
* In the IEC-60958 status word, check if the audio sample word length
* is 16-bit as several optimizations can be performed in such case.
*/
if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
word_length_16b = true;

/* I2S configuration. See Phillips' specification */
if (word_length_16b)
core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
else
core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
/*
* The I2S input word length is twice the lenght given in the IEC-60958
* status word. If the word size is greater than
* 20 bits, increment by one.
*/
core.i2s_cfg.in_length_bits = audio->iec->status[4]
& IEC958_AES4_CON_WORDLEN;
if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
core.i2s_cfg.in_length_bits++;
core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;

/* convert sample frequency to a number */
switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
case IEC958_AES3_CON_FS_32000:
fs_nr = 32000;
break;
case IEC958_AES3_CON_FS_44100:
fs_nr = 44100;
break;
case IEC958_AES3_CON_FS_48000:
fs_nr = 48000;
break;
case IEC958_AES3_CON_FS_88200:
fs_nr = 88200;
break;
case IEC958_AES3_CON_FS_96000:
fs_nr = 96000;
break;
case IEC958_AES3_CON_FS_176400:
fs_nr = 176400;
break;
case IEC958_AES3_CON_FS_192000:
fs_nr = 192000;
break;
default:
return -EINVAL;
}

err = hdmi_compute_acr(fs_nr, &n, &cts);

/* Audio clock regeneration settings */
core.n = n;
core.cts = cts;
if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
core.aud_par_busclk = 0;
core.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
} else {
core.aud_par_busclk = (((128 * 31) - 1) << 8);
core.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
core.use_mclk = true;
}

if (core.use_mclk)
core.mclk_mode = HDMI_AUDIO_MCLK_128FS;

/* Audio channels settings */
channel_count = (audio->cea->db1_ct_cc &
CEA861_AUDIO_INFOFRAME_DB1CC) + 1;

switch (channel_count) {
case 2:
audio_format.active_chnnls_msk = 0x03;
break;
case 3:
audio_format.active_chnnls_msk = 0x07;
break;
case 4:
audio_format.active_chnnls_msk = 0x0f;
break;
case 5:
audio_format.active_chnnls_msk = 0x1f;
break;
case 6:
audio_format.active_chnnls_msk = 0x3f;
break;
case 7:
audio_format.active_chnnls_msk = 0x7f;
break;
case 8:
audio_format.active_chnnls_msk = 0xff;
break;
default:
return -EINVAL;
}

/*
* the HDMI IP needs to enable four stereo channels when transmitting
* more than 2 audio channels
*/
if (channel_count == 2) {
audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
core.layout = HDMI_AUDIO_LAYOUT_2CH;
} else {
audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
HDMI_AUDIO_I2S_SD3_EN;
core.layout = HDMI_AUDIO_LAYOUT_8CH;
}

core.en_spdif = false;
/* use sample frequency from channel status word */
core.fs_override = true;
/* enable ACR packets */
core.en_acr_pkt = true;
/* disable direct streaming digital audio */
core.en_dsd_audio = false;
/* use parallel audio interface */
core.en_parallel_aud_input = true;

/* DMA settings */
if (word_length_16b)
audio_dma.transfer_size = 0x10;
else
audio_dma.transfer_size = 0x20;
audio_dma.block_size = 0xC0;
audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
audio_dma.fifo_threshold = 0x20; /* in number of samples */

/* audio FIFO format settings */
if (word_length_16b) {
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
} else {
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
}
audio_format.type = HDMI_AUDIO_TYPE_LPCM;
audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
/* disable start/stop signals of IEC 60958 blocks */
audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;

/* configure DMA and audio FIFO format*/
ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);

/* configure the core*/
ti_hdmi_4xxx_core_audio_config(ip_data, &core);

/* configure CEA 861 audio infoframe*/
ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea);

return 0;
}

int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data)
{
REG_FLD_MOD(hdmi_wp_base(ip_data),
Expand Down
10 changes: 0 additions & 10 deletions trunk/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,4 @@ struct hdmi_core_audio_config {
bool en_spdif;
};

#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
struct snd_cea_861_aud_if *info_aud);
void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_audio_config *cfg);
void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
struct hdmi_audio_dma *aud_dma);
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
struct hdmi_audio_format *aud_fmt);
#endif
#endif

0 comments on commit 1b87100

Please sign in to comment.