0001
0002
0003
0004
0005
0006
0007 #include <drm/drm_print.h>
0008
0009 #include "sti_hdmi_tx3g4c28phy.h"
0010
0011 #define HDMI_SRZ_CFG 0x504
0012 #define HDMI_SRZ_PLL_CFG 0x510
0013 #define HDMI_SRZ_ICNTL 0x518
0014 #define HDMI_SRZ_CALCODE_EXT 0x520
0015
0016 #define HDMI_SRZ_CFG_EN BIT(0)
0017 #define HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT BIT(1)
0018 #define HDMI_SRZ_CFG_EXTERNAL_DATA BIT(16)
0019 #define HDMI_SRZ_CFG_RBIAS_EXT BIT(17)
0020 #define HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION BIT(18)
0021 #define HDMI_SRZ_CFG_EN_BIASRES_DETECTION BIT(19)
0022 #define HDMI_SRZ_CFG_EN_SRC_TERMINATION BIT(24)
0023
0024 #define HDMI_SRZ_CFG_INTERNAL_MASK (HDMI_SRZ_CFG_EN | \
0025 HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT | \
0026 HDMI_SRZ_CFG_EXTERNAL_DATA | \
0027 HDMI_SRZ_CFG_RBIAS_EXT | \
0028 HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION | \
0029 HDMI_SRZ_CFG_EN_BIASRES_DETECTION | \
0030 HDMI_SRZ_CFG_EN_SRC_TERMINATION)
0031
0032 #define PLL_CFG_EN BIT(0)
0033 #define PLL_CFG_NDIV_SHIFT (8)
0034 #define PLL_CFG_IDF_SHIFT (16)
0035 #define PLL_CFG_ODF_SHIFT (24)
0036
0037 #define ODF_DIV_1 (0)
0038 #define ODF_DIV_2 (1)
0039 #define ODF_DIV_4 (2)
0040 #define ODF_DIV_8 (3)
0041
0042 #define HDMI_TIMEOUT_PLL_LOCK 50
0043
0044 struct plldividers_s {
0045 uint32_t min;
0046 uint32_t max;
0047 uint32_t idf;
0048 uint32_t odf;
0049 };
0050
0051
0052
0053
0054 #define NB_PLL_MODE 5
0055 static struct plldividers_s plldividers[NB_PLL_MODE] = {
0056 {0, 20000000, 1, ODF_DIV_8},
0057 {20000000, 42500000, 2, ODF_DIV_8},
0058 {42500000, 85000000, 4, ODF_DIV_4},
0059 {85000000, 170000000, 8, ODF_DIV_2},
0060 {170000000, 340000000, 16, ODF_DIV_1}
0061 };
0062
0063 #define NB_HDMI_PHY_CONFIG 2
0064 static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
0065 {0, 250000000, {0x0, 0x0, 0x0, 0x0} },
0066 {250000000, 300000000, {0x1110, 0x0, 0x0, 0x0} },
0067 };
0068
0069
0070
0071
0072
0073
0074
0075
0076 static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi)
0077 {
0078 u32 ckpxpll = hdmi->mode.clock * 1000;
0079 u32 val, tmdsck, idf, odf, pllctrl = 0;
0080 bool foundplldivides = false;
0081 int i;
0082
0083 DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);
0084
0085 for (i = 0; i < NB_PLL_MODE; i++) {
0086 if (ckpxpll >= plldividers[i].min &&
0087 ckpxpll < plldividers[i].max) {
0088 idf = plldividers[i].idf;
0089 odf = plldividers[i].odf;
0090 foundplldivides = true;
0091 break;
0092 }
0093 }
0094
0095 if (!foundplldivides) {
0096 DRM_ERROR("input TMDS clock speed (%d) not supported\n",
0097 ckpxpll);
0098 goto err;
0099 }
0100
0101
0102 tmdsck = ckpxpll;
0103 pllctrl |= 40 << PLL_CFG_NDIV_SHIFT;
0104
0105 if (tmdsck > 340000000) {
0106 DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck);
0107 goto err;
0108 }
0109
0110 pllctrl |= idf << PLL_CFG_IDF_SHIFT;
0111 pllctrl |= odf << PLL_CFG_ODF_SHIFT;
0112
0113
0114
0115
0116 hdmi->event_received = false;
0117 DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
0118 hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG);
0119
0120
0121 wait_event_interruptible_timeout(hdmi->wait_event,
0122 hdmi->event_received == true,
0123 msecs_to_jiffies
0124 (HDMI_TIMEOUT_PLL_LOCK));
0125
0126 if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
0127 DRM_ERROR("hdmi phy pll not locked\n");
0128 goto err;
0129 }
0130
0131 DRM_DEBUG_DRIVER("got PHY PLL Lock\n");
0132
0133 val = (HDMI_SRZ_CFG_EN |
0134 HDMI_SRZ_CFG_EXTERNAL_DATA |
0135 HDMI_SRZ_CFG_EN_BIASRES_DETECTION |
0136 HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION);
0137
0138 if (tmdsck > 165000000)
0139 val |= HDMI_SRZ_CFG_EN_SRC_TERMINATION;
0140
0141
0142
0143
0144
0145
0146 for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {
0147 if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&
0148 (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {
0149 val |= (hdmiphy_config[i].config[0]
0150 & ~HDMI_SRZ_CFG_INTERNAL_MASK);
0151 hdmi_write(hdmi, val, HDMI_SRZ_CFG);
0152
0153 val = hdmiphy_config[i].config[1];
0154 hdmi_write(hdmi, val, HDMI_SRZ_ICNTL);
0155
0156 val = hdmiphy_config[i].config[2];
0157 hdmi_write(hdmi, val, HDMI_SRZ_CALCODE_EXT);
0158
0159 DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x\n",
0160 hdmiphy_config[i].config[0],
0161 hdmiphy_config[i].config[1],
0162 hdmiphy_config[i].config[2]);
0163 return true;
0164 }
0165 }
0166
0167
0168
0169
0170
0171 hdmi_write(hdmi, val, HDMI_SRZ_CFG);
0172 hdmi_write(hdmi, 0x0, HDMI_SRZ_ICNTL);
0173 hdmi_write(hdmi, 0x0, HDMI_SRZ_CALCODE_EXT);
0174
0175 return true;
0176
0177 err:
0178 return false;
0179 }
0180
0181
0182
0183
0184
0185
0186 static void sti_hdmi_tx3g4c28phy_stop(struct sti_hdmi *hdmi)
0187 {
0188 int val = 0;
0189
0190 DRM_DEBUG_DRIVER("\n");
0191
0192 hdmi->event_received = false;
0193
0194 val = HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION;
0195 val |= HDMI_SRZ_CFG_EN_BIASRES_DETECTION;
0196
0197 hdmi_write(hdmi, val, HDMI_SRZ_CFG);
0198 hdmi_write(hdmi, 0, HDMI_SRZ_PLL_CFG);
0199
0200
0201 wait_event_interruptible_timeout(hdmi->wait_event,
0202 hdmi->event_received == true,
0203 msecs_to_jiffies
0204 (HDMI_TIMEOUT_PLL_LOCK));
0205
0206 if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)
0207 DRM_ERROR("hdmi phy pll not well disabled\n");
0208 }
0209
0210 struct hdmi_phy_ops tx3g4c28phy_ops = {
0211 .start = sti_hdmi_tx3g4c28phy_start,
0212 .stop = sti_hdmi_tx3g4c28phy_stop,
0213 };