diff options
author | Rahul Sharma <rahul.sharma@samsung.com> | 2012-11-26 00:22:57 -0500 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2012-12-05 00:39:23 -0500 |
commit | a144c2e9f17b738ac47716f1fb033cbfcfcde934 (patch) | |
tree | 8e7d0c97f1ebecf326f19de32770f868c2994522 | |
parent | a4d8de5f1b765aef577a9347f2166d61a5b0a2db (diff) |
drm/exynos: sending AVI and AUI info frames
This patch adds code for composing AVI and AUI info frames
and send them every VSYNC.
This patch is important for hdmi certification.
v3:
- Moved enums, macros to exynos_hdmi.c.
- Corrected hex format.
- Added static to hdmi_reg_infoframe.
v2:
- Added few blank lines.
- Corrected comments format.
- Added comments for 2's Complement calculation for check sum.
v1:
- Remove un-necessary blank lines.
- Change the case of hex constants.
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Fahad Kunnathadi <fahad.k@samsung.com>
Signed-off-by: Shirish S <s.shirish@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 165 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/regs-hdmi.h | 17 |
2 files changed, 161 insertions, 21 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 9f017748e730..bafb65389562 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -50,6 +50,29 @@ | |||
50 | #define MAX_HEIGHT 1080 | 50 | #define MAX_HEIGHT 1080 |
51 | #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) | 51 | #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) |
52 | 52 | ||
53 | /* AVI header and aspect ratio */ | ||
54 | #define HDMI_AVI_VERSION 0x02 | ||
55 | #define HDMI_AVI_LENGTH 0x0D | ||
56 | #define AVI_PIC_ASPECT_RATIO_16_9 (2 << 4) | ||
57 | #define AVI_SAME_AS_PIC_ASPECT_RATIO 8 | ||
58 | |||
59 | /* AUI header info */ | ||
60 | #define HDMI_AUI_VERSION 0x01 | ||
61 | #define HDMI_AUI_LENGTH 0x0A | ||
62 | |||
63 | /* HDMI infoframe to configure HDMI out packet header, AUI and AVI */ | ||
64 | enum HDMI_PACKET_TYPE { | ||
65 | /* refer to Table 5-8 Packet Type in HDMI specification v1.4a */ | ||
66 | /* InfoFrame packet type */ | ||
67 | HDMI_PACKET_TYPE_INFOFRAME = 0x80, | ||
68 | /* Vendor-Specific InfoFrame */ | ||
69 | HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1, | ||
70 | /* Auxiliary Video information InfoFrame */ | ||
71 | HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2, | ||
72 | /* Audio information InfoFrame */ | ||
73 | HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4 | ||
74 | }; | ||
75 | |||
53 | enum hdmi_type { | 76 | enum hdmi_type { |
54 | HDMI_TYPE13, | 77 | HDMI_TYPE13, |
55 | HDMI_TYPE14, | 78 | HDMI_TYPE14, |
@@ -182,6 +205,7 @@ struct hdmi_v13_conf { | |||
182 | int height; | 205 | int height; |
183 | int vrefresh; | 206 | int vrefresh; |
184 | bool interlace; | 207 | bool interlace; |
208 | int cea_video_id; | ||
185 | const u8 *hdmiphy_data; | 209 | const u8 *hdmiphy_data; |
186 | const struct hdmi_v13_preset_conf *conf; | 210 | const struct hdmi_v13_preset_conf *conf; |
187 | }; | 211 | }; |
@@ -353,15 +377,20 @@ static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = { | |||
353 | }; | 377 | }; |
354 | 378 | ||
355 | static const struct hdmi_v13_conf hdmi_v13_confs[] = { | 379 | static const struct hdmi_v13_conf hdmi_v13_confs[] = { |
356 | { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, | 380 | { 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25, |
357 | { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, | 381 | &hdmi_v13_conf_720p60 }, |
358 | { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p }, | 382 | { 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25, |
359 | { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 }, | 383 | &hdmi_v13_conf_720p60 }, |
360 | { 1920, 1080, 50, false, hdmiphy_v13_conf148_5, | 384 | { 720, 480, 60, false, 3, hdmiphy_v13_conf27_027, |
361 | &hdmi_v13_conf_1080p50 }, | 385 | &hdmi_v13_conf_480p }, |
362 | { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 }, | 386 | { 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25, |
363 | { 1920, 1080, 60, false, hdmiphy_v13_conf148_5, | 387 | &hdmi_v13_conf_1080i50 }, |
364 | &hdmi_v13_conf_1080p60 }, | 388 | { 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5, |
389 | &hdmi_v13_conf_1080p50 }, | ||
390 | { 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25, | ||
391 | &hdmi_v13_conf_1080i60 }, | ||
392 | { 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5, | ||
393 | &hdmi_v13_conf_1080p60 }, | ||
365 | }; | 394 | }; |
366 | 395 | ||
367 | /* HDMI Version 1.4 */ | 396 | /* HDMI Version 1.4 */ |
@@ -479,6 +508,7 @@ struct hdmi_conf { | |||
479 | int height; | 508 | int height; |
480 | int vrefresh; | 509 | int vrefresh; |
481 | bool interlace; | 510 | bool interlace; |
511 | int cea_video_id; | ||
482 | const u8 *hdmiphy_data; | 512 | const u8 *hdmiphy_data; |
483 | const struct hdmi_preset_conf *conf; | 513 | const struct hdmi_preset_conf *conf; |
484 | }; | 514 | }; |
@@ -934,16 +964,21 @@ static const struct hdmi_preset_conf hdmi_conf_1080p60 = { | |||
934 | }; | 964 | }; |
935 | 965 | ||
936 | static const struct hdmi_conf hdmi_confs[] = { | 966 | static const struct hdmi_conf hdmi_confs[] = { |
937 | { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 }, | 967 | { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 }, |
938 | { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 }, | 968 | { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 }, |
939 | { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 }, | 969 | { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 }, |
940 | { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, | 970 | { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, |
941 | { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, | 971 | { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, |
942 | { 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, | 972 | { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, |
943 | { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, | 973 | { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, |
944 | { 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, | 974 | { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, |
945 | }; | 975 | }; |
946 | 976 | ||
977 | struct hdmi_infoframe { | ||
978 | enum HDMI_PACKET_TYPE type; | ||
979 | u8 ver; | ||
980 | u8 len; | ||
981 | }; | ||
947 | 982 | ||
948 | static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id) | 983 | static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id) |
949 | { | 984 | { |
@@ -1267,6 +1302,88 @@ static int hdmi_conf_index(struct hdmi_context *hdata, | |||
1267 | return hdmi_v14_conf_index(mode); | 1302 | return hdmi_v14_conf_index(mode); |
1268 | } | 1303 | } |
1269 | 1304 | ||
1305 | static u8 hdmi_chksum(struct hdmi_context *hdata, | ||
1306 | u32 start, u8 len, u32 hdr_sum) | ||
1307 | { | ||
1308 | int i; | ||
1309 | |||
1310 | /* hdr_sum : header0 + header1 + header2 | ||
1311 | * start : start address of packet byte1 | ||
1312 | * len : packet bytes - 1 */ | ||
1313 | for (i = 0; i < len; ++i) | ||
1314 | hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4); | ||
1315 | |||
1316 | /* return 2's complement of 8 bit hdr_sum */ | ||
1317 | return (u8)(~(hdr_sum & 0xff) + 1); | ||
1318 | } | ||
1319 | |||
1320 | static void hdmi_reg_infoframe(struct hdmi_context *hdata, | ||
1321 | struct hdmi_infoframe *infoframe) | ||
1322 | { | ||
1323 | u32 hdr_sum; | ||
1324 | u8 chksum; | ||
1325 | u32 aspect_ratio; | ||
1326 | u32 mod; | ||
1327 | u32 vic; | ||
1328 | |||
1329 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
1330 | |||
1331 | mod = hdmi_reg_read(hdata, HDMI_MODE_SEL); | ||
1332 | if (hdata->dvi_mode) { | ||
1333 | hdmi_reg_writeb(hdata, HDMI_VSI_CON, | ||
1334 | HDMI_VSI_CON_DO_NOT_TRANSMIT); | ||
1335 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, | ||
1336 | HDMI_AVI_CON_DO_NOT_TRANSMIT); | ||
1337 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN); | ||
1338 | return; | ||
1339 | } | ||
1340 | |||
1341 | switch (infoframe->type) { | ||
1342 | case HDMI_PACKET_TYPE_AVI: | ||
1343 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC); | ||
1344 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type); | ||
1345 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver); | ||
1346 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len); | ||
1347 | hdr_sum = infoframe->type + infoframe->ver + infoframe->len; | ||
1348 | |||
1349 | /* Output format zero hardcoded ,RGB YBCR selection */ | ||
1350 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 | | ||
1351 | AVI_ACTIVE_FORMAT_VALID | | ||
1352 | AVI_UNDERSCANNED_DISPLAY_VALID); | ||
1353 | |||
1354 | aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9; | ||
1355 | |||
1356 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio | | ||
1357 | AVI_SAME_AS_PIC_ASPECT_RATIO); | ||
1358 | |||
1359 | if (hdata->type == HDMI_TYPE13) | ||
1360 | vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id; | ||
1361 | else | ||
1362 | vic = hdmi_confs[hdata->cur_conf].cea_video_id; | ||
1363 | |||
1364 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); | ||
1365 | |||
1366 | chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), | ||
1367 | infoframe->len, hdr_sum); | ||
1368 | DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum); | ||
1369 | hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum); | ||
1370 | break; | ||
1371 | case HDMI_PACKET_TYPE_AUI: | ||
1372 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02); | ||
1373 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type); | ||
1374 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver); | ||
1375 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len); | ||
1376 | hdr_sum = infoframe->type + infoframe->ver + infoframe->len; | ||
1377 | chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1), | ||
1378 | infoframe->len, hdr_sum); | ||
1379 | DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum); | ||
1380 | hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum); | ||
1381 | break; | ||
1382 | default: | ||
1383 | break; | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1270 | static bool hdmi_is_connected(void *ctx) | 1387 | static bool hdmi_is_connected(void *ctx) |
1271 | { | 1388 | { |
1272 | struct hdmi_context *hdata = ctx; | 1389 | struct hdmi_context *hdata = ctx; |
@@ -1542,6 +1659,8 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) | |||
1542 | 1659 | ||
1543 | static void hdmi_conf_init(struct hdmi_context *hdata) | 1660 | static void hdmi_conf_init(struct hdmi_context *hdata) |
1544 | { | 1661 | { |
1662 | struct hdmi_infoframe infoframe; | ||
1663 | |||
1545 | /* disable HPD interrupts */ | 1664 | /* disable HPD interrupts */ |
1546 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | | 1665 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | |
1547 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); | 1666 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); |
@@ -1576,9 +1695,17 @@ static void hdmi_conf_init(struct hdmi_context *hdata) | |||
1576 | hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); | 1695 | hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); |
1577 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); | 1696 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); |
1578 | } else { | 1697 | } else { |
1698 | infoframe.type = HDMI_PACKET_TYPE_AVI; | ||
1699 | infoframe.ver = HDMI_AVI_VERSION; | ||
1700 | infoframe.len = HDMI_AVI_LENGTH; | ||
1701 | hdmi_reg_infoframe(hdata, &infoframe); | ||
1702 | |||
1703 | infoframe.type = HDMI_PACKET_TYPE_AUI; | ||
1704 | infoframe.ver = HDMI_AUI_VERSION; | ||
1705 | infoframe.len = HDMI_AUI_LENGTH; | ||
1706 | hdmi_reg_infoframe(hdata, &infoframe); | ||
1707 | |||
1579 | /* enable AVI packet every vsync, fixes purple line problem */ | 1708 | /* enable AVI packet every vsync, fixes purple line problem */ |
1580 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02); | ||
1581 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5); | ||
1582 | hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); | 1709 | hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); |
1583 | } | 1710 | } |
1584 | } | 1711 | } |
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 9cc7c5e9718c..970cdb518eb1 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h | |||
@@ -298,14 +298,14 @@ | |||
298 | #define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714) | 298 | #define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714) |
299 | #define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718) | 299 | #define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718) |
300 | #define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C) | 300 | #define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C) |
301 | #define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n)) | 301 | #define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n-1)) |
302 | 302 | ||
303 | #define HDMI_AUI_CON HDMI_CORE_BASE(0x0800) | 303 | #define HDMI_AUI_CON HDMI_CORE_BASE(0x0800) |
304 | #define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810) | 304 | #define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810) |
305 | #define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814) | 305 | #define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814) |
306 | #define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818) | 306 | #define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818) |
307 | #define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C) | 307 | #define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C) |
308 | #define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n)) | 308 | #define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n-1)) |
309 | 309 | ||
310 | #define HDMI_MPG_CON HDMI_CORE_BASE(0x0900) | 310 | #define HDMI_MPG_CON HDMI_CORE_BASE(0x0900) |
311 | #define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C) | 311 | #define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C) |
@@ -338,6 +338,19 @@ | |||
338 | #define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60) | 338 | #define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60) |
339 | #define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64) | 339 | #define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64) |
340 | 340 | ||
341 | /* AVI bit definition */ | ||
342 | #define HDMI_AVI_CON_DO_NOT_TRANSMIT (0 << 1) | ||
343 | #define HDMI_AVI_CON_EVERY_VSYNC (1 << 1) | ||
344 | |||
345 | #define AVI_ACTIVE_FORMAT_VALID (1 << 4) | ||
346 | #define AVI_UNDERSCANNED_DISPLAY_VALID (1 << 1) | ||
347 | |||
348 | /* AUI bit definition */ | ||
349 | #define HDMI_AUI_CON_NO_TRAN (0 << 0) | ||
350 | |||
351 | /* VSI bit definition */ | ||
352 | #define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0) | ||
353 | |||
341 | /* HDCP related registers */ | 354 | /* HDCP related registers */ |
342 | #define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) | 355 | #define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) |
343 | #define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n)) | 356 | #define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n)) |