aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2016-11-07 10:04:43 -0500
committerInki Dae <daeinki@gmail.com>2016-12-05 08:08:58 -0500
commit5f9e228d1cdd45f7737f31746e02e99a7235d3dd (patch)
treec10b9cfeedaae53d7376e601a9fb0bfb3a2f4508
parentf03ee46be9401e3434f52bb15e92d1e640f76438 (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.c141
-rw-r--r--drivers/gpu/drm/exynos/regs-hdmi.h2
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
63enum hdmi_type { 50enum 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
670static 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
684static inline void hdmi_reg_writemask(struct hdmi_context *hdata, 677static 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
765static u8 hdmi_chksum(struct hdmi_context *hdata, 758static 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
780static 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
1128static void hdmi_conf_init(struct hdmi_context *hdata) 1078static 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
1464static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) 1403static 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))