forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/rockchip/rockchip_lvds.c
....@@ -1,30 +1,24 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
34 * Author:
45 * Mark Yao <mark.yao@rock-chips.com>
56 * Sandy Huang <hjc@rock-chips.com>
6
- *
7
- * This software is licensed under the terms of the GNU General Public
8
- * License version 2, as published by the Free Software Foundation, and
9
- * may be copied, distributed, and modified under those terms.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
157 */
16
-
17
-#include <drm/drm_atomic_helper.h>
18
-#include <drm/drm_crtc_helper.h>
19
-#include <drm/drm_panel.h>
20
-#include <drm/drm_of.h>
218
229 #include <linux/component.h>
2310 #include <linux/mfd/syscon.h>
24
-#include <linux/of_device.h>
2511 #include <linux/of_graph.h>
26
-#include <linux/regmap.h>
2712 #include <linux/phy/phy.h>
13
+#include <linux/of_platform.h>
14
+#include <linux/regmap.h>
15
+#include <drm/drm_atomic_helper.h>
16
+#include <drm/drm_bridge.h>
17
+#include <drm/drm_of.h>
18
+#include <drm/drm_panel.h>
19
+#include <drm/drm_probe_helper.h>
20
+#include <drm/drm_simple_kms_helper.h>
21
+
2822 #include <uapi/linux/videodev2.h>
2923
3024 #include "rockchip_drm_drv.h"
....@@ -67,6 +61,9 @@
6761 #define RK3368_LVDS_MSBSEL(x) HIWORD_UPDATE(x, 11, 11)
6862 #define RK3368_LVDS_P2S_EN(x) HIWORD_UPDATE(x, 6, 6)
6963
64
+#define RK3562_GRF_VO_CON0 0x05d0
65
+#define RK3562_GRF_VO_CON1 0x05d4
66
+
7067 #define RK3568_GRF_VO_CON0 0x0360
7168 #define RK3568_LVDS1_SELECT(x) HIWORD_UPDATE(x, 13, 12)
7269 #define RK3568_LVDS1_MSBSEL(x) HIWORD_UPDATE(x, 11, 11)
....@@ -86,10 +83,24 @@
8683 enum lvds_format {
8784 LVDS_8BIT_MODE_FORMAT_1,
8885 LVDS_8BIT_MODE_FORMAT_2,
89
- LVDS_8BIT_MODE_FORMAT_3,
90
- LVDS_6BIT_MODE,
86
+ LVDS_6BIT_MODE_FORMAT_1,
87
+ LVDS_6BIT_MODE_FORMAT_2,
9188 LVDS_10BIT_MODE_FORMAT_1,
9289 LVDS_10BIT_MODE_FORMAT_2,
90
+};
91
+
92
+enum rockchip_lvds_dual_link_pixels {
93
+ ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 0,
94
+ ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 1,
95
+ ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS = 2,
96
+ ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS = 3,
97
+};
98
+
99
+enum rockchip_of_lvds_pixels {
100
+ ROCKCHIP_OF_LVDS_EVEN = BIT(0),
101
+ ROCKCHIP_OF_LVDS_ODD = BIT(1),
102
+ ROCKCHIP_OF_LVDS_LEFT = BIT(2),
103
+ ROCKCHIP_OF_LVDS_RIGHT = BIT(3),
93104 };
94105
95106 struct rockchip_lvds;
....@@ -109,7 +120,8 @@
109120 enum lvds_format format;
110121 bool data_swap;
111122 bool dual_channel;
112
- enum drm_lvds_dual_link_pixels pixel_order;
123
+ bool phy_enabled;
124
+ enum rockchip_lvds_dual_link_pixels pixel_order;
113125
114126 struct rockchip_lvds *primary;
115127 struct rockchip_lvds *secondary;
....@@ -121,6 +133,99 @@
121133 struct drm_display_mode mode;
122134 struct rockchip_drm_sub_dev sub_dev;
123135 };
136
+
137
+static int rockchip_of_lvds_get_port_pixels_type(struct device_node *port_node)
138
+{
139
+ bool even_pixels =
140
+ of_property_read_bool(port_node, "dual-lvds-even-pixels");
141
+ bool odd_pixels =
142
+ of_property_read_bool(port_node, "dual-lvds-odd-pixels");
143
+ bool left_pixels =
144
+ of_property_read_bool(port_node, "dual-lvds-left-pixels");
145
+ bool right_pixels =
146
+ of_property_read_bool(port_node, "dual-lvds-right-pixels");
147
+
148
+ return (even_pixels ? ROCKCHIP_OF_LVDS_EVEN : 0) |
149
+ (odd_pixels ? ROCKCHIP_OF_LVDS_ODD : 0) |
150
+ (left_pixels ? ROCKCHIP_OF_LVDS_LEFT : 0) |
151
+ (right_pixels ? ROCKCHIP_OF_LVDS_RIGHT : 0);
152
+}
153
+
154
+static int rockchip_of_lvds_get_remote_pixels_type(
155
+ const struct device_node *port_node)
156
+{
157
+ struct device_node *endpoint = NULL;
158
+ int pixels_type = -EPIPE;
159
+
160
+ for_each_child_of_node(port_node, endpoint) {
161
+ struct device_node *remote_port;
162
+ int current_pt;
163
+
164
+ if (!of_node_name_eq(endpoint, "endpoint"))
165
+ continue;
166
+
167
+ remote_port = of_graph_get_remote_port(endpoint);
168
+ if (!remote_port) {
169
+ of_node_put(endpoint);
170
+ return -EPIPE;
171
+ }
172
+
173
+ current_pt = rockchip_of_lvds_get_port_pixels_type(remote_port);
174
+ of_node_put(remote_port);
175
+ if (pixels_type < 0)
176
+ pixels_type = current_pt;
177
+
178
+ /*
179
+ * Sanity check, ensure that all remote endpoints have the same
180
+ * pixel type. We may lift this restriction later if we need to
181
+ * support multiple sinks with different dual-link
182
+ * configurations by passing the endpoints explicitly to
183
+ * rockchip_of_lvds_get_dual_link_pixel_order().
184
+ */
185
+ if (!current_pt || pixels_type != current_pt) {
186
+ of_node_put(endpoint);
187
+ return -EINVAL;
188
+ }
189
+ }
190
+
191
+ return pixels_type;
192
+}
193
+
194
+static int rockchip_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
195
+ const struct device_node *port2)
196
+{
197
+ int remote_p1_pt, remote_p2_pt;
198
+
199
+ if (!port1 || !port2)
200
+ return -EINVAL;
201
+
202
+ remote_p1_pt = rockchip_of_lvds_get_remote_pixels_type(port1);
203
+ if (remote_p1_pt < 0)
204
+ return remote_p1_pt;
205
+
206
+ remote_p2_pt = rockchip_of_lvds_get_remote_pixels_type(port2);
207
+ if (remote_p2_pt < 0)
208
+ return remote_p2_pt;
209
+
210
+ /*
211
+ * A valid dual-lVDS bus is found when one remote port is marked with
212
+ * "dual-lvds-even-pixels" or "dual-lvds-left-pixels", and the other
213
+ * remote port is marked with "dual-lvds-odd-pixels"or
214
+ * "dual-lvds-right-pixels", bail out if the markers are not right.
215
+ */
216
+ if ((remote_p1_pt + remote_p2_pt != ROCKCHIP_OF_LVDS_EVEN + ROCKCHIP_OF_LVDS_ODD) &&
217
+ (remote_p1_pt + remote_p2_pt != ROCKCHIP_OF_LVDS_LEFT + ROCKCHIP_OF_LVDS_RIGHT))
218
+ return -EINVAL;
219
+
220
+ if (remote_p1_pt == ROCKCHIP_OF_LVDS_EVEN)
221
+ return ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
222
+ else if (remote_p1_pt == ROCKCHIP_OF_LVDS_ODD)
223
+ return ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
224
+ else if (remote_p1_pt == ROCKCHIP_OF_LVDS_LEFT)
225
+ return ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS;
226
+ else
227
+ return ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS;
228
+}
124229
125230 static inline struct rockchip_lvds *connector_to_lvds(struct drm_connector *c)
126231 {
....@@ -164,7 +269,7 @@
164269 struct rockchip_lvds *lvds = connector_to_lvds(connector);
165270 struct drm_panel *panel = lvds->panel;
166271
167
- return drm_panel_get_modes(panel);
272
+ return drm_panel_get_modes(panel, connector);
168273 }
169274
170275 static const
....@@ -186,17 +291,14 @@
186291 bus_format = info->bus_formats[0];
187292
188293 switch (bus_format) {
189
- case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: /* jeida-18 */
190
- lvds->format = LVDS_6BIT_MODE;
191
- break;
192294 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: /* jeida-24 */
193295 lvds->format = LVDS_8BIT_MODE_FORMAT_2;
194296 break;
195297 case MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA: /* jeida-30 */
196298 lvds->format = LVDS_10BIT_MODE_FORMAT_2;
197299 break;
198
- case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* vesa-18 */
199
- lvds->format = LVDS_8BIT_MODE_FORMAT_3;
300
+ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* jeida-18, compatible with the [JEIDA], [LDI] and [VESA] specifications */
301
+ lvds->format = LVDS_6BIT_MODE_FORMAT_1;
200302 break;
201303 case MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG: /* vesa-30 */
202304 lvds->format = LVDS_10BIT_MODE_FORMAT_1;
....@@ -237,24 +339,24 @@
237339 s->output_type = DRM_MODE_CONNECTOR_LVDS;
238340 s->bus_flags = info->bus_flags;
239341 s->tv_state = &conn_state->tv;
240
- s->eotf = TRADITIONAL_GAMMA_SDR;
342
+ s->eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
241343 s->color_space = V4L2_COLORSPACE_DEFAULT;
242344
243345 switch (lvds->pixel_order) {
244
- case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
346
+ case ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
245347 s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE;
246348 s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0;
247349 break;
248
- case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
350
+ case ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
249351 s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE;
250352 s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP;
251353 s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0;
252354 break;
253
- case DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS:
355
+ case ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS:
254356 s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
255357 s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0;
256358 break;
257
- case DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS:
359
+ case ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS:
258360 s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
259361 s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP;
260362 s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0;
....@@ -277,13 +379,16 @@
277379 if (lvds->funcs->enable)
278380 lvds->funcs->enable(lvds);
279381
280
- ret = phy_set_mode(lvds->phy, PHY_MODE_VIDEO_LVDS);
382
+ ret = phy_set_mode(lvds->phy, PHY_MODE_LVDS);
281383 if (ret) {
282384 DRM_DEV_ERROR(lvds->dev, "failed to set phy mode: %d\n", ret);
283385 return;
284386 }
285387
286
- phy_power_on(lvds->phy);
388
+ if (lvds->phy && !lvds->phy_enabled) {
389
+ phy_power_on(lvds->phy);
390
+ lvds->phy_enabled = true;
391
+ }
287392
288393 if (lvds->secondary)
289394 rockchip_lvds_enable(lvds->secondary);
....@@ -294,7 +399,10 @@
294399 if (lvds->funcs->disable)
295400 lvds->funcs->disable(lvds);
296401
297
- phy_power_off(lvds->phy);
402
+ if (lvds->phy && lvds->phy_enabled) {
403
+ phy_power_off(lvds->phy);
404
+ lvds->phy_enabled = false;
405
+ }
298406
299407 if (lvds->secondary)
300408 rockchip_lvds_disable(lvds->secondary);
....@@ -328,7 +436,22 @@
328436 struct rockchip_lvds *lvds = encoder_to_lvds(encoder);
329437
330438 if (lvds->panel)
331
- return drm_panel_loader_protect(lvds->panel, on);
439
+ panel_simple_loader_protect(lvds->panel);
440
+
441
+
442
+ if (on) {
443
+ phy_init(lvds->phy);
444
+ if (lvds->phy) {
445
+ lvds->phy->power_count++;
446
+ lvds->phy_enabled = true;
447
+ }
448
+ } else {
449
+ phy_exit(lvds->phy);
450
+ if (lvds->phy) {
451
+ lvds->phy->power_count--;
452
+ lvds->phy_enabled = false;
453
+ }
454
+ }
332455
333456 return 0;
334457 }
....@@ -339,23 +462,22 @@
339462 .disable = rockchip_lvds_encoder_disable,
340463 .atomic_check = rockchip_lvds_encoder_atomic_check,
341464 .atomic_mode_set = rockchip_lvds_encoder_atomic_mode_set,
342
- .loader_protect = rockchip_lvds_encoder_loader_protect,
343465 };
344466
345467 static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = {
346468 .destroy = drm_encoder_cleanup,
347469 };
348470
349
-static int rockchip_lvds_match_by_id(struct device *dev, void *data)
471
+static int rockchip_lvds_match_by_id(struct device *dev, const void *data)
350472 {
351473 struct rockchip_lvds *lvds = dev_get_drvdata(dev);
352
- unsigned int *id = data;
474
+ unsigned int *id = (unsigned int *)data;
353475
354476 return lvds->id == *id;
355477 }
356478
357479 static struct rockchip_lvds *rockchip_lvds_find_by_id(struct device_driver *drv,
358
- unsigned int id)
480
+ unsigned int id)
359481 {
360482 struct device *dev;
361483
....@@ -386,8 +508,8 @@
386508 if (ret)
387509 return ret;
388510
389
- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
390
- dev->of_node);
511
+ encoder->possible_crtcs = rockchip_drm_of_find_possible_crtcs(drm_dev,
512
+ dev->of_node);
391513
392514 ret = drm_encoder_init(drm_dev, encoder, &rockchip_lvds_encoder_funcs,
393515 DRM_MODE_ENCODER_LVDS, NULL);
....@@ -411,6 +533,15 @@
411533 goto err_free_encoder;
412534 }
413535
536
+ if (lvds->secondary) {
537
+ kfree(connector->name);
538
+ connector->name = kasprintf(GFP_KERNEL, "LVDS-DUAL");
539
+ if (!connector->name) {
540
+ ret = -ENOMEM;
541
+ goto err_free_connector;
542
+ }
543
+ }
544
+
414545 drm_connector_helper_add(connector,
415546 &rockchip_lvds_connector_helper_funcs);
416547
....@@ -421,18 +552,13 @@
421552 goto err_free_connector;
422553 }
423554
424
- ret = drm_panel_attach(lvds->panel, connector);
425
- if (ret < 0) {
426
- DRM_DEV_ERROR(lvds->dev,
427
- "failed to attach panel: %d\n", ret);
428
- goto err_free_connector;
429
- }
430555 lvds->sub_dev.connector = &lvds->connector;
431556 lvds->sub_dev.of_node = lvds->dev->of_node;
557
+ lvds->sub_dev.loader_protect = rockchip_lvds_encoder_loader_protect;
432558 rockchip_drm_register_sub_dev(&lvds->sub_dev);
433559 drm_object_attach_property(&connector->base, private->connector_id_prop, 0);
434560 } else {
435
- ret = drm_bridge_attach(encoder, lvds->bridge, NULL);
561
+ ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0);
436562 if (ret) {
437563 DRM_DEV_ERROR(lvds->dev,
438564 "failed to attach bridge: %d\n", ret);
....@@ -456,10 +582,8 @@
456582
457583 if (lvds->sub_dev.connector)
458584 rockchip_drm_unregister_sub_dev(&lvds->sub_dev);
459
- if (lvds->panel) {
460
- drm_panel_detach(lvds->panel);
585
+ if (lvds->panel)
461586 drm_connector_cleanup(&lvds->connector);
462
- }
463587
464588 if (lvds->encoder.dev)
465589 drm_encoder_cleanup(&lvds->encoder);
....@@ -633,7 +757,7 @@
633757 .disable = rk3368_lvds_disable,
634758 };
635759
636
-static int __maybe_unused rockchip_secondary_lvds_probe(struct rockchip_lvds *lvds)
760
+static int rk3568_lvds_probe(struct rockchip_lvds *lvds)
637761 {
638762 if (lvds->dual_channel) {
639763 struct rockchip_lvds *secondary = NULL;
....@@ -646,7 +770,7 @@
646770
647771 port0 = of_graph_get_port_by_id(lvds->dev->of_node, 1);
648772 port1 = of_graph_get_port_by_id(secondary->dev->of_node, 1);
649
- pixel_order = drm_of_lvds_get_dual_link_pixel_order(port0, port1);
773
+ pixel_order = rockchip_of_lvds_get_dual_link_pixel_order(port0, port1);
650774 of_node_put(port1);
651775 of_node_put(port0);
652776
....@@ -658,21 +782,58 @@
658782 return 0;
659783 }
660784
661
-static void rk3568_lvds_enable(struct rockchip_lvds *lvds)
785
+static void rk3562_lvds_enable(struct rockchip_lvds *lvds)
662786 {
663
- regmap_write(lvds->grf, RK3568_GRF_VO_CON2,
787
+ regmap_write(lvds->grf, RK3562_GRF_VO_CON1,
664788 RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) |
665789 RK3568_LVDS0_DCLK_INV_SEL(1));
666
- regmap_write(lvds->grf, RK3568_GRF_VO_CON0,
790
+ regmap_write(lvds->grf, RK3562_GRF_VO_CON0,
667791 RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1));
792
+}
793
+
794
+static void rk3562_lvds_disable(struct rockchip_lvds *lvds)
795
+{
796
+ regmap_write(lvds->grf, RK3562_GRF_VO_CON1, RK3568_LVDS0_MODE_EN(0));
797
+}
798
+
799
+static const struct rockchip_lvds_funcs rk3562_lvds_funcs = {
800
+ .enable = rk3562_lvds_enable,
801
+ .disable = rk3562_lvds_disable,
802
+};
803
+
804
+static void rk3568_lvds_enable(struct rockchip_lvds *lvds)
805
+{
806
+ if (lvds->id) {
807
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON3,
808
+ RK3568_LVDS1_MODE_EN(1) |
809
+ RK3568_LVDS1_P2S_EN(1) |
810
+ RK3568_LVDS1_DCLK_INV_SEL(1));
811
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON0,
812
+ RK3568_LVDS1_SELECT(lvds->format) |
813
+ RK3568_LVDS1_MSBSEL(1));
814
+ } else {
815
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON2,
816
+ RK3568_LVDS0_MODE_EN(1) |
817
+ RK3568_LVDS0_P2S_EN(1) |
818
+ RK3568_LVDS0_DCLK_INV_SEL(1));
819
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON0,
820
+ RK3568_LVDS0_SELECT(lvds->format) |
821
+ RK3568_LVDS0_MSBSEL(1));
822
+ }
668823 }
669824
670825 static void rk3568_lvds_disable(struct rockchip_lvds *lvds)
671826 {
672
- regmap_write(lvds->grf, RK3568_GRF_VO_CON2, RK3568_LVDS0_MODE_EN(0));
827
+ if (lvds->id)
828
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON3,
829
+ RK3568_LVDS1_MODE_EN(0));
830
+ else
831
+ regmap_write(lvds->grf, RK3568_GRF_VO_CON2,
832
+ RK3568_LVDS0_MODE_EN(0));
673833 }
674834
675835 static const struct rockchip_lvds_funcs rk3568_lvds_funcs = {
836
+ .probe = rk3568_lvds_probe,
676837 .enable = rk3568_lvds_enable,
677838 .disable = rk3568_lvds_disable,
678839 };
....@@ -682,6 +843,7 @@
682843 { .compatible = "rockchip,rk3126-lvds", .data = &rk3126_lvds_funcs },
683844 { .compatible = "rockchip,rk3288-lvds", .data = &rk3288_lvds_funcs },
684845 { .compatible = "rockchip,rk3368-lvds", .data = &rk3368_lvds_funcs },
846
+ { .compatible = "rockchip,rk3562-lvds", .data = &rk3562_lvds_funcs },
685847 { .compatible = "rockchip,rk3568-lvds", .data = &rk3568_lvds_funcs },
686848 {}
687849 };