Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/mediatek: add hdmi driver for MT2701 and MT7623

This patch adds hdmi dirver suppot for both MT2701 and MT7623.
And also support other (existing or future) chips that use
the same binding and driver.

Signed-off-by: chunhui dai <chunhui.dai@mediatek.com>
Signed-off-by: CK Hu <ck.hu@mediatek.com>

authored by

chunhui dai and committed by
CK Hu
0fc721b2 d1ef028d

+225 -2
+1
drivers/gpu/drm/mediatek/Makefile
··· 19 19 mediatek-drm-hdmi-objs := mtk_cec.o \ 20 20 mtk_hdmi.o \ 21 21 mtk_hdmi_ddc.o \ 22 + mtk_mt2701_hdmi_phy.o \ 22 23 mtk_mt8173_hdmi_phy.o \ 23 24 mtk_hdmi_phy.o 24 25
+7 -2
drivers/gpu/drm/mediatek/mtk_hdmi.c
··· 241 241 * The ARM trusted firmware provides an API for the HDMI driver to set 242 242 * this control bit to enable HDMI output in supervisor mode. 243 243 */ 244 - arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000, 245 - 0, 0, 0, 0, 0, &res); 244 + if (hdmi_phy->conf && hdmi_phy->conf->tz_disabled) 245 + regmap_update_bits(hdmi->sys_regmap, 246 + hdmi->sys_offset + HDMI_SYS_CFG20, 247 + 0x80008005, enable ? 0x80000005 : 0x8000); 248 + else 249 + arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 250 + 0x80000000, 0, 0, 0, 0, 0, &res); 246 251 247 252 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, 248 253 HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0);
+3
drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
··· 214 214 } 215 215 216 216 static const struct of_device_id mtk_hdmi_phy_match[] = { 217 + { .compatible = "mediatek,mt2701-hdmi-phy", 218 + .data = &mtk_hdmi_phy_2701_conf, 219 + }, 217 220 { .compatible = "mediatek,mt8173-hdmi-phy", 218 221 .data = &mtk_hdmi_phy_8173_conf, 219 222 },
+2
drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
··· 20 20 struct mtk_hdmi_phy; 21 21 22 22 struct mtk_hdmi_phy_conf { 23 + bool tz_disabled; 23 24 const struct clk_ops *hdmi_phy_clk_ops; 24 25 void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy); 25 26 void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy); ··· 55 54 56 55 extern struct platform_driver mtk_hdmi_phy_driver; 57 56 extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf; 57 + extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf; 58 58 59 59 #endif /* _MTK_HDMI_PHY_H */
+212
drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2018 MediaTek Inc. 4 + * Author: Chunhui Dai <chunhui.dai@mediatek.com> 5 + */ 6 + 7 + #include "mtk_hdmi_phy.h" 8 + 9 + #define HDMI_CON0 0x00 10 + #define RG_HDMITX_DRV_IBIAS 0 11 + #define RG_HDMITX_DRV_IBIAS_MASK (0x3f << 0) 12 + #define RG_HDMITX_EN_SER 12 13 + #define RG_HDMITX_EN_SER_MASK (0x0f << 12) 14 + #define RG_HDMITX_EN_SLDO 16 15 + #define RG_HDMITX_EN_SLDO_MASK (0x0f << 16) 16 + #define RG_HDMITX_EN_PRED 20 17 + #define RG_HDMITX_EN_PRED_MASK (0x0f << 20) 18 + #define RG_HDMITX_EN_IMP 24 19 + #define RG_HDMITX_EN_IMP_MASK (0x0f << 24) 20 + #define RG_HDMITX_EN_DRV 28 21 + #define RG_HDMITX_EN_DRV_MASK (0x0f << 28) 22 + 23 + #define HDMI_CON1 0x04 24 + #define RG_HDMITX_PRED_IBIAS 18 25 + #define RG_HDMITX_PRED_IBIAS_MASK (0x0f << 18) 26 + #define RG_HDMITX_PRED_IMP (0x01 << 22) 27 + #define RG_HDMITX_DRV_IMP 26 28 + #define RG_HDMITX_DRV_IMP_MASK (0x3f << 26) 29 + 30 + #define HDMI_CON2 0x08 31 + #define RG_HDMITX_EN_TX_CKLDO (0x01 << 0) 32 + #define RG_HDMITX_EN_TX_POSDIV (0x01 << 1) 33 + #define RG_HDMITX_TX_POSDIV 3 34 + #define RG_HDMITX_TX_POSDIV_MASK (0x03 << 3) 35 + #define RG_HDMITX_EN_MBIAS (0x01 << 6) 36 + #define RG_HDMITX_MBIAS_LPF_EN (0x01 << 7) 37 + 38 + #define HDMI_CON4 0x10 39 + #define RG_HDMITX_RESERVE_MASK (0xffffffff << 0) 40 + 41 + #define HDMI_CON6 0x18 42 + #define RG_HTPLL_BR 0 43 + #define RG_HTPLL_BR_MASK (0x03 << 0) 44 + #define RG_HTPLL_BC 2 45 + #define RG_HTPLL_BC_MASK (0x03 << 2) 46 + #define RG_HTPLL_BP 4 47 + #define RG_HTPLL_BP_MASK (0x0f << 4) 48 + #define RG_HTPLL_IR 8 49 + #define RG_HTPLL_IR_MASK (0x0f << 8) 50 + #define RG_HTPLL_IC 12 51 + #define RG_HTPLL_IC_MASK (0x0f << 12) 52 + #define RG_HTPLL_POSDIV 16 53 + #define RG_HTPLL_POSDIV_MASK (0x03 << 16) 54 + #define RG_HTPLL_PREDIV 18 55 + #define RG_HTPLL_PREDIV_MASK (0x03 << 18) 56 + #define RG_HTPLL_FBKSEL 20 57 + #define RG_HTPLL_FBKSEL_MASK (0x03 << 20) 58 + #define RG_HTPLL_RLH_EN (0x01 << 22) 59 + #define RG_HTPLL_FBKDIV 24 60 + #define RG_HTPLL_FBKDIV_MASK (0x7f << 24) 61 + #define RG_HTPLL_EN (0x01 << 31) 62 + 63 + #define HDMI_CON7 0x1c 64 + #define RG_HTPLL_AUTOK_EN (0x01 << 23) 65 + #define RG_HTPLL_DIVEN 28 66 + #define RG_HTPLL_DIVEN_MASK (0x07 << 28) 67 + 68 + static int mtk_hdmi_pll_prepare(struct clk_hw *hw) 69 + { 70 + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); 71 + 72 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN); 73 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN); 74 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK); 75 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS); 76 + usleep_range(80, 100); 77 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN); 78 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO); 79 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK); 80 + usleep_range(80, 100); 81 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN); 82 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV); 83 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK); 84 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK); 85 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK); 86 + usleep_range(80, 100); 87 + return 0; 88 + } 89 + 90 + static void mtk_hdmi_pll_unprepare(struct clk_hw *hw) 91 + { 92 + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); 93 + 94 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK); 95 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK); 96 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK); 97 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV); 98 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN); 99 + usleep_range(80, 100); 100 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK); 101 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO); 102 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN); 103 + usleep_range(80, 100); 104 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS); 105 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK); 106 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN); 107 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN); 108 + usleep_range(80, 100); 109 + } 110 + 111 + static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, 112 + unsigned long parent_rate) 113 + { 114 + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); 115 + u32 pos_div; 116 + 117 + if (rate <= 64000000) 118 + pos_div = 3; 119 + else if (rate <= 12800000) 120 + pos_div = 1; 121 + else 122 + pos_div = 1; 123 + 124 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK); 125 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK); 126 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC), 127 + RG_HTPLL_IC_MASK); 128 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR), 129 + RG_HTPLL_IR_MASK); 130 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV), 131 + RG_HDMITX_TX_POSDIV_MASK); 132 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL), 133 + RG_HTPLL_FBKSEL_MASK); 134 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV), 135 + RG_HTPLL_FBKDIV_MASK); 136 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN), 137 + RG_HTPLL_DIVEN_MASK); 138 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP), 139 + RG_HTPLL_BP_MASK); 140 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC), 141 + RG_HTPLL_BC_MASK); 142 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR), 143 + RG_HTPLL_BR_MASK); 144 + 145 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP); 146 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS), 147 + RG_HDMITX_PRED_IBIAS_MASK); 148 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK); 149 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP), 150 + RG_HDMITX_DRV_IMP_MASK); 151 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK); 152 + mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS), 153 + RG_HDMITX_DRV_IBIAS_MASK); 154 + return 0; 155 + } 156 + 157 + static const struct clk_ops mtk_hdmi_phy_pll_ops = { 158 + .prepare = mtk_hdmi_pll_prepare, 159 + .unprepare = mtk_hdmi_pll_unprepare, 160 + .set_rate = mtk_hdmi_pll_set_rate, 161 + .round_rate = mtk_hdmi_pll_round_rate, 162 + .recalc_rate = mtk_hdmi_pll_recalc_rate, 163 + }; 164 + 165 + static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy) 166 + { 167 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN); 168 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN); 169 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK); 170 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS); 171 + usleep_range(80, 100); 172 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN); 173 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO); 174 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK); 175 + usleep_range(80, 100); 176 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN); 177 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV); 178 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK); 179 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK); 180 + mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK); 181 + usleep_range(80, 100); 182 + } 183 + 184 + static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy) 185 + { 186 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK); 187 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK); 188 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK); 189 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV); 190 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN); 191 + usleep_range(80, 100); 192 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK); 193 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO); 194 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN); 195 + usleep_range(80, 100); 196 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS); 197 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK); 198 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN); 199 + mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN); 200 + usleep_range(80, 100); 201 + } 202 + 203 + struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = { 204 + .tz_disabled = true, 205 + .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops, 206 + .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds, 207 + .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds, 208 + }; 209 + 210 + MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>"); 211 + MODULE_DESCRIPTION("MediaTek HDMI PHY Driver"); 212 + MODULE_LICENSE("GPL v2");