#include "dc_reg.h"
#include "dc_priv.h"
#include "hdmi_reg.h"
+#include "hdmi.h"
#include "edid.h"
+/* datasheet claims this will always be 216MHz */
+#define HDMI_AUDIOCLK_FREQ 216000000
+
+#define HDMI_REKEY_DEFAULT 56
+
struct tegra_dc_hdmi_data {
struct tegra_dc *dc;
struct tegra_edid *edid;
},
};
+struct tegra_hdmi_audio_config {
+ unsigned pix_clock;
+ unsigned n;
+ unsigned cts;
+};
+
+const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
+ {25200000, 4096, 25250},
+ {27000000, 4096, 27000},
+ {54000000, 4096, 54000},
+ {74250000, 4096, 74250},
+ {148500000, 4096, 148500},
+ {0, 0, 0},
+};
+
+const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
+ {25200000, 14112, 63125},
+ {27000000, 6272, 30000},
+ {54000000, 6272, 60000},
+ {74250000, 6272, 82500},
+ {148500000, 6272, 165000},
+ {0, 0, 0},
+};
+
+const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
+ {25200000, 6144, 25250},
+ {27000000, 6144, 27000},
+ {54000000, 6144, 54000},
+ {74250000, 6144, 74250},
+ {148500000, 6144, 148500},
+ {0, 0, 0},
+};
+
+static const struct tegra_hdmi_audio_config
+*tegra_hdmi_get_audio_config(unsigned audio_freq, unsigned pix_clock)
+{
+ const struct tegra_hdmi_audio_config *table;
+
+ switch (audio_freq) {
+ case 32000:
+ table = tegra_hdmi_audio_32k;
+ break;
+
+ case 44100:
+ table = tegra_hdmi_audio_44_1k;
+ break;
+
+ case 48000:
+ table = tegra_hdmi_audio_48k;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ while (table->pix_clock) {
+ if (table->pix_clock == pix_clock)
+ return table;
+ table++;
+ }
+
+ return NULL;
+}
+
+
static inline unsigned long tegra_hdmi_readl(struct tegra_dc_hdmi_data *hdmi,
unsigned long reg)
{
DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS1);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS2);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS3);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS4);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS5);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS6);
- DUMP_REG(HDMI_NV_PDISP_AUDIO_FS7);
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
+ DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
}
+static void tegra_dc_hdmi_setup_audio_fs_tables(struct tegra_dc *dc)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+ int i;
+ unsigned freqs[] = {
+ 32000,
+ 44100,
+ 48000,
+ 88200,
+ 96000,
+ 176400,
+ 192000,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(freqs); i++) {
+ unsigned f = freqs[i];
+ unsigned eight_half;
+ unsigned delta;;
+
+ if (f > 96000)
+ delta = 2;
+ else if (f > 48000)
+ delta = 6;
+ else
+ delta = 9;
+
+ eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
+ tegra_hdmi_writel(hdmi, AUDIO_FS_LOW(eight_half - delta) |
+ AUDIO_FS_HIGH(eight_half + delta),
+ HDMI_NV_PDISP_AUDIO_FS(i));
+ }
+}
+
+static int tegra_dc_hdmi_setup_audio(struct tegra_dc *dc)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+ const struct tegra_hdmi_audio_config *config;
+ unsigned long audio_n;
+ unsigned audio_freq = 44100; /* TODO: find some way of configuring this */
+
+ tegra_hdmi_writel(hdmi,
+ AUDIO_CNTRL0_ERROR_TOLERANCE(9) |
+ AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0) |
+ AUDIO_CNTRL0_SOURCE_SELECT_AUTO,
+ HDMI_NV_PDISP_AUDIO_CNTRL0);
+
+ config = tegra_hdmi_get_audio_config(audio_freq, dc->mode.pclk);
+ if (!config) {
+ dev_err(&dc->ndev->dev,
+ "hdmi: can't set audio to %d at %d pix_clock",
+ audio_freq, dc->mode.pclk);
+ return -EINVAL;
+ }
+
+ tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
+
+ audio_n = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNALTE |
+ AUDIO_N_VALUE(config->n);
+ tegra_hdmi_writel(hdmi, audio_n, HDMI_NV_PDISP_AUDIO_N);
+
+ tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
+ HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
+ tegra_hdmi_writel(hdmi, ACR_SUBPACK_CTS(config->n),
+ HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
+
+ tegra_hdmi_writel(hdmi, SPARE_HW_CTS | SPARE_FORCE_SW_CTS |
+ SPARE_CTS_RESET_VAL(1),
+ HDMI_NV_PDISP_HDMI_SPARE);
+
+ audio_n &= ~AUDIO_N_RESETF;
+ tegra_hdmi_writel(hdmi, audio_n, HDMI_NV_PDISP_AUDIO_N);
+
+ tegra_dc_hdmi_setup_audio_fs_tables(dc);
+
+ return 0;
+}
+
+static void tegra_dc_hdmi_write_infopack(struct tegra_dc *dc, int header_reg,
+ u8 type, u8 version, void *data, int len)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+ u32 subpack[2]; /* extra byte for zero padding of subpack */
+ int i;
+ u8 csum;
+
+ /* first byte of data is the checksum */
+ csum = type + version + len - 1;
+ for (i = 1; i < len; i++)
+ csum +=((u8 *)data)[i];
+ ((u8 *)data)[0] = 0x100 - csum;
+
+ tegra_hdmi_writel(hdmi, INFOFRAME_HEADER_TYPE(type) |
+ INFOFRAME_HEADER_VERSION(version) |
+ INFOFRAME_HEADER_LEN(len - 1),
+ header_reg);
+
+ /* The audio inforame only has one set of subpack registers. The hdmi
+ * block pads the rest of the data as per the spec so we have to fixup
+ * the length before filling in the subpacks.
+ */
+ if (header_reg == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
+ len = 6;
+
+ /* each subpack 7 bytes devided into:
+ * subpack_low - bytes 0 - 3
+ * subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00)
+ */
+ for (i = 0; i < len; i++) {
+ int subpack_idx = i % 7;
+
+ if (subpack_idx == 0)
+ memset(subpack, 0x0, sizeof(subpack));
+
+ ((u8 *)subpack)[subpack_idx] = ((u8 *)data)[i];
+
+ if (subpack_idx == 6 || (i + 1 == len)) {
+ int reg = header_reg + 1 + (i / 7) * 2;
+
+ tegra_hdmi_writel(hdmi, subpack[0], reg);
+ tegra_hdmi_writel(hdmi, subpack[1], reg + 1);
+ }
+ }
+}
+
+static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+ struct hdmi_avi_infoframe avi;
+
+ if (dvi) {
+ tegra_hdmi_writel(hdmi, 0x0,
+ HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+ return;
+ }
+
+ memset(&avi, 0x0, sizeof(avi));
+
+ avi.r = HDMI_AVI_R_SAME;
+
+ if (dc->mode.v_active == 480) {
+ if (dc->mode.h_active == 640) {
+ avi.m = HDMI_AVI_M_4_3;
+ avi.vic = 1;
+ } else {
+ avi.m = HDMI_AVI_M_16_9;
+ avi.vic = 3;
+ }
+ } else if (dc->mode.v_active == 576) {
+ /* CEC modes 17 and 18 differ only by the pysical size of the
+ * screen so we have to calculation the physical aspect
+ * ratio. 4 * 10 / 3 is 13
+ */
+ if ((dc->out->h_size * 10) / dc->out->v_size > 14) {
+ avi.m = HDMI_AVI_M_16_9;
+ avi.vic = 18;
+ } else {
+ avi.m = HDMI_AVI_M_16_9;
+ avi.vic = 17;
+ }
+ } else if (dc->mode.v_active == 720) {
+ avi.m = HDMI_AVI_M_16_9;
+ if (dc->mode.h_front_porch == 110)
+ avi.vic = 4; /* 60 Hz */
+ else
+ avi.vic = 19; /* 50 Hz */
+ } else if (dc->mode.v_active == 720) {
+ avi.m = HDMI_AVI_M_16_9;
+ if (dc->mode.h_front_porch == 88)
+ avi.vic = 16; /* 60 Hz */
+ else if (dc->mode.h_front_porch == 528)
+ avi.vic = 31; /* 50 Hz */
+ else
+ avi.vic = 32; /* 24 Hz */
+ } else {
+ avi.m = HDMI_AVI_M_16_9;
+ avi.vic = 0;
+ }
+
+
+ tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
+ HDMI_INFOFRAME_TYPE_AVI,
+ HDMI_AVI_VERSION,
+ &avi, sizeof(avi));
+
+ tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
+ HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+}
+
+static void tegra_dc_hdmi_setup_audio_infoframe(struct tegra_dc *dc, bool dvi)
+{
+ struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+ struct hdmi_audio_infoframe audio;
+
+ if (dvi) {
+ tegra_hdmi_writel(hdmi, 0x0,
+ HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+ return;
+ }
+
+ memset(&audio, 0x0, sizeof(audio));
+
+ audio.cc = HDMI_AUDIO_CC_2;
+ tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER,
+ HDMI_INFOFRAME_TYPE_AUDIO,
+ HDMI_AUDIO_VERSION,
+ &audio, sizeof(audio));
+
+ tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
+ HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+}
+
static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
int pll1;
int ds;
int retries;
+ int rekey;
+ int err;
unsigned long val;
+ bool dvi = false;
/* enbale power, clocks, resets, etc. */
tegra_dc_setup_clk(dc, hdmi->clk);
VSYNC_WINDOW_ENABLE,
HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
- /* TODO: scale output to 16-235 */
-
tegra_hdmi_writel(hdmi,
(dc->ndev->id ? HDMI_SRC_DISPLAYB : HDMI_SRC_DISPLAYA) |
ARM_VIDEO_RANGE_LIMITED,
/* TODO: setup audio */
- /* values from harmony board. Will be replaced when
- * audio and avi are supported */
- tegra_hdmi_writel(hdmi, 0x00000001, 0x1e);
- tegra_hdmi_writel(hdmi, 0x00000000, 0x20);
- tegra_hdmi_writel(hdmi, 0x000000aa, 0x21);
- tegra_hdmi_writel(hdmi, 0x00000001, 0x23);
- tegra_hdmi_writel(hdmi, 0x00000001, 0x24);
- tegra_hdmi_writel(hdmi, 0x00000000, 0x25);
- tegra_hdmi_writel(hdmi, 0x000445eb, 0x26);
- tegra_hdmi_writel(hdmi, 0x00000004, 0x27);
- tegra_hdmi_writel(hdmi, 0x00002710, 0x2a);
- tegra_hdmi_writel(hdmi, 0x00000000, 0x35);
- tegra_hdmi_writel(hdmi, 0x0015bc10, 0x38);
- tegra_hdmi_writel(hdmi, 0x04c4bb58, 0x39);
- tegra_hdmi_writel(hdmi, 0x0263b9b6, 0x44);
- tegra_hdmi_writel(hdmi, 0x00002713, 0x4f);
- tegra_hdmi_writel(hdmi, 0x01e85426, 0x57);
- tegra_hdmi_writel(hdmi, 0x001136c2, 0x89);
- tegra_hdmi_writel(hdmi, 0x00000730, 0x8a);
- tegra_hdmi_writel(hdmi, 0x0001875b, 0x8c);
- tegra_hdmi_writel(hdmi, 0x00000000, 0x9d);
-
- tegra_hdmi_writel(hdmi, 0x40090038, HDMI_NV_PDISP_HDMI_CTRL);
- tegra_hdmi_writel(hdmi, 0x0, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+ err = tegra_dc_hdmi_setup_audio(dc);
+ if (err < 0)
+ dvi = true;
+
+ rekey = HDMI_REKEY_DEFAULT;
+ val = HDMI_CTRL_REKEY(rekey);
+ val |= HDMI_CTRL_MAX_AC_PACKET((dc->mode.h_sync_width +
+ dc->mode.h_back_porch +
+ dc->mode.h_front_porch -
+ rekey - 18) / 32);
+ if (!dvi)
+ val |= HDMI_CTRL_ENABLE;
+ tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_CTRL);
+
+ if (dvi)
+ tegra_hdmi_writel(hdmi, 0x0,
+ HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+ else
+ tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
+ HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+
+
+ tegra_dc_hdmi_setup_avi_infoframe(dc, dvi);
+ tegra_dc_hdmi_setup_audio_infoframe(dc, dvi);
/* TMDS CONFIG */
pll0 = 0x200033f;
--- /dev/null
+/*
+ * drivers/video/tegra/dc/hdmi.h
+ *
+ * non-tegra specific HDMI declarations
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Erik Gilling <konkers@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_VIDEO_TEGRA_DC_HDMI_H
+#define __DRIVERS_VIDEO_TEGRA_DC_HDMI_H
+
+#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
+#define HDMI_INFOFRAME_TYPE_AVI 0x82
+#define HDMI_INFOFRAME_TYPE_SPD 0x83
+#define HDMI_INFOFRAME_TYPE_AUDIO 0x84
+#define HDMI_INFOFRAME_TYPE_MPEG_SRC 0x85
+#define HDMI_INFOFRAME_TYPE_NTSC_VBI 0x86
+
+/* all fields little endian */
+struct hdmi_avi_infoframe {
+ /* PB0 */
+ u8 csum;
+
+ /* PB1 */
+ unsigned s:2; /* scan information */
+ unsigned b:2; /* bar info data valid */
+ unsigned a:1; /* active info present */
+ unsigned y:2; /* RGB or YCbCr */
+ unsigned res1:1;
+
+ /* PB2 */
+ unsigned r:4; /* active format aspect ratio */
+ unsigned m:2; /* picture aspect ratio */
+ unsigned c:2; /* colorimetry */
+
+ /* PB3 */
+ unsigned sc:2; /* scan information */
+ unsigned q:2; /* quantization range */
+ unsigned ec:3; /* extended colorimetry */
+ unsigned itc:1; /* it content */
+
+ /* PB4 */
+ unsigned vic:7; /* video format id code */
+ unsigned res4:1;
+
+ /* PB5 */
+ unsigned pr:4; /* pixel repetition factor */
+ unsigned cn:2; /* it content type*/
+ unsigned yq:2; /* ycc quantization range */
+
+ /* PB6-7 */
+ u16 top_bar_end_line;
+
+ /* PB8-9 */
+ u16 bot_bar_start_line;
+
+ /* PB10-11 */
+ u16 left_bar_end_pixel;
+
+ /* PB12-13 */
+ u16 right_bar_start_pixel;
+} __attribute__((packed));
+
+#define HDMI_AVI_VERSION 0x02
+
+#define HDMI_AVI_Y_RGB 0x0
+#define HDMI_AVI_Y_YCBCR_422 0x1
+#define HDMI_AVI_Y_YCBCR_444 0x2
+
+#define HDMI_AVI_B_VERT 0x1
+#define HDMI_AVI_B_HORIZ 0x2
+
+#define HDMI_AVI_S_NONE 0x0
+#define HDMI_AVI_S_OVERSCAN 0x1
+#define HDMI_AVI_S_UNDERSCAN 0x2
+
+#define HDMI_AVI_C_NONE 0x0
+#define HDMI_AVI_C_SMPTE 0x1
+#define HDMI_AVI_C_ITU_R 0x2
+#define HDMI_AVI_C_EXTENDED 0x4
+
+#define HDMI_AVI_M_4_3 0x1
+#define HDMI_AVI_M_16_9 0x2
+
+#define HDMI_AVI_R_SAME 0x8
+#define HDMI_AVI_R_4_3_CENTER 0x9
+#define HDMI_AVI_R_16_9_CENTER 0xa
+#define HDMI_AVI_R_14_9_CENTER 0xb
+
+/* all fields little endian */
+struct hdmi_audio_infoframe {
+ /* PB0 */
+ u8 csum;
+
+ /* PB1 */
+ unsigned cc:3; /* channel count */
+ unsigned res1:1;
+ unsigned ct:4; /* coding type */
+
+ /* PB2 */
+ unsigned ss:2; /* sample size */
+ unsigned sf:3; /* sample frequency */
+ unsigned res2:3;
+
+ /* PB3 */
+ unsigned cxt:5; /* coding extention type */
+ unsigned res3:3;
+
+ /* PB4 */
+ u8 ca; /* channel/speaker allocation */
+
+ /* PB5 */
+ unsigned res5:3;
+ unsigned lsv:4; /* level shift value */
+ unsigned dm_inh:1; /* downmix inhibit */
+
+ /* PB6-10 reserved */
+ u8 res6;
+ u8 res7;
+ u8 res8;
+ u8 res9;
+ u8 res10;
+} __attribute__((packed));
+
+#define HDMI_AUDIO_VERSION 0x01
+
+#define HDMI_AUDIO_CC_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUDIO_CC_2 0x1
+#define HDMI_AUDIO_CC_3 0x2
+#define HDMI_AUDIO_CC_4 0x3
+#define HDMI_AUDIO_CC_5 0x4
+#define HDMI_AUDIO_CC_6 0x5
+#define HDMI_AUDIO_CC_7 0x6
+#define HDMI_AUDIO_CC_8 0x7
+
+#define HDMI_AUDIO_CT_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUDIO_CT_PCM 0x1
+#define HDMI_AUDIO_CT_AC3 0x2
+#define HDMI_AUDIO_CT_MPEG1 0x3
+#define HDMI_AUDIO_CT_MP3 0x4
+#define HDMI_AUDIO_CT_MPEG2 0x5
+#define HDMI_AUDIO_CT_AAC_LC 0x6
+#define HDMI_AUDIO_CT_DTS 0x7
+#define HDMI_AUDIO_CT_ATRAC 0x8
+#define HDMI_AUDIO_CT_DSD 0x9
+#define HDMI_AUDIO_CT_E_AC3 0xa
+#define HDMI_AUDIO_CT_DTS_HD 0xb
+#define HDMI_AUDIO_CT_MLP 0xc
+#define HDMI_AUDIO_CT_DST 0xd
+#define HDMI_AUDIO_CT_WMA_PRO 0xe
+#define HDMI_AUDIO_CT_CXT 0xf
+
+#define HDMI_AUDIO_SF_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUIDO_SF_32K 0x1
+#define HDMI_AUDIO_SF_44_1K 0x2
+#define HDMI_AUDIO_SF_48K 0x3
+#define HDMI_AUDIO_SF_88_2K 0x4
+#define HDMI_AUDIO_SF_96K 0x5
+#define HDMI_AUDIO_SF_176_4K 0x6
+#define HDMI_AUDIO_SF_192K 0x7
+
+#define HDMI_AUDIO_SS_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUDIO_SS_16BIT 0x1
+#define HDMI_AUDIO_SS_20BIT 0x2
+#define HDMI_AUDIO_SS_24BIT 0x3
+
+#define HDMI_AUDIO_CXT_CT 0x0 /* refer to coding in CT */
+#define HDMI_AUDIO_CXT_HE_AAC 0x1
+#define HDMI_AUDIO_CXT_HE_AAC_V2 0x2
+#define HDMI_AUDIO_CXT_MPEG_SURROUND 0x3
+
+#endif
#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH 0x27
#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW 0x28
#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH 0x29
+#define INFOFRAME_CTRL_ENABLE (1 << 0)
+#define INFOFRAME_CTRL_OTHER (1 << 4)
+#define INFOFRAME_CTRL_SINGLE (1 << 8)
+
+#define INFOFRAME_HEADER_TYPE(x) ((x) & 0xff)
+#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
+#define INFOFRAME_HEADER_LEN(x) (((x) & 0xf) << 16)
+
#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a
+#define GENERIC_CTRL_ENABLE (1 << 0)
+#define GENERIC_CTRL_OTHER (1 << 4)
+#define GENERIC_CTRL_SINGLE (1 << 8)
+#define GENERIC_CTRL_HBLANK (1 << 12)
+#define GENERIC_CTRL_AUDIO (1 << 16)
+
#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS 0x2b
#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER 0x2c
#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW 0x2d
#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH 0x41
#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW 0x42
#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH 0x43
+#define ACR_SB3(x) (((x) & 0xff) << 8)
+#define ACR_SB2(x) (((x) & 0xff) << 16)
+#define ACR_SB1(x) (((x) & 0xff) << 24)
+#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
+
+#define ACR_SB6(x) (((x) & 0xff) << 0)
+#define ACR_SB5(x) (((x) & 0xff) << 8)
+#define ACR_SB4(x) (((x) & 0xff) << 16)
+#define ACR_ENABLE (1 << 31)
+#define ACR_SUBPACK_N(x) ((x) & 0xffffff)
+
#define HDMI_NV_PDISP_HDMI_CTRL 0x44
#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0)
#define HDMI_CTRL_AUDIO_LAYOUT (1 << 8)
#define HDMI_NV_PDISP_HDMI_EMU1 0x4d
#define HDMI_NV_PDISP_HDMI_EMU1_RDATA 0x4e
#define HDMI_NV_PDISP_HDMI_SPARE 0x4f
+#define SPARE_HW_CTS (1 << 0)
+#define SPARE_FORCE_SW_CTS (1 << 1)
+#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
+#define SPARE_ACR_PRIORITY_HIGH (0 << 31)
+#define SPARE_ACR_PRIORITY_LOW (1 << 31)
+
#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1 0x50
#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2 0x51
#define HDMI_NV_PDISP_HDCPRIF_ROM_CTRL 0x53
#define HDMI_NV_PDISP_AUDIO_DEBUG0 0x7f
#define HDMI_NV_PDISP_AUDIO_DEBUG1 0x80
#define HDMI_NV_PDISP_AUDIO_DEBUG2 0x81
-#define HDMI_NV_PDISP_AUDIO_FS1 0x82
-#define HDMI_NV_PDISP_AUDIO_FS2 0x83
-#define HDMI_NV_PDISP_AUDIO_FS3 0x84
-#define HDMI_NV_PDISP_AUDIO_FS4 0x85
-#define HDMI_NV_PDISP_AUDIO_FS5 0x86
-#define HDMI_NV_PDISP_AUDIO_FS6 0x87
-#define HDMI_NV_PDISP_AUDIO_FS7 0x88
+/* note: datasheet defines FS1..FS7. we have FS(0)..FS(6) */
+#define HDMI_NV_PDISP_AUDIO_FS(x) (0x82 + (x))
+#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0)
+#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
+
+
#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH 0x89
#define HDMI_NV_PDISP_AUDIO_THRESHOLD 0x8a
#define HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b
+#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0)
+#define AUDIO_CNTRL0_SOFT_RESET (1 << 8)
+#define AUDIO_CNTRL0_SOFT_RESET_ALL (1 << 12)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_UNKNOWN (1 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_32K (2 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_44_1K (0 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_48K (2 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_88_2K (8 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_96K (10 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_176_4K (12 << 16)
+#define AUDIO_CNTRL0_SAMPLING_FREQ_192K (14 << 16)
+#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
+#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
+
#define HDMI_NV_PDISP_AUDIO_N 0x8c
+#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0)
+#define AUDIO_N_RESETF (1 << 20)
+#define AUDIO_N_GENERATE_NORMAL (0 << 24)
+#define AUDIO_N_GENERATE_ALTERNALTE (1 << 24)
+#define AUDIO_N_LOOKUP_ENABLE (1 << 28)
+
#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING 0x94
#define HDMI_NV_PDISP_SOR_REFCLK 0x95
#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8)