forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
....@@ -1,35 +1,42 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License as published by
6
- * the Free Software Foundation; either version 2 of the License, or
7
- * (at your option) any later version.
84 */
95
106 #include <linux/clk.h>
7
+#include <linux/gpio/consumer.h>
118 #include <linux/mfd/syscon.h>
129 #include <linux/module.h>
10
+#include <linux/of_gpio.h>
1311 #include <linux/platform_device.h>
1412 #include <linux/phy/phy.h>
1513 #include <linux/regmap.h>
1614 #include <linux/pm_runtime.h>
1715
1816 #include <drm/drm_of.h>
19
-#include <drm/drmP.h>
2017 #include <drm/drm_crtc_helper.h>
18
+#include <drm/drm_dsc.h>
2119 #include <drm/drm_edid.h>
2220 #include <drm/bridge/dw_hdmi.h>
21
+#include <drm/drm_edid.h>
22
+#include <drm/drm_of.h>
23
+#include <drm/drm_probe_helper.h>
24
+#include <drm/drm_simple_kms_helper.h>
2325
2426 #include <uapi/linux/videodev2.h>
2527
2628 #include "rockchip_drm_drv.h"
2729 #include "rockchip_drm_vop.h"
2830
31
+#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
32
+
2933 #define RK3228_GRF_SOC_CON2 0x0408
30
-#define RK3228_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16)))
34
+#define RK3228_HDMI_SDAIN_MSK BIT(14)
35
+#define RK3228_HDMI_SCLIN_MSK BIT(13)
3136 #define RK3228_GRF_SOC_CON6 0x0418
32
-#define RK3228_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16)))
37
+#define RK3228_HDMI_HPD_VSEL BIT(6)
38
+#define RK3228_HDMI_SDA_VSEL BIT(5)
39
+#define RK3228_HDMI_SCL_VSEL BIT(4)
3340
3441 #define RK3288_GRF_SOC_CON6 0x025C
3542 #define RK3288_HDMI_LCDC_SEL BIT(4)
....@@ -57,13 +64,81 @@
5764 #define RK3399_GRF_SOC_CON20 0x6250
5865 #define RK3399_HDMI_LCDC_SEL BIT(6)
5966
67
+#define RK3528_VO_GRF_HDMI_MASK 0x60014
68
+#define RK3528_HDMI_SNKDET_SEL BIT(6)
69
+#define RK3528_HDMI_SNKDET BIT(5)
70
+#define RK3528_HDMI_CECIN_MSK BIT(2)
71
+#define RK3528_HDMI_SDAIN_MSK BIT(1)
72
+#define RK3528_HDMI_SCLIN_MSK BIT(0)
73
+
74
+#define RK3528PMU_GRF_SOC_CON6 0x70018
75
+#define RK3528_HDMI_SDA5V_GRF BIT(6)
76
+#define RK3528_HDMI_SCL5V_GRF BIT(5)
77
+#define RK3528_HDMI_CEC5V_GRF BIT(4)
78
+#define RK3528_HDMI_HPD5V_GRF BIT(3)
79
+
80
+#define RK3528_GPIO_SWPORT_DR_L 0x0000
81
+#define RK3528_GPIO0_A2_DR BIT(2)
82
+
6083 #define RK3568_GRF_VO_CON1 0x0364
6184 #define RK3568_HDMI_SDAIN_MSK BIT(15)
6285 #define RK3568_HDMI_SCLIN_MSK BIT(14)
6386
64
-#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
65
-#define RK_HDMI_COLORIMETRY_BT2020 (HDMI_COLORIMETRY_EXTENDED + \
66
- HDMI_EXTENDED_COLORIMETRY_BT2020)
87
+#define RK3588_GRF_SOC_CON2 0x0308
88
+#define RK3588_HDMI1_HPD_INT_MSK BIT(15)
89
+#define RK3588_HDMI1_HPD_INT_CLR BIT(14)
90
+#define RK3588_HDMI0_HPD_INT_MSK BIT(13)
91
+#define RK3588_HDMI0_HPD_INT_CLR BIT(12)
92
+#define RK3588_GRF_SOC_CON7 0x031c
93
+#define RK3588_SET_HPD_PATH_MASK (0x3 << 12)
94
+#define RK3588_GRF_SOC_STATUS1 0x0384
95
+#define RK3588_HDMI0_LOW_MORETHAN100MS BIT(20)
96
+#define RK3588_HDMI0_HPD_PORT_LEVEL BIT(19)
97
+#define RK3588_HDMI0_IHPD_PORT BIT(18)
98
+#define RK3588_HDMI0_OHPD_INT BIT(17)
99
+#define RK3588_HDMI0_LEVEL_INT BIT(16)
100
+#define RK3588_HDMI0_INTR_CHANGE_CNT (0x7 << 13)
101
+#define RK3588_HDMI1_LOW_MORETHAN100MS BIT(28)
102
+#define RK3588_HDMI1_HPD_PORT_LEVEL BIT(27)
103
+#define RK3588_HDMI1_IHPD_PORT BIT(26)
104
+#define RK3588_HDMI1_OHPD_INT BIT(25)
105
+#define RK3588_HDMI1_LEVEL_INT BIT(24)
106
+#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21)
107
+
108
+#define RK3588_GRF_VO1_CON3 0x000c
109
+#define RK3588_COLOR_FORMAT_MASK 0xf
110
+#define RK3588_RGB 0
111
+#define RK3588_YUV422 0x1
112
+#define RK3588_YUV444 0x2
113
+#define RK3588_YUV420 0x3
114
+#define RK3588_COMPRESSED_DATA 0xb
115
+#define RK3588_COLOR_DEPTH_MASK (0xf << 4)
116
+#define RK3588_8BPC 0
117
+#define RK3588_10BPC (0x6 << 4)
118
+#define RK3588_CECIN_MASK BIT(8)
119
+#define RK3588_SCLIN_MASK BIT(9)
120
+#define RK3588_SDAIN_MASK BIT(10)
121
+#define RK3588_MODE_MASK BIT(11)
122
+#define RK3588_COMPRESS_MODE_MASK BIT(12)
123
+#define RK3588_I2S_SEL_MASK BIT(13)
124
+#define RK3588_SPDIF_SEL_MASK BIT(14)
125
+#define RK3588_GRF_VO1_CON4 0x0010
126
+#define RK3588_HDMI21_MASK BIT(0)
127
+#define RK3588_GRF_VO1_CON9 0x0024
128
+#define RK3588_HDMI0_GRANT_SEL BIT(10)
129
+#define RK3588_HDMI0_GRANT_SW BIT(11)
130
+#define RK3588_HDMI1_GRANT_SEL BIT(12)
131
+#define RK3588_HDMI1_GRANT_SW BIT(13)
132
+#define RK3588_GRF_VO1_CON6 0x0018
133
+#define RK3588_GRF_VO1_CON7 0x001c
134
+
135
+#define COLOR_DEPTH_10BIT BIT(31)
136
+#define HDMI_FRL_MODE BIT(30)
137
+#define HDMI_EARC_MODE BIT(29)
138
+#define DATA_RATE_MASK 0xFFFFFFF
139
+
140
+#define HDMI20_MAX_RATE 600000
141
+#define HDMI_8K60_RATE 2376000
67142
68143 /**
69144 * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips
....@@ -77,72 +152,99 @@
77152 int ddc_en_reg;
78153 u32 lcdsel_big;
79154 u32 lcdsel_lit;
155
+ bool split_mode;
80156 };
81157
82
-/* HDMI output pixel format */
83
-enum drm_hdmi_output_type {
84
- DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
85
- DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
86
- DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
87
- DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
88
- DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
89
- DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
90
- DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
91
-};
92
-
93
-enum dw_hdmi_rockchip_color_depth {
94
- ROCKCHIP_HDMI_DEPTH_8,
95
- ROCKCHIP_HDMI_DEPTH_10,
96
- ROCKCHIP_HDMI_DEPTH_12,
97
- ROCKCHIP_HDMI_DEPTH_16,
98
- ROCKCHIP_HDMI_DEPTH_420_10,
99
- ROCKCHIP_HDMI_DEPTH_420_12,
100
- ROCKCHIP_HDMI_DEPTH_420_16
158
+enum hdmi_frl_rate_per_lane {
159
+ FRL_12G_PER_LANE = 12,
160
+ FRL_10G_PER_LANE = 10,
161
+ FRL_8G_PER_LANE = 8,
162
+ FRL_6G_PER_LANE = 6,
163
+ FRL_3G_PER_LANE = 3,
101164 };
102165
103166 struct rockchip_hdmi {
104167 struct device *dev;
105168 struct regmap *regmap;
169
+ struct regmap *vo1_regmap;
170
+ void __iomem *gpio_base;
106171 struct drm_encoder encoder;
172
+ struct drm_device *drm_dev;
107173 const struct rockchip_hdmi_chip_data *chip_data;
174
+ struct dw_hdmi_plat_data *plat_data;
175
+ struct clk *aud_clk;
108176 struct clk *phyref_clk;
109177 struct clk *grf_clk;
110178 struct clk *hclk_vio;
179
+ struct clk *hclk_vo1;
111180 struct clk *hclk_vop;
181
+ struct clk *hpd_clk;
182
+ struct clk *pclk;
183
+ struct clk *earc_clk;
184
+ struct clk *hdmitx_ref;
185
+ struct clk *link_clk;
112186 struct dw_hdmi *hdmi;
187
+ struct dw_hdmi_qp *hdmi_qp;
113188
114189 struct phy *phy;
115
- int max_tmdsclk;
190
+
191
+ u32 max_tmdsclk;
116192 bool unsupported_yuv_input;
117193 bool unsupported_deep_color;
118194 bool skip_check_420_mode;
119
- bool mode_changed;
195
+ bool hpd_wake_en;
120196 u8 force_output;
121197 u8 id;
198
+ bool hpd_stat;
199
+ bool is_hdmi_qp;
200
+ bool user_split_mode;
122201
123202 unsigned long bus_format;
124203 unsigned long output_bus_format;
125204 unsigned long enc_out_encoding;
205
+ unsigned long prev_bus_format;
126206 int color_changed;
207
+ int hpd_irq;
127208
128209 struct drm_property *color_depth_property;
129210 struct drm_property *hdmi_output_property;
130211 struct drm_property *colordepth_capacity;
131212 struct drm_property *outputmode_capacity;
132
- struct drm_property *colorimetry_property;
133213 struct drm_property *quant_range;
134214 struct drm_property *hdr_panel_metadata_property;
215
+ struct drm_property *next_hdr_sink_data_property;
135216 struct drm_property *output_hdmi_dvi;
136217 struct drm_property *output_type_capacity;
218
+ struct drm_property *user_split_mode_prop;
219
+ struct drm_property *allm_capacity;
220
+ struct drm_property *allm_enable;
137221
138222 struct drm_property_blob *hdr_panel_blob_ptr;
223
+ struct drm_property_blob *next_hdr_data_ptr;
139224
140225 unsigned int colordepth;
141226 unsigned int colorimetry;
142227 unsigned int hdmi_quant_range;
143228 unsigned int phy_bus_width;
144
- enum drm_hdmi_output_type hdmi_output;
229
+ unsigned int enable_allm;
230
+ enum rk_if_color_format hdmi_output;
145231 struct rockchip_drm_sub_dev sub_dev;
232
+
233
+ u8 max_frl_rate_per_lane;
234
+ u8 max_lanes;
235
+ u8 add_func;
236
+ u8 edid_colorimetry;
237
+ struct rockchip_drm_dsc_cap dsc_cap;
238
+ struct next_hdr_sink_data next_hdr_data;
239
+ struct dw_hdmi_link_config link_cfg;
240
+ struct gpio_desc *enable_gpio;
241
+
242
+ struct delayed_work work;
243
+ struct workqueue_struct *workqueue;
244
+ struct gpio_desc *hpd_gpiod;
245
+ struct pinctrl *p;
246
+ struct pinctrl_state *idle_state;
247
+ struct pinctrl_state *default_state;
146248 };
147249
148250 #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
....@@ -260,94 +362,6 @@
260362 }
261363 };
262364
263
-static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_rk356x[] = {
264
- {
265
- 30666000, {
266
- { 0x00b3, 0x0000 },
267
- { 0x2153, 0x0000 },
268
- { 0x40f3, 0x0000 },
269
- },
270
- }, {
271
- 36800000, {
272
- { 0x00b3, 0x0000 },
273
- { 0x2153, 0x0000 },
274
- { 0x40a2, 0x0001 },
275
- },
276
- }, {
277
- 46000000, {
278
- { 0x00b3, 0x0000 },
279
- { 0x2142, 0x0001 },
280
- { 0x40a2, 0x0001 },
281
- },
282
- }, {
283
- 61333000, {
284
- { 0x0072, 0x0001 },
285
- { 0x2142, 0x0001 },
286
- { 0x40a2, 0x0001 },
287
- },
288
- }, {
289
- 73600000, {
290
- { 0x0072, 0x0001 },
291
- { 0x2142, 0x0001 },
292
- { 0x4061, 0x0002 },
293
- },
294
- }, {
295
- 92000000, {
296
- { 0x0072, 0x0001 },
297
- { 0x2145, 0x0002 },
298
- { 0x4061, 0x0002 },
299
- },
300
- }, {
301
- 122666000, {
302
- { 0x0051, 0x0002 },
303
- { 0x2145, 0x0002 },
304
- { 0x4061, 0x0002 },
305
- },
306
- }, {
307
- 147200000, {
308
- { 0x0051, 0x0002 },
309
- { 0x2145, 0x0002 },
310
- { 0x4064, 0x0003 },
311
- },
312
- }, {
313
- 184000000, {
314
- { 0x0051, 0x0002 },
315
- { 0x214c, 0x0003 },
316
- { 0x4064, 0x0003 },
317
- },
318
- }, {
319
- 226666000, {
320
- { 0x0040, 0x0003 },
321
- { 0x214c, 0x0003 },
322
- { 0x4064, 0x0003 },
323
- },
324
- }, {
325
- 272000000, {
326
- { 0x0040, 0x0003 },
327
- { 0x214c, 0x0003 },
328
- { 0x5a64, 0x0003 },
329
- },
330
- }, {
331
- 340000000, {
332
- { 0x0040, 0x0002 },
333
- { 0x3b4c, 0x0003 },
334
- { 0x5a64, 0x0003 },
335
- },
336
- }, {
337
- 600000000, {
338
- { 0x1a40, 0x0003 },
339
- { 0x3b4c, 0x0003 },
340
- { 0x5a64, 0x0003 },
341
- },
342
- }, {
343
- ~0UL, {
344
- { 0x0000, 0x0000 },
345
- { 0x0000, 0x0000 },
346
- { 0x0000, 0x0000 },
347
- },
348
- }
349
-};
350
-
351365 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = {
352366 {
353367 30666000, {
....@@ -437,19 +451,6 @@
437451 }
438452 };
439453
440
-static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr_rk356x[] = {
441
- /* pixelclk bpp8 bpp10 bpp12 */
442
- {
443
- 272000000, { 0x0000, 0x0000, 0x0000 },
444
- }, {
445
- 340000000, { 0x0001, 0x0000, 0x0000 },
446
- }, {
447
- 600000000, { 0x0000, 0x0000, 0x0000 },
448
- }, {
449
- ~0UL, { 0x0000, 0x0000, 0x0000},
450
- }
451
-};
452
-
453454 static struct dw_hdmi_phy_config rockchip_phy_config[] = {
454455 /*pixelclk symbol term vlev*/
455456 { 74250000, 0x8009, 0x0004, 0x0272},
....@@ -459,6 +460,744 @@
459460 { ~0UL, 0x0000, 0x0000, 0x0000},
460461 { ~0UL, 0x0000, 0x0000, 0x0000},
461462 };
463
+
464
+enum ROW_INDEX_BPP {
465
+ ROW_INDEX_6BPP = 0,
466
+ ROW_INDEX_8BPP,
467
+ ROW_INDEX_10BPP,
468
+ ROW_INDEX_12BPP,
469
+ ROW_INDEX_23BPP,
470
+ MAX_ROW_INDEX
471
+};
472
+
473
+enum COLUMN_INDEX_BPC {
474
+ COLUMN_INDEX_8BPC = 0,
475
+ COLUMN_INDEX_10BPC,
476
+ COLUMN_INDEX_12BPC,
477
+ COLUMN_INDEX_14BPC,
478
+ COLUMN_INDEX_16BPC,
479
+ MAX_COLUMN_INDEX
480
+};
481
+
482
+#define PPS_TABLE_LEN 8
483
+#define PPS_BPP_LEN 4
484
+#define PPS_BPC_LEN 2
485
+
486
+struct pps_data {
487
+ u32 pic_width;
488
+ u32 pic_height;
489
+ u32 slice_width;
490
+ u32 slice_height;
491
+ bool convert_rgb;
492
+ u8 bpc;
493
+ u8 bpp;
494
+ u8 raw_pps[128];
495
+};
496
+
497
+/*
498
+ * Selected Rate Control Related Parameter Recommended Values
499
+ * from DSC_v1.11 spec & C Model release: DSC_model_20161212
500
+ */
501
+static struct pps_data pps_datas[PPS_TABLE_LEN] = {
502
+ {
503
+ /* 7680x4320/960X96 rgb 8bpc 12bpp */
504
+ 7680, 4320, 960, 96, 1, 8, 192,
505
+ {
506
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
507
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
508
+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
509
+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
510
+ 0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
511
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
512
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
513
+ 0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
514
+ 0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
515
+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
516
+ 0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
517
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
522
+ },
523
+ },
524
+ {
525
+ /* 7680x4320/960X96 rgb 8bpc 11bpp */
526
+ 7680, 4320, 960, 96, 1, 8, 176,
527
+ {
528
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
529
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
530
+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
531
+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
532
+ 0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
533
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
534
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
535
+ 0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
536
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
537
+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
538
+ 0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
539
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
544
+ },
545
+ },
546
+ {
547
+ /* 7680x4320/960X96 rgb 8bpc 10bpp */
548
+ 7680, 4320, 960, 96, 1, 8, 160,
549
+ {
550
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
551
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
552
+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
553
+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
554
+ 0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
555
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
556
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
557
+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
558
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
559
+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
560
+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
561
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
566
+ },
567
+ },
568
+ {
569
+ /* 7680x4320/960X96 rgb 8bpc 9bpp */
570
+ 7680, 4320, 960, 96, 1, 8, 144,
571
+ {
572
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
573
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
574
+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
575
+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
576
+ 0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
577
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
578
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
579
+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
580
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
581
+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
582
+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
583
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
588
+ },
589
+ },
590
+ {
591
+ /* 7680x4320/960X96 rgb 10bpc 12bpp */
592
+ 7680, 4320, 960, 96, 1, 10, 192,
593
+ {
594
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
595
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
596
+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
597
+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
598
+ 0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
599
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
600
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
601
+ 0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
602
+ 0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
603
+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
604
+ 0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
605
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
610
+ },
611
+ },
612
+ {
613
+ /* 7680x4320/960X96 rgb 10bpc 11bpp */
614
+ 7680, 4320, 960, 96, 1, 10, 176,
615
+ {
616
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
617
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
618
+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
619
+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
620
+ 0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
621
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
622
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
623
+ 0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
624
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
625
+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
626
+ 0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
627
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
632
+ },
633
+ },
634
+ {
635
+ /* 7680x4320/960X96 rgb 10bpc 10bpp */
636
+ 7680, 4320, 960, 96, 1, 10, 160,
637
+ {
638
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
639
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
640
+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
641
+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
642
+ 0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
643
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
644
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
645
+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
646
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
647
+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
648
+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
649
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
654
+ },
655
+ },
656
+ {
657
+ /* 7680x4320/960X96 rgb 10bpc 9bpp */
658
+ 7680, 4320, 960, 96, 1, 10, 144,
659
+ {
660
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
661
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
662
+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
663
+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
664
+ 0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
665
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
666
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
667
+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
668
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
669
+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
670
+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
671
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
676
+ },
677
+ },
678
+};
679
+
680
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
681
+{
682
+ switch (bus_format) {
683
+ case MEDIA_BUS_FMT_RGB888_1X24:
684
+ case MEDIA_BUS_FMT_RGB101010_1X30:
685
+ case MEDIA_BUS_FMT_RGB121212_1X36:
686
+ case MEDIA_BUS_FMT_RGB161616_1X48:
687
+ return true;
688
+
689
+ default:
690
+ return false;
691
+ }
692
+}
693
+
694
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
695
+{
696
+ switch (bus_format) {
697
+ case MEDIA_BUS_FMT_YUV8_1X24:
698
+ case MEDIA_BUS_FMT_YUV10_1X30:
699
+ case MEDIA_BUS_FMT_YUV12_1X36:
700
+ case MEDIA_BUS_FMT_YUV16_1X48:
701
+ return true;
702
+
703
+ default:
704
+ return false;
705
+ }
706
+}
707
+
708
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
709
+{
710
+ switch (bus_format) {
711
+ case MEDIA_BUS_FMT_UYVY8_1X16:
712
+ case MEDIA_BUS_FMT_UYVY10_1X20:
713
+ case MEDIA_BUS_FMT_UYVY12_1X24:
714
+ case MEDIA_BUS_FMT_YUYV8_1X16:
715
+ case MEDIA_BUS_FMT_YUYV10_1X20:
716
+ case MEDIA_BUS_FMT_YUYV12_1X24:
717
+ return true;
718
+
719
+ default:
720
+ return false;
721
+ }
722
+}
723
+
724
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
725
+{
726
+ switch (bus_format) {
727
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
728
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
729
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
730
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
731
+ return true;
732
+
733
+ default:
734
+ return false;
735
+ }
736
+}
737
+
738
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
739
+{
740
+ switch (bus_format) {
741
+ case MEDIA_BUS_FMT_RGB888_1X24:
742
+ case MEDIA_BUS_FMT_YUV8_1X24:
743
+ case MEDIA_BUS_FMT_UYVY8_1X16:
744
+ case MEDIA_BUS_FMT_YUYV8_1X16:
745
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
746
+ return 8;
747
+
748
+ case MEDIA_BUS_FMT_RGB101010_1X30:
749
+ case MEDIA_BUS_FMT_YUV10_1X30:
750
+ case MEDIA_BUS_FMT_UYVY10_1X20:
751
+ case MEDIA_BUS_FMT_YUYV10_1X20:
752
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
753
+ return 10;
754
+
755
+ case MEDIA_BUS_FMT_RGB121212_1X36:
756
+ case MEDIA_BUS_FMT_YUV12_1X36:
757
+ case MEDIA_BUS_FMT_UYVY12_1X24:
758
+ case MEDIA_BUS_FMT_YUYV12_1X24:
759
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
760
+ return 12;
761
+
762
+ case MEDIA_BUS_FMT_RGB161616_1X48:
763
+ case MEDIA_BUS_FMT_YUV16_1X48:
764
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
765
+ return 16;
766
+
767
+ default:
768
+ return 0;
769
+ }
770
+}
771
+
772
+static int hdmi_bus_fmt_to_color_format(unsigned int bus_format)
773
+{
774
+ switch (bus_format) {
775
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
776
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
777
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
778
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
779
+ return RK_IF_FORMAT_YCBCR420;
780
+
781
+ case MEDIA_BUS_FMT_YUV8_1X24:
782
+ case MEDIA_BUS_FMT_YUV10_1X30:
783
+ case MEDIA_BUS_FMT_YUV12_1X36:
784
+ case MEDIA_BUS_FMT_YUV16_1X48:
785
+ return RK_IF_FORMAT_YCBCR444;
786
+
787
+ case MEDIA_BUS_FMT_UYVY8_1X16:
788
+ case MEDIA_BUS_FMT_YUYV8_1X16:
789
+ case MEDIA_BUS_FMT_UYVY10_1X20:
790
+ case MEDIA_BUS_FMT_YUYV10_1X20:
791
+ case MEDIA_BUS_FMT_UYVY12_1X24:
792
+ case MEDIA_BUS_FMT_YVYU12_1X24:
793
+ return RK_IF_FORMAT_YCBCR422;
794
+
795
+ case MEDIA_BUS_FMT_RGB888_1X24:
796
+ case MEDIA_BUS_FMT_RGB101010_1X30:
797
+ case MEDIA_BUS_FMT_RGB121212_1X36:
798
+ case MEDIA_BUS_FMT_RGB161616_1X48:
799
+ default:
800
+ return RK_IF_FORMAT_RGB;
801
+ }
802
+}
803
+
804
+static unsigned int
805
+hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
806
+{
807
+ unsigned int tmdsclock = pixelclock;
808
+ unsigned int depth =
809
+ hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
810
+
811
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
812
+ switch (depth) {
813
+ case 16:
814
+ tmdsclock = pixelclock * 2;
815
+ break;
816
+ case 12:
817
+ tmdsclock = pixelclock * 3 / 2;
818
+ break;
819
+ case 10:
820
+ tmdsclock = pixelclock * 5 / 4;
821
+ break;
822
+ default:
823
+ break;
824
+ }
825
+ }
826
+
827
+ return tmdsclock;
828
+}
829
+
830
+static int rockchip_hdmi_match_by_id(struct device *dev, const void *data)
831
+{
832
+ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
833
+ const unsigned int *id = data;
834
+
835
+ return hdmi->id == *id;
836
+}
837
+
838
+static struct rockchip_hdmi *
839
+rockchip_hdmi_find_by_id(struct device_driver *drv, unsigned int id)
840
+{
841
+ struct device *dev;
842
+
843
+ dev = driver_find_device(drv, NULL, &id, rockchip_hdmi_match_by_id);
844
+ if (!dev)
845
+ return NULL;
846
+
847
+ return dev_get_drvdata(dev);
848
+}
849
+
850
+static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
851
+ struct drm_crtc_state *crtc_state,
852
+ unsigned int tmdsclk)
853
+{
854
+ struct drm_display_mode mode;
855
+ int max_lanes, max_rate_per_lane;
856
+ int max_dsc_lanes, max_dsc_rate_per_lane;
857
+ unsigned long max_frl_rate;
858
+
859
+ drm_mode_copy(&mode, &crtc_state->mode);
860
+ if (hdmi->plat_data->split_mode)
861
+ drm_mode_convert_to_origin_mode(&mode);
862
+
863
+ max_lanes = hdmi->max_lanes;
864
+ max_rate_per_lane = hdmi->max_frl_rate_per_lane;
865
+ max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
866
+
867
+ hdmi->link_cfg.dsc_mode = false;
868
+ hdmi->link_cfg.frl_lanes = max_lanes;
869
+ hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
870
+ hdmi->link_cfg.add_func = hdmi->add_func;
871
+
872
+ if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) {
873
+ dev_info(hdmi->dev, "use tmds mode\n");
874
+ hdmi->link_cfg.frl_mode = false;
875
+ return;
876
+ }
877
+
878
+ hdmi->link_cfg.frl_mode = true;
879
+
880
+ if (!hdmi->dsc_cap.v_1p2)
881
+ return;
882
+
883
+ max_dsc_lanes = hdmi->dsc_cap.max_lanes;
884
+ max_dsc_rate_per_lane =
885
+ hdmi->dsc_cap.max_frl_rate_per_lane;
886
+
887
+ if (mode.clock >= HDMI_8K60_RATE &&
888
+ !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) &&
889
+ !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) {
890
+ hdmi->link_cfg.dsc_mode = true;
891
+ hdmi->link_cfg.frl_lanes = max_dsc_lanes;
892
+ hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
893
+ } else {
894
+ hdmi->link_cfg.dsc_mode = false;
895
+ hdmi->link_cfg.frl_lanes = max_lanes;
896
+ hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
897
+ }
898
+}
899
+
900
+/////////////////////////////////////////////////////////////////////////////////////
901
+
902
+static int hdmi_dsc_get_slice_height(int vactive)
903
+{
904
+ int slice_height;
905
+
906
+ /*
907
+ * Slice Height determination : HDMI2.1 Section 7.7.5.2
908
+ * Select smallest slice height >=96, that results in a valid PPS and
909
+ * requires minimum padding lines required for final slice.
910
+ *
911
+ * Assumption : Vactive is even.
912
+ */
913
+ for (slice_height = 96; slice_height <= vactive; slice_height += 2)
914
+ if (vactive % slice_height == 0)
915
+ return slice_height;
916
+
917
+ return 0;
918
+}
919
+
920
+static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
921
+ struct drm_crtc_state *crtc_state,
922
+ int src_max_slices, int src_max_slice_width,
923
+ int hdmi_max_slices, int hdmi_throughput)
924
+{
925
+/* Pixel rates in KPixels/sec */
926
+#define HDMI_DSC_PEAK_PIXEL_RATE 2720000
927
+/*
928
+ * Rates at which the source and sink are required to process pixels in each
929
+ * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
930
+ */
931
+#define HDMI_DSC_MAX_ENC_THROUGHPUT_0 340000
932
+#define HDMI_DSC_MAX_ENC_THROUGHPUT_1 400000
933
+
934
+/* Spec limits the slice width to 2720 pixels */
935
+#define MAX_HDMI_SLICE_WIDTH 2720
936
+ int kslice_adjust;
937
+ int adjusted_clk_khz;
938
+ int min_slices;
939
+ int target_slices;
940
+ int max_throughput; /* max clock freq. in khz per slice */
941
+ int max_slice_width;
942
+ int slice_width;
943
+ int pixel_clock = crtc_state->mode.clock;
944
+
945
+ if (!hdmi_throughput)
946
+ return 0;
947
+
948
+ /*
949
+ * Slice Width determination : HDMI2.1 Section 7.7.5.1
950
+ * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
951
+ * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
952
+ * dividing adjusted clock value by 10.
953
+ */
954
+ if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
955
+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
956
+ kslice_adjust = 10;
957
+ else
958
+ kslice_adjust = 5;
959
+
960
+ /*
961
+ * As per spec, the rate at which the source and the sink process
962
+ * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
963
+ * This depends upon the pixel clock rate and output formats
964
+ * (kslice adjust).
965
+ * If pixel clock * kslice adjust >= 2720MHz slices can be processed
966
+ * at max 340MHz, otherwise they can be processed at max 400MHz.
967
+ */
968
+
969
+ adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
970
+
971
+ if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
972
+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
973
+ else
974
+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
975
+
976
+ /*
977
+ * Taking into account the sink's capability for maximum
978
+ * clock per slice (in MHz) as read from HF-VSDB.
979
+ */
980
+ max_throughput = min(max_throughput, hdmi_throughput * 1000);
981
+
982
+ min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
983
+ max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
984
+
985
+ /*
986
+ * Keep on increasing the num of slices/line, starting from min_slices
987
+ * per line till we get such a number, for which the slice_width is
988
+ * just less than max_slice_width. The slices/line selected should be
989
+ * less than or equal to the max horizontal slices that the combination
990
+ * of PCON encoder and HDMI decoder can support.
991
+ */
992
+ do {
993
+ if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
994
+ target_slices = 1;
995
+ else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
996
+ target_slices = 2;
997
+ else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
998
+ target_slices = 4;
999
+ else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
1000
+ target_slices = 8;
1001
+ else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
1002
+ target_slices = 12;
1003
+ else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
1004
+ target_slices = 16;
1005
+ else
1006
+ return 0;
1007
+
1008
+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, target_slices);
1009
+ if (slice_width > max_slice_width)
1010
+ min_slices = target_slices + 1;
1011
+ } while (slice_width > max_slice_width);
1012
+
1013
+ return target_slices;
1014
+}
1015
+
1016
+static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
1017
+ struct drm_crtc_state *crtc_state)
1018
+{
1019
+ int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
1020
+ int hdmi_max_slices = hdmi->dsc_cap.max_slices;
1021
+ int rk_max_slices = 8;
1022
+ int rk_max_slice_width = 2048;
1023
+
1024
+ return hdmi_dsc_get_num_slices(hdmi, crtc_state, rk_max_slices,
1025
+ rk_max_slice_width,
1026
+ hdmi_max_slices, hdmi_throughput);
1027
+}
1028
+
1029
+static int
1030
+hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
1031
+ int slice_width, int num_slices, bool hdmi_all_bpp,
1032
+ int hdmi_max_chunk_bytes)
1033
+{
1034
+ int max_dsc_bpp, min_dsc_bpp;
1035
+ int target_bytes;
1036
+ bool bpp_found = false;
1037
+ int bpp_decrement_x16;
1038
+ int bpp_target;
1039
+ int bpp_target_x16;
1040
+
1041
+ /*
1042
+ * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
1043
+ * Start with the max bpp and keep on decrementing with
1044
+ * fractional bpp, if supported by PCON DSC encoder
1045
+ *
1046
+ * for each bpp we check if no of bytes can be supported by HDMI sink
1047
+ */
1048
+
1049
+ /* only 9\10\12 bpp was tested */
1050
+ min_dsc_bpp = 9;
1051
+ max_dsc_bpp = 12;
1052
+
1053
+ /*
1054
+ * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
1055
+ * Section 7.7.34 : Source shall not enable compressed Video
1056
+ * Transport with bpp_target settings above 12 bpp unless
1057
+ * DSC_all_bpp is set to 1.
1058
+ */
1059
+ if (!hdmi_all_bpp)
1060
+ max_dsc_bpp = min(max_dsc_bpp, 12);
1061
+
1062
+ /*
1063
+ * The Sink has a limit of compressed data in bytes for a scanline,
1064
+ * as described in max_chunk_bytes field in HFVSDB block of edid.
1065
+ * The no. of bytes depend on the target bits per pixel that the
1066
+ * source configures. So we start with the max_bpp and calculate
1067
+ * the target_chunk_bytes. We keep on decrementing the target_bpp,
1068
+ * till we get the target_chunk_bytes just less than what the sink's
1069
+ * max_chunk_bytes, or else till we reach the min_dsc_bpp.
1070
+ *
1071
+ * The decrement is according to the fractional support from PCON DSC
1072
+ * encoder. For fractional BPP we use bpp_target as a multiple of 16.
1073
+ *
1074
+ * bpp_target_x16 = bpp_target * 16
1075
+ * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
1076
+ * {1/16, 1/8, 1/4, 1/2, 1} respectively.
1077
+ */
1078
+
1079
+ bpp_target = max_dsc_bpp;
1080
+
1081
+ /* src does not support fractional bpp implies decrement by 16 for bppx16 */
1082
+ if (!src_fractional_bpp)
1083
+ src_fractional_bpp = 1;
1084
+ bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
1085
+ bpp_target_x16 = bpp_target * 16;
1086
+
1087
+ while (bpp_target_x16 > (min_dsc_bpp * 16)) {
1088
+ int bpp;
1089
+
1090
+ bpp = DIV_ROUND_UP(bpp_target_x16, 16);
1091
+ target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
1092
+ if (target_bytes <= hdmi_max_chunk_bytes) {
1093
+ bpp_found = true;
1094
+ break;
1095
+ }
1096
+ bpp_target_x16 -= bpp_decrement_x16;
1097
+ }
1098
+ if (bpp_found)
1099
+ return bpp_target_x16;
1100
+
1101
+ return 0;
1102
+}
1103
+
1104
+static int
1105
+dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
1106
+ int num_slices, int slice_width)
1107
+{
1108
+ bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
1109
+ int fractional_bpp = 0;
1110
+ int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
1111
+
1112
+ return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
1113
+ num_slices, hdmi_all_bpp,
1114
+ hdmi_max_chunk_bytes);
1115
+}
1116
+
1117
+static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
1118
+ u16 pic_width, u16 pic_height,
1119
+ u16 slice_width, u16 slice_height,
1120
+ u16 bits_per_pixel, u8 bits_per_component)
1121
+{
1122
+ int i;
1123
+
1124
+ for (i = 0; i < PPS_TABLE_LEN; i++)
1125
+ if (pic_width == pps_datas[i].pic_width &&
1126
+ pic_height == pps_datas[i].pic_height &&
1127
+ slice_width == pps_datas[i].slice_width &&
1128
+ slice_height == pps_datas[i].slice_height &&
1129
+ bits_per_component == pps_datas[i].bpc &&
1130
+ bits_per_pixel == pps_datas[i].bpp &&
1131
+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb)
1132
+ break;
1133
+
1134
+ if (i == PPS_TABLE_LEN) {
1135
+ dev_err(hdmi->dev, "can't find pps cfg!\n");
1136
+ return -EINVAL;
1137
+ }
1138
+
1139
+ memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
1140
+ hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
1141
+ (pic_width / slice_width);
1142
+
1143
+ return 0;
1144
+}
1145
+
1146
+static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
1147
+ struct rockchip_crtc_state *s,
1148
+ struct drm_crtc_state *crtc_state)
1149
+{
1150
+ int ret;
1151
+ int slice_height;
1152
+ int slice_width;
1153
+ int bits_per_pixel;
1154
+ int slice_count;
1155
+ bool hdmi_is_dsc_1_2;
1156
+ unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
1157
+
1158
+ if (!crtc_state)
1159
+ return;
1160
+
1161
+ hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
1162
+
1163
+ if (!hdmi_is_dsc_1_2)
1164
+ return;
1165
+
1166
+ slice_height = hdmi_dsc_get_slice_height(crtc_state->mode.vdisplay);
1167
+ if (!slice_height)
1168
+ return;
1169
+
1170
+ slice_count = hdmi_dsc_slices(hdmi, crtc_state);
1171
+ if (!slice_count)
1172
+ return;
1173
+
1174
+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, slice_count);
1175
+
1176
+ bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width);
1177
+ if (!bits_per_pixel)
1178
+ return;
1179
+
1180
+ ret = dw_hdmi_qp_set_link_cfg(hdmi, crtc_state->mode.hdisplay,
1181
+ crtc_state->mode.vdisplay, slice_width,
1182
+ slice_height, bits_per_pixel, depth);
1183
+
1184
+ if (ret) {
1185
+ dev_err(hdmi->dev, "set vdsc cfg failed\n");
1186
+ return;
1187
+ }
1188
+ dev_info(hdmi->dev, "dsc_enable\n");
1189
+ s->dsc_enable = 1;
1190
+ s->dsc_sink_cap.version_major = 1;
1191
+ s->dsc_sink_cap.version_minor = 2;
1192
+ s->dsc_sink_cap.slice_width = slice_width;
1193
+ s->dsc_sink_cap.slice_height = slice_height;
1194
+ s->dsc_sink_cap.target_bits_per_pixel_x16 = bits_per_pixel;
1195
+ s->dsc_sink_cap.block_pred = 1;
1196
+ s->dsc_sink_cap.native_420 = 0;
1197
+
1198
+ memcpy(&s->pps, hdmi->link_cfg.pps_payload, 128);
1199
+}
1200
+/////////////////////////////////////////////////////////////////////////////////////////
4621201
4631202 static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi,
4641203 u32 *config,
....@@ -484,6 +1223,150 @@
4841223 return 0;
4851224 }
4861225
1226
+static void repo_hpd_event(struct work_struct *p_work)
1227
+{
1228
+ struct rockchip_hdmi *hdmi = container_of(p_work, struct rockchip_hdmi, work.work);
1229
+ bool change;
1230
+
1231
+ change = drm_helper_hpd_irq_event(hdmi->drm_dev);
1232
+ if (change) {
1233
+ dev_dbg(hdmi->dev, "hpd stat changed:%d\n", hdmi->hpd_stat);
1234
+ dw_hdmi_qp_cec_set_hpd(hdmi->hdmi_qp, hdmi->hpd_stat, change);
1235
+ }
1236
+}
1237
+
1238
+static irqreturn_t rockchip_hdmi_hardirq(int irq, void *dev_id)
1239
+{
1240
+ struct rockchip_hdmi *hdmi = dev_id;
1241
+ u32 intr_stat, val;
1242
+
1243
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
1244
+
1245
+ if (intr_stat) {
1246
+ dev_dbg(hdmi->dev, "hpd irq %#x\n", intr_stat);
1247
+
1248
+ if (!hdmi->id)
1249
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK,
1250
+ RK3588_HDMI0_HPD_INT_MSK);
1251
+ else
1252
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK,
1253
+ RK3588_HDMI1_HPD_INT_MSK);
1254
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1255
+ return IRQ_WAKE_THREAD;
1256
+ }
1257
+
1258
+ return IRQ_NONE;
1259
+}
1260
+
1261
+static irqreturn_t rockchip_hdmi_irq(int irq, void *dev_id)
1262
+{
1263
+ struct rockchip_hdmi *hdmi = dev_id;
1264
+ u32 intr_stat, val;
1265
+ int msecs;
1266
+ bool stat;
1267
+
1268
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
1269
+
1270
+ if (!intr_stat)
1271
+ return IRQ_NONE;
1272
+
1273
+ if (!hdmi->id) {
1274
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
1275
+ RK3588_HDMI0_HPD_INT_CLR);
1276
+ if (intr_stat & RK3588_HDMI0_LEVEL_INT)
1277
+ stat = true;
1278
+ else
1279
+ stat = false;
1280
+ } else {
1281
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
1282
+ RK3588_HDMI1_HPD_INT_CLR);
1283
+ if (intr_stat & RK3588_HDMI1_LEVEL_INT)
1284
+ stat = true;
1285
+ else
1286
+ stat = false;
1287
+ }
1288
+
1289
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1290
+
1291
+ if (stat) {
1292
+ hdmi->hpd_stat = true;
1293
+ msecs = 150;
1294
+ } else {
1295
+ hdmi->hpd_stat = false;
1296
+ msecs = 20;
1297
+ }
1298
+ mod_delayed_work(hdmi->workqueue, &hdmi->work, msecs_to_jiffies(msecs));
1299
+
1300
+ if (!hdmi->id) {
1301
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
1302
+ RK3588_HDMI0_HPD_INT_CLR) |
1303
+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
1304
+ } else {
1305
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
1306
+ RK3588_HDMI1_HPD_INT_CLR) |
1307
+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK);
1308
+ }
1309
+
1310
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1311
+
1312
+ return IRQ_HANDLED;
1313
+}
1314
+
1315
+static void init_hpd_work(struct rockchip_hdmi *hdmi)
1316
+{
1317
+ hdmi->workqueue = create_workqueue("hpd_queue");
1318
+ INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event);
1319
+}
1320
+
1321
+static irqreturn_t rockchip_hdmi_hpd_irq_handler(int irq, void *arg)
1322
+{
1323
+ u32 val;
1324
+ struct rockchip_hdmi *hdmi = arg;
1325
+
1326
+ val = gpiod_get_value(hdmi->hpd_gpiod);
1327
+ if (val) {
1328
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET, RK3528_HDMI_SNKDET);
1329
+ if (hdmi->hdmi && hdmi->hpd_wake_en && hdmi->hpd_gpiod)
1330
+ dw_hdmi_set_hpd_wake(hdmi->hdmi);
1331
+ } else {
1332
+ val = HIWORD_UPDATE(0, RK3528_HDMI_SNKDET);
1333
+ }
1334
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
1335
+
1336
+ return IRQ_HANDLED;
1337
+}
1338
+
1339
+static void dw_hdmi_rk3528_gpio_hpd_init(struct rockchip_hdmi *hdmi)
1340
+{
1341
+ u32 val;
1342
+
1343
+ if (hdmi->hpd_gpiod) {
1344
+ /* gpio0_a2's input enable is controlled by gpio output data bit */
1345
+ val = HIWORD_UPDATE(RK3528_GPIO0_A2_DR, RK3528_GPIO0_A2_DR);
1346
+ writel(val, hdmi->gpio_base + RK3528_GPIO_SWPORT_DR_L);
1347
+
1348
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET_SEL | RK3528_HDMI_SDAIN_MSK |
1349
+ RK3528_HDMI_SCLIN_MSK,
1350
+ RK3528_HDMI_SNKDET_SEL | RK3528_HDMI_SDAIN_MSK |
1351
+ RK3528_HDMI_SCLIN_MSK);
1352
+ } else {
1353
+ val = HIWORD_UPDATE(RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK,
1354
+ RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK);
1355
+ }
1356
+
1357
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
1358
+
1359
+ val = gpiod_get_value(hdmi->hpd_gpiod);
1360
+ if (val) {
1361
+ val = HIWORD_UPDATE(RK3528_HDMI_SNKDET, RK3528_HDMI_SNKDET);
1362
+ if (hdmi->hdmi && hdmi->hpd_wake_en && hdmi->hpd_gpiod)
1363
+ dw_hdmi_set_hpd_wake(hdmi->hdmi);
1364
+ } else {
1365
+ val = HIWORD_UPDATE(0, RK3528_HDMI_SNKDET);
1366
+ }
1367
+ regmap_write(hdmi->regmap, RK3528_VO_GRF_HDMI_MASK, val);
1368
+}
1369
+
4871370 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
4881371 {
4891372 int ret, val, phy_table_size;
....@@ -494,6 +1377,14 @@
4941377 if (IS_ERR(hdmi->regmap)) {
4951378 DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n");
4961379 return PTR_ERR(hdmi->regmap);
1380
+ }
1381
+
1382
+ if (hdmi->is_hdmi_qp) {
1383
+ hdmi->vo1_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,vo1_grf");
1384
+ if (IS_ERR(hdmi->vo1_regmap)) {
1385
+ DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,vo1_grf\n");
1386
+ return PTR_ERR(hdmi->vo1_regmap);
1387
+ }
4971388 }
4981389
4991390 hdmi->phyref_clk = devm_clk_get(hdmi->dev, "vpll");
....@@ -539,20 +1430,63 @@
5391430 return PTR_ERR(hdmi->hclk_vop);
5401431 }
5411432
542
- ret = of_property_read_u32(np, "max-tmdsclk",
543
- &hdmi->max_tmdsclk);
544
- if (ret != -EINVAL && ret < 0) {
545
- DRM_DEV_ERROR(hdmi->dev, "incorrect max tmdsclk\n");
546
- return ret;
547
- } else if (ret == -EINVAL) {
548
- DRM_DEV_DEBUG(hdmi->dev,
549
- "max tmdsclk is not set, set to 594M\n");
550
- hdmi->max_tmdsclk = 594000;
1433
+ hdmi->aud_clk = devm_clk_get_optional(hdmi->dev, "aud");
1434
+ if (IS_ERR(hdmi->aud_clk)) {
1435
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->aud_clk),
1436
+ "failed to get aud_clk clock\n");
1437
+ return PTR_ERR(hdmi->aud_clk);
5511438 }
552
- hdmi->unsupported_yuv_input =
553
- of_property_read_bool(np, "unsupported-yuv-input");
554
- hdmi->unsupported_deep_color =
555
- of_property_read_bool(np, "unsupported-deep-color");
1439
+
1440
+ hdmi->hpd_clk = devm_clk_get_optional(hdmi->dev, "hpd");
1441
+ if (IS_ERR(hdmi->hpd_clk)) {
1442
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hpd_clk),
1443
+ "failed to get hpd_clk clock\n");
1444
+ return PTR_ERR(hdmi->hpd_clk);
1445
+ }
1446
+
1447
+ hdmi->hclk_vo1 = devm_clk_get_optional(hdmi->dev, "hclk_vo1");
1448
+ if (IS_ERR(hdmi->hclk_vo1)) {
1449
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hclk_vo1),
1450
+ "failed to get hclk_vo1 clock\n");
1451
+ return PTR_ERR(hdmi->hclk_vo1);
1452
+ }
1453
+
1454
+ hdmi->earc_clk = devm_clk_get_optional(hdmi->dev, "earc");
1455
+ if (IS_ERR(hdmi->earc_clk)) {
1456
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->earc_clk),
1457
+ "failed to get earc_clk clock\n");
1458
+ return PTR_ERR(hdmi->earc_clk);
1459
+ }
1460
+
1461
+ hdmi->hdmitx_ref = devm_clk_get_optional(hdmi->dev, "hdmitx_ref");
1462
+ if (IS_ERR(hdmi->hdmitx_ref)) {
1463
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmitx_ref),
1464
+ "failed to get hdmitx_ref clock\n");
1465
+ return PTR_ERR(hdmi->hdmitx_ref);
1466
+ }
1467
+
1468
+ hdmi->pclk = devm_clk_get_optional(hdmi->dev, "pclk");
1469
+ if (IS_ERR(hdmi->pclk)) {
1470
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->pclk),
1471
+ "failed to get pclk clock\n");
1472
+ return PTR_ERR(hdmi->pclk);
1473
+ }
1474
+
1475
+ hdmi->link_clk = devm_clk_get_optional(hdmi->dev, "link_clk");
1476
+ if (IS_ERR(hdmi->link_clk)) {
1477
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->link_clk),
1478
+ "failed to get link_clk clock\n");
1479
+ return PTR_ERR(hdmi->link_clk);
1480
+ }
1481
+
1482
+ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable",
1483
+ GPIOD_OUT_HIGH);
1484
+ if (IS_ERR(hdmi->enable_gpio)) {
1485
+ ret = PTR_ERR(hdmi->enable_gpio);
1486
+ dev_err(hdmi->dev, "failed to request enable GPIO: %d\n", ret);
1487
+ return ret;
1488
+ }
1489
+
5561490 hdmi->skip_check_420_mode =
5571491 of_property_read_bool(np, "skip-check-420-mode");
5581492
....@@ -578,13 +1512,79 @@
5781512 dev_dbg(hdmi->dev, "use default hdmi phy table\n");
5791513 }
5801514
1515
+ hdmi->hpd_gpiod = devm_gpiod_get_optional(hdmi->dev, "hpd", GPIOD_IN);
1516
+
1517
+ if (IS_ERR(hdmi->hpd_gpiod)) {
1518
+ dev_err(hdmi->dev, "error getting HDP GPIO: %ld\n",
1519
+ PTR_ERR(hdmi->hpd_gpiod));
1520
+ return PTR_ERR(hdmi->hpd_gpiod);
1521
+ }
1522
+
1523
+ if (hdmi->hpd_gpiod) {
1524
+ struct resource *res;
1525
+ struct platform_device *pdev = to_platform_device(hdmi->dev);
1526
+
1527
+ /* gpio interrupt reflects hpd status */
1528
+ hdmi->hpd_irq = gpiod_to_irq(hdmi->hpd_gpiod);
1529
+ if (hdmi->hpd_irq < 0)
1530
+ return -EINVAL;
1531
+
1532
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1533
+ if (!res) {
1534
+ DRM_DEV_ERROR(hdmi->dev, "failed to get gpio regs\n");
1535
+ return -EINVAL;
1536
+ }
1537
+
1538
+ hdmi->gpio_base = devm_ioremap(hdmi->dev, res->start, resource_size(res));
1539
+ if (IS_ERR(hdmi->gpio_base)) {
1540
+ DRM_DEV_ERROR(hdmi->dev, "Unable to get gpio ioregmap\n");
1541
+ return PTR_ERR(hdmi->gpio_base);
1542
+ }
1543
+
1544
+ dw_hdmi_rk3528_gpio_hpd_init(hdmi);
1545
+ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq, NULL,
1546
+ rockchip_hdmi_hpd_irq_handler,
1547
+ IRQF_TRIGGER_RISING |
1548
+ IRQF_TRIGGER_FALLING |
1549
+ IRQF_ONESHOT,
1550
+ "hdmi-hpd", hdmi);
1551
+ if (ret) {
1552
+ dev_err(hdmi->dev, "failed to request hpd IRQ: %d\n", ret);
1553
+ return ret;
1554
+ }
1555
+
1556
+ hdmi->hpd_wake_en = device_property_read_bool(hdmi->dev, "hpd-wake-up");
1557
+ if (hdmi->hpd_wake_en)
1558
+ enable_irq_wake(hdmi->hpd_irq);
1559
+ }
1560
+
1561
+ hdmi->p = devm_pinctrl_get(hdmi->dev);
1562
+ if (IS_ERR(hdmi->p)) {
1563
+ dev_err(hdmi->dev, "could not get pinctrl\n");
1564
+ return PTR_ERR(hdmi->p);
1565
+ }
1566
+
1567
+ hdmi->idle_state = pinctrl_lookup_state(hdmi->p, "idle");
1568
+ if (IS_ERR(hdmi->idle_state)) {
1569
+ dev_dbg(hdmi->dev, "idle state is not defined\n");
1570
+ return 0;
1571
+ }
1572
+
1573
+ hdmi->default_state = pinctrl_lookup_state(hdmi->p, "default");
1574
+ if (IS_ERR(hdmi->default_state)) {
1575
+ dev_err(hdmi->dev, "could not find default state\n");
1576
+ return PTR_ERR(hdmi->default_state);
1577
+ }
1578
+
5811579 return 0;
5821580 }
5831581
5841582 static enum drm_mode_status
585
-dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
1583
+dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
1584
+ const struct drm_display_info *info,
5861585 const struct drm_display_mode *mode)
5871586 {
1587
+ struct drm_connector *connector = container_of(info, struct drm_connector, display_info);
5881588 struct drm_encoder *encoder = connector->encoder;
5891589 enum drm_mode_status status = MODE_OK;
5901590 struct drm_device *dev = connector->dev;
....@@ -633,8 +1633,12 @@
6331633 return MODE_BAD;
6341634 };
6351635
636
- if (hdmi->phy)
637
- phy_set_bus_width(hdmi->phy, 8);
1636
+ if (hdmi->phy) {
1637
+ if (hdmi->is_hdmi_qp)
1638
+ phy_set_bus_width(hdmi->phy, mode->clock * 10);
1639
+ else
1640
+ phy_set_bus_width(hdmi->phy, 8);
1641
+ }
6381642
6391643 /*
6401644 * ensure all drm display mode can work, if someone want support more
....@@ -660,18 +1664,25 @@
6601664 return status;
6611665 }
6621666
663
-static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
664
- .destroy = drm_encoder_cleanup,
665
-};
666
-
6671667 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
6681668 {
6691669 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
6701670 struct drm_crtc *crtc = encoder->crtc;
6711671 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
6721672
673
- if (!hdmi->mode_changed)
674
- s->output_if &= ~VOP_OUTPUT_IF_HDMI0;
1673
+ if (WARN_ON(!crtc || !crtc->state))
1674
+ return;
1675
+
1676
+ if (crtc->state->active_changed) {
1677
+ if (hdmi->plat_data->split_mode) {
1678
+ s->output_if &= ~(VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1);
1679
+ } else {
1680
+ if (!hdmi->id)
1681
+ s->output_if &= ~VOP_OUTPUT_IF_HDMI0;
1682
+ else
1683
+ s->output_if &= ~VOP_OUTPUT_IF_HDMI1;
1684
+ }
1685
+ }
6751686 /*
6761687 * when plug out hdmi it will be switch cvbs and then phy bus width
6771688 * must be set as 8
....@@ -696,6 +1707,13 @@
6961707
6971708 clk_set_rate(hdmi->phyref_clk,
6981709 crtc->state->adjusted_mode.crtc_clock * 1000);
1710
+
1711
+ if (hdmi->is_hdmi_qp) {
1712
+ if (hdmi->link_cfg.frl_mode)
1713
+ gpiod_set_value(hdmi->enable_gpio, 0);
1714
+ else
1715
+ gpiod_set_value(hdmi->enable_gpio, 1);
1716
+ }
6991717
7001718 if (hdmi->chip_data->lcdsel_grf_reg < 0)
7011719 return;
....@@ -735,6 +1753,185 @@
7351753 ret ? "LIT" : "BIG");
7361754 }
7371755
1756
+static int _dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_hdmi *hdmi, bool on)
1757
+{
1758
+ int ret;
1759
+
1760
+ if (on) {
1761
+ if (hdmi->is_hdmi_qp) {
1762
+ ret = clk_prepare_enable(hdmi->link_clk);
1763
+ if (ret < 0) {
1764
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable link_clk %d\n", ret);
1765
+ return ret;
1766
+ }
1767
+ }
1768
+
1769
+ hdmi->phy->power_count++;
1770
+ } else {
1771
+ clk_disable_unprepare(hdmi->link_clk);
1772
+ hdmi->phy->power_count--;
1773
+ }
1774
+
1775
+ return 0;
1776
+}
1777
+
1778
+static int dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on)
1779
+{
1780
+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
1781
+ struct rockchip_hdmi *secondary;
1782
+
1783
+ _dw_hdmi_rockchip_encoder_loader_protect(hdmi, on);
1784
+ if (hdmi->plat_data->right) {
1785
+ secondary = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id);
1786
+ _dw_hdmi_rockchip_encoder_loader_protect(secondary, on);
1787
+ }
1788
+
1789
+ return 0;
1790
+}
1791
+
1792
+static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
1793
+{
1794
+ int val;
1795
+ bool is_hdmi0;
1796
+
1797
+ if (!hdmi->id)
1798
+ is_hdmi0 = true;
1799
+ else
1800
+ is_hdmi0 = false;
1801
+
1802
+ if (!hdmi->link_cfg.frl_mode) {
1803
+ val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
1804
+ if (is_hdmi0)
1805
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
1806
+ else
1807
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
1808
+
1809
+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1810
+ if (is_hdmi0)
1811
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1812
+ else
1813
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1814
+
1815
+ return;
1816
+ }
1817
+
1818
+ val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
1819
+ if (is_hdmi0)
1820
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
1821
+ else
1822
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
1823
+
1824
+ if (hdmi->link_cfg.dsc_mode) {
1825
+ val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
1826
+ RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1827
+ if (is_hdmi0)
1828
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1829
+ else
1830
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1831
+ } else {
1832
+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1833
+ if (is_hdmi0)
1834
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1835
+ else
1836
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1837
+ }
1838
+}
1839
+
1840
+static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1841
+ u32 depth)
1842
+{
1843
+ u32 val = 0;
1844
+
1845
+ switch (bus_format) {
1846
+ case MEDIA_BUS_FMT_RGB888_1X24:
1847
+ case MEDIA_BUS_FMT_RGB101010_1X30:
1848
+ val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
1849
+ break;
1850
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1851
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1852
+ val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
1853
+ break;
1854
+ case MEDIA_BUS_FMT_YUV8_1X24:
1855
+ case MEDIA_BUS_FMT_YUV10_1X30:
1856
+ val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
1857
+ break;
1858
+ case MEDIA_BUS_FMT_YUYV10_1X20:
1859
+ case MEDIA_BUS_FMT_YUYV8_1X16:
1860
+ val = HIWORD_UPDATE(RK3588_YUV422, RK3588_COLOR_FORMAT_MASK);
1861
+ break;
1862
+ default:
1863
+ dev_err(hdmi->dev, "can't set correct color format\n");
1864
+ return;
1865
+ }
1866
+
1867
+ if (hdmi->link_cfg.dsc_mode)
1868
+ val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
1869
+
1870
+ if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1871
+ val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
1872
+ else
1873
+ val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
1874
+
1875
+ if (!hdmi->id)
1876
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1877
+ else
1878
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1879
+}
1880
+
1881
+static void rk3588_set_grf_cfg(void *data)
1882
+{
1883
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1884
+ int color_depth;
1885
+
1886
+ rk3588_set_link_mode(hdmi);
1887
+ color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
1888
+ rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth);
1889
+}
1890
+
1891
+static u64 rk3588_get_grf_color_fmt(void *data)
1892
+{
1893
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1894
+ u32 val, depth;
1895
+ u64 bus_format;
1896
+
1897
+ if (!hdmi->id)
1898
+ regmap_read(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, &val);
1899
+ else
1900
+ regmap_read(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, &val);
1901
+
1902
+ depth = (val & RK3588_COLOR_DEPTH_MASK) >> 4;
1903
+
1904
+ switch (val & RK3588_COLOR_FORMAT_MASK) {
1905
+ case RK3588_YUV444:
1906
+ if (!depth)
1907
+ bus_format = MEDIA_BUS_FMT_YUV8_1X24;
1908
+ else
1909
+ bus_format = MEDIA_BUS_FMT_YUV10_1X30;
1910
+ break;
1911
+ case RK3588_YUV422:
1912
+ bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
1913
+ break;
1914
+ case RK3588_YUV420:
1915
+ if (!depth)
1916
+ bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
1917
+ else
1918
+ bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
1919
+ break;
1920
+ case RK3588_RGB:
1921
+ if (!depth)
1922
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
1923
+ else
1924
+ bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
1925
+ break;
1926
+ default:
1927
+ dev_err(hdmi->dev, "can't get correct color format\n");
1928
+ bus_format = MEDIA_BUS_FMT_YUV8_1X24;
1929
+ break;
1930
+ }
1931
+
1932
+ return bus_format;
1933
+}
1934
+
7381935 static void
7391936 dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state,
7401937 struct drm_crtc_state *crtc_state,
....@@ -747,65 +1944,81 @@
7471944 unsigned int *eotf)
7481945 {
7491946 struct drm_display_info *info = &conn_state->connector->display_info;
750
- struct drm_display_mode *mode = &crtc_state->mode;
1947
+ struct drm_display_mode mode;
7511948 struct hdr_output_metadata *hdr_metadata;
752
- u32 vic = drm_match_cea_mode(mode);
753
- unsigned long tmdsclock, pixclock = mode->crtc_clock;
1949
+ u32 vic;
1950
+ unsigned long tmdsclock, pixclock;
7541951 unsigned int color_depth;
7551952 bool support_dc = false;
756
- bool sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
757
- int max_tmds_clock = info->max_tmds_clock;
1953
+ bool sink_is_hdmi = true;
1954
+ bool yuv422_out = false;
1955
+ u32 max_tmds_clock = info->max_tmds_clock;
7581956 int output_eotf;
7591957
760
- *color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
1958
+ drm_mode_copy(&mode, &crtc_state->mode);
1959
+ pixclock = mode.crtc_clock;
1960
+ if (hdmi->plat_data->split_mode) {
1961
+ drm_mode_convert_to_origin_mode(&mode);
1962
+ pixclock /= 2;
1963
+ }
1964
+
1965
+ vic = drm_match_cea_mode(&mode);
1966
+
1967
+ if (!hdmi->is_hdmi_qp)
1968
+ sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
1969
+ else
1970
+ sink_is_hdmi = dw_hdmi_qp_get_output_whether_hdmi(hdmi->hdmi_qp);
1971
+
1972
+ *color_format = RK_IF_FORMAT_RGB;
7611973
7621974 switch (hdmi->hdmi_output) {
763
- case DRM_HDMI_OUTPUT_YCBCR_HQ:
1975
+ case RK_IF_FORMAT_YCBCR_HQ:
7641976 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
765
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
1977
+ *color_format = RK_IF_FORMAT_YCBCR444;
7661978 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
767
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
1979
+ *color_format = RK_IF_FORMAT_YCBCR422;
7681980 else if (conn_state->connector->ycbcr_420_allowed &&
769
- drm_mode_is_420(info, mode) && pixclock >= 594000)
770
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
1981
+ drm_mode_is_420(info, &mode) &&
1982
+ (pixclock >= 594000 && !hdmi->is_hdmi_qp))
1983
+ *color_format = RK_IF_FORMAT_YCBCR420;
7711984 break;
772
- case DRM_HDMI_OUTPUT_YCBCR_LQ:
1985
+ case RK_IF_FORMAT_YCBCR_LQ:
7731986 if (conn_state->connector->ycbcr_420_allowed &&
774
- drm_mode_is_420(info, mode) && pixclock >= 594000)
775
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
1987
+ drm_mode_is_420(info, &mode) && pixclock >= 594000)
1988
+ *color_format = RK_IF_FORMAT_YCBCR420;
7761989 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
777
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
1990
+ *color_format = RK_IF_FORMAT_YCBCR422;
7781991 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
779
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
1992
+ *color_format = RK_IF_FORMAT_YCBCR444;
7801993 break;
781
- case DRM_HDMI_OUTPUT_YCBCR420:
1994
+ case RK_IF_FORMAT_YCBCR420:
7821995 if (conn_state->connector->ycbcr_420_allowed &&
783
- drm_mode_is_420(info, mode) && pixclock >= 594000)
784
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
1996
+ drm_mode_is_420(info, &mode) && pixclock >= 594000)
1997
+ *color_format = RK_IF_FORMAT_YCBCR420;
7851998 break;
786
- case DRM_HDMI_OUTPUT_YCBCR422:
1999
+ case RK_IF_FORMAT_YCBCR422:
7872000 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
788
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2001
+ *color_format = RK_IF_FORMAT_YCBCR422;
7892002 break;
790
- case DRM_HDMI_OUTPUT_YCBCR444:
2003
+ case RK_IF_FORMAT_YCBCR444:
7912004 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
792
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
2005
+ *color_format = RK_IF_FORMAT_YCBCR444;
7932006 break;
794
- case DRM_HDMI_OUTPUT_DEFAULT_RGB:
2007
+ case RK_IF_FORMAT_RGB:
7952008 default:
7962009 break;
7972010 }
7982011
799
- if (*color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
2012
+ if (*color_format == RK_IF_FORMAT_RGB &&
8002013 info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
8012014 support_dc = true;
802
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
2015
+ if (*color_format == RK_IF_FORMAT_YCBCR444 &&
8032016 info->edid_hdmi_dc_modes &
8042017 (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30))
8052018 support_dc = true;
806
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422)
2019
+ if (*color_format == RK_IF_FORMAT_YCBCR422)
8072020 support_dc = true;
808
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
2021
+ if (*color_format == RK_IF_FORMAT_YCBCR420 &&
8092022 info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
8102023 support_dc = true;
8112024
....@@ -815,52 +2028,65 @@
8152028 color_depth = 8;
8162029
8172030 if (!sink_is_hdmi) {
818
- *color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
2031
+ *color_format = RK_IF_FORMAT_RGB;
8192032 color_depth = 8;
8202033 }
8212034
822
- *eotf = TRADITIONAL_GAMMA_SDR;
2035
+ *eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
8232036 if (conn_state->hdr_output_metadata) {
8242037 hdr_metadata = (struct hdr_output_metadata *)
8252038 conn_state->hdr_output_metadata->data;
8262039 output_eotf = hdr_metadata->hdmi_metadata_type1.eotf;
827
- if (output_eotf > TRADITIONAL_GAMMA_HDR &&
828
- output_eotf < FUTURE_EOTF)
2040
+ if (output_eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR &&
2041
+ output_eotf <= HDMI_EOTF_BT_2100_HLG)
8292042 *eotf = output_eotf;
8302043 }
8312044
832
- if ((*eotf > TRADITIONAL_GAMMA_HDR &&
833
- conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf &
834
- BIT(*eotf)) || (hdmi->colorimetry ==
835
- RK_HDMI_COLORIMETRY_BT2020 && info->hdmi.colorimetry &
836
- (BIT(6) | BIT(7))))
837
- *enc_out_encoding = V4L2_YCBCR_ENC_BT2020;
838
- else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
839
- (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18))
840
- *enc_out_encoding = V4L2_YCBCR_ENC_601;
841
- else
842
- *enc_out_encoding = V4L2_YCBCR_ENC_709;
2045
+ hdmi->colorimetry = conn_state->colorspace;
8432046
844
- if (*enc_out_encoding == V4L2_YCBCR_ENC_BT2020) {
845
- /* BT2020 require color depth at lest 10bit */
846
- color_depth = 10;
847
- /* We prefer use YCbCr422 to send 10bit */
848
- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
849
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2047
+ /* bt2020 sdr/hdr output */
2048
+ if ((hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_CYCC) &&
2049
+ (hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_YCC) &&
2050
+ hdmi->edid_colorimetry & (BIT(6) | BIT(7))) {
2051
+ *enc_out_encoding = V4L2_YCBCR_ENC_BT2020;
2052
+ yuv422_out = true;
2053
+ /* bt709 hdr output */
2054
+ } else if ((hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_CYCC) &&
2055
+ (hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_YCC) &&
2056
+ (conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & BIT(*eotf) &&
2057
+ *eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR)) {
2058
+ *enc_out_encoding = V4L2_YCBCR_ENC_709;
2059
+ yuv422_out = true;
2060
+ } else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
2061
+ (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) {
2062
+ *enc_out_encoding = V4L2_YCBCR_ENC_601;
2063
+ } else {
2064
+ *enc_out_encoding = V4L2_YCBCR_ENC_709;
8502065 }
8512066
852
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2067
+ if ((yuv422_out || hdmi->hdmi_output == RK_IF_FORMAT_YCBCR_HQ) && color_depth == 10 &&
2068
+ (hdmi_bus_fmt_color_depth(hdmi->prev_bus_format) == 8 ||
2069
+ hdmi_bus_fmt_to_color_format(hdmi->prev_bus_format) == RK_IF_FORMAT_YCBCR422)) {
2070
+ /* We prefer use YCbCr422 to send hdr 10bit */
2071
+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
2072
+ *color_format = RK_IF_FORMAT_YCBCR422;
2073
+ }
2074
+
2075
+ if (mode.flags & DRM_MODE_FLAG_DBLCLK)
8532076 pixclock *= 2;
854
- if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
2077
+ if ((mode.flags & DRM_MODE_FLAG_3D_MASK) ==
8552078 DRM_MODE_FLAG_3D_FRAME_PACKING)
8562079 pixclock *= 2;
8572080
858
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
2081
+ if (hdmi->is_hdmi_qp && mode.clock >= 600000)
2082
+ *color_format = RK_IF_FORMAT_YCBCR420;
2083
+
2084
+ if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8)
8592085 tmdsclock = pixclock;
8602086 else
8612087 tmdsclock = pixclock * (color_depth) / 8;
8622088
863
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420)
2089
+ if (*color_format == RK_IF_FORMAT_YCBCR420)
8642090 tmdsclock /= 2;
8652091
8662092 /* XXX: max_tmds_clock of some sink is 0, we think it is 340MHz. */
....@@ -869,67 +2095,76 @@
8692095
8702096 max_tmds_clock = min(max_tmds_clock, hdmi->max_tmdsclk);
8712097
2098
+ if (hdmi->is_hdmi_qp && hdmi->link_cfg.rate_per_lane && mode.clock > 600000)
2099
+ max_tmds_clock =
2100
+ hdmi->link_cfg.frl_lanes * hdmi->link_cfg.rate_per_lane * 1000000;
2101
+
8722102 if (tmdsclock > max_tmds_clock) {
8732103 if (max_tmds_clock >= 594000) {
8742104 color_depth = 8;
8752105 } else if (max_tmds_clock > 340000) {
876
- if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
877
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2106
+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000)
2107
+ *color_format = RK_IF_FORMAT_YCBCR420;
8782108 } else {
8792109 color_depth = 8;
880
- if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
881
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2110
+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000)
2111
+ *color_format = RK_IF_FORMAT_YCBCR420;
8822112 }
8832113 }
8842114
885
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420) {
2115
+ if (*color_format == RK_IF_FORMAT_YCBCR420) {
8862116 *output_mode = ROCKCHIP_OUT_MODE_YUV420;
8872117 if (color_depth > 8)
8882118 *bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
8892119 else
8902120 *bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
8912121 *bus_width = color_depth / 2;
892
- hdmi->output_bus_format = *bus_format;
8932122 } else {
8942123 *output_mode = ROCKCHIP_OUT_MODE_AAAA;
895
-
8962124 if (color_depth > 8) {
897
- if (*color_format != DRM_HDMI_OUTPUT_DEFAULT_RGB)
898
- hdmi->output_bus_format = MEDIA_BUS_FMT_YUV10_1X30;
899
- else
900
- hdmi->output_bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
901
-
902
- if (!hdmi->unsupported_yuv_input)
903
- *bus_format = hdmi->output_bus_format;
2125
+ if (*color_format != RK_IF_FORMAT_RGB &&
2126
+ !hdmi->unsupported_yuv_input)
2127
+ *bus_format = MEDIA_BUS_FMT_YUV10_1X30;
9042128 else
9052129 *bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
9062130 } else {
907
- if (*color_format != DRM_HDMI_OUTPUT_DEFAULT_RGB)
908
- hdmi->output_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
909
- else
910
- hdmi->output_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
911
-
912
- if (!hdmi->unsupported_yuv_input)
913
- *bus_format = hdmi->output_bus_format;
2131
+ if (*color_format != RK_IF_FORMAT_RGB &&
2132
+ !hdmi->unsupported_yuv_input)
2133
+ *bus_format = MEDIA_BUS_FMT_YUV8_1X24;
9142134 else
9152135 *bus_format = MEDIA_BUS_FMT_RGB888_1X24;
9162136 }
917
-
918
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422) {
2137
+ if (*color_format == RK_IF_FORMAT_YCBCR422)
9192138 *bus_width = 8;
2139
+ else
2140
+ *bus_width = color_depth;
2141
+ }
9202142
2143
+ hdmi->bus_format = *bus_format;
2144
+
2145
+ if (*color_format == RK_IF_FORMAT_YCBCR422) {
2146
+ if (hdmi->is_hdmi_qp) {
2147
+ if (color_depth == 12)
2148
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV12_1X24;
2149
+ else if (color_depth == 10)
2150
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
2151
+ else
2152
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
2153
+
2154
+ *bus_format = hdmi->output_bus_format;
2155
+ hdmi->bus_format = *bus_format;
2156
+ *output_mode = ROCKCHIP_OUT_MODE_YUV422;
2157
+ } else {
9212158 if (color_depth == 12)
9222159 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
9232160 else if (color_depth == 10)
9242161 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
9252162 else
9262163 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
927
- } else {
928
- *bus_width = color_depth;
9292164 }
2165
+ } else {
2166
+ hdmi->output_bus_format = *bus_format;
9302167 }
931
-
932
- hdmi->bus_format = *bus_format;
9332168 }
9342169
9352170 static bool
....@@ -963,49 +2198,101 @@
9632198 {
9642199 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
9652200 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
966
- unsigned int colorformat, bus_width;
2201
+ unsigned int colorformat, bus_width, tmdsclk;
2202
+ struct drm_display_mode mode;
9672203 unsigned int output_mode;
9682204 unsigned long bus_format;
2205
+ int color_depth;
2206
+ bool secondary = false;
2207
+
2208
+ /*
2209
+ * There are two hdmi but only one encoder in split mode,
2210
+ * so we need to check twice.
2211
+ */
2212
+secondary:
2213
+ drm_mode_copy(&mode, &crtc_state->mode);
2214
+
2215
+ if (hdmi->plat_data->split_mode)
2216
+ drm_mode_convert_to_origin_mode(&mode);
9692217
9702218 dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi,
9712219 &colorformat,
9722220 &output_mode, &bus_format, &bus_width,
9732221 &hdmi->enc_out_encoding, &s->eotf);
9742222
2223
+ s->bus_format = bus_format;
2224
+ if (hdmi->is_hdmi_qp) {
2225
+ color_depth = hdmi_bus_fmt_color_depth(bus_format);
2226
+ tmdsclk = hdmi_get_tmdsclock(hdmi, crtc_state->mode.clock);
2227
+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
2228
+ tmdsclk /= 2;
2229
+ hdmi_select_link_config(hdmi, crtc_state, tmdsclk);
2230
+
2231
+ if (hdmi->link_cfg.frl_mode) {
2232
+ /* in the current version, support max 40G frl */
2233
+ if (hdmi->link_cfg.rate_per_lane >= 10) {
2234
+ hdmi->link_cfg.frl_lanes = 4;
2235
+ hdmi->link_cfg.rate_per_lane = 10;
2236
+ }
2237
+ bus_width = hdmi->link_cfg.frl_lanes *
2238
+ hdmi->link_cfg.rate_per_lane * 1000000;
2239
+ /* 10 bit color depth and frl mode */
2240
+ if (color_depth == 10)
2241
+ bus_width |=
2242
+ COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
2243
+ else
2244
+ bus_width |= HDMI_FRL_MODE;
2245
+ } else {
2246
+ bus_width = hdmi_get_tmdsclock(hdmi, mode.clock * 10);
2247
+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
2248
+ bus_width /= 2;
2249
+
2250
+ if (color_depth == 10 && !hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format))
2251
+ bus_width |= COLOR_DEPTH_10BIT;
2252
+ }
2253
+ }
2254
+
9752255 hdmi->phy_bus_width = bus_width;
2256
+
9762257 if (hdmi->phy)
9772258 phy_set_bus_width(hdmi->phy, bus_width);
9782259
9792260 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
9802261 s->tv_state = &conn_state->tv;
981
- s->output_if |= VOP_OUTPUT_IF_HDMI0;
2262
+
2263
+ if (hdmi->plat_data->split_mode) {
2264
+ s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
2265
+ if (hdmi->plat_data->right && hdmi->id)
2266
+ s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP;
2267
+ s->output_if |= VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1;
2268
+ } else {
2269
+ if (!hdmi->id)
2270
+ s->output_if |= VOP_OUTPUT_IF_HDMI0;
2271
+ else
2272
+ s->output_if |= VOP_OUTPUT_IF_HDMI1;
2273
+ }
9822274
9832275 s->output_mode = output_mode;
984
- s->bus_format = bus_format;
9852276 hdmi->bus_format = s->bus_format;
986
-
987
- hdmi->mode_changed = crtc_state->mode_changed;
9882277
9892278 if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_BT2020)
9902279 s->color_space = V4L2_COLORSPACE_BT2020;
991
- else if (colorformat == DRM_HDMI_OUTPUT_DEFAULT_RGB)
2280
+ else if (colorformat == RK_IF_FORMAT_RGB)
9922281 s->color_space = V4L2_COLORSPACE_DEFAULT;
9932282 else if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_709)
9942283 s->color_space = V4L2_COLORSPACE_REC709;
9952284 else
9962285 s->color_space = V4L2_COLORSPACE_SMPTE170M;
9972286
2287
+ if (hdmi->plat_data->split_mode && !secondary) {
2288
+ hdmi = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id);
2289
+ secondary = true;
2290
+ goto secondary;
2291
+ }
2292
+
9982293 return 0;
9992294 }
10002295
1001
-static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
1002
- struct drm_display_mode *mode,
1003
- struct drm_display_mode *adj)
1004
-{
1005
- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
1006
-
1007
- clk_set_rate(hdmi->phyref_clk, adj->crtc_clock * 1000);
1008
-}
10092296
10102297 static unsigned long
10112298 dw_hdmi_rockchip_get_input_bus_format(void *data)
....@@ -1063,6 +2350,14 @@
10632350 return hdmi->hdr_panel_blob_ptr;
10642351 }
10652352
2353
+static void dw_hdmi_rockchip_update_color_format(struct drm_connector_state *conn_state,
2354
+ void *data)
2355
+{
2356
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2357
+
2358
+ dw_hdmi_rockchip_check_color(conn_state, hdmi);
2359
+}
2360
+
10662361 static bool
10672362 dw_hdmi_rockchip_get_color_changed(void *data)
10682363 {
....@@ -1076,6 +2371,186 @@
10762371 return ret;
10772372 }
10782373
2374
+static int
2375
+dw_hdmi_rockchip_get_yuv422_format(struct drm_connector *connector,
2376
+ struct edid *edid)
2377
+{
2378
+ if (!connector || !edid)
2379
+ return -EINVAL;
2380
+
2381
+ return rockchip_drm_get_yuv422_format(connector, edid);
2382
+}
2383
+
2384
+static int
2385
+dw_hdmi_rockchip_get_edid_dsc_info(void *data, struct edid *edid)
2386
+{
2387
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2388
+
2389
+ if (!edid)
2390
+ return -EINVAL;
2391
+
2392
+ memset(&hdmi->dsc_cap, 0, sizeof(hdmi->dsc_cap));
2393
+ hdmi->max_frl_rate_per_lane = 0;
2394
+ hdmi->max_lanes = 0;
2395
+ hdmi->add_func = 0;
2396
+
2397
+ return rockchip_drm_parse_cea_ext(&hdmi->dsc_cap,
2398
+ &hdmi->max_frl_rate_per_lane,
2399
+ &hdmi->max_lanes, &hdmi->add_func, edid);
2400
+}
2401
+
2402
+static int
2403
+dw_hdmi_rockchip_get_next_hdr_data(void *data, struct edid *edid,
2404
+ struct drm_connector *connector)
2405
+{
2406
+ int ret;
2407
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2408
+ struct next_hdr_sink_data *sink_data = &hdmi->next_hdr_data;
2409
+ size_t size = sizeof(*sink_data);
2410
+ struct drm_property *property = hdmi->next_hdr_sink_data_property;
2411
+ struct drm_property_blob *blob = hdmi->hdr_panel_blob_ptr;
2412
+
2413
+ if (!edid)
2414
+ return -EINVAL;
2415
+
2416
+ rockchip_drm_parse_next_hdr(sink_data, edid);
2417
+
2418
+ ret = drm_property_replace_global_blob(connector->dev, &blob, size, sink_data,
2419
+ &connector->base, property);
2420
+
2421
+ return ret;
2422
+};
2423
+
2424
+static int dw_hdmi_rockchip_get_colorimetry(void *data, struct edid *edid)
2425
+{
2426
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2427
+
2428
+ return rockchip_drm_parse_colorimetry_data_block(&hdmi->edid_colorimetry, edid);
2429
+}
2430
+
2431
+static
2432
+struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
2433
+{
2434
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2435
+
2436
+ return &hdmi->link_cfg;
2437
+}
2438
+
2439
+static int dw_hdmi_rockchip_get_vp_id(struct drm_crtc_state *crtc_state)
2440
+{
2441
+ struct rockchip_crtc_state *s;
2442
+
2443
+ s = to_rockchip_crtc_state(crtc_state);
2444
+
2445
+ return s->vp_id;
2446
+}
2447
+
2448
+static int dw_hdmi_dclk_set(void *data, bool enable, int vp_id)
2449
+{
2450
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2451
+ char clk_name[16];
2452
+ struct clk *dclk;
2453
+ int ret;
2454
+
2455
+ snprintf(clk_name, sizeof(clk_name), "dclk_vp%d", vp_id);
2456
+
2457
+ dclk = devm_clk_get_optional(hdmi->dev, clk_name);
2458
+ if (IS_ERR(dclk)) {
2459
+ DRM_DEV_ERROR(hdmi->dev, "failed to get %s\n", clk_name);
2460
+ return PTR_ERR(dclk);
2461
+ } else if (!dclk) {
2462
+ if (hdmi->is_hdmi_qp) {
2463
+ DRM_DEV_ERROR(hdmi->dev, "failed to get %s\n", clk_name);
2464
+ return -ENOENT;
2465
+ }
2466
+
2467
+ return 0;
2468
+ }
2469
+
2470
+ if (enable) {
2471
+ ret = clk_prepare_enable(dclk);
2472
+ if (ret < 0)
2473
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable dclk for video port%d - %d\n",
2474
+ vp_id, ret);
2475
+ } else {
2476
+ clk_disable_unprepare(dclk);
2477
+ }
2478
+
2479
+ return 0;
2480
+}
2481
+
2482
+static int dw_hdmi_link_clk_set(void *data, bool enable)
2483
+{
2484
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2485
+ u64 phy_clk = hdmi->phy_bus_width;
2486
+ int ret;
2487
+
2488
+ if (enable) {
2489
+ ret = clk_prepare_enable(hdmi->link_clk);
2490
+ if (ret < 0) {
2491
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable link_clk %d\n", ret);
2492
+ return ret;
2493
+ }
2494
+
2495
+ if (((phy_clk & DATA_RATE_MASK) <= 6000000) &&
2496
+ (phy_clk & COLOR_DEPTH_10BIT))
2497
+ phy_clk = (phy_clk & DATA_RATE_MASK) * 10 * 8;
2498
+ else
2499
+ phy_clk = (phy_clk & DATA_RATE_MASK) * 100;
2500
+
2501
+ /*
2502
+ * To be compatible with vop dclk usage scenarios, hdmi phy pll clk
2503
+ * is set according to dclk rate.
2504
+ * But phy pll actual frequency will varies according to the color depth.
2505
+ * So we should get the actual frequency or clk_set_rate may not change
2506
+ * pll frequency when 8/10 bit switch.
2507
+ */
2508
+ clk_get_rate(hdmi->link_clk);
2509
+ clk_set_rate(hdmi->link_clk, phy_clk);
2510
+ } else {
2511
+ clk_disable_unprepare(hdmi->link_clk);
2512
+ }
2513
+ return 0;
2514
+}
2515
+
2516
+static bool
2517
+dw_hdmi_rockchip_check_hdr_color_change(struct drm_connector_state *conn_state,
2518
+ void *data)
2519
+{
2520
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2521
+
2522
+ if (!conn_state || !data)
2523
+ return false;
2524
+
2525
+ if (dw_hdmi_rockchip_check_color(conn_state, hdmi))
2526
+ return true;
2527
+
2528
+ return false;
2529
+}
2530
+
2531
+static void dw_hdmi_rockchip_set_prev_bus_format(void *data, unsigned long bus_format)
2532
+{
2533
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2534
+
2535
+ hdmi->prev_bus_format = bus_format;
2536
+}
2537
+
2538
+static void dw_hdmi_rockchip_set_ddc_io(void *data, bool enable)
2539
+{
2540
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2541
+
2542
+ if (!hdmi->p || !hdmi->idle_state || !hdmi->default_state)
2543
+ return;
2544
+
2545
+ if (!enable) {
2546
+ if (pinctrl_select_state(hdmi->p, hdmi->idle_state))
2547
+ dev_err(hdmi->dev, "could not select idle state\n");
2548
+ } else {
2549
+ if (pinctrl_select_state(hdmi->p, hdmi->default_state))
2550
+ dev_err(hdmi->dev, "could not select default state\n");
2551
+ }
2552
+}
2553
+
10792554 static const struct drm_prop_enum_list color_depth_enum_list[] = {
10802555 { 0, "Automatic" }, /* Prefer highest color depth */
10812556 { 8, "24bit" },
....@@ -1083,24 +2558,19 @@
10832558 };
10842559
10852560 static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
1086
- { DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
1087
- { DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
1088
- { DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
1089
- { DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
1090
- { DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
1091
- { DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
1092
- { DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
2561
+ { RK_IF_FORMAT_RGB, "rgb" },
2562
+ { RK_IF_FORMAT_YCBCR444, "ycbcr444" },
2563
+ { RK_IF_FORMAT_YCBCR422, "ycbcr422" },
2564
+ { RK_IF_FORMAT_YCBCR420, "ycbcr420" },
2565
+ { RK_IF_FORMAT_YCBCR_HQ, "ycbcr_high_subsampling" },
2566
+ { RK_IF_FORMAT_YCBCR_LQ, "ycbcr_low_subsampling" },
2567
+ { RK_IF_FORMAT_MAX, "invalid_output" },
10932568 };
10942569
10952570 static const struct drm_prop_enum_list quant_range_enum_list[] = {
10962571 { HDMI_QUANTIZATION_RANGE_DEFAULT, "default" },
10972572 { HDMI_QUANTIZATION_RANGE_LIMITED, "limit" },
10982573 { HDMI_QUANTIZATION_RANGE_FULL, "full" },
1099
-};
1100
-
1101
-static const struct drm_prop_enum_list colorimetry_enum_list[] = {
1102
- { HDMI_COLORIMETRY_NONE, "None" },
1103
- { RK_HDMI_COLORIMETRY_BT2020, "ITU_2020" },
11042574 };
11052575
11062576 static const struct drm_prop_enum_list output_hdmi_dvi_enum_list[] = {
....@@ -1114,10 +2584,15 @@
11142584 { 1, "HDMI" },
11152585 };
11162586
2587
+static const struct drm_prop_enum_list allm_enable_list[] = {
2588
+ { 0, "disable" },
2589
+ { 1, "enable" },
2590
+};
2591
+
11172592 static void
11182593 dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
11192594 unsigned int color, int version,
1120
- void *data)
2595
+ void *data, bool allm_en)
11212596 {
11222597 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
11232598 struct drm_property *prop;
....@@ -1125,47 +2600,59 @@
11252600
11262601 switch (color) {
11272602 case MEDIA_BUS_FMT_RGB101010_1X30:
1128
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB;
2603
+ hdmi->hdmi_output = RK_IF_FORMAT_RGB;
11292604 hdmi->colordepth = 10;
11302605 break;
11312606 case MEDIA_BUS_FMT_YUV8_1X24:
1132
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444;
2607
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444;
11332608 hdmi->colordepth = 8;
11342609 break;
11352610 case MEDIA_BUS_FMT_YUV10_1X30:
1136
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444;
2611
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444;
11372612 hdmi->colordepth = 10;
11382613 break;
11392614 case MEDIA_BUS_FMT_UYVY10_1X20:
1140
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422;
2615
+ case MEDIA_BUS_FMT_YUYV10_1X20:
2616
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422;
11412617 hdmi->colordepth = 10;
11422618 break;
11432619 case MEDIA_BUS_FMT_UYVY8_1X16:
1144
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422;
2620
+ case MEDIA_BUS_FMT_YUYV8_1X16:
2621
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422;
11452622 hdmi->colordepth = 8;
11462623 break;
11472624 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1148
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
2625
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420;
11492626 hdmi->colordepth = 8;
11502627 break;
11512628 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1152
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
2629
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420;
11532630 hdmi->colordepth = 10;
11542631 break;
11552632 default:
1156
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB;
2633
+ hdmi->hdmi_output = RK_IF_FORMAT_RGB;
11572634 hdmi->colordepth = 8;
11582635 }
11592636
11602637 hdmi->bus_format = color;
2638
+ hdmi->prev_bus_format = color;
11612639
1162
- if (hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR422) {
1163
- if (hdmi->colordepth == 12)
1164
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
1165
- else if (hdmi->colordepth == 10)
1166
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
1167
- else
1168
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
2640
+ if (hdmi->hdmi_output == RK_IF_FORMAT_YCBCR422) {
2641
+ if (hdmi->is_hdmi_qp) {
2642
+ if (hdmi->colordepth == 12)
2643
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV12_1X24;
2644
+ else if (hdmi->colordepth == 10)
2645
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
2646
+ else
2647
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
2648
+ } else {
2649
+ if (hdmi->colordepth == 12)
2650
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
2651
+ else if (hdmi->colordepth == 10)
2652
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
2653
+ else
2654
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
2655
+ }
11692656 } else {
11702657 hdmi->output_bus_format = hdmi->bus_format;
11712658 }
....@@ -1173,7 +2660,7 @@
11732660 /* RK3368 does not support deep color mode */
11742661 if (!hdmi->color_depth_property && !hdmi->unsupported_deep_color) {
11752662 prop = drm_property_create_enum(connector->dev, 0,
1176
- "hdmi_output_depth",
2663
+ RK_IF_PROP_COLOR_DEPTH,
11772664 color_depth_enum_list,
11782665 ARRAY_SIZE(color_depth_enum_list));
11792666 if (prop) {
....@@ -1182,7 +2669,7 @@
11822669 }
11832670 }
11842671
1185
- prop = drm_property_create_enum(connector->dev, 0, "hdmi_output_format",
2672
+ prop = drm_property_create_enum(connector->dev, 0, RK_IF_PROP_COLOR_FORMAT,
11862673 drm_hdmi_output_enum_list,
11872674 ARRAY_SIZE(drm_hdmi_output_enum_list));
11882675 if (prop) {
....@@ -1190,17 +2677,8 @@
11902677 drm_object_attach_property(&connector->base, prop, 0);
11912678 }
11922679
1193
- prop = drm_property_create_enum(connector->dev, 0,
1194
- "hdmi_output_colorimetry",
1195
- colorimetry_enum_list,
1196
- ARRAY_SIZE(colorimetry_enum_list));
1197
- if (prop) {
1198
- hdmi->colorimetry_property = prop;
1199
- drm_object_attach_property(&connector->base, prop, 0);
1200
- }
1201
-
12022680 prop = drm_property_create_range(connector->dev, 0,
1203
- "hdmi_color_depth_capacity",
2681
+ RK_IF_PROP_COLOR_DEPTH_CAPS,
12042682 0, 0xff);
12052683 if (prop) {
12062684 hdmi->colordepth_capacity = prop;
....@@ -1208,22 +2686,12 @@
12082686 }
12092687
12102688 prop = drm_property_create_range(connector->dev, 0,
1211
- "hdmi_output_mode_capacity",
2689
+ RK_IF_PROP_COLOR_FORMAT_CAPS,
12122690 0, 0xf);
12132691 if (prop) {
12142692 hdmi->outputmode_capacity = prop;
12152693 drm_object_attach_property(&connector->base, prop, 0);
12162694 }
1217
-
1218
- prop = drm_property_create_enum(connector->dev, 0,
1219
- "hdmi_quant_range",
1220
- quant_range_enum_list,
1221
- ARRAY_SIZE(quant_range_enum_list));
1222
- if (prop) {
1223
- hdmi->quant_range = prop;
1224
- drm_object_attach_property(&connector->base, prop, 0);
1225
- }
1226
-
12272695
12282696 prop = drm_property_create(connector->dev,
12292697 DRM_MODE_PROP_BLOB |
....@@ -1233,6 +2701,40 @@
12332701 hdmi->hdr_panel_metadata_property = prop;
12342702 drm_object_attach_property(&connector->base, prop, 0);
12352703 }
2704
+
2705
+ prop = drm_property_create(connector->dev,
2706
+ DRM_MODE_PROP_BLOB |
2707
+ DRM_MODE_PROP_IMMUTABLE,
2708
+ "NEXT_HDR_SINK_DATA", 0);
2709
+ if (prop) {
2710
+ hdmi->next_hdr_sink_data_property = prop;
2711
+ drm_object_attach_property(&connector->base, prop, 0);
2712
+ }
2713
+
2714
+ prop = drm_property_create_bool(connector->dev, DRM_MODE_PROP_IMMUTABLE,
2715
+ "USER_SPLIT_MODE");
2716
+ if (prop) {
2717
+ hdmi->user_split_mode_prop = prop;
2718
+ drm_object_attach_property(&connector->base, prop,
2719
+ hdmi->user_split_mode ? 1 : 0);
2720
+ }
2721
+
2722
+ prop = drm_property_create_bool(connector->dev, 0, "allm_capacity");
2723
+ if (prop) {
2724
+ hdmi->allm_capacity = prop;
2725
+ drm_object_attach_property(&connector->base, prop,
2726
+ !!(hdmi->add_func & SUPPORT_HDMI_ALLM));
2727
+ }
2728
+
2729
+ prop = drm_property_create_enum(connector->dev, 0,
2730
+ "allm_enable",
2731
+ allm_enable_list,
2732
+ ARRAY_SIZE(allm_enable_list));
2733
+ if (prop) {
2734
+ hdmi->allm_enable = prop;
2735
+ drm_object_attach_property(&connector->base, prop, 0);
2736
+ }
2737
+ hdmi->enable_allm = allm_en;
12362738
12372739 prop = drm_property_create_enum(connector->dev, 0,
12382740 "output_hdmi_dvi",
....@@ -1244,18 +2746,33 @@
12442746 }
12452747
12462748 prop = drm_property_create_enum(connector->dev, 0,
1247
- "output_type_capacity",
1248
- output_type_cap_list,
1249
- ARRAY_SIZE(output_type_cap_list));
2749
+ "output_type_capacity",
2750
+ output_type_cap_list,
2751
+ ARRAY_SIZE(output_type_cap_list));
12502752 if (prop) {
12512753 hdmi->output_type_capacity = prop;
12522754 drm_object_attach_property(&connector->base, prop, 0);
12532755 }
12542756
2757
+ if (!hdmi->is_hdmi_qp) {
2758
+ prop = drm_property_create_enum(connector->dev, 0,
2759
+ "hdmi_quant_range",
2760
+ quant_range_enum_list,
2761
+ ARRAY_SIZE(quant_range_enum_list));
2762
+ if (prop) {
2763
+ hdmi->quant_range = prop;
2764
+ drm_object_attach_property(&connector->base, prop, 0);
2765
+ }
2766
+ }
2767
+
12552768 prop = connector->dev->mode_config.hdr_output_metadata_property;
1256
- if (version >= 0x211a)
2769
+ if (hdmi->is_hdmi_qp)
12572770 drm_object_attach_property(&connector->base, prop, 0);
1258
- drm_object_attach_property(&connector->base, private->connector_id_prop, 0);
2771
+
2772
+ if (!drm_mode_create_hdmi_colorspace_property(connector))
2773
+ drm_object_attach_property(&connector->base,
2774
+ connector->colorspace_property, 0);
2775
+ drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id);
12592776 }
12602777
12612778 static void
....@@ -1294,16 +2811,16 @@
12942811 hdmi->quant_range = NULL;
12952812 }
12962813
1297
- if (hdmi->colorimetry_property) {
1298
- drm_property_destroy(connector->dev,
1299
- hdmi->colorimetry_property);
1300
- hdmi->colordepth_capacity = NULL;
1301
- }
1302
-
13032814 if (hdmi->hdr_panel_metadata_property) {
13042815 drm_property_destroy(connector->dev,
13052816 hdmi->hdr_panel_metadata_property);
13062817 hdmi->hdr_panel_metadata_property = NULL;
2818
+ }
2819
+
2820
+ if (hdmi->next_hdr_sink_data_property) {
2821
+ drm_property_destroy(connector->dev,
2822
+ hdmi->next_hdr_sink_data_property);
2823
+ hdmi->next_hdr_sink_data_property = NULL;
13072824 }
13082825
13092826 if (hdmi->output_hdmi_dvi) {
....@@ -1316,6 +2833,23 @@
13162833 drm_property_destroy(connector->dev,
13172834 hdmi->output_type_capacity);
13182835 hdmi->output_type_capacity = NULL;
2836
+ }
2837
+
2838
+ if (hdmi->user_split_mode_prop) {
2839
+ drm_property_destroy(connector->dev,
2840
+ hdmi->user_split_mode_prop);
2841
+ hdmi->user_split_mode_prop = NULL;
2842
+ }
2843
+
2844
+ if (hdmi->allm_capacity) {
2845
+ drm_property_destroy(connector->dev,
2846
+ hdmi->allm_capacity);
2847
+ hdmi->allm_capacity = NULL;
2848
+ }
2849
+
2850
+ if (hdmi->allm_enable) {
2851
+ drm_property_destroy(connector->dev, hdmi->allm_enable);
2852
+ hdmi->allm_enable = NULL;
13192853 }
13202854 }
13212855
....@@ -1353,14 +2887,16 @@
13532887 return 0;
13542888 } else if (property == config->hdr_output_metadata_property) {
13552889 return 0;
1356
- } else if (property == hdmi->colorimetry_property) {
1357
- hdmi->colorimetry = val;
1358
- return 0;
13592890 } else if (property == hdmi->output_hdmi_dvi) {
1360
- if (hdmi->force_output != val)
1361
- hdmi->color_changed++;
1362
- hdmi->force_output = val;
1363
- dw_hdmi_set_output_type(hdmi->hdmi, val);
2891
+ if (!hdmi->is_hdmi_qp) {
2892
+ if (hdmi->force_output != val)
2893
+ hdmi->color_changed++;
2894
+ hdmi->force_output = val;
2895
+ dw_hdmi_set_output_type(hdmi->hdmi, val);
2896
+ } else {
2897
+ hdmi->force_output = val;
2898
+ dw_hdmi_qp_set_output_type(hdmi->hdmi_qp, val);
2899
+ }
13642900 return 0;
13652901 } else if (property == hdmi->colordepth_capacity) {
13662902 return 0;
....@@ -1368,9 +2904,20 @@
13682904 return 0;
13692905 } else if (property == hdmi->output_type_capacity) {
13702906 return 0;
2907
+ } else if (property == hdmi->allm_capacity) {
2908
+ return 0;
2909
+ } else if (property == hdmi->allm_enable) {
2910
+ u64 allm_enable = hdmi->enable_allm;
2911
+
2912
+ hdmi->enable_allm = val;
2913
+ if (allm_enable != hdmi->enable_allm)
2914
+ dw_hdmi_qp_set_allm_enable(hdmi->hdmi_qp, hdmi->enable_allm);
2915
+ return 0;
13712916 }
13722917
1373
- DRM_ERROR("failed to set rockchip hdmi connector property %s\n", property->name);
2918
+ DRM_ERROR("Unknown property [PROP:%d:%s]\n",
2919
+ property->base.id, property->name);
2920
+
13742921 return -EINVAL;
13752922 }
13762923
....@@ -1384,7 +2931,6 @@
13842931 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
13852932 struct drm_display_info *info = &connector->display_info;
13862933 struct drm_mode_config *config = &connector->dev->mode_config;
1387
- struct rockchip_drm_private *private = connector->dev->dev_private;
13882934
13892935 if (property == hdmi->color_depth_property) {
13902936 *val = hdmi->colordepth;
....@@ -1393,32 +2939,32 @@
13932939 *val = hdmi->hdmi_output;
13942940 return 0;
13952941 } else if (property == hdmi->colordepth_capacity) {
1396
- *val = BIT(ROCKCHIP_HDMI_DEPTH_8);
2942
+ *val = BIT(RK_IF_DEPTH_8);
13972943 /* RK3368 only support 8bit */
13982944 if (hdmi->unsupported_deep_color)
13992945 return 0;
14002946 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
1401
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_10);
2947
+ *val |= BIT(RK_IF_DEPTH_10);
14022948 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)
1403
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_12);
2949
+ *val |= BIT(RK_IF_DEPTH_12);
14042950 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_48)
1405
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_16);
2951
+ *val |= BIT(RK_IF_DEPTH_16);
14062952 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
1407
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_10);
2953
+ *val |= BIT(RK_IF_DEPTH_420_10);
14082954 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
1409
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_12);
2955
+ *val |= BIT(RK_IF_DEPTH_420_12);
14102956 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)
1411
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_16);
2957
+ *val |= BIT(RK_IF_DEPTH_420_16);
14122958 return 0;
14132959 } else if (property == hdmi->outputmode_capacity) {
1414
- *val = BIT(DRM_HDMI_OUTPUT_DEFAULT_RGB);
2960
+ *val = BIT(RK_IF_FORMAT_RGB);
14152961 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
1416
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR444);
2962
+ *val |= BIT(RK_IF_FORMAT_YCBCR444);
14172963 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
1418
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR422);
2964
+ *val |= BIT(RK_IF_FORMAT_YCBCR422);
14192965 if (connector->ycbcr_420_allowed &&
14202966 info->color_formats & DRM_COLOR_FORMAT_YCRCB420)
1421
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR420);
2967
+ *val |= BIT(RK_IF_FORMAT_YCBCR420);
14222968 return 0;
14232969 } else if (property == hdmi->quant_range) {
14242970 *val = hdmi->hdmi_quant_range;
....@@ -1427,21 +2973,29 @@
14272973 *val = state->hdr_output_metadata ?
14282974 state->hdr_output_metadata->base.id : 0;
14292975 return 0;
1430
- } else if (property == hdmi->colorimetry_property) {
1431
- *val = hdmi->colorimetry;
1432
- return 0;
1433
- } else if (property == private->connector_id_prop) {
1434
- *val = hdmi->id;
1435
- return 0;
14362976 } else if (property == hdmi->output_hdmi_dvi) {
14372977 *val = hdmi->force_output;
14382978 return 0;
14392979 } else if (property == hdmi->output_type_capacity) {
1440
- *val = dw_hdmi_get_output_type_cap(hdmi->hdmi);
2980
+ if (!hdmi->is_hdmi_qp)
2981
+ *val = dw_hdmi_get_output_type_cap(hdmi->hdmi);
2982
+ else
2983
+ *val = dw_hdmi_qp_get_output_type_cap(hdmi->hdmi_qp);
2984
+ return 0;
2985
+ } else if (property == hdmi->user_split_mode_prop) {
2986
+ *val = hdmi->user_split_mode;
2987
+ return 0;
2988
+ } else if (property == hdmi->allm_capacity) {
2989
+ *val = !!(hdmi->add_func & SUPPORT_HDMI_ALLM);
2990
+ return 0;
2991
+ } else if (property == hdmi->allm_enable) {
2992
+ *val = hdmi->enable_allm;
14412993 return 0;
14422994 }
14432995
1444
- DRM_ERROR("failed to get rockchip hdmi connector property %s\n", property->name);
2996
+ DRM_ERROR("Unknown property [PROP:%d:%s]\n",
2997
+ property->base.id, property->name);
2998
+
14452999 return -EINVAL;
14463000 }
14473001
....@@ -1452,6 +3006,36 @@
14523006 .get_property = dw_hdmi_rockchip_get_property,
14533007 };
14543008
3009
+static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
3010
+ struct drm_display_mode *mode,
3011
+ struct drm_display_mode *adj)
3012
+{
3013
+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
3014
+ struct drm_crtc *crtc;
3015
+ struct rockchip_crtc_state *s;
3016
+
3017
+ if (!encoder->crtc)
3018
+ return;
3019
+ crtc = encoder->crtc;
3020
+
3021
+ if (!crtc->state)
3022
+ return;
3023
+ s = to_rockchip_crtc_state(crtc->state);
3024
+
3025
+ if (!s)
3026
+ return;
3027
+
3028
+ if (hdmi->is_hdmi_qp) {
3029
+ s->dsc_enable = 0;
3030
+ if (hdmi->link_cfg.dsc_mode)
3031
+ dw_hdmi_qp_dsc_configure(hdmi, s, crtc->state);
3032
+
3033
+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
3034
+ }
3035
+
3036
+ clk_set_rate(hdmi->phyref_clk, adj->crtc_clock * 1000);
3037
+}
3038
+
14553039 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
14563040 .enable = dw_hdmi_rockchip_encoder_enable,
14573041 .disable = dw_hdmi_rockchip_encoder_disable,
....@@ -1459,7 +3043,8 @@
14593043 .mode_set = dw_hdmi_rockchip_encoder_mode_set,
14603044 };
14613045
1462
-static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
3046
+static void
3047
+dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
14633048 {
14643049 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
14653050
....@@ -1467,13 +3052,15 @@
14673052 phy_power_off(hdmi->phy);
14683053 }
14693054
1470
-static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
1471
- struct drm_display_mode *mode)
3055
+static int
3056
+dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
3057
+ const struct drm_display_info *display,
3058
+ const struct drm_display_mode *mode)
14723059 {
14733060 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
14743061
14753062 dw_hdmi_rockchip_genphy_disable(dw_hdmi, data);
1476
- dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi);
3063
+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display);
14773064 return phy_power_on(hdmi->phy);
14783065 }
14793066
....@@ -1483,10 +3070,17 @@
14833070
14843071 dw_hdmi_phy_setup_hpd(dw_hdmi, data);
14853072
1486
- regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2,
1487
- RK3228_DDC_MASK_EN);
1488
- regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6,
1489
- RK3228_IO_3V_DOMAIN);
3073
+ regmap_write(hdmi->regmap,
3074
+ RK3228_GRF_SOC_CON6,
3075
+ HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL |
3076
+ RK3228_HDMI_SCL_VSEL,
3077
+ RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL |
3078
+ RK3228_HDMI_SCL_VSEL));
3079
+
3080
+ regmap_write(hdmi->regmap,
3081
+ RK3228_GRF_SOC_CON2,
3082
+ HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK,
3083
+ RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK));
14903084 }
14913085
14923086 static enum drm_connector_status
....@@ -1534,6 +3128,90 @@
15343128 RK3328_HDMI_HPD_IOE));
15353129 }
15363130
3131
+static void dw_hdmi_qp_rockchip_phy_disable(struct dw_hdmi_qp *dw_hdmi,
3132
+ void *data)
3133
+{
3134
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3135
+
3136
+ while (hdmi->phy->power_count > 0)
3137
+ phy_power_off(hdmi->phy);
3138
+}
3139
+
3140
+static int dw_hdmi_qp_rockchip_genphy_init(struct dw_hdmi_qp *dw_hdmi, void *data,
3141
+ struct drm_display_mode *mode)
3142
+{
3143
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3144
+
3145
+ dw_hdmi_qp_rockchip_phy_disable(dw_hdmi, data);
3146
+
3147
+ return phy_power_on(hdmi->phy);
3148
+}
3149
+
3150
+static enum drm_connector_status
3151
+dw_hdmi_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
3152
+{
3153
+ u32 val;
3154
+ int ret;
3155
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3156
+
3157
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
3158
+
3159
+ if (!hdmi->id) {
3160
+ if (val & RK3588_HDMI0_LEVEL_INT) {
3161
+ hdmi->hpd_stat = true;
3162
+ ret = connector_status_connected;
3163
+ } else {
3164
+ hdmi->hpd_stat = false;
3165
+ ret = connector_status_disconnected;
3166
+ }
3167
+ } else {
3168
+ if (val & RK3588_HDMI1_LEVEL_INT) {
3169
+ hdmi->hpd_stat = true;
3170
+ ret = connector_status_connected;
3171
+ } else {
3172
+ hdmi->hpd_stat = false;
3173
+ ret = connector_status_disconnected;
3174
+ }
3175
+ }
3176
+
3177
+ return ret;
3178
+}
3179
+
3180
+static void dw_hdmi_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
3181
+{
3182
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3183
+ u32 val;
3184
+
3185
+ if (!hdmi->id) {
3186
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
3187
+ RK3588_HDMI0_HPD_INT_CLR) |
3188
+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
3189
+ } else {
3190
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
3191
+ RK3588_HDMI1_HPD_INT_CLR) |
3192
+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK);
3193
+ }
3194
+
3195
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
3196
+}
3197
+
3198
+static void dw_hdmi_rk3588_phy_set_mode(struct dw_hdmi_qp *dw_hdmi, void *data,
3199
+ u32 mode_mask, bool enable)
3200
+{
3201
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3202
+
3203
+ if (!hdmi->phy)
3204
+ return;
3205
+
3206
+ /* set phy earc/frl mode */
3207
+ if (enable)
3208
+ hdmi->phy_bus_width |= mode_mask;
3209
+ else
3210
+ hdmi->phy_bus_width &= ~mode_mask;
3211
+
3212
+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
3213
+}
3214
+
15373215 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = {
15383216 .init = dw_hdmi_rockchip_genphy_init,
15393217 .disable = dw_hdmi_rockchip_genphy_disable,
....@@ -1548,11 +3226,14 @@
15483226
15493227 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
15503228 .mode_valid = dw_hdmi_rockchip_mode_valid,
3229
+ .mpll_cfg = rockchip_mpll_cfg,
3230
+ .cur_ctr = rockchip_cur_ctr,
15513231 .phy_config = rockchip_phy_config,
1552
- .phy_data = &rk3228_chip_data,
1553
- .phy_ops = &rk3228_hdmi_phy_ops,
1554
- .phy_name = "inno_dw_hdmi_phy",
3232
+ .phy_data = &rk3228_chip_data,
3233
+ .phy_ops = &rk3228_hdmi_phy_ops,
3234
+ .phy_name = "inno_dw_hdmi_phy2",
15553235 .phy_force_vendor = true,
3236
+ .max_tmdsclk = 371250,
15563237 .ycbcr_420_allowed = true,
15573238 };
15583239
....@@ -1570,6 +3251,7 @@
15703251 .phy_config = rockchip_phy_config,
15713252 .phy_data = &rk3288_chip_data,
15723253 .tmds_n_table = rockchip_werid_tmds_n_table,
3254
+ .unsupported_yuv_input = true,
15733255 .ycbcr_420_allowed = true,
15743256 };
15753257
....@@ -1579,6 +3261,20 @@
15793261 .read_hpd = dw_hdmi_rk3328_read_hpd,
15803262 .update_hpd = dw_hdmi_phy_update_hpd,
15813263 .setup_hpd = dw_hdmi_rk3328_setup_hpd,
3264
+};
3265
+
3266
+static enum drm_connector_status
3267
+dw_hdmi_rk3528_read_hpd(struct dw_hdmi *dw_hdmi, void *data)
3268
+{
3269
+ return dw_hdmi_phy_read_hpd(dw_hdmi, data);
3270
+}
3271
+
3272
+static const struct dw_hdmi_phy_ops rk3528_hdmi_phy_ops = {
3273
+ .init = dw_hdmi_rockchip_genphy_init,
3274
+ .disable = dw_hdmi_rockchip_genphy_disable,
3275
+ .read_hpd = dw_hdmi_rk3528_read_hpd,
3276
+ .update_hpd = dw_hdmi_phy_update_hpd,
3277
+ .setup_hpd = dw_hdmi_phy_setup_hpd,
15823278 };
15833279
15843280 static struct rockchip_hdmi_chip_data rk3328_chip_data = {
....@@ -1594,6 +3290,8 @@
15943290 .phy_ops = &rk3328_hdmi_phy_ops,
15953291 .phy_name = "inno_dw_hdmi_phy2",
15963292 .phy_force_vendor = true,
3293
+ .use_drm_infoframe = true,
3294
+ .max_tmdsclk = 371250,
15973295 .ycbcr_420_allowed = true,
15983296 };
15993297
....@@ -1608,6 +3306,8 @@
16083306 .cur_ctr = rockchip_cur_ctr,
16093307 .phy_config = rockchip_phy_config,
16103308 .phy_data = &rk3368_chip_data,
3309
+ .unsupported_deep_color = true,
3310
+ .max_tmdsclk = 340000,
16113311 .ycbcr_420_allowed = true,
16123312 };
16133313
....@@ -1624,6 +3324,24 @@
16243324 .cur_ctr = rockchip_cur_ctr,
16253325 .phy_config = rockchip_phy_config,
16263326 .phy_data = &rk3399_chip_data,
3327
+ .use_drm_infoframe = true,
3328
+ .ycbcr_420_allowed = true,
3329
+};
3330
+
3331
+static struct rockchip_hdmi_chip_data rk3528_chip_data = {
3332
+ .lcdsel_grf_reg = -1,
3333
+};
3334
+
3335
+static const struct dw_hdmi_plat_data rk3528_hdmi_drv_data = {
3336
+ .mode_valid = dw_hdmi_rockchip_mode_valid,
3337
+ .mpll_cfg = rockchip_mpll_cfg,
3338
+ .cur_ctr = rockchip_cur_ctr,
3339
+ .phy_config = rockchip_phy_config,
3340
+ .phy_data = &rk3528_chip_data,
3341
+ .phy_ops = &rk3528_hdmi_phy_ops,
3342
+ .phy_name = "inno_dw_hdmi_phy2",
3343
+ .phy_force_vendor = true,
3344
+ .use_drm_infoframe = true,
16273345 .ycbcr_420_allowed = true,
16283346 };
16293347
....@@ -1634,12 +3352,37 @@
16343352
16353353 static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
16363354 .mode_valid = dw_hdmi_rockchip_mode_valid,
1637
- .mpll_cfg = rockchip_mpll_cfg_rk356x,
3355
+ .mpll_cfg = rockchip_mpll_cfg,
16383356 .mpll_cfg_420 = rockchip_mpll_cfg_420,
1639
- .cur_ctr = rockchip_cur_ctr_rk356x,
3357
+ .cur_ctr = rockchip_cur_ctr,
16403358 .phy_config = rockchip_phy_config,
16413359 .phy_data = &rk3568_chip_data,
16423360 .ycbcr_420_allowed = true,
3361
+ .use_drm_infoframe = true,
3362
+};
3363
+
3364
+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
3365
+ .init = dw_hdmi_qp_rockchip_genphy_init,
3366
+ .disable = dw_hdmi_qp_rockchip_phy_disable,
3367
+ .read_hpd = dw_hdmi_rk3588_read_hpd,
3368
+ .setup_hpd = dw_hdmi_rk3588_setup_hpd,
3369
+ .set_mode = dw_hdmi_rk3588_phy_set_mode,
3370
+};
3371
+
3372
+struct rockchip_hdmi_chip_data rk3588_hdmi_chip_data = {
3373
+ .lcdsel_grf_reg = -1,
3374
+ .ddc_en_reg = RK3588_GRF_VO1_CON3,
3375
+ .split_mode = true,
3376
+};
3377
+
3378
+static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
3379
+ .phy_data = &rk3588_hdmi_chip_data,
3380
+ .qp_phy_ops = &rk3588_hdmi_phy_ops,
3381
+ .phy_name = "samsung_hdptx_phy",
3382
+ .phy_force_vendor = true,
3383
+ .ycbcr_420_allowed = true,
3384
+ .is_hdmi_qp = true,
3385
+ .use_drm_infoframe = true,
16433386 };
16443387
16453388 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
....@@ -1659,8 +3402,14 @@
16593402 { .compatible = "rockchip,rk3399-dw-hdmi",
16603403 .data = &rk3399_hdmi_drv_data
16613404 },
3405
+ { .compatible = "rockchip,rk3528-dw-hdmi",
3406
+ .data = &rk3528_hdmi_drv_data
3407
+ },
16623408 { .compatible = "rockchip,rk3568-dw-hdmi",
16633409 .data = &rk3568_hdmi_drv_data
3410
+ },
3411
+ { .compatible = "rockchip,rk3588-dw-hdmi",
3412
+ .data = &rk3588_hdmi_drv_data
16643413 },
16653414 {},
16663415 };
....@@ -1670,32 +3419,24 @@
16703419 void *data)
16713420 {
16723421 struct platform_device *pdev = to_platform_device(dev);
1673
- struct dw_hdmi_plat_data *plat_data;
1674
- const struct of_device_id *match;
16753422 struct drm_device *drm = data;
16763423 struct drm_encoder *encoder;
16773424 struct rockchip_hdmi *hdmi;
1678
- int ret, id;
3425
+ struct dw_hdmi_plat_data *plat_data;
3426
+ struct rockchip_hdmi *secondary;
3427
+ int ret;
3428
+ u32 val;
16793429
16803430 if (!pdev->dev.of_node)
16813431 return -ENODEV;
16823432
1683
- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
3433
+ hdmi = platform_get_drvdata(pdev);
16843434 if (!hdmi)
16853435 return -ENOMEM;
16863436
1687
- match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
1688
- plat_data = devm_kmemdup(&pdev->dev, match->data,
1689
- sizeof(*plat_data), GFP_KERNEL);
1690
- if (!plat_data)
1691
- return -ENOMEM;
3437
+ plat_data = hdmi->plat_data;
3438
+ hdmi->drm_dev = drm;
16923439
1693
- id = of_alias_get_id(dev->of_node, "hdmi");
1694
- if (id < 0)
1695
- id = 0;
1696
- hdmi->id = id;
1697
- hdmi->dev = &pdev->dev;
1698
- hdmi->chip_data = plat_data->phy_data;
16993440 plat_data->phy_data = hdmi;
17003441 plat_data->get_input_bus_format =
17013442 dw_hdmi_rockchip_get_input_bus_format;
....@@ -1713,23 +3454,123 @@
17133454 dw_hdmi_rockchip_get_hdr_blob;
17143455 plat_data->get_color_changed =
17153456 dw_hdmi_rockchip_get_color_changed;
3457
+ plat_data->get_yuv422_format =
3458
+ dw_hdmi_rockchip_get_yuv422_format;
3459
+ plat_data->get_edid_dsc_info =
3460
+ dw_hdmi_rockchip_get_edid_dsc_info;
3461
+ plat_data->get_next_hdr_data =
3462
+ dw_hdmi_rockchip_get_next_hdr_data;
3463
+ plat_data->get_colorimetry =
3464
+ dw_hdmi_rockchip_get_colorimetry;
3465
+ plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg;
3466
+ plat_data->set_grf_cfg = rk3588_set_grf_cfg;
3467
+ plat_data->get_grf_color_fmt = rk3588_get_grf_color_fmt;
3468
+ plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode;
3469
+ plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode;
3470
+ plat_data->dclk_set = dw_hdmi_dclk_set;
3471
+ plat_data->link_clk_set = dw_hdmi_link_clk_set;
3472
+ plat_data->get_vp_id = dw_hdmi_rockchip_get_vp_id;
3473
+ plat_data->update_color_format =
3474
+ dw_hdmi_rockchip_update_color_format;
3475
+ plat_data->check_hdr_color_change =
3476
+ dw_hdmi_rockchip_check_hdr_color_change;
3477
+ plat_data->set_prev_bus_format =
3478
+ dw_hdmi_rockchip_set_prev_bus_format;
3479
+ plat_data->set_ddc_io =
3480
+ dw_hdmi_rockchip_set_ddc_io;
17163481 plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
17173482
1718
- encoder = &hdmi->encoder;
3483
+ secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id);
3484
+ /* If don't enable hdmi0 and hdmi1, we don't enable split mode */
3485
+ if (hdmi->chip_data->split_mode && secondary) {
17193486
1720
- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
1721
- /*
1722
- * If we failed to find the CRTC(s) which this encoder is
1723
- * supposed to be connected to, it's because the CRTC has
1724
- * not been registered yet. Defer probing, and hope that
1725
- * the required CRTC is added later.
1726
- */
1727
- if (encoder->possible_crtcs == 0)
1728
- return -EPROBE_DEFER;
3487
+ /*
3488
+ * hdmi can only attach bridge and init encoder/connector in the
3489
+ * last bind hdmi in split mode, or hdmi->hdmi_qp will not be initialized
3490
+ * and plat_data->left/right will be null pointer. we must check if split
3491
+ * mode is on and determine the sequence of hdmi bind.
3492
+ */
3493
+ if (device_property_read_bool(dev, "split-mode") ||
3494
+ device_property_read_bool(secondary->dev, "split-mode")) {
3495
+ plat_data->split_mode = true;
3496
+ secondary->plat_data->split_mode = true;
3497
+ if (!secondary->plat_data->first_screen)
3498
+ plat_data->first_screen = true;
3499
+ }
3500
+
3501
+ if (device_property_read_bool(dev, "user-split-mode") ||
3502
+ device_property_read_bool(secondary->dev, "user-split-mode")) {
3503
+ hdmi->user_split_mode = true;
3504
+ secondary->user_split_mode = true;
3505
+ }
3506
+ }
3507
+
3508
+ if (!plat_data->first_screen) {
3509
+ encoder = &hdmi->encoder;
3510
+ encoder->possible_crtcs = rockchip_drm_of_find_possible_crtcs(drm, dev->of_node);
3511
+ /*
3512
+ * If we failed to find the CRTC(s) which this encoder is
3513
+ * supposed to be connected to, it's because the CRTC has
3514
+ * not been registered yet. Defer probing, and hope that
3515
+ * the required CRTC is added later.
3516
+ */
3517
+ if (encoder->possible_crtcs == 0)
3518
+ return -EPROBE_DEFER;
3519
+
3520
+ drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
3521
+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
3522
+ }
3523
+
3524
+ if (!plat_data->max_tmdsclk)
3525
+ hdmi->max_tmdsclk = 594000;
3526
+ else
3527
+ hdmi->max_tmdsclk = plat_data->max_tmdsclk;
3528
+
3529
+ hdmi->is_hdmi_qp = plat_data->is_hdmi_qp;
3530
+
3531
+ hdmi->unsupported_yuv_input = plat_data->unsupported_yuv_input;
3532
+ hdmi->unsupported_deep_color = plat_data->unsupported_deep_color;
17293533
17303534 ret = rockchip_hdmi_parse_dt(hdmi);
17313535 if (ret) {
17323536 DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
3537
+ return ret;
3538
+ }
3539
+
3540
+ ret = clk_prepare_enable(hdmi->aud_clk);
3541
+ if (ret) {
3542
+ dev_err(hdmi->dev, "Failed to enable HDMI aud_clk: %d\n", ret);
3543
+ return ret;
3544
+ }
3545
+
3546
+ ret = clk_prepare_enable(hdmi->hpd_clk);
3547
+ if (ret) {
3548
+ dev_err(hdmi->dev, "Failed to enable HDMI hpd_clk: %d\n", ret);
3549
+ return ret;
3550
+ }
3551
+
3552
+ ret = clk_prepare_enable(hdmi->hclk_vo1);
3553
+ if (ret) {
3554
+ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vo1: %d\n", ret);
3555
+ return ret;
3556
+ }
3557
+
3558
+ ret = clk_prepare_enable(hdmi->earc_clk);
3559
+ if (ret) {
3560
+ dev_err(hdmi->dev, "Failed to enable HDMI earc_clk: %d\n", ret);
3561
+ return ret;
3562
+ }
3563
+
3564
+ ret = clk_prepare_enable(hdmi->hdmitx_ref);
3565
+ if (ret) {
3566
+ dev_err(hdmi->dev, "Failed to enable HDMI hdmitx_ref: %d\n",
3567
+ ret);
3568
+ return ret;
3569
+ }
3570
+
3571
+ ret = clk_prepare_enable(hdmi->pclk);
3572
+ if (ret) {
3573
+ dev_err(hdmi->dev, "Failed to enable HDMI pclk: %d\n", ret);
17333574 return ret;
17343575 }
17353576
....@@ -1739,6 +3580,39 @@
17393580 RK3568_HDMI_SCLIN_MSK,
17403581 RK3568_HDMI_SDAIN_MSK |
17413582 RK3568_HDMI_SCLIN_MSK));
3583
+ }
3584
+
3585
+ if (hdmi->is_hdmi_qp) {
3586
+ if (!hdmi->id) {
3587
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3588
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3589
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3590
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3591
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
3592
+
3593
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3594
+ RK3588_SET_HPD_PATH_MASK);
3595
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3596
+
3597
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
3598
+ RK3588_HDMI0_GRANT_SEL);
3599
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3600
+ } else {
3601
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3602
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3603
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3604
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3605
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
3606
+
3607
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3608
+ RK3588_SET_HPD_PATH_MASK);
3609
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3610
+
3611
+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
3612
+ RK3588_HDMI1_GRANT_SEL);
3613
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3614
+ }
3615
+ init_hpd_work(hdmi);
17423616 }
17433617
17443618 ret = clk_prepare_enable(hdmi->phyref_clk);
....@@ -1762,6 +3636,26 @@
17623636 return ret;
17633637 }
17643638
3639
+ if (hdmi->is_hdmi_qp) {
3640
+ if (!hdmi->id)
3641
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
3642
+ else
3643
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK);
3644
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
3645
+
3646
+ hdmi->hpd_irq = platform_get_irq(pdev, 4);
3647
+ if (hdmi->hpd_irq < 0)
3648
+ return hdmi->hpd_irq;
3649
+
3650
+ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq,
3651
+ rockchip_hdmi_hardirq,
3652
+ rockchip_hdmi_irq,
3653
+ IRQF_SHARED, "dw-hdmi-qp-hpd",
3654
+ hdmi);
3655
+ if (ret)
3656
+ return ret;
3657
+ }
3658
+
17653659 hdmi->phy = devm_phy_optional_get(dev, "hdmi");
17663660 if (IS_ERR(hdmi->phy)) {
17673661 hdmi->phy = devm_phy_optional_get(dev, "hdmi_phy");
....@@ -1773,13 +3667,39 @@
17733667 }
17743668 }
17753669
1776
- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
1777
- drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
1778
- DRM_MODE_ENCODER_TMDS, NULL);
3670
+ if (hdmi->is_hdmi_qp) {
3671
+ hdmi->hdmi_qp = dw_hdmi_qp_bind(pdev, &hdmi->encoder, plat_data);
17793672
1780
- platform_set_drvdata(pdev, hdmi);
3673
+ if (IS_ERR(hdmi->hdmi_qp)) {
3674
+ ret = PTR_ERR(hdmi->hdmi_qp);
3675
+ drm_encoder_cleanup(&hdmi->encoder);
3676
+ }
17813677
1782
- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
3678
+ if (plat_data->connector) {
3679
+ hdmi->sub_dev.connector = plat_data->connector;
3680
+ hdmi->sub_dev.loader_protect = dw_hdmi_rockchip_encoder_loader_protect;
3681
+ if (secondary && device_property_read_bool(secondary->dev, "split-mode"))
3682
+ hdmi->sub_dev.of_node = secondary->dev->of_node;
3683
+ else
3684
+ hdmi->sub_dev.of_node = hdmi->dev->of_node;
3685
+
3686
+ rockchip_drm_register_sub_dev(&hdmi->sub_dev);
3687
+ }
3688
+
3689
+ if (plat_data->split_mode && secondary) {
3690
+ if (device_property_read_bool(dev, "split-mode")) {
3691
+ plat_data->right = secondary->hdmi_qp;
3692
+ secondary->plat_data->left = hdmi->hdmi_qp;
3693
+ } else {
3694
+ plat_data->left = secondary->hdmi_qp;
3695
+ secondary->plat_data->right = hdmi->hdmi_qp;
3696
+ }
3697
+ }
3698
+
3699
+ return ret;
3700
+ }
3701
+
3702
+ hdmi->hdmi = dw_hdmi_bind(pdev, &hdmi->encoder, plat_data);
17833703
17843704 /*
17853705 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
....@@ -1787,9 +3707,15 @@
17873707 */
17883708 if (IS_ERR(hdmi->hdmi)) {
17893709 ret = PTR_ERR(hdmi->hdmi);
1790
- drm_encoder_cleanup(encoder);
3710
+ drm_encoder_cleanup(&hdmi->encoder);
3711
+ clk_disable_unprepare(hdmi->aud_clk);
17913712 clk_disable_unprepare(hdmi->phyref_clk);
17923713 clk_disable_unprepare(hdmi->hclk_vop);
3714
+ clk_disable_unprepare(hdmi->hpd_clk);
3715
+ clk_disable_unprepare(hdmi->hclk_vo1);
3716
+ clk_disable_unprepare(hdmi->earc_clk);
3717
+ clk_disable_unprepare(hdmi->hdmitx_ref);
3718
+ clk_disable_unprepare(hdmi->pclk);
17933719 }
17943720
17953721 if (plat_data->connector) {
....@@ -1806,11 +3732,27 @@
18063732 {
18073733 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
18083734
3735
+ if (hdmi->is_hdmi_qp) {
3736
+ cancel_delayed_work(&hdmi->work);
3737
+ flush_workqueue(hdmi->workqueue);
3738
+ destroy_workqueue(hdmi->workqueue);
3739
+ }
3740
+
18093741 if (hdmi->sub_dev.connector)
18103742 rockchip_drm_unregister_sub_dev(&hdmi->sub_dev);
1811
- dw_hdmi_unbind(hdmi->hdmi);
3743
+
3744
+ if (hdmi->is_hdmi_qp)
3745
+ dw_hdmi_qp_unbind(hdmi->hdmi_qp);
3746
+ else
3747
+ dw_hdmi_unbind(hdmi->hdmi);
3748
+ clk_disable_unprepare(hdmi->aud_clk);
18123749 clk_disable_unprepare(hdmi->phyref_clk);
18133750 clk_disable_unprepare(hdmi->hclk_vop);
3751
+ clk_disable_unprepare(hdmi->hpd_clk);
3752
+ clk_disable_unprepare(hdmi->hclk_vo1);
3753
+ clk_disable_unprepare(hdmi->earc_clk);
3754
+ clk_disable_unprepare(hdmi->hdmitx_ref);
3755
+ clk_disable_unprepare(hdmi->pclk);
18143756 }
18153757
18163758 static const struct component_ops dw_hdmi_rockchip_ops = {
....@@ -1820,6 +3762,33 @@
18203762
18213763 static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
18223764 {
3765
+ struct rockchip_hdmi *hdmi;
3766
+ const struct of_device_id *match;
3767
+ struct dw_hdmi_plat_data *plat_data;
3768
+ int id;
3769
+
3770
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
3771
+ if (!hdmi)
3772
+ return -ENOMEM;
3773
+
3774
+ id = of_alias_get_id(pdev->dev.of_node, "hdmi");
3775
+ if (id < 0)
3776
+ id = 0;
3777
+
3778
+ hdmi->id = id;
3779
+ hdmi->dev = &pdev->dev;
3780
+
3781
+ match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
3782
+ plat_data = devm_kmemdup(&pdev->dev, match->data,
3783
+ sizeof(*plat_data), GFP_KERNEL);
3784
+ if (!plat_data)
3785
+ return -ENOMEM;
3786
+
3787
+ plat_data->id = hdmi->id;
3788
+ hdmi->plat_data = plat_data;
3789
+ hdmi->chip_data = plat_data->phy_data;
3790
+
3791
+ platform_set_drvdata(pdev, hdmi);
18233792 pm_runtime_enable(&pdev->dev);
18243793 pm_runtime_get_sync(&pdev->dev);
18253794
....@@ -1828,12 +3797,25 @@
18283797
18293798 static void dw_hdmi_rockchip_shutdown(struct platform_device *pdev)
18303799 {
1831
- struct rockchip_hdmi *hdmi = platform_get_drvdata(pdev);
3800
+ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
18323801
18333802 if (!hdmi)
18343803 return;
18353804
1836
- dw_hdmi_suspend(&pdev->dev, hdmi->hdmi);
3805
+ if (hdmi->is_hdmi_qp) {
3806
+ if (hdmi->hpd_irq)
3807
+ disable_irq(hdmi->hpd_irq);
3808
+ cancel_delayed_work(&hdmi->work);
3809
+ flush_workqueue(hdmi->workqueue);
3810
+ dw_hdmi_qp_suspend(hdmi->dev, hdmi->hdmi_qp);
3811
+ } else {
3812
+ if (hdmi->hpd_gpiod) {
3813
+ disable_irq(hdmi->hpd_irq);
3814
+ if (hdmi->hpd_wake_en)
3815
+ disable_irq_wake(hdmi->hpd_irq);
3816
+ }
3817
+ dw_hdmi_suspend(hdmi->hdmi);
3818
+ }
18373819 pm_runtime_put_sync(&pdev->dev);
18383820 }
18393821
....@@ -1849,7 +3831,15 @@
18493831 {
18503832 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
18513833
1852
- dw_hdmi_suspend(dev, hdmi->hdmi);
3834
+ if (hdmi->is_hdmi_qp) {
3835
+ if (hdmi->hpd_irq)
3836
+ disable_irq(hdmi->hpd_irq);
3837
+ dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp);
3838
+ } else {
3839
+ if (hdmi->hpd_gpiod)
3840
+ disable_irq(hdmi->hpd_irq);
3841
+ dw_hdmi_suspend(hdmi->hdmi);
3842
+ }
18533843 pm_runtime_put_sync(dev);
18543844
18553845 return 0;
....@@ -1858,14 +3848,56 @@
18583848 static int dw_hdmi_rockchip_resume(struct device *dev)
18593849 {
18603850 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
3851
+ u32 val;
18613852
3853
+ if (hdmi->is_hdmi_qp) {
3854
+ if (!hdmi->id) {
3855
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3856
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3857
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3858
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3859
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
3860
+
3861
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3862
+ RK3588_SET_HPD_PATH_MASK);
3863
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3864
+
3865
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
3866
+ RK3588_HDMI0_GRANT_SEL);
3867
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3868
+ } else {
3869
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3870
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3871
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3872
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3873
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
3874
+
3875
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3876
+ RK3588_SET_HPD_PATH_MASK);
3877
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3878
+
3879
+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
3880
+ RK3588_HDMI1_GRANT_SEL);
3881
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3882
+ }
3883
+
3884
+ dw_hdmi_qp_resume(dev, hdmi->hdmi_qp);
3885
+ if (hdmi->hpd_irq)
3886
+ enable_irq(hdmi->hpd_irq);
3887
+ drm_helper_hpd_irq_event(hdmi->drm_dev);
3888
+ } else {
3889
+ if (hdmi->hpd_gpiod) {
3890
+ dw_hdmi_rk3528_gpio_hpd_init(hdmi);
3891
+ enable_irq(hdmi->hpd_irq);
3892
+ }
3893
+ dw_hdmi_resume(hdmi->hdmi);
3894
+ }
18623895 pm_runtime_get_sync(dev);
1863
- dw_hdmi_resume(dev, hdmi->hdmi);
18643896
1865
- return 0;
3897
+ return 0;
18663898 }
18673899
1868
-static const struct dev_pm_ops dw_hdmi_pm_ops = {
3900
+static const struct dev_pm_ops dw_hdmi_rockchip_pm = {
18693901 SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend,
18703902 dw_hdmi_rockchip_resume)
18713903 };
....@@ -1876,7 +3908,7 @@
18763908 .shutdown = dw_hdmi_rockchip_shutdown,
18773909 .driver = {
18783910 .name = "dwhdmi-rockchip",
3911
+ .pm = &dw_hdmi_rockchip_pm,
18793912 .of_match_table = dw_hdmi_rockchip_dt_ids,
1880
- .pm = &dw_hdmi_pm_ops,
18813913 },
18823914 };