diff options
author | Andrzej Hajda <a.hajda@samsung.com> | 2016-11-07 10:04:43 -0500 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2016-12-05 08:08:58 -0500 |
commit | 5f9e228d1cdd45f7737f31746e02e99a7235d3dd (patch) | |
tree | c10b9cfeedaae53d7376e601a9fb0bfb3a2f4508 | |
parent | f03ee46be9401e3434f52bb15e92d1e640f76438 (diff) |
drm/exynos/hdmi: refactor infoframe code
Use core helpers to generate infoframes and generate vendor frame if necessary.
Changelog:
- changed 'ret >= 0' checks to '!ret'
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 141 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/regs-hdmi.h | 2 |
2 files changed, 42 insertions, 101 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 38eaa63afb31..5ed8b1effe71 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -47,19 +47,6 @@ | |||
47 | 47 | ||
48 | #define HOTPLUG_DEBOUNCE_MS 1100 | 48 | #define HOTPLUG_DEBOUNCE_MS 1100 |
49 | 49 | ||
50 | /* AVI header and aspect ratio */ | ||
51 | #define HDMI_AVI_VERSION 0x02 | ||
52 | #define HDMI_AVI_LENGTH 0x0d | ||
53 | |||
54 | /* AUI header info */ | ||
55 | #define HDMI_AUI_VERSION 0x01 | ||
56 | #define HDMI_AUI_LENGTH 0x0a | ||
57 | |||
58 | /* AVI active format aspect ratio */ | ||
59 | #define AVI_SAME_AS_PIC_ASPECT_RATIO 0x08 | ||
60 | #define AVI_4_3_CENTER_RATIO 0x09 | ||
61 | #define AVI_16_9_CENTER_RATIO 0x0a | ||
62 | |||
63 | enum hdmi_type { | 50 | enum hdmi_type { |
64 | HDMI_TYPE13, | 51 | HDMI_TYPE13, |
65 | HDMI_TYPE14, | 52 | HDMI_TYPE14, |
@@ -131,7 +118,6 @@ struct hdmi_context { | |||
131 | bool dvi_mode; | 118 | bool dvi_mode; |
132 | struct delayed_work hotplug_work; | 119 | struct delayed_work hotplug_work; |
133 | struct drm_display_mode current_mode; | 120 | struct drm_display_mode current_mode; |
134 | u8 cea_video_id; | ||
135 | const struct hdmi_driver_data *drv_data; | 121 | const struct hdmi_driver_data *drv_data; |
136 | 122 | ||
137 | void __iomem *regs; | 123 | void __iomem *regs; |
@@ -681,6 +667,13 @@ static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id, | |||
681 | } | 667 | } |
682 | } | 668 | } |
683 | 669 | ||
670 | static inline void hdmi_reg_write_buf(struct hdmi_context *hdata, u32 reg_id, | ||
671 | u8 *buf, int size) | ||
672 | { | ||
673 | for (reg_id = hdmi_map_reg(hdata, reg_id); size; --size, reg_id += 4) | ||
674 | writel(*buf++, hdata->regs + reg_id); | ||
675 | } | ||
676 | |||
684 | static inline void hdmi_reg_writemask(struct hdmi_context *hdata, | 677 | static inline void hdmi_reg_writemask(struct hdmi_context *hdata, |
685 | u32 reg_id, u32 value, u32 mask) | 678 | u32 reg_id, u32 value, u32 mask) |
686 | { | 679 | { |
@@ -762,93 +755,50 @@ static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy) | |||
762 | return ret; | 755 | return ret; |
763 | } | 756 | } |
764 | 757 | ||
765 | static u8 hdmi_chksum(struct hdmi_context *hdata, | 758 | static void hdmi_reg_infoframes(struct hdmi_context *hdata) |
766 | u32 start, u8 len, u32 hdr_sum) | ||
767 | { | ||
768 | int i; | ||
769 | |||
770 | /* hdr_sum : header0 + header1 + header2 | ||
771 | * start : start address of packet byte1 | ||
772 | * len : packet bytes - 1 */ | ||
773 | for (i = 0; i < len; ++i) | ||
774 | hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4); | ||
775 | |||
776 | /* return 2's complement of 8 bit hdr_sum */ | ||
777 | return (u8)(~(hdr_sum & 0xff) + 1); | ||
778 | } | ||
779 | |||
780 | static void hdmi_reg_infoframe(struct hdmi_context *hdata, | ||
781 | union hdmi_infoframe *infoframe) | ||
782 | { | 759 | { |
783 | u32 hdr_sum; | 760 | union hdmi_infoframe frm; |
784 | u8 chksum; | 761 | u8 buf[25]; |
785 | u8 ar; | 762 | int ret; |
786 | 763 | ||
787 | if (hdata->dvi_mode) { | 764 | if (hdata->dvi_mode) { |
788 | hdmi_reg_writeb(hdata, HDMI_VSI_CON, | ||
789 | HDMI_VSI_CON_DO_NOT_TRANSMIT); | ||
790 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, | 765 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, |
791 | HDMI_AVI_CON_DO_NOT_TRANSMIT); | 766 | HDMI_AVI_CON_DO_NOT_TRANSMIT); |
767 | hdmi_reg_writeb(hdata, HDMI_VSI_CON, | ||
768 | HDMI_VSI_CON_DO_NOT_TRANSMIT); | ||
792 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN); | 769 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN); |
793 | return; | 770 | return; |
794 | } | 771 | } |
795 | 772 | ||
796 | switch (infoframe->any.type) { | 773 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, |
797 | case HDMI_INFOFRAME_TYPE_AVI: | 774 | &hdata->current_mode); |
775 | if (!ret) | ||
776 | ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf)); | ||
777 | if (ret > 0) { | ||
798 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC); | 778 | hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC); |
799 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type); | 779 | hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret); |
800 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, | 780 | } else { |
801 | infoframe->any.version); | 781 | DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret); |
802 | hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length); | 782 | } |
803 | hdr_sum = infoframe->any.type + infoframe->any.version + | ||
804 | infoframe->any.length; | ||
805 | |||
806 | /* Output format zero hardcoded ,RGB YBCR selection */ | ||
807 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 | | ||
808 | AVI_ACTIVE_FORMAT_VALID | | ||
809 | AVI_UNDERSCANNED_DISPLAY_VALID); | ||
810 | |||
811 | /* | ||
812 | * Set the aspect ratio as per the mode, mentioned in | ||
813 | * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard | ||
814 | */ | ||
815 | ar = hdata->current_mode.picture_aspect_ratio; | ||
816 | switch (ar) { | ||
817 | case HDMI_PICTURE_ASPECT_4_3: | ||
818 | ar |= AVI_4_3_CENTER_RATIO; | ||
819 | break; | ||
820 | case HDMI_PICTURE_ASPECT_16_9: | ||
821 | ar |= AVI_16_9_CENTER_RATIO; | ||
822 | break; | ||
823 | case HDMI_PICTURE_ASPECT_NONE: | ||
824 | default: | ||
825 | ar |= AVI_SAME_AS_PIC_ASPECT_RATIO; | ||
826 | break; | ||
827 | } | ||
828 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar); | ||
829 | 783 | ||
830 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id); | 784 | ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi, |
785 | &hdata->current_mode); | ||
786 | if (!ret) | ||
787 | ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf, | ||
788 | sizeof(buf)); | ||
789 | if (ret > 0) { | ||
790 | hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC); | ||
791 | hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, ret); | ||
792 | } | ||
831 | 793 | ||
832 | chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), | 794 | ret = hdmi_audio_infoframe_init(&frm.audio); |
833 | infoframe->any.length, hdr_sum); | 795 | if (!ret) { |
834 | DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum); | 796 | frm.audio.channels = 2; |
835 | hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum); | 797 | ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf)); |
836 | break; | 798 | } |
837 | case HDMI_INFOFRAME_TYPE_AUDIO: | 799 | if (ret > 0) { |
838 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02); | 800 | hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC); |
839 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type); | 801 | hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret); |
840 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, | ||
841 | infoframe->any.version); | ||
842 | hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length); | ||
843 | hdr_sum = infoframe->any.type + infoframe->any.version + | ||
844 | infoframe->any.length; | ||
845 | chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1), | ||
846 | infoframe->any.length, hdr_sum); | ||
847 | DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum); | ||
848 | hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum); | ||
849 | break; | ||
850 | default: | ||
851 | break; | ||
852 | } | 802 | } |
853 | } | 803 | } |
854 | 804 | ||
@@ -1127,8 +1077,6 @@ static void hdmi_start(struct hdmi_context *hdata, bool start) | |||
1127 | 1077 | ||
1128 | static void hdmi_conf_init(struct hdmi_context *hdata) | 1078 | static void hdmi_conf_init(struct hdmi_context *hdata) |
1129 | { | 1079 | { |
1130 | union hdmi_infoframe infoframe; | ||
1131 | |||
1132 | /* disable HPD interrupts from HDMI IP block, use GPIO instead */ | 1080 | /* disable HPD interrupts from HDMI IP block, use GPIO instead */ |
1133 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | | 1081 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | |
1134 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); | 1082 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); |
@@ -1164,15 +1112,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata) | |||
1164 | hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); | 1112 | hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); |
1165 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); | 1113 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); |
1166 | } else { | 1114 | } else { |
1167 | infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI; | 1115 | hdmi_reg_infoframes(hdata); |
1168 | infoframe.any.version = HDMI_AVI_VERSION; | ||
1169 | infoframe.any.length = HDMI_AVI_LENGTH; | ||
1170 | hdmi_reg_infoframe(hdata, &infoframe); | ||
1171 | |||
1172 | infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO; | ||
1173 | infoframe.any.version = HDMI_AUI_VERSION; | ||
1174 | infoframe.any.length = HDMI_AUI_LENGTH; | ||
1175 | hdmi_reg_infoframe(hdata, &infoframe); | ||
1176 | 1116 | ||
1177 | /* enable AVI packet every vsync, fixes purple line problem */ | 1117 | /* enable AVI packet every vsync, fixes purple line problem */ |
1178 | hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); | 1118 | hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); |
@@ -1458,7 +1398,6 @@ static void hdmi_mode_set(struct drm_encoder *encoder, | |||
1458 | "INTERLACED" : "PROGRESSIVE"); | 1398 | "INTERLACED" : "PROGRESSIVE"); |
1459 | 1399 | ||
1460 | drm_mode_copy(&hdata->current_mode, m); | 1400 | drm_mode_copy(&hdata->current_mode, m); |
1461 | hdata->cea_video_id = drm_match_cea_mode(mode); | ||
1462 | } | 1401 | } |
1463 | 1402 | ||
1464 | static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) | 1403 | static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) |
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 169667a22bdc..a0507dc18d9e 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h | |||
@@ -361,9 +361,11 @@ | |||
361 | 361 | ||
362 | /* AUI bit definition */ | 362 | /* AUI bit definition */ |
363 | #define HDMI_AUI_CON_NO_TRAN (0 << 0) | 363 | #define HDMI_AUI_CON_NO_TRAN (0 << 0) |
364 | #define HDMI_AUI_CON_EVERY_VSYNC (1 << 1) | ||
364 | 365 | ||
365 | /* VSI bit definition */ | 366 | /* VSI bit definition */ |
366 | #define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0) | 367 | #define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0) |
368 | #define HDMI_VSI_CON_EVERY_VSYNC (1 << 1) | ||
367 | 369 | ||
368 | /* HDCP related registers */ | 370 | /* HDCP related registers */ |
369 | #define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) | 371 | #define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) |