^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/nvmem-consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/rockchip/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* REG: 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PRE_PLL_REFCLK_SEL_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PRE_PLL_REFCLK_SEL_PCLK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define PRE_PLL_REFCLK_SEL_OSCCLK 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* REG: 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define BYPASS_RXSENSE_EN_MASK BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BYPASS_RXSENSE_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define BYPASS_PWRON_EN_MASK BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define BYPASS_PWRON_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define BYPASS_PLLPD_EN_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define BYPASS_PLLPD_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* REG: 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define BYPASS_PDATA_EN_MASK BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define BYPASS_PDATA_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PDATAEN_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define PDATAEN_DISABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define PDATAEN_ENABLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* REG: 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define BYPASS_AUTO_TERM_RES_CAL BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define AUDO_TERM_RES_CAL_SPEED_14_8(x) UPDATE(x, 6, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* REG: 0x04 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define AUDO_TERM_RES_CAL_SPEED_7_0(x) UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* REG: 0xaa */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define POST_PLL_CTRL_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define POST_PLL_CTRL_MANUAL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* REG: 0xe0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define POST_PLL_POWER_MASK BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define POST_PLL_POWER_DOWN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define POST_PLL_POWER_UP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define PRE_PLL_POWER_MASK BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define PRE_PLL_POWER_DOWN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define PRE_PLL_POWER_UP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define RXSENSE_CLK_CH_MASK BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define RXSENSE_CLK_CH_ENABLE BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define RXSENSE_DATA_CH2_MASK BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define RXSENSE_DATA_CH2_ENABLE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define RXSENSE_DATA_CH1_MASK BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define RXSENSE_DATA_CH1_ENABLE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define RXSENSE_DATA_CH0_MASK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define RXSENSE_DATA_CH0_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* REG: 0xe1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define BANDGAP_MASK BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define BANDGAP_ENABLE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define BANDGAP_DISABLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define TMDS_DRIVER_MASK GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define TMDS_DRIVER_ENABLE UPDATE(0xf, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define TMDS_DRIVER_DISABLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* REG: 0xe2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PRE_PLL_FB_DIV_8_MASK BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define PRE_PLL_FB_DIV_8_SHIFT 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define PRE_PLL_FB_DIV_8(x) UPDATE(x, 7, 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define PCLK_VCO_DIV_5_MASK BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define PCLK_VCO_DIV_5_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define PRE_PLL_PRE_DIV_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* REG: 0xe3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* REG: 0xe4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define PRE_PLL_PCLK_DIV_B_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define PRE_PLL_PCLK_DIV_A_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* REG: 0xe5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define PRE_PLL_PCLK_DIV_C_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define PRE_PLL_PCLK_DIV_D_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* REG: 0xe6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* REG: 0xe8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define PRE_PLL_LOCK_STATUS BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* REG: 0xe9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define POST_PLL_POST_DIV_EN_MASK GENMASK(7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define POST_PLL_POST_DIV_DISABLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define POST_PLL_PRE_DIV_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* REG: 0xea */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* REG: 0xeb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define POST_PLL_FB_DIV_8_MASK BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define POST_PLL_FB_DIV_8(x) UPDATE(x, 7, 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define POST_PLL_POST_DIV_MASK GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define POST_PLL_POST_DIV(x) UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define POST_PLL_LOCK_STATUS BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* REG: 0xee */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define TMDS_CH_TA_MASK GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define TMDS_CH_TA_ENABLE UPDATE(0xf, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define TMDS_CH_TA_DISABLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* REG: 0xef */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* REG: 0xf0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* REG: 0xf1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* REG: 0xf2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) enum inno_hdmi_phy_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) INNO_HDMI_PHY_RK3228,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) INNO_HDMI_PHY_RK3328
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct phy_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u8 regs[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct inno_hdmi_phy_drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct inno_hdmi_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct clk *sysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* platform data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct inno_hdmi_phy_drv_data *plat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* efuse flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bool efuse_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* clk provider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct clk *pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct pre_pll_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned long pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u16 fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u8 tmds_div_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u8 tmds_div_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u8 tmds_div_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u8 pclk_div_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 pclk_div_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 pclk_div_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u8 pclk_div_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u8 vco_div_5_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u32 fracdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct post_pll_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u16 fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u8 postdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct inno_hdmi_phy_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) void (*init)(struct inno_hdmi_phy *inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int (*power_on)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) const struct phy_config *phy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) void (*power_off)(struct inno_hdmi_phy *inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int (*pre_pll_update)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) const struct pre_pll_config *cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) unsigned long (*recalc_rate)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned long parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct inno_hdmi_phy_drv_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) enum inno_hdmi_phy_type dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) const struct inno_hdmi_phy_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) const struct phy_config *phy_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * If only using integer freq div can't get frequency we want, frac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * freq div is needed. For example, pclk 88.75 Mhz and tmdsclk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * 110.9375 Mhz must use frac div 0xF00000. The actual frequency is different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * from the target frequency. Such as the tmds clock 110.9375 Mhz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * the actual tmds clock we get is 110.93719 Mhz. It is important
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * to note that RK322X platforms do not support frac div.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static const struct pre_pll_config pre_pll_cfg_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { 40000000, 50000000, 1, 100, 2, 2, 2, 1, 0, 0, 15, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { 65000000, 65000000, 1, 130, 2, 2, 2, 1, 0, 0, 12, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 0, 0, 10, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { 71000000, 71000000, 3, 284, 0, 3, 3, 1, 0, 0, 8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 10, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 0, 0, 8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 0, 0, 8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { 88750000, 110937500, 1, 110, 2, 1, 1, 1, 1, 0, 5, 0, 0xF00000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {108000000, 108000000, 1, 90, 3, 0, 0, 1, 0, 0, 5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {108000000, 135000000, 1, 90, 0, 2, 2, 1, 0, 0, 5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {119000000, 119000000, 1, 119, 2, 1, 1, 1, 0, 0, 6, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {119000000, 148750000, 1, 99, 0, 2, 2, 1, 0, 0, 5, 0, 0x2AAAAA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {162000000, 162000000, 1, 108, 0, 2, 2, 1, 0, 0, 4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {162000000, 202500000, 1, 135, 0, 2, 2, 1, 0, 0, 5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { ~0UL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static const struct post_pll_config post_pll_cfg_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {33750000, 1, 40, 8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {33750000, 1, 80, 8, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {33750000, 1, 10, 2, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {74250000, 1, 40, 8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {74250000, 18, 80, 8, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {148500000, 2, 40, 4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {297000000, 4, 40, 2, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {594000000, 8, 40, 1, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { ~0UL, 0, 0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static const struct phy_config rk3228_phy_cfg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { 165000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 340000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 594000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ~0UL, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static const struct phy_config rk3328_phy_cfg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { 165000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 0x00, 0xac, 0xcc, 0xcc, 0xcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 340000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 0x3f, 0xac, 0xcc, 0xcd, 0xdd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 594000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 0x00, 0xac, 0xcc, 0xcc, 0xcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ~0UL, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static inline struct inno_hdmi_phy *to_inno_hdmi_phy(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return container_of(hw, struct inno_hdmi_phy, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) regmap_write(inno->regmap, reg * 4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) regmap_read(inno->regmap, reg * 4, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) regmap_update_bits(inno->regmap, reg * 4, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int bus_width = phy_get_bus_width(inno->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u32 tmdsclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) switch (bus_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) tmdsclk = (u32)rate / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) tmdsclk = (u32)rate * 5 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) tmdsclk = (u32)rate * 3 / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) tmdsclk = (u32)rate * 5 / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case 12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) tmdsclk = (u32)rate * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) tmdsclk = (u32)rate * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) tmdsclk = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return tmdsclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static irqreturn_t inno_hdmi_phy_hardirq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct inno_hdmi_phy *inno = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int intr_stat1, intr_stat2, intr_stat3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) intr_stat1 = inno_read(inno, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) intr_stat2 = inno_read(inno, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) intr_stat3 = inno_read(inno, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (intr_stat1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) inno_write(inno, 0x04, intr_stat1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (intr_stat2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) inno_write(inno, 0x06, intr_stat2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (intr_stat3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) inno_write(inno, 0x08, intr_stat3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (intr_stat1 || intr_stat2 || intr_stat3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static irqreturn_t inno_hdmi_phy_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct inno_hdmi_phy *inno = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* set pdata_en to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) inno_update_bits(inno, 0x02, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* set pdata_en to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) inno_update_bits(inno, 0x02, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int inno_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) unsigned long parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int inno_hdmi_phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) const struct post_pll_config *cfg = post_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u32 chipversion = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (inno->phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) phy_cfg = inno->phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (!tmdsclock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_err(inno->dev, "TMDS clock is zero!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3328 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) rockchip_get_cpu_version())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) chipversion = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) tmdsclock <= 33750000 && inno->efuse_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) chipversion = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) for (; cfg->tmdsclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (tmdsclock <= cfg->tmdsclock &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cfg->version & chipversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (tmdsclock <= phy_cfg->tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (cfg->tmdsclock == ~0UL || phy_cfg->tmdsclock == ~0UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_dbg(inno->dev, "Inno HDMI PHY Power On\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) inno_hdmi_phy_clk_set_rate(&inno->hw, inno->pixclock, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (inno->plat_data->ops->power_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return inno->plat_data->ops->power_on(inno, cfg, phy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int inno_hdmi_phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (inno->plat_data->ops->power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) inno->plat_data->ops->power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) inno->tmdsclock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static const struct phy_ops inno_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .power_on = inno_hdmi_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .power_off = inno_hdmi_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int inno_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) status = inno_read(inno, 0xe0) & PRE_PLL_POWER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) status = inno_read(inno, 0xa0) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return status ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int inno_hdmi_phy_clk_prepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) inno_update_bits(inno, 0xa0, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static void inno_hdmi_phy_clk_unprepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) inno_update_bits(inno, 0xa0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static unsigned long inno_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (inno->plat_data->ops->recalc_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return inno->plat_data->ops->recalc_rate(inno, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return inno->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static long inno_hdmi_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) const struct pre_pll_config *cfg = pre_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) for (; cfg->pixclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (cfg->pixclock == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* XXX: Limit pixel clock under 600MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (cfg->pixclock > 600000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * If there is no dts phy cfg table, use default phy cfg table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * The tmds clock maximum is 594MHz. So there is no need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * whether tmds clock is out of range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!inno->phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return cfg->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* Check if tmds clock is out of dts phy config's range. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) for (i = 0; inno->phy_cfg[i].tmdsclock != ~0UL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (inno->phy_cfg[i].tmdsclock >= tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (inno->phy_cfg[i].tmdsclock == ~0UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return cfg->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int inno_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) const struct pre_pll_config *cfg = pre_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) dev_dbg(inno->dev, "%s rate %lu tmdsclk %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) __func__, rate, tmdsclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (inno->tmdsclock == tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) for (; cfg->pixclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (cfg->pixclock == ~0UL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dev_err(inno->dev, "unsupported rate %lu\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (inno->plat_data->ops->pre_pll_update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) inno->plat_data->ops->pre_pll_update(inno, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) inno->pixclock = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) inno->tmdsclock = tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static const struct clk_ops inno_hdmi_phy_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) .prepare = inno_hdmi_phy_clk_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) .unprepare = inno_hdmi_phy_clk_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) .is_prepared = inno_hdmi_phy_clk_is_prepared,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) .recalc_rate = inno_hdmi_phy_clk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .round_rate = inno_hdmi_phy_clk_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) .set_rate = inno_hdmi_phy_clk_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct device *dev = inno->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct clk_init_data init = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct clk *refclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) refclk = devm_clk_get(dev, "refclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (IS_ERR(refclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) dev_err(dev, "failed to get ref clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return PTR_ERR(refclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) parent_name = __clk_get_name(refclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) init.name = "pin_hd20_pclk";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) init.ops = &inno_hdmi_phy_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* optional override of the clock name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) of_property_read_string(np, "clock-output-names", &init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) inno->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) inno->pclk = devm_clk_register(dev, &inno->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (IS_ERR(inno->pclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) ret = PTR_ERR(inno->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) dev_err(dev, "failed to register clock: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ret = of_clk_add_provider(np, of_clk_src_simple_get, inno->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) dev_err(dev, "failed to register OF clock provider: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) inno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) const struct phy_config *phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) int pll_tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* pdata_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* Power down Post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* Post-PLL update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) m = POST_PLL_PRE_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) v = POST_PLL_PRE_DIV(cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) m = POST_PLL_FB_DIV_8_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) v = POST_PLL_FB_DIV_8(cfg->fbdiv >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) inno_update_bits(inno, 0xeb, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) inno_write(inno, 0xea, POST_PLL_FB_DIV_7_0(cfg->fbdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (cfg->postdiv == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* Disable Post-PLL post divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) m = POST_PLL_POST_DIV_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) v = POST_PLL_POST_DIV_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /* Enable Post-PLL post divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) m = POST_PLL_POST_DIV_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) v = POST_PLL_POST_DIV_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) m = POST_PLL_POST_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) v = POST_PLL_POST_DIV(cfg->postdiv / 2 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) inno_update_bits(inno, 0xeb, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) for (v = 0; v < 4; v++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) inno_write(inno, 0xef + v, phy_cfg->regs[v]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* Power up Post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* BandGap enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* TMDS driver enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* Wait for post PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) pll_tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) while (!(inno_read(inno, 0xeb) & POST_PLL_LOCK_STATUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) dev_err(inno->dev, "Post-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) pll_tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) usleep_range(100, 110);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (cfg->tmdsclock > 340000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* pdata_en enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* TMDS driver Disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* BandGap Disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /* Post-PLL power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static void inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct nvmem_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) unsigned char *efuse_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * Use phy internal register control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * rxsense/poweron/pllpd/pdataen signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) m = BYPASS_RXSENSE_EN_MASK | BYPASS_PWRON_EN_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) BYPASS_PLLPD_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) v = BYPASS_RXSENSE_EN | BYPASS_PWRON_EN | BYPASS_PLLPD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) inno_update_bits(inno, 0x01, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) inno_update_bits(inno, 0x02, BYPASS_PDATA_EN_MASK, BYPASS_PDATA_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * reg0xe9 default value is 0xe4, reg0xea is 0x50.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * if phy had been set in uboot, one of them will be different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if ((inno_read(inno, 0xe9) != 0xe4 || inno_read(inno, 0xea) != 0x50)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) dev_info(inno->dev, "phy had been powered up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) inno->phy->power_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) inno_hdmi_phy_rk3228_power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* manual power down post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) inno_update_bits(inno, 0xaa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) POST_PLL_CTRL_MASK, POST_PLL_CTRL_MANUAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) cell = nvmem_cell_get(inno->dev, "hdmi_phy_flag");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (IS_ERR(cell)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev_err(inno->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) "failed to get id cell: %ld\n", PTR_ERR(cell));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) efuse_buf = nvmem_cell_read(cell, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) nvmem_cell_put(cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) inno->efuse_flag = efuse_buf[0] ? true : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) kfree(efuse_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) inno_hdmi_phy_rk3228_pre_pll_update(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) const struct pre_pll_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) int pll_tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Power down PRE-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) m = PRE_PLL_FB_DIV_8_MASK | PCLK_VCO_DIV_5_MASK | PRE_PLL_PRE_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) v = PRE_PLL_FB_DIV_8(cfg->fbdiv >> 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) PCLK_VCO_DIV_5(cfg->vco_div_5_en) | PRE_PLL_PRE_DIV(cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) inno_update_bits(inno, 0xe2, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) inno_write(inno, 0xe3, PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) m = PRE_PLL_PCLK_DIV_B_MASK | PRE_PLL_PCLK_DIV_A_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) v = PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) inno_update_bits(inno, 0xe4, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) m = PRE_PLL_PCLK_DIV_C_MASK | PRE_PLL_PCLK_DIV_D_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) v = PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) inno_update_bits(inno, 0xe5, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) m = PRE_PLL_TMDSCLK_DIV_C_MASK | PRE_PLL_TMDSCLK_DIV_A_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) PRE_PLL_TMDSCLK_DIV_B_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) v = PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) inno_update_bits(inno, 0xe6, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /* Power up PRE-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Wait for Pre-PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) pll_tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) while (!(inno_read(inno, 0xe8) & PRE_PLL_LOCK_STATUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) dev_err(inno->dev, "Pre-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) pll_tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) usleep_range(100, 110);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) const struct phy_config *phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) u64 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /* set pdata_en to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) inno_update_bits(inno, 0x02, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* Power off post PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) inno_update_bits(inno, 0xaa, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) val = cfg->fbdiv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) inno_write(inno, 0xac, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (cfg->postdiv == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) inno_write(inno, 0xaa, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) val = (cfg->fbdiv >> 8) | cfg->prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) inno_write(inno, 0xab, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) val = (cfg->postdiv / 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) inno_write(inno, 0xad, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) val = (cfg->fbdiv >> 8) | cfg->prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) inno_write(inno, 0xab, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) inno_write(inno, 0xaa, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) for (val = 0; val < 14; val++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) inno_write(inno, 0xb5 + val, phy_cfg->regs[val]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* bit[7:6] of reg c8/c9/ca/c8 is ESD detect threshold:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * 00 - 340mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * 01 - 280mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * 10 - 260mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * 11 - 240mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * default is 240mV, now we set it to 340mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) inno_write(inno, 0xc8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) inno_write(inno, 0xc9, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) inno_write(inno, 0xca, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) inno_write(inno, 0xcb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (phy_cfg->tmdsclock > 340000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /* Set termination resistor to 100ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) val = clk_get_rate(inno->sysclk) / 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) inno_write(inno, 0xc5, ((val >> 8) & 0xff) | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) inno_write(inno, 0xc6, val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) inno_write(inno, 0xc7, 3 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) inno_write(inno, 0xc5, ((val >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) inno_write(inno, 0xc5, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* clk termination resistor is 50ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (phy_cfg->tmdsclock > 165000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) inno_write(inno, 0xc8, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* data termination resistor is 150ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) inno_write(inno, 0xc9, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) inno_write(inno, 0xca, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) inno_write(inno, 0xcb, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /* set TMDS sync detection counter length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) temp = 47520000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) do_div(temp, inno->tmdsclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) inno_write(inno, 0xd8, (temp >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) inno_write(inno, 0xd9, temp & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Power up post PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) inno_update_bits(inno, 0xaa, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* Power up tmds driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) inno_update_bits(inno, 0xb0, 4, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) inno_write(inno, 0xb2, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /* Wait for post PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) for (val = 0; val < 5; val++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (inno_read(inno, 0xaf) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (!(inno_read(inno, 0xaf) & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) dev_err(inno->dev, "HDMI PHY Post PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (phy_cfg->tmdsclock > 340000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* set pdata_en to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) inno_update_bits(inno, 0x02, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* Enable PHY IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) inno_write(inno, 0x05, 0x22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) inno_write(inno, 0x07, 0x22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /* Power off driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) inno_write(inno, 0xb2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* Power off band gap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) inno_update_bits(inno, 0xb0, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* Power off post pll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) inno_update_bits(inno, 0xaa, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) /* Disable PHY IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) inno_write(inno, 0x05, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) inno_write(inno, 0x07, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * Use phy internal register control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * rxsense/poweron/pllpd/pdataen signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) inno_write(inno, 0x01, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) inno_write(inno, 0x02, 0x91);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * reg0xc8 default value is 0xc0, if phy had been set in uboot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * the value of bit[7:6] will be zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if ((inno_read(inno, 0xc8) & 0xc0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) dev_info(inno->dev, "phy had been powered up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) inno->phy->power_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /* manual power down post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) inno_hdmi_phy_rk3328_power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) inno_hdmi_phy_rk3328_pre_pll_update(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) const struct pre_pll_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /* Power off PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) inno_update_bits(inno, 0xa0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* Configure pre-pll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) inno_write(inno, 0xa1, cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (cfg->fracdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) inno_write(inno, 0xa2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) inno_write(inno, 0xa3, cfg->fbdiv & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) val = (cfg->pclk_div_a & 0x1f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) ((cfg->pclk_div_b & 3) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) inno_write(inno, 0xa5, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) val = (cfg->pclk_div_d & 0x1f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ((cfg->pclk_div_c & 3) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) inno_write(inno, 0xa6, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) val = ((cfg->tmds_div_a & 3) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ((cfg->tmds_div_b & 3) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) (cfg->tmds_div_c & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) inno_write(inno, 0xa4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (cfg->fracdiv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) val = cfg->fracdiv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) inno_write(inno, 0xd3, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) val = (cfg->fracdiv >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) inno_write(inno, 0xd2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) val = (cfg->fracdiv >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) inno_write(inno, 0xd1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) inno_write(inno, 0xd3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) inno_write(inno, 0xd2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) inno_write(inno, 0xd1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* Power up PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) inno_update_bits(inno, 0xa0, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* Wait for PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) for (val = 0; val < 5; val++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (inno_read(inno, 0xa9) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (val == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) dev_err(inno->dev, "Pre-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) inno_hdmi_rk3328_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) unsigned long frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) u8 nd, no_a, no_b, no_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) u16 nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) u64 vco = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) nd = inno_read(inno, 0xa1) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) vco *= nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if ((inno_read(inno, 0xa2) & 0x30) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) frac = inno_read(inno, 0xd3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) (inno_read(inno, 0xd2) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) (inno_read(inno, 0xd1) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (inno_read(inno, 0xa0) & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) do_div(vco, nd * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) no_a = inno_read(inno, 0xa5) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) no_d = inno_read(inno, 0xa6) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (no_a == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) do_div(vco, nd * no_b * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) do_div(vco, nd * no_a * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) frac = vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) inno->pixclock = DIV_ROUND_CLOSEST(frac, 1000) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) inno_hdmi_rk3228_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) u8 nd, no_a, no_b, no_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) u16 nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) u64 vco = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) nd = inno_read(inno, 0xe2) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) nf = ((inno_read(inno, 0xe2) & 0x80) << 1) | inno_read(inno, 0xe3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) vco *= nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if ((inno_read(inno, 0xe2) >> 5) & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) do_div(vco, nd * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) no_a = inno_read(inno, 0xe4) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!no_a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) no_a = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) no_b = ((inno_read(inno, 0xe4) >> 5) & 0x3) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) no_d = inno_read(inno, 0xe5) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (no_a == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) do_div(vco, nd * no_b * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) do_div(vco, nd * no_a * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) inno->pixclock = vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return inno->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) .init = inno_hdmi_phy_rk3228_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) .power_on = inno_hdmi_phy_rk3228_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) .power_off = inno_hdmi_phy_rk3228_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) .pre_pll_update = inno_hdmi_phy_rk3228_pre_pll_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) .recalc_rate = inno_hdmi_rk3228_phy_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static const struct inno_hdmi_phy_ops rk3328_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .init = inno_hdmi_phy_rk3328_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .power_on = inno_hdmi_phy_rk3328_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .power_off = inno_hdmi_phy_rk3328_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) .pre_pll_update = inno_hdmi_phy_rk3328_pre_pll_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) .recalc_rate = inno_hdmi_rk3328_phy_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) .dev_type = INNO_HDMI_PHY_RK3228,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) .ops = &rk3228_hdmi_phy_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) .phy_cfg_table = rk3228_phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static const struct inno_hdmi_phy_drv_data rk3328_hdmi_phy_drv_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .dev_type = INNO_HDMI_PHY_RK3328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .ops = &rk3328_hdmi_phy_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .phy_cfg_table = rk3328_phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static const struct of_device_id inno_hdmi_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) { .compatible = "rockchip,rk3228-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) .data = &rk3228_hdmi_phy_drv_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) { .compatible = "rockchip,rk3328-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) .data = &rk3328_hdmi_phy_drv_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static const struct regmap_config inno_hdmi_phy_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .max_register = 0x400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int inno_hdmi_update_phy_table(struct inno_hdmi_phy *inno, u32 *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct phy_config *phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int phy_table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) for (i = 0; i < phy_table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) phy_cfg[i].tmdsclock =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) (unsigned long)config[i * 15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) for (j = 0; j < 14; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) phy_cfg[i].regs[j] = (u8)config[i * 15 + 1 + j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * The last set of phy cfg is used to indicate whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * there is no more phy cfg data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) phy_cfg[i].tmdsclock = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) for (j = 0; j < 14; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) phy_cfg[i].regs[j] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) #define PHY_TAB_LEN 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int inno_hdmi_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct inno_hdmi_phy *inno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) u32 *phy_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) int ret, val, phy_table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (!inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) inno->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) match = of_match_node(inno_hdmi_phy_of_match, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) inno->plat_data = (struct inno_hdmi_phy_drv_data *)match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (!inno->plat_data || !inno->plat_data->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) regs = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (IS_ERR(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) inno->sysclk = devm_clk_get(inno->dev, "sysclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (IS_ERR(inno->sysclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) ret = PTR_ERR(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dev_err(inno->dev, "Unable to get inno phy sysclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) ret = clk_prepare_enable(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) dev_err(inno->dev, "Cannot enable inno phy sysclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) inno->regmap = devm_regmap_init_mmio(dev, regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) &inno_hdmi_phy_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (IS_ERR(inno->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ret = PTR_ERR(inno->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) dev_err(dev, "failed to init regmap: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) inno->phy = devm_phy_create(dev, NULL, &inno_hdmi_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (IS_ERR(inno->phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dev_err(dev, "failed to create HDMI PHY\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) ret = PTR_ERR(inno->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (of_get_property(np, "rockchip,phy-table", &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (val % PHY_TAB_LEN || !val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) dev_err(dev, "Invalid phy cfg table format!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) phy_config = kmalloc(val, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (!phy_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) dev_err(dev, "kmalloc phy table failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) phy_table_size = val / PHY_TAB_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /* Effective phy cfg data and the end of phy cfg table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) inno->phy_cfg = devm_kzalloc(dev, val + PHY_TAB_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (!inno->phy_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) of_property_read_u32_array(np, "rockchip,phy-table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) phy_config, val / sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) ret = inno_hdmi_update_phy_table(inno, phy_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) inno->phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) phy_table_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) dev_dbg(dev, "use default hdmi phy table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) phy_set_drvdata(inno->phy, inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) phy_set_bus_width(inno->phy, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) dev_err(dev, "failed to register PHY provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) ret = PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (inno->plat_data->ops->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) inno->plat_data->ops->init(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) ret = inno_hdmi_phy_clk_register(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) inno->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (inno->irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) ret = devm_request_threaded_irq(inno->dev, inno->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) inno_hdmi_phy_hardirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) inno_hdmi_phy_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) dev_name(inno->dev), inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) platform_set_drvdata(pdev, inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) of_clk_del_provider(pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) err_regsmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) clk_disable_unprepare(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static int inno_hdmi_phy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct inno_hdmi_phy *inno = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) of_clk_del_provider(pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) clk_disable_unprepare(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) static struct platform_driver inno_hdmi_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) .probe = inno_hdmi_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) .remove = inno_hdmi_phy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) .name = "inno-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) .of_match_table = of_match_ptr(inno_hdmi_phy_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) module_platform_driver(inno_hdmi_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) MODULE_DESCRIPTION("Innosilion HDMI 2.0 Transmitter PHY Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) MODULE_LICENSE("GPL v2");