Loading drivers/gpu/drm/tegra/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ config DRM_TEGRA select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER select DRM_HDMI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT Loading drivers/gpu/drm/tegra/hdmi.c +109 −117 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/debugfs.h> #include <linux/gpio.h> #include <linux/hdmi.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> Loading @@ -17,6 +18,8 @@ #include <mach/clk.h> #include <drm/drm_edid.h> #include "hdmi.h" #include "drm.h" #include "dc.h" Loading Loading @@ -401,54 +404,65 @@ static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk) return 0; } static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, unsigned int offset, u8 type, u8 version, void *data, size_t size) static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size) { unsigned long value; u8 *ptr = data; u32 subpack[2]; unsigned long value = 0; size_t i; u8 csum; /* first byte of data is the checksum */ csum = type + version + size - 1; for (i = size; i > 0; i--) value = (value << 8) | ptr[i - 1]; for (i = 1; i < size; i++) csum += ptr[i]; return value; } ptr[0] = 0x100 - csum; static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, size_t size) { const u8 *ptr = data; unsigned long offset; unsigned long value; size_t i, j; value = INFOFRAME_HEADER_TYPE(type) | INFOFRAME_HEADER_VERSION(version) | INFOFRAME_HEADER_LEN(size - 1); tegra_hdmi_writel(hdmi, value, offset); switch (ptr[0]) { case HDMI_INFOFRAME_TYPE_AVI: offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER; break; /* 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 (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER) size = 6; case HDMI_INFOFRAME_TYPE_AUDIO: offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER; break; /* 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 < size; i++) { size_t index = i % 7; case HDMI_INFOFRAME_TYPE_VENDOR: offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER; break; if (index == 0) memset(subpack, 0x0, sizeof(subpack)); default: dev_err(hdmi->dev, "unsupported infoframe type: %02x\n", ptr[0]); return; } ((u8 *)subpack)[index] = ptr[i]; value = INFOFRAME_HEADER_TYPE(ptr[0]) | INFOFRAME_HEADER_VERSION(ptr[1]) | INFOFRAME_HEADER_LEN(ptr[2]); tegra_hdmi_writel(hdmi, value, offset); offset++; if (index == 6 || (i + 1 == size)) { unsigned int reg = offset + 1 + (i / 7) * 2; /* * Each subpack contains 7 bytes, divided into: * - subpack_low: bytes 0 - 3 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) */ for (i = 3, j = 0; i < size; i += 7, j += 8) { size_t rem = size - i, num = min_t(size_t, rem, 4); tegra_hdmi_writel(hdmi, subpack[0], reg); tegra_hdmi_writel(hdmi, subpack[1], reg + 1); } value = tegra_hdmi_subpack(&ptr[i], num); tegra_hdmi_writel(hdmi, value, offset++); num = min_t(size_t, rem - num, 3); value = tegra_hdmi_subpack(&ptr[i + 4], num); tegra_hdmi_writel(hdmi, value, offset++); } } Loading @@ -456,9 +470,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, struct drm_display_mode *mode) { struct hdmi_avi_infoframe frame; unsigned int h_front_porch; unsigned int hsize = 16; unsigned int vsize = 9; u8 buffer[17]; ssize_t err; if (hdmi->dvi) { tegra_hdmi_writel(hdmi, 0, Loading @@ -466,69 +479,19 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, return; } h_front_porch = mode->hsync_start - mode->hdisplay; memset(&frame, 0, sizeof(frame)); frame.r = HDMI_AVI_R_SAME; switch (mode->vdisplay) { case 480: if (mode->hdisplay == 640) { frame.m = HDMI_AVI_M_4_3; frame.vic = 1; } else { frame.m = HDMI_AVI_M_16_9; frame.vic = 3; } break; case 576: if (((hsize * 10) / vsize) > 14) { frame.m = HDMI_AVI_M_16_9; frame.vic = 18; } else { frame.m = HDMI_AVI_M_4_3; frame.vic = 17; } break; case 720: case 1470: /* stereo mode */ frame.m = HDMI_AVI_M_16_9; if (h_front_porch == 110) frame.vic = 4; else frame.vic = 19; break; case 1080: case 2205: /* stereo mode */ frame.m = HDMI_AVI_M_16_9; switch (h_front_porch) { case 88: frame.vic = 16; break; case 528: frame.vic = 31; break; default: frame.vic = 32; break; err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); if (err < 0) { dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); return; } break; default: frame.m = HDMI_AVI_M_16_9; frame.vic = 0; break; err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER, HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION, &frame, sizeof(frame)); tegra_hdmi_write_infopack(hdmi, buffer, err); tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); Loading @@ -537,6 +500,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) { struct hdmi_audio_infoframe frame; u8 buffer[14]; ssize_t err; if (hdmi->dvi) { tegra_hdmi_writel(hdmi, 0, Loading @@ -544,14 +509,29 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) return; } memset(&frame, 0, sizeof(frame)); frame.cc = HDMI_AUDIO_CC_2; err = hdmi_audio_infoframe_init(&frame); if (err < 0) { dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER, HDMI_INFOFRAME_TYPE_AUDIO, HDMI_AUDIO_VERSION, &frame, sizeof(frame)); frame.channels = 2; err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n", err); return; } /* * The audio infoframe has only one set of subpack registers, so the * infoframe needs to be truncated. One set of subpack registers can * contain 7 bytes. Including the 3 byte header only the first 10 * bytes can be programmed. */ tegra_hdmi_write_infopack(hdmi, buffer, min(10, err)); tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); Loading @@ -559,8 +539,10 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) { struct hdmi_stereo_infoframe frame; struct hdmi_vendor_infoframe frame; unsigned long value; u8 buffer[10]; ssize_t err; if (!hdmi->stereo) { value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); Loading @@ -570,22 +552,32 @@ static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) } memset(&frame, 0, sizeof(frame)); frame.regid0 = 0x03; frame.regid1 = 0x0c; frame.regid2 = 0x00; frame.hdmi_video_format = 2; frame.type = HDMI_INFOFRAME_TYPE_VENDOR; frame.version = 0x01; frame.length = 6; frame.data[0] = 0x03; /* regid0 */ frame.data[1] = 0x0c; /* regid1 */ frame.data[2] = 0x00; /* regid2 */ frame.data[3] = 0x02 << 5; /* video format */ /* TODO: 74 MHz limit? */ if (1) { frame._3d_structure = 0; frame.data[4] = 0x00 << 4; /* 3D structure */ } else { frame._3d_structure = 8; frame._3d_ext_data = 0; frame.data[4] = 0x08 << 4; /* 3D structure */ frame.data[5] = 0x00 << 4; /* 3D ext. data */ } err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER, HDMI_INFOFRAME_TYPE_VENDOR, HDMI_VENDOR_VERSION, &frame, 6); tegra_hdmi_write_infopack(hdmi, buffer, err); value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); value |= GENERIC_CTRL_ENABLE; Loading drivers/gpu/drm/tegra/hdmi.h +0 −189 Original line number Diff line number Diff line Loading @@ -10,195 +10,6 @@ #ifndef TEGRA_HDMI_H #define TEGRA_HDMI_H 1 #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; } __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; } __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 /* all fields little endian */ struct hdmi_stereo_infoframe { /* PB0 */ u8 csum; /* PB1 */ u8 regid0; /* PB2 */ u8 regid1; /* PB3 */ u8 regid2; /* PB4 */ unsigned res1:5; unsigned hdmi_video_format:3; /* PB5 */ unsigned res2:4; unsigned _3d_structure:4; /* PB6*/ unsigned res3:4; unsigned _3d_ext_data:4; } __packed; #define HDMI_VENDOR_VERSION 0x01 /* register definitions */ #define HDMI_CTXSW 0x00 Loading Loading
drivers/gpu/drm/tegra/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ config DRM_TEGRA select DRM_KMS_HELPER select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER select DRM_HDMI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT Loading
drivers/gpu/drm/tegra/hdmi.c +109 −117 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/debugfs.h> #include <linux/gpio.h> #include <linux/hdmi.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> Loading @@ -17,6 +18,8 @@ #include <mach/clk.h> #include <drm/drm_edid.h> #include "hdmi.h" #include "drm.h" #include "dc.h" Loading Loading @@ -401,54 +404,65 @@ static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk) return 0; } static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, unsigned int offset, u8 type, u8 version, void *data, size_t size) static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size) { unsigned long value; u8 *ptr = data; u32 subpack[2]; unsigned long value = 0; size_t i; u8 csum; /* first byte of data is the checksum */ csum = type + version + size - 1; for (i = size; i > 0; i--) value = (value << 8) | ptr[i - 1]; for (i = 1; i < size; i++) csum += ptr[i]; return value; } ptr[0] = 0x100 - csum; static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, size_t size) { const u8 *ptr = data; unsigned long offset; unsigned long value; size_t i, j; value = INFOFRAME_HEADER_TYPE(type) | INFOFRAME_HEADER_VERSION(version) | INFOFRAME_HEADER_LEN(size - 1); tegra_hdmi_writel(hdmi, value, offset); switch (ptr[0]) { case HDMI_INFOFRAME_TYPE_AVI: offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER; break; /* 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 (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER) size = 6; case HDMI_INFOFRAME_TYPE_AUDIO: offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER; break; /* 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 < size; i++) { size_t index = i % 7; case HDMI_INFOFRAME_TYPE_VENDOR: offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER; break; if (index == 0) memset(subpack, 0x0, sizeof(subpack)); default: dev_err(hdmi->dev, "unsupported infoframe type: %02x\n", ptr[0]); return; } ((u8 *)subpack)[index] = ptr[i]; value = INFOFRAME_HEADER_TYPE(ptr[0]) | INFOFRAME_HEADER_VERSION(ptr[1]) | INFOFRAME_HEADER_LEN(ptr[2]); tegra_hdmi_writel(hdmi, value, offset); offset++; if (index == 6 || (i + 1 == size)) { unsigned int reg = offset + 1 + (i / 7) * 2; /* * Each subpack contains 7 bytes, divided into: * - subpack_low: bytes 0 - 3 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) */ for (i = 3, j = 0; i < size; i += 7, j += 8) { size_t rem = size - i, num = min_t(size_t, rem, 4); tegra_hdmi_writel(hdmi, subpack[0], reg); tegra_hdmi_writel(hdmi, subpack[1], reg + 1); } value = tegra_hdmi_subpack(&ptr[i], num); tegra_hdmi_writel(hdmi, value, offset++); num = min_t(size_t, rem - num, 3); value = tegra_hdmi_subpack(&ptr[i + 4], num); tegra_hdmi_writel(hdmi, value, offset++); } } Loading @@ -456,9 +470,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, struct drm_display_mode *mode) { struct hdmi_avi_infoframe frame; unsigned int h_front_porch; unsigned int hsize = 16; unsigned int vsize = 9; u8 buffer[17]; ssize_t err; if (hdmi->dvi) { tegra_hdmi_writel(hdmi, 0, Loading @@ -466,69 +479,19 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, return; } h_front_porch = mode->hsync_start - mode->hdisplay; memset(&frame, 0, sizeof(frame)); frame.r = HDMI_AVI_R_SAME; switch (mode->vdisplay) { case 480: if (mode->hdisplay == 640) { frame.m = HDMI_AVI_M_4_3; frame.vic = 1; } else { frame.m = HDMI_AVI_M_16_9; frame.vic = 3; } break; case 576: if (((hsize * 10) / vsize) > 14) { frame.m = HDMI_AVI_M_16_9; frame.vic = 18; } else { frame.m = HDMI_AVI_M_4_3; frame.vic = 17; } break; case 720: case 1470: /* stereo mode */ frame.m = HDMI_AVI_M_16_9; if (h_front_porch == 110) frame.vic = 4; else frame.vic = 19; break; case 1080: case 2205: /* stereo mode */ frame.m = HDMI_AVI_M_16_9; switch (h_front_porch) { case 88: frame.vic = 16; break; case 528: frame.vic = 31; break; default: frame.vic = 32; break; err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); if (err < 0) { dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); return; } break; default: frame.m = HDMI_AVI_M_16_9; frame.vic = 0; break; err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER, HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION, &frame, sizeof(frame)); tegra_hdmi_write_infopack(hdmi, buffer, err); tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); Loading @@ -537,6 +500,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) { struct hdmi_audio_infoframe frame; u8 buffer[14]; ssize_t err; if (hdmi->dvi) { tegra_hdmi_writel(hdmi, 0, Loading @@ -544,14 +509,29 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) return; } memset(&frame, 0, sizeof(frame)); frame.cc = HDMI_AUDIO_CC_2; err = hdmi_audio_infoframe_init(&frame); if (err < 0) { dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER, HDMI_INFOFRAME_TYPE_AUDIO, HDMI_AUDIO_VERSION, &frame, sizeof(frame)); frame.channels = 2; err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n", err); return; } /* * The audio infoframe has only one set of subpack registers, so the * infoframe needs to be truncated. One set of subpack registers can * contain 7 bytes. Including the 3 byte header only the first 10 * bytes can be programmed. */ tegra_hdmi_write_infopack(hdmi, buffer, min(10, err)); tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); Loading @@ -559,8 +539,10 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) { struct hdmi_stereo_infoframe frame; struct hdmi_vendor_infoframe frame; unsigned long value; u8 buffer[10]; ssize_t err; if (!hdmi->stereo) { value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); Loading @@ -570,22 +552,32 @@ static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) } memset(&frame, 0, sizeof(frame)); frame.regid0 = 0x03; frame.regid1 = 0x0c; frame.regid2 = 0x00; frame.hdmi_video_format = 2; frame.type = HDMI_INFOFRAME_TYPE_VENDOR; frame.version = 0x01; frame.length = 6; frame.data[0] = 0x03; /* regid0 */ frame.data[1] = 0x0c; /* regid1 */ frame.data[2] = 0x00; /* regid2 */ frame.data[3] = 0x02 << 5; /* video format */ /* TODO: 74 MHz limit? */ if (1) { frame._3d_structure = 0; frame.data[4] = 0x00 << 4; /* 3D structure */ } else { frame._3d_structure = 8; frame._3d_ext_data = 0; frame.data[4] = 0x08 << 4; /* 3D structure */ frame.data[5] = 0x00 << 4; /* 3D ext. data */ } err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); if (err < 0) { dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n", err); return; } tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER, HDMI_INFOFRAME_TYPE_VENDOR, HDMI_VENDOR_VERSION, &frame, 6); tegra_hdmi_write_infopack(hdmi, buffer, err); value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); value |= GENERIC_CTRL_ENABLE; Loading
drivers/gpu/drm/tegra/hdmi.h +0 −189 Original line number Diff line number Diff line Loading @@ -10,195 +10,6 @@ #ifndef TEGRA_HDMI_H #define TEGRA_HDMI_H 1 #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; } __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; } __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 /* all fields little endian */ struct hdmi_stereo_infoframe { /* PB0 */ u8 csum; /* PB1 */ u8 regid0; /* PB2 */ u8 regid1; /* PB3 */ u8 regid2; /* PB4 */ unsigned res1:5; unsigned hdmi_video_format:3; /* PB5 */ unsigned res2:4; unsigned _3d_structure:4; /* PB6*/ unsigned res3:4; unsigned _3d_ext_data:4; } __packed; #define HDMI_VENDOR_VERSION 0x01 /* register definitions */ #define HDMI_CTXSW 0x00 Loading