1 /*
2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <dm/of_access.h>
9 #include <errno.h>
10 #include <syscon.h>
11 #include <regmap.h>
12 #include <dm/device.h>
13 #include <dm/read.h>
14 #include <dm/pinctrl.h>
15 #include <linux/media-bus-format.h>
16 #include <asm/gpio.h>
17 #include <backlight.h>
18
19 #include "rockchip_display.h"
20 #include "rockchip_crtc.h"
21 #include "rockchip_connector.h"
22 #include "rockchip_phy.h"
23 #include "rockchip_panel.h"
24
25 #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16))
26
27 #define PX30_GRF_PD_VO_CON1 0x0438
28 #define PX30_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3)
29 #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2)
30
31 #define RK1808_GRF_PD_VO_CON1 0x0444
32 #define RK1808_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3)
33
34 #define RV1106_VENC_GRF_VOP_IO_WRAPPER 0x1000c
35 #define RV1106_IO_BYPASS_SEL(v) HIWORD_UPDATE(v, 0, 1)
36 #define RV1106_VOGRF_VOP_PIPE_BYPASS 0x60034
37 #define RV1106_VOP_PIPE_BYPASS(v) HIWORD_UPDATE(v, 0, 1)
38
39 #define RV1126_GRF_IOFUNC_CON3 0x1026c
40 #define RV1126_LCDC_IO_BYPASS(v) HIWORD_UPDATE(v, 0, 0)
41
42 #define RK3288_GRF_SOC_CON6 0x025c
43 #define RK3288_LVDS_LCDC_SEL(v) HIWORD_UPDATE(v, 3, 3)
44 #define RK3288_GRF_SOC_CON7 0x0260
45 #define RK3288_LVDS_PWRDWN(v) HIWORD_UPDATE(v, 15, 15)
46 #define RK3288_LVDS_CON_ENABLE_2(v) HIWORD_UPDATE(v, 12, 12)
47 #define RK3288_LVDS_CON_ENABLE_1(v) HIWORD_UPDATE(v, 11, 11)
48 #define RK3288_LVDS_CON_CLKINV(v) HIWORD_UPDATE(v, 8, 8)
49 #define RK3288_LVDS_CON_TTL_EN(v) HIWORD_UPDATE(v, 6, 6)
50
51 #define RK3368_GRF_SOC_CON15 0x043c
52 #define RK3368_FORCE_JETAG(v) HIWORD_UPDATE(v, 13, 13)
53
54 #define RK3562_GRF_IOC_VO_IO_CON 0x10500
55 #define RK3562_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
56
57 #define RK3568_GRF_VO_CON1 0X0364
58 #define RK3568_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
59
60 struct rockchip_rgb;
61
62 struct rockchip_rgb_funcs {
63 void (*prepare)(struct rockchip_rgb *rgb, int pipe);
64 void (*unprepare)(struct rockchip_rgb *rgb);
65 };
66
67 struct rockchip_rgb {
68 struct rockchip_connector connector;
69 int id;
70 struct udevice *dev;
71 struct regmap *grf;
72 bool data_sync_bypass;
73 struct rockchip_phy *phy;
74 const struct rockchip_rgb_funcs *funcs;
75 };
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
to_rockchip_mcu_panel(struct rockchip_panel * panel)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 }
134
rockchip_rgb_connector_prepare(struct rockchip_connector * conn,struct display_state * state)135 static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
136 struct display_state *state)
137 {
138 struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
139 struct crtc_state *crtc_state = &state->crtc_state;
140 int pipe = crtc_state->crtc_id;
141 int ret;
142
143 pinctrl_select_state(rgb->dev, "default");
144
145 if (rgb->funcs && rgb->funcs->prepare)
146 rgb->funcs->prepare(rgb, pipe);
147
148 if (rgb->phy) {
149 ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL);
150 if (ret) {
151 dev_err(rgb->dev, "failed to set phy mode: %d\n", ret);
152 return ret;
153 }
154
155 rockchip_phy_power_on(rgb->phy);
156 }
157
158 return 0;
159 }
160
rockchip_rgb_connector_unprepare(struct rockchip_connector * conn,struct display_state * state)161 static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn,
162 struct display_state *state)
163 {
164 struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
165
166 if (rgb->phy)
167 rockchip_phy_power_off(rgb->phy);
168
169 if (rgb->funcs && rgb->funcs->unprepare)
170 rgb->funcs->unprepare(rgb);
171
172 pinctrl_select_state(rgb->dev, "sleep");
173 }
174
rockchip_rgb_connector_init(struct rockchip_connector * conn,struct display_state * state)175 static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state)
176 {
177 struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
178 struct connector_state *conn_state = &state->conn_state;
179
180 rgb->phy = conn->phy;
181
182 conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
183 conn_state->disp_info = rockchip_get_disp_info(conn_state->type, rgb->id);
184
185 switch (conn_state->bus_format) {
186 case MEDIA_BUS_FMT_RGB666_1X18:
187 conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
188 conn_state->output_if = VOP_OUTPUT_IF_RGB;
189 break;
190 case MEDIA_BUS_FMT_RGB565_1X16:
191 conn_state->output_mode = ROCKCHIP_OUT_MODE_P565;
192 conn_state->output_if = VOP_OUTPUT_IF_RGB;
193 break;
194 case MEDIA_BUS_FMT_SRGB888_3X8:
195 case MEDIA_BUS_FMT_SBGR888_3X8:
196 case MEDIA_BUS_FMT_SRBG888_3X8:
197 conn_state->output_mode = ROCKCHIP_OUT_MODE_S888;
198 conn_state->output_if = VOP_OUTPUT_IF_RGB;
199 break;
200 case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
201 case MEDIA_BUS_FMT_SBGR888_DUMMY_4X8:
202 case MEDIA_BUS_FMT_SRBG888_DUMMY_4X8:
203 conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
204 conn_state->output_if = VOP_OUTPUT_IF_RGB;
205 break;
206 case MEDIA_BUS_FMT_YUYV8_2X8:
207 case MEDIA_BUS_FMT_YVYU8_2X8:
208 case MEDIA_BUS_FMT_UYVY8_2X8:
209 case MEDIA_BUS_FMT_VYUY8_2X8:
210 conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656;
211 conn_state->output_if = VOP_OUTPUT_IF_BT656;
212 break;
213 case MEDIA_BUS_FMT_YUYV8_1X16:
214 case MEDIA_BUS_FMT_YVYU8_1X16:
215 case MEDIA_BUS_FMT_UYVY8_1X16:
216 case MEDIA_BUS_FMT_VYUY8_1X16:
217 conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120;
218 conn_state->output_if = VOP_OUTPUT_IF_BT1120;
219 break;
220 case MEDIA_BUS_FMT_RGB888_1X24:
221 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
222 default:
223 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
224 conn_state->output_if = VOP_OUTPUT_IF_RGB;
225 break;
226 }
227
228 return 0;
229 }
230
231 static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = {
232 .init = rockchip_rgb_connector_init,
233 .prepare = rockchip_rgb_connector_prepare,
234 .unprepare = rockchip_rgb_connector_unprepare,
235 };
236
rockchip_mcu_panel_send_cmds(struct display_state * state,struct mcu_cmd_seq * cmds)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
rockchip_mcu_panel_prepare(struct rockchip_panel * panel)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
rockchip_mcu_panel_unprepare(struct rockchip_panel * panel)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
rockchip_mcu_panel_enable(struct rockchip_panel * panel)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
rockchip_mcu_panel_disable(struct rockchip_panel * panel)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
rockchip_mcu_panel_parse_cmds(const u8 * data,int length,struct mcu_cmd_seq * pcmds)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
rockchip_mcu_panel_init(struct rockchip_mcu_panel * mcu_panel,ofnode mcu_panel_node)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
rockchip_rgb_probe(struct udevice * dev)479 static int rockchip_rgb_probe(struct udevice *dev)
480 {
481 struct rockchip_rgb *rgb = dev_get_priv(dev);
482 ofnode mcu_panel_node;
483 int phandle;
484 int ret;
485 struct udevice *syscon;
486
487 rgb->dev = dev;
488 rgb->funcs = (const struct rockchip_rgb_funcs *)dev_get_driver_data(dev);
489
490 ret = uclass_get_device_by_name(UCLASS_SYSCON, "syscon@fdc60000", &syscon);
491 rgb->grf = syscon_get_regmap(syscon);
492 rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass");
493 rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
494 if (rgb->id < 0)
495 rgb->id = 0;
496
497 mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
498 if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
499 struct rockchip_mcu_panel *mcu_panel;
500
501 mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
502 if (!mcu_panel) {
503 printf("failed to alloc mcu_panel data\n");
504 return -ENOMEM;
505 }
506
507 ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
508 if (ret < 0) {
509 printf("failed to init mcu_panel: %d\n", ret);
510 return ret;
511 }
512
513 phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
514 if (phandle < 0) {
515 printf("failed to find backlight phandle\n");
516 return -EINVAL;
517 }
518
519 ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
520 &mcu_panel->backlight);
521 if (ret && ret != -ENOENT) {
522 printf("%s: failed to get backlight device: %d\n", __func__, ret);
523 return ret;
524 }
525
526 mcu_panel->base.dev = dev;
527 mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
528 mcu_panel->base.bpc = mcu_panel->desc->bpc;
529 mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
530 mcu_panel->enabled = false;
531 mcu_panel->prepared = false;
532
533 rgb->connector.panel = &mcu_panel->base;
534 }
535
536 rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
537 NULL, DRM_MODE_CONNECTOR_LVDS);
538
539 return 0;
540 }
541
rv1106_rgb_prepare(struct rockchip_rgb * rgb,int pipe)542 static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
543 {
544 regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER,
545 RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0));
546 regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS,
547 RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
548 }
549
550 static const struct rockchip_rgb_funcs rv1106_rgb_funcs = {
551 .prepare = rv1106_rgb_prepare,
552 };
553
rv1126_rgb_prepare(struct rockchip_rgb * rgb,int pipe)554 static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
555 {
556 regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3,
557 RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass));
558 }
559
560 static const struct rockchip_rgb_funcs rv1126_rgb_funcs = {
561 .prepare = rv1126_rgb_prepare,
562 };
563
px30_rgb_prepare(struct rockchip_rgb * rgb,int pipe)564 static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
565 {
566 regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) |
567 PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
568 }
569
570 static const struct rockchip_rgb_funcs px30_rgb_funcs = {
571 .prepare = px30_rgb_prepare,
572 };
573
rk1808_rgb_prepare(struct rockchip_rgb * rgb,int pipe)574 static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
575 {
576 regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1,
577 RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
578 }
579
580 static const struct rockchip_rgb_funcs rk1808_rgb_funcs = {
581 .prepare = rk1808_rgb_prepare,
582 };
583
rk3288_rgb_prepare(struct rockchip_rgb * rgb,int pipe)584 static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
585 {
586 regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe));
587 regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
588 RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) |
589 RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) |
590 RK3288_LVDS_CON_TTL_EN(1));
591 }
592
rk3288_rgb_unprepare(struct rockchip_rgb * rgb)593 static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb)
594 {
595 regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
596 RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) |
597 RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0));
598 }
599
600 static const struct rockchip_rgb_funcs rk3288_rgb_funcs = {
601 .prepare = rk3288_rgb_prepare,
602 .unprepare = rk3288_rgb_unprepare,
603 };
604
rk3368_rgb_prepare(struct rockchip_rgb * rgb,int pipe)605 static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
606 {
607 regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0));
608 }
609
610 static const struct rockchip_rgb_funcs rk3368_rgb_funcs = {
611 .prepare = rk3368_rgb_prepare,
612 };
613
rk3562_rgb_prepare(struct rockchip_rgb * rgb,int pipe)614 static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
615 {
616 regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
617 RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
618 }
619
620 static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
621 .prepare = rk3562_rgb_prepare,
622 };
623
rk3568_rgb_prepare(struct rockchip_rgb * rgb,int pipe)624 static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
625 {
626 regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
627 }
628
629 static const struct rockchip_rgb_funcs rk3568_rgb_funcs = {
630 .prepare = rk3568_rgb_prepare,
631 };
632
633 static const struct udevice_id rockchip_rgb_ids[] = {
634 {
635 .compatible = "rockchip,px30-rgb",
636 .data = (ulong)&px30_rgb_funcs,
637 },
638 {
639 .compatible = "rockchip,rk1808-rgb",
640 .data = (ulong)&rk1808_rgb_funcs,
641 },
642 {
643 .compatible = "rockchip,rk3066-rgb",
644 },
645 {
646 .compatible = "rockchip,rk3128-rgb",
647 },
648 {
649 .compatible = "rockchip,rk3288-rgb",
650 .data = (ulong)&rk3288_rgb_funcs,
651 },
652 {
653 .compatible = "rockchip,rk3308-rgb",
654 },
655 {
656 .compatible = "rockchip,rk3368-rgb",
657 .data = (ulong)&rk3368_rgb_funcs,
658 },
659 {
660 .compatible = "rockchip,rk3562-rgb",
661 .data = (ulong)&rk3562_rgb_funcs,
662 },
663 {
664 .compatible = "rockchip,rk3568-rgb",
665 .data = (ulong)&rk3568_rgb_funcs,
666 },
667 {
668 .compatible = "rockchip,rv1106-rgb",
669 .data = (ulong)&rv1106_rgb_funcs,
670 },
671 {
672 .compatible = "rockchip,rv1108-rgb",
673 },
674 {
675 .compatible = "rockchip,rv1126-rgb",
676 .data = (ulong)&rv1126_rgb_funcs,
677 },
678 {}
679 };
680
681 U_BOOT_DRIVER(rockchip_rgb) = {
682 .name = "rockchip_rgb",
683 .id = UCLASS_DISPLAY,
684 .of_match = rockchip_rgb_ids,
685 .probe = rockchip_rgb_probe,
686 .priv_auto_alloc_size = sizeof(struct rockchip_rgb),
687 };
688