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

media: i2c: ds90ub9xx: Set serializer temperature ramp

For continuous PLL lock, it is recommended to extend the temperature
ramp down range of the DS90UB953-Q1 serializer based on the device's
initial temperature [1].

The serializer's die temperature is reported only to the deserializer
through the sensor status registers, and for UB9702, it is recommended
to set the temperature ramp during the link setup sequence, i.e. before
we even probe the ub953 driver.

Add support to the deserializer driver to configure ub953's temperature
ramp.

[1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1

Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>

authored by

Jai Luthra and committed by
Hans Verkuil
a0574474 e2a3b695

+131 -1
+6 -1
drivers/media/i2c/ds90ub953.h
··· 71 71 72 72 /* Indirect register blocks */ 73 73 #define UB953_IND_TARGET_PAT_GEN 0x00 74 - #define UB953_IND_TARGET_FPD3_TX 0x01 74 + #define UB953_IND_TARGET_ANALOG 0x01 75 75 #define UB953_IND_TARGET_DIE_ID 0x02 76 76 77 77 #define UB953_IND_PGEN_CTL 0x01 ··· 91 91 #define UB953_IND_PGEN_VBP 0x0e 92 92 #define UB953_IND_PGEN_VFP 0x0f 93 93 #define UB953_IND_PGEN_COLOR(n) (0x10 + (n)) /* n <= 15 */ 94 + 95 + #define UB953_IND_ANA_TEMP_DYNAMIC_CFG 0x4b 96 + #define UB953_IND_ANA_TEMP_DYNAMIC_CFG_OV BIT(5) 97 + #define UB953_IND_ANA_TEMP_STATIC_CFG 0x4c 98 + #define UB953_IND_ANA_TEMP_STATIC_CFG_MASK GENMASK(6, 4) 94 99 95 100 /* UB971 Registers */ 96 101
+125
drivers/media/i2c/ds90ub960.c
··· 2017 2017 return ret; 2018 2018 } 2019 2019 2020 + static int ub960_rxport_serializer_read(struct ub960_rxport *rxport, u8 reg, 2021 + u8 *val, int *err) 2022 + { 2023 + struct ub960_data *priv = rxport->priv; 2024 + struct device *dev = &priv->client->dev; 2025 + union i2c_smbus_data data = { 0 }; 2026 + int ret; 2027 + 2028 + if (err && *err) 2029 + return *err; 2030 + 2031 + ret = i2c_smbus_xfer(priv->client->adapter, rxport->ser.alias, 2032 + priv->client->flags, I2C_SMBUS_READ, reg, 2033 + I2C_SMBUS_BYTE_DATA, &data); 2034 + if (ret) 2035 + dev_err(dev, 2036 + "rx%u: cannot read serializer register 0x%02x (%d)!\n", 2037 + rxport->nport, reg, ret); 2038 + else 2039 + *val = data.byte; 2040 + 2041 + if (ret && err) 2042 + *err = ret; 2043 + 2044 + return ret; 2045 + } 2046 + 2047 + static int ub960_serializer_temp_ramp(struct ub960_rxport *rxport) 2048 + { 2049 + struct ub960_data *priv = rxport->priv; 2050 + short temp_dynamic_offset[] = {-1, -1, 0, 0, 1, 1, 1, 3}; 2051 + u8 temp_dynamic_cfg; 2052 + u8 nport = rxport->nport; 2053 + u8 ser_temp_code; 2054 + int ret; 2055 + 2056 + /* Configure temp ramp only on UB953 */ 2057 + if (!fwnode_device_is_compatible(rxport->ser.fwnode, "ti,ds90ub953-q1")) 2058 + return 0; 2059 + 2060 + /* Read current serializer die temperature */ 2061 + ub960_rxport_read(priv, nport, UB960_RR_SENSOR_STS_2, &ser_temp_code, 2062 + &ret); 2063 + 2064 + /* Enable I2C passthrough on back channel */ 2065 + ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 2066 + UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, 2067 + UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, &ret); 2068 + 2069 + if (ret) 2070 + return ret; 2071 + 2072 + /* Select indirect page for analog regs on the serializer */ 2073 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_CTL, 2074 + UB953_IND_TARGET_ANALOG << 2, &ret); 2075 + 2076 + /* Set temperature ramp dynamic and static config */ 2077 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR, 2078 + UB953_IND_ANA_TEMP_DYNAMIC_CFG, &ret); 2079 + ub960_rxport_serializer_read(rxport, UB953_REG_IND_ACC_DATA, 2080 + &temp_dynamic_cfg, &ret); 2081 + 2082 + if (ret) 2083 + return ret; 2084 + 2085 + temp_dynamic_cfg |= UB953_IND_ANA_TEMP_DYNAMIC_CFG_OV; 2086 + temp_dynamic_cfg += temp_dynamic_offset[ser_temp_code]; 2087 + 2088 + /* Update temp static config */ 2089 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR, 2090 + UB953_IND_ANA_TEMP_STATIC_CFG, &ret); 2091 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_DATA, 2092 + UB953_IND_ANA_TEMP_STATIC_CFG_MASK, &ret); 2093 + 2094 + /* Update temperature ramp dynamic config */ 2095 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR, 2096 + UB953_IND_ANA_TEMP_DYNAMIC_CFG, &ret); 2097 + 2098 + /* Enable I2C auto ack on BC before we set dynamic cfg and reset */ 2099 + ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 2100 + UB960_RR_BCC_CONFIG_AUTO_ACK_ALL, 2101 + UB960_RR_BCC_CONFIG_AUTO_ACK_ALL, &ret); 2102 + 2103 + ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_DATA, 2104 + temp_dynamic_cfg, &ret); 2105 + 2106 + if (ret) 2107 + return ret; 2108 + 2109 + /* Soft reset to apply PLL updates */ 2110 + ub960_rxport_serializer_write(rxport, UB953_REG_RESET_CTL, 2111 + UB953_REG_RESET_CTL_DIGITAL_RESET_0, 2112 + &ret); 2113 + msleep(20); 2114 + 2115 + /* Disable I2C passthrough and auto-ack on BC */ 2116 + ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 2117 + UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH | 2118 + UB960_RR_BCC_CONFIG_AUTO_ACK_ALL, 2119 + 0x0, &ret); 2120 + 2121 + return ret; 2122 + } 2123 + 2020 2124 static int ub960_rxport_bc_ser_config(struct ub960_rxport *rxport) 2021 2125 { 2022 2126 struct ub960_data *priv = rxport->priv; ··· 2498 2394 ret = -EIO; 2499 2395 dev_err_probe(dev, ret, "Failed to lock all RX ports\n"); 2500 2396 return ret; 2397 + } 2398 + 2399 + /* Set temperature ramp on serializer */ 2400 + for_each_active_rxport(priv, it) { 2401 + ret = ub960_serializer_temp_ramp(it.rxport); 2402 + if (ret) 2403 + return ret; 2404 + 2405 + ub960_rxport_update_bits(priv, it.nport, UB960_RR_BCC_CONFIG, 2406 + UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, 2407 + UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, 2408 + &ret); 2409 + if (ret) 2410 + return ret; 2501 2411 } 2502 2412 2503 2413 /* ··· 3188 3070 3189 3071 /* Wait time for stable lock */ 3190 3072 fsleep(15000); 3073 + 3074 + /* Set temperature ramp on serializer */ 3075 + for_each_active_rxport(priv, it) { 3076 + ret = ub960_serializer_temp_ramp(it.rxport); 3077 + if (ret) 3078 + return ret; 3079 + } 3191 3080 3192 3081 for_each_active_rxport_fpd4(priv, it) { 3193 3082 ret = ub960_enable_dfe_lms_ub9702(priv, it.nport);