hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
....@@ -1,10 +1,6 @@
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>
....@@ -18,20 +14,30 @@
1814 #include <linux/pm_runtime.h>
1915
2016 #include <drm/drm_of.h>
21
-#include <drm/drmP.h>
2217 #include <drm/drm_crtc_helper.h>
18
+#include <drm/drm_dsc.h>
2319 #include <drm/drm_edid.h>
20
+#include <drm/drm_hdcp.h>
2421 #include <drm/bridge/dw_hdmi.h>
22
+#include <drm/drm_edid.h>
23
+#include <drm/drm_of.h>
24
+#include <drm/drm_probe_helper.h>
25
+#include <drm/drm_simple_kms_helper.h>
2526
2627 #include <uapi/linux/videodev2.h>
2728
2829 #include "rockchip_drm_drv.h"
2930 #include "rockchip_drm_vop.h"
3031
32
+#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
33
+
3134 #define RK3228_GRF_SOC_CON2 0x0408
32
-#define RK3228_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16)))
35
+#define RK3228_HDMI_SDAIN_MSK BIT(14)
36
+#define RK3228_HDMI_SCLIN_MSK BIT(13)
3337 #define RK3228_GRF_SOC_CON6 0x0418
34
-#define RK3228_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16)))
38
+#define RK3228_HDMI_HPD_VSEL BIT(6)
39
+#define RK3228_HDMI_SDA_VSEL BIT(5)
40
+#define RK3228_HDMI_SCL_VSEL BIT(4)
3541
3642 #define RK3288_GRF_SOC_CON6 0x025C
3743 #define RK3288_HDMI_LCDC_SEL BIT(4)
....@@ -79,9 +85,65 @@
7985 #define RK3568_HDMI_SDAIN_MSK BIT(15)
8086 #define RK3568_HDMI_SCLIN_MSK BIT(14)
8187
82
-#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
83
-#define RK_HDMI_COLORIMETRY_BT2020 (HDMI_COLORIMETRY_EXTENDED + \
84
- HDMI_EXTENDED_COLORIMETRY_BT2020)
88
+#define RK3588_GRF_SOC_CON2 0x0308
89
+#define RK3588_HDMI1_HPD_INT_MSK BIT(15)
90
+#define RK3588_HDMI1_HPD_INT_CLR BIT(14)
91
+#define RK3588_HDMI0_HPD_INT_MSK BIT(13)
92
+#define RK3588_HDMI0_HPD_INT_CLR BIT(12)
93
+#define RK3588_GRF_SOC_CON7 0x031c
94
+#define RK3588_SET_HPD_PATH_MASK (0x3 << 12)
95
+#define RK3588_GRF_SOC_STATUS1 0x0384
96
+#define RK3588_HDMI0_LOW_MORETHAN100MS BIT(20)
97
+#define RK3588_HDMI0_HPD_PORT_LEVEL BIT(19)
98
+#define RK3588_HDMI0_IHPD_PORT BIT(18)
99
+#define RK3588_HDMI0_OHPD_INT BIT(17)
100
+#define RK3588_HDMI0_LEVEL_INT BIT(16)
101
+#define RK3588_HDMI0_INTR_CHANGE_CNT (0x7 << 13)
102
+#define RK3588_HDMI1_LOW_MORETHAN100MS BIT(28)
103
+#define RK3588_HDMI1_HPD_PORT_LEVEL BIT(27)
104
+#define RK3588_HDMI1_IHPD_PORT BIT(26)
105
+#define RK3588_HDMI1_OHPD_INT BIT(25)
106
+#define RK3588_HDMI1_LEVEL_INT BIT(24)
107
+#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21)
108
+
109
+#define RK3588_GRF_VO1_CON1 0x0004
110
+#define HDCP1_P1_GPIO_IN BIT(9)
111
+#define RK3588_GRF_VO1_CON3 0x000c
112
+#define RK3588_COLOR_FORMAT_MASK 0xf
113
+#define RK3588_RGB 0
114
+#define RK3588_YUV422 0x1
115
+#define RK3588_YUV444 0x2
116
+#define RK3588_YUV420 0x3
117
+#define RK3588_COMPRESSED_DATA 0xb
118
+#define RK3588_COLOR_DEPTH_MASK (0xf << 4)
119
+#define RK3588_8BPC 0
120
+#define RK3588_10BPC (0x6 << 4)
121
+#define RK3588_CECIN_MASK BIT(8)
122
+#define RK3588_SCLIN_MASK BIT(9)
123
+#define RK3588_SDAIN_MASK BIT(10)
124
+#define RK3588_MODE_MASK BIT(11)
125
+#define RK3588_COMPRESS_MODE_MASK BIT(12)
126
+#define RK3588_I2S_SEL_MASK BIT(13)
127
+#define RK3588_SPDIF_SEL_MASK BIT(14)
128
+#define RK3588_GRF_VO1_CON4 0x0010
129
+#define RK3588_HDMI21_MASK BIT(0)
130
+#define RK3588_GRF_VO1_CON9 0x0024
131
+#define RK3588_HDMI0_GRANT_SEL BIT(10)
132
+#define RK3588_HDMI0_GRANT_SW BIT(11)
133
+#define RK3588_HDMI1_GRANT_SEL BIT(12)
134
+#define RK3588_HDMI1_GRANT_SW BIT(13)
135
+#define RK3588_GRF_VO1_CON4 0x0010
136
+#define RK3588_HDMI_HDCP14_MEM_EN BIT(15)
137
+#define RK3588_GRF_VO1_CON6 0x0018
138
+#define RK3588_GRF_VO1_CON7 0x001c
139
+
140
+#define COLOR_DEPTH_10BIT BIT(31)
141
+#define HDMI_FRL_MODE BIT(30)
142
+#define HDMI_EARC_MODE BIT(29)
143
+#define DATA_RATE_MASK 0xFFFFFFF
144
+
145
+#define HDMI20_MAX_RATE 600000
146
+#define HDMI_8K60_RATE 2376000
85147
86148 /**
87149 * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips
....@@ -95,82 +157,99 @@
95157 int ddc_en_reg;
96158 u32 lcdsel_big;
97159 u32 lcdsel_lit;
160
+ bool split_mode;
98161 };
99162
100
-/* HDMI output pixel format */
101
-enum drm_hdmi_output_type {
102
- DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
103
- DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
104
- DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
105
- DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
106
- DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
107
- DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
108
- DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
109
-};
110
-
111
-enum dw_hdmi_rockchip_color_depth {
112
- ROCKCHIP_HDMI_DEPTH_8,
113
- ROCKCHIP_HDMI_DEPTH_10,
114
- ROCKCHIP_HDMI_DEPTH_12,
115
- ROCKCHIP_HDMI_DEPTH_16,
116
- ROCKCHIP_HDMI_DEPTH_420_10,
117
- ROCKCHIP_HDMI_DEPTH_420_12,
118
- ROCKCHIP_HDMI_DEPTH_420_16
163
+enum hdmi_frl_rate_per_lane {
164
+ FRL_12G_PER_LANE = 12,
165
+ FRL_10G_PER_LANE = 10,
166
+ FRL_8G_PER_LANE = 8,
167
+ FRL_6G_PER_LANE = 6,
168
+ FRL_3G_PER_LANE = 3,
119169 };
120170
121171 struct rockchip_hdmi {
122172 struct device *dev;
123173 struct regmap *regmap;
174
+ struct regmap *vo1_regmap;
124175 void __iomem *gpio_base;
125176 struct drm_encoder encoder;
177
+ struct drm_device *drm_dev;
126178 const struct rockchip_hdmi_chip_data *chip_data;
179
+ struct dw_hdmi_plat_data *plat_data;
180
+ struct clk *aud_clk;
127181 struct clk *phyref_clk;
128182 struct clk *grf_clk;
129183 struct clk *hclk_vio;
184
+ struct clk *hclk_vo1;
130185 struct clk *hclk_vop;
131
- struct clk *dclk_vop;
186
+ struct clk *hpd_clk;
187
+ struct clk *pclk;
188
+ struct clk *earc_clk;
189
+ struct clk *hdmitx_ref;
190
+ struct clk *link_clk;
132191 struct dw_hdmi *hdmi;
192
+ struct dw_hdmi_qp *hdmi_qp;
133193
134194 struct phy *phy;
135
- int max_tmdsclk;
195
+
196
+ u32 max_tmdsclk;
136197 bool unsupported_yuv_input;
137198 bool unsupported_deep_color;
138199 bool skip_check_420_mode;
139
- bool mode_changed;
140200 bool hpd_wake_en;
141201 u8 force_output;
142202 u8 id;
203
+ bool hpd_stat;
204
+ bool is_hdmi_qp;
143205
144206 unsigned long bus_format;
145207 unsigned long output_bus_format;
146208 unsigned long enc_out_encoding;
147209 unsigned long prev_bus_format;
148210 int color_changed;
211
+ int hpd_irq;
149212
150213 struct drm_property *color_depth_property;
151214 struct drm_property *hdmi_output_property;
152215 struct drm_property *colordepth_capacity;
153216 struct drm_property *outputmode_capacity;
154
- struct drm_property *colorimetry_property;
155217 struct drm_property *quant_range;
156218 struct drm_property *hdr_panel_metadata_property;
219
+ struct drm_property *next_hdr_sink_data_property;
157220 struct drm_property *output_hdmi_dvi;
158221 struct drm_property *output_type_capacity;
222
+ struct drm_property *allm_capacity;
223
+ struct drm_property *allm_enable;
224
+ struct drm_property *hdcp_state_property;
159225
160226 struct drm_property_blob *hdr_panel_blob_ptr;
227
+ struct drm_property_blob *next_hdr_data_ptr;
161228
162229 unsigned int colordepth;
163230 unsigned int colorimetry;
164231 unsigned int hdmi_quant_range;
165232 unsigned int phy_bus_width;
166
- enum drm_hdmi_output_type hdmi_output;
233
+ unsigned int enable_allm;
234
+ enum rk_if_color_format hdmi_output;
167235 struct rockchip_drm_sub_dev sub_dev;
168236
237
+ u8 max_frl_rate_per_lane;
238
+ u8 max_lanes;
239
+ u8 add_func;
240
+ u8 edid_colorimetry;
241
+ u8 hdcp_status;
242
+ struct rockchip_drm_dsc_cap dsc_cap;
243
+ struct next_hdr_sink_data next_hdr_data;
244
+ struct dw_hdmi_link_config link_cfg;
245
+ struct gpio_desc *enable_gpio;
246
+
247
+ struct delayed_work work;
248
+ struct workqueue_struct *workqueue;
169249 struct gpio_desc *hpd_gpiod;
170250 struct pinctrl *p;
171251 struct pinctrl_state *idle_state;
172252 struct pinctrl_state *default_state;
173
- int hpd_irq;
174253 };
175254
176255 #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
....@@ -288,94 +367,6 @@
288367 }
289368 };
290369
291
-static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_rk356x[] = {
292
- {
293
- 30666000, {
294
- { 0x00b3, 0x0000 },
295
- { 0x2153, 0x0000 },
296
- { 0x40f3, 0x0000 },
297
- },
298
- }, {
299
- 36800000, {
300
- { 0x00b3, 0x0000 },
301
- { 0x2153, 0x0000 },
302
- { 0x40a2, 0x0001 },
303
- },
304
- }, {
305
- 46000000, {
306
- { 0x00b3, 0x0000 },
307
- { 0x2142, 0x0001 },
308
- { 0x40a2, 0x0001 },
309
- },
310
- }, {
311
- 61333000, {
312
- { 0x0072, 0x0001 },
313
- { 0x2142, 0x0001 },
314
- { 0x40a2, 0x0001 },
315
- },
316
- }, {
317
- 73600000, {
318
- { 0x0072, 0x0001 },
319
- { 0x2142, 0x0001 },
320
- { 0x4061, 0x0002 },
321
- },
322
- }, {
323
- 92000000, {
324
- { 0x0072, 0x0001 },
325
- { 0x2145, 0x0002 },
326
- { 0x4061, 0x0002 },
327
- },
328
- }, {
329
- 122666000, {
330
- { 0x0051, 0x0002 },
331
- { 0x2145, 0x0002 },
332
- { 0x4061, 0x0002 },
333
- },
334
- }, {
335
- 147200000, {
336
- { 0x0051, 0x0002 },
337
- { 0x2145, 0x0002 },
338
- { 0x4064, 0x0003 },
339
- },
340
- }, {
341
- 184000000, {
342
- { 0x0051, 0x0002 },
343
- { 0x214c, 0x0003 },
344
- { 0x4064, 0x0003 },
345
- },
346
- }, {
347
- 226666000, {
348
- { 0x0040, 0x0003 },
349
- { 0x214c, 0x0003 },
350
- { 0x4064, 0x0003 },
351
- },
352
- }, {
353
- 272000000, {
354
- { 0x0040, 0x0003 },
355
- { 0x214c, 0x0003 },
356
- { 0x5a64, 0x0003 },
357
- },
358
- }, {
359
- 340000000, {
360
- { 0x0040, 0x0002 },
361
- { 0x3b4c, 0x0003 },
362
- { 0x5a64, 0x0003 },
363
- },
364
- }, {
365
- 600000000, {
366
- { 0x1a40, 0x0003 },
367
- { 0x3b4c, 0x0003 },
368
- { 0x5a64, 0x0003 },
369
- },
370
- }, {
371
- ~0UL, {
372
- { 0x0000, 0x0000 },
373
- { 0x0000, 0x0000 },
374
- { 0x0000, 0x0000 },
375
- },
376
- }
377
-};
378
-
379370 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = {
380371 {
381372 30666000, {
....@@ -465,19 +456,6 @@
465456 }
466457 };
467458
468
-static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr_rk356x[] = {
469
- /* pixelclk bpp8 bpp10 bpp12 */
470
- {
471
- 272000000, { 0x0000, 0x0000, 0x0000 },
472
- }, {
473
- 340000000, { 0x0001, 0x0000, 0x0000 },
474
- }, {
475
- 600000000, { 0x0000, 0x0000, 0x0000 },
476
- }, {
477
- ~0UL, { 0x0000, 0x0000, 0x0000},
478
- }
479
-};
480
-
481459 static struct dw_hdmi_phy_config rockchip_phy_config[] = {
482460 /*pixelclk symbol term vlev*/
483461 { 74250000, 0x8009, 0x0004, 0x0272},
....@@ -488,24 +466,301 @@
488466 { ~0UL, 0x0000, 0x0000, 0x0000},
489467 };
490468
469
+enum ROW_INDEX_BPP {
470
+ ROW_INDEX_6BPP = 0,
471
+ ROW_INDEX_8BPP,
472
+ ROW_INDEX_10BPP,
473
+ ROW_INDEX_12BPP,
474
+ ROW_INDEX_23BPP,
475
+ MAX_ROW_INDEX
476
+};
477
+
478
+enum COLUMN_INDEX_BPC {
479
+ COLUMN_INDEX_8BPC = 0,
480
+ COLUMN_INDEX_10BPC,
481
+ COLUMN_INDEX_12BPC,
482
+ COLUMN_INDEX_14BPC,
483
+ COLUMN_INDEX_16BPC,
484
+ MAX_COLUMN_INDEX
485
+};
486
+
487
+#define PPS_TABLE_LEN 8
488
+#define PPS_BPP_LEN 4
489
+#define PPS_BPC_LEN 2
490
+
491
+struct pps_data {
492
+ u32 pic_width;
493
+ u32 pic_height;
494
+ u32 slice_width;
495
+ u32 slice_height;
496
+ bool convert_rgb;
497
+ u8 bpc;
498
+ u8 bpp;
499
+ u8 raw_pps[128];
500
+};
501
+
502
+/*
503
+ * Selected Rate Control Related Parameter Recommended Values
504
+ * from DSC_v1.11 spec & C Model release: DSC_model_20161212
505
+ */
506
+static struct pps_data pps_datas[PPS_TABLE_LEN] = {
507
+ {
508
+ /* 7680x4320/960X96 rgb 8bpc 12bpp */
509
+ 7680, 4320, 960, 96, 1, 8, 192,
510
+ {
511
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
512
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
513
+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
514
+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
515
+ 0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
516
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
517
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
518
+ 0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
519
+ 0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
520
+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
521
+ 0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
522
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
527
+ },
528
+ },
529
+ {
530
+ /* 7680x4320/960X96 rgb 8bpc 11bpp */
531
+ 7680, 4320, 960, 96, 1, 8, 176,
532
+ {
533
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
534
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
535
+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
536
+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
537
+ 0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
538
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
539
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
540
+ 0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
541
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
542
+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
543
+ 0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
544
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
549
+ },
550
+ },
551
+ {
552
+ /* 7680x4320/960X96 rgb 8bpc 10bpp */
553
+ 7680, 4320, 960, 96, 1, 8, 160,
554
+ {
555
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
556
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
557
+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
558
+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
559
+ 0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
560
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
561
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
562
+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
563
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
564
+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
565
+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
566
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
571
+ },
572
+ },
573
+ {
574
+ /* 7680x4320/960X96 rgb 8bpc 9bpp */
575
+ 7680, 4320, 960, 96, 1, 8, 144,
576
+ {
577
+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
578
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
579
+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
580
+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
581
+ 0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
582
+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
583
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
584
+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
585
+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
586
+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
587
+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
588
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
593
+ },
594
+ },
595
+ {
596
+ /* 7680x4320/960X96 rgb 10bpc 12bpp */
597
+ 7680, 4320, 960, 96, 1, 10, 192,
598
+ {
599
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
600
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
601
+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
602
+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
603
+ 0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
604
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
605
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
606
+ 0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
607
+ 0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
608
+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
609
+ 0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
610
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
615
+ },
616
+ },
617
+ {
618
+ /* 7680x4320/960X96 rgb 10bpc 11bpp */
619
+ 7680, 4320, 960, 96, 1, 10, 176,
620
+ {
621
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
622
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
623
+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
624
+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
625
+ 0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
626
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
627
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
628
+ 0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
629
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
630
+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
631
+ 0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
632
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
637
+ },
638
+ },
639
+ {
640
+ /* 7680x4320/960X96 rgb 10bpc 10bpp */
641
+ 7680, 4320, 960, 96, 1, 10, 160,
642
+ {
643
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
644
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
645
+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
646
+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
647
+ 0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
648
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
649
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
650
+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
651
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
652
+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
653
+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
654
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
659
+ },
660
+ },
661
+ {
662
+ /* 7680x4320/960X96 rgb 10bpc 9bpp */
663
+ 7680, 4320, 960, 96, 1, 10, 144,
664
+ {
665
+ 0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
666
+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
667
+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
668
+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
669
+ 0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
670
+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
671
+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
672
+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
673
+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
674
+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
675
+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
676
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
681
+ },
682
+ },
683
+};
684
+
685
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
686
+{
687
+ switch (bus_format) {
688
+ case MEDIA_BUS_FMT_RGB888_1X24:
689
+ case MEDIA_BUS_FMT_RGB101010_1X30:
690
+ case MEDIA_BUS_FMT_RGB121212_1X36:
691
+ case MEDIA_BUS_FMT_RGB161616_1X48:
692
+ return true;
693
+
694
+ default:
695
+ return false;
696
+ }
697
+}
698
+
699
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
700
+{
701
+ switch (bus_format) {
702
+ case MEDIA_BUS_FMT_YUV8_1X24:
703
+ case MEDIA_BUS_FMT_YUV10_1X30:
704
+ case MEDIA_BUS_FMT_YUV12_1X36:
705
+ case MEDIA_BUS_FMT_YUV16_1X48:
706
+ return true;
707
+
708
+ default:
709
+ return false;
710
+ }
711
+}
712
+
713
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
714
+{
715
+ switch (bus_format) {
716
+ case MEDIA_BUS_FMT_UYVY8_1X16:
717
+ case MEDIA_BUS_FMT_UYVY10_1X20:
718
+ case MEDIA_BUS_FMT_UYVY12_1X24:
719
+ case MEDIA_BUS_FMT_YUYV8_1X16:
720
+ case MEDIA_BUS_FMT_YUYV10_1X20:
721
+ case MEDIA_BUS_FMT_YUYV12_1X24:
722
+ return true;
723
+
724
+ default:
725
+ return false;
726
+ }
727
+}
728
+
729
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
730
+{
731
+ switch (bus_format) {
732
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
733
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
734
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
735
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
736
+ return true;
737
+
738
+ default:
739
+ return false;
740
+ }
741
+}
742
+
491743 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
492744 {
493745 switch (bus_format) {
494746 case MEDIA_BUS_FMT_RGB888_1X24:
495747 case MEDIA_BUS_FMT_YUV8_1X24:
496748 case MEDIA_BUS_FMT_UYVY8_1X16:
749
+ case MEDIA_BUS_FMT_YUYV8_1X16:
497750 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
498751 return 8;
499752
500753 case MEDIA_BUS_FMT_RGB101010_1X30:
501754 case MEDIA_BUS_FMT_YUV10_1X30:
502755 case MEDIA_BUS_FMT_UYVY10_1X20:
756
+ case MEDIA_BUS_FMT_YUYV10_1X20:
503757 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
504758 return 10;
505759
506760 case MEDIA_BUS_FMT_RGB121212_1X36:
507761 case MEDIA_BUS_FMT_YUV12_1X36:
508762 case MEDIA_BUS_FMT_UYVY12_1X24:
763
+ case MEDIA_BUS_FMT_YUYV12_1X24:
509764 case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
510765 return 12;
511766
....@@ -518,6 +773,436 @@
518773 return 0;
519774 }
520775 }
776
+
777
+static int hdmi_bus_fmt_to_color_format(unsigned int bus_format)
778
+{
779
+ switch (bus_format) {
780
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
781
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
782
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
783
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
784
+ return RK_IF_FORMAT_YCBCR420;
785
+
786
+ case MEDIA_BUS_FMT_YUV8_1X24:
787
+ case MEDIA_BUS_FMT_YUV10_1X30:
788
+ case MEDIA_BUS_FMT_YUV12_1X36:
789
+ case MEDIA_BUS_FMT_YUV16_1X48:
790
+ return RK_IF_FORMAT_YCBCR444;
791
+
792
+ case MEDIA_BUS_FMT_UYVY8_1X16:
793
+ case MEDIA_BUS_FMT_YUYV8_1X16:
794
+ case MEDIA_BUS_FMT_UYVY10_1X20:
795
+ case MEDIA_BUS_FMT_YUYV10_1X20:
796
+ case MEDIA_BUS_FMT_UYVY12_1X24:
797
+ case MEDIA_BUS_FMT_YVYU12_1X24:
798
+ return RK_IF_FORMAT_YCBCR422;
799
+
800
+ case MEDIA_BUS_FMT_RGB888_1X24:
801
+ case MEDIA_BUS_FMT_RGB101010_1X30:
802
+ case MEDIA_BUS_FMT_RGB121212_1X36:
803
+ case MEDIA_BUS_FMT_RGB161616_1X48:
804
+ default:
805
+ return RK_IF_FORMAT_RGB;
806
+ }
807
+}
808
+
809
+static unsigned int
810
+hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
811
+{
812
+ unsigned int tmdsclock = pixelclock;
813
+ unsigned int depth =
814
+ hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
815
+
816
+ if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
817
+ switch (depth) {
818
+ case 16:
819
+ tmdsclock = pixelclock * 2;
820
+ break;
821
+ case 12:
822
+ tmdsclock = pixelclock * 3 / 2;
823
+ break;
824
+ case 10:
825
+ tmdsclock = pixelclock * 5 / 4;
826
+ break;
827
+ default:
828
+ break;
829
+ }
830
+ }
831
+
832
+ return tmdsclock;
833
+}
834
+
835
+static int rockchip_hdmi_match_by_id(struct device *dev, const void *data)
836
+{
837
+ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
838
+ const unsigned int *id = data;
839
+
840
+ return hdmi->id == *id;
841
+}
842
+
843
+static struct rockchip_hdmi *
844
+rockchip_hdmi_find_by_id(struct device_driver *drv, unsigned int id)
845
+{
846
+ struct device *dev;
847
+
848
+ dev = driver_find_device(drv, NULL, &id, rockchip_hdmi_match_by_id);
849
+ if (!dev)
850
+ return NULL;
851
+
852
+ return dev_get_drvdata(dev);
853
+}
854
+
855
+static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
856
+ struct drm_crtc_state *crtc_state,
857
+ unsigned int tmdsclk)
858
+{
859
+ struct drm_display_mode mode = {};
860
+ int max_lanes, max_rate_per_lane;
861
+ int max_dsc_lanes, max_dsc_rate_per_lane;
862
+ unsigned long max_frl_rate;
863
+
864
+ drm_mode_copy(&mode, &crtc_state->mode);
865
+ if (hdmi->plat_data->split_mode)
866
+ drm_mode_convert_to_origin_mode(&mode);
867
+
868
+ max_lanes = hdmi->max_lanes;
869
+ max_rate_per_lane = hdmi->max_frl_rate_per_lane;
870
+ max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
871
+
872
+ hdmi->link_cfg.dsc_mode = false;
873
+ hdmi->link_cfg.frl_lanes = max_lanes;
874
+ hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
875
+ hdmi->link_cfg.add_func = hdmi->add_func;
876
+
877
+ if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) {
878
+ dev_info(hdmi->dev, "use tmds mode\n");
879
+ hdmi->link_cfg.frl_mode = false;
880
+ return;
881
+ }
882
+
883
+ hdmi->link_cfg.frl_mode = true;
884
+
885
+ if (!hdmi->dsc_cap.v_1p2)
886
+ return;
887
+
888
+ max_dsc_lanes = hdmi->dsc_cap.max_lanes;
889
+ max_dsc_rate_per_lane =
890
+ hdmi->dsc_cap.max_frl_rate_per_lane;
891
+
892
+ if (mode.clock >= HDMI_8K60_RATE &&
893
+ !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) &&
894
+ !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) {
895
+ hdmi->link_cfg.dsc_mode = true;
896
+ hdmi->link_cfg.frl_lanes = max_dsc_lanes;
897
+ hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
898
+ } else {
899
+ hdmi->link_cfg.dsc_mode = false;
900
+ hdmi->link_cfg.frl_lanes = max_lanes;
901
+ hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
902
+ }
903
+}
904
+
905
+/////////////////////////////////////////////////////////////////////////////////////
906
+
907
+static int hdmi_dsc_get_slice_height(int vactive)
908
+{
909
+ int slice_height;
910
+
911
+ /*
912
+ * Slice Height determination : HDMI2.1 Section 7.7.5.2
913
+ * Select smallest slice height >=96, that results in a valid PPS and
914
+ * requires minimum padding lines required for final slice.
915
+ *
916
+ * Assumption : Vactive is even.
917
+ */
918
+ for (slice_height = 96; slice_height <= vactive; slice_height += 2)
919
+ if (vactive % slice_height == 0)
920
+ return slice_height;
921
+
922
+ return 0;
923
+}
924
+
925
+static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
926
+ struct drm_crtc_state *crtc_state,
927
+ int src_max_slices, int src_max_slice_width,
928
+ int hdmi_max_slices, int hdmi_throughput)
929
+{
930
+/* Pixel rates in KPixels/sec */
931
+#define HDMI_DSC_PEAK_PIXEL_RATE 2720000
932
+/*
933
+ * Rates at which the source and sink are required to process pixels in each
934
+ * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
935
+ */
936
+#define HDMI_DSC_MAX_ENC_THROUGHPUT_0 340000
937
+#define HDMI_DSC_MAX_ENC_THROUGHPUT_1 400000
938
+
939
+/* Spec limits the slice width to 2720 pixels */
940
+#define MAX_HDMI_SLICE_WIDTH 2720
941
+ int kslice_adjust;
942
+ int adjusted_clk_khz;
943
+ int min_slices;
944
+ int target_slices;
945
+ int max_throughput; /* max clock freq. in khz per slice */
946
+ int max_slice_width;
947
+ int slice_width;
948
+ int pixel_clock = crtc_state->mode.clock;
949
+
950
+ if (!hdmi_throughput)
951
+ return 0;
952
+
953
+ /*
954
+ * Slice Width determination : HDMI2.1 Section 7.7.5.1
955
+ * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
956
+ * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
957
+ * dividing adjusted clock value by 10.
958
+ */
959
+ if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
960
+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
961
+ kslice_adjust = 10;
962
+ else
963
+ kslice_adjust = 5;
964
+
965
+ /*
966
+ * As per spec, the rate at which the source and the sink process
967
+ * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
968
+ * This depends upon the pixel clock rate and output formats
969
+ * (kslice adjust).
970
+ * If pixel clock * kslice adjust >= 2720MHz slices can be processed
971
+ * at max 340MHz, otherwise they can be processed at max 400MHz.
972
+ */
973
+
974
+ adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
975
+
976
+ if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
977
+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
978
+ else
979
+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
980
+
981
+ /*
982
+ * Taking into account the sink's capability for maximum
983
+ * clock per slice (in MHz) as read from HF-VSDB.
984
+ */
985
+ max_throughput = min(max_throughput, hdmi_throughput * 1000);
986
+
987
+ min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
988
+ max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
989
+
990
+ /*
991
+ * Keep on increasing the num of slices/line, starting from min_slices
992
+ * per line till we get such a number, for which the slice_width is
993
+ * just less than max_slice_width. The slices/line selected should be
994
+ * less than or equal to the max horizontal slices that the combination
995
+ * of PCON encoder and HDMI decoder can support.
996
+ */
997
+ do {
998
+ if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
999
+ target_slices = 1;
1000
+ else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
1001
+ target_slices = 2;
1002
+ else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
1003
+ target_slices = 4;
1004
+ else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
1005
+ target_slices = 8;
1006
+ else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
1007
+ target_slices = 12;
1008
+ else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
1009
+ target_slices = 16;
1010
+ else
1011
+ return 0;
1012
+
1013
+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, target_slices);
1014
+ if (slice_width > max_slice_width)
1015
+ min_slices = target_slices + 1;
1016
+ } while (slice_width > max_slice_width);
1017
+
1018
+ return target_slices;
1019
+}
1020
+
1021
+static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
1022
+ struct drm_crtc_state *crtc_state)
1023
+{
1024
+ int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
1025
+ int hdmi_max_slices = hdmi->dsc_cap.max_slices;
1026
+ int rk_max_slices = 8;
1027
+ int rk_max_slice_width = 2048;
1028
+
1029
+ return hdmi_dsc_get_num_slices(hdmi, crtc_state, rk_max_slices,
1030
+ rk_max_slice_width,
1031
+ hdmi_max_slices, hdmi_throughput);
1032
+}
1033
+
1034
+static int
1035
+hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
1036
+ int slice_width, int num_slices, bool hdmi_all_bpp,
1037
+ int hdmi_max_chunk_bytes)
1038
+{
1039
+ int max_dsc_bpp, min_dsc_bpp;
1040
+ int target_bytes;
1041
+ bool bpp_found = false;
1042
+ int bpp_decrement_x16;
1043
+ int bpp_target;
1044
+ int bpp_target_x16;
1045
+
1046
+ /*
1047
+ * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
1048
+ * Start with the max bpp and keep on decrementing with
1049
+ * fractional bpp, if supported by PCON DSC encoder
1050
+ *
1051
+ * for each bpp we check if no of bytes can be supported by HDMI sink
1052
+ */
1053
+
1054
+ /* only 9\10\12 bpp was tested */
1055
+ min_dsc_bpp = 9;
1056
+ max_dsc_bpp = 12;
1057
+
1058
+ /*
1059
+ * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
1060
+ * Section 7.7.34 : Source shall not enable compressed Video
1061
+ * Transport with bpp_target settings above 12 bpp unless
1062
+ * DSC_all_bpp is set to 1.
1063
+ */
1064
+ if (!hdmi_all_bpp)
1065
+ max_dsc_bpp = min(max_dsc_bpp, 12);
1066
+
1067
+ /*
1068
+ * The Sink has a limit of compressed data in bytes for a scanline,
1069
+ * as described in max_chunk_bytes field in HFVSDB block of edid.
1070
+ * The no. of bytes depend on the target bits per pixel that the
1071
+ * source configures. So we start with the max_bpp and calculate
1072
+ * the target_chunk_bytes. We keep on decrementing the target_bpp,
1073
+ * till we get the target_chunk_bytes just less than what the sink's
1074
+ * max_chunk_bytes, or else till we reach the min_dsc_bpp.
1075
+ *
1076
+ * The decrement is according to the fractional support from PCON DSC
1077
+ * encoder. For fractional BPP we use bpp_target as a multiple of 16.
1078
+ *
1079
+ * bpp_target_x16 = bpp_target * 16
1080
+ * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
1081
+ * {1/16, 1/8, 1/4, 1/2, 1} respectively.
1082
+ */
1083
+
1084
+ bpp_target = max_dsc_bpp;
1085
+
1086
+ /* src does not support fractional bpp implies decrement by 16 for bppx16 */
1087
+ if (!src_fractional_bpp)
1088
+ src_fractional_bpp = 1;
1089
+ bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
1090
+ bpp_target_x16 = bpp_target * 16;
1091
+
1092
+ while (bpp_target_x16 > (min_dsc_bpp * 16)) {
1093
+ int bpp;
1094
+
1095
+ bpp = DIV_ROUND_UP(bpp_target_x16, 16);
1096
+ target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
1097
+ if (target_bytes <= hdmi_max_chunk_bytes) {
1098
+ bpp_found = true;
1099
+ break;
1100
+ }
1101
+ bpp_target_x16 -= bpp_decrement_x16;
1102
+ }
1103
+ if (bpp_found)
1104
+ return bpp_target_x16;
1105
+
1106
+ return 0;
1107
+}
1108
+
1109
+static int
1110
+dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
1111
+ int num_slices, int slice_width)
1112
+{
1113
+ bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
1114
+ int fractional_bpp = 0;
1115
+ int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
1116
+
1117
+ return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
1118
+ num_slices, hdmi_all_bpp,
1119
+ hdmi_max_chunk_bytes);
1120
+}
1121
+
1122
+static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
1123
+ u16 pic_width, u16 pic_height,
1124
+ u16 slice_width, u16 slice_height,
1125
+ u16 bits_per_pixel, u8 bits_per_component)
1126
+{
1127
+ int i;
1128
+
1129
+ for (i = 0; i < PPS_TABLE_LEN; i++)
1130
+ if (pic_width == pps_datas[i].pic_width &&
1131
+ pic_height == pps_datas[i].pic_height &&
1132
+ slice_width == pps_datas[i].slice_width &&
1133
+ slice_height == pps_datas[i].slice_height &&
1134
+ bits_per_component == pps_datas[i].bpc &&
1135
+ bits_per_pixel == pps_datas[i].bpp &&
1136
+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb)
1137
+ break;
1138
+
1139
+ if (i == PPS_TABLE_LEN) {
1140
+ dev_err(hdmi->dev, "can't find pps cfg!\n");
1141
+ return -EINVAL;
1142
+ }
1143
+
1144
+ memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
1145
+ hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
1146
+ (pic_width / slice_width);
1147
+
1148
+ return 0;
1149
+}
1150
+
1151
+static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
1152
+ struct rockchip_crtc_state *s,
1153
+ struct drm_crtc_state *crtc_state)
1154
+{
1155
+ int ret;
1156
+ int slice_height;
1157
+ int slice_width;
1158
+ int bits_per_pixel;
1159
+ int slice_count;
1160
+ bool hdmi_is_dsc_1_2;
1161
+ unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
1162
+
1163
+ if (!crtc_state)
1164
+ return;
1165
+
1166
+ hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
1167
+
1168
+ if (!hdmi_is_dsc_1_2)
1169
+ return;
1170
+
1171
+ slice_height = hdmi_dsc_get_slice_height(crtc_state->mode.vdisplay);
1172
+ if (!slice_height)
1173
+ return;
1174
+
1175
+ slice_count = hdmi_dsc_slices(hdmi, crtc_state);
1176
+ if (!slice_count)
1177
+ return;
1178
+
1179
+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, slice_count);
1180
+
1181
+ bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width);
1182
+ if (!bits_per_pixel)
1183
+ return;
1184
+
1185
+ ret = dw_hdmi_qp_set_link_cfg(hdmi, crtc_state->mode.hdisplay,
1186
+ crtc_state->mode.vdisplay, slice_width,
1187
+ slice_height, bits_per_pixel, depth);
1188
+
1189
+ if (ret) {
1190
+ dev_err(hdmi->dev, "set vdsc cfg failed\n");
1191
+ return;
1192
+ }
1193
+ dev_info(hdmi->dev, "dsc_enable\n");
1194
+ s->dsc_enable = 1;
1195
+ s->dsc_sink_cap.version_major = 1;
1196
+ s->dsc_sink_cap.version_minor = 2;
1197
+ s->dsc_sink_cap.slice_width = slice_width;
1198
+ s->dsc_sink_cap.slice_height = slice_height;
1199
+ s->dsc_sink_cap.target_bits_per_pixel_x16 = bits_per_pixel;
1200
+ s->dsc_sink_cap.block_pred = 1;
1201
+ s->dsc_sink_cap.native_420 = 0;
1202
+
1203
+ memcpy(&s->pps, hdmi->link_cfg.pps_payload, 128);
1204
+}
1205
+/////////////////////////////////////////////////////////////////////////////////////////
5211206
5221207 static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi,
5231208 u32 *config,
....@@ -541,6 +1226,101 @@
5411226 }
5421227
5431228 return 0;
1229
+}
1230
+
1231
+static void repo_hpd_event(struct work_struct *p_work)
1232
+{
1233
+ struct rockchip_hdmi *hdmi = container_of(p_work, struct rockchip_hdmi, work.work);
1234
+ bool change;
1235
+
1236
+ change = drm_helper_hpd_irq_event(hdmi->drm_dev);
1237
+ if (change) {
1238
+ dev_dbg(hdmi->dev, "hpd stat changed:%d\n", hdmi->hpd_stat);
1239
+ dw_hdmi_qp_cec_set_hpd(hdmi->hdmi_qp, hdmi->hpd_stat, change);
1240
+ }
1241
+}
1242
+
1243
+static irqreturn_t rockchip_hdmi_hardirq(int irq, void *dev_id)
1244
+{
1245
+ struct rockchip_hdmi *hdmi = dev_id;
1246
+ u32 intr_stat, val;
1247
+
1248
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
1249
+
1250
+ if (intr_stat) {
1251
+ dev_dbg(hdmi->dev, "hpd irq %#x\n", intr_stat);
1252
+
1253
+ if (!hdmi->id)
1254
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK,
1255
+ RK3588_HDMI0_HPD_INT_MSK);
1256
+ else
1257
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK,
1258
+ RK3588_HDMI1_HPD_INT_MSK);
1259
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1260
+ return IRQ_WAKE_THREAD;
1261
+ }
1262
+
1263
+ return IRQ_NONE;
1264
+}
1265
+
1266
+static irqreturn_t rockchip_hdmi_irq(int irq, void *dev_id)
1267
+{
1268
+ struct rockchip_hdmi *hdmi = dev_id;
1269
+ u32 intr_stat, val;
1270
+ int msecs;
1271
+ bool stat;
1272
+
1273
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
1274
+
1275
+ if (!intr_stat)
1276
+ return IRQ_NONE;
1277
+
1278
+ if (!hdmi->id) {
1279
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
1280
+ RK3588_HDMI0_HPD_INT_CLR);
1281
+ if (intr_stat & RK3588_HDMI0_LEVEL_INT)
1282
+ stat = true;
1283
+ else
1284
+ stat = false;
1285
+ } else {
1286
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
1287
+ RK3588_HDMI1_HPD_INT_CLR);
1288
+ if (intr_stat & RK3588_HDMI1_LEVEL_INT)
1289
+ stat = true;
1290
+ else
1291
+ stat = false;
1292
+ }
1293
+
1294
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1295
+
1296
+ if (stat) {
1297
+ hdmi->hpd_stat = true;
1298
+ msecs = 150;
1299
+ } else {
1300
+ hdmi->hpd_stat = false;
1301
+ msecs = 20;
1302
+ }
1303
+ mod_delayed_work(hdmi->workqueue, &hdmi->work, msecs_to_jiffies(msecs));
1304
+
1305
+ if (!hdmi->id) {
1306
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
1307
+ RK3588_HDMI0_HPD_INT_CLR) |
1308
+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
1309
+ } else {
1310
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
1311
+ RK3588_HDMI1_HPD_INT_CLR) |
1312
+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK);
1313
+ }
1314
+
1315
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
1316
+
1317
+ return IRQ_HANDLED;
1318
+}
1319
+
1320
+static void init_hpd_work(struct rockchip_hdmi *hdmi)
1321
+{
1322
+ hdmi->workqueue = create_workqueue("hpd_queue");
1323
+ INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event);
5441324 }
5451325
5461326 static irqreturn_t rockchip_hdmi_hpd_irq_handler(int irq, void *arg)
....@@ -604,6 +1384,14 @@
6041384 return PTR_ERR(hdmi->regmap);
6051385 }
6061386
1387
+ if (hdmi->is_hdmi_qp) {
1388
+ hdmi->vo1_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,vo1_grf");
1389
+ if (IS_ERR(hdmi->vo1_regmap)) {
1390
+ DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,vo1_grf\n");
1391
+ return PTR_ERR(hdmi->vo1_regmap);
1392
+ }
1393
+ }
1394
+
6071395 hdmi->phyref_clk = devm_clk_get(hdmi->dev, "vpll");
6081396 if (PTR_ERR(hdmi->phyref_clk) == -ENOENT)
6091397 hdmi->phyref_clk = devm_clk_get(hdmi->dev, "ref");
....@@ -647,26 +1435,63 @@
6471435 return PTR_ERR(hdmi->hclk_vop);
6481436 }
6491437
650
- hdmi->dclk_vop = devm_clk_get_optional(hdmi->dev, "dclk_vop");
651
- if (IS_ERR(hdmi->dclk_vop)) {
652
- dev_err(hdmi->dev, "failed to get dclk_vop\n");
653
- return PTR_ERR(hdmi->dclk_vop);
1438
+ hdmi->aud_clk = devm_clk_get_optional(hdmi->dev, "aud");
1439
+ if (IS_ERR(hdmi->aud_clk)) {
1440
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->aud_clk),
1441
+ "failed to get aud_clk clock\n");
1442
+ return PTR_ERR(hdmi->aud_clk);
6541443 }
6551444
656
- ret = of_property_read_u32(np, "max-tmdsclk",
657
- &hdmi->max_tmdsclk);
658
- if (ret != -EINVAL && ret < 0) {
659
- DRM_DEV_ERROR(hdmi->dev, "incorrect max tmdsclk\n");
660
- return ret;
661
- } else if (ret == -EINVAL) {
662
- DRM_DEV_DEBUG(hdmi->dev,
663
- "max tmdsclk is not set, set to 594M\n");
664
- hdmi->max_tmdsclk = 594000;
1445
+ hdmi->hpd_clk = devm_clk_get_optional(hdmi->dev, "hpd");
1446
+ if (IS_ERR(hdmi->hpd_clk)) {
1447
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hpd_clk),
1448
+ "failed to get hpd_clk clock\n");
1449
+ return PTR_ERR(hdmi->hpd_clk);
6651450 }
666
- hdmi->unsupported_yuv_input =
667
- of_property_read_bool(np, "unsupported-yuv-input");
668
- hdmi->unsupported_deep_color =
669
- of_property_read_bool(np, "unsupported-deep-color");
1451
+
1452
+ hdmi->hclk_vo1 = devm_clk_get_optional(hdmi->dev, "hclk_vo1");
1453
+ if (IS_ERR(hdmi->hclk_vo1)) {
1454
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hclk_vo1),
1455
+ "failed to get hclk_vo1 clock\n");
1456
+ return PTR_ERR(hdmi->hclk_vo1);
1457
+ }
1458
+
1459
+ hdmi->earc_clk = devm_clk_get_optional(hdmi->dev, "earc");
1460
+ if (IS_ERR(hdmi->earc_clk)) {
1461
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->earc_clk),
1462
+ "failed to get earc_clk clock\n");
1463
+ return PTR_ERR(hdmi->earc_clk);
1464
+ }
1465
+
1466
+ hdmi->hdmitx_ref = devm_clk_get_optional(hdmi->dev, "hdmitx_ref");
1467
+ if (IS_ERR(hdmi->hdmitx_ref)) {
1468
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmitx_ref),
1469
+ "failed to get hdmitx_ref clock\n");
1470
+ return PTR_ERR(hdmi->hdmitx_ref);
1471
+ }
1472
+
1473
+ hdmi->pclk = devm_clk_get_optional(hdmi->dev, "pclk");
1474
+ if (IS_ERR(hdmi->pclk)) {
1475
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->pclk),
1476
+ "failed to get pclk clock\n");
1477
+ return PTR_ERR(hdmi->pclk);
1478
+ }
1479
+
1480
+ hdmi->link_clk = devm_clk_get_optional(hdmi->dev, "link_clk");
1481
+ if (IS_ERR(hdmi->link_clk)) {
1482
+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->link_clk),
1483
+ "failed to get link_clk clock\n");
1484
+ return PTR_ERR(hdmi->link_clk);
1485
+ }
1486
+
1487
+ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable",
1488
+ GPIOD_OUT_HIGH);
1489
+ if (IS_ERR(hdmi->enable_gpio)) {
1490
+ ret = PTR_ERR(hdmi->enable_gpio);
1491
+ dev_err(hdmi->dev, "failed to request enable GPIO: %d\n", ret);
1492
+ return ret;
1493
+ }
1494
+
6701495 hdmi->skip_check_420_mode =
6711496 of_property_read_bool(np, "skip-check-420-mode");
6721497
....@@ -760,23 +1585,17 @@
7601585 }
7611586
7621587 static enum drm_mode_status
763
-dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
1588
+dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
1589
+ const struct drm_display_info *info,
7641590 const struct drm_display_mode *mode)
7651591 {
1592
+ struct drm_connector *connector = container_of(info, struct drm_connector, display_info);
7661593 struct drm_encoder *encoder = connector->encoder;
7671594 enum drm_mode_status status = MODE_OK;
7681595 struct drm_device *dev = connector->dev;
7691596 struct rockchip_drm_private *priv = dev->dev_private;
7701597 struct drm_crtc *crtc;
7711598 struct rockchip_hdmi *hdmi;
772
-
773
- /*
774
- * Pixel clocks we support are always < 2GHz and so fit in an
775
- * int. We should make sure source rate does too so we don't get
776
- * overflow when we multiply by 1000.
777
- */
778
- if (mode->clock > INT_MAX / 1000)
779
- return MODE_BAD;
7801599
7811600 if (!encoder) {
7821601 const struct drm_connector_helper_funcs *funcs;
....@@ -793,6 +1612,21 @@
7931612 return MODE_BAD;
7941613
7951614 hdmi = to_rockchip_hdmi(encoder);
1615
+
1616
+ if (hdmi->is_hdmi_qp) {
1617
+ if (!hdmi->enable_gpio && mode->clock > 600000)
1618
+ return MODE_BAD;
1619
+
1620
+ return MODE_OK;
1621
+ }
1622
+
1623
+ /*
1624
+ * Pixel clocks we support are always < 2GHz and so fit in an
1625
+ * int. We should make sure source rate does too so we don't get
1626
+ * overflow when we multiply by 1000.
1627
+ */
1628
+ if (mode->clock > INT_MAX / 1000)
1629
+ return MODE_BAD;
7961630
7971631 /*
7981632 * If sink max TMDS clock < 340MHz, we should check the mode pixel
....@@ -811,8 +1645,12 @@
8111645 return MODE_BAD;
8121646 };
8131647
814
- if (hdmi->phy)
815
- phy_set_bus_width(hdmi->phy, 8);
1648
+ if (hdmi->phy) {
1649
+ if (hdmi->is_hdmi_qp)
1650
+ phy_set_bus_width(hdmi->phy, mode->clock * 10);
1651
+ else
1652
+ phy_set_bus_width(hdmi->phy, 8);
1653
+ }
8161654
8171655 /*
8181656 * ensure all drm display mode can work, if someone want support more
....@@ -838,21 +1676,29 @@
8381676 return status;
8391677 }
8401678
841
-static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
842
- .destroy = drm_encoder_cleanup,
843
-};
844
-
8451679 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
8461680 {
8471681 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
8481682 struct drm_crtc *crtc = encoder->crtc;
849
- struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
1683
+ struct rockchip_crtc_state *s;
8501684
851
- if (WARN_ON(!crtc || !crtc->state))
1685
+ if (!crtc || !crtc->state) {
1686
+ dev_info(hdmi->dev, "%s old crtc state is null\n", __func__);
8521687 return;
1688
+ }
8531689
854
- if (!hdmi->mode_changed)
855
- s->output_if &= ~VOP_OUTPUT_IF_HDMI0;
1690
+ s = to_rockchip_crtc_state(crtc->state);
1691
+
1692
+ if (crtc->state->active_changed) {
1693
+ if (hdmi->plat_data->split_mode) {
1694
+ s->output_if &= ~(VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1);
1695
+ } else {
1696
+ if (!hdmi->id)
1697
+ s->output_if &= ~VOP_OUTPUT_IF_HDMI0;
1698
+ else
1699
+ s->output_if &= ~VOP_OUTPUT_IF_HDMI1;
1700
+ }
1701
+ }
8561702 /*
8571703 * when plug out hdmi it will be switch cvbs and then phy bus width
8581704 * must be set as 8
....@@ -869,14 +1715,23 @@
8691715 int mux;
8701716 int ret;
8711717
872
- if (WARN_ON(!crtc || !crtc->state))
1718
+ if (!crtc || !crtc->state) {
1719
+ dev_info(hdmi->dev, "%s old crtc state is null\n", __func__);
8731720 return;
1721
+ }
8741722
8751723 if (hdmi->phy)
8761724 phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
8771725
8781726 clk_set_rate(hdmi->phyref_clk,
8791727 crtc->state->adjusted_mode.crtc_clock * 1000);
1728
+
1729
+ if (hdmi->is_hdmi_qp) {
1730
+ if (hdmi->link_cfg.frl_mode)
1731
+ gpiod_set_value(hdmi->enable_gpio, 0);
1732
+ else
1733
+ gpiod_set_value(hdmi->enable_gpio, 1);
1734
+ }
8801735
8811736 if (hdmi->chip_data->lcdsel_grf_reg < 0)
8821737 return;
....@@ -916,6 +1771,205 @@
9161771 ret ? "LIT" : "BIG");
9171772 }
9181773
1774
+static int _dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_hdmi *hdmi, bool on)
1775
+{
1776
+ int ret;
1777
+
1778
+ if (on) {
1779
+ if (hdmi->is_hdmi_qp) {
1780
+ ret = clk_prepare_enable(hdmi->link_clk);
1781
+ if (ret < 0) {
1782
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable link_clk %d\n", ret);
1783
+ return ret;
1784
+ }
1785
+ }
1786
+
1787
+ hdmi->phy->power_count++;
1788
+ } else {
1789
+ clk_disable_unprepare(hdmi->link_clk);
1790
+ hdmi->phy->power_count--;
1791
+ }
1792
+
1793
+ return 0;
1794
+}
1795
+
1796
+static int dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on)
1797
+{
1798
+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
1799
+ struct rockchip_hdmi *secondary;
1800
+
1801
+ _dw_hdmi_rockchip_encoder_loader_protect(hdmi, on);
1802
+ if (hdmi->plat_data->right) {
1803
+ secondary = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id);
1804
+ _dw_hdmi_rockchip_encoder_loader_protect(secondary, on);
1805
+ }
1806
+
1807
+ return 0;
1808
+}
1809
+
1810
+static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
1811
+{
1812
+ int val;
1813
+ bool is_hdmi0;
1814
+
1815
+ if (!hdmi->id)
1816
+ is_hdmi0 = true;
1817
+ else
1818
+ is_hdmi0 = false;
1819
+
1820
+ if (!hdmi->link_cfg.frl_mode) {
1821
+ val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
1822
+ if (is_hdmi0)
1823
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
1824
+ else
1825
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
1826
+
1827
+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1828
+ if (is_hdmi0)
1829
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1830
+ else
1831
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1832
+
1833
+ return;
1834
+ }
1835
+
1836
+ val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
1837
+ if (is_hdmi0)
1838
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
1839
+ else
1840
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
1841
+
1842
+ if (hdmi->link_cfg.dsc_mode) {
1843
+ val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
1844
+ RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1845
+ if (is_hdmi0)
1846
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1847
+ else
1848
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1849
+ } else {
1850
+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1851
+ if (is_hdmi0)
1852
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1853
+ else
1854
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1855
+ }
1856
+}
1857
+
1858
+static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1859
+ u32 depth)
1860
+{
1861
+ u32 val = 0;
1862
+
1863
+ switch (bus_format) {
1864
+ case MEDIA_BUS_FMT_RGB888_1X24:
1865
+ case MEDIA_BUS_FMT_RGB101010_1X30:
1866
+ val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
1867
+ break;
1868
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1869
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1870
+ val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
1871
+ break;
1872
+ case MEDIA_BUS_FMT_YUV8_1X24:
1873
+ case MEDIA_BUS_FMT_YUV10_1X30:
1874
+ val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
1875
+ break;
1876
+ case MEDIA_BUS_FMT_YUYV10_1X20:
1877
+ case MEDIA_BUS_FMT_YUYV8_1X16:
1878
+ val = HIWORD_UPDATE(RK3588_YUV422, RK3588_COLOR_FORMAT_MASK);
1879
+ break;
1880
+ default:
1881
+ dev_err(hdmi->dev, "can't set correct color format\n");
1882
+ return;
1883
+ }
1884
+
1885
+ if (hdmi->link_cfg.dsc_mode)
1886
+ val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
1887
+
1888
+ if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1889
+ val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
1890
+ else
1891
+ val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
1892
+
1893
+ if (!hdmi->id)
1894
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
1895
+ else
1896
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
1897
+}
1898
+
1899
+static void rk3588_set_hdcp_status(void *data, u8 status)
1900
+{
1901
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1902
+
1903
+ hdmi->hdcp_status = status;
1904
+}
1905
+
1906
+static void rk3588_set_hdcp2_enable(void *data, bool enable)
1907
+{
1908
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1909
+ u32 val;
1910
+
1911
+ if (enable)
1912
+ val = HIWORD_UPDATE(HDCP1_P1_GPIO_IN, HDCP1_P1_GPIO_IN);
1913
+ else
1914
+ val = HIWORD_UPDATE(0, HDCP1_P1_GPIO_IN);
1915
+
1916
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON1, val);
1917
+}
1918
+
1919
+static void rk3588_set_grf_cfg(void *data)
1920
+{
1921
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1922
+ int color_depth;
1923
+
1924
+ rk3588_set_link_mode(hdmi);
1925
+ color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
1926
+ rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth);
1927
+}
1928
+
1929
+static u64 rk3588_get_grf_color_fmt(void *data)
1930
+{
1931
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1932
+ u32 val, depth;
1933
+ u64 bus_format;
1934
+
1935
+ if (!hdmi->id)
1936
+ regmap_read(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, &val);
1937
+ else
1938
+ regmap_read(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, &val);
1939
+
1940
+ depth = (val & RK3588_COLOR_DEPTH_MASK) >> 4;
1941
+
1942
+ switch (val & RK3588_COLOR_FORMAT_MASK) {
1943
+ case RK3588_YUV444:
1944
+ if (!depth)
1945
+ bus_format = MEDIA_BUS_FMT_YUV8_1X24;
1946
+ else
1947
+ bus_format = MEDIA_BUS_FMT_YUV10_1X30;
1948
+ break;
1949
+ case RK3588_YUV422:
1950
+ bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
1951
+ break;
1952
+ case RK3588_YUV420:
1953
+ if (!depth)
1954
+ bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
1955
+ else
1956
+ bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
1957
+ break;
1958
+ case RK3588_RGB:
1959
+ if (!depth)
1960
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
1961
+ else
1962
+ bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
1963
+ break;
1964
+ default:
1965
+ dev_err(hdmi->dev, "can't get correct color format\n");
1966
+ bus_format = MEDIA_BUS_FMT_YUV8_1X24;
1967
+ break;
1968
+ }
1969
+
1970
+ return bus_format;
1971
+}
1972
+
9191973 static void
9201974 dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state,
9211975 struct drm_crtc_state *crtc_state,
....@@ -928,66 +1982,81 @@
9281982 unsigned int *eotf)
9291983 {
9301984 struct drm_display_info *info = &conn_state->connector->display_info;
931
- struct drm_display_mode *mode = &crtc_state->mode;
1985
+ struct drm_display_mode mode = {};
9321986 struct hdr_output_metadata *hdr_metadata;
933
- u32 vic = drm_match_cea_mode(mode);
934
- unsigned long tmdsclock, pixclock = mode->crtc_clock;
1987
+ u32 vic;
1988
+ unsigned long tmdsclock, pixclock;
9351989 unsigned int color_depth;
9361990 bool support_dc = false;
937
- bool sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
1991
+ bool sink_is_hdmi = true;
9381992 bool yuv422_out = false;
939
- int max_tmds_clock = info->max_tmds_clock;
1993
+ u32 max_tmds_clock = info->max_tmds_clock;
9401994 int output_eotf;
9411995
942
- *color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
1996
+ drm_mode_copy(&mode, &crtc_state->mode);
1997
+ pixclock = mode.crtc_clock;
1998
+ if (hdmi->plat_data->split_mode) {
1999
+ drm_mode_convert_to_origin_mode(&mode);
2000
+ pixclock /= 2;
2001
+ }
2002
+
2003
+ vic = drm_match_cea_mode(&mode);
2004
+
2005
+ if (!hdmi->is_hdmi_qp)
2006
+ sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
2007
+ else
2008
+ sink_is_hdmi = dw_hdmi_qp_get_output_whether_hdmi(hdmi->hdmi_qp);
2009
+
2010
+ *color_format = RK_IF_FORMAT_RGB;
9432011
9442012 switch (hdmi->hdmi_output) {
945
- case DRM_HDMI_OUTPUT_YCBCR_HQ:
2013
+ case RK_IF_FORMAT_YCBCR_HQ:
9462014 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
947
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
2015
+ *color_format = RK_IF_FORMAT_YCBCR444;
9482016 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
949
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2017
+ *color_format = RK_IF_FORMAT_YCBCR422;
9502018 else if (conn_state->connector->ycbcr_420_allowed &&
951
- drm_mode_is_420(info, mode) && pixclock >= 594000)
952
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2019
+ drm_mode_is_420(info, &mode) &&
2020
+ (pixclock >= 594000 && !hdmi->is_hdmi_qp))
2021
+ *color_format = RK_IF_FORMAT_YCBCR420;
9532022 break;
954
- case DRM_HDMI_OUTPUT_YCBCR_LQ:
2023
+ case RK_IF_FORMAT_YCBCR_LQ:
9552024 if (conn_state->connector->ycbcr_420_allowed &&
956
- drm_mode_is_420(info, mode) && pixclock >= 594000)
957
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2025
+ drm_mode_is_420(info, &mode) && pixclock >= 594000)
2026
+ *color_format = RK_IF_FORMAT_YCBCR420;
9582027 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
959
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2028
+ *color_format = RK_IF_FORMAT_YCBCR422;
9602029 else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
961
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
2030
+ *color_format = RK_IF_FORMAT_YCBCR444;
9622031 break;
963
- case DRM_HDMI_OUTPUT_YCBCR420:
2032
+ case RK_IF_FORMAT_YCBCR420:
9642033 if (conn_state->connector->ycbcr_420_allowed &&
965
- drm_mode_is_420(info, mode) && pixclock >= 594000)
966
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2034
+ drm_mode_is_420(info, &mode) && pixclock >= 594000)
2035
+ *color_format = RK_IF_FORMAT_YCBCR420;
9672036 break;
968
- case DRM_HDMI_OUTPUT_YCBCR422:
2037
+ case RK_IF_FORMAT_YCBCR422:
9692038 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
970
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2039
+ *color_format = RK_IF_FORMAT_YCBCR422;
9712040 break;
972
- case DRM_HDMI_OUTPUT_YCBCR444:
2041
+ case RK_IF_FORMAT_YCBCR444:
9732042 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
974
- *color_format = DRM_HDMI_OUTPUT_YCBCR444;
2043
+ *color_format = RK_IF_FORMAT_YCBCR444;
9752044 break;
976
- case DRM_HDMI_OUTPUT_DEFAULT_RGB:
2045
+ case RK_IF_FORMAT_RGB:
9772046 default:
9782047 break;
9792048 }
9802049
981
- if (*color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
2050
+ if (*color_format == RK_IF_FORMAT_RGB &&
9822051 info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
9832052 support_dc = true;
984
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
2053
+ if (*color_format == RK_IF_FORMAT_YCBCR444 &&
9852054 info->edid_hdmi_dc_modes &
9862055 (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30))
9872056 support_dc = true;
988
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422)
2057
+ if (*color_format == RK_IF_FORMAT_YCBCR422)
9892058 support_dc = true;
990
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
2059
+ if (*color_format == RK_IF_FORMAT_YCBCR420 &&
9912060 info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
9922061 support_dc = true;
9932062
....@@ -996,30 +2065,29 @@
9962065 else
9972066 color_depth = 8;
9982067
999
- if (!sink_is_hdmi) {
1000
- *color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
1001
- color_depth = 8;
1002
- }
1003
-
1004
- *eotf = TRADITIONAL_GAMMA_SDR;
2068
+ *eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
10052069 if (conn_state->hdr_output_metadata) {
10062070 hdr_metadata = (struct hdr_output_metadata *)
10072071 conn_state->hdr_output_metadata->data;
10082072 output_eotf = hdr_metadata->hdmi_metadata_type1.eotf;
1009
- if (output_eotf > TRADITIONAL_GAMMA_HDR &&
1010
- output_eotf < FUTURE_EOTF)
2073
+ if (output_eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR &&
2074
+ output_eotf <= HDMI_EOTF_BT_2100_HLG)
10112075 *eotf = output_eotf;
10122076 }
10132077
2078
+ hdmi->colorimetry = conn_state->colorspace;
2079
+
10142080 /* bt2020 sdr/hdr output */
1015
- if (hdmi->colorimetry == RK_HDMI_COLORIMETRY_BT2020 &&
1016
- info->hdmi.colorimetry & (BIT(6) | BIT(7))) {
2081
+ if ((hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_CYCC) &&
2082
+ (hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_YCC) &&
2083
+ hdmi->edid_colorimetry & (BIT(6) | BIT(7))) {
10172084 *enc_out_encoding = V4L2_YCBCR_ENC_BT2020;
10182085 yuv422_out = true;
10192086 /* bt709 hdr output */
1020
- } else if (hdmi->colorimetry != RK_HDMI_COLORIMETRY_BT2020 &&
2087
+ } else if ((hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_CYCC) &&
2088
+ (hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_YCC) &&
10212089 (conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & BIT(*eotf) &&
1022
- *eotf > TRADITIONAL_GAMMA_HDR)) {
2090
+ *eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR)) {
10232091 *enc_out_encoding = V4L2_YCBCR_ENC_709;
10242092 yuv422_out = true;
10252093 } else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
....@@ -1029,25 +2097,34 @@
10292097 *enc_out_encoding = V4L2_YCBCR_ENC_709;
10302098 }
10312099
1032
- if ((yuv422_out || hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR_HQ) &&
1033
- color_depth == 10 && hdmi_bus_fmt_color_depth(hdmi->prev_bus_format) == 8) {
2100
+ if ((yuv422_out || hdmi->hdmi_output == RK_IF_FORMAT_YCBCR_HQ) && color_depth == 10 &&
2101
+ (hdmi_bus_fmt_color_depth(hdmi->prev_bus_format) == 8 ||
2102
+ hdmi_bus_fmt_to_color_format(hdmi->prev_bus_format) == RK_IF_FORMAT_YCBCR422)) {
10342103 /* We prefer use YCbCr422 to send hdr 10bit */
10352104 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
1036
- *color_format = DRM_HDMI_OUTPUT_YCBCR422;
2105
+ *color_format = RK_IF_FORMAT_YCBCR422;
10372106 }
10382107
1039
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2108
+ if (mode.flags & DRM_MODE_FLAG_DBLCLK)
10402109 pixclock *= 2;
1041
- if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
2110
+ if ((mode.flags & DRM_MODE_FLAG_3D_MASK) ==
10422111 DRM_MODE_FLAG_3D_FRAME_PACKING)
10432112 pixclock *= 2;
10442113
1045
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
2114
+ if (hdmi->is_hdmi_qp && mode.clock >= 600000)
2115
+ *color_format = RK_IF_FORMAT_YCBCR420;
2116
+
2117
+ if (!sink_is_hdmi) {
2118
+ *color_format = RK_IF_FORMAT_RGB;
2119
+ color_depth = 8;
2120
+ }
2121
+
2122
+ if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8)
10462123 tmdsclock = pixclock;
10472124 else
10482125 tmdsclock = pixclock * (color_depth) / 8;
10492126
1050
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420)
2127
+ if (*color_format == RK_IF_FORMAT_YCBCR420)
10512128 tmdsclock /= 2;
10522129
10532130 /* XXX: max_tmds_clock of some sink is 0, we think it is 340MHz. */
....@@ -1056,67 +2133,76 @@
10562133
10572134 max_tmds_clock = min(max_tmds_clock, hdmi->max_tmdsclk);
10582135
2136
+ if (hdmi->is_hdmi_qp && hdmi->link_cfg.rate_per_lane && mode.clock > 600000)
2137
+ max_tmds_clock =
2138
+ hdmi->link_cfg.frl_lanes * hdmi->link_cfg.rate_per_lane * 1000000;
2139
+
10592140 if (tmdsclock > max_tmds_clock) {
10602141 if (max_tmds_clock >= 594000) {
10612142 color_depth = 8;
10622143 } else if (max_tmds_clock > 340000) {
1063
- if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
1064
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2144
+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000)
2145
+ *color_format = RK_IF_FORMAT_YCBCR420;
10652146 } else {
10662147 color_depth = 8;
1067
- if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
1068
- *color_format = DRM_HDMI_OUTPUT_YCBCR420;
2148
+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000)
2149
+ *color_format = RK_IF_FORMAT_YCBCR420;
10692150 }
10702151 }
10712152
1072
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR420) {
2153
+ if (*color_format == RK_IF_FORMAT_YCBCR420) {
10732154 *output_mode = ROCKCHIP_OUT_MODE_YUV420;
10742155 if (color_depth > 8)
10752156 *bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
10762157 else
10772158 *bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
10782159 *bus_width = color_depth / 2;
1079
- hdmi->output_bus_format = *bus_format;
10802160 } else {
10812161 *output_mode = ROCKCHIP_OUT_MODE_AAAA;
1082
-
10832162 if (color_depth > 8) {
1084
- if (*color_format != DRM_HDMI_OUTPUT_DEFAULT_RGB)
1085
- hdmi->output_bus_format = MEDIA_BUS_FMT_YUV10_1X30;
1086
- else
1087
- hdmi->output_bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
1088
-
1089
- if (!hdmi->unsupported_yuv_input)
1090
- *bus_format = hdmi->output_bus_format;
2163
+ if (*color_format != RK_IF_FORMAT_RGB &&
2164
+ !hdmi->unsupported_yuv_input)
2165
+ *bus_format = MEDIA_BUS_FMT_YUV10_1X30;
10912166 else
10922167 *bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
10932168 } else {
1094
- if (*color_format != DRM_HDMI_OUTPUT_DEFAULT_RGB)
1095
- hdmi->output_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
1096
- else
1097
- hdmi->output_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
1098
-
1099
- if (!hdmi->unsupported_yuv_input)
1100
- *bus_format = hdmi->output_bus_format;
2169
+ if (*color_format != RK_IF_FORMAT_RGB &&
2170
+ !hdmi->unsupported_yuv_input)
2171
+ *bus_format = MEDIA_BUS_FMT_YUV8_1X24;
11012172 else
11022173 *bus_format = MEDIA_BUS_FMT_RGB888_1X24;
11032174 }
1104
-
1105
- if (*color_format == DRM_HDMI_OUTPUT_YCBCR422) {
2175
+ if (*color_format == RK_IF_FORMAT_YCBCR422)
11062176 *bus_width = 8;
2177
+ else
2178
+ *bus_width = color_depth;
2179
+ }
11072180
2181
+ hdmi->bus_format = *bus_format;
2182
+
2183
+ if (*color_format == RK_IF_FORMAT_YCBCR422) {
2184
+ if (hdmi->is_hdmi_qp) {
2185
+ if (color_depth == 12)
2186
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV12_1X24;
2187
+ else if (color_depth == 10)
2188
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
2189
+ else
2190
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
2191
+
2192
+ *bus_format = hdmi->output_bus_format;
2193
+ hdmi->bus_format = *bus_format;
2194
+ *output_mode = ROCKCHIP_OUT_MODE_YUV422;
2195
+ } else {
11082196 if (color_depth == 12)
11092197 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
11102198 else if (color_depth == 10)
11112199 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
11122200 else
11132201 hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
1114
- } else {
1115
- *bus_width = color_depth;
11162202 }
2203
+ } else {
2204
+ hdmi->output_bus_format = *bus_format;
11172205 }
1118
-
1119
- hdmi->bus_format = *bus_format;
11202206 }
11212207
11222208 static bool
....@@ -1150,49 +2236,101 @@
11502236 {
11512237 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
11522238 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
1153
- unsigned int colorformat, bus_width;
2239
+ unsigned int colorformat, bus_width, tmdsclk;
2240
+ struct drm_display_mode mode = {};
11542241 unsigned int output_mode;
11552242 unsigned long bus_format;
2243
+ int color_depth;
2244
+ bool secondary = false;
2245
+
2246
+ /*
2247
+ * There are two hdmi but only one encoder in split mode,
2248
+ * so we need to check twice.
2249
+ */
2250
+secondary:
2251
+ drm_mode_copy(&mode, &crtc_state->mode);
2252
+
2253
+ if (hdmi->plat_data->split_mode)
2254
+ drm_mode_convert_to_origin_mode(&mode);
11562255
11572256 dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi,
11582257 &colorformat,
11592258 &output_mode, &bus_format, &bus_width,
11602259 &hdmi->enc_out_encoding, &s->eotf);
11612260
2261
+ s->bus_format = bus_format;
2262
+ if (hdmi->is_hdmi_qp) {
2263
+ color_depth = hdmi_bus_fmt_color_depth(bus_format);
2264
+ tmdsclk = hdmi_get_tmdsclock(hdmi, crtc_state->mode.clock);
2265
+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
2266
+ tmdsclk /= 2;
2267
+ hdmi_select_link_config(hdmi, crtc_state, tmdsclk);
2268
+
2269
+ if (hdmi->link_cfg.frl_mode) {
2270
+ /* in the current version, support max 40G frl */
2271
+ if (hdmi->link_cfg.rate_per_lane >= 10) {
2272
+ hdmi->link_cfg.frl_lanes = 4;
2273
+ hdmi->link_cfg.rate_per_lane = 10;
2274
+ }
2275
+ bus_width = hdmi->link_cfg.frl_lanes *
2276
+ hdmi->link_cfg.rate_per_lane * 1000000;
2277
+ /* 10 bit color depth and frl mode */
2278
+ if (color_depth == 10)
2279
+ bus_width |=
2280
+ COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
2281
+ else
2282
+ bus_width |= HDMI_FRL_MODE;
2283
+ } else {
2284
+ bus_width = hdmi_get_tmdsclock(hdmi, mode.clock * 10);
2285
+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
2286
+ bus_width /= 2;
2287
+
2288
+ if (color_depth == 10 && !hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format))
2289
+ bus_width |= COLOR_DEPTH_10BIT;
2290
+ }
2291
+ }
2292
+
11622293 hdmi->phy_bus_width = bus_width;
2294
+
11632295 if (hdmi->phy)
11642296 phy_set_bus_width(hdmi->phy, bus_width);
11652297
11662298 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
11672299 s->tv_state = &conn_state->tv;
1168
- s->output_if |= VOP_OUTPUT_IF_HDMI0;
2300
+
2301
+ if (hdmi->plat_data->split_mode) {
2302
+ s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
2303
+ if (hdmi->plat_data->right && hdmi->id)
2304
+ s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP;
2305
+ s->output_if |= VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1;
2306
+ } else {
2307
+ if (!hdmi->id)
2308
+ s->output_if |= VOP_OUTPUT_IF_HDMI0;
2309
+ else
2310
+ s->output_if |= VOP_OUTPUT_IF_HDMI1;
2311
+ }
11692312
11702313 s->output_mode = output_mode;
1171
- s->bus_format = bus_format;
11722314 hdmi->bus_format = s->bus_format;
1173
-
1174
- hdmi->mode_changed = crtc_state->mode_changed;
11752315
11762316 if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_BT2020)
11772317 s->color_space = V4L2_COLORSPACE_BT2020;
1178
- else if (colorformat == DRM_HDMI_OUTPUT_DEFAULT_RGB)
2318
+ else if (colorformat == RK_IF_FORMAT_RGB)
11792319 s->color_space = V4L2_COLORSPACE_DEFAULT;
11802320 else if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_709)
11812321 s->color_space = V4L2_COLORSPACE_REC709;
11822322 else
11832323 s->color_space = V4L2_COLORSPACE_SMPTE170M;
11842324
2325
+ if (hdmi->plat_data->split_mode && !secondary) {
2326
+ hdmi = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id);
2327
+ secondary = true;
2328
+ goto secondary;
2329
+ }
2330
+
11852331 return 0;
11862332 }
11872333
1188
-static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
1189
- struct drm_display_mode *mode,
1190
- struct drm_display_mode *adj)
1191
-{
1192
- struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
1193
-
1194
- clk_set_rate(hdmi->phyref_clk, adj->crtc_clock * 1000);
1195
-}
11962334
11972335 static unsigned long
11982336 dw_hdmi_rockchip_get_input_bus_format(void *data)
....@@ -1271,6 +2409,148 @@
12712409 return ret;
12722410 }
12732411
2412
+static int
2413
+dw_hdmi_rockchip_get_yuv422_format(struct drm_connector *connector,
2414
+ struct edid *edid)
2415
+{
2416
+ if (!connector || !edid)
2417
+ return -EINVAL;
2418
+
2419
+ return rockchip_drm_get_yuv422_format(connector, edid);
2420
+}
2421
+
2422
+static int
2423
+dw_hdmi_rockchip_get_edid_dsc_info(void *data, struct edid *edid)
2424
+{
2425
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2426
+
2427
+ if (!edid)
2428
+ return -EINVAL;
2429
+
2430
+ memset(&hdmi->dsc_cap, 0, sizeof(hdmi->dsc_cap));
2431
+ hdmi->max_frl_rate_per_lane = 0;
2432
+ hdmi->max_lanes = 0;
2433
+ hdmi->add_func = 0;
2434
+
2435
+ return rockchip_drm_parse_cea_ext(&hdmi->dsc_cap,
2436
+ &hdmi->max_frl_rate_per_lane,
2437
+ &hdmi->max_lanes, &hdmi->add_func, edid);
2438
+}
2439
+
2440
+static int
2441
+dw_hdmi_rockchip_get_next_hdr_data(void *data, struct edid *edid,
2442
+ struct drm_connector *connector)
2443
+{
2444
+ int ret;
2445
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2446
+ struct next_hdr_sink_data *sink_data = &hdmi->next_hdr_data;
2447
+ size_t size = sizeof(*sink_data);
2448
+ struct drm_property *property = hdmi->next_hdr_sink_data_property;
2449
+ struct drm_property_blob *blob = hdmi->hdr_panel_blob_ptr;
2450
+
2451
+ if (!edid)
2452
+ return -EINVAL;
2453
+
2454
+ rockchip_drm_parse_next_hdr(sink_data, edid);
2455
+
2456
+ ret = drm_property_replace_global_blob(connector->dev, &blob, size, sink_data,
2457
+ &connector->base, property);
2458
+
2459
+ return ret;
2460
+};
2461
+
2462
+static int dw_hdmi_rockchip_get_colorimetry(void *data, struct edid *edid)
2463
+{
2464
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2465
+
2466
+ return rockchip_drm_parse_colorimetry_data_block(&hdmi->edid_colorimetry, edid);
2467
+}
2468
+
2469
+static
2470
+struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
2471
+{
2472
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2473
+
2474
+ return &hdmi->link_cfg;
2475
+}
2476
+
2477
+static int dw_hdmi_rockchip_get_vp_id(struct drm_crtc_state *crtc_state)
2478
+{
2479
+ struct rockchip_crtc_state *s;
2480
+
2481
+ s = to_rockchip_crtc_state(crtc_state);
2482
+
2483
+ return s->vp_id;
2484
+}
2485
+
2486
+static int dw_hdmi_dclk_set(void *data, bool enable, int vp_id)
2487
+{
2488
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2489
+ char clk_name[16];
2490
+ struct clk *dclk;
2491
+ int ret;
2492
+
2493
+ snprintf(clk_name, sizeof(clk_name), "dclk_vp%d", vp_id);
2494
+
2495
+ dclk = devm_clk_get_optional(hdmi->dev, clk_name);
2496
+ if (IS_ERR(dclk)) {
2497
+ DRM_DEV_ERROR(hdmi->dev, "failed to get %s\n", clk_name);
2498
+ return PTR_ERR(dclk);
2499
+ } else if (!dclk) {
2500
+ if (hdmi->is_hdmi_qp) {
2501
+ DRM_DEV_ERROR(hdmi->dev, "failed to get %s\n", clk_name);
2502
+ return -ENOENT;
2503
+ }
2504
+
2505
+ return 0;
2506
+ }
2507
+
2508
+ if (enable) {
2509
+ ret = clk_prepare_enable(dclk);
2510
+ if (ret < 0)
2511
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable dclk for video port%d - %d\n",
2512
+ vp_id, ret);
2513
+ } else {
2514
+ clk_disable_unprepare(dclk);
2515
+ }
2516
+
2517
+ return 0;
2518
+}
2519
+
2520
+static int dw_hdmi_link_clk_set(void *data, bool enable)
2521
+{
2522
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
2523
+ u64 phy_clk = hdmi->phy_bus_width;
2524
+ int ret;
2525
+
2526
+ if (enable) {
2527
+ ret = clk_prepare_enable(hdmi->link_clk);
2528
+ if (ret < 0) {
2529
+ DRM_DEV_ERROR(hdmi->dev, "failed to enable link_clk %d\n", ret);
2530
+ return ret;
2531
+ }
2532
+
2533
+ if (((phy_clk & DATA_RATE_MASK) <= 6000000) &&
2534
+ (phy_clk & COLOR_DEPTH_10BIT))
2535
+ phy_clk = (phy_clk & DATA_RATE_MASK) * 10 * 8;
2536
+ else
2537
+ phy_clk = (phy_clk & DATA_RATE_MASK) * 100;
2538
+
2539
+ /*
2540
+ * To be compatible with vop dclk usage scenarios, hdmi phy pll clk
2541
+ * is set according to dclk rate.
2542
+ * But phy pll actual frequency will varies according to the color depth.
2543
+ * So we should get the actual frequency or clk_set_rate may not change
2544
+ * pll frequency when 8/10 bit switch.
2545
+ */
2546
+ clk_get_rate(hdmi->link_clk);
2547
+ clk_set_rate(hdmi->link_clk, phy_clk);
2548
+ } else {
2549
+ clk_disable_unprepare(hdmi->link_clk);
2550
+ }
2551
+ return 0;
2552
+}
2553
+
12742554 static bool
12752555 dw_hdmi_rockchip_check_hdr_color_change(struct drm_connector_state *conn_state,
12762556 void *data)
....@@ -1309,23 +2589,16 @@
13092589 }
13102590 }
13112591
1312
-static int dw_hdmi_rockchip_dclk_set(void *data, bool enable, int vp_id)
2592
+static void dw_hdmi_rockchip_set_hdcp14_mem(void *data, bool enable)
13132593 {
13142594 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1315
- int ret = 0;
2595
+ u32 val;
13162596
1317
- if (!hdmi->dclk_vop)
1318
- return 0;
1319
-
1320
- if (enable) {
1321
- ret = clk_prepare_enable(hdmi->dclk_vop);
1322
- if (ret < 0)
1323
- dev_err(hdmi->dev, "failed to enable dclk_vop\n");
1324
- } else {
1325
- clk_disable_unprepare(hdmi->dclk_vop);
1326
- }
1327
-
1328
- return ret;
2597
+ val = HIWORD_UPDATE(enable << 15, RK3588_HDMI_HDCP14_MEM_EN);
2598
+ if (!hdmi->id)
2599
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
2600
+ else
2601
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
13292602 }
13302603
13312604 static const struct drm_prop_enum_list color_depth_enum_list[] = {
....@@ -1335,24 +2608,19 @@
13352608 };
13362609
13372610 static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
1338
- { DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
1339
- { DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
1340
- { DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
1341
- { DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
1342
- { DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
1343
- { DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
1344
- { DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
2611
+ { RK_IF_FORMAT_RGB, "rgb" },
2612
+ { RK_IF_FORMAT_YCBCR444, "ycbcr444" },
2613
+ { RK_IF_FORMAT_YCBCR422, "ycbcr422" },
2614
+ { RK_IF_FORMAT_YCBCR420, "ycbcr420" },
2615
+ { RK_IF_FORMAT_YCBCR_HQ, "ycbcr_high_subsampling" },
2616
+ { RK_IF_FORMAT_YCBCR_LQ, "ycbcr_low_subsampling" },
2617
+ { RK_IF_FORMAT_MAX, "invalid_output" },
13452618 };
13462619
13472620 static const struct drm_prop_enum_list quant_range_enum_list[] = {
13482621 { HDMI_QUANTIZATION_RANGE_DEFAULT, "default" },
13492622 { HDMI_QUANTIZATION_RANGE_LIMITED, "limit" },
13502623 { HDMI_QUANTIZATION_RANGE_FULL, "full" },
1351
-};
1352
-
1353
-static const struct drm_prop_enum_list colorimetry_enum_list[] = {
1354
- { HDMI_COLORIMETRY_NONE, "None" },
1355
- { RK_HDMI_COLORIMETRY_BT2020, "ITU_2020" },
13562624 };
13572625
13582626 static const struct drm_prop_enum_list output_hdmi_dvi_enum_list[] = {
....@@ -1366,59 +2634,76 @@
13662634 { 1, "HDMI" },
13672635 };
13682636
2637
+static const struct drm_prop_enum_list allm_enable_list[] = {
2638
+ { 0, "disable" },
2639
+ { 1, "enable" },
2640
+};
2641
+
13692642 static void
13702643 dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
13712644 unsigned int color, int version,
1372
- void *data)
2645
+ void *data, bool allm_en)
13732646 {
13742647 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
13752648 struct drm_property *prop;
13762649 struct rockchip_drm_private *private = connector->dev->dev_private;
2650
+ int ret;
13772651
13782652 switch (color) {
13792653 case MEDIA_BUS_FMT_RGB101010_1X30:
1380
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB;
2654
+ hdmi->hdmi_output = RK_IF_FORMAT_RGB;
13812655 hdmi->colordepth = 10;
13822656 break;
13832657 case MEDIA_BUS_FMT_YUV8_1X24:
1384
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444;
2658
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444;
13852659 hdmi->colordepth = 8;
13862660 break;
13872661 case MEDIA_BUS_FMT_YUV10_1X30:
1388
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR444;
2662
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444;
13892663 hdmi->colordepth = 10;
13902664 break;
13912665 case MEDIA_BUS_FMT_UYVY10_1X20:
1392
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422;
2666
+ case MEDIA_BUS_FMT_YUYV10_1X20:
2667
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422;
13932668 hdmi->colordepth = 10;
13942669 break;
13952670 case MEDIA_BUS_FMT_UYVY8_1X16:
1396
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR422;
2671
+ case MEDIA_BUS_FMT_YUYV8_1X16:
2672
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422;
13972673 hdmi->colordepth = 8;
13982674 break;
13992675 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1400
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
2676
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420;
14012677 hdmi->colordepth = 8;
14022678 break;
14032679 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1404
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
2680
+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420;
14052681 hdmi->colordepth = 10;
14062682 break;
14072683 default:
1408
- hdmi->hdmi_output = DRM_HDMI_OUTPUT_DEFAULT_RGB;
2684
+ hdmi->hdmi_output = RK_IF_FORMAT_RGB;
14092685 hdmi->colordepth = 8;
14102686 }
14112687
14122688 hdmi->bus_format = color;
14132689 hdmi->prev_bus_format = color;
14142690
1415
- if (hdmi->hdmi_output == DRM_HDMI_OUTPUT_YCBCR422) {
1416
- if (hdmi->colordepth == 12)
1417
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
1418
- else if (hdmi->colordepth == 10)
1419
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
1420
- else
1421
- hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
2691
+ if (hdmi->hdmi_output == RK_IF_FORMAT_YCBCR422) {
2692
+ if (hdmi->is_hdmi_qp) {
2693
+ if (hdmi->colordepth == 12)
2694
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV12_1X24;
2695
+ else if (hdmi->colordepth == 10)
2696
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
2697
+ else
2698
+ hdmi->output_bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
2699
+ } else {
2700
+ if (hdmi->colordepth == 12)
2701
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24;
2702
+ else if (hdmi->colordepth == 10)
2703
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20;
2704
+ else
2705
+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16;
2706
+ }
14222707 } else {
14232708 hdmi->output_bus_format = hdmi->bus_format;
14242709 }
....@@ -1426,7 +2711,7 @@
14262711 /* RK3368 does not support deep color mode */
14272712 if (!hdmi->color_depth_property && !hdmi->unsupported_deep_color) {
14282713 prop = drm_property_create_enum(connector->dev, 0,
1429
- "hdmi_output_depth",
2714
+ RK_IF_PROP_COLOR_DEPTH,
14302715 color_depth_enum_list,
14312716 ARRAY_SIZE(color_depth_enum_list));
14322717 if (prop) {
....@@ -1435,7 +2720,7 @@
14352720 }
14362721 }
14372722
1438
- prop = drm_property_create_enum(connector->dev, 0, "hdmi_output_format",
2723
+ prop = drm_property_create_enum(connector->dev, 0, RK_IF_PROP_COLOR_FORMAT,
14392724 drm_hdmi_output_enum_list,
14402725 ARRAY_SIZE(drm_hdmi_output_enum_list));
14412726 if (prop) {
....@@ -1443,17 +2728,8 @@
14432728 drm_object_attach_property(&connector->base, prop, 0);
14442729 }
14452730
1446
- prop = drm_property_create_enum(connector->dev, 0,
1447
- "hdmi_output_colorimetry",
1448
- colorimetry_enum_list,
1449
- ARRAY_SIZE(colorimetry_enum_list));
1450
- if (prop) {
1451
- hdmi->colorimetry_property = prop;
1452
- drm_object_attach_property(&connector->base, prop, 0);
1453
- }
1454
-
14552731 prop = drm_property_create_range(connector->dev, 0,
1456
- "hdmi_color_depth_capacity",
2732
+ RK_IF_PROP_COLOR_DEPTH_CAPS,
14572733 0, 0xff);
14582734 if (prop) {
14592735 hdmi->colordepth_capacity = prop;
....@@ -1461,22 +2737,12 @@
14612737 }
14622738
14632739 prop = drm_property_create_range(connector->dev, 0,
1464
- "hdmi_output_mode_capacity",
2740
+ RK_IF_PROP_COLOR_FORMAT_CAPS,
14652741 0, 0xf);
14662742 if (prop) {
14672743 hdmi->outputmode_capacity = prop;
14682744 drm_object_attach_property(&connector->base, prop, 0);
14692745 }
1470
-
1471
- prop = drm_property_create_enum(connector->dev, 0,
1472
- "hdmi_quant_range",
1473
- quant_range_enum_list,
1474
- ARRAY_SIZE(quant_range_enum_list));
1475
- if (prop) {
1476
- hdmi->quant_range = prop;
1477
- drm_object_attach_property(&connector->base, prop, 0);
1478
- }
1479
-
14802746
14812747 prop = drm_property_create(connector->dev,
14822748 DRM_MODE_PROP_BLOB |
....@@ -1485,6 +2751,34 @@
14852751 if (prop) {
14862752 hdmi->hdr_panel_metadata_property = prop;
14872753 drm_object_attach_property(&connector->base, prop, 0);
2754
+ }
2755
+
2756
+ prop = drm_property_create(connector->dev,
2757
+ DRM_MODE_PROP_BLOB |
2758
+ DRM_MODE_PROP_IMMUTABLE,
2759
+ "NEXT_HDR_SINK_DATA", 0);
2760
+ if (prop) {
2761
+ hdmi->next_hdr_sink_data_property = prop;
2762
+ drm_object_attach_property(&connector->base, prop, 0);
2763
+ }
2764
+
2765
+ if (hdmi->is_hdmi_qp) {
2766
+ prop = drm_property_create_bool(connector->dev, 0, "allm_capacity");
2767
+ if (prop) {
2768
+ hdmi->allm_capacity = prop;
2769
+ drm_object_attach_property(&connector->base, prop,
2770
+ !!(hdmi->add_func & SUPPORT_HDMI_ALLM));
2771
+ }
2772
+
2773
+ prop = drm_property_create_enum(connector->dev, 0,
2774
+ "allm_enable",
2775
+ allm_enable_list,
2776
+ ARRAY_SIZE(allm_enable_list));
2777
+ if (prop) {
2778
+ hdmi->allm_enable = prop;
2779
+ drm_object_attach_property(&connector->base, prop, 0);
2780
+ }
2781
+ hdmi->enable_allm = allm_en;
14882782 }
14892783
14902784 prop = drm_property_create_enum(connector->dev, 0,
....@@ -1497,18 +2791,48 @@
14972791 }
14982792
14992793 prop = drm_property_create_enum(connector->dev, 0,
1500
- "output_type_capacity",
1501
- output_type_cap_list,
1502
- ARRAY_SIZE(output_type_cap_list));
2794
+ "output_type_capacity",
2795
+ output_type_cap_list,
2796
+ ARRAY_SIZE(output_type_cap_list));
15032797 if (prop) {
15042798 hdmi->output_type_capacity = prop;
15052799 drm_object_attach_property(&connector->base, prop, 0);
15062800 }
15072801
2802
+ if (!hdmi->is_hdmi_qp) {
2803
+ prop = drm_property_create_enum(connector->dev, 0,
2804
+ "hdmi_quant_range",
2805
+ quant_range_enum_list,
2806
+ ARRAY_SIZE(quant_range_enum_list));
2807
+ if (prop) {
2808
+ hdmi->quant_range = prop;
2809
+ drm_object_attach_property(&connector->base, prop, 0);
2810
+ }
2811
+ }
2812
+
15082813 prop = connector->dev->mode_config.hdr_output_metadata_property;
1509
- if (version >= 0x211a)
2814
+ if (hdmi->is_hdmi_qp)
15102815 drm_object_attach_property(&connector->base, prop, 0);
1511
- drm_object_attach_property(&connector->base, private->connector_id_prop, 0);
2816
+
2817
+ if (!drm_mode_create_hdmi_colorspace_property(connector))
2818
+ drm_object_attach_property(&connector->base,
2819
+ connector->colorspace_property, 0);
2820
+ drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id);
2821
+
2822
+ ret = drm_connector_attach_content_protection_property(connector, true);
2823
+ if (ret) {
2824
+ dev_err(hdmi->dev, "failed to attach content protection: %d\n", ret);
2825
+ return;
2826
+ }
2827
+
2828
+ prop = drm_property_create_range(connector->dev, 0, RK_IF_PROP_ENCRYPTED,
2829
+ RK_IF_HDCP_ENCRYPTED_NONE, RK_IF_HDCP_ENCRYPTED_LEVEL2);
2830
+ if (!prop) {
2831
+ dev_err(hdmi->dev, "create hdcp encrypted prop for hdmi%d failed\n", hdmi->id);
2832
+ return;
2833
+ }
2834
+ hdmi->hdcp_state_property = prop;
2835
+ drm_object_attach_property(&connector->base, prop, RK_IF_HDCP_ENCRYPTED_NONE);
15122836 }
15132837
15142838 static void
....@@ -1547,16 +2871,16 @@
15472871 hdmi->quant_range = NULL;
15482872 }
15492873
1550
- if (hdmi->colorimetry_property) {
1551
- drm_property_destroy(connector->dev,
1552
- hdmi->colorimetry_property);
1553
- hdmi->colordepth_capacity = NULL;
1554
- }
1555
-
15562874 if (hdmi->hdr_panel_metadata_property) {
15572875 drm_property_destroy(connector->dev,
15582876 hdmi->hdr_panel_metadata_property);
15592877 hdmi->hdr_panel_metadata_property = NULL;
2878
+ }
2879
+
2880
+ if (hdmi->next_hdr_sink_data_property) {
2881
+ drm_property_destroy(connector->dev,
2882
+ hdmi->next_hdr_sink_data_property);
2883
+ hdmi->next_hdr_sink_data_property = NULL;
15602884 }
15612885
15622886 if (hdmi->output_hdmi_dvi) {
....@@ -1569,6 +2893,17 @@
15692893 drm_property_destroy(connector->dev,
15702894 hdmi->output_type_capacity);
15712895 hdmi->output_type_capacity = NULL;
2896
+ }
2897
+
2898
+ if (hdmi->allm_capacity) {
2899
+ drm_property_destroy(connector->dev,
2900
+ hdmi->allm_capacity);
2901
+ hdmi->allm_capacity = NULL;
2902
+ }
2903
+
2904
+ if (hdmi->allm_enable) {
2905
+ drm_property_destroy(connector->dev, hdmi->allm_enable);
2906
+ hdmi->allm_enable = NULL;
15722907 }
15732908 }
15742909
....@@ -1606,14 +2941,16 @@
16062941 return 0;
16072942 } else if (property == config->hdr_output_metadata_property) {
16082943 return 0;
1609
- } else if (property == hdmi->colorimetry_property) {
1610
- hdmi->colorimetry = val;
1611
- return 0;
16122944 } else if (property == hdmi->output_hdmi_dvi) {
1613
- if (hdmi->force_output != val)
1614
- hdmi->color_changed++;
1615
- hdmi->force_output = val;
1616
- dw_hdmi_set_output_type(hdmi->hdmi, val);
2945
+ if (!hdmi->is_hdmi_qp) {
2946
+ if (hdmi->force_output != val)
2947
+ hdmi->color_changed++;
2948
+ hdmi->force_output = val;
2949
+ dw_hdmi_set_output_type(hdmi->hdmi, val);
2950
+ } else {
2951
+ hdmi->force_output = val;
2952
+ dw_hdmi_qp_set_output_type(hdmi->hdmi_qp, val);
2953
+ }
16172954 return 0;
16182955 } else if (property == hdmi->colordepth_capacity) {
16192956 return 0;
....@@ -1621,9 +2958,22 @@
16212958 return 0;
16222959 } else if (property == hdmi->output_type_capacity) {
16232960 return 0;
2961
+ } else if (property == hdmi->allm_capacity) {
2962
+ return 0;
2963
+ } else if (property == hdmi->allm_enable) {
2964
+ u64 allm_enable = hdmi->enable_allm;
2965
+
2966
+ hdmi->enable_allm = val;
2967
+ if (allm_enable != hdmi->enable_allm)
2968
+ dw_hdmi_qp_set_allm_enable(hdmi->hdmi_qp, hdmi->enable_allm);
2969
+ return 0;
2970
+ } else if (property == hdmi->hdcp_state_property) {
2971
+ return 0;
16242972 }
16252973
1626
- DRM_ERROR("failed to set rockchip hdmi connector property %s\n", property->name);
2974
+ DRM_ERROR("Unknown property [PROP:%d:%s]\n",
2975
+ property->base.id, property->name);
2976
+
16272977 return -EINVAL;
16282978 }
16292979
....@@ -1637,7 +2987,6 @@
16372987 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
16382988 struct drm_display_info *info = &connector->display_info;
16392989 struct drm_mode_config *config = &connector->dev->mode_config;
1640
- struct rockchip_drm_private *private = connector->dev->dev_private;
16412990
16422991 if (property == hdmi->color_depth_property) {
16432992 *val = hdmi->colordepth;
....@@ -1646,32 +2995,32 @@
16462995 *val = hdmi->hdmi_output;
16472996 return 0;
16482997 } else if (property == hdmi->colordepth_capacity) {
1649
- *val = BIT(ROCKCHIP_HDMI_DEPTH_8);
2998
+ *val = BIT(RK_IF_DEPTH_8);
16502999 /* RK3368 only support 8bit */
16513000 if (hdmi->unsupported_deep_color)
16523001 return 0;
16533002 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
1654
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_10);
3003
+ *val |= BIT(RK_IF_DEPTH_10);
16553004 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)
1656
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_12);
3005
+ *val |= BIT(RK_IF_DEPTH_12);
16573006 if (info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_48)
1658
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_16);
3007
+ *val |= BIT(RK_IF_DEPTH_16);
16593008 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
1660
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_10);
3009
+ *val |= BIT(RK_IF_DEPTH_420_10);
16613010 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
1662
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_12);
3011
+ *val |= BIT(RK_IF_DEPTH_420_12);
16633012 if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)
1664
- *val |= BIT(ROCKCHIP_HDMI_DEPTH_420_16);
3013
+ *val |= BIT(RK_IF_DEPTH_420_16);
16653014 return 0;
16663015 } else if (property == hdmi->outputmode_capacity) {
1667
- *val = BIT(DRM_HDMI_OUTPUT_DEFAULT_RGB);
3016
+ *val = BIT(RK_IF_FORMAT_RGB);
16683017 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
1669
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR444);
3018
+ *val |= BIT(RK_IF_FORMAT_YCBCR444);
16703019 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
1671
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR422);
3020
+ *val |= BIT(RK_IF_FORMAT_YCBCR422);
16723021 if (connector->ycbcr_420_allowed &&
16733022 info->color_formats & DRM_COLOR_FORMAT_YCRCB420)
1674
- *val |= BIT(DRM_HDMI_OUTPUT_YCBCR420);
3023
+ *val |= BIT(RK_IF_FORMAT_YCBCR420);
16753024 return 0;
16763025 } else if (property == hdmi->quant_range) {
16773026 *val = hdmi->hdmi_quant_range;
....@@ -1680,21 +3029,34 @@
16803029 *val = state->hdr_output_metadata ?
16813030 state->hdr_output_metadata->base.id : 0;
16823031 return 0;
1683
- } else if (property == hdmi->colorimetry_property) {
1684
- *val = hdmi->colorimetry;
1685
- return 0;
1686
- } else if (property == private->connector_id_prop) {
1687
- *val = hdmi->id;
1688
- return 0;
16893032 } else if (property == hdmi->output_hdmi_dvi) {
16903033 *val = hdmi->force_output;
16913034 return 0;
16923035 } else if (property == hdmi->output_type_capacity) {
1693
- *val = dw_hdmi_get_output_type_cap(hdmi->hdmi);
3036
+ if (!hdmi->is_hdmi_qp)
3037
+ *val = dw_hdmi_get_output_type_cap(hdmi->hdmi);
3038
+ else
3039
+ *val = dw_hdmi_qp_get_output_type_cap(hdmi->hdmi_qp);
3040
+ return 0;
3041
+ } else if (property == hdmi->allm_capacity) {
3042
+ *val = !!(hdmi->add_func & SUPPORT_HDMI_ALLM);
3043
+ return 0;
3044
+ } else if (property == hdmi->allm_enable) {
3045
+ *val = hdmi->enable_allm;
3046
+ return 0;
3047
+ } else if (property == hdmi->hdcp_state_property) {
3048
+ if (hdmi->hdcp_status & BIT(1))
3049
+ *val = RK_IF_HDCP_ENCRYPTED_LEVEL2;
3050
+ else if (hdmi->hdcp_status & BIT(0))
3051
+ *val = RK_IF_HDCP_ENCRYPTED_LEVEL1;
3052
+ else
3053
+ *val = RK_IF_HDCP_ENCRYPTED_NONE;
16943054 return 0;
16953055 }
16963056
1697
- DRM_ERROR("failed to get rockchip hdmi connector property %s\n", property->name);
3057
+ DRM_ERROR("Unknown property [PROP:%d:%s]\n",
3058
+ property->base.id, property->name);
3059
+
16983060 return -EINVAL;
16993061 }
17003062
....@@ -1705,6 +3067,36 @@
17053067 .get_property = dw_hdmi_rockchip_get_property,
17063068 };
17073069
3070
+static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
3071
+ struct drm_display_mode *mode,
3072
+ struct drm_display_mode *adj)
3073
+{
3074
+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
3075
+ struct drm_crtc *crtc;
3076
+ struct rockchip_crtc_state *s;
3077
+
3078
+ if (!encoder->crtc)
3079
+ return;
3080
+ crtc = encoder->crtc;
3081
+
3082
+ if (!crtc->state)
3083
+ return;
3084
+ s = to_rockchip_crtc_state(crtc->state);
3085
+
3086
+ if (!s)
3087
+ return;
3088
+
3089
+ if (hdmi->is_hdmi_qp) {
3090
+ s->dsc_enable = 0;
3091
+ if (hdmi->link_cfg.dsc_mode)
3092
+ dw_hdmi_qp_dsc_configure(hdmi, s, crtc->state);
3093
+
3094
+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
3095
+ }
3096
+
3097
+ clk_set_rate(hdmi->phyref_clk, adj->crtc_clock * 1000);
3098
+}
3099
+
17083100 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
17093101 .enable = dw_hdmi_rockchip_encoder_enable,
17103102 .disable = dw_hdmi_rockchip_encoder_disable,
....@@ -1712,7 +3104,8 @@
17123104 .mode_set = dw_hdmi_rockchip_encoder_mode_set,
17133105 };
17143106
1715
-static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
3107
+static void
3108
+dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data)
17163109 {
17173110 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
17183111
....@@ -1720,13 +3113,15 @@
17203113 phy_power_off(hdmi->phy);
17213114 }
17223115
1723
-static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
1724
- struct drm_display_mode *mode)
3116
+static int
3117
+dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
3118
+ const struct drm_display_info *display,
3119
+ const struct drm_display_mode *mode)
17253120 {
17263121 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
17273122
17283123 dw_hdmi_rockchip_genphy_disable(dw_hdmi, data);
1729
- dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi);
3124
+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display);
17303125 return phy_power_on(hdmi->phy);
17313126 }
17323127
....@@ -1736,10 +3131,17 @@
17363131
17373132 dw_hdmi_phy_setup_hpd(dw_hdmi, data);
17383133
1739
- regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2,
1740
- RK3228_DDC_MASK_EN);
1741
- regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6,
1742
- RK3228_IO_3V_DOMAIN);
3134
+ regmap_write(hdmi->regmap,
3135
+ RK3228_GRF_SOC_CON6,
3136
+ HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL |
3137
+ RK3228_HDMI_SCL_VSEL,
3138
+ RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL |
3139
+ RK3228_HDMI_SCL_VSEL));
3140
+
3141
+ regmap_write(hdmi->regmap,
3142
+ RK3228_GRF_SOC_CON2,
3143
+ HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK,
3144
+ RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK));
17433145 }
17443146
17453147 static enum drm_connector_status
....@@ -1787,6 +3189,90 @@
17873189 RK3328_HDMI_HPD_IOE));
17883190 }
17893191
3192
+static void dw_hdmi_qp_rockchip_phy_disable(struct dw_hdmi_qp *dw_hdmi,
3193
+ void *data)
3194
+{
3195
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3196
+
3197
+ while (hdmi->phy->power_count > 0)
3198
+ phy_power_off(hdmi->phy);
3199
+}
3200
+
3201
+static int dw_hdmi_qp_rockchip_genphy_init(struct dw_hdmi_qp *dw_hdmi, void *data,
3202
+ struct drm_display_mode *mode)
3203
+{
3204
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3205
+
3206
+ dw_hdmi_qp_rockchip_phy_disable(dw_hdmi, data);
3207
+
3208
+ return phy_power_on(hdmi->phy);
3209
+}
3210
+
3211
+static enum drm_connector_status
3212
+dw_hdmi_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
3213
+{
3214
+ u32 val;
3215
+ int ret;
3216
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3217
+
3218
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
3219
+
3220
+ if (!hdmi->id) {
3221
+ if (val & RK3588_HDMI0_LEVEL_INT) {
3222
+ hdmi->hpd_stat = true;
3223
+ ret = connector_status_connected;
3224
+ } else {
3225
+ hdmi->hpd_stat = false;
3226
+ ret = connector_status_disconnected;
3227
+ }
3228
+ } else {
3229
+ if (val & RK3588_HDMI1_LEVEL_INT) {
3230
+ hdmi->hpd_stat = true;
3231
+ ret = connector_status_connected;
3232
+ } else {
3233
+ hdmi->hpd_stat = false;
3234
+ ret = connector_status_disconnected;
3235
+ }
3236
+ }
3237
+
3238
+ return ret;
3239
+}
3240
+
3241
+static void dw_hdmi_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
3242
+{
3243
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3244
+ u32 val;
3245
+
3246
+ if (!hdmi->id) {
3247
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
3248
+ RK3588_HDMI0_HPD_INT_CLR) |
3249
+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
3250
+ } else {
3251
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
3252
+ RK3588_HDMI1_HPD_INT_CLR) |
3253
+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK);
3254
+ }
3255
+
3256
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
3257
+}
3258
+
3259
+static void dw_hdmi_rk3588_phy_set_mode(struct dw_hdmi_qp *dw_hdmi, void *data,
3260
+ u32 mode_mask, bool enable)
3261
+{
3262
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
3263
+
3264
+ if (!hdmi->phy)
3265
+ return;
3266
+
3267
+ /* set phy earc/frl mode */
3268
+ if (enable)
3269
+ hdmi->phy_bus_width |= mode_mask;
3270
+ else
3271
+ hdmi->phy_bus_width &= ~mode_mask;
3272
+
3273
+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
3274
+}
3275
+
17903276 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = {
17913277 .init = dw_hdmi_rockchip_genphy_init,
17923278 .disable = dw_hdmi_rockchip_genphy_disable,
....@@ -1801,11 +3287,14 @@
18013287
18023288 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
18033289 .mode_valid = dw_hdmi_rockchip_mode_valid,
3290
+ .mpll_cfg = rockchip_mpll_cfg,
3291
+ .cur_ctr = rockchip_cur_ctr,
18043292 .phy_config = rockchip_phy_config,
1805
- .phy_data = &rk3228_chip_data,
1806
- .phy_ops = &rk3228_hdmi_phy_ops,
1807
- .phy_name = "inno_dw_hdmi_phy",
3293
+ .phy_data = &rk3228_chip_data,
3294
+ .phy_ops = &rk3228_hdmi_phy_ops,
3295
+ .phy_name = "inno_dw_hdmi_phy2",
18083296 .phy_force_vendor = true,
3297
+ .max_tmdsclk = 371250,
18093298 .ycbcr_420_allowed = true,
18103299 };
18113300
....@@ -1823,6 +3312,7 @@
18233312 .phy_config = rockchip_phy_config,
18243313 .phy_data = &rk3288_chip_data,
18253314 .tmds_n_table = rockchip_werid_tmds_n_table,
3315
+ .unsupported_yuv_input = true,
18263316 .ycbcr_420_allowed = true,
18273317 };
18283318
....@@ -1861,6 +3351,8 @@
18613351 .phy_ops = &rk3328_hdmi_phy_ops,
18623352 .phy_name = "inno_dw_hdmi_phy2",
18633353 .phy_force_vendor = true,
3354
+ .use_drm_infoframe = true,
3355
+ .max_tmdsclk = 371250,
18643356 .ycbcr_420_allowed = true,
18653357 };
18663358
....@@ -1875,6 +3367,8 @@
18753367 .cur_ctr = rockchip_cur_ctr,
18763368 .phy_config = rockchip_phy_config,
18773369 .phy_data = &rk3368_chip_data,
3370
+ .unsupported_deep_color = true,
3371
+ .max_tmdsclk = 340000,
18783372 .ycbcr_420_allowed = true,
18793373 };
18803374
....@@ -1891,6 +3385,7 @@
18913385 .cur_ctr = rockchip_cur_ctr,
18923386 .phy_config = rockchip_phy_config,
18933387 .phy_data = &rk3399_chip_data,
3388
+ .use_drm_infoframe = true,
18943389 .ycbcr_420_allowed = true,
18953390 };
18963391
....@@ -1907,6 +3402,7 @@
19073402 .phy_ops = &rk3528_hdmi_phy_ops,
19083403 .phy_name = "inno_dw_hdmi_phy2",
19093404 .phy_force_vendor = true,
3405
+ .use_drm_infoframe = true,
19103406 .ycbcr_420_allowed = true,
19113407 };
19123408
....@@ -1917,12 +3413,38 @@
19173413
19183414 static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
19193415 .mode_valid = dw_hdmi_rockchip_mode_valid,
1920
- .mpll_cfg = rockchip_mpll_cfg_rk356x,
3416
+ .mpll_cfg = rockchip_mpll_cfg,
19213417 .mpll_cfg_420 = rockchip_mpll_cfg_420,
1922
- .cur_ctr = rockchip_cur_ctr_rk356x,
3418
+ .cur_ctr = rockchip_cur_ctr,
19233419 .phy_config = rockchip_phy_config,
19243420 .phy_data = &rk3568_chip_data,
19253421 .ycbcr_420_allowed = true,
3422
+ .use_drm_infoframe = true,
3423
+};
3424
+
3425
+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
3426
+ .init = dw_hdmi_qp_rockchip_genphy_init,
3427
+ .disable = dw_hdmi_qp_rockchip_phy_disable,
3428
+ .read_hpd = dw_hdmi_rk3588_read_hpd,
3429
+ .setup_hpd = dw_hdmi_rk3588_setup_hpd,
3430
+ .set_mode = dw_hdmi_rk3588_phy_set_mode,
3431
+};
3432
+
3433
+struct rockchip_hdmi_chip_data rk3588_hdmi_chip_data = {
3434
+ .lcdsel_grf_reg = -1,
3435
+ .ddc_en_reg = RK3588_GRF_VO1_CON3,
3436
+ .split_mode = true,
3437
+};
3438
+
3439
+static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
3440
+ .mode_valid = dw_hdmi_rockchip_mode_valid,
3441
+ .phy_data = &rk3588_hdmi_chip_data,
3442
+ .qp_phy_ops = &rk3588_hdmi_phy_ops,
3443
+ .phy_name = "samsung_hdptx_phy",
3444
+ .phy_force_vendor = true,
3445
+ .ycbcr_420_allowed = true,
3446
+ .is_hdmi_qp = true,
3447
+ .use_drm_infoframe = true,
19263448 };
19273449
19283450 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
....@@ -1948,6 +3470,9 @@
19483470 { .compatible = "rockchip,rk3568-dw-hdmi",
19493471 .data = &rk3568_hdmi_drv_data
19503472 },
3473
+ { .compatible = "rockchip,rk3588-dw-hdmi",
3474
+ .data = &rk3588_hdmi_drv_data
3475
+ },
19513476 {},
19523477 };
19533478 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
....@@ -1956,32 +3481,24 @@
19563481 void *data)
19573482 {
19583483 struct platform_device *pdev = to_platform_device(dev);
1959
- struct dw_hdmi_plat_data *plat_data;
1960
- const struct of_device_id *match;
19613484 struct drm_device *drm = data;
19623485 struct drm_encoder *encoder;
19633486 struct rockchip_hdmi *hdmi;
1964
- int ret, id;
3487
+ struct dw_hdmi_plat_data *plat_data;
3488
+ struct rockchip_hdmi *secondary;
3489
+ int ret;
3490
+ u32 val;
19653491
19663492 if (!pdev->dev.of_node)
19673493 return -ENODEV;
19683494
1969
- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
3495
+ hdmi = platform_get_drvdata(pdev);
19703496 if (!hdmi)
19713497 return -ENOMEM;
19723498
1973
- match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
1974
- plat_data = devm_kmemdup(&pdev->dev, match->data,
1975
- sizeof(*plat_data), GFP_KERNEL);
1976
- if (!plat_data)
1977
- return -ENOMEM;
3499
+ plat_data = hdmi->plat_data;
3500
+ hdmi->drm_dev = drm;
19783501
1979
- id = of_alias_get_id(dev->of_node, "hdmi");
1980
- if (id < 0)
1981
- id = 0;
1982
- hdmi->id = id;
1983
- hdmi->dev = &pdev->dev;
1984
- hdmi->chip_data = plat_data->phy_data;
19853502 plat_data->phy_data = hdmi;
19863503 plat_data->get_input_bus_format =
19873504 dw_hdmi_rockchip_get_input_bus_format;
....@@ -1999,6 +3516,24 @@
19993516 dw_hdmi_rockchip_get_hdr_blob;
20003517 plat_data->get_color_changed =
20013518 dw_hdmi_rockchip_get_color_changed;
3519
+ plat_data->get_yuv422_format =
3520
+ dw_hdmi_rockchip_get_yuv422_format;
3521
+ plat_data->get_edid_dsc_info =
3522
+ dw_hdmi_rockchip_get_edid_dsc_info;
3523
+ plat_data->get_next_hdr_data =
3524
+ dw_hdmi_rockchip_get_next_hdr_data;
3525
+ plat_data->get_colorimetry =
3526
+ dw_hdmi_rockchip_get_colorimetry;
3527
+ plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg;
3528
+ plat_data->set_hdcp2_enable = rk3588_set_hdcp2_enable;
3529
+ plat_data->set_hdcp_status = rk3588_set_hdcp_status;
3530
+ plat_data->set_grf_cfg = rk3588_set_grf_cfg;
3531
+ plat_data->get_grf_color_fmt = rk3588_get_grf_color_fmt;
3532
+ plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode;
3533
+ plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode;
3534
+ plat_data->dclk_set = dw_hdmi_dclk_set;
3535
+ plat_data->link_clk_set = dw_hdmi_link_clk_set;
3536
+ plat_data->get_vp_id = dw_hdmi_rockchip_get_vp_id;
20023537 plat_data->update_color_format =
20033538 dw_hdmi_rockchip_update_color_format;
20043539 plat_data->check_hdr_color_change =
....@@ -2007,25 +3542,95 @@
20073542 dw_hdmi_rockchip_set_prev_bus_format;
20083543 plat_data->set_ddc_io =
20093544 dw_hdmi_rockchip_set_ddc_io;
2010
- plat_data->dclk_set =
2011
- dw_hdmi_rockchip_dclk_set;
3545
+ plat_data->set_hdcp14_mem =
3546
+ dw_hdmi_rockchip_set_hdcp14_mem;
20123547 plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
20133548
2014
- encoder = &hdmi->encoder;
3549
+ secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id);
3550
+ /* If don't enable hdmi0 and hdmi1, we don't enable split mode */
3551
+ if (hdmi->chip_data->split_mode && secondary) {
20153552
2016
- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
2017
- /*
2018
- * If we failed to find the CRTC(s) which this encoder is
2019
- * supposed to be connected to, it's because the CRTC has
2020
- * not been registered yet. Defer probing, and hope that
2021
- * the required CRTC is added later.
2022
- */
2023
- if (encoder->possible_crtcs == 0)
2024
- return -EPROBE_DEFER;
3553
+ /*
3554
+ * hdmi can only attach bridge and init encoder/connector in the
3555
+ * last bind hdmi in split mode, or hdmi->hdmi_qp will not be initialized
3556
+ * and plat_data->left/right will be null pointer. we must check if split
3557
+ * mode is on and determine the sequence of hdmi bind.
3558
+ */
3559
+ if (device_property_read_bool(dev, "split-mode") ||
3560
+ device_property_read_bool(secondary->dev, "split-mode")) {
3561
+ plat_data->split_mode = true;
3562
+ secondary->plat_data->split_mode = true;
3563
+ if (!secondary->plat_data->first_screen)
3564
+ plat_data->first_screen = true;
3565
+ }
3566
+ }
3567
+
3568
+ if (!plat_data->first_screen) {
3569
+ encoder = &hdmi->encoder;
3570
+ encoder->possible_crtcs = rockchip_drm_of_find_possible_crtcs(drm, dev->of_node);
3571
+ /*
3572
+ * If we failed to find the CRTC(s) which this encoder is
3573
+ * supposed to be connected to, it's because the CRTC has
3574
+ * not been registered yet. Defer probing, and hope that
3575
+ * the required CRTC is added later.
3576
+ */
3577
+ if (encoder->possible_crtcs == 0)
3578
+ return -EPROBE_DEFER;
3579
+
3580
+ drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
3581
+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
3582
+ }
3583
+
3584
+ if (!plat_data->max_tmdsclk)
3585
+ hdmi->max_tmdsclk = 594000;
3586
+ else
3587
+ hdmi->max_tmdsclk = plat_data->max_tmdsclk;
3588
+
3589
+ hdmi->is_hdmi_qp = plat_data->is_hdmi_qp;
3590
+
3591
+ hdmi->unsupported_yuv_input = plat_data->unsupported_yuv_input;
3592
+ hdmi->unsupported_deep_color = plat_data->unsupported_deep_color;
20253593
20263594 ret = rockchip_hdmi_parse_dt(hdmi);
20273595 if (ret) {
20283596 DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
3597
+ return ret;
3598
+ }
3599
+
3600
+ ret = clk_prepare_enable(hdmi->aud_clk);
3601
+ if (ret) {
3602
+ dev_err(hdmi->dev, "Failed to enable HDMI aud_clk: %d\n", ret);
3603
+ return ret;
3604
+ }
3605
+
3606
+ ret = clk_prepare_enable(hdmi->hpd_clk);
3607
+ if (ret) {
3608
+ dev_err(hdmi->dev, "Failed to enable HDMI hpd_clk: %d\n", ret);
3609
+ return ret;
3610
+ }
3611
+
3612
+ ret = clk_prepare_enable(hdmi->hclk_vo1);
3613
+ if (ret) {
3614
+ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vo1: %d\n", ret);
3615
+ return ret;
3616
+ }
3617
+
3618
+ ret = clk_prepare_enable(hdmi->earc_clk);
3619
+ if (ret) {
3620
+ dev_err(hdmi->dev, "Failed to enable HDMI earc_clk: %d\n", ret);
3621
+ return ret;
3622
+ }
3623
+
3624
+ ret = clk_prepare_enable(hdmi->hdmitx_ref);
3625
+ if (ret) {
3626
+ dev_err(hdmi->dev, "Failed to enable HDMI hdmitx_ref: %d\n",
3627
+ ret);
3628
+ return ret;
3629
+ }
3630
+
3631
+ ret = clk_prepare_enable(hdmi->pclk);
3632
+ if (ret) {
3633
+ dev_err(hdmi->dev, "Failed to enable HDMI pclk: %d\n", ret);
20293634 return ret;
20303635 }
20313636
....@@ -2035,6 +3640,39 @@
20353640 RK3568_HDMI_SCLIN_MSK,
20363641 RK3568_HDMI_SDAIN_MSK |
20373642 RK3568_HDMI_SCLIN_MSK));
3643
+ }
3644
+
3645
+ if (hdmi->is_hdmi_qp) {
3646
+ if (!hdmi->id) {
3647
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3648
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3649
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3650
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3651
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
3652
+
3653
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3654
+ RK3588_SET_HPD_PATH_MASK);
3655
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3656
+
3657
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
3658
+ RK3588_HDMI0_GRANT_SEL);
3659
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3660
+ } else {
3661
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3662
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3663
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3664
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3665
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
3666
+
3667
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3668
+ RK3588_SET_HPD_PATH_MASK);
3669
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3670
+
3671
+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
3672
+ RK3588_HDMI1_GRANT_SEL);
3673
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3674
+ }
3675
+ init_hpd_work(hdmi);
20383676 }
20393677
20403678 ret = clk_prepare_enable(hdmi->phyref_clk);
....@@ -2058,6 +3696,26 @@
20583696 return ret;
20593697 }
20603698
3699
+ if (hdmi->is_hdmi_qp) {
3700
+ if (!hdmi->id)
3701
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
3702
+ else
3703
+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK);
3704
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
3705
+
3706
+ hdmi->hpd_irq = platform_get_irq(pdev, 4);
3707
+ if (hdmi->hpd_irq < 0)
3708
+ return hdmi->hpd_irq;
3709
+
3710
+ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq,
3711
+ rockchip_hdmi_hardirq,
3712
+ rockchip_hdmi_irq,
3713
+ IRQF_SHARED, "dw-hdmi-qp-hpd",
3714
+ hdmi);
3715
+ if (ret)
3716
+ return ret;
3717
+ }
3718
+
20613719 hdmi->phy = devm_phy_optional_get(dev, "hdmi");
20623720 if (IS_ERR(hdmi->phy)) {
20633721 hdmi->phy = devm_phy_optional_get(dev, "hdmi_phy");
....@@ -2069,22 +3727,68 @@
20693727 }
20703728 }
20713729
2072
- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
2073
- drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
2074
- DRM_MODE_ENCODER_TMDS, NULL);
3730
+ if (hdmi->is_hdmi_qp) {
3731
+ hdmi->hdmi_qp = dw_hdmi_qp_bind(pdev, &hdmi->encoder, plat_data);
20753732
2076
- platform_set_drvdata(pdev, hdmi);
3733
+ if (IS_ERR(hdmi->hdmi_qp)) {
3734
+ ret = PTR_ERR(hdmi->hdmi_qp);
3735
+ drm_encoder_cleanup(&hdmi->encoder);
3736
+ }
20773737
2078
- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
3738
+ if (plat_data->bridge) {
3739
+ struct drm_connector *connector = NULL;
3740
+ struct list_head *connector_list =
3741
+ &plat_data->bridge->dev->mode_config.connector_list;
3742
+
3743
+ list_for_each_entry(connector, connector_list, head)
3744
+ if (drm_connector_has_possible_encoder(connector,
3745
+ &hdmi->encoder))
3746
+ break;
3747
+
3748
+ hdmi->sub_dev.connector = connector;
3749
+ hdmi->sub_dev.of_node = dev->of_node;
3750
+ rockchip_drm_register_sub_dev(&hdmi->sub_dev);
3751
+ } else if (plat_data->connector) {
3752
+ hdmi->sub_dev.connector = plat_data->connector;
3753
+ hdmi->sub_dev.loader_protect = dw_hdmi_rockchip_encoder_loader_protect;
3754
+ if (secondary && device_property_read_bool(secondary->dev, "split-mode"))
3755
+ hdmi->sub_dev.of_node = secondary->dev->of_node;
3756
+ else
3757
+ hdmi->sub_dev.of_node = hdmi->dev->of_node;
3758
+
3759
+ rockchip_drm_register_sub_dev(&hdmi->sub_dev);
3760
+ }
3761
+
3762
+ if (plat_data->split_mode && secondary) {
3763
+ if (device_property_read_bool(dev, "split-mode")) {
3764
+ plat_data->right = secondary->hdmi_qp;
3765
+ secondary->plat_data->left = hdmi->hdmi_qp;
3766
+ } else {
3767
+ plat_data->left = secondary->hdmi_qp;
3768
+ secondary->plat_data->right = hdmi->hdmi_qp;
3769
+ }
3770
+ }
3771
+
3772
+ return ret;
3773
+ }
3774
+
3775
+ hdmi->hdmi = dw_hdmi_bind(pdev, &hdmi->encoder, plat_data);
3776
+
20793777 /*
20803778 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
20813779 * which would have called the encoder cleanup. Do it manually.
20823780 */
20833781 if (IS_ERR(hdmi->hdmi)) {
20843782 ret = PTR_ERR(hdmi->hdmi);
2085
- drm_encoder_cleanup(encoder);
3783
+ drm_encoder_cleanup(&hdmi->encoder);
3784
+ clk_disable_unprepare(hdmi->aud_clk);
20863785 clk_disable_unprepare(hdmi->phyref_clk);
20873786 clk_disable_unprepare(hdmi->hclk_vop);
3787
+ clk_disable_unprepare(hdmi->hpd_clk);
3788
+ clk_disable_unprepare(hdmi->hclk_vo1);
3789
+ clk_disable_unprepare(hdmi->earc_clk);
3790
+ clk_disable_unprepare(hdmi->hdmitx_ref);
3791
+ clk_disable_unprepare(hdmi->pclk);
20883792 }
20893793
20903794 if (plat_data->connector) {
....@@ -2101,11 +3805,27 @@
21013805 {
21023806 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
21033807
3808
+ if (hdmi->is_hdmi_qp) {
3809
+ cancel_delayed_work(&hdmi->work);
3810
+ flush_workqueue(hdmi->workqueue);
3811
+ destroy_workqueue(hdmi->workqueue);
3812
+ }
3813
+
21043814 if (hdmi->sub_dev.connector)
21053815 rockchip_drm_unregister_sub_dev(&hdmi->sub_dev);
2106
- dw_hdmi_unbind(hdmi->hdmi);
3816
+
3817
+ if (hdmi->is_hdmi_qp)
3818
+ dw_hdmi_qp_unbind(hdmi->hdmi_qp);
3819
+ else
3820
+ dw_hdmi_unbind(hdmi->hdmi);
3821
+ clk_disable_unprepare(hdmi->aud_clk);
21073822 clk_disable_unprepare(hdmi->phyref_clk);
21083823 clk_disable_unprepare(hdmi->hclk_vop);
3824
+ clk_disable_unprepare(hdmi->hpd_clk);
3825
+ clk_disable_unprepare(hdmi->hclk_vo1);
3826
+ clk_disable_unprepare(hdmi->earc_clk);
3827
+ clk_disable_unprepare(hdmi->hdmitx_ref);
3828
+ clk_disable_unprepare(hdmi->pclk);
21093829 }
21103830
21113831 static const struct component_ops dw_hdmi_rockchip_ops = {
....@@ -2115,6 +3835,33 @@
21153835
21163836 static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
21173837 {
3838
+ struct rockchip_hdmi *hdmi;
3839
+ const struct of_device_id *match;
3840
+ struct dw_hdmi_plat_data *plat_data;
3841
+ int id;
3842
+
3843
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
3844
+ if (!hdmi)
3845
+ return -ENOMEM;
3846
+
3847
+ id = of_alias_get_id(pdev->dev.of_node, "hdmi");
3848
+ if (id < 0)
3849
+ id = 0;
3850
+
3851
+ hdmi->id = id;
3852
+ hdmi->dev = &pdev->dev;
3853
+
3854
+ match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
3855
+ plat_data = devm_kmemdup(&pdev->dev, match->data,
3856
+ sizeof(*plat_data), GFP_KERNEL);
3857
+ if (!plat_data)
3858
+ return -ENOMEM;
3859
+
3860
+ plat_data->id = hdmi->id;
3861
+ hdmi->plat_data = plat_data;
3862
+ hdmi->chip_data = plat_data->phy_data;
3863
+
3864
+ platform_set_drvdata(pdev, hdmi);
21183865 pm_runtime_enable(&pdev->dev);
21193866 pm_runtime_get_sync(&pdev->dev);
21203867
....@@ -2123,17 +3870,25 @@
21233870
21243871 static void dw_hdmi_rockchip_shutdown(struct platform_device *pdev)
21253872 {
2126
- struct rockchip_hdmi *hdmi = platform_get_drvdata(pdev);
3873
+ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
21273874
21283875 if (!hdmi)
21293876 return;
21303877
2131
- if (hdmi->hpd_gpiod) {
2132
- disable_irq(hdmi->hpd_irq);
2133
- if (hdmi->hpd_wake_en)
2134
- disable_irq_wake(hdmi->hpd_irq);
3878
+ if (hdmi->is_hdmi_qp) {
3879
+ if (hdmi->hpd_irq)
3880
+ disable_irq(hdmi->hpd_irq);
3881
+ cancel_delayed_work(&hdmi->work);
3882
+ flush_workqueue(hdmi->workqueue);
3883
+ dw_hdmi_qp_suspend(hdmi->dev, hdmi->hdmi_qp);
3884
+ } else {
3885
+ if (hdmi->hpd_gpiod) {
3886
+ disable_irq(hdmi->hpd_irq);
3887
+ if (hdmi->hpd_wake_en)
3888
+ disable_irq_wake(hdmi->hpd_irq);
3889
+ }
3890
+ dw_hdmi_suspend(hdmi->hdmi);
21353891 }
2136
- dw_hdmi_suspend(&pdev->dev, hdmi->hdmi);
21373892 pm_runtime_put_sync(&pdev->dev);
21383893 }
21393894
....@@ -2149,9 +3904,15 @@
21493904 {
21503905 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
21513906
2152
- if (hdmi->hpd_gpiod)
2153
- disable_irq(hdmi->hpd_irq);
2154
- dw_hdmi_suspend(dev, hdmi->hdmi);
3907
+ if (hdmi->is_hdmi_qp) {
3908
+ if (hdmi->hpd_irq)
3909
+ disable_irq(hdmi->hpd_irq);
3910
+ dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp);
3911
+ } else {
3912
+ if (hdmi->hpd_gpiod)
3913
+ disable_irq(hdmi->hpd_irq);
3914
+ dw_hdmi_suspend(hdmi->hdmi);
3915
+ }
21553916 pm_runtime_put_sync(dev);
21563917
21573918 return 0;
....@@ -2160,18 +3921,56 @@
21603921 static int dw_hdmi_rockchip_resume(struct device *dev)
21613922 {
21623923 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
3924
+ u32 val;
21633925
2164
- if (hdmi->hpd_gpiod) {
2165
- dw_hdmi_rk3528_gpio_hpd_init(hdmi);
2166
- enable_irq(hdmi->hpd_irq);
3926
+ if (hdmi->is_hdmi_qp) {
3927
+ if (!hdmi->id) {
3928
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3929
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3930
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3931
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3932
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val);
3933
+
3934
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3935
+ RK3588_SET_HPD_PATH_MASK);
3936
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3937
+
3938
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
3939
+ RK3588_HDMI0_GRANT_SEL);
3940
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3941
+ } else {
3942
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
3943
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
3944
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
3945
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
3946
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
3947
+
3948
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
3949
+ RK3588_SET_HPD_PATH_MASK);
3950
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
3951
+
3952
+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
3953
+ RK3588_HDMI1_GRANT_SEL);
3954
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val);
3955
+ }
3956
+
3957
+ dw_hdmi_qp_resume(dev, hdmi->hdmi_qp);
3958
+ if (hdmi->hpd_irq)
3959
+ enable_irq(hdmi->hpd_irq);
3960
+ drm_helper_hpd_irq_event(hdmi->drm_dev);
3961
+ } else {
3962
+ if (hdmi->hpd_gpiod) {
3963
+ dw_hdmi_rk3528_gpio_hpd_init(hdmi);
3964
+ enable_irq(hdmi->hpd_irq);
3965
+ }
3966
+ dw_hdmi_resume(hdmi->hdmi);
21673967 }
21683968 pm_runtime_get_sync(dev);
2169
- dw_hdmi_resume(dev, hdmi->hdmi);
21703969
2171
- return 0;
3970
+ return 0;
21723971 }
21733972
2174
-static const struct dev_pm_ops dw_hdmi_pm_ops = {
3973
+static const struct dev_pm_ops dw_hdmi_rockchip_pm = {
21753974 SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend,
21763975 dw_hdmi_rockchip_resume)
21773976 };
....@@ -2182,7 +3981,7 @@
21823981 .shutdown = dw_hdmi_rockchip_shutdown,
21833982 .driver = {
21843983 .name = "dwhdmi-rockchip",
3984
+ .pm = &dw_hdmi_rockchip_pm,
21853985 .of_match_table = dw_hdmi_rockchip_dt_ids,
2186
- .pm = &dw_hdmi_pm_ops,
21873986 },
21883987 };