hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
u-boot/drivers/video/drm/rockchip_rgb.c
....@@ -13,11 +13,14 @@
1313 #include <dm/read.h>
1414 #include <dm/pinctrl.h>
1515 #include <linux/media-bus-format.h>
16
+#include <asm/gpio.h>
17
+#include <backlight.h>
1618
1719 #include "rockchip_display.h"
1820 #include "rockchip_crtc.h"
1921 #include "rockchip_connector.h"
2022 #include "rockchip_phy.h"
23
+#include "rockchip_panel.h"
2124
2225 #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16))
2326
....@@ -48,6 +51,9 @@
4851 #define RK3368_GRF_SOC_CON15 0x043c
4952 #define RK3368_FORCE_JETAG(v) HIWORD_UPDATE(v, 13, 13)
5053
54
+#define RK3562_GRF_IOC_VO_IO_CON 0x10500
55
+#define RK3562_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
56
+
5157 #define RK3568_GRF_VO_CON1 0X0364
5258 #define RK3568_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
5359
....@@ -67,6 +73,64 @@
6773 struct rockchip_phy *phy;
6874 const struct rockchip_rgb_funcs *funcs;
6975 };
76
+
77
+struct mcu_cmd_header {
78
+ u8 data_type;
79
+ u8 delay;
80
+ u8 payload_length;
81
+} __packed;
82
+
83
+struct mcu_cmd_desc {
84
+ struct mcu_cmd_header header;
85
+ const u8 *payload;
86
+};
87
+
88
+struct mcu_cmd_seq {
89
+ struct mcu_cmd_desc *cmds;
90
+ unsigned int cmd_cnt;
91
+};
92
+
93
+struct rockchip_mcu_panel_desc {
94
+ struct mcu_cmd_seq *init_seq;
95
+ struct mcu_cmd_seq *exit_seq;
96
+
97
+ struct {
98
+ unsigned int width;
99
+ unsigned int height;
100
+ } size;
101
+
102
+ struct {
103
+ unsigned int prepare;
104
+ unsigned int enable;
105
+ unsigned int disable;
106
+ unsigned int unprepare;
107
+ unsigned int reset;
108
+ unsigned int init;
109
+ } delay;
110
+
111
+ unsigned int bpc;
112
+ u32 bus_format;
113
+ u32 bus_flags;
114
+ bool power_invert;
115
+};
116
+
117
+struct rockchip_mcu_panel {
118
+ struct rockchip_panel base;
119
+ struct rockchip_mcu_panel_desc *desc;
120
+ struct udevice *power_supply;
121
+ struct udevice *backlight;
122
+
123
+ struct gpio_desc enable_gpio;
124
+ struct gpio_desc reset_gpio;
125
+
126
+ bool prepared;
127
+ bool enabled;
128
+};
129
+
130
+static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel)
131
+{
132
+ return container_of(panel, struct rockchip_mcu_panel, base);
133
+}
70134
71135 static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
72136 struct display_state *state)
....@@ -170,9 +234,254 @@
170234 .unprepare = rockchip_rgb_connector_unprepare,
171235 };
172236
237
+static int rockchip_mcu_panel_send_cmds(struct display_state *state,
238
+ struct mcu_cmd_seq *cmds)
239
+{
240
+ int i;
241
+
242
+ if (!cmds)
243
+ return -EINVAL;
244
+
245
+ display_send_mcu_cmd(state, MCU_SETBYPASS, 1);
246
+ for (i = 0; i < cmds->cmd_cnt; i++) {
247
+ struct mcu_cmd_desc *desc = &cmds->cmds[i];
248
+ int value = 0;
249
+
250
+ value = desc->payload[0];
251
+ display_send_mcu_cmd(state, desc->header.data_type, value);
252
+
253
+ if (desc->header.delay)
254
+ mdelay(desc->header.delay);
255
+ }
256
+ display_send_mcu_cmd(state, MCU_SETBYPASS, 0);
257
+
258
+ return 0;
259
+}
260
+
261
+static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel)
262
+{
263
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
264
+ int ret;
265
+
266
+ if (mcu_panel->prepared)
267
+ return;
268
+
269
+ if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
270
+ dm_gpio_set_value(&mcu_panel->enable_gpio, 1);
271
+
272
+ if (mcu_panel->desc->delay.prepare)
273
+ mdelay(mcu_panel->desc->delay.prepare);
274
+
275
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
276
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
277
+
278
+ if (mcu_panel->desc->delay.reset)
279
+ mdelay(mcu_panel->desc->delay.reset);
280
+
281
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
282
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 0);
283
+
284
+ if (mcu_panel->desc->delay.init)
285
+ mdelay(mcu_panel->desc->delay.init);
286
+
287
+ if (mcu_panel->desc->init_seq) {
288
+ ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq);
289
+ if (ret)
290
+ printf("failed to send mcu panel init cmds: %d\n", ret);
291
+ }
292
+
293
+ mcu_panel->prepared = true;
294
+}
295
+
296
+static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel)
297
+{
298
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
299
+ int ret;
300
+
301
+ if (!mcu_panel->prepared)
302
+ return;
303
+
304
+ if (mcu_panel->desc->exit_seq) {
305
+ ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq);
306
+ if (ret)
307
+ printf("failed to send mcu panel exit cmds: %d\n", ret);
308
+ }
309
+
310
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
311
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
312
+
313
+ if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
314
+ dm_gpio_set_value(&mcu_panel->enable_gpio, 0);
315
+
316
+ if (mcu_panel->desc->delay.unprepare)
317
+ mdelay(mcu_panel->desc->delay.unprepare);
318
+
319
+ mcu_panel->prepared = false;
320
+}
321
+
322
+static void rockchip_mcu_panel_enable(struct rockchip_panel *panel)
323
+{
324
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
325
+
326
+ if (mcu_panel->enabled)
327
+ return;
328
+
329
+ if (mcu_panel->desc->delay.enable)
330
+ mdelay(mcu_panel->desc->delay.enable);
331
+
332
+ if (mcu_panel->backlight)
333
+ backlight_enable(mcu_panel->backlight);
334
+
335
+ mcu_panel->enabled = true;
336
+}
337
+
338
+static void rockchip_mcu_panel_disable(struct rockchip_panel *panel)
339
+{
340
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
341
+
342
+ if (!mcu_panel->enabled)
343
+ return;
344
+
345
+ if (mcu_panel->backlight)
346
+ backlight_disable(mcu_panel->backlight);
347
+
348
+ if (mcu_panel->desc->delay.disable)
349
+ mdelay(mcu_panel->desc->delay.disable);
350
+
351
+ mcu_panel->enabled = false;
352
+}
353
+
354
+static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = {
355
+ .prepare = rockchip_mcu_panel_prepare,
356
+ .unprepare = rockchip_mcu_panel_unprepare,
357
+ .enable = rockchip_mcu_panel_enable,
358
+ .disable = rockchip_mcu_panel_disable,
359
+};
360
+
361
+static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length,
362
+ struct mcu_cmd_seq *pcmds)
363
+{
364
+ int len;
365
+ const u8 *buf;
366
+ const struct mcu_cmd_header *header;
367
+ int i, cnt = 0;
368
+
369
+ /* scan commands */
370
+ cnt = 0;
371
+ buf = data;
372
+ len = length;
373
+ while (len > sizeof(*header)) {
374
+ header = (const struct mcu_cmd_header *)buf;
375
+ buf += sizeof(*header) + header->payload_length;
376
+ len -= sizeof(*header) + header->payload_length;
377
+ cnt++;
378
+ }
379
+
380
+ pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc));
381
+ if (!pcmds->cmds)
382
+ return -ENOMEM;
383
+
384
+ pcmds->cmd_cnt = cnt;
385
+
386
+ buf = data;
387
+ len = length;
388
+ for (i = 0; i < cnt; i++) {
389
+ struct mcu_cmd_desc *desc = &pcmds->cmds[i];
390
+
391
+ header = (const struct mcu_cmd_header *)buf;
392
+ length -= sizeof(*header);
393
+ buf += sizeof(*header);
394
+ desc->header.data_type = header->data_type;
395
+ desc->header.delay = header->delay;
396
+ desc->header.payload_length = header->payload_length;
397
+ desc->payload = buf;
398
+ buf += header->payload_length;
399
+ length -= header->payload_length;
400
+ }
401
+
402
+ return 0;
403
+}
404
+
405
+static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node)
406
+{
407
+ const void *data;
408
+ int len;
409
+ int ret;
410
+
411
+ ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0,
412
+ &mcu_panel->enable_gpio, GPIOD_IS_OUT);
413
+ if (ret && ret != -ENOENT) {
414
+ printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret);
415
+ return ret;
416
+ }
417
+
418
+ ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0,
419
+ &mcu_panel->reset_gpio, GPIOD_IS_OUT);
420
+ if (ret && ret != -ENOENT) {
421
+ printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret);
422
+ return ret;
423
+ }
424
+
425
+ mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc));
426
+ if (!mcu_panel->desc)
427
+ return -ENOMEM;
428
+
429
+ mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert");
430
+
431
+ mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0);
432
+ mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0);
433
+ mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0);
434
+ mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0);
435
+ mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0);
436
+ mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0);
437
+
438
+ mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format",
439
+ MEDIA_BUS_FMT_RBG888_1X24);
440
+ mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8);
441
+
442
+ data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len);
443
+ if (data) {
444
+ mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq));
445
+ if (!mcu_panel->desc->init_seq)
446
+ return -ENOMEM;
447
+
448
+ ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq);
449
+ if (ret) {
450
+ printf("failed to parse panel init sequence\n");
451
+ goto free_on_cmds;
452
+ }
453
+ }
454
+
455
+ data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len);
456
+ if (data) {
457
+ mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq));
458
+ if (!mcu_panel->desc->exit_seq) {
459
+ ret = -ENOMEM;
460
+ goto free_on_cmds;
461
+ }
462
+
463
+ ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq);
464
+ if (ret) {
465
+ printf("failed to parse panel exit sequence\n");
466
+ goto free_cmds;
467
+ }
468
+ }
469
+
470
+ return 0;
471
+
472
+free_cmds:
473
+ free(mcu_panel->desc->exit_seq);
474
+free_on_cmds:
475
+ free(mcu_panel->desc->init_seq);
476
+ return ret;
477
+}
478
+
173479 static int rockchip_rgb_probe(struct udevice *dev)
174480 {
175481 struct rockchip_rgb *rgb = dev_get_priv(dev);
482
+ ofnode mcu_panel_node;
483
+ int phandle;
484
+ int ret;
176485
177486 rgb->dev = dev;
178487 rgb->funcs = (const struct rockchip_rgb_funcs *)dev_get_driver_data(dev);
....@@ -181,6 +490,45 @@
181490 rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
182491 if (rgb->id < 0)
183492 rgb->id = 0;
493
+
494
+ mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
495
+ if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
496
+ struct rockchip_mcu_panel *mcu_panel;
497
+
498
+ mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
499
+ if (!mcu_panel) {
500
+ printf("failed to alloc mcu_panel data\n");
501
+ return -ENOMEM;
502
+ }
503
+
504
+ ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
505
+ if (ret < 0) {
506
+ printf("failed to init mcu_panel: %d\n", ret);
507
+ return ret;
508
+ }
509
+
510
+ phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
511
+ if (phandle < 0) {
512
+ printf("failed to find backlight phandle\n");
513
+ return -EINVAL;
514
+ }
515
+
516
+ ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
517
+ &mcu_panel->backlight);
518
+ if (ret && ret != -ENOENT) {
519
+ printf("%s: failed to get backlight device: %d\n", __func__, ret);
520
+ return ret;
521
+ }
522
+
523
+ mcu_panel->base.dev = dev;
524
+ mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
525
+ mcu_panel->base.bpc = mcu_panel->desc->bpc;
526
+ mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
527
+ mcu_panel->enabled = false;
528
+ mcu_panel->prepared = false;
529
+
530
+ rgb->connector.panel = &mcu_panel->base;
531
+ }
184532
185533 rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
186534 NULL, DRM_MODE_CONNECTOR_LVDS);
....@@ -260,6 +608,16 @@
260608 .prepare = rk3368_rgb_prepare,
261609 };
262610
611
+static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
612
+{
613
+ regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
614
+ RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
615
+}
616
+
617
+static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
618
+ .prepare = rk3562_rgb_prepare,
619
+};
620
+
263621 static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
264622 {
265623 regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
....@@ -296,6 +654,10 @@
296654 .data = (ulong)&rk3368_rgb_funcs,
297655 },
298656 {
657
+ .compatible = "rockchip,rk3562-rgb",
658
+ .data = (ulong)&rk3562_rgb_funcs,
659
+ },
660
+ {
299661 .compatible = "rockchip,rk3568-rgb",
300662 .data = (ulong)&rk3568_rgb_funcs,
301663 },