hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/rkx110_x120/pattern_gen.c
....@@ -8,6 +8,8 @@
88 #include <linux/debugfs.h>
99
1010 #include "rkx110_x120.h"
11
+#include "rkx110_x120_display.h"
12
+#include "hal/cru_api.h"
1113
1214 #define PATTERN_GEN_PATTERN_CTRL 0x0000
1315 #define PATTERN_START_PCLK BIT(31)
....@@ -29,11 +31,10 @@
2931 #define PATTERN_GEN_VALUE0 0x0014
3032 #define PATTERN_GEN_VALUE1 0x0018
3133
32
-static void pattern_gen_enable(struct pattern_gen *pattern_gen)
34
+static void pattern_gen_config(struct i2c_client *client, struct pattern_gen *pattern_gen,
35
+ struct videomode *vm)
3336 {
34
- struct i2c_client *client = pattern_gen->chip->client;
3537 struct rk_serdes *serdes = pattern_gen->chip->serdes;
36
- const struct videomode *vm = serdes->vm;
3738
3839 serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
3940 PATTERN_RECTANGLE_H | PATTERN_RECTANGLE_V,
....@@ -53,24 +54,311 @@
5354 serdes->i2c_write_reg(client, pattern_gen->base + PATTERN_GEN_PATERN_VH_CFG3,
5455 FIELD_PREP(PATTERN_HSA, vm->hsync_len));
5556
56
- serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
57
- PATTERN_START_PCLK,
58
- FIELD_PREP(PATTERN_START_PCLK, 1));
5957 serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
6058 BIT(pattern_gen->link_src_offset + 16) |
6159 BIT(pattern_gen->link_src_offset));
60
+}
61
+
62
+static void pattern_stop_stream(struct pattern_gen *pattern_gen)
63
+{
64
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
65
+
66
+ if (serdes->version != SERDES_V1)
67
+ return;
68
+
69
+ if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
70
+ return;
71
+
72
+ rk_serdes_display_video_start(serdes, pattern_gen->route, false);
73
+
74
+ if (!strcmp(pattern_gen->name, "lvds0")) {
75
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
76
+ RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
77
+ } else if (!strcmp(pattern_gen->name, "lvds1")) {
78
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
79
+ RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
80
+ } else if (!strcmp(pattern_gen->name, "dual-lvds")) {
81
+ rkx110_set_stream_source(serdes, RK_SERDES_RGB_RX, DEVICE_LOCAL);
82
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
83
+ RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
84
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
85
+ RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
86
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
87
+ RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
88
+ } else if (!strcmp(pattern_gen->name, "dsi0")) {
89
+ serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
90
+ 0x1400140);
91
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
92
+ RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
93
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
94
+ RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
95
+ rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, false);
96
+ } else if (!strcmp(pattern_gen->name, "dsi1")) {
97
+ serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
98
+ 0x2800280);
99
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
100
+ RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
101
+ hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
102
+ RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
103
+ rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, false);
104
+ }
105
+}
106
+
107
+static void pattern_start_stream(struct pattern_gen *pattern_gen, bool is_pattern_stream)
108
+{
109
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
110
+ struct videomode *vm = &pattern_gen->route->vm;
111
+ u32 delay_length;
112
+
113
+ if (serdes->version != SERDES_V1)
114
+ return;
115
+
116
+ if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
117
+ return;
118
+
119
+ if (!strcmp(pattern_gen->name, "lvds0")) {
120
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
121
+ RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
122
+ } else if (!strcmp(pattern_gen->name, "lvds1")) {
123
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
124
+ RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
125
+ } else if (!strcmp(pattern_gen->name, "dual-lvds")) {
126
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
127
+ RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
128
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
129
+ RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
130
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
131
+ RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
132
+ rkx110_set_stream_source(serdes, RK_SERDES_DUAL_LVDS_RX,
133
+ DEVICE_LOCAL);
134
+ } else if (!strcmp(pattern_gen->name, "dsi0")) {
135
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
136
+ RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
137
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
138
+ RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
139
+ serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
140
+ 0x1400000);
141
+
142
+ rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 0,
143
+ is_pattern_stream ? false : true);
144
+ if (is_pattern_stream)
145
+ delay_length = vm->hsync_len + vm->hback_porch +
146
+ vm->hactive + vm->hfront_porch;
147
+ else
148
+ delay_length = (vm->vfront_porch + 1) * (vm->hsync_len +
149
+ vm->hback_porch + vm->hactive + vm->hfront_porch);
150
+ rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 0, delay_length);
151
+ rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, true);
152
+ } else if (!strcmp(pattern_gen->name, "dsi1")) {
153
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
154
+ RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
155
+ hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
156
+ RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
157
+ serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
158
+ 0x2800000);
159
+
160
+ rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 1,
161
+ is_pattern_stream ? false : true);
162
+ if (is_pattern_stream)
163
+ delay_length = vm->hsync_len + vm->hback_porch +
164
+ vm->hactive + vm->hfront_porch;
165
+ else
166
+ delay_length = (vm->vfront_porch + 1) * (vm->hsync_len +
167
+ vm->hback_porch + vm->hactive + vm->hfront_porch);
168
+ rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 1, delay_length);
169
+ rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, true);
170
+ }
171
+
172
+ rk_serdes_display_video_start(serdes, pattern_gen->route, true);
173
+}
174
+
175
+static void pattern_switch_clk_to_pattern(struct pattern_gen *pattern_gen, struct videomode *vm)
176
+{
177
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
178
+ struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk;
179
+
180
+ if (serdes->version != SERDES_V1)
181
+ return;
182
+
183
+ if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
184
+ return;
185
+
186
+ if (!strcmp(pattern_gen->name, "lvds0")) {
187
+ hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock);
188
+ dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n",
189
+ hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN));
190
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
191
+ RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN);
192
+ } else if (!strcmp(pattern_gen->name, "lvds1")) {
193
+ hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock);
194
+ dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n",
195
+ hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN));
196
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
197
+ RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN);
198
+ } else if (!strcmp(pattern_gen->name, "dual-lvds")) {
199
+ hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock);
200
+ dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n",
201
+ hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN));
202
+ hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock);
203
+ dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n",
204
+ hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN));
205
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
206
+ RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN);
207
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
208
+ RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN);
209
+ } else if (!strcmp(pattern_gen->name, "dsi0")) {
210
+ hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL,
211
+ RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_PATTERN_GEN);
212
+ } else if (!strcmp(pattern_gen->name, "dsi1")) {
213
+ hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL,
214
+ RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_PATTERN_GEN);
215
+ }
216
+}
217
+
218
+static void pattern_switch_clk_to_stream(struct pattern_gen *pattern_gen)
219
+{
220
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
221
+ struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk;
222
+
223
+ if (serdes->version != SERDES_V1)
224
+ return;
225
+
226
+ if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
227
+ return;
228
+
229
+ if (!strcmp(pattern_gen->name, "lvds0")) {
230
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
231
+ RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE);
232
+ } else if (!strcmp(pattern_gen->name, "lvds1")) {
233
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
234
+ RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE);
235
+ } else if (!strcmp(pattern_gen->name, "dual-lvds")) {
236
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
237
+ RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE);
238
+ hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
239
+ RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE);
240
+ } else if (!strcmp(pattern_gen->name, "dsi0")) {
241
+ hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL,
242
+ RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_RKLINK_TX_PRE);
243
+ } else if (!strcmp(pattern_gen->name, "dsi1")) {
244
+ hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL,
245
+ RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_RKLINK_TX_PRE);
246
+ }
247
+}
248
+
249
+static int pattern_get_route(struct pattern_gen *pattern_gen)
250
+{
251
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
252
+ struct rk_serdes_route *route;
253
+ int i;
254
+
255
+ for (i = 0; i < serdes->route_nr; i++) {
256
+ route = serdes->route[i];
257
+
258
+ if (pattern_gen->chip == &serdes->chip[DEVICE_LOCAL]) {
259
+ if ((pattern_gen->type == route->local_port0) ||
260
+ (pattern_gen->type == route->local_port1)) {
261
+ pattern_gen->route = route;
262
+ break;
263
+ }
264
+ }
265
+ if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE0]) {
266
+ if ((pattern_gen->type == route->remote0_port0) ||
267
+ (pattern_gen->type == route->remote0_port1)) {
268
+ pattern_gen->route = route;
269
+ break;
270
+ }
271
+ }
272
+
273
+ if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE1]) {
274
+ if ((pattern_gen->type == route->remote1_port0) ||
275
+ (pattern_gen->type == route->remote1_port1)) {
276
+ pattern_gen->route = route;
277
+ break;
278
+ }
279
+ }
280
+ }
281
+
282
+ if (i >= serdes->route_nr) {
283
+ dev_info(serdes->dev, "can't find the %s in route\n", pattern_gen->name);
284
+ return -EINVAL;
285
+ }
286
+
287
+ return 0;
288
+}
289
+
290
+static void pattern_gen_enable(struct pattern_gen *pattern_gen)
291
+{
292
+ struct i2c_client *client = pattern_gen->chip->client;
293
+ struct rk_serdes *serdes = pattern_gen->chip->serdes;
294
+ struct videomode vm;
295
+ int ret;
296
+
297
+ ret = pattern_get_route(pattern_gen);
298
+ if (ret)
299
+ return;
300
+
301
+ memcpy(&vm, &pattern_gen->route->vm, sizeof(vm));
302
+
303
+ pattern_stop_stream(pattern_gen);
304
+ if (!strcmp(pattern_gen->name, "dual-lvds")) {
305
+ struct pattern_gen *lvds0_pat = pattern_gen + 1;
306
+ struct pattern_gen *lvds1_pat = pattern_gen + 2;
307
+
308
+ vm.hactive /= 2;
309
+ vm.hfront_porch /= 2;
310
+ vm.hback_porch /= 2;
311
+ vm.hsync_len /= 2;
312
+ vm.pixelclock /= 2;
313
+
314
+ pattern_switch_clk_to_pattern(pattern_gen, &vm);
315
+ pattern_gen_config(client, lvds0_pat, &vm);
316
+ pattern_gen_config(client, lvds1_pat, &vm);
317
+ serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
318
+ BIT(pattern_gen->link_src_offset + 16) |
319
+ BIT(pattern_gen->link_src_offset));
320
+ } else {
321
+ pattern_switch_clk_to_pattern(pattern_gen, &vm);
322
+ pattern_gen_config(client, pattern_gen, &vm);
323
+ serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
324
+ PATTERN_START_PCLK,
325
+ FIELD_PREP(PATTERN_START_PCLK, 1));
326
+ }
327
+
328
+ pattern_start_stream(pattern_gen, true);
62329 }
63330
64331 static void pattern_gen_disable(struct pattern_gen *pattern_gen)
65332 {
66333 struct i2c_client *client = pattern_gen->chip->client;
67334 struct rk_serdes *serdes = pattern_gen->chip->serdes;
335
+ int ret;
68336
69
- serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
70
- BIT(pattern_gen->link_src_offset + 16));
71
- serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
72
- PATTERN_START_PCLK,
73
- FIELD_PREP(PATTERN_START_PCLK, 0));
337
+ ret = pattern_get_route(pattern_gen);
338
+ if (ret)
339
+ return;
340
+
341
+ pattern_stop_stream(pattern_gen);
342
+ if (!strcmp(pattern_gen->name, "dual-lvds")) {
343
+ struct pattern_gen *lvds0_pat = pattern_gen + 1;
344
+ struct pattern_gen *lvds1_pat = pattern_gen + 2;
345
+
346
+ serdes->i2c_write_reg(client, lvds0_pat->link_src_reg,
347
+ BIT(lvds0_pat->link_src_offset + 16));
348
+ serdes->i2c_write_reg(client, lvds1_pat->link_src_reg,
349
+ BIT(lvds1_pat->link_src_offset + 16));
350
+ serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
351
+ BIT(pattern_gen->link_src_offset + 16));
352
+ } else {
353
+ serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
354
+ BIT(pattern_gen->link_src_offset + 16));
355
+ serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
356
+ PATTERN_START_PCLK,
357
+ FIELD_PREP(PATTERN_START_PCLK, 0));
358
+ }
359
+
360
+ pattern_switch_clk_to_stream(pattern_gen);
361
+ pattern_start_stream(pattern_gen, false);
74362 }
75363
76364 static ssize_t pattern_gen_write(struct file *file, const char __user *ubuf,