1*c8afe684SRob Clark /* 2*c8afe684SRob Clark * Copyright (C) 2013 Red Hat 3*c8afe684SRob Clark * Author: Rob Clark <robdclark@gmail.com> 4*c8afe684SRob Clark * 5*c8afe684SRob Clark * This program is free software; you can redistribute it and/or modify it 6*c8afe684SRob Clark * under the terms of the GNU General Public License version 2 as published by 7*c8afe684SRob Clark * the Free Software Foundation. 8*c8afe684SRob Clark * 9*c8afe684SRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 10*c8afe684SRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*c8afe684SRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*c8afe684SRob Clark * more details. 13*c8afe684SRob Clark * 14*c8afe684SRob Clark * You should have received a copy of the GNU General Public License along with 15*c8afe684SRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 16*c8afe684SRob Clark */ 17*c8afe684SRob Clark 18*c8afe684SRob Clark #include "hdmi.h" 19*c8afe684SRob Clark 20*c8afe684SRob Clark struct hdmi_phy_8x60 { 21*c8afe684SRob Clark struct hdmi_phy base; 22*c8afe684SRob Clark struct hdmi *hdmi; 23*c8afe684SRob Clark }; 24*c8afe684SRob Clark #define to_hdmi_phy_8x60(x) container_of(x, struct hdmi_phy_8x60, base) 25*c8afe684SRob Clark 26*c8afe684SRob Clark static void hdmi_phy_8x60_destroy(struct hdmi_phy *phy) 27*c8afe684SRob Clark { 28*c8afe684SRob Clark struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy); 29*c8afe684SRob Clark kfree(phy_8x60); 30*c8afe684SRob Clark } 31*c8afe684SRob Clark 32*c8afe684SRob Clark static void hdmi_phy_8x60_reset(struct hdmi_phy *phy) 33*c8afe684SRob Clark { 34*c8afe684SRob Clark struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy); 35*c8afe684SRob Clark struct hdmi *hdmi = phy_8x60->hdmi; 36*c8afe684SRob Clark unsigned int val; 37*c8afe684SRob Clark 38*c8afe684SRob Clark val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL); 39*c8afe684SRob Clark 40*c8afe684SRob Clark if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { 41*c8afe684SRob Clark /* pull low */ 42*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 43*c8afe684SRob Clark val & ~HDMI_PHY_CTRL_SW_RESET); 44*c8afe684SRob Clark } else { 45*c8afe684SRob Clark /* pull high */ 46*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 47*c8afe684SRob Clark val | HDMI_PHY_CTRL_SW_RESET); 48*c8afe684SRob Clark } 49*c8afe684SRob Clark 50*c8afe684SRob Clark msleep(100); 51*c8afe684SRob Clark 52*c8afe684SRob Clark if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { 53*c8afe684SRob Clark /* pull high */ 54*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 55*c8afe684SRob Clark val | HDMI_PHY_CTRL_SW_RESET); 56*c8afe684SRob Clark } else { 57*c8afe684SRob Clark /* pull low */ 58*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 59*c8afe684SRob Clark val & ~HDMI_PHY_CTRL_SW_RESET); 60*c8afe684SRob Clark } 61*c8afe684SRob Clark } 62*c8afe684SRob Clark 63*c8afe684SRob Clark static void hdmi_phy_8x60_powerup(struct hdmi_phy *phy, 64*c8afe684SRob Clark unsigned long int pixclock) 65*c8afe684SRob Clark { 66*c8afe684SRob Clark struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy); 67*c8afe684SRob Clark struct hdmi *hdmi = phy_8x60->hdmi; 68*c8afe684SRob Clark 69*c8afe684SRob Clark /* De-serializer delay D/C for non-lbk mode: */ 70*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG0, 71*c8afe684SRob Clark HDMI_8x60_PHY_REG0_DESER_DEL_CTRL(3)); 72*c8afe684SRob Clark 73*c8afe684SRob Clark if (pixclock == 27000000) { 74*c8afe684SRob Clark /* video_format == HDMI_VFRMT_720x480p60_16_9 */ 75*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG1, 76*c8afe684SRob Clark HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) | 77*c8afe684SRob Clark HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(3)); 78*c8afe684SRob Clark } else { 79*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG1, 80*c8afe684SRob Clark HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) | 81*c8afe684SRob Clark HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(4)); 82*c8afe684SRob Clark } 83*c8afe684SRob Clark 84*c8afe684SRob Clark /* No matter what, start from the power down mode: */ 85*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 86*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_PWRGEN | 87*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_PLL | 88*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_4 | 89*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_3 | 90*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_2 | 91*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_1 | 92*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 93*c8afe684SRob Clark 94*c8afe684SRob Clark /* Turn PowerGen on: */ 95*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 96*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_PLL | 97*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_4 | 98*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_3 | 99*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_2 | 100*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_1 | 101*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 102*c8afe684SRob Clark 103*c8afe684SRob Clark /* Turn PLL power on: */ 104*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 105*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_4 | 106*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_3 | 107*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_2 | 108*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_1 | 109*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 110*c8afe684SRob Clark 111*c8afe684SRob Clark /* Write to HIGH after PLL power down de-assert: */ 112*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG3, 113*c8afe684SRob Clark HDMI_8x60_PHY_REG3_PLL_ENABLE); 114*c8afe684SRob Clark 115*c8afe684SRob Clark /* ASIC power on; PHY REG9 = 0 */ 116*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG9, 0); 117*c8afe684SRob Clark 118*c8afe684SRob Clark /* Enable PLL lock detect, PLL lock det will go high after lock 119*c8afe684SRob Clark * Enable the re-time logic 120*c8afe684SRob Clark */ 121*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG12, 122*c8afe684SRob Clark HDMI_8x60_PHY_REG12_RETIMING_EN | 123*c8afe684SRob Clark HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN); 124*c8afe684SRob Clark 125*c8afe684SRob Clark /* Drivers are on: */ 126*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 127*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 128*c8afe684SRob Clark 129*c8afe684SRob Clark /* If the RX detector is needed: */ 130*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 131*c8afe684SRob Clark HDMI_8x60_PHY_REG2_RCV_SENSE_EN | 132*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 133*c8afe684SRob Clark 134*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG4, 0); 135*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG5, 0); 136*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG6, 0); 137*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG7, 0); 138*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG8, 0); 139*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG9, 0); 140*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG10, 0); 141*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG11, 0); 142*c8afe684SRob Clark 143*c8afe684SRob Clark /* If we want to use lock enable based on counting: */ 144*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG12, 145*c8afe684SRob Clark HDMI_8x60_PHY_REG12_RETIMING_EN | 146*c8afe684SRob Clark HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN | 147*c8afe684SRob Clark HDMI_8x60_PHY_REG12_FORCE_LOCK); 148*c8afe684SRob Clark } 149*c8afe684SRob Clark 150*c8afe684SRob Clark static void hdmi_phy_8x60_powerdown(struct hdmi_phy *phy) 151*c8afe684SRob Clark { 152*c8afe684SRob Clark struct hdmi_phy_8x60 *phy_8x60 = to_hdmi_phy_8x60(phy); 153*c8afe684SRob Clark struct hdmi *hdmi = phy_8x60->hdmi; 154*c8afe684SRob Clark 155*c8afe684SRob Clark /* Assert RESET PHY from controller */ 156*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 157*c8afe684SRob Clark HDMI_PHY_CTRL_SW_RESET); 158*c8afe684SRob Clark udelay(10); 159*c8afe684SRob Clark /* De-assert RESET PHY from controller */ 160*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_PHY_CTRL, 0); 161*c8afe684SRob Clark /* Turn off Driver */ 162*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 163*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_4 | 164*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_3 | 165*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_2 | 166*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_1 | 167*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 168*c8afe684SRob Clark udelay(10); 169*c8afe684SRob Clark /* Disable PLL */ 170*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG3, 0); 171*c8afe684SRob Clark /* Power down PHY, but keep RX-sense: */ 172*c8afe684SRob Clark hdmi_write(hdmi, REG_HDMI_8x60_PHY_REG2, 173*c8afe684SRob Clark HDMI_8x60_PHY_REG2_RCV_SENSE_EN | 174*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_PWRGEN | 175*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_PLL | 176*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_4 | 177*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_3 | 178*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_2 | 179*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DRIVE_1 | 180*c8afe684SRob Clark HDMI_8x60_PHY_REG2_PD_DESER); 181*c8afe684SRob Clark } 182*c8afe684SRob Clark 183*c8afe684SRob Clark static const struct hdmi_phy_funcs hdmi_phy_8x60_funcs = { 184*c8afe684SRob Clark .destroy = hdmi_phy_8x60_destroy, 185*c8afe684SRob Clark .reset = hdmi_phy_8x60_reset, 186*c8afe684SRob Clark .powerup = hdmi_phy_8x60_powerup, 187*c8afe684SRob Clark .powerdown = hdmi_phy_8x60_powerdown, 188*c8afe684SRob Clark }; 189*c8afe684SRob Clark 190*c8afe684SRob Clark struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi) 191*c8afe684SRob Clark { 192*c8afe684SRob Clark struct hdmi_phy_8x60 *phy_8x60; 193*c8afe684SRob Clark struct hdmi_phy *phy = NULL; 194*c8afe684SRob Clark int ret; 195*c8afe684SRob Clark 196*c8afe684SRob Clark phy_8x60 = kzalloc(sizeof(*phy_8x60), GFP_KERNEL); 197*c8afe684SRob Clark if (!phy_8x60) { 198*c8afe684SRob Clark ret = -ENOMEM; 199*c8afe684SRob Clark goto fail; 200*c8afe684SRob Clark } 201*c8afe684SRob Clark 202*c8afe684SRob Clark phy = &phy_8x60->base; 203*c8afe684SRob Clark 204*c8afe684SRob Clark phy->funcs = &hdmi_phy_8x60_funcs; 205*c8afe684SRob Clark 206*c8afe684SRob Clark phy_8x60->hdmi = hdmi; 207*c8afe684SRob Clark 208*c8afe684SRob Clark return phy; 209*c8afe684SRob Clark 210*c8afe684SRob Clark fail: 211*c8afe684SRob Clark if (phy) 212*c8afe684SRob Clark hdmi_phy_8x60_destroy(phy); 213*c8afe684SRob Clark return ERR_PTR(ret); 214*c8afe684SRob Clark } 215