aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-08-24 22:35:35 -0400
committerDave Airlie <airlied@redhat.com>2016-08-24 22:35:35 -0400
commit78acdd4a7e5a5de56c4ac1e10390a98b7c605ed6 (patch)
tree1825104346edc7eeb41bad49c64a3692c26e3efd
parent0d42204f374380b6334de7dd2fe7e7d795250290 (diff)
parent808263393198b9b0f9d53b9983330fb4298851ec (diff)
Merge branch 'for-next' of git://people.freedesktop.org/~seanpaul/dogwood into drm-next
This pull request contains the following rockchip drm changes: - Introduce support for rk3399 vop/crtc - Add PSR framework to the rockchip driver - Implement PSR in the rockchip analogix edp driver - Fix panel on/off in analogix to avoid damaging panels - Some miscellaneous fixes to clean up logs and code readability * 'for-next' of git://people.freedesktop.org/~seanpaul/dogwood: drm/rockchip: analogix_dp: drop unnecessary probe deferral "error" print drm/rockchip: Enable vblank without event drm/rockchip: Improve analogix-dp psr handling drm/rockchip: A couple small fixes to psr drm/rockchip: Use a spinlock to protect psr state drm/rockchip: Don't use a delayed worker for psr state changes drm/rockchip: Convert psr_list_mutex to spinlock and use it drm/rockchip: analogix_dp: implement PSR function drm/bridge: analogix_dp: add the PSR function support drm/rockchip: add an common abstracted PSR driver drm/rockchip: vop: export line flag function drm/bridge: analogix_dp: Ensure the panel is properly prepared/unprepared dt-bindings: add compatible strings for big/little rockchip vops dt-bindings: sort Rockchip vop compatible by chip's number drm/rockchip: vop: add rk3399 vop support drm/rockchip: vop: introduce VOP_REG_MASK drm/rockchip: sort registers define by chip's number
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt4
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c182
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.h8
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c51
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h34
-rw-r--r--drivers/gpu/drm/rockchip/Makefile2
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c70
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c12
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.c245
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.h26
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c198
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h7
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c242
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.h193
-rw-r--r--include/drm/bridge/analogix_dp.h3
17 files changed, 1168 insertions, 118 deletions
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
index 5489b59e3d41..9eb3f0a2a078 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
@@ -6,8 +6,10 @@ buffer to an external LCD interface.
6 6
7Required properties: 7Required properties:
8- compatible: value should be one of the following 8- compatible: value should be one of the following
9 "rockchip,rk3288-vop";
10 "rockchip,rk3036-vop"; 9 "rockchip,rk3036-vop";
10 "rockchip,rk3288-vop";
11 "rockchip,rk3399-vop-big";
12 "rockchip,rk3399-vop-lit";
11 13
12- interrupts: should contain a list of all VOP IP block interrupts in the 14- interrupts: should contain a list of all VOP IP block interrupts in the
13 order: VSYNC, LCD_SYSTEM. The interrupt specifier 15 order: VSYNC, LCD_SYSTEM. The interrupt specifier
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715daf73cb..efac8aba6776 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
97 return 0; 97 return 0;
98} 98}
99 99
100int analogix_dp_enable_psr(struct device *dev)
101{
102 struct analogix_dp_device *dp = dev_get_drvdata(dev);
103 struct edp_vsc_psr psr_vsc;
104
105 if (!dp->psr_support)
106 return -EINVAL;
107
108 /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
109 memset(&psr_vsc, 0, sizeof(psr_vsc));
110 psr_vsc.sdp_header.HB0 = 0;
111 psr_vsc.sdp_header.HB1 = 0x7;
112 psr_vsc.sdp_header.HB2 = 0x2;
113 psr_vsc.sdp_header.HB3 = 0x8;
114
115 psr_vsc.DB0 = 0;
116 psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
117
118 analogix_dp_send_psr_spd(dp, &psr_vsc);
119 return 0;
120}
121EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
122
123int analogix_dp_disable_psr(struct device *dev)
124{
125 struct analogix_dp_device *dp = dev_get_drvdata(dev);
126 struct edp_vsc_psr psr_vsc;
127
128 if (!dp->psr_support)
129 return -EINVAL;
130
131 /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
132 memset(&psr_vsc, 0, sizeof(psr_vsc));
133 psr_vsc.sdp_header.HB0 = 0;
134 psr_vsc.sdp_header.HB1 = 0x7;
135 psr_vsc.sdp_header.HB2 = 0x2;
136 psr_vsc.sdp_header.HB3 = 0x8;
137
138 psr_vsc.DB0 = 0;
139 psr_vsc.DB1 = 0;
140
141 analogix_dp_send_psr_spd(dp, &psr_vsc);
142 return 0;
143}
144EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
145
146static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
147{
148 unsigned char psr_version;
149
150 analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, &psr_version);
151 dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
152
153 return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
154}
155
156static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
157{
158 unsigned char psr_en;
159
160 /* Disable psr function */
161 analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, &psr_en);
162 psr_en &= ~DP_PSR_ENABLE;
163 analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
164
165 /* Main-Link transmitter remains active during PSR active states */
166 psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
167 analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
168
169 /* Enable psr function */
170 psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
171 DP_PSR_CRC_VERIFICATION;
172 analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
173
174 analogix_dp_enable_psr_crc(dp);
175}
176
100static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) 177static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
101{ 178{
102 int i; 179 int i;
@@ -921,13 +998,69 @@ static void analogix_dp_commit(struct analogix_dp_device *dp)
921 998
922 /* Enable video */ 999 /* Enable video */
923 analogix_dp_start_video(dp); 1000 analogix_dp_start_video(dp);
1001
1002 dp->psr_support = analogix_dp_detect_sink_psr(dp);
1003 if (dp->psr_support)
1004 analogix_dp_enable_sink_psr(dp);
1005}
1006
1007/*
1008 * This function is a bit of a catch-all for panel preparation, hopefully
1009 * simplifying the logic of functions that need to prepare/unprepare the panel
1010 * below.
1011 *
1012 * If @prepare is true, this function will prepare the panel. Conversely, if it
1013 * is false, the panel will be unprepared.
1014 *
1015 * If @is_modeset_prepare is true, the function will disregard the current state
1016 * of the panel and either prepare/unprepare the panel based on @prepare. Once
1017 * it finishes, it will update dp->panel_is_modeset to reflect the current state
1018 * of the panel.
1019 */
1020static int analogix_dp_prepare_panel(struct analogix_dp_device *dp,
1021 bool prepare, bool is_modeset_prepare)
1022{
1023 int ret = 0;
1024
1025 if (!dp->plat_data->panel)
1026 return 0;
1027
1028 mutex_lock(&dp->panel_lock);
1029
1030 /*
1031 * Exit early if this is a temporary prepare/unprepare and we're already
1032 * modeset (since we neither want to prepare twice or unprepare early).
1033 */
1034 if (dp->panel_is_modeset && !is_modeset_prepare)
1035 goto out;
1036
1037 if (prepare)
1038 ret = drm_panel_prepare(dp->plat_data->panel);
1039 else
1040 ret = drm_panel_unprepare(dp->plat_data->panel);
1041
1042 if (ret)
1043 goto out;
1044
1045 if (is_modeset_prepare)
1046 dp->panel_is_modeset = prepare;
1047
1048out:
1049 mutex_unlock(&dp->panel_lock);
1050 return ret;
924} 1051}
925 1052
926int analogix_dp_get_modes(struct drm_connector *connector) 1053int analogix_dp_get_modes(struct drm_connector *connector)
927{ 1054{
928 struct analogix_dp_device *dp = to_dp(connector); 1055 struct analogix_dp_device *dp = to_dp(connector);
929 struct edid *edid = (struct edid *)dp->edid; 1056 struct edid *edid = (struct edid *)dp->edid;
930 int num_modes = 0; 1057 int ret, num_modes = 0;
1058
1059 ret = analogix_dp_prepare_panel(dp, true, false);
1060 if (ret) {
1061 DRM_ERROR("Failed to prepare panel (%d)\n", ret);
1062 return 0;
1063 }
931 1064
932 if (analogix_dp_handle_edid(dp) == 0) { 1065 if (analogix_dp_handle_edid(dp) == 0) {
933 drm_mode_connector_update_edid_property(&dp->connector, edid); 1066 drm_mode_connector_update_edid_property(&dp->connector, edid);
@@ -940,6 +1073,10 @@ int analogix_dp_get_modes(struct drm_connector *connector)
940 if (dp->plat_data->get_modes) 1073 if (dp->plat_data->get_modes)
941 num_modes += dp->plat_data->get_modes(dp->plat_data, connector); 1074 num_modes += dp->plat_data->get_modes(dp->plat_data, connector);
942 1075
1076 ret = analogix_dp_prepare_panel(dp, false, false);
1077 if (ret)
1078 DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
1079
943 return num_modes; 1080 return num_modes;
944} 1081}
945 1082
@@ -960,11 +1097,23 @@ enum drm_connector_status
960analogix_dp_detect(struct drm_connector *connector, bool force) 1097analogix_dp_detect(struct drm_connector *connector, bool force)
961{ 1098{
962 struct analogix_dp_device *dp = to_dp(connector); 1099 struct analogix_dp_device *dp = to_dp(connector);
1100 enum drm_connector_status status = connector_status_disconnected;
1101 int ret;
963 1102
964 if (analogix_dp_detect_hpd(dp)) 1103 ret = analogix_dp_prepare_panel(dp, true, false);
1104 if (ret) {
1105 DRM_ERROR("Failed to prepare panel (%d)\n", ret);
965 return connector_status_disconnected; 1106 return connector_status_disconnected;
1107 }
1108
1109 if (!analogix_dp_detect_hpd(dp))
1110 status = connector_status_connected;
966 1111
967 return connector_status_connected; 1112 ret = analogix_dp_prepare_panel(dp, false, false);
1113 if (ret)
1114 DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
1115
1116 return status;
968} 1117}
969 1118
970static void analogix_dp_connector_destroy(struct drm_connector *connector) 1119static void analogix_dp_connector_destroy(struct drm_connector *connector)
@@ -1035,6 +1184,16 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
1035 return 0; 1184 return 0;
1036} 1185}
1037 1186
1187static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge)
1188{
1189 struct analogix_dp_device *dp = bridge->driver_private;
1190 int ret;
1191
1192 ret = analogix_dp_prepare_panel(dp, true, true);
1193 if (ret)
1194 DRM_ERROR("failed to setup the panel ret = %d\n", ret);
1195}
1196
1038static void analogix_dp_bridge_enable(struct drm_bridge *bridge) 1197static void analogix_dp_bridge_enable(struct drm_bridge *bridge)
1039{ 1198{
1040 struct analogix_dp_device *dp = bridge->driver_private; 1199 struct analogix_dp_device *dp = bridge->driver_private;
@@ -1058,6 +1217,7 @@ static void analogix_dp_bridge_enable(struct drm_bridge *bridge)
1058static void analogix_dp_bridge_disable(struct drm_bridge *bridge) 1217static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
1059{ 1218{
1060 struct analogix_dp_device *dp = bridge->driver_private; 1219 struct analogix_dp_device *dp = bridge->driver_private;
1220 int ret;
1061 1221
1062 if (dp->dpms_mode != DRM_MODE_DPMS_ON) 1222 if (dp->dpms_mode != DRM_MODE_DPMS_ON)
1063 return; 1223 return;
@@ -1077,6 +1237,10 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
1077 1237
1078 pm_runtime_put_sync(dp->dev); 1238 pm_runtime_put_sync(dp->dev);
1079 1239
1240 ret = analogix_dp_prepare_panel(dp, false, true);
1241 if (ret)
1242 DRM_ERROR("failed to setup the panel ret = %d\n", ret);
1243
1080 dp->dpms_mode = DRM_MODE_DPMS_OFF; 1244 dp->dpms_mode = DRM_MODE_DPMS_OFF;
1081} 1245}
1082 1246
@@ -1165,9 +1329,9 @@ static void analogix_dp_bridge_nop(struct drm_bridge *bridge)
1165} 1329}
1166 1330
1167static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { 1331static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
1332 .pre_enable = analogix_dp_bridge_pre_enable,
1168 .enable = analogix_dp_bridge_enable, 1333 .enable = analogix_dp_bridge_enable,
1169 .disable = analogix_dp_bridge_disable, 1334 .disable = analogix_dp_bridge_disable,
1170 .pre_enable = analogix_dp_bridge_nop,
1171 .post_disable = analogix_dp_bridge_nop, 1335 .post_disable = analogix_dp_bridge_nop,
1172 .mode_set = analogix_dp_bridge_mode_set, 1336 .mode_set = analogix_dp_bridge_mode_set,
1173 .attach = analogix_dp_bridge_attach, 1337 .attach = analogix_dp_bridge_attach,
@@ -1254,6 +1418,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
1254 dp->dev = &pdev->dev; 1418 dp->dev = &pdev->dev;
1255 dp->dpms_mode = DRM_MODE_DPMS_OFF; 1419 dp->dpms_mode = DRM_MODE_DPMS_OFF;
1256 1420
1421 mutex_init(&dp->panel_lock);
1422 dp->panel_is_modeset = false;
1423
1257 /* 1424 /*
1258 * platform dp driver need containor_of the plat_data to get 1425 * platform dp driver need containor_of the plat_data to get
1259 * the driver private data, so we need to store the point of 1426 * the driver private data, so we need to store the point of
@@ -1333,13 +1500,6 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
1333 1500
1334 phy_power_on(dp->phy); 1501 phy_power_on(dp->phy);
1335 1502
1336 if (dp->plat_data->panel) {
1337 if (drm_panel_prepare(dp->plat_data->panel)) {
1338 DRM_ERROR("failed to setup the panel\n");
1339 return -EBUSY;
1340 }
1341 }
1342
1343 analogix_dp_init_dp(dp); 1503 analogix_dp_init_dp(dp);
1344 1504
1345 ret = devm_request_threaded_irq(&pdev->dev, dp->irq, 1505 ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index b45638043ec4..473b9802b2d6 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -177,6 +177,10 @@ struct analogix_dp_device {
177 int hpd_gpio; 177 int hpd_gpio;
178 bool force_hpd; 178 bool force_hpd;
179 unsigned char edid[EDID_BLOCK_LENGTH * 2]; 179 unsigned char edid[EDID_BLOCK_LENGTH * 2];
180 bool psr_support;
181
182 struct mutex panel_lock;
183 bool panel_is_modeset;
180 184
181 struct analogix_dp_plat_data *plat_data; 185 struct analogix_dp_plat_data *plat_data;
182}; 186};
@@ -278,4 +282,8 @@ int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp);
278void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); 282void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp);
279void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); 283void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
280void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); 284void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
285void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
286void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
287 struct edp_vsc_psr *vsc);
288
281#endif /* _ANALOGIX_DP_CORE_H */ 289#endif /* _ANALOGIX_DP_CORE_H */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 48030f0cf497..52c1b6b2982e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1322,3 +1322,54 @@ void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
1322 reg |= SCRAMBLING_DISABLE; 1322 reg |= SCRAMBLING_DISABLE;
1323 writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); 1323 writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
1324} 1324}
1325
1326void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp)
1327{
1328 writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
1329}
1330
1331void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
1332 struct edp_vsc_psr *vsc)
1333{
1334 unsigned int val;
1335
1336 /* don't send info frame */
1337 val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1338 val &= ~IF_EN;
1339 writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1340
1341 /* configure single frame update mode */
1342 writel(PSR_FRAME_UP_TYPE_BURST | PSR_CRC_SEL_HARDWARE,
1343 dp->reg_base + ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL);
1344
1345 /* configure VSC HB0~HB3 */
1346 writel(vsc->sdp_header.HB0, dp->reg_base + ANALOGIX_DP_SPD_HB0);
1347 writel(vsc->sdp_header.HB1, dp->reg_base + ANALOGIX_DP_SPD_HB1);
1348 writel(vsc->sdp_header.HB2, dp->reg_base + ANALOGIX_DP_SPD_HB2);
1349 writel(vsc->sdp_header.HB3, dp->reg_base + ANALOGIX_DP_SPD_HB3);
1350
1351 /* configure reused VSC PB0~PB3, magic number from vendor */
1352 writel(0x00, dp->reg_base + ANALOGIX_DP_SPD_PB0);
1353 writel(0x16, dp->reg_base + ANALOGIX_DP_SPD_PB1);
1354 writel(0xCE, dp->reg_base + ANALOGIX_DP_SPD_PB2);
1355 writel(0x5D, dp->reg_base + ANALOGIX_DP_SPD_PB3);
1356
1357 /* configure DB0 / DB1 values */
1358 writel(vsc->DB0, dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB0);
1359 writel(vsc->DB1, dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB1);
1360
1361 /* set reuse spd inforframe */
1362 val = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
1363 val |= REUSE_SPD_EN;
1364 writel(val, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
1365
1366 /* mark info frame update */
1367 val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1368 val = (val | IF_UP) & ~IF_EN;
1369 writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1370
1371 /* send info frame */
1372 val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1373 val |= IF_EN;
1374 writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
1375}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index cdcc6c5add5e..40200c652533 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -22,6 +22,8 @@
22#define ANALOGIX_DP_VIDEO_CTL_8 0x3C 22#define ANALOGIX_DP_VIDEO_CTL_8 0x3C
23#define ANALOGIX_DP_VIDEO_CTL_10 0x44 23#define ANALOGIX_DP_VIDEO_CTL_10 0x44
24 24
25#define ANALOGIX_DP_SPDIF_AUDIO_CTL_0 0xD8
26
25#define ANALOGIX_DP_PLL_REG_1 0xfc 27#define ANALOGIX_DP_PLL_REG_1 0xfc
26#define ANALOGIX_DP_PLL_REG_2 0x9e4 28#define ANALOGIX_DP_PLL_REG_2 0x9e4
27#define ANALOGIX_DP_PLL_REG_3 0x9e8 29#define ANALOGIX_DP_PLL_REG_3 0x9e8
@@ -30,6 +32,21 @@
30 32
31#define ANALOGIX_DP_PD 0x12c 33#define ANALOGIX_DP_PD 0x12c
32 34
35#define ANALOGIX_DP_IF_TYPE 0x244
36#define ANALOGIX_DP_IF_PKT_DB1 0x254
37#define ANALOGIX_DP_IF_PKT_DB2 0x258
38#define ANALOGIX_DP_SPD_HB0 0x2F8
39#define ANALOGIX_DP_SPD_HB1 0x2FC
40#define ANALOGIX_DP_SPD_HB2 0x300
41#define ANALOGIX_DP_SPD_HB3 0x304
42#define ANALOGIX_DP_SPD_PB0 0x308
43#define ANALOGIX_DP_SPD_PB1 0x30C
44#define ANALOGIX_DP_SPD_PB2 0x310
45#define ANALOGIX_DP_SPD_PB3 0x314
46#define ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL 0x318
47#define ANALOGIX_DP_VSC_SHADOW_DB0 0x31C
48#define ANALOGIX_DP_VSC_SHADOW_DB1 0x320
49
33#define ANALOGIX_DP_LANE_MAP 0x35C 50#define ANALOGIX_DP_LANE_MAP 0x35C
34 51
35#define ANALOGIX_DP_ANALOG_CTL_1 0x370 52#define ANALOGIX_DP_ANALOG_CTL_1 0x370
@@ -103,6 +120,8 @@
103 120
104#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 121#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800
105 122
123#define ANALOGIX_DP_CRC_CON 0x890
124
106/* ANALOGIX_DP_TX_SW_RESET */ 125/* ANALOGIX_DP_TX_SW_RESET */
107#define RESET_DP_TX (0x1 << 0) 126#define RESET_DP_TX (0x1 << 0)
108 127
@@ -151,6 +170,7 @@
151#define VID_CHK_UPDATE_TYPE_SHIFT (4) 170#define VID_CHK_UPDATE_TYPE_SHIFT (4)
152#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) 171#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
153#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) 172#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
173#define REUSE_SPD_EN (0x1 << 3)
154 174
155/* ANALOGIX_DP_VIDEO_CTL_8 */ 175/* ANALOGIX_DP_VIDEO_CTL_8 */
156#define VID_HRES_TH(x) (((x) & 0xf) << 4) 176#define VID_HRES_TH(x) (((x) & 0xf) << 4)
@@ -167,6 +187,12 @@
167#define REF_CLK_27M (0x0 << 0) 187#define REF_CLK_27M (0x0 << 0)
168#define REF_CLK_MASK (0x1 << 0) 188#define REF_CLK_MASK (0x1 << 0)
169 189
190/* ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL */
191#define PSR_FRAME_UP_TYPE_BURST (0x1 << 0)
192#define PSR_FRAME_UP_TYPE_SINGLE (0x0 << 0)
193#define PSR_CRC_SEL_HARDWARE (0x1 << 1)
194#define PSR_CRC_SEL_MANUALLY (0x0 << 1)
195
170/* ANALOGIX_DP_LANE_MAP */ 196/* ANALOGIX_DP_LANE_MAP */
171#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) 197#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
172#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) 198#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
@@ -376,4 +402,12 @@
376#define VIDEO_MODE_SLAVE_MODE (0x1 << 0) 402#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
377#define VIDEO_MODE_MASTER_MODE (0x0 << 0) 403#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
378 404
405/* ANALOGIX_DP_PKT_SEND_CTL */
406#define IF_UP (0x1 << 4)
407#define IF_EN (0x1 << 0)
408
409/* ANALOGIX_DP_CRC_CON */
410#define PSR_VID_CRC_FLUSH (0x1 << 2)
411#define PSR_VID_CRC_ENABLE (0x1 << 0)
412
379#endif /* _ANALOGIX_DP_REG_H */ 413#endif /* _ANALOGIX_DP_REG_H */
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 05d07138a2b2..9746365694ba 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,7 +3,7 @@
3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. 3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
4 4
5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ 5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
6 rockchip_drm_gem.o rockchip_drm_vop.o 6 rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
7rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o 7rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
8 8
9obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o 9obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 0e63ee25bef8..e83be157cc2a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -32,6 +32,7 @@
32#include <drm/bridge/analogix_dp.h> 32#include <drm/bridge/analogix_dp.h>
33 33
34#include "rockchip_drm_drv.h" 34#include "rockchip_drm_drv.h"
35#include "rockchip_drm_psr.h"
35#include "rockchip_drm_vop.h" 36#include "rockchip_drm_vop.h"
36 37
37#define RK3288_GRF_SOC_CON6 0x25c 38#define RK3288_GRF_SOC_CON6 0x25c
@@ -41,6 +42,8 @@
41 42
42#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 43#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
43 44
45#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS 100
46
44#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm) 47#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm)
45 48
46/** 49/**
@@ -68,11 +71,62 @@ struct rockchip_dp_device {
68 struct regmap *grf; 71 struct regmap *grf;
69 struct reset_control *rst; 72 struct reset_control *rst;
70 73
74 struct work_struct psr_work;
75 spinlock_t psr_lock;
76 unsigned int psr_state;
77
71 const struct rockchip_dp_chip_data *data; 78 const struct rockchip_dp_chip_data *data;
72 79
73 struct analogix_dp_plat_data plat_data; 80 struct analogix_dp_plat_data plat_data;
74}; 81};
75 82
83static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
84{
85 struct rockchip_dp_device *dp = to_dp(encoder);
86 unsigned long flags;
87
88 dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
89
90 spin_lock_irqsave(&dp->psr_lock, flags);
91 if (enabled)
92 dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
93 else
94 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
95
96 schedule_work(&dp->psr_work);
97 spin_unlock_irqrestore(&dp->psr_lock, flags);
98}
99
100static void analogix_dp_psr_work(struct work_struct *work)
101{
102 struct rockchip_dp_device *dp =
103 container_of(work, typeof(*dp), psr_work);
104 struct drm_crtc *crtc = dp->encoder.crtc;
105 int psr_state = dp->psr_state;
106 int vact_end;
107 int ret;
108 unsigned long flags;
109
110 if (!crtc)
111 return;
112
113 vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
114
115 ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
116 PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
117 if (ret) {
118 dev_err(dp->dev, "line flag interrupt did not arrive\n");
119 return;
120 }
121
122 spin_lock_irqsave(&dp->psr_lock, flags);
123 if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
124 analogix_dp_enable_psr(dp->dev);
125 else
126 analogix_dp_disable_psr(dp->dev);
127 spin_unlock_irqrestore(&dp->psr_lock, flags);
128}
129
76static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) 130static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
77{ 131{
78 reset_control_assert(dp->rst); 132 reset_control_assert(dp->rst);
@@ -87,6 +141,8 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
87 struct rockchip_dp_device *dp = to_dp(plat_data); 141 struct rockchip_dp_device *dp = to_dp(plat_data);
88 int ret; 142 int ret;
89 143
144 cancel_work_sync(&dp->psr_work);
145
90 ret = clk_prepare_enable(dp->pclk); 146 ret = clk_prepare_enable(dp->pclk);
91 if (ret < 0) { 147 if (ret < 0) {
92 dev_err(dp->dev, "failed to enable pclk %d\n", ret); 148 dev_err(dp->dev, "failed to enable pclk %d\n", ret);
@@ -342,12 +398,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
342 dp->plat_data.power_off = rockchip_dp_powerdown; 398 dp->plat_data.power_off = rockchip_dp_powerdown;
343 dp->plat_data.get_modes = rockchip_dp_get_modes; 399 dp->plat_data.get_modes = rockchip_dp_get_modes;
344 400
401 spin_lock_init(&dp->psr_lock);
402 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
403 INIT_WORK(&dp->psr_work, analogix_dp_psr_work);
404
405 rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
406
345 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); 407 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
346} 408}
347 409
348static void rockchip_dp_unbind(struct device *dev, struct device *master, 410static void rockchip_dp_unbind(struct device *dev, struct device *master,
349 void *data) 411 void *data)
350{ 412{
413 struct rockchip_dp_device *dp = dev_get_drvdata(dev);
414
415 rockchip_drm_psr_unregister(&dp->encoder);
416
351 return analogix_dp_unbind(dev, master, data); 417 return analogix_dp_unbind(dev, master, data);
352} 418}
353 419
@@ -381,10 +447,8 @@ static int rockchip_dp_probe(struct platform_device *pdev)
381 447
382 panel = of_drm_find_panel(panel_node); 448 panel = of_drm_find_panel(panel_node);
383 of_node_put(panel_node); 449 of_node_put(panel_node);
384 if (!panel) { 450 if (!panel)
385 DRM_ERROR("failed to find panel\n");
386 return -EPROBE_DEFER; 451 return -EPROBE_DEFER;
387 }
388 } 452 }
389 453
390 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); 454 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index a822d49a255a..76eaf1de52e4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)
156 156
157 drm_dev->dev_private = private; 157 drm_dev->dev_private = private;
158 158
159 INIT_LIST_HEAD(&private->psr_list);
160 spin_lock_init(&private->psr_list_lock);
161
159 drm_mode_config_init(drm_dev); 162 drm_mode_config_init(drm_dev);
160 163
161 rockchip_drm_mode_config_init(drm_dev); 164 rockchip_drm_mode_config_init(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea3932940061..5c698456aa1c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -61,6 +61,9 @@ struct rockchip_drm_private {
61 struct drm_gem_object *fbdev_bo; 61 struct drm_gem_object *fbdev_bo;
62 const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; 62 const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
63 struct drm_atomic_state *state; 63 struct drm_atomic_state *state;
64
65 struct list_head psr_list;
66 spinlock_t psr_list_lock;
64}; 67};
65 68
66int rockchip_register_crtc_funcs(struct drm_crtc *crtc, 69int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -70,4 +73,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
70 struct device *dev); 73 struct device *dev);
71void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 74void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
72 struct device *dev); 75 struct device *dev);
76int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
77 unsigned int mstimeout);
78
73#endif /* _ROCKCHIP_DRM_DRV_H_ */ 79#endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 55c52734c52d..ba45d9d8bb62 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -22,6 +22,7 @@
22#include "rockchip_drm_drv.h" 22#include "rockchip_drm_drv.h"
23#include "rockchip_drm_fb.h" 23#include "rockchip_drm_fb.h"
24#include "rockchip_drm_gem.h" 24#include "rockchip_drm_gem.h"
25#include "rockchip_drm_psr.h"
25 26
26#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb) 27#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
27 28
@@ -63,9 +64,20 @@ static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
63 rockchip_fb->obj[0], handle); 64 rockchip_fb->obj[0], handle);
64} 65}
65 66
67static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
68 struct drm_file *file,
69 unsigned int flags, unsigned int color,
70 struct drm_clip_rect *clips,
71 unsigned int num_clips)
72{
73 rockchip_drm_psr_flush(fb->dev);
74 return 0;
75}
76
66static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { 77static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
67 .destroy = rockchip_drm_fb_destroy, 78 .destroy = rockchip_drm_fb_destroy,
68 .create_handle = rockchip_drm_fb_create_handle, 79 .create_handle = rockchip_drm_fb_create_handle,
80 .dirty = rockchip_drm_fb_dirty,
69}; 81};
70 82
71static struct rockchip_drm_fb * 83static struct rockchip_drm_fb *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
new file mode 100644
index 000000000000..c6ac5d01c8e4
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -0,0 +1,245 @@
1/*
2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author: Yakir Yang <ykk@rock-chips.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <drm/drmP.h>
16#include <drm/drm_crtc_helper.h>
17
18#include "rockchip_drm_drv.h"
19#include "rockchip_drm_psr.h"
20
21#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(3000) /* 3 seconds */
22
23enum psr_state {
24 PSR_FLUSH,
25 PSR_ENABLE,
26 PSR_DISABLE,
27};
28
29struct psr_drv {
30 struct list_head list;
31 struct drm_encoder *encoder;
32
33 spinlock_t lock;
34 enum psr_state state;
35
36 struct timer_list flush_timer;
37
38 void (*set)(struct drm_encoder *encoder, bool enable);
39};
40
41static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
42{
43 struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
44 struct psr_drv *psr;
45 unsigned long flags;
46
47 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
48 list_for_each_entry(psr, &drm_drv->psr_list, list) {
49 if (psr->encoder->crtc == crtc)
50 goto out;
51 }
52 psr = ERR_PTR(-ENODEV);
53
54out:
55 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
56 return psr;
57}
58
59static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
60{
61 /*
62 * Allowed finite state machine:
63 *
64 * PSR_ENABLE < = = = = = > PSR_FLUSH
65 * | ^ |
66 * | | |
67 * v | |
68 * PSR_DISABLE < - - - - - - - - -
69 */
70 if (state == psr->state)
71 return;
72
73 /* Requesting a flush when disabled is a noop */
74 if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
75 return;
76
77 psr->state = state;
78
79 /* Already disabled in flush, change the state, but not the hardware */
80 if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
81 return;
82
83 /* Actually commit the state change to hardware */
84 switch (psr->state) {
85 case PSR_ENABLE:
86 psr->set(psr->encoder, true);
87 break;
88
89 case PSR_DISABLE:
90 case PSR_FLUSH:
91 psr->set(psr->encoder, false);
92 break;
93 }
94}
95
96static void psr_set_state(struct psr_drv *psr, enum psr_state state)
97{
98 unsigned long flags;
99
100 spin_lock_irqsave(&psr->lock, flags);
101 psr_set_state_locked(psr, state);
102 spin_unlock_irqrestore(&psr->lock, flags);
103}
104
105static void psr_flush_handler(unsigned long data)
106{
107 struct psr_drv *psr = (struct psr_drv *)data;
108 unsigned long flags;
109
110 /* If the state has changed since we initiated the flush, do nothing */
111 spin_lock_irqsave(&psr->lock, flags);
112 if (psr->state == PSR_FLUSH)
113 psr_set_state_locked(psr, PSR_ENABLE);
114 spin_unlock_irqrestore(&psr->lock, flags);
115}
116
117/**
118 * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
119 * @crtc: CRTC to obtain the PSR encoder
120 *
121 * Returns:
122 * Zero on success, negative errno on failure.
123 */
124int rockchip_drm_psr_enable(struct drm_crtc *crtc)
125{
126 struct psr_drv *psr = find_psr_by_crtc(crtc);
127
128 if (IS_ERR(psr))
129 return PTR_ERR(psr);
130
131 psr_set_state(psr, PSR_ENABLE);
132 return 0;
133}
134EXPORT_SYMBOL(rockchip_drm_psr_enable);
135
136/**
137 * rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC
138 * @crtc: CRTC to obtain the PSR encoder
139 *
140 * Returns:
141 * Zero on success, negative errno on failure.
142 */
143int rockchip_drm_psr_disable(struct drm_crtc *crtc)
144{
145 struct psr_drv *psr = find_psr_by_crtc(crtc);
146
147 if (IS_ERR(psr))
148 return PTR_ERR(psr);
149
150 psr_set_state(psr, PSR_DISABLE);
151 return 0;
152}
153EXPORT_SYMBOL(rockchip_drm_psr_disable);
154
155/**
156 * rockchip_drm_psr_flush - force to flush all registered PSR encoders
157 * @dev: drm device
158 *
159 * Disable the PSR function for all registered encoders, and then enable the
160 * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
161 * changed during flush time, then keep the state no change after flush
162 * timeout.
163 *
164 * Returns:
165 * Zero on success, negative errno on failure.
166 */
167void rockchip_drm_psr_flush(struct drm_device *dev)
168{
169 struct rockchip_drm_private *drm_drv = dev->dev_private;
170 struct psr_drv *psr;
171 unsigned long flags;
172
173 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
174 list_for_each_entry(psr, &drm_drv->psr_list, list) {
175 mod_timer(&psr->flush_timer,
176 round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
177
178 psr_set_state(psr, PSR_FLUSH);
179 }
180 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
181}
182EXPORT_SYMBOL(rockchip_drm_psr_flush);
183
184/**
185 * rockchip_drm_psr_register - register encoder to psr driver
186 * @encoder: encoder that obtain the PSR function
187 * @psr_set: call back to set PSR state
188 *
189 * Returns:
190 * Zero on success, negative errno on failure.
191 */
192int rockchip_drm_psr_register(struct drm_encoder *encoder,
193 void (*psr_set)(struct drm_encoder *, bool enable))
194{
195 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
196 struct psr_drv *psr;
197 unsigned long flags;
198
199 if (!encoder || !psr_set)
200 return -EINVAL;
201
202 psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
203 if (!psr)
204 return -ENOMEM;
205
206 setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
207 spin_lock_init(&psr->lock);
208
209 psr->state = PSR_DISABLE;
210 psr->encoder = encoder;
211 psr->set = psr_set;
212
213 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
214 list_add_tail(&psr->list, &drm_drv->psr_list);
215 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
216
217 return 0;
218}
219EXPORT_SYMBOL(rockchip_drm_psr_register);
220
221/**
222 * rockchip_drm_psr_unregister - unregister encoder to psr driver
223 * @encoder: encoder that obtain the PSR function
224 * @psr_set: call back to set PSR state
225 *
226 * Returns:
227 * Zero on success, negative errno on failure.
228 */
229void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
230{
231 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
232 struct psr_drv *psr, *n;
233 unsigned long flags;
234
235 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
236 list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
237 if (psr->encoder == encoder) {
238 del_timer(&psr->flush_timer);
239 list_del(&psr->list);
240 kfree(psr);
241 }
242 }
243 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
244}
245EXPORT_SYMBOL(rockchip_drm_psr_unregister);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
new file mode 100644
index 000000000000..c35b68873a30
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author: Yakir Yang <ykk@rock-chips.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __ROCKCHIP_DRM_PSR___
16#define __ROCKCHIP_DRM_PSR___
17
18void rockchip_drm_psr_flush(struct drm_device *dev);
19int rockchip_drm_psr_enable(struct drm_crtc *crtc);
20int rockchip_drm_psr_disable(struct drm_crtc *crtc);
21
22int rockchip_drm_psr_register(struct drm_encoder *encoder,
23 void (*psr_set)(struct drm_encoder *, bool enable));
24void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
25
26#endif /* __ROCKCHIP_DRM_PSR__ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index efbc41ad83b6..d486049f9722 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -34,17 +34,21 @@
34#include "rockchip_drm_drv.h" 34#include "rockchip_drm_drv.h"
35#include "rockchip_drm_gem.h" 35#include "rockchip_drm_gem.h"
36#include "rockchip_drm_fb.h" 36#include "rockchip_drm_fb.h"
37#include "rockchip_drm_psr.h"
37#include "rockchip_drm_vop.h" 38#include "rockchip_drm_vop.h"
38 39
39#define __REG_SET_RELAXED(x, off, mask, shift, v) \ 40#define __REG_SET_RELAXED(x, off, mask, shift, v, write_mask) \
40 vop_mask_write_relaxed(x, off, (mask) << shift, (v) << shift) 41 vop_mask_write(x, off, mask, shift, v, write_mask, true)
41#define __REG_SET_NORMAL(x, off, mask, shift, v) \ 42
42 vop_mask_write(x, off, (mask) << shift, (v) << shift) 43#define __REG_SET_NORMAL(x, off, mask, shift, v, write_mask) \
44 vop_mask_write(x, off, mask, shift, v, write_mask, false)
43 45
44#define REG_SET(x, base, reg, v, mode) \ 46#define REG_SET(x, base, reg, v, mode) \
45 __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) 47 __REG_SET_##mode(x, base + reg.offset, \
48 reg.mask, reg.shift, v, reg.write_mask)
46#define REG_SET_MASK(x, base, reg, mask, v, mode) \ 49#define REG_SET_MASK(x, base, reg, mask, v, mode) \
47 __REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v) 50 __REG_SET_##mode(x, base + reg.offset, \
51 mask, reg.shift, v, reg.write_mask)
48 52
49#define VOP_WIN_SET(x, win, name, v) \ 53#define VOP_WIN_SET(x, win, name, v) \
50 REG_SET(x, win->base, win->phy->name, v, RELAXED) 54 REG_SET(x, win->base, win->phy->name, v, RELAXED)
@@ -106,6 +110,7 @@ struct vop {
106 struct device *dev; 110 struct device *dev;
107 struct drm_device *drm_dev; 111 struct drm_device *drm_dev;
108 bool is_enabled; 112 bool is_enabled;
113 bool vblank_active;
109 114
110 /* mutex vsync_ work */ 115 /* mutex vsync_ work */
111 struct mutex vsync_mutex; 116 struct mutex vsync_mutex;
@@ -116,6 +121,8 @@ struct vop {
116 /* protected by dev->event_lock */ 121 /* protected by dev->event_lock */
117 struct drm_pending_vblank_event *event; 122 struct drm_pending_vblank_event *event;
118 123
124 struct completion line_flag_completion;
125
119 const struct vop_data *data; 126 const struct vop_data *data;
120 127
121 uint32_t *regsbak; 128 uint32_t *regsbak;
@@ -162,27 +169,25 @@ static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base,
162} 169}
163 170
164static inline void vop_mask_write(struct vop *vop, uint32_t offset, 171static inline void vop_mask_write(struct vop *vop, uint32_t offset,
165 uint32_t mask, uint32_t v) 172 uint32_t mask, uint32_t shift, uint32_t v,
173 bool write_mask, bool relaxed)
166{ 174{
167 if (mask) { 175 if (!mask)
168 uint32_t cached_val = vop->regsbak[offset >> 2]; 176 return;
169
170 cached_val = (cached_val & ~mask) | v;
171 writel(cached_val, vop->regs + offset);
172 vop->regsbak[offset >> 2] = cached_val;
173 }
174}
175 177
176static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset, 178 if (write_mask) {
177 uint32_t mask, uint32_t v) 179 v = ((v << shift) & 0xffff) | (mask << (shift + 16));
178{ 180 } else {
179 if (mask) {
180 uint32_t cached_val = vop->regsbak[offset >> 2]; 181 uint32_t cached_val = vop->regsbak[offset >> 2];
181 182
182 cached_val = (cached_val & ~mask) | v; 183 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
183 writel_relaxed(cached_val, vop->regs + offset); 184 vop->regsbak[offset >> 2] = v;
184 vop->regsbak[offset >> 2] = cached_val;
185 } 185 }
186
187 if (relaxed)
188 writel_relaxed(v, vop->regs + offset);
189 else
190 writel(v, vop->regs + offset);
186} 191}
187 192
188static inline uint32_t vop_get_intr_type(struct vop *vop, 193static inline uint32_t vop_get_intr_type(struct vop *vop,
@@ -428,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
428 spin_unlock_irqrestore(&vop->irq_lock, flags); 433 spin_unlock_irqrestore(&vop->irq_lock, flags);
429} 434}
430 435
436/*
437 * (1) each frame starts at the start of the Vsync pulse which is signaled by
438 * the "FRAME_SYNC" interrupt.
439 * (2) the active data region of each frame ends at dsp_vact_end
440 * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
441 * to get "LINE_FLAG" interrupt at the end of the active on screen data.
442 *
443 * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
444 * Interrupts
445 * LINE_FLAG -------------------------------+
446 * FRAME_SYNC ----+ |
447 * | |
448 * v v
449 * | Vsync | Vbp | Vactive | Vfp |
450 * ^ ^ ^ ^
451 * | | | |
452 * | | | |
453 * dsp_vs_end ------------+ | | | VOP_DSP_VTOTAL_VS_END
454 * dsp_vact_start --------------+ | | VOP_DSP_VACT_ST_END
455 * dsp_vact_end ----------------------------+ | VOP_DSP_VACT_ST_END
456 * dsp_total -------------------------------------+ VOP_DSP_VTOTAL_VS_END
457 */
458static bool vop_line_flag_irq_is_enabled(struct vop *vop)
459{
460 uint32_t line_flag_irq;
461 unsigned long flags;
462
463 spin_lock_irqsave(&vop->irq_lock, flags);
464
465 line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
466
467 spin_unlock_irqrestore(&vop->irq_lock, flags);
468
469 return !!line_flag_irq;
470}
471
472static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
473{
474 unsigned long flags;
475
476 if (WARN_ON(!vop->is_enabled))
477 return;
478
479 spin_lock_irqsave(&vop->irq_lock, flags);
480
481 VOP_CTRL_SET(vop, line_flag_num[0], line_num);
482 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
483
484 spin_unlock_irqrestore(&vop->irq_lock, flags);
485}
486
487static void vop_line_flag_irq_disable(struct vop *vop)
488{
489 unsigned long flags;
490
491 if (WARN_ON(!vop->is_enabled))
492 return;
493
494 spin_lock_irqsave(&vop->irq_lock, flags);
495
496 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
497
498 spin_unlock_irqrestore(&vop->irq_lock, flags);
499}
500
431static int vop_enable(struct drm_crtc *crtc) 501static int vop_enable(struct drm_crtc *crtc)
432{ 502{
433 struct vop *vop = to_vop(crtc); 503 struct vop *vop = to_vop(crtc);
@@ -849,6 +919,8 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
849 919
850 spin_unlock_irqrestore(&vop->irq_lock, flags); 920 spin_unlock_irqrestore(&vop->irq_lock, flags);
851 921
922 rockchip_drm_psr_disable(&vop->crtc);
923
852 return 0; 924 return 0;
853} 925}
854 926
@@ -865,6 +937,8 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
865 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0); 937 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
866 938
867 spin_unlock_irqrestore(&vop->irq_lock, flags); 939 spin_unlock_irqrestore(&vop->irq_lock, flags);
940
941 rockchip_drm_psr_enable(&vop->crtc);
868} 942}
869 943
870static void vop_crtc_wait_for_update(struct drm_crtc *crtc) 944static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
@@ -908,7 +982,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
908 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; 982 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
909 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; 983 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
910 u16 vact_end = vact_st + vdisplay; 984 u16 vact_end = vact_st + vdisplay;
911 uint32_t val; 985 uint32_t pin_pol, val;
912 int ret; 986 int ret;
913 987
914 WARN_ON(vop->event); 988 WARN_ON(vop->event);
@@ -955,21 +1029,26 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
955 vop_dsp_hold_valid_irq_disable(vop); 1029 vop_dsp_hold_valid_irq_disable(vop);
956 } 1030 }
957 1031
958 val = 0x8; 1032 pin_pol = 0x8;
959 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1; 1033 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
960 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1); 1034 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
961 VOP_CTRL_SET(vop, pin_pol, val); 1035 VOP_CTRL_SET(vop, pin_pol, pin_pol);
1036
962 switch (s->output_type) { 1037 switch (s->output_type) {
963 case DRM_MODE_CONNECTOR_LVDS: 1038 case DRM_MODE_CONNECTOR_LVDS:
964 VOP_CTRL_SET(vop, rgb_en, 1); 1039 VOP_CTRL_SET(vop, rgb_en, 1);
1040 VOP_CTRL_SET(vop, rgb_pin_pol, pin_pol);
965 break; 1041 break;
966 case DRM_MODE_CONNECTOR_eDP: 1042 case DRM_MODE_CONNECTOR_eDP:
1043 VOP_CTRL_SET(vop, edp_pin_pol, pin_pol);
967 VOP_CTRL_SET(vop, edp_en, 1); 1044 VOP_CTRL_SET(vop, edp_en, 1);
968 break; 1045 break;
969 case DRM_MODE_CONNECTOR_HDMIA: 1046 case DRM_MODE_CONNECTOR_HDMIA:
1047 VOP_CTRL_SET(vop, hdmi_pin_pol, pin_pol);
970 VOP_CTRL_SET(vop, hdmi_en, 1); 1048 VOP_CTRL_SET(vop, hdmi_en, 1);
971 break; 1049 break;
972 case DRM_MODE_CONNECTOR_DSI: 1050 case DRM_MODE_CONNECTOR_DSI:
1051 VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol);
973 VOP_CTRL_SET(vop, mipi_en, 1); 1052 VOP_CTRL_SET(vop, mipi_en, 1);
974 break; 1053 break;
975 default: 1054 default:
@@ -1016,10 +1095,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
1016 struct vop *vop = to_vop(crtc); 1095 struct vop *vop = to_vop(crtc);
1017 1096
1018 spin_lock_irq(&crtc->dev->event_lock); 1097 spin_lock_irq(&crtc->dev->event_lock);
1019 if (crtc->state->event) { 1098 vop->vblank_active = true;
1020 WARN_ON(drm_crtc_vblank_get(crtc) != 0); 1099 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1021 WARN_ON(vop->event); 1100 WARN_ON(vop->event);
1022 1101
1102 if (crtc->state->event) {
1023 vop->event = crtc->state->event; 1103 vop->event = crtc->state->event;
1024 crtc->state->event = NULL; 1104 crtc->state->event = NULL;
1025 } 1105 }
@@ -1106,12 +1186,14 @@ static void vop_handle_vblank(struct vop *vop)
1106 1186
1107 spin_lock_irqsave(&drm->event_lock, flags); 1187 spin_lock_irqsave(&drm->event_lock, flags);
1108 if (vop->event) { 1188 if (vop->event) {
1109
1110 drm_crtc_send_vblank_event(crtc, vop->event); 1189 drm_crtc_send_vblank_event(crtc, vop->event);
1111 drm_crtc_vblank_put(crtc);
1112 vop->event = NULL; 1190 vop->event = NULL;
1113 1191
1114 } 1192 }
1193 if (vop->vblank_active) {
1194 vop->vblank_active = false;
1195 drm_crtc_vblank_put(crtc);
1196 }
1115 spin_unlock_irqrestore(&drm->event_lock, flags); 1197 spin_unlock_irqrestore(&drm->event_lock, flags);
1116 1198
1117 if (!completion_done(&vop->wait_update_complete)) 1199 if (!completion_done(&vop->wait_update_complete))
@@ -1149,6 +1231,12 @@ static irqreturn_t vop_isr(int irq, void *data)
1149 ret = IRQ_HANDLED; 1231 ret = IRQ_HANDLED;
1150 } 1232 }
1151 1233
1234 if (active_irqs & LINE_FLAG_INTR) {
1235 complete(&vop->line_flag_completion);
1236 active_irqs &= ~LINE_FLAG_INTR;
1237 ret = IRQ_HANDLED;
1238 }
1239
1152 if (active_irqs & FS_INTR) { 1240 if (active_irqs & FS_INTR) {
1153 drm_crtc_handle_vblank(crtc); 1241 drm_crtc_handle_vblank(crtc);
1154 vop_handle_vblank(vop); 1242 vop_handle_vblank(vop);
@@ -1250,6 +1338,7 @@ static int vop_create_crtc(struct vop *vop)
1250 1338
1251 init_completion(&vop->dsp_hold_completion); 1339 init_completion(&vop->dsp_hold_completion);
1252 init_completion(&vop->wait_update_complete); 1340 init_completion(&vop->wait_update_complete);
1341 init_completion(&vop->line_flag_completion);
1253 crtc->port = port; 1342 crtc->port = port;
1254 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs); 1343 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
1255 1344
@@ -1377,6 +1466,7 @@ static int vop_initial(struct vop *vop)
1377 clk_disable(vop->aclk); 1466 clk_disable(vop->aclk);
1378 1467
1379 vop->is_enabled = false; 1468 vop->is_enabled = false;
1469 vop->vblank_active = false;
1380 1470
1381 return 0; 1471 return 0;
1382 1472
@@ -1406,6 +1496,49 @@ static void vop_win_init(struct vop *vop)
1406 } 1496 }
1407} 1497}
1408 1498
1499/**
1500 * rockchip_drm_wait_line_flag - acqiure the give line flag event
1501 * @crtc: CRTC to enable line flag
1502 * @line_num: interested line number
1503 * @mstimeout: millisecond for timeout
1504 *
1505 * Driver would hold here until the interested line flag interrupt have
1506 * happened or timeout to wait.
1507 *
1508 * Returns:
1509 * Zero on success, negative errno on failure.
1510 */
1511int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
1512 unsigned int mstimeout)
1513{
1514 struct vop *vop = to_vop(crtc);
1515 unsigned long jiffies_left;
1516
1517 if (!crtc || !vop->is_enabled)
1518 return -ENODEV;
1519
1520 if (line_num > crtc->mode.vtotal || mstimeout <= 0)
1521 return -EINVAL;
1522
1523 if (vop_line_flag_irq_is_enabled(vop))
1524 return -EBUSY;
1525
1526 reinit_completion(&vop->line_flag_completion);
1527 vop_line_flag_irq_enable(vop, line_num);
1528
1529 jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
1530 msecs_to_jiffies(mstimeout));
1531 vop_line_flag_irq_disable(vop);
1532
1533 if (jiffies_left == 0) {
1534 dev_err(vop->dev, "Timeout waiting for IRQ\n");
1535 return -ETIMEDOUT;
1536 }
1537
1538 return 0;
1539}
1540EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
1541
1409static int vop_bind(struct device *dev, struct device *master, void *data) 1542static int vop_bind(struct device *dev, struct device *master, void *data)
1410{ 1543{
1411 struct platform_device *pdev = to_platform_device(dev); 1544 struct platform_device *pdev = to_platform_device(dev);
@@ -1474,6 +1607,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1474 return ret; 1607 return ret;
1475 1608
1476 pm_runtime_enable(&pdev->dev); 1609 pm_runtime_enable(&pdev->dev);
1610
1477 return 0; 1611 return 0;
1478} 1612}
1479 1613
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 071ff0be7a95..1dbc52615257 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -33,6 +33,7 @@ struct vop_reg {
33 uint32_t offset; 33 uint32_t offset;
34 uint32_t shift; 34 uint32_t shift;
35 uint32_t mask; 35 uint32_t mask;
36 bool write_mask;
36}; 37};
37 38
38struct vop_ctrl { 39struct vop_ctrl {
@@ -48,6 +49,10 @@ struct vop_ctrl {
48 struct vop_reg dither_down; 49 struct vop_reg dither_down;
49 struct vop_reg dither_up; 50 struct vop_reg dither_up;
50 struct vop_reg pin_pol; 51 struct vop_reg pin_pol;
52 struct vop_reg rgb_pin_pol;
53 struct vop_reg hdmi_pin_pol;
54 struct vop_reg edp_pin_pol;
55 struct vop_reg mipi_pin_pol;
51 56
52 struct vop_reg htotal_pw; 57 struct vop_reg htotal_pw;
53 struct vop_reg hact_st_end; 58 struct vop_reg hact_st_end;
@@ -56,6 +61,8 @@ struct vop_ctrl {
56 struct vop_reg hpost_st_end; 61 struct vop_reg hpost_st_end;
57 struct vop_reg vpost_st_end; 62 struct vop_reg vpost_st_end;
58 63
64 struct vop_reg line_flag_num[2];
65
59 struct vop_reg cfg_done; 66 struct vop_reg cfg_done;
60}; 67};
61 68
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index b7f59c443730..35c51f3402f2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -23,7 +23,14 @@
23#define VOP_REG(off, _mask, s) \ 23#define VOP_REG(off, _mask, s) \
24 {.offset = off, \ 24 {.offset = off, \
25 .mask = _mask, \ 25 .mask = _mask, \
26 .shift = s,} 26 .shift = s, \
27 .write_mask = false,}
28
29#define VOP_REG_MASK(off, _mask, s) \
30 {.offset = off, \
31 .mask = _mask, \
32 .shift = s, \
33 .write_mask = true,}
27 34
28static const uint32_t formats_win_full[] = { 35static const uint32_t formats_win_full[] = {
29 DRM_FORMAT_XRGB8888, 36 DRM_FORMAT_XRGB8888,
@@ -50,6 +57,89 @@ static const uint32_t formats_win_lite[] = {
50 DRM_FORMAT_BGR565, 57 DRM_FORMAT_BGR565,
51}; 58};
52 59
60static const struct vop_scl_regs rk3036_win_scl = {
61 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
62 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
63 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
64 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
65};
66
67static const struct vop_win_phy rk3036_win0_data = {
68 .scl = &rk3036_win_scl,
69 .data_formats = formats_win_full,
70 .nformats = ARRAY_SIZE(formats_win_full),
71 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
72 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
73 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
74 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
75 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
76 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
77 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
78 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
79 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
80 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
81};
82
83static const struct vop_win_phy rk3036_win1_data = {
84 .data_formats = formats_win_lite,
85 .nformats = ARRAY_SIZE(formats_win_lite),
86 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
87 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
88 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
89 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
90 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
91 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
92 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
93 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
94};
95
96static const struct vop_win_data rk3036_vop_win_data[] = {
97 { .base = 0x00, .phy = &rk3036_win0_data,
98 .type = DRM_PLANE_TYPE_PRIMARY },
99 { .base = 0x00, .phy = &rk3036_win1_data,
100 .type = DRM_PLANE_TYPE_CURSOR },
101};
102
103static const int rk3036_vop_intrs[] = {
104 DSP_HOLD_VALID_INTR,
105 FS_INTR,
106 LINE_FLAG_INTR,
107 BUS_ERROR_INTR,
108};
109
110static const struct vop_intr rk3036_intr = {
111 .intrs = rk3036_vop_intrs,
112 .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
113 .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
114 .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
115 .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
116};
117
118static const struct vop_ctrl rk3036_ctrl_data = {
119 .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
120 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
121 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
122 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
123 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
124 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
125 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
126 .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
127 .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
128};
129
130static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
131 {RK3036_DSP_CTRL1, 0x00000000},
132};
133
134static const struct vop_data rk3036_vop = {
135 .init_table = rk3036_vop_init_reg_table,
136 .table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
137 .ctrl = &rk3036_ctrl_data,
138 .intr = &rk3036_intr,
139 .win = rk3036_vop_win_data,
140 .win_size = ARRAY_SIZE(rk3036_vop_win_data),
141};
142
53static const struct vop_scl_extension rk3288_win_full_scl_ext = { 143static const struct vop_scl_extension rk3288_win_full_scl_ext = {
54 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 144 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
55 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 145 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
@@ -133,6 +223,7 @@ static const struct vop_ctrl rk3288_ctrl_data = {
133 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 223 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
134 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 224 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
135 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 225 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
226 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
136 .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0), 227 .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
137}; 228};
138 229
@@ -190,93 +281,104 @@ static const struct vop_data rk3288_vop = {
190 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 281 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
191}; 282};
192 283
193static const struct vop_scl_regs rk3036_win_scl = { 284static const struct vop_ctrl rk3399_ctrl_data = {
194 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 285 .standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22),
195 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 286 .gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
196 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 287 .rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12),
197 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 288 .hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13),
198}; 289 .edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14),
199 290 .mipi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 15),
200static const struct vop_win_phy rk3036_win0_data = { 291 .dither_down = VOP_REG(RK3399_DSP_CTRL1, 0xf, 1),
201 .scl = &rk3036_win_scl, 292 .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6),
202 .data_formats = formats_win_full, 293 .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
203 .nformats = ARRAY_SIZE(formats_win_full), 294 .out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
204 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), 295 .rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
205 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), 296 .hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20),
206 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), 297 .edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24),
207 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0), 298 .mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28),
208 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0), 299 .htotal_pw = VOP_REG(RK3399_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
209 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0), 300 .hact_st_end = VOP_REG(RK3399_DSP_HACT_ST_END, 0x1fff1fff, 0),
210 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0), 301 .vtotal_pw = VOP_REG(RK3399_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
211 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), 302 .vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
212 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), 303 .hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
213 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), 304 .vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
305 .line_flag_num[0] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 0),
306 .line_flag_num[1] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 16),
307 .cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
214}; 308};
215 309
216static const struct vop_win_phy rk3036_win1_data = { 310static const int rk3399_vop_intrs[] = {
217 .data_formats = formats_win_lite,
218 .nformats = ARRAY_SIZE(formats_win_lite),
219 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
220 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
221 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
222 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
223 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
224 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
225 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
226 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
227};
228
229static const struct vop_win_data rk3036_vop_win_data[] = {
230 { .base = 0x00, .phy = &rk3036_win0_data,
231 .type = DRM_PLANE_TYPE_PRIMARY },
232 { .base = 0x00, .phy = &rk3036_win1_data,
233 .type = DRM_PLANE_TYPE_CURSOR },
234};
235
236static const int rk3036_vop_intrs[] = {
237 DSP_HOLD_VALID_INTR,
238 FS_INTR, 311 FS_INTR,
312 0, 0,
239 LINE_FLAG_INTR, 313 LINE_FLAG_INTR,
314 0,
240 BUS_ERROR_INTR, 315 BUS_ERROR_INTR,
316 0, 0, 0, 0, 0, 0, 0,
317 DSP_HOLD_VALID_INTR,
241}; 318};
242 319
243static const struct vop_intr rk3036_intr = { 320static const struct vop_intr rk3399_vop_intr = {
244 .intrs = rk3036_vop_intrs, 321 .intrs = rk3399_vop_intrs,
245 .nintrs = ARRAY_SIZE(rk3036_vop_intrs), 322 .nintrs = ARRAY_SIZE(rk3399_vop_intrs),
246 .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0), 323 .status = VOP_REG_MASK(RK3399_INTR_STATUS0, 0xffff, 0),
247 .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4), 324 .enable = VOP_REG_MASK(RK3399_INTR_EN0, 0xffff, 0),
248 .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8), 325 .clear = VOP_REG_MASK(RK3399_INTR_CLEAR0, 0xffff, 0),
249}; 326};
250 327
251static const struct vop_ctrl rk3036_ctrl_data = { 328static const struct vop_reg_data rk3399_init_reg_table[] = {
252 .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), 329 {RK3399_SYS_CTRL, 0x2000f800},
253 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), 330 {RK3399_DSP_CTRL0, 0x00000000},
254 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), 331 {RK3399_WIN0_CTRL0, 0x00000080},
255 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 332 {RK3399_WIN1_CTRL0, 0x00000080},
256 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), 333 /* TODO: Win2/3 support multiple area function, but we haven't found
257 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 334 * a suitable way to use it yet, so let's just use them as other windows
258 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), 335 * with only area 0 enabled.
259 .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0), 336 */
337 {RK3399_WIN2_CTRL0, 0x00000010},
338 {RK3399_WIN3_CTRL0, 0x00000010},
260}; 339};
261 340
262static const struct vop_reg_data rk3036_vop_init_reg_table[] = { 341static const struct vop_data rk3399_vop_big = {
263 {RK3036_DSP_CTRL1, 0x00000000}, 342 .init_table = rk3399_init_reg_table,
343 .table_size = ARRAY_SIZE(rk3399_init_reg_table),
344 .intr = &rk3399_vop_intr,
345 .ctrl = &rk3399_ctrl_data,
346 /*
347 * rk3399 vop big windows register layout is same as rk3288.
348 */
349 .win = rk3288_vop_win_data,
350 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
264}; 351};
265 352
266static const struct vop_data rk3036_vop = { 353static const struct vop_win_data rk3399_vop_lit_win_data[] = {
267 .init_table = rk3036_vop_init_reg_table, 354 { .base = 0x00, .phy = &rk3288_win01_data,
268 .table_size = ARRAY_SIZE(rk3036_vop_init_reg_table), 355 .type = DRM_PLANE_TYPE_PRIMARY },
269 .ctrl = &rk3036_ctrl_data, 356 { .base = 0x00, .phy = &rk3288_win23_data,
270 .intr = &rk3036_intr, 357 .type = DRM_PLANE_TYPE_CURSOR},
271 .win = rk3036_vop_win_data, 358};
272 .win_size = ARRAY_SIZE(rk3036_vop_win_data), 359
360static const struct vop_data rk3399_vop_lit = {
361 .init_table = rk3399_init_reg_table,
362 .table_size = ARRAY_SIZE(rk3399_init_reg_table),
363 .intr = &rk3399_vop_intr,
364 .ctrl = &rk3399_ctrl_data,
365 /*
366 * rk3399 vop lit windows register layout is same as rk3288,
367 * but cut off the win1 and win3 windows.
368 */
369 .win = rk3399_vop_lit_win_data,
370 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
273}; 371};
274 372
275static const struct of_device_id vop_driver_dt_match[] = { 373static const struct of_device_id vop_driver_dt_match[] = {
276 { .compatible = "rockchip,rk3288-vop",
277 .data = &rk3288_vop },
278 { .compatible = "rockchip,rk3036-vop", 374 { .compatible = "rockchip,rk3036-vop",
279 .data = &rk3036_vop }, 375 .data = &rk3036_vop },
376 { .compatible = "rockchip,rk3288-vop",
377 .data = &rk3288_vop },
378 { .compatible = "rockchip,rk3399-vop-big",
379 .data = &rk3399_vop_big },
380 { .compatible = "rockchip,rk3399-vop-lit",
381 .data = &rk3399_vop_lit },
280 {}, 382 {},
281}; 383};
282MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 384MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
index d4b46cba2f26..cd197260ece5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
@@ -166,4 +166,197 @@
166#define RK3036_HWC_LUT_ADDR 0x800 166#define RK3036_HWC_LUT_ADDR 0x800
167/* rk3036 register definition end */ 167/* rk3036 register definition end */
168 168
169/* rk3399 register definition */
170#define RK3399_REG_CFG_DONE 0x00000
171#define RK3399_VERSION_INFO 0x00004
172#define RK3399_SYS_CTRL 0x00008
173#define RK3399_SYS_CTRL1 0x0000c
174#define RK3399_DSP_CTRL0 0x00010
175#define RK3399_DSP_CTRL1 0x00014
176#define RK3399_DSP_BG 0x00018
177#define RK3399_MCU_CTRL 0x0001c
178#define RK3399_WB_CTRL0 0x00020
179#define RK3399_WB_CTRL1 0x00024
180#define RK3399_WB_YRGB_MST 0x00028
181#define RK3399_WB_CBR_MST 0x0002c
182#define RK3399_WIN0_CTRL0 0x00030
183#define RK3399_WIN0_CTRL1 0x00034
184#define RK3399_WIN0_COLOR_KEY 0x00038
185#define RK3399_WIN0_VIR 0x0003c
186#define RK3399_WIN0_YRGB_MST 0x00040
187#define RK3399_WIN0_CBR_MST 0x00044
188#define RK3399_WIN0_ACT_INFO 0x00048
189#define RK3399_WIN0_DSP_INFO 0x0004c
190#define RK3399_WIN0_DSP_ST 0x00050
191#define RK3399_WIN0_SCL_FACTOR_YRGB 0x00054
192#define RK3399_WIN0_SCL_FACTOR_CBR 0x00058
193#define RK3399_WIN0_SCL_OFFSET 0x0005c
194#define RK3399_WIN0_SRC_ALPHA_CTRL 0x00060
195#define RK3399_WIN0_DST_ALPHA_CTRL 0x00064
196#define RK3399_WIN0_FADING_CTRL 0x00068
197#define RK3399_WIN0_CTRL2 0x0006c
198#define RK3399_WIN1_CTRL0 0x00070
199#define RK3399_WIN1_CTRL1 0x00074
200#define RK3399_WIN1_COLOR_KEY 0x00078
201#define RK3399_WIN1_VIR 0x0007c
202#define RK3399_WIN1_YRGB_MST 0x00080
203#define RK3399_WIN1_CBR_MST 0x00084
204#define RK3399_WIN1_ACT_INFO 0x00088
205#define RK3399_WIN1_DSP_INFO 0x0008c
206#define RK3399_WIN1_DSP_ST 0x00090
207#define RK3399_WIN1_SCL_FACTOR_YRGB 0x00094
208#define RK3399_WIN1_SCL_FACTOR_CBR 0x00098
209#define RK3399_WIN1_SCL_OFFSET 0x0009c
210#define RK3399_WIN1_SRC_ALPHA_CTRL 0x000a0
211#define RK3399_WIN1_DST_ALPHA_CTRL 0x000a4
212#define RK3399_WIN1_FADING_CTRL 0x000a8
213#define RK3399_WIN1_CTRL2 0x000ac
214#define RK3399_WIN2_CTRL0 0x000b0
215#define RK3399_WIN2_CTRL1 0x000b4
216#define RK3399_WIN2_VIR0_1 0x000b8
217#define RK3399_WIN2_VIR2_3 0x000bc
218#define RK3399_WIN2_MST0 0x000c0
219#define RK3399_WIN2_DSP_INFO0 0x000c4
220#define RK3399_WIN2_DSP_ST0 0x000c8
221#define RK3399_WIN2_COLOR_KEY 0x000cc
222#define RK3399_WIN2_MST1 0x000d0
223#define RK3399_WIN2_DSP_INFO1 0x000d4
224#define RK3399_WIN2_DSP_ST1 0x000d8
225#define RK3399_WIN2_SRC_ALPHA_CTRL 0x000dc
226#define RK3399_WIN2_MST2 0x000e0
227#define RK3399_WIN2_DSP_INFO2 0x000e4
228#define RK3399_WIN2_DSP_ST2 0x000e8
229#define RK3399_WIN2_DST_ALPHA_CTRL 0x000ec
230#define RK3399_WIN2_MST3 0x000f0
231#define RK3399_WIN2_DSP_INFO3 0x000f4
232#define RK3399_WIN2_DSP_ST3 0x000f8
233#define RK3399_WIN2_FADING_CTRL 0x000fc
234#define RK3399_WIN3_CTRL0 0x00100
235#define RK3399_WIN3_CTRL1 0x00104
236#define RK3399_WIN3_VIR0_1 0x00108
237#define RK3399_WIN3_VIR2_3 0x0010c
238#define RK3399_WIN3_MST0 0x00110
239#define RK3399_WIN3_DSP_INFO0 0x00114
240#define RK3399_WIN3_DSP_ST0 0x00118
241#define RK3399_WIN3_COLOR_KEY 0x0011c
242#define RK3399_WIN3_MST1 0x00120
243#define RK3399_WIN3_DSP_INFO1 0x00124
244#define RK3399_WIN3_DSP_ST1 0x00128
245#define RK3399_WIN3_SRC_ALPHA_CTRL 0x0012c
246#define RK3399_WIN3_MST2 0x00130
247#define RK3399_WIN3_DSP_INFO2 0x00134
248#define RK3399_WIN3_DSP_ST2 0x00138
249#define RK3399_WIN3_DST_ALPHA_CTRL 0x0013c
250#define RK3399_WIN3_MST3 0x00140
251#define RK3399_WIN3_DSP_INFO3 0x00144
252#define RK3399_WIN3_DSP_ST3 0x00148
253#define RK3399_WIN3_FADING_CTRL 0x0014c
254#define RK3399_HWC_CTRL0 0x00150
255#define RK3399_HWC_CTRL1 0x00154
256#define RK3399_HWC_MST 0x00158
257#define RK3399_HWC_DSP_ST 0x0015c
258#define RK3399_HWC_SRC_ALPHA_CTRL 0x00160
259#define RK3399_HWC_DST_ALPHA_CTRL 0x00164
260#define RK3399_HWC_FADING_CTRL 0x00168
261#define RK3399_HWC_RESERVED1 0x0016c
262#define RK3399_POST_DSP_HACT_INFO 0x00170
263#define RK3399_POST_DSP_VACT_INFO 0x00174
264#define RK3399_POST_SCL_FACTOR_YRGB 0x00178
265#define RK3399_POST_RESERVED 0x0017c
266#define RK3399_POST_SCL_CTRL 0x00180
267#define RK3399_POST_DSP_VACT_INFO_F1 0x00184
268#define RK3399_DSP_HTOTAL_HS_END 0x00188
269#define RK3399_DSP_HACT_ST_END 0x0018c
270#define RK3399_DSP_VTOTAL_VS_END 0x00190
271#define RK3399_DSP_VACT_ST_END 0x00194
272#define RK3399_DSP_VS_ST_END_F1 0x00198
273#define RK3399_DSP_VACT_ST_END_F1 0x0019c
274#define RK3399_PWM_CTRL 0x001a0
275#define RK3399_PWM_PERIOD_HPR 0x001a4
276#define RK3399_PWM_DUTY_LPR 0x001a8
277#define RK3399_PWM_CNT 0x001ac
278#define RK3399_BCSH_COLOR_BAR 0x001b0
279#define RK3399_BCSH_BCS 0x001b4
280#define RK3399_BCSH_H 0x001b8
281#define RK3399_BCSH_CTRL 0x001bc
282#define RK3399_CABC_CTRL0 0x001c0
283#define RK3399_CABC_CTRL1 0x001c4
284#define RK3399_CABC_CTRL2 0x001c8
285#define RK3399_CABC_CTRL3 0x001cc
286#define RK3399_CABC_GAUSS_LINE0_0 0x001d0
287#define RK3399_CABC_GAUSS_LINE0_1 0x001d4
288#define RK3399_CABC_GAUSS_LINE1_0 0x001d8
289#define RK3399_CABC_GAUSS_LINE1_1 0x001dc
290#define RK3399_CABC_GAUSS_LINE2_0 0x001e0
291#define RK3399_CABC_GAUSS_LINE2_1 0x001e4
292#define RK3399_FRC_LOWER01_0 0x001e8
293#define RK3399_FRC_LOWER01_1 0x001ec
294#define RK3399_FRC_LOWER10_0 0x001f0
295#define RK3399_FRC_LOWER10_1 0x001f4
296#define RK3399_FRC_LOWER11_0 0x001f8
297#define RK3399_FRC_LOWER11_1 0x001fc
298#define RK3399_AFBCD0_CTRL 0x00200
299#define RK3399_AFBCD0_HDR_PTR 0x00204
300#define RK3399_AFBCD0_PIC_SIZE 0x00208
301#define RK3399_AFBCD0_STATUS 0x0020c
302#define RK3399_AFBCD1_CTRL 0x00220
303#define RK3399_AFBCD1_HDR_PTR 0x00224
304#define RK3399_AFBCD1_PIC_SIZE 0x00228
305#define RK3399_AFBCD1_STATUS 0x0022c
306#define RK3399_AFBCD2_CTRL 0x00240
307#define RK3399_AFBCD2_HDR_PTR 0x00244
308#define RK3399_AFBCD2_PIC_SIZE 0x00248
309#define RK3399_AFBCD2_STATUS 0x0024c
310#define RK3399_AFBCD3_CTRL 0x00260
311#define RK3399_AFBCD3_HDR_PTR 0x00264
312#define RK3399_AFBCD3_PIC_SIZE 0x00268
313#define RK3399_AFBCD3_STATUS 0x0026c
314#define RK3399_INTR_EN0 0x00280
315#define RK3399_INTR_CLEAR0 0x00284
316#define RK3399_INTR_STATUS0 0x00288
317#define RK3399_INTR_RAW_STATUS0 0x0028c
318#define RK3399_INTR_EN1 0x00290
319#define RK3399_INTR_CLEAR1 0x00294
320#define RK3399_INTR_STATUS1 0x00298
321#define RK3399_INTR_RAW_STATUS1 0x0029c
322#define RK3399_LINE_FLAG 0x002a0
323#define RK3399_VOP_STATUS 0x002a4
324#define RK3399_BLANKING_VALUE 0x002a8
325#define RK3399_MCU_BYPASS_PORT 0x002ac
326#define RK3399_WIN0_DSP_BG 0x002b0
327#define RK3399_WIN1_DSP_BG 0x002b4
328#define RK3399_WIN2_DSP_BG 0x002b8
329#define RK3399_WIN3_DSP_BG 0x002bc
330#define RK3399_YUV2YUV_WIN 0x002c0
331#define RK3399_YUV2YUV_POST 0x002c4
332#define RK3399_AUTO_GATING_EN 0x002cc
333#define RK3399_WIN0_CSC_COE 0x003a0
334#define RK3399_WIN1_CSC_COE 0x003c0
335#define RK3399_WIN2_CSC_COE 0x003e0
336#define RK3399_WIN3_CSC_COE 0x00400
337#define RK3399_HWC_CSC_COE 0x00420
338#define RK3399_BCSH_R2Y_CSC_COE 0x00440
339#define RK3399_BCSH_Y2R_CSC_COE 0x00460
340#define RK3399_POST_YUV2YUV_Y2R_COE 0x00480
341#define RK3399_POST_YUV2YUV_3X3_COE 0x004a0
342#define RK3399_POST_YUV2YUV_R2Y_COE 0x004c0
343#define RK3399_WIN0_YUV2YUV_Y2R 0x004e0
344#define RK3399_WIN0_YUV2YUV_3X3 0x00500
345#define RK3399_WIN0_YUV2YUV_R2Y 0x00520
346#define RK3399_WIN1_YUV2YUV_Y2R 0x00540
347#define RK3399_WIN1_YUV2YUV_3X3 0x00560
348#define RK3399_WIN1_YUV2YUV_R2Y 0x00580
349#define RK3399_WIN2_YUV2YUV_Y2R 0x005a0
350#define RK3399_WIN2_YUV2YUV_3X3 0x005c0
351#define RK3399_WIN2_YUV2YUV_R2Y 0x005e0
352#define RK3399_WIN3_YUV2YUV_Y2R 0x00600
353#define RK3399_WIN3_YUV2YUV_3X3 0x00620
354#define RK3399_WIN3_YUV2YUV_R2Y 0x00640
355#define RK3399_WIN2_LUT_ADDR 0x01000
356#define RK3399_WIN3_LUT_ADDR 0x01400
357#define RK3399_HWC_LUT_ADDR 0x01800
358#define RK3399_CABC_GAMMA_LUT_ADDR 0x01c00
359#define RK3399_GAMMA_LUT_ADDR 0x02000
360/* rk3399 register definition end */
361
169#endif /* _ROCKCHIP_VOP_REG_H */ 362#endif /* _ROCKCHIP_VOP_REG_H */
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index 261b86d20e77..9cd8838e1ec3 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -38,6 +38,9 @@ struct analogix_dp_plat_data {
38 struct drm_connector *); 38 struct drm_connector *);
39}; 39};
40 40
41int analogix_dp_enable_psr(struct device *dev);
42int analogix_dp_disable_psr(struct device *dev);
43
41int analogix_dp_resume(struct device *dev); 44int analogix_dp_resume(struct device *dev);
42int analogix_dp_suspend(struct device *dev); 45int analogix_dp_suspend(struct device *dev);
43 46