xref: /aosp_15_r20/external/coreboot/src/drivers/i2c/rtd2132/rtd2132.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <delay.h>
5 #include <device/device.h>
6 #include <device/smbus.h>
7 #include <device/pci.h>
8 #include "chip.h"
9 
10 /* Chip commands */
11 #define RTD2132_COMMAND			0x01
12 #define RTD2132_DATA			0x00
13 #define RTD2132_FIRMWARE		0x80
14 #define  RTD2132_FIRMWARE_START		0x00
15 #define  RTD2132_FIRMWARE_STOP		0x01
16 
17 /* Panel Power Sequence Timing Registers. */
18 #define RTD2132_COMMAND_PWR_SEQ_T1	0x32 /* 1ms units. */
19 #define RTD2132_COMMAND_PWR_SEQ_T2	0x33 /* 4ms units. */
20 #define RTD2132_COMMAND_PWR_SEQ_T3	0x34 /* 1ms units. */
21 #define RTD2132_COMMAND_PWR_SEQ_T4	0x35 /* 1ms units. */
22 #define RTD2132_COMMAND_PWR_SEQ_T5	0x36 /* 4ms units. */
23 #define RTD2132_COMMAND_PWR_SEQ_T6	0x37 /* 1ms units. */
24 #define RTD2132_COMMAND_PWR_SEQ_T7	0x38 /* 4ms units. */
25 
26 /* Spread spectrum configuration */
27 #define RTD2132_COMMAND_SSCG_CONFIG_0	0x39
28 #define  RTD2132_SSCG_ENABLE		0xa0
29 #define  RTD2132_SSCG_DISABLE		0x20
30 #define RTD2132_COMMAND_SSCG_CONFIG_1	0x3a
31 #define  RTD2132_SSCG_CONFIG_DISABLED	0x01	/* DISABLED */
32 #define  RTD2132_SSCG_CONFIG_0_5	0x07	/* 0.5% */
33 #define  RTD2132_SSCG_CONFIG_1_0	0x0f	/* 1.0% */
34 #define  RTD2132_SSCG_CONFIG_1_5	0x16	/* 1.5% */
35 
36 /* LVDS Swap */
37 #define RTD2132_COMMAND_LVDS_SWAP	0x3b
38 #define  RTD2132_LVDS_SWAP_DUAL		0x80
39 #define  RTD2132_LVDS_SWAP_NORMAL	0x04
40 #define  RTD2132_LVDS_SWAP_MIRROR	0x14
41 #define  RTD2132_LVDS_SWAP_P_N		0x24
42 #define  RTD2132_LVDS_SWAP_MIRROR_P_N	0x34
43 #define  RTD2132_LVDS_SWAP_R_L		0x0c
44 
45 /* Configuration values from devicetree */
46 #define RTD2132_SSCG_PERCENT_0_0	0x00	/* DISABLED */
47 #define RTD2132_SSCG_PERCENT_0_5	0x05	/* 0.5% */
48 #define RTD2132_SSCG_PERCENT_1_0	0x10	/* 1.0% */
49 #define RTD2132_SSCG_PERCENT_1_5	0x15	/* 1.5% */
50 
51 #define  RTD2132_LVDS_SWAP_CFG_DUAL		0x80
52 #define  RTD2132_LVDS_SWAP_CFG_NORMAL		0x00
53 #define  RTD2132_LVDS_SWAP_CFG_MIRROR		0x01
54 #define  RTD2132_LVDS_SWAP_CFG_P_N		0x02
55 #define  RTD2132_LVDS_SWAP_CFG_MIRROR_P_N	0x03
56 #define  RTD2132_LVDS_SWAP_CFG_R_L		0x04
57 
58 #define RTD2132_DEBUG_REG 0
59 
rtd2132_write_reg(struct device * dev,u8 reg,u8 value)60 static void rtd2132_write_reg(struct device *dev, u8 reg, u8 value)
61 {
62 	if (RTD2132_DEBUG_REG)
63 		printk(BIOS_DEBUG, "RTD2132 0x%02x <- 0x%02x\n", reg, value);
64 	smbus_write_byte(dev, RTD2132_COMMAND, reg);
65 	smbus_write_byte(dev, RTD2132_DATA, value);
66 }
67 
rtd2132_firmware_stop(struct device * dev)68 static void rtd2132_firmware_stop(struct device *dev)
69 {
70 	smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_STOP);
71 	mdelay(60);
72 }
73 
rtd2132_firmware_start(struct device * dev)74 static void rtd2132_firmware_start(struct device *dev)
75 {
76 	smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_START);
77 }
78 
rtd2132_pps(struct device * dev,struct drivers_i2c_rtd2132_config * cfg)79 static void rtd2132_pps(struct device *dev, struct drivers_i2c_rtd2132_config *cfg)
80 {
81 	/* T2, T5, and T7 register values are in units of 4ms. */
82 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T1, cfg->t1);
83 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T2, cfg->t2 / 4);
84 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T3, cfg->t3);
85 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T4, cfg->t4);
86 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T5, cfg->t5 / 4);
87 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T6, cfg->t6);
88 	rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T7, cfg->t7 / 4);
89 }
90 
rtd2132_sscg_enable(struct device * dev,u8 sscg_percent)91 static void rtd2132_sscg_enable(struct device *dev, u8 sscg_percent)
92 {
93 	/* SSCG_Config_0 */
94 	rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0,
95 	                  RTD2132_SSCG_ENABLE);
96 
97 	/* SSCG_Config_1 */
98 	rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1, sscg_percent);
99 }
100 
rtd2132_sscg_disable(struct device * dev)101 static void rtd2132_sscg_disable(struct device *dev)
102 {
103 	/* SSCG_Config_0 */
104 	rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0,
105 	                  RTD2132_SSCG_DISABLE);
106 
107 	/* SSCG_Config_1 */
108 	rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1,
109 	                  RTD2132_SSCG_CONFIG_DISABLED);
110 }
111 
rtd2132_sscg(struct device * dev,struct drivers_i2c_rtd2132_config * cfg)112 static void rtd2132_sscg(struct device *dev, struct drivers_i2c_rtd2132_config *cfg)
113 {
114 	switch (cfg->sscg_percent) {
115 	case RTD2132_SSCG_PERCENT_0_0:
116 		printk(BIOS_INFO, "RTD2132: Disable Spread Spectrum\n");
117 		rtd2132_sscg_disable(dev);
118 		break;
119 	case RTD2132_SSCG_PERCENT_0_5:
120 		printk(BIOS_INFO, "RTD2132: Enable 0.5%% Spread Spectrum\n");
121 		rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_0_5);
122 		break;
123 	case RTD2132_SSCG_PERCENT_1_0:
124 		printk(BIOS_INFO, "RTD2132: Enable 1.0%% Spread Spectrum\n");
125 		rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_1_0);
126 		break;
127 	case RTD2132_SSCG_PERCENT_1_5:
128 		printk(BIOS_INFO, "RTD2132: Enable 1.5%% Spread Spectrum\n");
129 		rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_1_5);
130 		break;
131 	default:
132 		printk(BIOS_ERR, "RTD2132: Invalid Spread Spectrum 0x%02x\n",
133 		       cfg->sscg_percent);
134 	}
135 }
136 
rtd2132_lvds_swap(struct device * dev,struct drivers_i2c_rtd2132_config * cfg)137 static void rtd2132_lvds_swap(struct device *dev,
138 			      struct drivers_i2c_rtd2132_config *cfg)
139 {
140 	u8 swap_value = RTD2132_LVDS_SWAP_NORMAL;
141 
142 	switch (cfg->lvds_swap & ~RTD2132_LVDS_SWAP_CFG_DUAL) {
143 	case RTD2132_LVDS_SWAP_CFG_NORMAL:
144 		swap_value = RTD2132_LVDS_SWAP_NORMAL;
145 		break;
146 	case RTD2132_LVDS_SWAP_CFG_MIRROR:
147 		swap_value = RTD2132_LVDS_SWAP_MIRROR;
148 		break;
149 	case RTD2132_LVDS_SWAP_CFG_P_N:
150 		swap_value = RTD2132_LVDS_SWAP_P_N;
151 		break;
152 	case RTD2132_LVDS_SWAP_CFG_MIRROR_P_N:
153 		swap_value = RTD2132_LVDS_SWAP_MIRROR_P_N;
154 		break;
155 	case RTD2132_LVDS_SWAP_CFG_R_L:
156 		swap_value = RTD2132_LVDS_SWAP_R_L;
157 		break;
158 	default:
159 		printk(BIOS_ERR, "RTD2132: Invalid LVDS swap value 0x%02x\n",
160 		       cfg->lvds_swap);
161 	}
162 
163 	if (cfg->lvds_swap & RTD2132_LVDS_SWAP_CFG_DUAL)
164 		swap_value |= RTD2132_LVDS_SWAP_DUAL;
165 
166 	printk(BIOS_INFO, "RTD2132: LVDS Swap 0x%02x\n", swap_value);
167 
168 	rtd2132_write_reg(dev, RTD2132_COMMAND_LVDS_SWAP, swap_value);
169 }
170 
rtd2132_defaults(struct device * dev)171 static void rtd2132_defaults(struct device *dev)
172 {
173 	static const struct def_setting {
174 		u8 reg;
175 		u8 value;
176 	} def_settings[] = {
177 		{ 0x3c, 0x06 },
178 		{ 0x3d, 0x38 },
179 		{ 0x3e, 0x73 },
180 		{ 0x3f, 0x33 },
181 		{ 0x06, 0x90 },
182 		{ 0x06, 0xb0 },
183 		{ 0x06, 0x80 },
184 	};
185 	int i;
186 
187 	for (i = 0; i < ARRAY_SIZE(def_settings); i++)
188 		rtd2132_write_reg(dev, def_settings[i].reg,
189 		                  def_settings[i].value);
190 }
191 
rtd2132_setup(struct device * dev)192 static void rtd2132_setup(struct device *dev)
193 {
194 	struct drivers_i2c_rtd2132_config *config = dev->chip_info;
195 
196 	if (!config)
197 		return;
198 
199 	/* Stop running firmware */
200 	rtd2132_firmware_stop(dev);
201 
202 	/* Panel Power Sequencing Settings. */
203 	rtd2132_pps(dev, config);
204 
205 	/* Spread spectrum configuration */
206 	rtd2132_sscg(dev, config);
207 
208 	/* LVDS Swap Setting. */
209 	rtd2132_lvds_swap(dev, config);
210 
211 	/* Default settings. */
212 	rtd2132_defaults(dev);
213 
214 	/* Start firmware */
215 	rtd2132_firmware_start(dev);
216 }
217 
rtd2132_init(struct device * dev)218 static void rtd2132_init(struct device *dev)
219 {
220 	if (dev->enabled && dev->path.type == DEVICE_PATH_I2C &&
221 	    ops_smbus_bus(get_pbus_smbus(dev))) {
222 		rtd2132_setup(dev);
223 	}
224 }
225 
226 static struct device_operations rtd2132_operations = {
227 	.read_resources		= noop_read_resources,
228 	.set_resources		= noop_set_resources,
229 	.init			= rtd2132_init,
230 };
231 
enable_dev(struct device * dev)232 static void enable_dev(struct device *dev)
233 {
234 	dev->ops = &rtd2132_operations;
235 }
236 
237 struct chip_operations drivers_i2c_rtd2132_ops = {
238 	.name = "Realtek RTD2132 LVDS Bridge",
239 	.enable_dev = enable_dev,
240 };
241