diff options
author | Dave Airlie <airlied@redhat.com> | 2018-03-13 20:59:16 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-03-13 20:59:16 -0400 |
commit | 0b8eeac5c6ca6dcb19cce04bf8910006ac73dbd3 (patch) | |
tree | b883a42fa60a1a092bf4649051dbc4e3ba9677a2 | |
parent | 62ccb6533920ce6e8a18ef7c5ee3f98783a1a42a (diff) | |
parent | 60beeccc72cabefcb8874fec542b3142e262b6c2 (diff) |
Merge tag 'drm-misc-next-2018-03-09-3' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.17:
UAPI Changes:
plane: Add color encoding/range properties (Jyri)
nouveau: Replace iturbt_709 property with color_encoding property (Ville)
Core Changes:
atomic: Move plane clipping into plane check helper (Ville)
property: Multiple new property checks/verification (Ville)
Driver Changes:
rockchip: Fixes & improvements for rk3399/chromebook plus (various)
sun4i: Add H3/H5 HDMI support (Jernej)
i915: Add support for limited/full-range ycbcr toggling (Ville)
pl111: Add bandwidth checking/limiting (Linus)
Cc: Jernej Skrabec <jernej.skrabec@siol.net>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
* tag 'drm-misc-next-2018-03-09-3' of git://anongit.freedesktop.org/drm/drm-misc: (85 commits)
drm/rockchip: Don't use atomic constructs for psr
drm/rockchip: analogix_dp: set psr activate/deactivate when enable/disable bridge
drm/rockchip: dw_hdmi: Move HDMI vpll clock enable to bind()
drm/rockchip: inno_hdmi: reorder clk_disable_unprepare call in unbind
drm/rockchip: inno_hdmi: Fix error handling path.
drm/rockchip: dw-mipi-dsi: Fix connector and encoder cleanup.
drm/nouveau: Replace the iturbt_709 prop with the standard COLOR_ENCODING prop
drm/pl111: Use max memory bandwidth for resolution
drm/bridge: sii902x: Retry status read after DDI I2C
drm/pl111: Handle the RealView variant separately
drm/pl111: Make the default BPP a per-variant variable
drm: simple_kms_helper: Fix .mode_valid() documentation
bridge: Elaborate a bit on dumb VGA bridges in Kconfig
drm/atomic: Add new reverse iterator over all plane state (V2)
drm: Reject bad property flag combinations
drm: Make property flags u32
drm/uapi: Deprecate DRM_MODE_PROP_PENDING
drm: WARN when trying to add enum value > 63 to a bitmask property
drm: WARN when trying add enum values to non-enum/bitmask properties
drm: Reject replacing property enum values
...
96 files changed, 1800 insertions, 678 deletions
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index b995bfee734a..8bdef4920edc 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | |||
@@ -102,6 +102,7 @@ DWC HDMI PHY | |||
102 | Required properties: | 102 | Required properties: |
103 | - compatible: value must be one of: | 103 | - compatible: value must be one of: |
104 | * allwinner,sun8i-a83t-hdmi-phy | 104 | * allwinner,sun8i-a83t-hdmi-phy |
105 | * allwinner,sun8i-h3-hdmi-phy | ||
105 | - reg: base address and size of memory-mapped region | 106 | - reg: base address and size of memory-mapped region |
106 | - clocks: phandles to the clocks feeding the HDMI PHY | 107 | - clocks: phandles to the clocks feeding the HDMI PHY |
107 | * bus: the HDMI PHY interface clock | 108 | * bus: the HDMI PHY interface clock |
@@ -110,6 +111,9 @@ Required properties: | |||
110 | - resets: phandle to the reset controller driving the PHY | 111 | - resets: phandle to the reset controller driving the PHY |
111 | - reset-names: must be "phy" | 112 | - reset-names: must be "phy" |
112 | 113 | ||
114 | H3 HDMI PHY requires additional clock: | ||
115 | - pll-0: parent of phy clock | ||
116 | |||
113 | TV Encoder | 117 | TV Encoder |
114 | ---------- | 118 | ---------- |
115 | 119 | ||
@@ -275,6 +279,7 @@ Required properties: | |||
275 | - compatible: value must be one of: | 279 | - compatible: value must be one of: |
276 | * allwinner,sun8i-a83t-de2-mixer-0 | 280 | * allwinner,sun8i-a83t-de2-mixer-0 |
277 | * allwinner,sun8i-a83t-de2-mixer-1 | 281 | * allwinner,sun8i-a83t-de2-mixer-1 |
282 | * allwinner,sun8i-h3-de2-mixer-0 | ||
278 | * allwinner,sun8i-v3s-de2-mixer | 283 | * allwinner,sun8i-v3s-de2-mixer |
279 | - reg: base address and size of the memory-mapped region. | 284 | - reg: base address and size of the memory-mapped region. |
280 | - clocks: phandles to the clocks feeding the mixer | 285 | - clocks: phandles to the clocks feeding the mixer |
@@ -305,6 +310,7 @@ Required properties: | |||
305 | * allwinner,sun7i-a20-display-engine | 310 | * allwinner,sun7i-a20-display-engine |
306 | * allwinner,sun8i-a33-display-engine | 311 | * allwinner,sun8i-a33-display-engine |
307 | * allwinner,sun8i-a83t-display-engine | 312 | * allwinner,sun8i-a83t-display-engine |
313 | * allwinner,sun8i-h3-display-engine | ||
308 | * allwinner,sun8i-v3s-display-engine | 314 | * allwinner,sun8i-v3s-display-engine |
309 | 315 | ||
310 | - allwinner,pipelines: list of phandle to the display engine | 316 | - allwinner,pipelines: list of phandle to the display engine |
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 877647ef35a9..cf5cbd63ecdf 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c | |||
@@ -229,7 +229,6 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { | |||
229 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, | 229 | static int hdlcd_plane_atomic_check(struct drm_plane *plane, |
230 | struct drm_plane_state *state) | 230 | struct drm_plane_state *state) |
231 | { | 231 | { |
232 | struct drm_rect clip = { 0 }; | ||
233 | struct drm_crtc_state *crtc_state; | 232 | struct drm_crtc_state *crtc_state; |
234 | u32 src_h = state->src_h >> 16; | 233 | u32 src_h = state->src_h >> 16; |
235 | 234 | ||
@@ -249,11 +248,7 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane, | |||
249 | return -EINVAL; | 248 | return -EINVAL; |
250 | } | 249 | } |
251 | 250 | ||
252 | if (crtc_state->enable) | 251 | return drm_atomic_helper_check_plane_state(state, crtc_state, |
253 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
254 | &clip.x2, &clip.y2); | ||
255 | |||
256 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
257 | DRM_PLANE_HELPER_NO_SCALING, | 252 | DRM_PLANE_HELPER_NO_SCALING, |
258 | DRM_PLANE_HELPER_NO_SCALING, | 253 | DRM_PLANE_HELPER_NO_SCALING, |
259 | false, true); | 254 | false, true); |
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 2885d69af456..ee32361c87ac 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c | |||
@@ -141,18 +141,13 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, | |||
141 | struct drm_crtc_state *crtc_state = | 141 | struct drm_crtc_state *crtc_state = |
142 | drm_atomic_get_existing_crtc_state(state->state, state->crtc); | 142 | drm_atomic_get_existing_crtc_state(state->state, state->crtc); |
143 | struct malidp_crtc_state *mc; | 143 | struct malidp_crtc_state *mc; |
144 | struct drm_rect clip = { 0 }; | ||
145 | u32 src_w, src_h; | 144 | u32 src_w, src_h; |
146 | int ret; | 145 | int ret; |
147 | 146 | ||
148 | if (!crtc_state) | 147 | if (!crtc_state) |
149 | return -EINVAL; | 148 | return -EINVAL; |
150 | 149 | ||
151 | if (crtc_state->enable) | 150 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
152 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
153 | &clip.x2, &clip.y2); | ||
154 | |||
155 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
156 | 0, INT_MAX, true, true); | 151 | 0, INT_MAX, true, true); |
157 | if (ret) | 152 | if (ret) |
158 | return ret; | 153 | return ret; |
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index e2adfbef7d6b..03eeee11dd5b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -1200,13 +1200,14 @@ static int armada_drm_primary_update(struct drm_plane *plane, | |||
1200 | .crtc_h = crtc_h, | 1200 | .crtc_h = crtc_h, |
1201 | .rotation = DRM_MODE_ROTATE_0, | 1201 | .rotation = DRM_MODE_ROTATE_0, |
1202 | }; | 1202 | }; |
1203 | const struct drm_rect clip = { | 1203 | struct drm_crtc_state crtc_state = { |
1204 | .x2 = crtc->mode.hdisplay, | 1204 | .crtc = crtc, |
1205 | .y2 = crtc->mode.vdisplay, | 1205 | .enable = crtc->enabled, |
1206 | .mode = crtc->mode, | ||
1206 | }; | 1207 | }; |
1207 | int ret; | 1208 | int ret; |
1208 | 1209 | ||
1209 | ret = drm_atomic_helper_check_plane_state(&state, crtc->state, &clip, 0, | 1210 | ret = drm_atomic_helper_check_plane_state(&state, &crtc_state, 0, |
1210 | INT_MAX, true, false); | 1211 | INT_MAX, true, false); |
1211 | if (ret) | 1212 | if (ret) |
1212 | return ret; | 1213 | return ret; |
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 77b55adaa2ac..c391955009d6 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -205,9 +205,10 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
205 | .crtc_h = crtc_h, | 205 | .crtc_h = crtc_h, |
206 | .rotation = DRM_MODE_ROTATE_0, | 206 | .rotation = DRM_MODE_ROTATE_0, |
207 | }; | 207 | }; |
208 | const struct drm_rect clip = { | 208 | struct drm_crtc_state crtc_state = { |
209 | .x2 = crtc->mode.hdisplay, | 209 | .crtc = crtc, |
210 | .y2 = crtc->mode.vdisplay, | 210 | .enable = crtc->enabled, |
211 | .mode = crtc->mode, | ||
211 | }; | 212 | }; |
212 | int ret; | 213 | int ret; |
213 | 214 | ||
@@ -215,7 +216,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
215 | crtc_x, crtc_y, crtc_w, crtc_h, | 216 | crtc_x, crtc_y, crtc_w, crtc_h, |
216 | src_x, src_y, src_w, src_h); | 217 | src_x, src_y, src_w, src_h); |
217 | 218 | ||
218 | ret = drm_atomic_helper_check_plane_state(&state, crtc->state, &clip, 0, | 219 | ret = drm_atomic_helper_check_plane_state(&state, &crtc_state, 0, |
219 | INT_MAX, true, false); | 220 | INT_MAX, true, false); |
220 | if (ret) | 221 | if (ret) |
221 | return ret; | 222 | return ret; |
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 3b99d5a06c16..3aa65bdecb0e 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig | |||
@@ -30,7 +30,8 @@ config DRM_DUMB_VGA_DAC | |||
30 | depends on OF | 30 | depends on OF |
31 | select DRM_KMS_HELPER | 31 | select DRM_KMS_HELPER |
32 | help | 32 | help |
33 | Support for RGB to VGA DAC based bridges | 33 | Support for non-programmable RGB to VGA DAC bridges, such as ADI |
34 | ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs. | ||
34 | 35 | ||
35 | config DRM_LVDS_ENCODER | 36 | config DRM_LVDS_ENCODER |
36 | tristate "Transparent parallel to LVDS encoder support" | 37 | tristate "Transparent parallel to LVDS encoder support" |
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index b2756bc4225a..a693ab3078f0 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | |||
@@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) | |||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | int analogix_dp_psr_supported(struct device *dev) | 101 | int analogix_dp_psr_supported(struct analogix_dp_device *dp) |
102 | { | 102 | { |
103 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
104 | 103 | ||
105 | return dp->psr_support; | 104 | return dp->psr_support; |
106 | } | 105 | } |
107 | EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); | 106 | EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); |
108 | 107 | ||
109 | int analogix_dp_enable_psr(struct device *dev) | 108 | int analogix_dp_enable_psr(struct analogix_dp_device *dp) |
110 | { | 109 | { |
111 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
112 | struct edp_vsc_psr psr_vsc; | 110 | struct edp_vsc_psr psr_vsc; |
113 | 111 | ||
114 | if (!dp->psr_support) | 112 | if (!dp->psr_support) |
@@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) | |||
129 | } | 127 | } |
130 | EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); | 128 | EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); |
131 | 129 | ||
132 | int analogix_dp_disable_psr(struct device *dev) | 130 | int analogix_dp_disable_psr(struct analogix_dp_device *dp) |
133 | { | 131 | { |
134 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
135 | struct edp_vsc_psr psr_vsc; | 132 | struct edp_vsc_psr psr_vsc; |
136 | int ret; | 133 | int ret; |
137 | 134 | ||
@@ -1015,27 +1012,30 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge) | |||
1015 | { | 1012 | { |
1016 | struct analogix_dp_device *dp = bridge->driver_private; | 1013 | struct analogix_dp_device *dp = bridge->driver_private; |
1017 | struct drm_encoder *encoder = dp->encoder; | 1014 | struct drm_encoder *encoder = dp->encoder; |
1018 | struct drm_connector *connector = &dp->connector; | 1015 | struct drm_connector *connector = NULL; |
1019 | int ret; | 1016 | int ret = 0; |
1020 | 1017 | ||
1021 | if (!bridge->encoder) { | 1018 | if (!bridge->encoder) { |
1022 | DRM_ERROR("Parent encoder object not found"); | 1019 | DRM_ERROR("Parent encoder object not found"); |
1023 | return -ENODEV; | 1020 | return -ENODEV; |
1024 | } | 1021 | } |
1025 | 1022 | ||
1026 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 1023 | if (!dp->plat_data->skip_connector) { |
1024 | connector = &dp->connector; | ||
1025 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
1027 | 1026 | ||
1028 | ret = drm_connector_init(dp->drm_dev, connector, | 1027 | ret = drm_connector_init(dp->drm_dev, connector, |
1029 | &analogix_dp_connector_funcs, | 1028 | &analogix_dp_connector_funcs, |
1030 | DRM_MODE_CONNECTOR_eDP); | 1029 | DRM_MODE_CONNECTOR_eDP); |
1031 | if (ret) { | 1030 | if (ret) { |
1032 | DRM_ERROR("Failed to initialize connector with drm\n"); | 1031 | DRM_ERROR("Failed to initialize connector with drm\n"); |
1033 | return ret; | 1032 | return ret; |
1034 | } | 1033 | } |
1035 | 1034 | ||
1036 | drm_connector_helper_add(connector, | 1035 | drm_connector_helper_add(connector, |
1037 | &analogix_dp_connector_helper_funcs); | 1036 | &analogix_dp_connector_helper_funcs); |
1038 | drm_mode_connector_attach_encoder(connector, encoder); | 1037 | drm_mode_connector_attach_encoder(connector, encoder); |
1038 | } | ||
1039 | 1039 | ||
1040 | /* | 1040 | /* |
1041 | * NOTE: the connector registration is implemented in analogix | 1041 | * NOTE: the connector registration is implemented in analogix |
@@ -1279,8 +1279,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, | |||
1279 | return analogix_dp_transfer(dp, msg); | 1279 | return analogix_dp_transfer(dp, msg); |
1280 | } | 1280 | } |
1281 | 1281 | ||
1282 | int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | 1282 | struct analogix_dp_device * |
1283 | struct analogix_dp_plat_data *plat_data) | 1283 | analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, |
1284 | struct analogix_dp_plat_data *plat_data) | ||
1284 | { | 1285 | { |
1285 | struct platform_device *pdev = to_platform_device(dev); | 1286 | struct platform_device *pdev = to_platform_device(dev); |
1286 | struct analogix_dp_device *dp; | 1287 | struct analogix_dp_device *dp; |
@@ -1290,14 +1291,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1290 | 1291 | ||
1291 | if (!plat_data) { | 1292 | if (!plat_data) { |
1292 | dev_err(dev, "Invalided input plat_data\n"); | 1293 | dev_err(dev, "Invalided input plat_data\n"); |
1293 | return -EINVAL; | 1294 | return ERR_PTR(-EINVAL); |
1294 | } | 1295 | } |
1295 | 1296 | ||
1296 | dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); | 1297 | dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); |
1297 | if (!dp) | 1298 | if (!dp) |
1298 | return -ENOMEM; | 1299 | return ERR_PTR(-ENOMEM); |
1299 | |||
1300 | dev_set_drvdata(dev, dp); | ||
1301 | 1300 | ||
1302 | dp->dev = &pdev->dev; | 1301 | dp->dev = &pdev->dev; |
1303 | dp->dpms_mode = DRM_MODE_DPMS_OFF; | 1302 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
@@ -1314,7 +1313,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1314 | 1313 | ||
1315 | ret = analogix_dp_dt_parse_pdata(dp); | 1314 | ret = analogix_dp_dt_parse_pdata(dp); |
1316 | if (ret) | 1315 | if (ret) |
1317 | return ret; | 1316 | return ERR_PTR(ret); |
1318 | 1317 | ||
1319 | dp->phy = devm_phy_get(dp->dev, "dp"); | 1318 | dp->phy = devm_phy_get(dp->dev, "dp"); |
1320 | if (IS_ERR(dp->phy)) { | 1319 | if (IS_ERR(dp->phy)) { |
@@ -1328,14 +1327,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1328 | if (ret == -ENOSYS || ret == -ENODEV) | 1327 | if (ret == -ENOSYS || ret == -ENODEV) |
1329 | dp->phy = NULL; | 1328 | dp->phy = NULL; |
1330 | else | 1329 | else |
1331 | return ret; | 1330 | return ERR_PTR(ret); |
1332 | } | 1331 | } |
1333 | } | 1332 | } |
1334 | 1333 | ||
1335 | dp->clock = devm_clk_get(&pdev->dev, "dp"); | 1334 | dp->clock = devm_clk_get(&pdev->dev, "dp"); |
1336 | if (IS_ERR(dp->clock)) { | 1335 | if (IS_ERR(dp->clock)) { |
1337 | dev_err(&pdev->dev, "failed to get clock\n"); | 1336 | dev_err(&pdev->dev, "failed to get clock\n"); |
1338 | return PTR_ERR(dp->clock); | 1337 | return ERR_CAST(dp->clock); |
1339 | } | 1338 | } |
1340 | 1339 | ||
1341 | clk_prepare_enable(dp->clock); | 1340 | clk_prepare_enable(dp->clock); |
@@ -1344,7 +1343,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1344 | 1343 | ||
1345 | dp->reg_base = devm_ioremap_resource(&pdev->dev, res); | 1344 | dp->reg_base = devm_ioremap_resource(&pdev->dev, res); |
1346 | if (IS_ERR(dp->reg_base)) | 1345 | if (IS_ERR(dp->reg_base)) |
1347 | return PTR_ERR(dp->reg_base); | 1346 | return ERR_CAST(dp->reg_base); |
1348 | 1347 | ||
1349 | dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); | 1348 | dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); |
1350 | 1349 | ||
@@ -1365,7 +1364,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1365 | "hpd_gpio"); | 1364 | "hpd_gpio"); |
1366 | if (ret) { | 1365 | if (ret) { |
1367 | dev_err(&pdev->dev, "failed to get hpd gpio\n"); | 1366 | dev_err(&pdev->dev, "failed to get hpd gpio\n"); |
1368 | return ret; | 1367 | return ERR_PTR(ret); |
1369 | } | 1368 | } |
1370 | dp->irq = gpio_to_irq(dp->hpd_gpio); | 1369 | dp->irq = gpio_to_irq(dp->hpd_gpio); |
1371 | irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | 1370 | irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; |
@@ -1377,16 +1376,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1377 | 1376 | ||
1378 | if (dp->irq == -ENXIO) { | 1377 | if (dp->irq == -ENXIO) { |
1379 | dev_err(&pdev->dev, "failed to get irq\n"); | 1378 | dev_err(&pdev->dev, "failed to get irq\n"); |
1380 | return -ENODEV; | 1379 | return ERR_PTR(-ENODEV); |
1381 | } | 1380 | } |
1382 | 1381 | ||
1383 | pm_runtime_enable(dev); | ||
1384 | |||
1385 | pm_runtime_get_sync(dev); | ||
1386 | phy_power_on(dp->phy); | ||
1387 | |||
1388 | analogix_dp_init_dp(dp); | ||
1389 | |||
1390 | ret = devm_request_threaded_irq(&pdev->dev, dp->irq, | 1382 | ret = devm_request_threaded_irq(&pdev->dev, dp->irq, |
1391 | analogix_dp_hardirq, | 1383 | analogix_dp_hardirq, |
1392 | analogix_dp_irq_thread, | 1384 | analogix_dp_irq_thread, |
@@ -1406,38 +1398,30 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
1406 | 1398 | ||
1407 | ret = drm_dp_aux_register(&dp->aux); | 1399 | ret = drm_dp_aux_register(&dp->aux); |
1408 | if (ret) | 1400 | if (ret) |
1409 | goto err_disable_pm_runtime; | 1401 | return ERR_PTR(ret); |
1402 | |||
1403 | pm_runtime_enable(dev); | ||
1410 | 1404 | ||
1411 | ret = analogix_dp_create_bridge(drm_dev, dp); | 1405 | ret = analogix_dp_create_bridge(drm_dev, dp); |
1412 | if (ret) { | 1406 | if (ret) { |
1413 | DRM_ERROR("failed to create bridge (%d)\n", ret); | 1407 | DRM_ERROR("failed to create bridge (%d)\n", ret); |
1414 | drm_encoder_cleanup(dp->encoder); | ||
1415 | goto err_disable_pm_runtime; | 1408 | goto err_disable_pm_runtime; |
1416 | } | 1409 | } |
1417 | 1410 | ||
1418 | phy_power_off(dp->phy); | 1411 | return dp; |
1419 | pm_runtime_put(dev); | ||
1420 | |||
1421 | return 0; | ||
1422 | 1412 | ||
1423 | err_disable_pm_runtime: | 1413 | err_disable_pm_runtime: |
1424 | 1414 | ||
1425 | phy_power_off(dp->phy); | ||
1426 | pm_runtime_put(dev); | ||
1427 | pm_runtime_disable(dev); | 1415 | pm_runtime_disable(dev); |
1428 | 1416 | ||
1429 | return ret; | 1417 | return ERR_PTR(ret); |
1430 | } | 1418 | } |
1431 | EXPORT_SYMBOL_GPL(analogix_dp_bind); | 1419 | EXPORT_SYMBOL_GPL(analogix_dp_bind); |
1432 | 1420 | ||
1433 | void analogix_dp_unbind(struct device *dev, struct device *master, | 1421 | void analogix_dp_unbind(struct analogix_dp_device *dp) |
1434 | void *data) | ||
1435 | { | 1422 | { |
1436 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
1437 | |||
1438 | analogix_dp_bridge_disable(dp->bridge); | 1423 | analogix_dp_bridge_disable(dp->bridge); |
1439 | dp->connector.funcs->destroy(&dp->connector); | 1424 | dp->connector.funcs->destroy(&dp->connector); |
1440 | dp->encoder->funcs->destroy(dp->encoder); | ||
1441 | 1425 | ||
1442 | if (dp->plat_data->panel) { | 1426 | if (dp->plat_data->panel) { |
1443 | if (drm_panel_unprepare(dp->plat_data->panel)) | 1427 | if (drm_panel_unprepare(dp->plat_data->panel)) |
@@ -1447,16 +1431,14 @@ void analogix_dp_unbind(struct device *dev, struct device *master, | |||
1447 | } | 1431 | } |
1448 | 1432 | ||
1449 | drm_dp_aux_unregister(&dp->aux); | 1433 | drm_dp_aux_unregister(&dp->aux); |
1450 | pm_runtime_disable(dev); | 1434 | pm_runtime_disable(dp->dev); |
1451 | clk_disable_unprepare(dp->clock); | 1435 | clk_disable_unprepare(dp->clock); |
1452 | } | 1436 | } |
1453 | EXPORT_SYMBOL_GPL(analogix_dp_unbind); | 1437 | EXPORT_SYMBOL_GPL(analogix_dp_unbind); |
1454 | 1438 | ||
1455 | #ifdef CONFIG_PM | 1439 | #ifdef CONFIG_PM |
1456 | int analogix_dp_suspend(struct device *dev) | 1440 | int analogix_dp_suspend(struct analogix_dp_device *dp) |
1457 | { | 1441 | { |
1458 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
1459 | |||
1460 | clk_disable_unprepare(dp->clock); | 1442 | clk_disable_unprepare(dp->clock); |
1461 | 1443 | ||
1462 | if (dp->plat_data->panel) { | 1444 | if (dp->plat_data->panel) { |
@@ -1468,9 +1450,8 @@ int analogix_dp_suspend(struct device *dev) | |||
1468 | } | 1450 | } |
1469 | EXPORT_SYMBOL_GPL(analogix_dp_suspend); | 1451 | EXPORT_SYMBOL_GPL(analogix_dp_suspend); |
1470 | 1452 | ||
1471 | int analogix_dp_resume(struct device *dev) | 1453 | int analogix_dp_resume(struct analogix_dp_device *dp) |
1472 | { | 1454 | { |
1473 | struct analogix_dp_device *dp = dev_get_drvdata(dev); | ||
1474 | int ret; | 1455 | int ret; |
1475 | 1456 | ||
1476 | ret = clk_prepare_enable(dp->clock); | 1457 | ret = clk_prepare_enable(dp->clock); |
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index b1ab4ab09532..60373d7eb220 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c | |||
@@ -137,7 +137,9 @@ static int sii902x_get_modes(struct drm_connector *connector) | |||
137 | struct sii902x *sii902x = connector_to_sii902x(connector); | 137 | struct sii902x *sii902x = connector_to_sii902x(connector); |
138 | struct regmap *regmap = sii902x->regmap; | 138 | struct regmap *regmap = sii902x->regmap; |
139 | u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; | 139 | u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; |
140 | struct device *dev = &sii902x->i2c->dev; | ||
140 | unsigned long timeout; | 141 | unsigned long timeout; |
142 | unsigned int retries; | ||
141 | unsigned int status; | 143 | unsigned int status; |
142 | struct edid *edid; | 144 | struct edid *edid; |
143 | int num = 0; | 145 | int num = 0; |
@@ -159,7 +161,7 @@ static int sii902x_get_modes(struct drm_connector *connector) | |||
159 | time_before(jiffies, timeout)); | 161 | time_before(jiffies, timeout)); |
160 | 162 | ||
161 | if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) { | 163 | if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) { |
162 | dev_err(&sii902x->i2c->dev, "failed to acquire the i2c bus\n"); | 164 | dev_err(dev, "failed to acquire the i2c bus\n"); |
163 | return -ETIMEDOUT; | 165 | return -ETIMEDOUT; |
164 | } | 166 | } |
165 | 167 | ||
@@ -179,9 +181,19 @@ static int sii902x_get_modes(struct drm_connector *connector) | |||
179 | if (ret) | 181 | if (ret) |
180 | return ret; | 182 | return ret; |
181 | 183 | ||
182 | ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status); | 184 | /* |
185 | * Sometimes the I2C bus can stall after failure to use the | ||
186 | * EDID channel. Retry a few times to see if things clear | ||
187 | * up, else continue anyway. | ||
188 | */ | ||
189 | retries = 5; | ||
190 | do { | ||
191 | ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, | ||
192 | &status); | ||
193 | retries--; | ||
194 | } while (ret && retries); | ||
183 | if (ret) | 195 | if (ret) |
184 | return ret; | 196 | dev_err(dev, "failed to read status (%d)\n", ret); |
185 | 197 | ||
186 | ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA, | 198 | ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA, |
187 | SII902X_SYS_CTRL_DDC_BUS_REQ | | 199 | SII902X_SYS_CTRL_DDC_BUS_REQ | |
@@ -201,7 +213,7 @@ static int sii902x_get_modes(struct drm_connector *connector) | |||
201 | 213 | ||
202 | if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ | | 214 | if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ | |
203 | SII902X_SYS_CTRL_DDC_BUS_GRTD)) { | 215 | SII902X_SYS_CTRL_DDC_BUS_GRTD)) { |
204 | dev_err(&sii902x->i2c->dev, "failed to release the i2c bus\n"); | 216 | dev_err(dev, "failed to release the i2c bus\n"); |
205 | return -ETIMEDOUT; | 217 | return -ETIMEDOUT; |
206 | } | 218 | } |
207 | 219 | ||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index f9802399cc0d..53ebbe2904b6 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | |||
@@ -1654,6 +1654,8 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) | |||
1654 | * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified | 1654 | * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified |
1655 | * as needing the workaround, with 4 iterations for v1.30a and 1 | 1655 | * as needing the workaround, with 4 iterations for v1.30a and 1 |
1656 | * iteration for others. | 1656 | * iteration for others. |
1657 | * The Amlogic Meson GX SoCs (v2.01a) have been identified as needing | ||
1658 | * the workaround with a single iteration. | ||
1657 | */ | 1659 | */ |
1658 | 1660 | ||
1659 | switch (hdmi->version) { | 1661 | switch (hdmi->version) { |
@@ -1662,6 +1664,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) | |||
1662 | break; | 1664 | break; |
1663 | case 0x131a: | 1665 | case 0x131a: |
1664 | case 0x132a: | 1666 | case 0x132a: |
1667 | case 0x201a: | ||
1665 | count = 1; | 1668 | count = 1; |
1666 | break; | 1669 | break; |
1667 | default: | 1670 | default: |
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 7bac101c285c..226171a3ece1 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | |||
@@ -342,7 +342,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) | |||
342 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, | 342 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, |
343 | val, !(val & GEN_CMD_FULL), 1000, | 343 | val, !(val & GEN_CMD_FULL), 1000, |
344 | CMD_PKT_STATUS_TIMEOUT_US); | 344 | CMD_PKT_STATUS_TIMEOUT_US); |
345 | if (ret < 0) { | 345 | if (ret) { |
346 | dev_err(dsi->dev, "failed to get available command FIFO\n"); | 346 | dev_err(dsi->dev, "failed to get available command FIFO\n"); |
347 | return ret; | 347 | return ret; |
348 | } | 348 | } |
@@ -353,7 +353,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) | |||
353 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, | 353 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, |
354 | val, (val & mask) == mask, | 354 | val, (val & mask) == mask, |
355 | 1000, CMD_PKT_STATUS_TIMEOUT_US); | 355 | 1000, CMD_PKT_STATUS_TIMEOUT_US); |
356 | if (ret < 0) { | 356 | if (ret) { |
357 | dev_err(dsi->dev, "failed to write command FIFO\n"); | 357 | dev_err(dsi->dev, "failed to write command FIFO\n"); |
358 | return ret; | 358 | return ret; |
359 | } | 359 | } |
@@ -385,7 +385,7 @@ static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, | |||
385 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, | 385 | ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, |
386 | val, !(val & GEN_PLD_W_FULL), 1000, | 386 | val, !(val & GEN_PLD_W_FULL), 1000, |
387 | CMD_PKT_STATUS_TIMEOUT_US); | 387 | CMD_PKT_STATUS_TIMEOUT_US); |
388 | if (ret < 0) { | 388 | if (ret) { |
389 | dev_err(dsi->dev, | 389 | dev_err(dsi->dev, |
390 | "failed to get available write payload FIFO\n"); | 390 | "failed to get available write payload FIFO\n"); |
391 | return ret; | 391 | return ret; |
@@ -721,13 +721,13 @@ static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi) | |||
721 | 721 | ||
722 | ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, | 722 | ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, |
723 | val & PHY_LOCK, 1000, PHY_STATUS_TIMEOUT_US); | 723 | val & PHY_LOCK, 1000, PHY_STATUS_TIMEOUT_US); |
724 | if (ret < 0) | 724 | if (ret) |
725 | DRM_DEBUG_DRIVER("failed to wait phy lock state\n"); | 725 | DRM_DEBUG_DRIVER("failed to wait phy lock state\n"); |
726 | 726 | ||
727 | ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, | 727 | ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, |
728 | val, val & PHY_STOP_STATE_CLK_LANE, 1000, | 728 | val, val & PHY_STOP_STATE_CLK_LANE, 1000, |
729 | PHY_STATUS_TIMEOUT_US); | 729 | PHY_STATUS_TIMEOUT_US); |
730 | if (ret < 0) | 730 | if (ret) |
731 | DRM_DEBUG_DRIVER("failed to wait phy clk lane stop state\n"); | 731 | DRM_DEBUG_DRIVER("failed to wait phy clk lane stop state\n"); |
732 | } | 732 | } |
733 | 733 | ||
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 46733d534587..34b7d420e555 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -759,6 +759,10 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, | |||
759 | state->rotation = val; | 759 | state->rotation = val; |
760 | } else if (property == plane->zpos_property) { | 760 | } else if (property == plane->zpos_property) { |
761 | state->zpos = val; | 761 | state->zpos = val; |
762 | } else if (property == plane->color_encoding_property) { | ||
763 | state->color_encoding = val; | ||
764 | } else if (property == plane->color_range_property) { | ||
765 | state->color_range = val; | ||
762 | } else if (plane->funcs->atomic_set_property) { | 766 | } else if (plane->funcs->atomic_set_property) { |
763 | return plane->funcs->atomic_set_property(plane, state, | 767 | return plane->funcs->atomic_set_property(plane, state, |
764 | property, val); | 768 | property, val); |
@@ -818,6 +822,10 @@ drm_atomic_plane_get_property(struct drm_plane *plane, | |||
818 | *val = state->rotation; | 822 | *val = state->rotation; |
819 | } else if (property == plane->zpos_property) { | 823 | } else if (property == plane->zpos_property) { |
820 | *val = state->zpos; | 824 | *val = state->zpos; |
825 | } else if (property == plane->color_encoding_property) { | ||
826 | *val = state->color_encoding; | ||
827 | } else if (property == plane->color_range_property) { | ||
828 | *val = state->color_range; | ||
821 | } else if (plane->funcs->atomic_get_property) { | 829 | } else if (plane->funcs->atomic_get_property) { |
822 | return plane->funcs->atomic_get_property(plane, state, property, val); | 830 | return plane->funcs->atomic_get_property(plane, state, property, val); |
823 | } else { | 831 | } else { |
@@ -882,12 +890,14 @@ static int drm_atomic_plane_check(struct drm_plane *plane, | |||
882 | } | 890 | } |
883 | 891 | ||
884 | /* Check whether this plane supports the fb pixel format. */ | 892 | /* Check whether this plane supports the fb pixel format. */ |
885 | ret = drm_plane_check_pixel_format(plane, state->fb->format->format); | 893 | ret = drm_plane_check_pixel_format(plane, state->fb->format->format, |
894 | state->fb->modifier); | ||
886 | if (ret) { | 895 | if (ret) { |
887 | struct drm_format_name_buf format_name; | 896 | struct drm_format_name_buf format_name; |
888 | DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", | 897 | DRM_DEBUG_ATOMIC("Invalid pixel format %s, modifier 0x%llx\n", |
889 | drm_get_format_name(state->fb->format->format, | 898 | drm_get_format_name(state->fb->format->format, |
890 | &format_name)); | 899 | &format_name), |
900 | state->fb->modifier); | ||
891 | return ret; | 901 | return ret; |
892 | } | 902 | } |
893 | 903 | ||
@@ -944,6 +954,10 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, | |||
944 | drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest)); | 954 | drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest)); |
945 | drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src)); | 955 | drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src)); |
946 | drm_printf(p, "\trotation=%x\n", state->rotation); | 956 | drm_printf(p, "\trotation=%x\n", state->rotation); |
957 | drm_printf(p, "\tcolor-encoding=%s\n", | ||
958 | drm_get_color_encoding_name(state->color_encoding)); | ||
959 | drm_printf(p, "\tcolor-range=%s\n", | ||
960 | drm_get_color_range_name(state->color_range)); | ||
947 | 961 | ||
948 | if (plane->funcs->atomic_print_state) | 962 | if (plane->funcs->atomic_print_state) |
949 | plane->funcs->atomic_print_state(p, state); | 963 | plane->funcs->atomic_print_state(p, state); |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ae3cbfe9e01c..00c78c1c9681 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -699,7 +699,6 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset); | |||
699 | * drm_atomic_helper_check_plane_state() - Check plane state for validity | 699 | * drm_atomic_helper_check_plane_state() - Check plane state for validity |
700 | * @plane_state: plane state to check | 700 | * @plane_state: plane state to check |
701 | * @crtc_state: crtc state to check | 701 | * @crtc_state: crtc state to check |
702 | * @clip: integer clipping coordinates | ||
703 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point | 702 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point |
704 | * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point | 703 | * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point |
705 | * @can_position: is it legal to position the plane such that it | 704 | * @can_position: is it legal to position the plane such that it |
@@ -719,7 +718,6 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset); | |||
719 | */ | 718 | */ |
720 | int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, | 719 | int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, |
721 | const struct drm_crtc_state *crtc_state, | 720 | const struct drm_crtc_state *crtc_state, |
722 | const struct drm_rect *clip, | ||
723 | int min_scale, | 721 | int min_scale, |
724 | int max_scale, | 722 | int max_scale, |
725 | bool can_position, | 723 | bool can_position, |
@@ -729,6 +727,7 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, | |||
729 | struct drm_rect *src = &plane_state->src; | 727 | struct drm_rect *src = &plane_state->src; |
730 | struct drm_rect *dst = &plane_state->dst; | 728 | struct drm_rect *dst = &plane_state->dst; |
731 | unsigned int rotation = plane_state->rotation; | 729 | unsigned int rotation = plane_state->rotation; |
730 | struct drm_rect clip = {}; | ||
732 | int hscale, vscale; | 731 | int hscale, vscale; |
733 | 732 | ||
734 | WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc); | 733 | WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc); |
@@ -764,7 +763,10 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, | |||
764 | return -ERANGE; | 763 | return -ERANGE; |
765 | } | 764 | } |
766 | 765 | ||
767 | plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); | 766 | if (crtc_state->enable) |
767 | drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2); | ||
768 | |||
769 | plane_state->visible = drm_rect_clip_scaled(src, dst, &clip, hscale, vscale); | ||
768 | 770 | ||
769 | drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); | 771 | drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); |
770 | 772 | ||
@@ -778,10 +780,10 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, | |||
778 | */ | 780 | */ |
779 | return 0; | 781 | return 0; |
780 | 782 | ||
781 | if (!can_position && !drm_rect_equals(dst, clip)) { | 783 | if (!can_position && !drm_rect_equals(dst, &clip)) { |
782 | DRM_DEBUG_KMS("Plane must cover entire CRTC\n"); | 784 | DRM_DEBUG_KMS("Plane must cover entire CRTC\n"); |
783 | drm_rect_debug_print("dst: ", dst, false); | 785 | drm_rect_debug_print("dst: ", dst, false); |
784 | drm_rect_debug_print("clip: ", clip, false); | 786 | drm_rect_debug_print("clip: ", &clip, false); |
785 | return -EINVAL; | 787 | return -EINVAL; |
786 | } | 788 | } |
787 | 789 | ||
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 0d002b045bd2..4ff064623836 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c | |||
@@ -88,6 +88,20 @@ | |||
88 | * drm_mode_crtc_set_gamma_size(). Drivers which support both should use | 88 | * drm_mode_crtc_set_gamma_size(). Drivers which support both should use |
89 | * drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the | 89 | * drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the |
90 | * "GAMMA_LUT" property above. | 90 | * "GAMMA_LUT" property above. |
91 | * | ||
92 | * Support for different non RGB color encodings is controlled through | ||
93 | * &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They | ||
94 | * are set up by calling drm_plane_create_color_properties(). | ||
95 | * | ||
96 | * "COLOR_ENCODING" | ||
97 | * Optional plane enum property to support different non RGB | ||
98 | * color encodings. The driver can provide a subset of standard | ||
99 | * enum values supported by the DRM plane. | ||
100 | * | ||
101 | * "COLOR_RANGE" | ||
102 | * Optional plane enum property to support different non RGB | ||
103 | * color parameter ranges. The driver can provide a subset of | ||
104 | * standard enum values supported by the DRM plane. | ||
91 | */ | 105 | */ |
92 | 106 | ||
93 | /** | 107 | /** |
@@ -339,3 +353,122 @@ out: | |||
339 | drm_modeset_unlock(&crtc->mutex); | 353 | drm_modeset_unlock(&crtc->mutex); |
340 | return ret; | 354 | return ret; |
341 | } | 355 | } |
356 | |||
357 | static const char * const color_encoding_name[] = { | ||
358 | [DRM_COLOR_YCBCR_BT601] = "ITU-R BT.601 YCbCr", | ||
359 | [DRM_COLOR_YCBCR_BT709] = "ITU-R BT.709 YCbCr", | ||
360 | [DRM_COLOR_YCBCR_BT2020] = "ITU-R BT.2020 YCbCr", | ||
361 | }; | ||
362 | |||
363 | static const char * const color_range_name[] = { | ||
364 | [DRM_COLOR_YCBCR_FULL_RANGE] = "YCbCr full range", | ||
365 | [DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range", | ||
366 | }; | ||
367 | |||
368 | /** | ||
369 | * drm_get_color_encoding_name - return a string for color encoding | ||
370 | * @encoding: color encoding to compute name of | ||
371 | * | ||
372 | * In contrast to the other drm_get_*_name functions this one here returns a | ||
373 | * const pointer and hence is threadsafe. | ||
374 | */ | ||
375 | const char *drm_get_color_encoding_name(enum drm_color_encoding encoding) | ||
376 | { | ||
377 | if (WARN_ON(encoding >= ARRAY_SIZE(color_encoding_name))) | ||
378 | return "unknown"; | ||
379 | |||
380 | return color_encoding_name[encoding]; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * drm_get_color_range_name - return a string for color range | ||
385 | * @range: color range to compute name of | ||
386 | * | ||
387 | * In contrast to the other drm_get_*_name functions this one here returns a | ||
388 | * const pointer and hence is threadsafe. | ||
389 | */ | ||
390 | const char *drm_get_color_range_name(enum drm_color_range range) | ||
391 | { | ||
392 | if (WARN_ON(range >= ARRAY_SIZE(color_range_name))) | ||
393 | return "unknown"; | ||
394 | |||
395 | return color_range_name[range]; | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * drm_plane_create_color_properties - color encoding related plane properties | ||
400 | * @plane: plane object | ||
401 | * @supported_encodings: bitfield indicating supported color encodings | ||
402 | * @supported_ranges: bitfileld indicating supported color ranges | ||
403 | * @default_encoding: default color encoding | ||
404 | * @default_range: default color range | ||
405 | * | ||
406 | * Create and attach plane specific COLOR_ENCODING and COLOR_RANGE | ||
407 | * properties to @plane. The supported encodings and ranges should | ||
408 | * be provided in supported_encodings and supported_ranges bitmasks. | ||
409 | * Each bit set in the bitmask indicates that its number as enum | ||
410 | * value is supported. | ||
411 | */ | ||
412 | int drm_plane_create_color_properties(struct drm_plane *plane, | ||
413 | u32 supported_encodings, | ||
414 | u32 supported_ranges, | ||
415 | enum drm_color_encoding default_encoding, | ||
416 | enum drm_color_range default_range) | ||
417 | { | ||
418 | struct drm_device *dev = plane->dev; | ||
419 | struct drm_property *prop; | ||
420 | struct drm_prop_enum_list enum_list[max(DRM_COLOR_ENCODING_MAX, | ||
421 | DRM_COLOR_RANGE_MAX)]; | ||
422 | int i, len; | ||
423 | |||
424 | if (WARN_ON(supported_encodings == 0 || | ||
425 | (supported_encodings & -BIT(DRM_COLOR_ENCODING_MAX)) != 0 || | ||
426 | (supported_encodings & BIT(default_encoding)) == 0)) | ||
427 | return -EINVAL; | ||
428 | |||
429 | if (WARN_ON(supported_ranges == 0 || | ||
430 | (supported_ranges & -BIT(DRM_COLOR_RANGE_MAX)) != 0 || | ||
431 | (supported_ranges & BIT(default_range)) == 0)) | ||
432 | return -EINVAL; | ||
433 | |||
434 | len = 0; | ||
435 | for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) { | ||
436 | if ((supported_encodings & BIT(i)) == 0) | ||
437 | continue; | ||
438 | |||
439 | enum_list[len].type = i; | ||
440 | enum_list[len].name = color_encoding_name[i]; | ||
441 | len++; | ||
442 | } | ||
443 | |||
444 | prop = drm_property_create_enum(dev, 0, "COLOR_ENCODING", | ||
445 | enum_list, len); | ||
446 | if (!prop) | ||
447 | return -ENOMEM; | ||
448 | plane->color_encoding_property = prop; | ||
449 | drm_object_attach_property(&plane->base, prop, default_encoding); | ||
450 | if (plane->state) | ||
451 | plane->state->color_encoding = default_encoding; | ||
452 | |||
453 | len = 0; | ||
454 | for (i = 0; i < DRM_COLOR_RANGE_MAX; i++) { | ||
455 | if ((supported_ranges & BIT(i)) == 0) | ||
456 | continue; | ||
457 | |||
458 | enum_list[len].type = i; | ||
459 | enum_list[len].name = color_range_name[i]; | ||
460 | len++; | ||
461 | } | ||
462 | |||
463 | prop = drm_property_create_enum(dev, 0, "COLOR_RANGE", | ||
464 | enum_list, len); | ||
465 | if (!prop) | ||
466 | return -ENOMEM; | ||
467 | plane->color_range_property = prop; | ||
468 | drm_object_attach_property(&plane->base, prop, default_range); | ||
469 | if (plane->state) | ||
470 | plane->state->color_range = default_range; | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | EXPORT_SYMBOL(drm_plane_create_color_properties); | ||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 353e24fcde9e..03583887cfec 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -629,12 +629,14 @@ retry: | |||
629 | */ | 629 | */ |
630 | if (!crtc->primary->format_default) { | 630 | if (!crtc->primary->format_default) { |
631 | ret = drm_plane_check_pixel_format(crtc->primary, | 631 | ret = drm_plane_check_pixel_format(crtc->primary, |
632 | fb->format->format); | 632 | fb->format->format, |
633 | fb->modifier); | ||
633 | if (ret) { | 634 | if (ret) { |
634 | struct drm_format_name_buf format_name; | 635 | struct drm_format_name_buf format_name; |
635 | DRM_DEBUG_KMS("Invalid pixel format %s\n", | 636 | DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n", |
636 | drm_get_format_name(fb->format->format, | 637 | drm_get_format_name(fb->format->format, |
637 | &format_name)); | 638 | &format_name), |
639 | fb->modifier); | ||
638 | goto out; | 640 | goto out; |
639 | } | 641 | } |
640 | } | 642 | } |
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index af00f42ba269..3c2b82865ad2 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h | |||
@@ -71,6 +71,8 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | |||
71 | void *data, struct drm_file *file_priv); | 71 | void *data, struct drm_file *file_priv); |
72 | 72 | ||
73 | /* drm_color_mgmt.c */ | 73 | /* drm_color_mgmt.c */ |
74 | const char *drm_get_color_encoding_name(enum drm_color_encoding encoding); | ||
75 | const char *drm_get_color_range_name(enum drm_color_range range); | ||
74 | 76 | ||
75 | /* IOCTLs */ | 77 | /* IOCTLs */ |
76 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, | 78 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
@@ -196,8 +198,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
196 | /* drm_plane.c */ | 198 | /* drm_plane.c */ |
197 | int drm_plane_register_all(struct drm_device *dev); | 199 | int drm_plane_register_all(struct drm_device *dev); |
198 | void drm_plane_unregister_all(struct drm_device *dev); | 200 | void drm_plane_unregister_all(struct drm_device *dev); |
199 | int drm_plane_check_pixel_format(const struct drm_plane *plane, | 201 | int drm_plane_check_pixel_format(struct drm_plane *plane, |
200 | u32 format); | 202 | u32 format, u64 modifier); |
201 | 203 | ||
202 | /* drm_bridge.c */ | 204 | /* drm_bridge.c */ |
203 | void drm_bridge_detach(struct drm_bridge *bridge); | 205 | void drm_bridge_detach(struct drm_bridge *bridge); |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 9acc1e157813..a1b9338736e3 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -99,7 +99,7 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev, | |||
99 | case DRM_MINOR_CONTROL: | 99 | case DRM_MINOR_CONTROL: |
100 | return &dev->control; | 100 | return &dev->control; |
101 | default: | 101 | default: |
102 | return NULL; | 102 | BUG(); |
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 7ca500b8c399..3c54044214db 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c | |||
@@ -153,7 +153,7 @@ EXPORT_SYMBOL(drm_legacy_ioremapfree); | |||
153 | u64 drm_get_max_iomem(void) | 153 | u64 drm_get_max_iomem(void) |
154 | { | 154 | { |
155 | struct resource *tmp; | 155 | struct resource *tmp; |
156 | u64 max_iomem = 0; | 156 | resource_size_t max_iomem = 0; |
157 | 157 | ||
158 | for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { | 158 | for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { |
159 | max_iomem = max(max_iomem, tmp->end); | 159 | max_iomem = max(max_iomem, tmp->end); |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 186c4e90cc1c..a351bd888a61 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -180,7 +180,7 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node, | |||
180 | struct drm_mm *mm = hole_node->mm; | 180 | struct drm_mm *mm = hole_node->mm; |
181 | struct rb_node **link, *rb; | 181 | struct rb_node **link, *rb; |
182 | struct drm_mm_node *parent; | 182 | struct drm_mm_node *parent; |
183 | bool leftmost = true; | 183 | bool leftmost; |
184 | 184 | ||
185 | node->__subtree_last = LAST(node); | 185 | node->__subtree_last = LAST(node); |
186 | 186 | ||
@@ -201,6 +201,7 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node, | |||
201 | } else { | 201 | } else { |
202 | rb = NULL; | 202 | rb = NULL; |
203 | link = &mm->interval_tree.rb_root.rb_node; | 203 | link = &mm->interval_tree.rb_root.rb_node; |
204 | leftmost = true; | ||
204 | } | 205 | } |
205 | 206 | ||
206 | while (*link) { | 207 | while (*link) { |
@@ -208,11 +209,11 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node, | |||
208 | parent = rb_entry(rb, struct drm_mm_node, rb); | 209 | parent = rb_entry(rb, struct drm_mm_node, rb); |
209 | if (parent->__subtree_last < node->__subtree_last) | 210 | if (parent->__subtree_last < node->__subtree_last) |
210 | parent->__subtree_last = node->__subtree_last; | 211 | parent->__subtree_last = node->__subtree_last; |
211 | if (node->start < parent->start) | 212 | if (node->start < parent->start) { |
212 | link = &parent->rb.rb_left; | 213 | link = &parent->rb.rb_left; |
213 | else { | 214 | } else { |
214 | link = &parent->rb.rb_right; | 215 | link = &parent->rb.rb_right; |
215 | leftmost = true; | 216 | leftmost = false; |
216 | } | 217 | } |
217 | } | 218 | } |
218 | 219 | ||
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 963e23db0fe7..8a5100685875 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c | |||
@@ -113,6 +113,7 @@ retry: | |||
113 | kfree(ctx); | 113 | kfree(ctx); |
114 | return; | 114 | return; |
115 | } | 115 | } |
116 | ww_acquire_done(&ctx->ww_ctx); | ||
116 | 117 | ||
117 | WARN_ON(config->acquire_ctx); | 118 | WARN_ON(config->acquire_ctx); |
118 | 119 | ||
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 4c191c050e7d..1fe122461298 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c | |||
@@ -122,12 +122,10 @@ int drm_of_component_probe(struct device *dev, | |||
122 | if (!port) | 122 | if (!port) |
123 | break; | 123 | break; |
124 | 124 | ||
125 | if (!of_device_is_available(port->parent)) { | 125 | if (of_device_is_available(port->parent)) |
126 | of_node_put(port); | 126 | drm_of_component_match_add(dev, &match, compare_of, |
127 | continue; | 127 | port); |
128 | } | ||
129 | 128 | ||
130 | drm_of_component_match_add(dev, &match, compare_of, port); | ||
131 | of_node_put(port); | 129 | of_node_put(port); |
132 | } | 130 | } |
133 | 131 | ||
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 1f2af707ce03..902cc1a71e45 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/dmi.h> | 11 | #include <linux/dmi.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <drm/drm_connector.h> | 13 | #include <drm/drm_connector.h> |
14 | #include <drm/drm_utils.h> | ||
14 | 15 | ||
15 | #ifdef CONFIG_DMI | 16 | #ifdef CONFIG_DMI |
16 | 17 | ||
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 09de6ecb3968..a5d1fc7e8a37 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c | |||
@@ -549,16 +549,33 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
549 | return 0; | 549 | return 0; |
550 | } | 550 | } |
551 | 551 | ||
552 | int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format) | 552 | int drm_plane_check_pixel_format(struct drm_plane *plane, |
553 | u32 format, u64 modifier) | ||
553 | { | 554 | { |
554 | unsigned int i; | 555 | unsigned int i; |
555 | 556 | ||
556 | for (i = 0; i < plane->format_count; i++) { | 557 | for (i = 0; i < plane->format_count; i++) { |
557 | if (format == plane->format_types[i]) | 558 | if (format == plane->format_types[i]) |
558 | return 0; | 559 | break; |
560 | } | ||
561 | if (i == plane->format_count) | ||
562 | return -EINVAL; | ||
563 | |||
564 | if (!plane->modifier_count) | ||
565 | return 0; | ||
566 | |||
567 | for (i = 0; i < plane->modifier_count; i++) { | ||
568 | if (modifier == plane->modifiers[i]) | ||
569 | break; | ||
559 | } | 570 | } |
571 | if (i == plane->modifier_count) | ||
572 | return -EINVAL; | ||
560 | 573 | ||
561 | return -EINVAL; | 574 | if (plane->funcs->format_mod_supported && |
575 | !plane->funcs->format_mod_supported(plane, format, modifier)) | ||
576 | return -EINVAL; | ||
577 | |||
578 | return 0; | ||
562 | } | 579 | } |
563 | 580 | ||
564 | /* | 581 | /* |
@@ -602,12 +619,14 @@ static int __setplane_internal(struct drm_plane *plane, | |||
602 | } | 619 | } |
603 | 620 | ||
604 | /* Check whether this plane supports the fb pixel format. */ | 621 | /* Check whether this plane supports the fb pixel format. */ |
605 | ret = drm_plane_check_pixel_format(plane, fb->format->format); | 622 | ret = drm_plane_check_pixel_format(plane, fb->format->format, |
623 | fb->modifier); | ||
606 | if (ret) { | 624 | if (ret) { |
607 | struct drm_format_name_buf format_name; | 625 | struct drm_format_name_buf format_name; |
608 | DRM_DEBUG_KMS("Invalid pixel format %s\n", | 626 | DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n", |
609 | drm_get_format_name(fb->format->format, | 627 | drm_get_format_name(fb->format->format, |
610 | &format_name)); | 628 | &format_name), |
629 | fb->modifier); | ||
611 | goto out; | 630 | goto out; |
612 | } | 631 | } |
613 | 632 | ||
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index f1be8cd4e387..f88f68161519 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -106,7 +106,6 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, | |||
106 | * @fb: framebuffer to flip onto plane | 106 | * @fb: framebuffer to flip onto plane |
107 | * @src: source coordinates in 16.16 fixed point | 107 | * @src: source coordinates in 16.16 fixed point |
108 | * @dst: integer destination coordinates | 108 | * @dst: integer destination coordinates |
109 | * @clip: integer clipping coordinates | ||
110 | * @rotation: plane rotation | 109 | * @rotation: plane rotation |
111 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point | 110 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point |
112 | * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point | 111 | * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point |
@@ -131,7 +130,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane, | |||
131 | struct drm_framebuffer *fb, | 130 | struct drm_framebuffer *fb, |
132 | struct drm_rect *src, | 131 | struct drm_rect *src, |
133 | struct drm_rect *dst, | 132 | struct drm_rect *dst, |
134 | const struct drm_rect *clip, | ||
135 | unsigned int rotation, | 133 | unsigned int rotation, |
136 | int min_scale, | 134 | int min_scale, |
137 | int max_scale, | 135 | int max_scale, |
@@ -157,11 +155,12 @@ int drm_plane_helper_check_update(struct drm_plane *plane, | |||
157 | struct drm_crtc_state crtc_state = { | 155 | struct drm_crtc_state crtc_state = { |
158 | .crtc = crtc, | 156 | .crtc = crtc, |
159 | .enable = crtc->enabled, | 157 | .enable = crtc->enabled, |
158 | .mode = crtc->mode, | ||
160 | }; | 159 | }; |
161 | int ret; | 160 | int ret; |
162 | 161 | ||
163 | ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, | 162 | ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, |
164 | clip, min_scale, max_scale, | 163 | min_scale, max_scale, |
165 | can_position, | 164 | can_position, |
166 | can_update_disabled); | 165 | can_update_disabled); |
167 | if (ret) | 166 | if (ret) |
@@ -239,16 +238,12 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
239 | .x2 = crtc_x + crtc_w, | 238 | .x2 = crtc_x + crtc_w, |
240 | .y2 = crtc_y + crtc_h, | 239 | .y2 = crtc_y + crtc_h, |
241 | }; | 240 | }; |
242 | const struct drm_rect clip = { | ||
243 | .x2 = crtc->mode.hdisplay, | ||
244 | .y2 = crtc->mode.vdisplay, | ||
245 | }; | ||
246 | struct drm_connector **connector_list; | 241 | struct drm_connector **connector_list; |
247 | int num_connectors, ret; | 242 | int num_connectors, ret; |
248 | bool visible; | 243 | bool visible; |
249 | 244 | ||
250 | ret = drm_plane_helper_check_update(plane, crtc, fb, | 245 | ret = drm_plane_helper_check_update(plane, crtc, fb, |
251 | &src, &dest, &clip, | 246 | &src, &dest, |
252 | DRM_MODE_ROTATE_0, | 247 | DRM_MODE_ROTATE_0, |
253 | DRM_PLANE_HELPER_NO_SCALING, | 248 | DRM_PLANE_HELPER_NO_SCALING, |
254 | DRM_PLANE_HELPER_NO_SCALING, | 249 | DRM_PLANE_HELPER_NO_SCALING, |
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index e82a976f0fba..7856a9b3f8a8 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -230,26 +230,26 @@ void drm_gem_map_detach(struct dma_buf *dma_buf, | |||
230 | struct drm_prime_attachment *prime_attach = attach->priv; | 230 | struct drm_prime_attachment *prime_attach = attach->priv; |
231 | struct drm_gem_object *obj = dma_buf->priv; | 231 | struct drm_gem_object *obj = dma_buf->priv; |
232 | struct drm_device *dev = obj->dev; | 232 | struct drm_device *dev = obj->dev; |
233 | struct sg_table *sgt; | ||
234 | 233 | ||
235 | if (dev->driver->gem_prime_unpin) | 234 | if (prime_attach) { |
236 | dev->driver->gem_prime_unpin(obj); | 235 | struct sg_table *sgt = prime_attach->sgt; |
237 | 236 | ||
238 | if (!prime_attach) | 237 | if (sgt) { |
239 | return; | 238 | if (prime_attach->dir != DMA_NONE) |
240 | 239 | dma_unmap_sg_attrs(attach->dev, sgt->sgl, | |
241 | sgt = prime_attach->sgt; | 240 | sgt->nents, |
242 | if (sgt) { | 241 | prime_attach->dir, |
243 | if (prime_attach->dir != DMA_NONE) | 242 | DMA_ATTR_SKIP_CPU_SYNC); |
244 | dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, | 243 | sg_free_table(sgt); |
245 | prime_attach->dir, | 244 | } |
246 | DMA_ATTR_SKIP_CPU_SYNC); | 245 | |
247 | sg_free_table(sgt); | 246 | kfree(sgt); |
247 | kfree(prime_attach); | ||
248 | attach->priv = NULL; | ||
248 | } | 249 | } |
249 | 250 | ||
250 | kfree(sgt); | 251 | if (dev->driver->gem_prime_unpin) |
251 | kfree(prime_attach); | 252 | dev->driver->gem_prime_unpin(obj); |
252 | attach->priv = NULL; | ||
253 | } | 253 | } |
254 | EXPORT_SYMBOL(drm_gem_map_detach); | 254 | EXPORT_SYMBOL(drm_gem_map_detach); |
255 | 255 | ||
@@ -922,40 +922,40 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg); | |||
922 | /** | 922 | /** |
923 | * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array | 923 | * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array |
924 | * @sgt: scatter-gather table to convert | 924 | * @sgt: scatter-gather table to convert |
925 | * @pages: array of page pointers to store the page array in | 925 | * @pages: optional array of page pointers to store the page array in |
926 | * @addrs: optional array to store the dma bus address of each page | 926 | * @addrs: optional array to store the dma bus address of each page |
927 | * @max_pages: size of both the passed-in arrays | 927 | * @max_entries: size of both the passed-in arrays |
928 | * | 928 | * |
929 | * Exports an sg table into an array of pages and addresses. This is currently | 929 | * Exports an sg table into an array of pages and addresses. This is currently |
930 | * required by the TTM driver in order to do correct fault handling. | 930 | * required by the TTM driver in order to do correct fault handling. |
931 | */ | 931 | */ |
932 | int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, | 932 | int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, |
933 | dma_addr_t *addrs, int max_pages) | 933 | dma_addr_t *addrs, int max_entries) |
934 | { | 934 | { |
935 | unsigned count; | 935 | unsigned count; |
936 | struct scatterlist *sg; | 936 | struct scatterlist *sg; |
937 | struct page *page; | 937 | struct page *page; |
938 | u32 len; | 938 | u32 len, index; |
939 | int pg_index; | ||
940 | dma_addr_t addr; | 939 | dma_addr_t addr; |
941 | 940 | ||
942 | pg_index = 0; | 941 | index = 0; |
943 | for_each_sg(sgt->sgl, sg, sgt->nents, count) { | 942 | for_each_sg(sgt->sgl, sg, sgt->nents, count) { |
944 | len = sg->length; | 943 | len = sg->length; |
945 | page = sg_page(sg); | 944 | page = sg_page(sg); |
946 | addr = sg_dma_address(sg); | 945 | addr = sg_dma_address(sg); |
947 | 946 | ||
948 | while (len > 0) { | 947 | while (len > 0) { |
949 | if (WARN_ON(pg_index >= max_pages)) | 948 | if (WARN_ON(index >= max_entries)) |
950 | return -1; | 949 | return -1; |
951 | pages[pg_index] = page; | 950 | if (pages) |
951 | pages[index] = page; | ||
952 | if (addrs) | 952 | if (addrs) |
953 | addrs[pg_index] = addr; | 953 | addrs[index] = addr; |
954 | 954 | ||
955 | page++; | 955 | page++; |
956 | addr += PAGE_SIZE; | 956 | addr += PAGE_SIZE; |
957 | len -= PAGE_SIZE; | 957 | len -= PAGE_SIZE; |
958 | pg_index++; | 958 | index++; |
959 | } | 959 | } |
960 | } | 960 | } |
961 | return 0; | 961 | return 0; |
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index bae50e6b819d..6ac6ee41a6a3 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c | |||
@@ -50,11 +50,27 @@ | |||
50 | * IOCTL and in the get/set property IOCTL. | 50 | * IOCTL and in the get/set property IOCTL. |
51 | */ | 51 | */ |
52 | 52 | ||
53 | static bool drm_property_type_valid(struct drm_property *property) | 53 | static bool drm_property_flags_valid(u32 flags) |
54 | { | 54 | { |
55 | if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) | 55 | u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE; |
56 | return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE); | 56 | u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE; |
57 | return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE); | 57 | |
58 | /* Reject undefined/deprecated flags */ | ||
59 | if (flags & ~(DRM_MODE_PROP_LEGACY_TYPE | | ||
60 | DRM_MODE_PROP_EXTENDED_TYPE | | ||
61 | DRM_MODE_PROP_IMMUTABLE | | ||
62 | DRM_MODE_PROP_ATOMIC)) | ||
63 | return false; | ||
64 | |||
65 | /* We want either a legacy type or an extended type, but not both */ | ||
66 | if (!legacy_type == !ext_type) | ||
67 | return false; | ||
68 | |||
69 | /* Only one legacy type at a time please */ | ||
70 | if (legacy_type && !is_power_of_2(legacy_type)) | ||
71 | return false; | ||
72 | |||
73 | return true; | ||
58 | } | 74 | } |
59 | 75 | ||
60 | /** | 76 | /** |
@@ -72,12 +88,19 @@ static bool drm_property_type_valid(struct drm_property *property) | |||
72 | * Returns: | 88 | * Returns: |
73 | * A pointer to the newly created property on success, NULL on failure. | 89 | * A pointer to the newly created property on success, NULL on failure. |
74 | */ | 90 | */ |
75 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, | 91 | struct drm_property *drm_property_create(struct drm_device *dev, |
76 | const char *name, int num_values) | 92 | u32 flags, const char *name, |
93 | int num_values) | ||
77 | { | 94 | { |
78 | struct drm_property *property = NULL; | 95 | struct drm_property *property = NULL; |
79 | int ret; | 96 | int ret; |
80 | 97 | ||
98 | if (WARN_ON(!drm_property_flags_valid(flags))) | ||
99 | return NULL; | ||
100 | |||
101 | if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN)) | ||
102 | return NULL; | ||
103 | |||
81 | property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); | 104 | property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); |
82 | if (!property) | 105 | if (!property) |
83 | return NULL; | 106 | return NULL; |
@@ -99,15 +122,11 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, | |||
99 | property->num_values = num_values; | 122 | property->num_values = num_values; |
100 | INIT_LIST_HEAD(&property->enum_list); | 123 | INIT_LIST_HEAD(&property->enum_list); |
101 | 124 | ||
102 | if (name) { | 125 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
103 | strncpy(property->name, name, DRM_PROP_NAME_LEN); | 126 | property->name[DRM_PROP_NAME_LEN-1] = '\0'; |
104 | property->name[DRM_PROP_NAME_LEN-1] = '\0'; | ||
105 | } | ||
106 | 127 | ||
107 | list_add_tail(&property->head, &dev->mode_config.property_list); | 128 | list_add_tail(&property->head, &dev->mode_config.property_list); |
108 | 129 | ||
109 | WARN_ON(!drm_property_type_valid(property)); | ||
110 | |||
111 | return property; | 130 | return property; |
112 | fail: | 131 | fail: |
113 | kfree(property->values); | 132 | kfree(property->values); |
@@ -135,10 +154,10 @@ EXPORT_SYMBOL(drm_property_create); | |||
135 | * Returns: | 154 | * Returns: |
136 | * A pointer to the newly created property on success, NULL on failure. | 155 | * A pointer to the newly created property on success, NULL on failure. |
137 | */ | 156 | */ |
138 | struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, | 157 | struct drm_property *drm_property_create_enum(struct drm_device *dev, |
139 | const char *name, | 158 | u32 flags, const char *name, |
140 | const struct drm_prop_enum_list *props, | 159 | const struct drm_prop_enum_list *props, |
141 | int num_values) | 160 | int num_values) |
142 | { | 161 | { |
143 | struct drm_property *property; | 162 | struct drm_property *property; |
144 | int i, ret; | 163 | int i, ret; |
@@ -184,10 +203,10 @@ EXPORT_SYMBOL(drm_property_create_enum); | |||
184 | * A pointer to the newly created property on success, NULL on failure. | 203 | * A pointer to the newly created property on success, NULL on failure. |
185 | */ | 204 | */ |
186 | struct drm_property *drm_property_create_bitmask(struct drm_device *dev, | 205 | struct drm_property *drm_property_create_bitmask(struct drm_device *dev, |
187 | int flags, const char *name, | 206 | u32 flags, const char *name, |
188 | const struct drm_prop_enum_list *props, | 207 | const struct drm_prop_enum_list *props, |
189 | int num_props, | 208 | int num_props, |
190 | uint64_t supported_bits) | 209 | uint64_t supported_bits) |
191 | { | 210 | { |
192 | struct drm_property *property; | 211 | struct drm_property *property; |
193 | int i, ret, index = 0; | 212 | int i, ret, index = 0; |
@@ -221,8 +240,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, | |||
221 | EXPORT_SYMBOL(drm_property_create_bitmask); | 240 | EXPORT_SYMBOL(drm_property_create_bitmask); |
222 | 241 | ||
223 | static struct drm_property *property_create_range(struct drm_device *dev, | 242 | static struct drm_property *property_create_range(struct drm_device *dev, |
224 | int flags, const char *name, | 243 | u32 flags, const char *name, |
225 | uint64_t min, uint64_t max) | 244 | uint64_t min, uint64_t max) |
226 | { | 245 | { |
227 | struct drm_property *property; | 246 | struct drm_property *property; |
228 | 247 | ||
@@ -255,9 +274,9 @@ static struct drm_property *property_create_range(struct drm_device *dev, | |||
255 | * Returns: | 274 | * Returns: |
256 | * A pointer to the newly created property on success, NULL on failure. | 275 | * A pointer to the newly created property on success, NULL on failure. |
257 | */ | 276 | */ |
258 | struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, | 277 | struct drm_property *drm_property_create_range(struct drm_device *dev, |
259 | const char *name, | 278 | u32 flags, const char *name, |
260 | uint64_t min, uint64_t max) | 279 | uint64_t min, uint64_t max) |
261 | { | 280 | { |
262 | return property_create_range(dev, DRM_MODE_PROP_RANGE | flags, | 281 | return property_create_range(dev, DRM_MODE_PROP_RANGE | flags, |
263 | name, min, max); | 282 | name, min, max); |
@@ -284,8 +303,8 @@ EXPORT_SYMBOL(drm_property_create_range); | |||
284 | * A pointer to the newly created property on success, NULL on failure. | 303 | * A pointer to the newly created property on success, NULL on failure. |
285 | */ | 304 | */ |
286 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, | 305 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, |
287 | int flags, const char *name, | 306 | u32 flags, const char *name, |
288 | int64_t min, int64_t max) | 307 | int64_t min, int64_t max) |
289 | { | 308 | { |
290 | return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags, | 309 | return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags, |
291 | name, I642U64(min), I642U64(max)); | 310 | name, I642U64(min), I642U64(max)); |
@@ -311,7 +330,7 @@ EXPORT_SYMBOL(drm_property_create_signed_range); | |||
311 | * A pointer to the newly created property on success, NULL on failure. | 330 | * A pointer to the newly created property on success, NULL on failure. |
312 | */ | 331 | */ |
313 | struct drm_property *drm_property_create_object(struct drm_device *dev, | 332 | struct drm_property *drm_property_create_object(struct drm_device *dev, |
314 | int flags, const char *name, | 333 | u32 flags, const char *name, |
315 | uint32_t type) | 334 | uint32_t type) |
316 | { | 335 | { |
317 | struct drm_property *property; | 336 | struct drm_property *property; |
@@ -347,8 +366,8 @@ EXPORT_SYMBOL(drm_property_create_object); | |||
347 | * Returns: | 366 | * Returns: |
348 | * A pointer to the newly created property on success, NULL on failure. | 367 | * A pointer to the newly created property on success, NULL on failure. |
349 | */ | 368 | */ |
350 | struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags, | 369 | struct drm_property *drm_property_create_bool(struct drm_device *dev, |
351 | const char *name) | 370 | u32 flags, const char *name) |
352 | { | 371 | { |
353 | return drm_property_create_range(dev, flags, name, 0, 1); | 372 | return drm_property_create_range(dev, flags, name, 0, 1); |
354 | } | 373 | } |
@@ -374,26 +393,24 @@ int drm_property_add_enum(struct drm_property *property, int index, | |||
374 | { | 393 | { |
375 | struct drm_property_enum *prop_enum; | 394 | struct drm_property_enum *prop_enum; |
376 | 395 | ||
377 | if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) || | 396 | if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN)) |
378 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK))) | 397 | return -EINVAL; |
398 | |||
399 | if (WARN_ON(!drm_property_type_is(property, DRM_MODE_PROP_ENUM) && | ||
400 | !drm_property_type_is(property, DRM_MODE_PROP_BITMASK))) | ||
379 | return -EINVAL; | 401 | return -EINVAL; |
380 | 402 | ||
381 | /* | 403 | /* |
382 | * Bitmask enum properties have the additional constraint of values | 404 | * Bitmask enum properties have the additional constraint of values |
383 | * from 0 to 63 | 405 | * from 0 to 63 |
384 | */ | 406 | */ |
385 | if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) && | 407 | if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) && |
386 | (value > 63)) | 408 | value > 63)) |
387 | return -EINVAL; | 409 | return -EINVAL; |
388 | 410 | ||
389 | if (!list_empty(&property->enum_list)) { | 411 | list_for_each_entry(prop_enum, &property->enum_list, head) { |
390 | list_for_each_entry(prop_enum, &property->enum_list, head) { | 412 | if (WARN_ON(prop_enum->value == value)) |
391 | if (prop_enum->value == value) { | 413 | return -EINVAL; |
392 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); | ||
393 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; | ||
394 | return 0; | ||
395 | } | ||
396 | } | ||
397 | } | 414 | } |
398 | 415 | ||
399 | prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); | 416 | prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); |
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 6c327fdbaaee..987a353c7f72 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c | |||
@@ -92,6 +92,28 @@ static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { | |||
92 | .atomic_disable = drm_simple_kms_crtc_disable, | 92 | .atomic_disable = drm_simple_kms_crtc_disable, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc) | ||
96 | { | ||
97 | struct drm_simple_display_pipe *pipe; | ||
98 | |||
99 | pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); | ||
100 | if (!pipe->funcs || !pipe->funcs->enable_vblank) | ||
101 | return 0; | ||
102 | |||
103 | return pipe->funcs->enable_vblank(pipe); | ||
104 | } | ||
105 | |||
106 | static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc) | ||
107 | { | ||
108 | struct drm_simple_display_pipe *pipe; | ||
109 | |||
110 | pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); | ||
111 | if (!pipe->funcs || !pipe->funcs->disable_vblank) | ||
112 | return; | ||
113 | |||
114 | pipe->funcs->disable_vblank(pipe); | ||
115 | } | ||
116 | |||
95 | static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { | 117 | static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { |
96 | .reset = drm_atomic_helper_crtc_reset, | 118 | .reset = drm_atomic_helper_crtc_reset, |
97 | .destroy = drm_crtc_cleanup, | 119 | .destroy = drm_crtc_cleanup, |
@@ -99,12 +121,13 @@ static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { | |||
99 | .page_flip = drm_atomic_helper_page_flip, | 121 | .page_flip = drm_atomic_helper_page_flip, |
100 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, | 122 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, |
101 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | 123 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, |
124 | .enable_vblank = drm_simple_kms_crtc_enable_vblank, | ||
125 | .disable_vblank = drm_simple_kms_crtc_disable_vblank, | ||
102 | }; | 126 | }; |
103 | 127 | ||
104 | static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, | 128 | static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, |
105 | struct drm_plane_state *plane_state) | 129 | struct drm_plane_state *plane_state) |
106 | { | 130 | { |
107 | struct drm_rect clip = { 0 }; | ||
108 | struct drm_simple_display_pipe *pipe; | 131 | struct drm_simple_display_pipe *pipe; |
109 | struct drm_crtc_state *crtc_state; | 132 | struct drm_crtc_state *crtc_state; |
110 | int ret; | 133 | int ret; |
@@ -112,15 +135,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, | |||
112 | pipe = container_of(plane, struct drm_simple_display_pipe, plane); | 135 | pipe = container_of(plane, struct drm_simple_display_pipe, plane); |
113 | crtc_state = drm_atomic_get_new_crtc_state(plane_state->state, | 136 | crtc_state = drm_atomic_get_new_crtc_state(plane_state->state, |
114 | &pipe->crtc); | 137 | &pipe->crtc); |
115 | if (!crtc_state->enable) | ||
116 | return 0; /* nothing to check when disabling or disabled */ | ||
117 | |||
118 | if (crtc_state->enable) | ||
119 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
120 | &clip.x2, &clip.y2); | ||
121 | 138 | ||
122 | ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, | 139 | ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, |
123 | &clip, | ||
124 | DRM_PLANE_HELPER_NO_SCALING, | 140 | DRM_PLANE_HELPER_NO_SCALING, |
125 | DRM_PLANE_HELPER_NO_SCALING, | 141 | DRM_PLANE_HELPER_NO_SCALING, |
126 | false, true); | 142 | false, true); |
@@ -128,7 +144,7 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, | |||
128 | return ret; | 144 | return ret; |
129 | 145 | ||
130 | if (!plane_state->visible) | 146 | if (!plane_state->visible) |
131 | return -EINVAL; | 147 | return 0; |
132 | 148 | ||
133 | if (!pipe->funcs || !pipe->funcs->check) | 149 | if (!pipe->funcs || !pipe->funcs->check) |
134 | return 0; | 150 | return 0; |
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index c781cb426bf1..e02ddb01917b 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c | |||
@@ -120,6 +120,9 @@ static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe) | |||
120 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 120 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
121 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); | 121 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
122 | 122 | ||
123 | if (WARN_ON(!crtc)) | ||
124 | return 0; | ||
125 | |||
123 | if (crtc->funcs->get_vblank_counter) | 126 | if (crtc->funcs->get_vblank_counter) |
124 | return crtc->funcs->get_vblank_counter(crtc); | 127 | return crtc->funcs->get_vblank_counter(crtc); |
125 | } | 128 | } |
@@ -318,6 +321,9 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe) | |||
318 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 321 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
319 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); | 322 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
320 | 323 | ||
324 | if (WARN_ON(!crtc)) | ||
325 | return; | ||
326 | |||
321 | if (crtc->funcs->disable_vblank) { | 327 | if (crtc->funcs->disable_vblank) { |
322 | crtc->funcs->disable_vblank(crtc); | 328 | crtc->funcs->disable_vblank(crtc); |
323 | return; | 329 | return; |
@@ -920,6 +926,9 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe) | |||
920 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 926 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
921 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); | 927 | struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); |
922 | 928 | ||
929 | if (WARN_ON(!crtc)) | ||
930 | return 0; | ||
931 | |||
923 | if (crtc->funcs->enable_vblank) | 932 | if (crtc->funcs->enable_vblank) |
924 | return crtc->funcs->enable_vblank(crtc); | 933 | return crtc->funcs->enable_vblank(crtc); |
925 | } | 934 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index 39629e7a80b9..964831dab102 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c | |||
@@ -41,6 +41,7 @@ struct exynos_dp_device { | |||
41 | struct device *dev; | 41 | struct device *dev; |
42 | 42 | ||
43 | struct videomode vm; | 43 | struct videomode vm; |
44 | struct analogix_dp_device *adp; | ||
44 | struct analogix_dp_plat_data plat_data; | 45 | struct analogix_dp_plat_data plat_data; |
45 | }; | 46 | }; |
46 | 47 | ||
@@ -157,13 +158,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) | |||
157 | struct drm_device *drm_dev = data; | 158 | struct drm_device *drm_dev = data; |
158 | int ret; | 159 | int ret; |
159 | 160 | ||
160 | /* | ||
161 | * Just like the probe function said, we don't need the | ||
162 | * device drvrate anymore, we should leave the charge to | ||
163 | * analogix dp driver, set the device drvdata to NULL. | ||
164 | */ | ||
165 | dev_set_drvdata(dev, NULL); | ||
166 | |||
167 | dp->dev = dev; | 161 | dp->dev = dev; |
168 | dp->drm_dev = drm_dev; | 162 | dp->drm_dev = drm_dev; |
169 | 163 | ||
@@ -190,13 +184,22 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) | |||
190 | 184 | ||
191 | dp->plat_data.encoder = encoder; | 185 | dp->plat_data.encoder = encoder; |
192 | 186 | ||
193 | return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); | 187 | dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); |
188 | if (IS_ERR(dp->adp)) { | ||
189 | dp->encoder.funcs->destroy(&dp->encoder); | ||
190 | return PTR_ERR(dp->adp); | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | 194 | } |
195 | 195 | ||
196 | static void exynos_dp_unbind(struct device *dev, struct device *master, | 196 | static void exynos_dp_unbind(struct device *dev, struct device *master, |
197 | void *data) | 197 | void *data) |
198 | { | 198 | { |
199 | return analogix_dp_unbind(dev, master, data); | 199 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
200 | |||
201 | analogix_dp_unbind(dp->adp); | ||
202 | dp->encoder.funcs->destroy(&dp->encoder); | ||
200 | } | 203 | } |
201 | 204 | ||
202 | static const struct component_ops exynos_dp_ops = { | 205 | static const struct component_ops exynos_dp_ops = { |
@@ -241,6 +244,7 @@ static int exynos_dp_probe(struct platform_device *pdev) | |||
241 | 244 | ||
242 | /* The remote port can be either a panel or a bridge */ | 245 | /* The remote port can be either a panel or a bridge */ |
243 | dp->plat_data.panel = panel; | 246 | dp->plat_data.panel = panel; |
247 | dp->plat_data.skip_connector = !!bridge; | ||
244 | dp->ptn_bridge = bridge; | 248 | dp->ptn_bridge = bridge; |
245 | 249 | ||
246 | out: | 250 | out: |
@@ -257,12 +261,16 @@ static int exynos_dp_remove(struct platform_device *pdev) | |||
257 | #ifdef CONFIG_PM | 261 | #ifdef CONFIG_PM |
258 | static int exynos_dp_suspend(struct device *dev) | 262 | static int exynos_dp_suspend(struct device *dev) |
259 | { | 263 | { |
260 | return analogix_dp_suspend(dev); | 264 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
265 | |||
266 | return analogix_dp_suspend(dp->adp); | ||
261 | } | 267 | } |
262 | 268 | ||
263 | static int exynos_dp_resume(struct device *dev) | 269 | static int exynos_dp_resume(struct device *dev) |
264 | { | 270 | { |
265 | return analogix_dp_resume(dev); | 271 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
272 | |||
273 | return analogix_dp_resume(dp->adp); | ||
266 | } | 274 | } |
267 | #endif | 275 | #endif |
268 | 276 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1412abcb27d4..47ca8b97ce50 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -6132,6 +6132,7 @@ enum { | |||
6132 | #define _DVSACNTR 0x72180 | 6132 | #define _DVSACNTR 0x72180 |
6133 | #define DVS_ENABLE (1<<31) | 6133 | #define DVS_ENABLE (1<<31) |
6134 | #define DVS_GAMMA_ENABLE (1<<30) | 6134 | #define DVS_GAMMA_ENABLE (1<<30) |
6135 | #define DVS_YUV_RANGE_CORRECTION_DISABLE (1<<27) | ||
6135 | #define DVS_PIXFORMAT_MASK (3<<25) | 6136 | #define DVS_PIXFORMAT_MASK (3<<25) |
6136 | #define DVS_FORMAT_YUV422 (0<<25) | 6137 | #define DVS_FORMAT_YUV422 (0<<25) |
6137 | #define DVS_FORMAT_RGBX101010 (1<<25) | 6138 | #define DVS_FORMAT_RGBX101010 (1<<25) |
@@ -6140,6 +6141,7 @@ enum { | |||
6140 | #define DVS_PIPE_CSC_ENABLE (1<<24) | 6141 | #define DVS_PIPE_CSC_ENABLE (1<<24) |
6141 | #define DVS_SOURCE_KEY (1<<22) | 6142 | #define DVS_SOURCE_KEY (1<<22) |
6142 | #define DVS_RGB_ORDER_XBGR (1<<20) | 6143 | #define DVS_RGB_ORDER_XBGR (1<<20) |
6144 | #define DVS_YUV_FORMAT_BT709 (1<<18) | ||
6143 | #define DVS_YUV_BYTE_ORDER_MASK (3<<16) | 6145 | #define DVS_YUV_BYTE_ORDER_MASK (3<<16) |
6144 | #define DVS_YUV_ORDER_YUYV (0<<16) | 6146 | #define DVS_YUV_ORDER_YUYV (0<<16) |
6145 | #define DVS_YUV_ORDER_UYVY (1<<16) | 6147 | #define DVS_YUV_ORDER_UYVY (1<<16) |
@@ -6199,6 +6201,7 @@ enum { | |||
6199 | #define _SPRA_CTL 0x70280 | 6201 | #define _SPRA_CTL 0x70280 |
6200 | #define SPRITE_ENABLE (1<<31) | 6202 | #define SPRITE_ENABLE (1<<31) |
6201 | #define SPRITE_GAMMA_ENABLE (1<<30) | 6203 | #define SPRITE_GAMMA_ENABLE (1<<30) |
6204 | #define SPRITE_YUV_RANGE_CORRECTION_DISABLE (1<<28) | ||
6202 | #define SPRITE_PIXFORMAT_MASK (7<<25) | 6205 | #define SPRITE_PIXFORMAT_MASK (7<<25) |
6203 | #define SPRITE_FORMAT_YUV422 (0<<25) | 6206 | #define SPRITE_FORMAT_YUV422 (0<<25) |
6204 | #define SPRITE_FORMAT_RGBX101010 (1<<25) | 6207 | #define SPRITE_FORMAT_RGBX101010 (1<<25) |
@@ -6210,7 +6213,7 @@ enum { | |||
6210 | #define SPRITE_SOURCE_KEY (1<<22) | 6213 | #define SPRITE_SOURCE_KEY (1<<22) |
6211 | #define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */ | 6214 | #define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */ |
6212 | #define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19) | 6215 | #define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19) |
6213 | #define SPRITE_YUV_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */ | 6216 | #define SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */ |
6214 | #define SPRITE_YUV_BYTE_ORDER_MASK (3<<16) | 6217 | #define SPRITE_YUV_BYTE_ORDER_MASK (3<<16) |
6215 | #define SPRITE_YUV_ORDER_YUYV (0<<16) | 6218 | #define SPRITE_YUV_ORDER_YUYV (0<<16) |
6216 | #define SPRITE_YUV_ORDER_UYVY (1<<16) | 6219 | #define SPRITE_YUV_ORDER_UYVY (1<<16) |
@@ -6286,6 +6289,7 @@ enum { | |||
6286 | #define SP_FORMAT_RGBA8888 (0xf<<26) | 6289 | #define SP_FORMAT_RGBA8888 (0xf<<26) |
6287 | #define SP_ALPHA_PREMULTIPLY (1<<23) /* CHV pipe B */ | 6290 | #define SP_ALPHA_PREMULTIPLY (1<<23) /* CHV pipe B */ |
6288 | #define SP_SOURCE_KEY (1<<22) | 6291 | #define SP_SOURCE_KEY (1<<22) |
6292 | #define SP_YUV_FORMAT_BT709 (1<<18) | ||
6289 | #define SP_YUV_BYTE_ORDER_MASK (3<<16) | 6293 | #define SP_YUV_BYTE_ORDER_MASK (3<<16) |
6290 | #define SP_YUV_ORDER_YUYV (0<<16) | 6294 | #define SP_YUV_ORDER_YUYV (0<<16) |
6291 | #define SP_YUV_ORDER_UYVY (1<<16) | 6295 | #define SP_YUV_ORDER_UYVY (1<<16) |
@@ -6305,6 +6309,12 @@ enum { | |||
6305 | #define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4) | 6309 | #define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4) |
6306 | #define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8) | 6310 | #define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8) |
6307 | #define SP_CONST_ALPHA_ENABLE (1<<31) | 6311 | #define SP_CONST_ALPHA_ENABLE (1<<31) |
6312 | #define _SPACLRC0 (VLV_DISPLAY_BASE + 0x721d0) | ||
6313 | #define SP_CONTRAST(x) ((x) << 18) /* u3.6 */ | ||
6314 | #define SP_BRIGHTNESS(x) ((x) & 0xff) /* s8 */ | ||
6315 | #define _SPACLRC1 (VLV_DISPLAY_BASE + 0x721d4) | ||
6316 | #define SP_SH_SIN(x) (((x) & 0x7ff) << 16) /* s4.7 */ | ||
6317 | #define SP_SH_COS(x) (x) /* u3.7 */ | ||
6308 | #define _SPAGAMC (VLV_DISPLAY_BASE + 0x721f4) | 6318 | #define _SPAGAMC (VLV_DISPLAY_BASE + 0x721f4) |
6309 | 6319 | ||
6310 | #define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280) | 6320 | #define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280) |
@@ -6318,6 +6328,8 @@ enum { | |||
6318 | #define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0) | 6328 | #define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0) |
6319 | #define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4) | 6329 | #define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4) |
6320 | #define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8) | 6330 | #define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8) |
6331 | #define _SPBCLRC0 (VLV_DISPLAY_BASE + 0x722d0) | ||
6332 | #define _SPBCLRC1 (VLV_DISPLAY_BASE + 0x722d4) | ||
6321 | #define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4) | 6333 | #define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4) |
6322 | 6334 | ||
6323 | #define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \ | 6335 | #define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \ |
@@ -6334,6 +6346,8 @@ enum { | |||
6334 | #define SPKEYMAXVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL) | 6346 | #define SPKEYMAXVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL) |
6335 | #define SPTILEOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPATILEOFF, _SPBTILEOFF) | 6347 | #define SPTILEOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPATILEOFF, _SPBTILEOFF) |
6336 | #define SPCONSTALPHA(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA) | 6348 | #define SPCONSTALPHA(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA) |
6349 | #define SPCLRC0(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC0, _SPBCLRC0) | ||
6350 | #define SPCLRC1(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC1, _SPBCLRC1) | ||
6337 | #define SPGAMC(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC) | 6351 | #define SPGAMC(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC) |
6338 | 6352 | ||
6339 | /* | 6353 | /* |
@@ -6379,6 +6393,7 @@ enum { | |||
6379 | #define _PLANE_CTL_3_A 0x70380 | 6393 | #define _PLANE_CTL_3_A 0x70380 |
6380 | #define PLANE_CTL_ENABLE (1 << 31) | 6394 | #define PLANE_CTL_ENABLE (1 << 31) |
6381 | #define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-GLK */ | 6395 | #define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-GLK */ |
6396 | #define PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE (1 << 28) | ||
6382 | /* | 6397 | /* |
6383 | * ICL+ uses the same PLANE_CTL_FORMAT bits, but the field definition | 6398 | * ICL+ uses the same PLANE_CTL_FORMAT bits, but the field definition |
6384 | * expanded to include bit 23 as well. However, the shift-24 based values | 6399 | * expanded to include bit 23 as well. However, the shift-24 based values |
@@ -6400,6 +6415,7 @@ enum { | |||
6400 | #define PLANE_CTL_KEY_ENABLE_DESTINATION ( 2 << 21) | 6415 | #define PLANE_CTL_KEY_ENABLE_DESTINATION ( 2 << 21) |
6401 | #define PLANE_CTL_ORDER_BGRX (0 << 20) | 6416 | #define PLANE_CTL_ORDER_BGRX (0 << 20) |
6402 | #define PLANE_CTL_ORDER_RGBX (1 << 20) | 6417 | #define PLANE_CTL_ORDER_RGBX (1 << 20) |
6418 | #define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 (1 << 18) | ||
6403 | #define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16) | 6419 | #define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16) |
6404 | #define PLANE_CTL_YUV422_YUYV ( 0 << 16) | 6420 | #define PLANE_CTL_YUV422_YUYV ( 0 << 16) |
6405 | #define PLANE_CTL_YUV422_UYVY ( 1 << 16) | 6421 | #define PLANE_CTL_YUV422_UYVY ( 1 << 16) |
@@ -6452,7 +6468,13 @@ enum { | |||
6452 | #define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */ | 6468 | #define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */ |
6453 | #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ | 6469 | #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ |
6454 | #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) | 6470 | #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) |
6471 | #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) | ||
6455 | #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) | 6472 | #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) |
6473 | #define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17) | ||
6474 | #define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709 (1 << 17) | ||
6475 | #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17) | ||
6476 | #define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 (3 << 17) | ||
6477 | #define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 (4 << 17) | ||
6456 | #define PLANE_COLOR_PLANE_GAMMA_DISABLE (1 << 13) | 6478 | #define PLANE_COLOR_PLANE_GAMMA_DISABLE (1 << 13) |
6457 | #define PLANE_COLOR_ALPHA_MASK (0x3 << 4) | 6479 | #define PLANE_COLOR_ALPHA_MASK (0x3 << 4) |
6458 | #define PLANE_COLOR_ALPHA_DISABLE (0 << 4) | 6480 | #define PLANE_COLOR_ALPHA_DISABLE (0 << 4) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5d46771d58f6..8be9c3371b7e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3083,9 +3083,6 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) | |||
3083 | 3083 | ||
3084 | static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) | 3084 | static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) |
3085 | { | 3085 | { |
3086 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
3087 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | ||
3088 | struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc); | ||
3089 | const struct drm_framebuffer *fb = plane_state->base.fb; | 3086 | const struct drm_framebuffer *fb = plane_state->base.fb; |
3090 | int src_x = plane_state->base.src.x1 >> 16; | 3087 | int src_x = plane_state->base.src.x1 >> 16; |
3091 | int src_y = plane_state->base.src.y1 >> 16; | 3088 | int src_y = plane_state->base.src.y1 >> 16; |
@@ -3095,11 +3092,6 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) | |||
3095 | int y = src_y / vsub; | 3092 | int y = src_y / vsub; |
3096 | u32 offset; | 3093 | u32 offset; |
3097 | 3094 | ||
3098 | if (!skl_plane_has_ccs(dev_priv, crtc->pipe, plane->id)) { | ||
3099 | DRM_DEBUG_KMS("No RC support on %s\n", plane->base.name); | ||
3100 | return -EINVAL; | ||
3101 | } | ||
3102 | |||
3103 | if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) { | 3095 | if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) { |
3104 | DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n", | 3096 | DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n", |
3105 | plane_state->base.rotation); | 3097 | plane_state->base.rotation); |
@@ -3564,6 +3556,12 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, | |||
3564 | PLANE_CTL_PIPE_GAMMA_ENABLE | | 3556 | PLANE_CTL_PIPE_GAMMA_ENABLE | |
3565 | PLANE_CTL_PIPE_CSC_ENABLE | | 3557 | PLANE_CTL_PIPE_CSC_ENABLE | |
3566 | PLANE_CTL_PLANE_GAMMA_DISABLE; | 3558 | PLANE_CTL_PLANE_GAMMA_DISABLE; |
3559 | |||
3560 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | ||
3561 | plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; | ||
3562 | |||
3563 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | ||
3564 | plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE; | ||
3567 | } | 3565 | } |
3568 | 3566 | ||
3569 | plane_ctl |= skl_plane_ctl_format(fb->format->format); | 3567 | plane_ctl |= skl_plane_ctl_format(fb->format->format); |
@@ -3593,6 +3591,16 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |||
3593 | plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; | 3591 | plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; |
3594 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); | 3592 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); |
3595 | 3593 | ||
3594 | if (intel_format_is_yuv(fb->format->format)) { | ||
3595 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | ||
3596 | plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; | ||
3597 | else | ||
3598 | plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709; | ||
3599 | |||
3600 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | ||
3601 | plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; | ||
3602 | } | ||
3603 | |||
3596 | return plane_color_ctl; | 3604 | return plane_color_ctl; |
3597 | } | 3605 | } |
3598 | 3606 | ||
@@ -9389,18 +9397,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, | |||
9389 | struct intel_plane_state *plane_state) | 9397 | struct intel_plane_state *plane_state) |
9390 | { | 9398 | { |
9391 | const struct drm_framebuffer *fb = plane_state->base.fb; | 9399 | const struct drm_framebuffer *fb = plane_state->base.fb; |
9392 | struct drm_rect clip = {}; | ||
9393 | int src_x, src_y; | 9400 | int src_x, src_y; |
9394 | u32 offset; | 9401 | u32 offset; |
9395 | int ret; | 9402 | int ret; |
9396 | 9403 | ||
9397 | if (crtc_state->base.enable) | ||
9398 | drm_mode_get_hv_timing(&crtc_state->base.mode, | ||
9399 | &clip.x2, &clip.y2); | ||
9400 | |||
9401 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, | 9404 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, |
9402 | &crtc_state->base, | 9405 | &crtc_state->base, |
9403 | &clip, | ||
9404 | DRM_PLANE_HELPER_NO_SCALING, | 9406 | DRM_PLANE_HELPER_NO_SCALING, |
9405 | DRM_PLANE_HELPER_NO_SCALING, | 9407 | DRM_PLANE_HELPER_NO_SCALING, |
9406 | true, true); | 9408 | true, true); |
@@ -12839,7 +12841,6 @@ intel_check_primary_plane(struct intel_plane *plane, | |||
12839 | int min_scale = DRM_PLANE_HELPER_NO_SCALING; | 12841 | int min_scale = DRM_PLANE_HELPER_NO_SCALING; |
12840 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; | 12842 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; |
12841 | bool can_position = false; | 12843 | bool can_position = false; |
12842 | struct drm_rect clip = {}; | ||
12843 | int ret; | 12844 | int ret; |
12844 | 12845 | ||
12845 | if (INTEL_GEN(dev_priv) >= 9) { | 12846 | if (INTEL_GEN(dev_priv) >= 9) { |
@@ -12851,13 +12852,8 @@ intel_check_primary_plane(struct intel_plane *plane, | |||
12851 | can_position = true; | 12852 | can_position = true; |
12852 | } | 12853 | } |
12853 | 12854 | ||
12854 | if (crtc_state->base.enable) | ||
12855 | drm_mode_get_hv_timing(&crtc_state->base.mode, | ||
12856 | &clip.x2, &clip.y2); | ||
12857 | |||
12858 | ret = drm_atomic_helper_check_plane_state(&state->base, | 12855 | ret = drm_atomic_helper_check_plane_state(&state->base, |
12859 | &crtc_state->base, | 12856 | &crtc_state->base, |
12860 | &clip, | ||
12861 | min_scale, max_scale, | 12857 | min_scale, max_scale, |
12862 | can_position, true); | 12858 | can_position, true); |
12863 | if (ret) | 12859 | if (ret) |
@@ -13338,6 +13334,15 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
13338 | DRM_MODE_ROTATE_0, | 13334 | DRM_MODE_ROTATE_0, |
13339 | supported_rotations); | 13335 | supported_rotations); |
13340 | 13336 | ||
13337 | if (INTEL_GEN(dev_priv) >= 9) | ||
13338 | drm_plane_create_color_properties(&primary->base, | ||
13339 | BIT(DRM_COLOR_YCBCR_BT601) | | ||
13340 | BIT(DRM_COLOR_YCBCR_BT709), | ||
13341 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | | ||
13342 | BIT(DRM_COLOR_YCBCR_FULL_RANGE), | ||
13343 | DRM_COLOR_YCBCR_BT709, | ||
13344 | DRM_COLOR_YCBCR_LIMITED_RANGE); | ||
13345 | |||
13341 | drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); | 13346 | drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); |
13342 | 13347 | ||
13343 | return primary; | 13348 | return primary; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 50874f4035cf..24e9caebe463 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -1596,6 +1596,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | |||
1596 | const struct intel_plane_state *plane_state); | 1596 | const struct intel_plane_state *plane_state); |
1597 | u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, | 1597 | u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, |
1598 | const struct intel_plane_state *plane_state); | 1598 | const struct intel_plane_state *plane_state); |
1599 | u32 glk_color_ctl(const struct intel_plane_state *plane_state); | ||
1599 | u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, | 1600 | u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, |
1600 | unsigned int rotation); | 1601 | unsigned int rotation); |
1601 | int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, | 1602 | int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, |
@@ -2021,6 +2022,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, | |||
2021 | 2022 | ||
2022 | 2023 | ||
2023 | /* intel_sprite.c */ | 2024 | /* intel_sprite.c */ |
2025 | bool intel_format_is_yuv(u32 format); | ||
2024 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, | 2026 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, |
2025 | int usecs); | 2027 | int usecs); |
2026 | struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, | 2028 | struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index e098e4b2c85c..dbdcf85032df 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -41,8 +41,7 @@ | |||
41 | #include <drm/i915_drm.h> | 41 | #include <drm/i915_drm.h> |
42 | #include "i915_drv.h" | 42 | #include "i915_drv.h" |
43 | 43 | ||
44 | static bool | 44 | bool intel_format_is_yuv(u32 format) |
45 | format_is_yuv(uint32_t format) | ||
46 | { | 45 | { |
47 | switch (format) { | 46 | switch (format) { |
48 | case DRM_FORMAT_YUYV: | 47 | case DRM_FORMAT_YUYV: |
@@ -266,6 +265,7 @@ skl_update_plane(struct intel_plane *plane, | |||
266 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | 265 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) |
267 | I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), | 266 | I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), |
268 | plane_state->color_ctl); | 267 | plane_state->color_ctl); |
268 | |||
269 | if (key->flags) { | 269 | if (key->flags) { |
270 | I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); | 270 | I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); |
271 | I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value); | 271 | I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value); |
@@ -346,44 +346,103 @@ skl_plane_get_hw_state(struct intel_plane *plane) | |||
346 | } | 346 | } |
347 | 347 | ||
348 | static void | 348 | static void |
349 | chv_update_csc(struct intel_plane *plane, uint32_t format) | 349 | chv_update_csc(const struct intel_plane_state *plane_state) |
350 | { | 350 | { |
351 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
351 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 352 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
353 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
352 | enum plane_id plane_id = plane->id; | 354 | enum plane_id plane_id = plane->id; |
353 | |||
354 | /* Seems RGB data bypasses the CSC always */ | ||
355 | if (!format_is_yuv(format)) | ||
356 | return; | ||
357 | |||
358 | /* | 355 | /* |
359 | * BT.601 limited range YCbCr -> full range RGB | 356 | * |r| | c0 c1 c2 | |cr| |
357 | * |g| = | c3 c4 c5 | x |y | | ||
358 | * |b| | c6 c7 c8 | |cb| | ||
360 | * | 359 | * |
361 | * |r| | 6537 4769 0| |cr | | 360 | * Coefficients are s3.12. |
362 | * |g| = |-3330 4769 -1605| x |y-64| | ||
363 | * |b| | 0 4769 8263| |cb | | ||
364 | * | 361 | * |
365 | * Cb and Cr apparently come in as signed already, so no | 362 | * Cb and Cr apparently come in as signed already, and |
366 | * need for any offset. For Y we need to remove the offset. | 363 | * we always get full range data in on account of CLRC0/1. |
367 | */ | 364 | */ |
368 | I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); | 365 | static const s16 csc_matrix[][9] = { |
366 | /* BT.601 full range YCbCr -> full range RGB */ | ||
367 | [DRM_COLOR_YCBCR_BT601] = { | ||
368 | 5743, 4096, 0, | ||
369 | -2925, 4096, -1410, | ||
370 | 0, 4096, 7258, | ||
371 | }, | ||
372 | /* BT.709 full range YCbCr -> full range RGB */ | ||
373 | [DRM_COLOR_YCBCR_BT709] = { | ||
374 | 6450, 4096, 0, | ||
375 | -1917, 4096, -767, | ||
376 | 0, 4096, 7601, | ||
377 | }, | ||
378 | }; | ||
379 | const s16 *csc = csc_matrix[plane_state->base.color_encoding]; | ||
380 | |||
381 | /* Seems RGB data bypasses the CSC always */ | ||
382 | if (!intel_format_is_yuv(fb->format->format)) | ||
383 | return; | ||
384 | |||
385 | I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | ||
369 | I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | 386 | I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); |
370 | I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | 387 | I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0)); |
371 | 388 | ||
372 | I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537)); | 389 | I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0])); |
373 | I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0)); | 390 | I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2])); |
374 | I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769)); | 391 | I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4])); |
375 | I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0)); | 392 | I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6])); |
376 | I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(8263)); | 393 | I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8])); |
377 | 394 | ||
378 | I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64)); | 395 | I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0)); |
379 | I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | 396 | I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512)); |
380 | I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | 397 | I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512)); |
381 | 398 | ||
382 | I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | 399 | I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
383 | I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | 400 | I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
384 | I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | 401 | I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
385 | } | 402 | } |
386 | 403 | ||
404 | #define SIN_0 0 | ||
405 | #define COS_0 1 | ||
406 | |||
407 | static void | ||
408 | vlv_update_clrc(const struct intel_plane_state *plane_state) | ||
409 | { | ||
410 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
411 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | ||
412 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
413 | enum pipe pipe = plane->pipe; | ||
414 | enum plane_id plane_id = plane->id; | ||
415 | int contrast, brightness, sh_scale, sh_sin, sh_cos; | ||
416 | |||
417 | if (intel_format_is_yuv(fb->format->format) && | ||
418 | plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) { | ||
419 | /* | ||
420 | * Expand limited range to full range: | ||
421 | * Contrast is applied first and is used to expand Y range. | ||
422 | * Brightness is applied second and is used to remove the | ||
423 | * offset from Y. Saturation/hue is used to expand CbCr range. | ||
424 | */ | ||
425 | contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16); | ||
426 | brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16); | ||
427 | sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128); | ||
428 | sh_sin = SIN_0 * sh_scale; | ||
429 | sh_cos = COS_0 * sh_scale; | ||
430 | } else { | ||
431 | /* Pass-through everything. */ | ||
432 | contrast = 1 << 6; | ||
433 | brightness = 0; | ||
434 | sh_scale = 1 << 7; | ||
435 | sh_sin = SIN_0 * sh_scale; | ||
436 | sh_cos = COS_0 * sh_scale; | ||
437 | } | ||
438 | |||
439 | /* FIXME these register are single buffered :( */ | ||
440 | I915_WRITE_FW(SPCLRC0(pipe, plane_id), | ||
441 | SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness)); | ||
442 | I915_WRITE_FW(SPCLRC1(pipe, plane_id), | ||
443 | SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos)); | ||
444 | } | ||
445 | |||
387 | static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, | 446 | static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, |
388 | const struct intel_plane_state *plane_state) | 447 | const struct intel_plane_state *plane_state) |
389 | { | 448 | { |
@@ -433,6 +492,9 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, | |||
433 | return 0; | 492 | return 0; |
434 | } | 493 | } |
435 | 494 | ||
495 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | ||
496 | sprctl |= SP_YUV_FORMAT_BT709; | ||
497 | |||
436 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 498 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
437 | sprctl |= SP_TILED; | 499 | sprctl |= SP_TILED; |
438 | 500 | ||
@@ -477,8 +539,10 @@ vlv_update_plane(struct intel_plane *plane, | |||
477 | 539 | ||
478 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 540 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
479 | 541 | ||
542 | vlv_update_clrc(plane_state); | ||
543 | |||
480 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) | 544 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) |
481 | chv_update_csc(plane, fb->format->format); | 545 | chv_update_csc(plane_state); |
482 | 546 | ||
483 | if (key->flags) { | 547 | if (key->flags) { |
484 | I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value); | 548 | I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value); |
@@ -584,6 +648,12 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, | |||
584 | return 0; | 648 | return 0; |
585 | } | 649 | } |
586 | 650 | ||
651 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | ||
652 | sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709; | ||
653 | |||
654 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | ||
655 | sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE; | ||
656 | |||
587 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 657 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
588 | sprctl |= SPRITE_TILED; | 658 | sprctl |= SPRITE_TILED; |
589 | 659 | ||
@@ -740,6 +810,12 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, | |||
740 | return 0; | 810 | return 0; |
741 | } | 811 | } |
742 | 812 | ||
813 | if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) | ||
814 | dvscntr |= DVS_YUV_FORMAT_BT709; | ||
815 | |||
816 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | ||
817 | dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE; | ||
818 | |||
743 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 819 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
744 | dvscntr |= DVS_TILED; | 820 | dvscntr |= DVS_TILED; |
745 | 821 | ||
@@ -979,7 +1055,7 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
979 | src_y = src->y1 >> 16; | 1055 | src_y = src->y1 >> 16; |
980 | src_h = drm_rect_height(src) >> 16; | 1056 | src_h = drm_rect_height(src) >> 16; |
981 | 1057 | ||
982 | if (format_is_yuv(fb->format->format)) { | 1058 | if (intel_format_is_yuv(fb->format->format)) { |
983 | src_x &= ~1; | 1059 | src_x &= ~1; |
984 | src_w &= ~1; | 1060 | src_w &= ~1; |
985 | 1061 | ||
@@ -1459,6 +1535,14 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1459 | DRM_MODE_ROTATE_0, | 1535 | DRM_MODE_ROTATE_0, |
1460 | supported_rotations); | 1536 | supported_rotations); |
1461 | 1537 | ||
1538 | drm_plane_create_color_properties(&intel_plane->base, | ||
1539 | BIT(DRM_COLOR_YCBCR_BT601) | | ||
1540 | BIT(DRM_COLOR_YCBCR_BT709), | ||
1541 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | | ||
1542 | BIT(DRM_COLOR_YCBCR_FULL_RANGE), | ||
1543 | DRM_COLOR_YCBCR_BT709, | ||
1544 | DRM_COLOR_YCBCR_LIMITED_RANGE); | ||
1545 | |||
1462 | drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); | 1546 | drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); |
1463 | 1547 | ||
1464 | return intel_plane; | 1548 | return intel_plane; |
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 150628293c51..d7e3583e608e 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c | |||
@@ -351,7 +351,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
351 | struct drm_framebuffer *old_fb = old_state->fb; | 351 | struct drm_framebuffer *old_fb = old_state->fb; |
352 | unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; | 352 | unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; |
353 | bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); | 353 | bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); |
354 | struct drm_rect clip = {}; | ||
355 | int hsub, vsub; | 354 | int hsub, vsub; |
356 | int ret; | 355 | int ret; |
357 | 356 | ||
@@ -367,11 +366,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
367 | if (WARN_ON(!crtc_state)) | 366 | if (WARN_ON(!crtc_state)) |
368 | return -EINVAL; | 367 | return -EINVAL; |
369 | 368 | ||
370 | if (crtc_state->enable) | 369 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
371 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
372 | &clip.x2, &clip.y2); | ||
373 | |||
374 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
375 | DRM_PLANE_HELPER_NO_SCALING, | 370 | DRM_PLANE_HELPER_NO_SCALING, |
376 | DRM_PLANE_HELPER_NO_SCALING, | 371 | DRM_PLANE_HELPER_NO_SCALING, |
377 | can_position, true); | 372 | can_position, true); |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index b5c6eec9a584..2f4b0ffee598 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c | |||
@@ -91,7 +91,6 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, | |||
91 | { | 91 | { |
92 | struct drm_framebuffer *fb = state->fb; | 92 | struct drm_framebuffer *fb = state->fb; |
93 | struct drm_crtc_state *crtc_state; | 93 | struct drm_crtc_state *crtc_state; |
94 | struct drm_rect clip = { 0, }; | ||
95 | 94 | ||
96 | if (!fb) | 95 | if (!fb) |
97 | return 0; | 96 | return 0; |
@@ -108,11 +107,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, | |||
108 | if (IS_ERR(crtc_state)) | 107 | if (IS_ERR(crtc_state)) |
109 | return PTR_ERR(crtc_state); | 108 | return PTR_ERR(crtc_state); |
110 | 109 | ||
111 | if (crtc_state->enable) | 110 | return drm_atomic_helper_check_plane_state(state, crtc_state, |
112 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
113 | &clip.x2, &clip.y2); | ||
114 | |||
115 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
116 | DRM_PLANE_HELPER_NO_SCALING, | 111 | DRM_PLANE_HELPER_NO_SCALING, |
117 | DRM_PLANE_HELPER_NO_SCALING, | 112 | DRM_PLANE_HELPER_NO_SCALING, |
118 | true, true); | 113 | true, true); |
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 3801bee1f9e6..c78a3a59f58c 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c | |||
@@ -49,7 +49,6 @@ static int meson_plane_atomic_check(struct drm_plane *plane, | |||
49 | struct drm_plane_state *state) | 49 | struct drm_plane_state *state) |
50 | { | 50 | { |
51 | struct drm_crtc_state *crtc_state; | 51 | struct drm_crtc_state *crtc_state; |
52 | struct drm_rect clip = { 0, }; | ||
53 | 52 | ||
54 | if (!state->crtc) | 53 | if (!state->crtc) |
55 | return 0; | 54 | return 0; |
@@ -58,11 +57,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane, | |||
58 | if (IS_ERR(crtc_state)) | 57 | if (IS_ERR(crtc_state)) |
59 | return PTR_ERR(crtc_state); | 58 | return PTR_ERR(crtc_state); |
60 | 59 | ||
61 | if (crtc_state->enable) | 60 | return drm_atomic_helper_check_plane_state(state, crtc_state, |
62 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
63 | &clip.x2, &clip.y2); | ||
64 | |||
65 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
66 | DRM_PLANE_HELPER_NO_SCALING, | 61 | DRM_PLANE_HELPER_NO_SCALING, |
67 | DRM_PLANE_HELPER_NO_SCALING, | 62 | DRM_PLANE_HELPER_NO_SCALING, |
68 | true, true); | 63 | true, true); |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 98d4d7331767..44fc9fe4737a 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -286,7 +286,6 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, | |||
286 | uint32_t max_width, max_height; | 286 | uint32_t max_width, max_height; |
287 | bool out_of_bounds = false; | 287 | bool out_of_bounds = false; |
288 | uint32_t caps = 0; | 288 | uint32_t caps = 0; |
289 | struct drm_rect clip = {}; | ||
290 | int min_scale, max_scale; | 289 | int min_scale, max_scale; |
291 | int ret; | 290 | int ret; |
292 | 291 | ||
@@ -323,11 +322,7 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, | |||
323 | min_scale = FRAC_16_16(1, 8); | 322 | min_scale = FRAC_16_16(1, 8); |
324 | max_scale = FRAC_16_16(8, 1); | 323 | max_scale = FRAC_16_16(8, 1); |
325 | 324 | ||
326 | if (crtc_state->enable) | 325 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
327 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
328 | &clip.x2, &clip.y2); | ||
329 | |||
330 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
331 | min_scale, max_scale, | 326 | min_scale, max_scale, |
332 | true, true); | 327 | true, true); |
333 | if (ret) | 328 | if (ret) |
@@ -471,7 +466,6 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane, | |||
471 | { | 466 | { |
472 | struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state); | 467 | struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state); |
473 | struct drm_crtc_state *crtc_state; | 468 | struct drm_crtc_state *crtc_state; |
474 | struct drm_rect clip = {}; | ||
475 | int min_scale, max_scale; | 469 | int min_scale, max_scale; |
476 | int ret; | 470 | int ret; |
477 | 471 | ||
@@ -502,11 +496,7 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane, | |||
502 | min_scale = FRAC_16_16(1, 8); | 496 | min_scale = FRAC_16_16(1, 8); |
503 | max_scale = FRAC_16_16(8, 1); | 497 | max_scale = FRAC_16_16(8, 1); |
504 | 498 | ||
505 | if (crtc_state->enable) | 499 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
506 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
507 | &clip.x2, &clip.y2); | ||
508 | |||
509 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
510 | min_scale, max_scale, | 500 | min_scale, max_scale, |
511 | true, true); | 501 | true, true); |
512 | if (ret) | 502 | if (ret) |
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 1207ffe36250..5cae8db9dcd4 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c | |||
@@ -131,11 +131,37 @@ static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, | |||
131 | return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); | 131 | return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); |
132 | } | 132 | } |
133 | 133 | ||
134 | static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) | ||
135 | { | ||
136 | struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); | ||
137 | |||
138 | /* Clear and enable VBLANK IRQ */ | ||
139 | mxsfb_enable_axi_clk(mxsfb); | ||
140 | writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
141 | writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); | ||
142 | mxsfb_disable_axi_clk(mxsfb); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) | ||
148 | { | ||
149 | struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); | ||
150 | |||
151 | /* Disable and clear VBLANK IRQ */ | ||
152 | mxsfb_enable_axi_clk(mxsfb); | ||
153 | writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
154 | writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
155 | mxsfb_disable_axi_clk(mxsfb); | ||
156 | } | ||
157 | |||
134 | static struct drm_simple_display_pipe_funcs mxsfb_funcs = { | 158 | static struct drm_simple_display_pipe_funcs mxsfb_funcs = { |
135 | .enable = mxsfb_pipe_enable, | 159 | .enable = mxsfb_pipe_enable, |
136 | .disable = mxsfb_pipe_disable, | 160 | .disable = mxsfb_pipe_disable, |
137 | .update = mxsfb_pipe_update, | 161 | .update = mxsfb_pipe_update, |
138 | .prepare_fb = mxsfb_pipe_prepare_fb, | 162 | .prepare_fb = mxsfb_pipe_prepare_fb, |
163 | .enable_vblank = mxsfb_pipe_enable_vblank, | ||
164 | .disable_vblank = mxsfb_pipe_disable_vblank, | ||
139 | }; | 165 | }; |
140 | 166 | ||
141 | static int mxsfb_load(struct drm_device *drm, unsigned long flags) | 167 | static int mxsfb_load(struct drm_device *drm, unsigned long flags) |
@@ -274,33 +300,11 @@ static void mxsfb_lastclose(struct drm_device *drm) | |||
274 | drm_fbdev_cma_restore_mode(mxsfb->fbdev); | 300 | drm_fbdev_cma_restore_mode(mxsfb->fbdev); |
275 | } | 301 | } |
276 | 302 | ||
277 | static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc) | 303 | static void mxsfb_irq_preinstall(struct drm_device *drm) |
278 | { | ||
279 | struct mxsfb_drm_private *mxsfb = drm->dev_private; | ||
280 | |||
281 | /* Clear and enable VBLANK IRQ */ | ||
282 | mxsfb_enable_axi_clk(mxsfb); | ||
283 | writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
284 | writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); | ||
285 | mxsfb_disable_axi_clk(mxsfb); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc) | ||
291 | { | 304 | { |
292 | struct mxsfb_drm_private *mxsfb = drm->dev_private; | 305 | struct mxsfb_drm_private *mxsfb = drm->dev_private; |
293 | 306 | ||
294 | /* Disable and clear VBLANK IRQ */ | 307 | mxsfb_pipe_disable_vblank(&mxsfb->pipe); |
295 | mxsfb_enable_axi_clk(mxsfb); | ||
296 | writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
297 | writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); | ||
298 | mxsfb_disable_axi_clk(mxsfb); | ||
299 | } | ||
300 | |||
301 | static void mxsfb_irq_preinstall(struct drm_device *drm) | ||
302 | { | ||
303 | mxsfb_disable_vblank(drm, 0); | ||
304 | } | 308 | } |
305 | 309 | ||
306 | static irqreturn_t mxsfb_irq_handler(int irq, void *data) | 310 | static irqreturn_t mxsfb_irq_handler(int irq, void *data) |
@@ -333,8 +337,6 @@ static struct drm_driver mxsfb_driver = { | |||
333 | .irq_handler = mxsfb_irq_handler, | 337 | .irq_handler = mxsfb_irq_handler, |
334 | .irq_preinstall = mxsfb_irq_preinstall, | 338 | .irq_preinstall = mxsfb_irq_preinstall, |
335 | .irq_uninstall = mxsfb_irq_preinstall, | 339 | .irq_uninstall = mxsfb_irq_preinstall, |
336 | .enable_vblank = mxsfb_enable_vblank, | ||
337 | .disable_vblank = mxsfb_disable_vblank, | ||
338 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 340 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
339 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 341 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
340 | .dumb_create = drm_gem_cma_dumb_create, | 342 | .dumb_create = drm_gem_cma_dumb_create, |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index c8c2333f24ee..df4358e31075 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c | |||
@@ -46,7 +46,6 @@ struct nouveau_plane { | |||
46 | struct drm_property *brightness; | 46 | struct drm_property *brightness; |
47 | struct drm_property *hue; | 47 | struct drm_property *hue; |
48 | struct drm_property *saturation; | 48 | struct drm_property *saturation; |
49 | struct drm_property *iturbt_709; | ||
50 | } props; | 49 | } props; |
51 | 50 | ||
52 | int colorkey; | 51 | int colorkey; |
@@ -54,7 +53,7 @@ struct nouveau_plane { | |||
54 | int brightness; | 53 | int brightness; |
55 | int hue; | 54 | int hue; |
56 | int saturation; | 55 | int saturation; |
57 | int iturbt_709; | 56 | enum drm_color_encoding color_encoding; |
58 | 57 | ||
59 | void (*set_params)(struct nouveau_plane *); | 58 | void (*set_params)(struct nouveau_plane *); |
60 | }; | 59 | }; |
@@ -166,7 +165,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
166 | if (fb->format->format == DRM_FORMAT_NV12 || | 165 | if (fb->format->format == DRM_FORMAT_NV12 || |
167 | fb->format->format == DRM_FORMAT_NV21) | 166 | fb->format->format == DRM_FORMAT_NV21) |
168 | format |= NV_PVIDEO_FORMAT_PLANAR; | 167 | format |= NV_PVIDEO_FORMAT_PLANAR; |
169 | if (nv_plane->iturbt_709) | 168 | if (nv_plane->color_encoding == DRM_COLOR_YCBCR_BT709) |
170 | format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; | 169 | format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; |
171 | if (nv_plane->colorkey & (1 << 24)) | 170 | if (nv_plane->colorkey & (1 << 24)) |
172 | format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; | 171 | format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; |
@@ -229,7 +228,7 @@ nv10_set_params(struct nouveau_plane *plane) | |||
229 | nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff); | 228 | nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff); |
230 | 229 | ||
231 | if (plane->cur) { | 230 | if (plane->cur) { |
232 | if (plane->iturbt_709) | 231 | if (plane->color_encoding == DRM_COLOR_YCBCR_BT709) |
233 | format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; | 232 | format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; |
234 | if (plane->colorkey & (1 << 24)) | 233 | if (plane->colorkey & (1 << 24)) |
235 | format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; | 234 | format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; |
@@ -258,8 +257,8 @@ nv_set_property(struct drm_plane *plane, | |||
258 | nv_plane->hue = value; | 257 | nv_plane->hue = value; |
259 | else if (property == nv_plane->props.saturation) | 258 | else if (property == nv_plane->props.saturation) |
260 | nv_plane->saturation = value; | 259 | nv_plane->saturation = value; |
261 | else if (property == nv_plane->props.iturbt_709) | 260 | else if (property == nv_plane->base.color_encoding_property) |
262 | nv_plane->iturbt_709 = value; | 261 | nv_plane->color_encoding = value; |
263 | else | 262 | else |
264 | return -EINVAL; | 263 | return -EINVAL; |
265 | 264 | ||
@@ -313,14 +312,11 @@ nv10_overlay_init(struct drm_device *device) | |||
313 | device, 0, "hue", 0, 359); | 312 | device, 0, "hue", 0, 359); |
314 | plane->props.saturation = drm_property_create_range( | 313 | plane->props.saturation = drm_property_create_range( |
315 | device, 0, "saturation", 0, 8192 - 1); | 314 | device, 0, "saturation", 0, 8192 - 1); |
316 | plane->props.iturbt_709 = drm_property_create_range( | ||
317 | device, 0, "iturbt_709", 0, 1); | ||
318 | if (!plane->props.colorkey || | 315 | if (!plane->props.colorkey || |
319 | !plane->props.contrast || | 316 | !plane->props.contrast || |
320 | !plane->props.brightness || | 317 | !plane->props.brightness || |
321 | !plane->props.hue || | 318 | !plane->props.hue || |
322 | !plane->props.saturation || | 319 | !plane->props.saturation) |
323 | !plane->props.iturbt_709) | ||
324 | goto cleanup; | 320 | goto cleanup; |
325 | 321 | ||
326 | plane->colorkey = 0; | 322 | plane->colorkey = 0; |
@@ -343,9 +339,13 @@ nv10_overlay_init(struct drm_device *device) | |||
343 | drm_object_attach_property(&plane->base.base, | 339 | drm_object_attach_property(&plane->base.base, |
344 | plane->props.saturation, plane->saturation); | 340 | plane->props.saturation, plane->saturation); |
345 | 341 | ||
346 | plane->iturbt_709 = 0; | 342 | plane->color_encoding = DRM_COLOR_YCBCR_BT601; |
347 | drm_object_attach_property(&plane->base.base, | 343 | drm_plane_create_color_properties(&plane->base, |
348 | plane->props.iturbt_709, plane->iturbt_709); | 344 | BIT(DRM_COLOR_YCBCR_BT601) | |
345 | BIT(DRM_COLOR_YCBCR_BT709), | ||
346 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE), | ||
347 | DRM_COLOR_YCBCR_BT601, | ||
348 | DRM_COLOR_YCBCR_LIMITED_RANGE); | ||
349 | 349 | ||
350 | plane->set_params = nv10_set_params; | 350 | plane->set_params = nv10_set_params; |
351 | nv10_set_params(plane); | 351 | nv10_set_params(plane); |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 1f55b3d80a56..6af3bc483c84 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -1143,15 +1143,9 @@ static int | |||
1143 | nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, | 1143 | nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, |
1144 | struct nv50_head_atom *asyh) | 1144 | struct nv50_head_atom *asyh) |
1145 | { | 1145 | { |
1146 | struct drm_rect clip = {}; | ||
1147 | int ret; | 1146 | int ret; |
1148 | 1147 | ||
1149 | if (asyh->state.enable) | ||
1150 | drm_mode_get_hv_timing(&asyh->state.mode, | ||
1151 | &clip.x2, &clip.y2); | ||
1152 | |||
1153 | ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, | 1148 | ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, |
1154 | &clip, | ||
1155 | DRM_PLANE_HELPER_NO_SCALING, | 1149 | DRM_PLANE_HELPER_NO_SCALING, |
1156 | DRM_PLANE_HELPER_NO_SCALING, | 1150 | DRM_PLANE_HELPER_NO_SCALING, |
1157 | true, true); | 1151 | true, true); |
@@ -1435,18 +1429,12 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, | |||
1435 | struct nv50_head_atom *asyh) | 1429 | struct nv50_head_atom *asyh) |
1436 | { | 1430 | { |
1437 | const struct drm_framebuffer *fb = asyw->state.fb; | 1431 | const struct drm_framebuffer *fb = asyw->state.fb; |
1438 | struct drm_rect clip = {}; | ||
1439 | int ret; | 1432 | int ret; |
1440 | 1433 | ||
1441 | if (!fb->format->depth) | 1434 | if (!fb->format->depth) |
1442 | return -EINVAL; | 1435 | return -EINVAL; |
1443 | 1436 | ||
1444 | if (asyh->state.enable) | ||
1445 | drm_mode_get_hv_timing(&asyh->state.mode, | ||
1446 | &clip.x2, &clip.y2); | ||
1447 | |||
1448 | ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, | 1437 | ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, |
1449 | &clip, | ||
1450 | DRM_PLANE_HELPER_NO_SCALING, | 1438 | DRM_PLANE_HELPER_NO_SCALING, |
1451 | DRM_PLANE_HELPER_NO_SCALING, | 1439 | DRM_PLANE_HELPER_NO_SCALING, |
1452 | false, true); | 1440 | false, true); |
diff --git a/drivers/gpu/drm/panel/panel-arm-versatile.c b/drivers/gpu/drm/panel/panel-arm-versatile.c index 3930b4925b15..b428c4678106 100644 --- a/drivers/gpu/drm/panel/panel-arm-versatile.c +++ b/drivers/gpu/drm/panel/panel-arm-versatile.c | |||
@@ -132,7 +132,7 @@ static const struct versatile_panel_type versatile_panels[] = { | |||
132 | .width_mm = 79, | 132 | .width_mm = 79, |
133 | .height_mm = 54, | 133 | .height_mm = 54, |
134 | .mode = { | 134 | .mode = { |
135 | .clock = 10000000, | 135 | .clock = 10000, |
136 | .hdisplay = 320, | 136 | .hdisplay = 320, |
137 | .hsync_start = 320 + 6, | 137 | .hsync_start = 320 + 6, |
138 | .hsync_end = 320 + 6 + 6, | 138 | .hsync_end = 320 + 6 + 6, |
@@ -156,7 +156,7 @@ static const struct versatile_panel_type versatile_panels[] = { | |||
156 | .width_mm = 171, | 156 | .width_mm = 171, |
157 | .height_mm = 130, | 157 | .height_mm = 130, |
158 | .mode = { | 158 | .mode = { |
159 | .clock = 25000000, | 159 | .clock = 25000, |
160 | .hdisplay = 640, | 160 | .hdisplay = 640, |
161 | .hsync_start = 640 + 24, | 161 | .hsync_start = 640 + 24, |
162 | .hsync_end = 640 + 24 + 96, | 162 | .hsync_end = 640 + 24 + 96, |
@@ -179,7 +179,7 @@ static const struct versatile_panel_type versatile_panels[] = { | |||
179 | .width_mm = 34, | 179 | .width_mm = 34, |
180 | .height_mm = 45, | 180 | .height_mm = 45, |
181 | .mode = { | 181 | .mode = { |
182 | .clock = 625000000, | 182 | .clock = 62500, |
183 | .hdisplay = 176, | 183 | .hdisplay = 176, |
184 | .hsync_start = 176 + 2, | 184 | .hsync_start = 176 + 2, |
185 | .hsync_end = 176 + 2 + 3, | 185 | .hsync_end = 176 + 2 + 3, |
@@ -203,7 +203,7 @@ static const struct versatile_panel_type versatile_panels[] = { | |||
203 | .width_mm = 37, | 203 | .width_mm = 37, |
204 | .height_mm = 50, | 204 | .height_mm = 50, |
205 | .mode = { | 205 | .mode = { |
206 | .clock = 5400000, | 206 | .clock = 5400, |
207 | .hdisplay = 240, | 207 | .hdisplay = 240, |
208 | .hsync_start = 240 + 10, | 208 | .hsync_start = 240 + 10, |
209 | .hsync_end = 240 + 10 + 10, | 209 | .hsync_end = 240 + 10 + 10, |
diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index 82cb3e60ddc8..e5e2abd66491 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig | |||
@@ -8,7 +8,6 @@ config DRM_PL111 | |||
8 | select DRM_GEM_CMA_HELPER | 8 | select DRM_GEM_CMA_HELPER |
9 | select DRM_BRIDGE | 9 | select DRM_BRIDGE |
10 | select DRM_PANEL_BRIDGE | 10 | select DRM_PANEL_BRIDGE |
11 | select DRM_DUMB_VGA_DAC | ||
12 | select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE | 11 | select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE |
13 | help | 12 | help |
14 | Choose this option for DRM support for the PL111 CLCD controller. | 13 | Choose this option for DRM support for the PL111 CLCD controller. |
diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index d75923896609..310646427907 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c | |||
@@ -50,6 +50,41 @@ irqreturn_t pl111_irq(int irq, void *data) | |||
50 | return status; | 50 | return status; |
51 | } | 51 | } |
52 | 52 | ||
53 | static enum drm_mode_status | ||
54 | pl111_mode_valid(struct drm_crtc *crtc, | ||
55 | const struct drm_display_mode *mode) | ||
56 | { | ||
57 | struct drm_device *drm = crtc->dev; | ||
58 | struct pl111_drm_dev_private *priv = drm->dev_private; | ||
59 | u32 cpp = priv->variant->fb_bpp / 8; | ||
60 | u64 bw; | ||
61 | |||
62 | /* | ||
63 | * We use the pixelclock to also account for interlaced modes, the | ||
64 | * resulting bandwidth is in bytes per second. | ||
65 | */ | ||
66 | bw = mode->clock * 1000; /* In Hz */ | ||
67 | bw = bw * mode->hdisplay * mode->vdisplay * cpp; | ||
68 | bw = div_u64(bw, mode->htotal * mode->vtotal); | ||
69 | |||
70 | /* | ||
71 | * If no bandwidth constraints, anything goes, else | ||
72 | * check if we are too fast. | ||
73 | */ | ||
74 | if (priv->memory_bw && (bw > priv->memory_bw)) { | ||
75 | DRM_DEBUG_KMS("%d x %d @ %d Hz, %d cpp, bw %llu too fast\n", | ||
76 | mode->hdisplay, mode->vdisplay, | ||
77 | mode->clock * 1000, cpp, bw); | ||
78 | |||
79 | return MODE_BAD; | ||
80 | } | ||
81 | DRM_DEBUG_KMS("%d x %d @ %d Hz, %d cpp, bw %llu bytes/s OK\n", | ||
82 | mode->hdisplay, mode->vdisplay, | ||
83 | mode->clock * 1000, cpp, bw); | ||
84 | |||
85 | return MODE_OK; | ||
86 | } | ||
87 | |||
53 | static int pl111_display_check(struct drm_simple_display_pipe *pipe, | 88 | static int pl111_display_check(struct drm_simple_display_pipe *pipe, |
54 | struct drm_plane_state *pstate, | 89 | struct drm_plane_state *pstate, |
55 | struct drm_crtc_state *cstate) | 90 | struct drm_crtc_state *cstate) |
@@ -321,8 +356,10 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, | |||
321 | } | 356 | } |
322 | } | 357 | } |
323 | 358 | ||
324 | int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc) | 359 | static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe) |
325 | { | 360 | { |
361 | struct drm_crtc *crtc = &pipe->crtc; | ||
362 | struct drm_device *drm = crtc->dev; | ||
326 | struct pl111_drm_dev_private *priv = drm->dev_private; | 363 | struct pl111_drm_dev_private *priv = drm->dev_private; |
327 | 364 | ||
328 | writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + priv->ienb); | 365 | writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + priv->ienb); |
@@ -330,8 +367,10 @@ int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc) | |||
330 | return 0; | 367 | return 0; |
331 | } | 368 | } |
332 | 369 | ||
333 | void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) | 370 | static void pl111_display_disable_vblank(struct drm_simple_display_pipe *pipe) |
334 | { | 371 | { |
372 | struct drm_crtc *crtc = &pipe->crtc; | ||
373 | struct drm_device *drm = crtc->dev; | ||
335 | struct pl111_drm_dev_private *priv = drm->dev_private; | 374 | struct pl111_drm_dev_private *priv = drm->dev_private; |
336 | 375 | ||
337 | writel(0, priv->regs + priv->ienb); | 376 | writel(0, priv->regs + priv->ienb); |
@@ -343,7 +382,8 @@ static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe, | |||
343 | return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); | 382 | return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); |
344 | } | 383 | } |
345 | 384 | ||
346 | static const struct drm_simple_display_pipe_funcs pl111_display_funcs = { | 385 | static struct drm_simple_display_pipe_funcs pl111_display_funcs = { |
386 | .mode_valid = pl111_mode_valid, | ||
347 | .check = pl111_display_check, | 387 | .check = pl111_display_check, |
348 | .enable = pl111_display_enable, | 388 | .enable = pl111_display_enable, |
349 | .disable = pl111_display_disable, | 389 | .disable = pl111_display_disable, |
@@ -502,6 +542,11 @@ int pl111_display_init(struct drm_device *drm) | |||
502 | if (ret) | 542 | if (ret) |
503 | return ret; | 543 | return ret; |
504 | 544 | ||
545 | if (!priv->variant->broken_vblank) { | ||
546 | pl111_display_funcs.enable_vblank = pl111_display_enable_vblank; | ||
547 | pl111_display_funcs.disable_vblank = pl111_display_disable_vblank; | ||
548 | } | ||
549 | |||
505 | ret = drm_simple_display_pipe_init(drm, &priv->pipe, | 550 | ret = drm_simple_display_pipe_init(drm, &priv->pipe, |
506 | &pl111_display_funcs, | 551 | &pl111_display_funcs, |
507 | priv->variant->formats, | 552 | priv->variant->formats, |
diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index 6d0e450e51b1..8639b2d4ddf7 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h | |||
@@ -43,6 +43,7 @@ struct drm_minor; | |||
43 | * @broken_vblank: the vblank IRQ is broken on this variant | 43 | * @broken_vblank: the vblank IRQ is broken on this variant |
44 | * @formats: array of supported pixel formats on this variant | 44 | * @formats: array of supported pixel formats on this variant |
45 | * @nformats: the length of the array of supported pixel formats | 45 | * @nformats: the length of the array of supported pixel formats |
46 | * @fb_bpp: desired bits per pixel on the default framebuffer | ||
46 | */ | 47 | */ |
47 | struct pl111_variant_data { | 48 | struct pl111_variant_data { |
48 | const char *name; | 49 | const char *name; |
@@ -52,6 +53,7 @@ struct pl111_variant_data { | |||
52 | bool broken_vblank; | 53 | bool broken_vblank; |
53 | const u32 *formats; | 54 | const u32 *formats; |
54 | unsigned int nformats; | 55 | unsigned int nformats; |
56 | unsigned int fb_bpp; | ||
55 | }; | 57 | }; |
56 | 58 | ||
57 | struct pl111_drm_dev_private { | 59 | struct pl111_drm_dev_private { |
@@ -63,6 +65,7 @@ struct pl111_drm_dev_private { | |||
63 | struct drm_simple_display_pipe pipe; | 65 | struct drm_simple_display_pipe pipe; |
64 | 66 | ||
65 | void *regs; | 67 | void *regs; |
68 | u32 memory_bw; | ||
66 | u32 ienb; | 69 | u32 ienb; |
67 | u32 ctrl; | 70 | u32 ctrl; |
68 | /* The pixel clock (a reference to our clock divider off of CLCDCLK). */ | 71 | /* The pixel clock (a reference to our clock divider off of CLCDCLK). */ |
@@ -79,8 +82,6 @@ struct pl111_drm_dev_private { | |||
79 | }; | 82 | }; |
80 | 83 | ||
81 | int pl111_display_init(struct drm_device *dev); | 84 | int pl111_display_init(struct drm_device *dev); |
82 | int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc); | ||
83 | void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc); | ||
84 | irqreturn_t pl111_irq(int irq, void *data); | 85 | irqreturn_t pl111_irq(int irq, void *data); |
85 | int pl111_debugfs_init(struct drm_minor *minor); | 86 | int pl111_debugfs_init(struct drm_minor *minor); |
86 | 87 | ||
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 1231905150d0..4621259d5387 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c | |||
@@ -192,7 +192,7 @@ static int pl111_modeset_init(struct drm_device *dev) | |||
192 | 192 | ||
193 | drm_mode_config_reset(dev); | 193 | drm_mode_config_reset(dev); |
194 | 194 | ||
195 | drm_fb_cma_fbdev_init(dev, 32, 0); | 195 | drm_fb_cma_fbdev_init(dev, priv->variant->fb_bpp, 0); |
196 | 196 | ||
197 | drm_kms_helper_poll_init(dev); | 197 | drm_kms_helper_poll_init(dev); |
198 | 198 | ||
@@ -249,11 +249,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev, | |||
249 | if (!priv) | 249 | if (!priv) |
250 | return -ENOMEM; | 250 | return -ENOMEM; |
251 | 251 | ||
252 | if (!variant->broken_vblank) { | ||
253 | pl111_drm_driver.enable_vblank = pl111_enable_vblank; | ||
254 | pl111_drm_driver.disable_vblank = pl111_disable_vblank; | ||
255 | } | ||
256 | |||
257 | drm = drm_dev_alloc(&pl111_drm_driver, dev); | 252 | drm = drm_dev_alloc(&pl111_drm_driver, dev); |
258 | if (IS_ERR(drm)) | 253 | if (IS_ERR(drm)) |
259 | return PTR_ERR(drm); | 254 | return PTR_ERR(drm); |
@@ -262,6 +257,12 @@ static int pl111_amba_probe(struct amba_device *amba_dev, | |||
262 | drm->dev_private = priv; | 257 | drm->dev_private = priv; |
263 | priv->variant = variant; | 258 | priv->variant = variant; |
264 | 259 | ||
260 | if (of_property_read_u32(dev->of_node, "max-memory-bandwidth", | ||
261 | &priv->memory_bw)) { | ||
262 | dev_info(dev, "no max memory bandwidth specified, assume unlimited\n"); | ||
263 | priv->memory_bw = 0; | ||
264 | } | ||
265 | |||
265 | /* The two variants swap this register */ | 266 | /* The two variants swap this register */ |
266 | if (variant->is_pl110) { | 267 | if (variant->is_pl110) { |
267 | priv->ienb = CLCD_PL110_IENB; | 268 | priv->ienb = CLCD_PL110_IENB; |
@@ -341,6 +342,7 @@ static const struct pl111_variant_data pl110_variant = { | |||
341 | .is_pl110 = true, | 342 | .is_pl110 = true, |
342 | .formats = pl110_pixel_formats, | 343 | .formats = pl110_pixel_formats, |
343 | .nformats = ARRAY_SIZE(pl110_pixel_formats), | 344 | .nformats = ARRAY_SIZE(pl110_pixel_formats), |
345 | .fb_bpp = 16, | ||
344 | }; | 346 | }; |
345 | 347 | ||
346 | /* RealView, Versatile Express etc use this modern variant */ | 348 | /* RealView, Versatile Express etc use this modern variant */ |
@@ -365,6 +367,7 @@ static const struct pl111_variant_data pl111_variant = { | |||
365 | .name = "PL111", | 367 | .name = "PL111", |
366 | .formats = pl111_pixel_formats, | 368 | .formats = pl111_pixel_formats, |
367 | .nformats = ARRAY_SIZE(pl111_pixel_formats), | 369 | .nformats = ARRAY_SIZE(pl111_pixel_formats), |
370 | .fb_bpp = 32, | ||
368 | }; | 371 | }; |
369 | 372 | ||
370 | static const struct amba_id pl111_id_table[] = { | 373 | static const struct amba_id pl111_id_table[] = { |
diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c index 05a4b89e0934..9302f516045e 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.c +++ b/drivers/gpu/drm/pl111/pl111_versatile.c | |||
@@ -230,6 +230,23 @@ static const u32 pl110_versatile_pixel_formats[] = { | |||
230 | DRM_FORMAT_XRGB1555, | 230 | DRM_FORMAT_XRGB1555, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static const u32 pl111_realview_pixel_formats[] = { | ||
234 | DRM_FORMAT_ABGR8888, | ||
235 | DRM_FORMAT_XBGR8888, | ||
236 | DRM_FORMAT_ARGB8888, | ||
237 | DRM_FORMAT_XRGB8888, | ||
238 | DRM_FORMAT_BGR565, | ||
239 | DRM_FORMAT_RGB565, | ||
240 | DRM_FORMAT_ABGR1555, | ||
241 | DRM_FORMAT_XBGR1555, | ||
242 | DRM_FORMAT_ARGB1555, | ||
243 | DRM_FORMAT_XRGB1555, | ||
244 | DRM_FORMAT_ABGR4444, | ||
245 | DRM_FORMAT_XBGR4444, | ||
246 | DRM_FORMAT_ARGB4444, | ||
247 | DRM_FORMAT_XRGB4444, | ||
248 | }; | ||
249 | |||
233 | /* | 250 | /* |
234 | * The Integrator variant is a PL110 with a bunch of broken, or not | 251 | * The Integrator variant is a PL110 with a bunch of broken, or not |
235 | * yet implemented features | 252 | * yet implemented features |
@@ -241,6 +258,7 @@ static const struct pl111_variant_data pl110_integrator = { | |||
241 | .broken_vblank = true, | 258 | .broken_vblank = true, |
242 | .formats = pl110_integrator_pixel_formats, | 259 | .formats = pl110_integrator_pixel_formats, |
243 | .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), | 260 | .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), |
261 | .fb_bpp = 16, | ||
244 | }; | 262 | }; |
245 | 263 | ||
246 | /* | 264 | /* |
@@ -253,6 +271,19 @@ static const struct pl111_variant_data pl110_versatile = { | |||
253 | .external_bgr = true, | 271 | .external_bgr = true, |
254 | .formats = pl110_versatile_pixel_formats, | 272 | .formats = pl110_versatile_pixel_formats, |
255 | .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats), | 273 | .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats), |
274 | .fb_bpp = 16, | ||
275 | }; | ||
276 | |||
277 | /* | ||
278 | * RealView PL111 variant, the only real difference from the vanilla | ||
279 | * PL111 is that we select 16bpp framebuffer by default to be able | ||
280 | * to get 1024x768 without saturating the memory bus. | ||
281 | */ | ||
282 | static const struct pl111_variant_data pl111_realview = { | ||
283 | .name = "PL111 RealView", | ||
284 | .formats = pl111_realview_pixel_formats, | ||
285 | .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), | ||
286 | .fb_bpp = 16, | ||
256 | }; | 287 | }; |
257 | 288 | ||
258 | int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) | 289 | int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) |
@@ -304,6 +335,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) | |||
304 | case REALVIEW_CLCD_PBA8: | 335 | case REALVIEW_CLCD_PBA8: |
305 | case REALVIEW_CLCD_PBX: | 336 | case REALVIEW_CLCD_PBX: |
306 | versatile_syscon_map = map; | 337 | versatile_syscon_map = map; |
338 | priv->variant = &pl111_realview; | ||
307 | priv->variant_display_enable = pl111_realview_clcd_enable; | 339 | priv->variant_display_enable = pl111_realview_clcd_enable; |
308 | priv->variant_display_disable = pl111_realview_clcd_disable; | 340 | priv->variant_display_disable = pl111_realview_clcd_disable; |
309 | dev_info(dev, "set up callbacks for RealView PL111\n"); | 341 | dev_info(dev, "set up callbacks for RealView PL111\n"); |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 5687a94d4cb1..68556bd9dad2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c | |||
@@ -572,7 +572,6 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, | |||
572 | { | 572 | { |
573 | struct drm_device *dev = plane->dev; | 573 | struct drm_device *dev = plane->dev; |
574 | struct drm_crtc_state *crtc_state; | 574 | struct drm_crtc_state *crtc_state; |
575 | struct drm_rect clip = {}; | ||
576 | int ret; | 575 | int ret; |
577 | 576 | ||
578 | if (!state->crtc) { | 577 | if (!state->crtc) { |
@@ -589,11 +588,7 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, | |||
589 | if (IS_ERR(crtc_state)) | 588 | if (IS_ERR(crtc_state)) |
590 | return PTR_ERR(crtc_state); | 589 | return PTR_ERR(crtc_state); |
591 | 590 | ||
592 | if (crtc_state->enable) | 591 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
593 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
594 | &clip.x2, &clip.y2); | ||
595 | |||
596 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
597 | DRM_PLANE_HELPER_NO_SCALING, | 592 | DRM_PLANE_HELPER_NO_SCALING, |
598 | DRM_PLANE_HELPER_NO_SCALING, | 593 | DRM_PLANE_HELPER_NO_SCALING, |
599 | true, true); | 594 | true, true); |
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 1262120a3834..7d76ff47028d 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | |||
@@ -77,6 +77,7 @@ struct rockchip_dp_device { | |||
77 | 77 | ||
78 | const struct rockchip_dp_chip_data *data; | 78 | const struct rockchip_dp_chip_data *data; |
79 | 79 | ||
80 | struct analogix_dp_device *adp; | ||
80 | struct analogix_dp_plat_data plat_data; | 81 | struct analogix_dp_plat_data plat_data; |
81 | }; | 82 | }; |
82 | 83 | ||
@@ -84,7 +85,7 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) | |||
84 | { | 85 | { |
85 | struct rockchip_dp_device *dp = to_dp(encoder); | 86 | struct rockchip_dp_device *dp = to_dp(encoder); |
86 | 87 | ||
87 | if (!analogix_dp_psr_supported(dp->dev)) | 88 | if (!analogix_dp_psr_supported(dp->adp)) |
88 | return; | 89 | return; |
89 | 90 | ||
90 | DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); | 91 | DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); |
@@ -114,9 +115,9 @@ static void analogix_dp_psr_work(struct work_struct *work) | |||
114 | 115 | ||
115 | mutex_lock(&dp->psr_lock); | 116 | mutex_lock(&dp->psr_lock); |
116 | if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) | 117 | if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) |
117 | analogix_dp_enable_psr(dp->dev); | 118 | analogix_dp_enable_psr(dp->adp); |
118 | else | 119 | else |
119 | analogix_dp_disable_psr(dp->dev); | 120 | analogix_dp_disable_psr(dp->adp); |
120 | mutex_unlock(&dp->psr_lock); | 121 | mutex_unlock(&dp->psr_lock); |
121 | } | 122 | } |
122 | 123 | ||
@@ -149,12 +150,17 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) | |||
149 | return ret; | 150 | return ret; |
150 | } | 151 | } |
151 | 152 | ||
152 | return 0; | 153 | return rockchip_drm_psr_activate(&dp->encoder); |
153 | } | 154 | } |
154 | 155 | ||
155 | static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) | 156 | static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) |
156 | { | 157 | { |
157 | struct rockchip_dp_device *dp = to_dp(plat_data); | 158 | struct rockchip_dp_device *dp = to_dp(plat_data); |
159 | int ret; | ||
160 | |||
161 | ret = rockchip_drm_psr_deactivate(&dp->encoder); | ||
162 | if (ret != 0) | ||
163 | return ret; | ||
158 | 164 | ||
159 | clk_disable_unprepare(dp->pclk); | 165 | clk_disable_unprepare(dp->pclk); |
160 | 166 | ||
@@ -258,13 +264,8 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { | |||
258 | .atomic_check = rockchip_dp_drm_encoder_atomic_check, | 264 | .atomic_check = rockchip_dp_drm_encoder_atomic_check, |
259 | }; | 265 | }; |
260 | 266 | ||
261 | static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) | ||
262 | { | ||
263 | drm_encoder_cleanup(encoder); | ||
264 | } | ||
265 | |||
266 | static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { | 267 | static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { |
267 | .destroy = rockchip_dp_drm_encoder_destroy, | 268 | .destroy = drm_encoder_cleanup, |
268 | }; | 269 | }; |
269 | 270 | ||
270 | static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) | 271 | static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) |
@@ -334,13 +335,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, | |||
334 | struct drm_device *drm_dev = data; | 335 | struct drm_device *drm_dev = data; |
335 | int ret; | 336 | int ret; |
336 | 337 | ||
337 | /* | ||
338 | * Just like the probe function said, we don't need the | ||
339 | * device drvrate anymore, we should leave the charge to | ||
340 | * analogix dp driver, set the device drvdata to NULL. | ||
341 | */ | ||
342 | dev_set_drvdata(dev, NULL); | ||
343 | |||
344 | dp_data = of_device_get_match_data(dev); | 338 | dp_data = of_device_get_match_data(dev); |
345 | if (!dp_data) | 339 | if (!dp_data) |
346 | return -ENODEV; | 340 | return -ENODEV; |
@@ -365,9 +359,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, | |||
365 | dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; | 359 | dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; |
366 | INIT_WORK(&dp->psr_work, analogix_dp_psr_work); | 360 | INIT_WORK(&dp->psr_work, analogix_dp_psr_work); |
367 | 361 | ||
368 | rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); | 362 | ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); |
363 | if (ret < 0) | ||
364 | goto err_cleanup_encoder; | ||
365 | |||
366 | dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); | ||
367 | if (IS_ERR(dp->adp)) { | ||
368 | ret = PTR_ERR(dp->adp); | ||
369 | goto err_unreg_psr; | ||
370 | } | ||
369 | 371 | ||
370 | return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); | 372 | return 0; |
373 | err_unreg_psr: | ||
374 | rockchip_drm_psr_unregister(&dp->encoder); | ||
375 | err_cleanup_encoder: | ||
376 | dp->encoder.funcs->destroy(&dp->encoder); | ||
377 | return ret; | ||
371 | } | 378 | } |
372 | 379 | ||
373 | static void rockchip_dp_unbind(struct device *dev, struct device *master, | 380 | static void rockchip_dp_unbind(struct device *dev, struct device *master, |
@@ -375,9 +382,9 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, | |||
375 | { | 382 | { |
376 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); | 383 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); |
377 | 384 | ||
385 | analogix_dp_unbind(dp->adp); | ||
378 | rockchip_drm_psr_unregister(&dp->encoder); | 386 | rockchip_drm_psr_unregister(&dp->encoder); |
379 | 387 | dp->encoder.funcs->destroy(&dp->encoder); | |
380 | analogix_dp_unbind(dev, master, data); | ||
381 | } | 388 | } |
382 | 389 | ||
383 | static const struct component_ops rockchip_dp_component_ops = { | 390 | static const struct component_ops rockchip_dp_component_ops = { |
@@ -407,11 +414,6 @@ static int rockchip_dp_probe(struct platform_device *pdev) | |||
407 | if (ret < 0) | 414 | if (ret < 0) |
408 | return ret; | 415 | return ret; |
409 | 416 | ||
410 | /* | ||
411 | * We just use the drvdata until driver run into component | ||
412 | * add function, and then we would set drvdata to null, so | ||
413 | * that analogix dp driver could take charge of the drvdata. | ||
414 | */ | ||
415 | platform_set_drvdata(pdev, dp); | 417 | platform_set_drvdata(pdev, dp); |
416 | 418 | ||
417 | return component_add(dev, &rockchip_dp_component_ops); | 419 | return component_add(dev, &rockchip_dp_component_ops); |
@@ -424,10 +426,26 @@ static int rockchip_dp_remove(struct platform_device *pdev) | |||
424 | return 0; | 426 | return 0; |
425 | } | 427 | } |
426 | 428 | ||
429 | #ifdef CONFIG_PM_SLEEP | ||
430 | static int rockchip_dp_suspend(struct device *dev) | ||
431 | { | ||
432 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); | ||
433 | |||
434 | return analogix_dp_suspend(dp->adp); | ||
435 | } | ||
436 | |||
437 | static int rockchip_dp_resume(struct device *dev) | ||
438 | { | ||
439 | struct rockchip_dp_device *dp = dev_get_drvdata(dev); | ||
440 | |||
441 | return analogix_dp_resume(dp->adp); | ||
442 | } | ||
443 | #endif | ||
444 | |||
427 | static const struct dev_pm_ops rockchip_dp_pm_ops = { | 445 | static const struct dev_pm_ops rockchip_dp_pm_ops = { |
428 | #ifdef CONFIG_PM_SLEEP | 446 | #ifdef CONFIG_PM_SLEEP |
429 | .suspend = analogix_dp_suspend, | 447 | .suspend = rockchip_dp_suspend, |
430 | .resume_early = analogix_dp_resume, | 448 | .resume_early = rockchip_dp_resume, |
431 | #endif | 449 | #endif |
432 | }; | 450 | }; |
433 | 451 | ||
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 591953cbdd18..d53d5a09547f 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c | |||
@@ -1302,8 +1302,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, | |||
1302 | err_mipi_dsi_host: | 1302 | err_mipi_dsi_host: |
1303 | mipi_dsi_host_unregister(&dsi->dsi_host); | 1303 | mipi_dsi_host_unregister(&dsi->dsi_host); |
1304 | err_cleanup: | 1304 | err_cleanup: |
1305 | drm_encoder_cleanup(&dsi->encoder); | 1305 | dsi->connector.funcs->destroy(&dsi->connector); |
1306 | drm_connector_cleanup(&dsi->connector); | 1306 | dsi->encoder.funcs->destroy(&dsi->encoder); |
1307 | err_pllref: | 1307 | err_pllref: |
1308 | clk_disable_unprepare(dsi->pllref_clk); | 1308 | clk_disable_unprepare(dsi->pllref_clk); |
1309 | return ret; | 1309 | return ret; |
@@ -1316,6 +1316,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, | |||
1316 | 1316 | ||
1317 | mipi_dsi_host_unregister(&dsi->dsi_host); | 1317 | mipi_dsi_host_unregister(&dsi->dsi_host); |
1318 | pm_runtime_disable(dev); | 1318 | pm_runtime_disable(dev); |
1319 | |||
1320 | dsi->connector.funcs->destroy(&dsi->connector); | ||
1321 | dsi->encoder.funcs->destroy(&dsi->encoder); | ||
1322 | |||
1319 | clk_disable_unprepare(dsi->pllref_clk); | 1323 | clk_disable_unprepare(dsi->pllref_clk); |
1320 | } | 1324 | } |
1321 | 1325 | ||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 3574b0ae2ad1..11309a2a4e43 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | |||
@@ -165,7 +165,6 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { | |||
165 | static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) | 165 | static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) |
166 | { | 166 | { |
167 | struct device_node *np = hdmi->dev->of_node; | 167 | struct device_node *np = hdmi->dev->of_node; |
168 | int ret; | ||
169 | 168 | ||
170 | hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); | 169 | hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); |
171 | if (IS_ERR(hdmi->regmap)) { | 170 | if (IS_ERR(hdmi->regmap)) { |
@@ -193,13 +192,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) | |||
193 | return PTR_ERR(hdmi->grf_clk); | 192 | return PTR_ERR(hdmi->grf_clk); |
194 | } | 193 | } |
195 | 194 | ||
196 | ret = clk_prepare_enable(hdmi->vpll_clk); | ||
197 | if (ret) { | ||
198 | DRM_DEV_ERROR(hdmi->dev, | ||
199 | "Failed to enable HDMI vpll: %d\n", ret); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | return 0; | 195 | return 0; |
204 | } | 196 | } |
205 | 197 | ||
@@ -374,6 +366,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, | |||
374 | return ret; | 366 | return ret; |
375 | } | 367 | } |
376 | 368 | ||
369 | ret = clk_prepare_enable(hdmi->vpll_clk); | ||
370 | if (ret) { | ||
371 | DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", | ||
372 | ret); | ||
373 | return ret; | ||
374 | } | ||
375 | |||
377 | drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); | 376 | drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); |
378 | drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, | 377 | drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, |
379 | DRM_MODE_ENCODER_TMDS, NULL); | 378 | DRM_MODE_ENCODER_TMDS, NULL); |
@@ -389,6 +388,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, | |||
389 | if (IS_ERR(hdmi->hdmi)) { | 388 | if (IS_ERR(hdmi->hdmi)) { |
390 | ret = PTR_ERR(hdmi->hdmi); | 389 | ret = PTR_ERR(hdmi->hdmi); |
391 | drm_encoder_cleanup(encoder); | 390 | drm_encoder_cleanup(encoder); |
391 | clk_disable_unprepare(hdmi->vpll_clk); | ||
392 | } | 392 | } |
393 | 393 | ||
394 | return ret; | 394 | return ret; |
@@ -400,6 +400,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, | |||
400 | struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); | 400 | struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); |
401 | 401 | ||
402 | dw_hdmi_unbind(hdmi->hdmi); | 402 | dw_hdmi_unbind(hdmi->hdmi); |
403 | clk_disable_unprepare(hdmi->vpll_clk); | ||
403 | } | 404 | } |
404 | 405 | ||
405 | static const struct component_ops dw_hdmi_rockchip_ops = { | 406 | static const struct component_ops dw_hdmi_rockchip_ops = { |
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index f6ad48766d49..88d0774c97bd 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c | |||
@@ -849,8 +849,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, | |||
849 | } | 849 | } |
850 | 850 | ||
851 | irq = platform_get_irq(pdev, 0); | 851 | irq = platform_get_irq(pdev, 0); |
852 | if (irq < 0) | 852 | if (irq < 0) { |
853 | return irq; | 853 | ret = irq; |
854 | goto err_disable_clk; | ||
855 | } | ||
854 | 856 | ||
855 | inno_hdmi_reset(hdmi); | 857 | inno_hdmi_reset(hdmi); |
856 | 858 | ||
@@ -858,7 +860,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, | |||
858 | if (IS_ERR(hdmi->ddc)) { | 860 | if (IS_ERR(hdmi->ddc)) { |
859 | ret = PTR_ERR(hdmi->ddc); | 861 | ret = PTR_ERR(hdmi->ddc); |
860 | hdmi->ddc = NULL; | 862 | hdmi->ddc = NULL; |
861 | return ret; | 863 | goto err_disable_clk; |
862 | } | 864 | } |
863 | 865 | ||
864 | /* | 866 | /* |
@@ -872,7 +874,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, | |||
872 | 874 | ||
873 | ret = inno_hdmi_register(drm, hdmi); | 875 | ret = inno_hdmi_register(drm, hdmi); |
874 | if (ret) | 876 | if (ret) |
875 | return ret; | 877 | goto err_put_adapter; |
876 | 878 | ||
877 | dev_set_drvdata(dev, hdmi); | 879 | dev_set_drvdata(dev, hdmi); |
878 | 880 | ||
@@ -882,7 +884,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, | |||
882 | ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, | 884 | ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, |
883 | inno_hdmi_irq, IRQF_SHARED, | 885 | inno_hdmi_irq, IRQF_SHARED, |
884 | dev_name(dev), hdmi); | 886 | dev_name(dev), hdmi); |
887 | if (ret < 0) | ||
888 | goto err_cleanup_hdmi; | ||
885 | 889 | ||
890 | return 0; | ||
891 | err_cleanup_hdmi: | ||
892 | hdmi->connector.funcs->destroy(&hdmi->connector); | ||
893 | hdmi->encoder.funcs->destroy(&hdmi->encoder); | ||
894 | err_put_adapter: | ||
895 | i2c_put_adapter(hdmi->ddc); | ||
896 | err_disable_clk: | ||
897 | clk_disable_unprepare(hdmi->pclk); | ||
886 | return ret; | 898 | return ret; |
887 | } | 899 | } |
888 | 900 | ||
@@ -894,8 +906,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, | |||
894 | hdmi->connector.funcs->destroy(&hdmi->connector); | 906 | hdmi->connector.funcs->destroy(&hdmi->connector); |
895 | hdmi->encoder.funcs->destroy(&hdmi->encoder); | 907 | hdmi->encoder.funcs->destroy(&hdmi->encoder); |
896 | 908 | ||
897 | clk_disable_unprepare(hdmi->pclk); | ||
898 | i2c_put_adapter(hdmi->ddc); | 909 | i2c_put_adapter(hdmi->ddc); |
910 | clk_disable_unprepare(hdmi->pclk); | ||
899 | } | 911 | } |
900 | 912 | ||
901 | static const struct component_ops inno_hdmi_ops = { | 913 | static const struct component_ops inno_hdmi_ops = { |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 88084ca15115..f814d37b1db2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c | |||
@@ -134,7 +134,7 @@ static int rockchip_drm_bind(struct device *dev) | |||
134 | drm_dev->dev_private = private; | 134 | drm_dev->dev_private = private; |
135 | 135 | ||
136 | INIT_LIST_HEAD(&private->psr_list); | 136 | INIT_LIST_HEAD(&private->psr_list); |
137 | spin_lock_init(&private->psr_list_lock); | 137 | mutex_init(&private->psr_list_lock); |
138 | 138 | ||
139 | ret = rockchip_drm_init_iommu(drm_dev); | 139 | ret = rockchip_drm_init_iommu(drm_dev); |
140 | if (ret) | 140 | if (ret) |
@@ -314,6 +314,14 @@ static int compare_dev(struct device *dev, void *data) | |||
314 | return dev == (struct device *)data; | 314 | return dev == (struct device *)data; |
315 | } | 315 | } |
316 | 316 | ||
317 | static void rockchip_drm_match_remove(struct device *dev) | ||
318 | { | ||
319 | struct device_link *link; | ||
320 | |||
321 | list_for_each_entry(link, &dev->links.consumers, s_node) | ||
322 | device_link_del(link); | ||
323 | } | ||
324 | |||
317 | static struct component_match *rockchip_drm_match_add(struct device *dev) | 325 | static struct component_match *rockchip_drm_match_add(struct device *dev) |
318 | { | 326 | { |
319 | struct component_match *match = NULL; | 327 | struct component_match *match = NULL; |
@@ -331,10 +339,15 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) | |||
331 | 339 | ||
332 | if (!d) | 340 | if (!d) |
333 | break; | 341 | break; |
342 | |||
343 | device_link_add(dev, d, DL_FLAG_STATELESS); | ||
334 | component_match_add(dev, &match, compare_dev, d); | 344 | component_match_add(dev, &match, compare_dev, d); |
335 | } while (true); | 345 | } while (true); |
336 | } | 346 | } |
337 | 347 | ||
348 | if (IS_ERR(match)) | ||
349 | rockchip_drm_match_remove(dev); | ||
350 | |||
338 | return match ?: ERR_PTR(-ENODEV); | 351 | return match ?: ERR_PTR(-ENODEV); |
339 | } | 352 | } |
340 | 353 | ||
@@ -411,13 +424,21 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) | |||
411 | if (IS_ERR(match)) | 424 | if (IS_ERR(match)) |
412 | return PTR_ERR(match); | 425 | return PTR_ERR(match); |
413 | 426 | ||
414 | return component_master_add_with_match(dev, &rockchip_drm_ops, match); | 427 | ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); |
428 | if (ret < 0) { | ||
429 | rockchip_drm_match_remove(dev); | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | return 0; | ||
415 | } | 434 | } |
416 | 435 | ||
417 | static int rockchip_drm_platform_remove(struct platform_device *pdev) | 436 | static int rockchip_drm_platform_remove(struct platform_device *pdev) |
418 | { | 437 | { |
419 | component_master_del(&pdev->dev, &rockchip_drm_ops); | 438 | component_master_del(&pdev->dev, &rockchip_drm_ops); |
420 | 439 | ||
440 | rockchip_drm_match_remove(&pdev->dev); | ||
441 | |||
421 | return 0; | 442 | return 0; |
422 | } | 443 | } |
423 | 444 | ||
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 498dfbc52cec..9c064a40458b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h | |||
@@ -55,7 +55,7 @@ struct rockchip_drm_private { | |||
55 | struct mutex mm_lock; | 55 | struct mutex mm_lock; |
56 | struct drm_mm mm; | 56 | struct drm_mm mm; |
57 | struct list_head psr_list; | 57 | struct list_head psr_list; |
58 | spinlock_t psr_list_lock; | 58 | struct mutex psr_list_lock; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, | 61 | int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c index 3acfd576b7df..b339ca943139 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include "rockchip_drm_drv.h" | 18 | #include "rockchip_drm_drv.h" |
19 | #include "rockchip_drm_psr.h" | 19 | #include "rockchip_drm_psr.h" |
20 | 20 | ||
21 | #define PSR_FLUSH_TIMEOUT msecs_to_jiffies(100) | 21 | #define PSR_FLUSH_TIMEOUT_MS 100 |
22 | 22 | ||
23 | enum psr_state { | 23 | enum psr_state { |
24 | PSR_FLUSH, | 24 | PSR_FLUSH, |
@@ -30,11 +30,11 @@ struct psr_drv { | |||
30 | struct list_head list; | 30 | struct list_head list; |
31 | struct drm_encoder *encoder; | 31 | struct drm_encoder *encoder; |
32 | 32 | ||
33 | spinlock_t lock; | 33 | struct mutex lock; |
34 | bool active; | 34 | bool active; |
35 | enum psr_state state; | 35 | enum psr_state state; |
36 | 36 | ||
37 | struct timer_list flush_timer; | 37 | struct delayed_work flush_work; |
38 | 38 | ||
39 | void (*set)(struct drm_encoder *encoder, bool enable); | 39 | void (*set)(struct drm_encoder *encoder, bool enable); |
40 | }; | 40 | }; |
@@ -43,9 +43,8 @@ static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc) | |||
43 | { | 43 | { |
44 | struct rockchip_drm_private *drm_drv = crtc->dev->dev_private; | 44 | struct rockchip_drm_private *drm_drv = crtc->dev->dev_private; |
45 | struct psr_drv *psr; | 45 | struct psr_drv *psr; |
46 | unsigned long flags; | ||
47 | 46 | ||
48 | spin_lock_irqsave(&drm_drv->psr_list_lock, flags); | 47 | mutex_lock(&drm_drv->psr_list_lock); |
49 | list_for_each_entry(psr, &drm_drv->psr_list, list) { | 48 | list_for_each_entry(psr, &drm_drv->psr_list, list) { |
50 | if (psr->encoder->crtc == crtc) | 49 | if (psr->encoder->crtc == crtc) |
51 | goto out; | 50 | goto out; |
@@ -53,7 +52,24 @@ static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc) | |||
53 | psr = ERR_PTR(-ENODEV); | 52 | psr = ERR_PTR(-ENODEV); |
54 | 53 | ||
55 | out: | 54 | out: |
56 | spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags); | 55 | mutex_unlock(&drm_drv->psr_list_lock); |
56 | return psr; | ||
57 | } | ||
58 | |||
59 | static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder) | ||
60 | { | ||
61 | struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; | ||
62 | struct psr_drv *psr; | ||
63 | |||
64 | mutex_lock(&drm_drv->psr_list_lock); | ||
65 | list_for_each_entry(psr, &drm_drv->psr_list, list) { | ||
66 | if (psr->encoder == encoder) | ||
67 | goto out; | ||
68 | } | ||
69 | psr = ERR_PTR(-ENODEV); | ||
70 | |||
71 | out: | ||
72 | mutex_unlock(&drm_drv->psr_list_lock); | ||
57 | return psr; | 73 | return psr; |
58 | } | 74 | } |
59 | 75 | ||
@@ -94,43 +110,40 @@ static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state) | |||
94 | 110 | ||
95 | static void psr_set_state(struct psr_drv *psr, enum psr_state state) | 111 | static void psr_set_state(struct psr_drv *psr, enum psr_state state) |
96 | { | 112 | { |
97 | unsigned long flags; | 113 | mutex_lock(&psr->lock); |
98 | |||
99 | spin_lock_irqsave(&psr->lock, flags); | ||
100 | psr_set_state_locked(psr, state); | 114 | psr_set_state_locked(psr, state); |
101 | spin_unlock_irqrestore(&psr->lock, flags); | 115 | mutex_unlock(&psr->lock); |
102 | } | 116 | } |
103 | 117 | ||
104 | static void psr_flush_handler(struct timer_list *t) | 118 | static void psr_flush_handler(struct work_struct *work) |
105 | { | 119 | { |
106 | struct psr_drv *psr = from_timer(psr, t, flush_timer); | 120 | struct psr_drv *psr = container_of(to_delayed_work(work), |
107 | unsigned long flags; | 121 | struct psr_drv, flush_work); |
108 | 122 | ||
109 | /* If the state has changed since we initiated the flush, do nothing */ | 123 | /* If the state has changed since we initiated the flush, do nothing */ |
110 | spin_lock_irqsave(&psr->lock, flags); | 124 | mutex_lock(&psr->lock); |
111 | if (psr->state == PSR_FLUSH) | 125 | if (psr->state == PSR_FLUSH) |
112 | psr_set_state_locked(psr, PSR_ENABLE); | 126 | psr_set_state_locked(psr, PSR_ENABLE); |
113 | spin_unlock_irqrestore(&psr->lock, flags); | 127 | mutex_unlock(&psr->lock); |
114 | } | 128 | } |
115 | 129 | ||
116 | /** | 130 | /** |
117 | * rockchip_drm_psr_activate - activate PSR on the given pipe | 131 | * rockchip_drm_psr_activate - activate PSR on the given pipe |
118 | * @crtc: CRTC to obtain the PSR encoder | 132 | * @encoder: encoder to obtain the PSR encoder |
119 | * | 133 | * |
120 | * Returns: | 134 | * Returns: |
121 | * Zero on success, negative errno on failure. | 135 | * Zero on success, negative errno on failure. |
122 | */ | 136 | */ |
123 | int rockchip_drm_psr_activate(struct drm_crtc *crtc) | 137 | int rockchip_drm_psr_activate(struct drm_encoder *encoder) |
124 | { | 138 | { |
125 | struct psr_drv *psr = find_psr_by_crtc(crtc); | 139 | struct psr_drv *psr = find_psr_by_encoder(encoder); |
126 | unsigned long flags; | ||
127 | 140 | ||
128 | if (IS_ERR(psr)) | 141 | if (IS_ERR(psr)) |
129 | return PTR_ERR(psr); | 142 | return PTR_ERR(psr); |
130 | 143 | ||
131 | spin_lock_irqsave(&psr->lock, flags); | 144 | mutex_lock(&psr->lock); |
132 | psr->active = true; | 145 | psr->active = true; |
133 | spin_unlock_irqrestore(&psr->lock, flags); | 146 | mutex_unlock(&psr->lock); |
134 | 147 | ||
135 | return 0; | 148 | return 0; |
136 | } | 149 | } |
@@ -138,23 +151,22 @@ EXPORT_SYMBOL(rockchip_drm_psr_activate); | |||
138 | 151 | ||
139 | /** | 152 | /** |
140 | * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe | 153 | * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe |
141 | * @crtc: CRTC to obtain the PSR encoder | 154 | * @encoder: encoder to obtain the PSR encoder |
142 | * | 155 | * |
143 | * Returns: | 156 | * Returns: |
144 | * Zero on success, negative errno on failure. | 157 | * Zero on success, negative errno on failure. |
145 | */ | 158 | */ |
146 | int rockchip_drm_psr_deactivate(struct drm_crtc *crtc) | 159 | int rockchip_drm_psr_deactivate(struct drm_encoder *encoder) |
147 | { | 160 | { |
148 | struct psr_drv *psr = find_psr_by_crtc(crtc); | 161 | struct psr_drv *psr = find_psr_by_encoder(encoder); |
149 | unsigned long flags; | ||
150 | 162 | ||
151 | if (IS_ERR(psr)) | 163 | if (IS_ERR(psr)) |
152 | return PTR_ERR(psr); | 164 | return PTR_ERR(psr); |
153 | 165 | ||
154 | spin_lock_irqsave(&psr->lock, flags); | 166 | mutex_lock(&psr->lock); |
155 | psr->active = false; | 167 | psr->active = false; |
156 | spin_unlock_irqrestore(&psr->lock, flags); | 168 | mutex_unlock(&psr->lock); |
157 | del_timer_sync(&psr->flush_timer); | 169 | cancel_delayed_work_sync(&psr->flush_work); |
158 | 170 | ||
159 | return 0; | 171 | return 0; |
160 | } | 172 | } |
@@ -162,9 +174,8 @@ EXPORT_SYMBOL(rockchip_drm_psr_deactivate); | |||
162 | 174 | ||
163 | static void rockchip_drm_do_flush(struct psr_drv *psr) | 175 | static void rockchip_drm_do_flush(struct psr_drv *psr) |
164 | { | 176 | { |
165 | mod_timer(&psr->flush_timer, | ||
166 | round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT)); | ||
167 | psr_set_state(psr, PSR_FLUSH); | 177 | psr_set_state(psr, PSR_FLUSH); |
178 | mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS); | ||
168 | } | 179 | } |
169 | 180 | ||
170 | /** | 181 | /** |
@@ -201,12 +212,11 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev) | |||
201 | { | 212 | { |
202 | struct rockchip_drm_private *drm_drv = dev->dev_private; | 213 | struct rockchip_drm_private *drm_drv = dev->dev_private; |
203 | struct psr_drv *psr; | 214 | struct psr_drv *psr; |
204 | unsigned long flags; | ||
205 | 215 | ||
206 | spin_lock_irqsave(&drm_drv->psr_list_lock, flags); | 216 | mutex_lock(&drm_drv->psr_list_lock); |
207 | list_for_each_entry(psr, &drm_drv->psr_list, list) | 217 | list_for_each_entry(psr, &drm_drv->psr_list, list) |
208 | rockchip_drm_do_flush(psr); | 218 | rockchip_drm_do_flush(psr); |
209 | spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags); | 219 | mutex_unlock(&drm_drv->psr_list_lock); |
210 | } | 220 | } |
211 | EXPORT_SYMBOL(rockchip_drm_psr_flush_all); | 221 | EXPORT_SYMBOL(rockchip_drm_psr_flush_all); |
212 | 222 | ||
@@ -223,7 +233,6 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, | |||
223 | { | 233 | { |
224 | struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; | 234 | struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; |
225 | struct psr_drv *psr; | 235 | struct psr_drv *psr; |
226 | unsigned long flags; | ||
227 | 236 | ||
228 | if (!encoder || !psr_set) | 237 | if (!encoder || !psr_set) |
229 | return -EINVAL; | 238 | return -EINVAL; |
@@ -232,17 +241,17 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, | |||
232 | if (!psr) | 241 | if (!psr) |
233 | return -ENOMEM; | 242 | return -ENOMEM; |
234 | 243 | ||
235 | timer_setup(&psr->flush_timer, psr_flush_handler, 0); | 244 | INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler); |
236 | spin_lock_init(&psr->lock); | 245 | mutex_init(&psr->lock); |
237 | 246 | ||
238 | psr->active = true; | 247 | psr->active = true; |
239 | psr->state = PSR_DISABLE; | 248 | psr->state = PSR_DISABLE; |
240 | psr->encoder = encoder; | 249 | psr->encoder = encoder; |
241 | psr->set = psr_set; | 250 | psr->set = psr_set; |
242 | 251 | ||
243 | spin_lock_irqsave(&drm_drv->psr_list_lock, flags); | 252 | mutex_lock(&drm_drv->psr_list_lock); |
244 | list_add_tail(&psr->list, &drm_drv->psr_list); | 253 | list_add_tail(&psr->list, &drm_drv->psr_list); |
245 | spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags); | 254 | mutex_unlock(&drm_drv->psr_list_lock); |
246 | 255 | ||
247 | return 0; | 256 | return 0; |
248 | } | 257 | } |
@@ -260,16 +269,15 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder) | |||
260 | { | 269 | { |
261 | struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; | 270 | struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; |
262 | struct psr_drv *psr, *n; | 271 | struct psr_drv *psr, *n; |
263 | unsigned long flags; | ||
264 | 272 | ||
265 | spin_lock_irqsave(&drm_drv->psr_list_lock, flags); | 273 | mutex_lock(&drm_drv->psr_list_lock); |
266 | list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { | 274 | list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { |
267 | if (psr->encoder == encoder) { | 275 | if (psr->encoder == encoder) { |
268 | del_timer(&psr->flush_timer); | 276 | cancel_delayed_work_sync(&psr->flush_work); |
269 | list_del(&psr->list); | 277 | list_del(&psr->list); |
270 | kfree(psr); | 278 | kfree(psr); |
271 | } | 279 | } |
272 | } | 280 | } |
273 | spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags); | 281 | mutex_unlock(&drm_drv->psr_list_lock); |
274 | } | 282 | } |
275 | EXPORT_SYMBOL(rockchip_drm_psr_unregister); | 283 | EXPORT_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 index b420cf1bf902..b1ea0155e57c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h | |||
@@ -18,8 +18,8 @@ | |||
18 | void rockchip_drm_psr_flush_all(struct drm_device *dev); | 18 | void rockchip_drm_psr_flush_all(struct drm_device *dev); |
19 | int rockchip_drm_psr_flush(struct drm_crtc *crtc); | 19 | int rockchip_drm_psr_flush(struct drm_crtc *crtc); |
20 | 20 | ||
21 | int rockchip_drm_psr_activate(struct drm_crtc *crtc); | 21 | int rockchip_drm_psr_activate(struct drm_encoder *encoder); |
22 | int rockchip_drm_psr_deactivate(struct drm_crtc *crtc); | 22 | int rockchip_drm_psr_deactivate(struct drm_encoder *encoder); |
23 | 23 | ||
24 | int rockchip_drm_psr_register(struct drm_encoder *encoder, | 24 | int rockchip_drm_psr_register(struct drm_encoder *encoder, |
25 | void (*psr_set)(struct drm_encoder *, bool enable)); | 25 | void (*psr_set)(struct drm_encoder *, bool enable)); |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 66736227c96e..158e79e5062e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -256,6 +256,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, | |||
256 | { | 256 | { |
257 | uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT; | 257 | uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT; |
258 | 258 | ||
259 | if (vskiplines) | ||
260 | *vskiplines = 0; | ||
261 | |||
259 | if (is_horizontal) { | 262 | if (is_horizontal) { |
260 | if (mode == SCALE_UP) | 263 | if (mode == SCALE_UP) |
261 | val = GET_SCL_FT_BIC(src, dst); | 264 | val = GET_SCL_FT_BIC(src, dst); |
@@ -296,7 +299,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, | |||
296 | uint16_t vsu_mode; | 299 | uint16_t vsu_mode; |
297 | uint16_t lb_mode; | 300 | uint16_t lb_mode; |
298 | uint32_t val; | 301 | uint32_t val; |
299 | int vskiplines = 0; | 302 | int vskiplines; |
300 | 303 | ||
301 | if (dst_w > 3840) { | 304 | if (dst_w > 3840) { |
302 | DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); | 305 | DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); |
@@ -566,8 +569,6 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, | |||
566 | 569 | ||
567 | WARN_ON(vop->event); | 570 | WARN_ON(vop->event); |
568 | 571 | ||
569 | rockchip_drm_psr_deactivate(&vop->crtc); | ||
570 | |||
571 | drm_crtc_vblank_off(crtc); | 572 | drm_crtc_vblank_off(crtc); |
572 | 573 | ||
573 | /* | 574 | /* |
@@ -627,7 +628,6 @@ static int vop_plane_atomic_check(struct drm_plane *plane, | |||
627 | struct vop_win *vop_win = to_vop_win(plane); | 628 | struct vop_win *vop_win = to_vop_win(plane); |
628 | const struct vop_win_data *win = vop_win->data; | 629 | const struct vop_win_data *win = vop_win->data; |
629 | int ret; | 630 | int ret; |
630 | struct drm_rect clip = {}; | ||
631 | int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : | 631 | int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : |
632 | DRM_PLANE_HELPER_NO_SCALING; | 632 | DRM_PLANE_HELPER_NO_SCALING; |
633 | int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : | 633 | int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : |
@@ -640,11 +640,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, | |||
640 | if (WARN_ON(!crtc_state)) | 640 | if (WARN_ON(!crtc_state)) |
641 | return -EINVAL; | 641 | return -EINVAL; |
642 | 642 | ||
643 | if (crtc_state->enable) | 643 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
644 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
645 | &clip.x2, &clip.y2); | ||
646 | |||
647 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
648 | min_scale, max_scale, | 644 | min_scale, max_scale, |
649 | true, true); | 645 | true, true); |
650 | if (ret) | 646 | if (ret) |
@@ -939,8 +935,6 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, | |||
939 | clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); | 935 | clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); |
940 | 936 | ||
941 | VOP_REG_SET(vop, common, standby, 0); | 937 | VOP_REG_SET(vop, common, standby, 0); |
942 | |||
943 | rockchip_drm_psr_activate(&vop->crtc); | ||
944 | } | 938 | } |
945 | 939 | ||
946 | static bool vop_fs_irq_is_pending(struct vop *vop) | 940 | static bool vop_fs_irq_is_pending(struct vop *vop) |
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index 8bc7e8418b8d..9ab00a87f7cc 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c | |||
@@ -35,7 +35,6 @@ static int stm_gem_cma_dumb_create(struct drm_file *file, | |||
35 | struct drm_device *dev, | 35 | struct drm_device *dev, |
36 | struct drm_mode_create_dumb *args) | 36 | struct drm_mode_create_dumb *args) |
37 | { | 37 | { |
38 | #ifdef CONFIG_MMU | ||
39 | unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); | 38 | unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); |
40 | 39 | ||
41 | /* | 40 | /* |
@@ -44,7 +43,6 @@ static int stm_gem_cma_dumb_create(struct drm_file *file, | |||
44 | */ | 43 | */ |
45 | args->pitch = roundup(min_pitch, 128); | 44 | args->pitch = roundup(min_pitch, 128); |
46 | args->height = roundup(args->height, 4); | 45 | args->height = roundup(args->height, 4); |
47 | #endif | ||
48 | 46 | ||
49 | return drm_gem_cma_dumb_create_internal(file, dev, args); | 47 | return drm_gem_cma_dumb_create_internal(file, dev, args); |
50 | } | 48 | } |
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 7327da3bc94f..eee6bc0eaf97 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config DRM_SUN4I | 1 | config DRM_SUN4I |
2 | tristate "DRM Support for Allwinner A10 Display Engine" | 2 | tristate "DRM Support for Allwinner A10 Display Engine" |
3 | depends on DRM && ARM && COMMON_CLK | 3 | depends on DRM && (ARM || ARM64) && COMMON_CLK |
4 | depends on ARCH_SUNXI || COMPILE_TEST | 4 | depends on ARCH_SUNXI || COMPILE_TEST |
5 | select DRM_GEM_CMA_HELPER | 5 | select DRM_GEM_CMA_HELPER |
6 | select DRM_KMS_HELPER | 6 | select DRM_KMS_HELPER |
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 1610e748119b..330843ce4280 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile | |||
@@ -12,6 +12,7 @@ sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o | |||
12 | 12 | ||
13 | sun8i-drm-hdmi-y += sun8i_dw_hdmi.o | 13 | sun8i-drm-hdmi-y += sun8i_dw_hdmi.o |
14 | sun8i-drm-hdmi-y += sun8i_hdmi_phy.o | 14 | sun8i-drm-hdmi-y += sun8i_hdmi_phy.o |
15 | sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o | ||
15 | 16 | ||
16 | sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ | 17 | sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ |
17 | sun8i_vi_layer.o sun8i_ui_scaler.o \ | 18 | sun8i_vi_layer.o sun8i_ui_scaler.o \ |
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 245b189fc4d8..092ade4ff6a5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c | |||
@@ -92,13 +92,8 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend, | |||
92 | SUN4I_BACKEND_MODCTL_LAY_EN(layer), val); | 92 | SUN4I_BACKEND_MODCTL_LAY_EN(layer), val); |
93 | } | 93 | } |
94 | 94 | ||
95 | static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, | 95 | static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) |
96 | u32 format, u32 *mode) | ||
97 | { | 96 | { |
98 | if (plane && (plane->type == DRM_PLANE_TYPE_PRIMARY) && | ||
99 | (format == DRM_FORMAT_ARGB8888)) | ||
100 | format = DRM_FORMAT_XRGB8888; | ||
101 | |||
102 | switch (format) { | 97 | switch (format) { |
103 | case DRM_FORMAT_ARGB8888: | 98 | case DRM_FORMAT_ARGB8888: |
104 | *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; | 99 | *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; |
@@ -191,8 +186,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, | |||
191 | DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", | 186 | DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", |
192 | interlaced ? "on" : "off"); | 187 | interlaced ? "on" : "off"); |
193 | 188 | ||
194 | ret = sun4i_backend_drm_format_to_layer(plane, fb->format->format, | 189 | ret = sun4i_backend_drm_format_to_layer(fb->format->format, &val); |
195 | &val); | ||
196 | if (ret) { | 190 | if (ret) { |
197 | DRM_DEBUG_DRIVER("Invalid format\n"); | 191 | DRM_DEBUG_DRIVER("Invalid format\n"); |
198 | return ret; | 192 | return ret; |
@@ -211,7 +205,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend, | |||
211 | u32 val; | 205 | u32 val; |
212 | int ret; | 206 | int ret; |
213 | 207 | ||
214 | ret = sun4i_backend_drm_format_to_layer(NULL, fmt, &val); | 208 | ret = sun4i_backend_drm_format_to_layer(fmt, &val); |
215 | if (ret) { | 209 | if (ret) { |
216 | DRM_DEBUG_DRIVER("Invalid format\n"); | 210 | DRM_DEBUG_DRIVER("Invalid format\n"); |
217 | return ret; | 211 | return ret; |
@@ -275,12 +269,16 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer, | |||
275 | struct drm_plane *plane) | 269 | struct drm_plane *plane) |
276 | { | 270 | { |
277 | struct drm_plane_state *state = plane->state; | 271 | struct drm_plane_state *state = plane->state; |
272 | struct sun4i_layer_state *p_state = state_to_sun4i_layer_state(state); | ||
278 | unsigned int priority = state->normalized_zpos; | 273 | unsigned int priority = state->normalized_zpos; |
274 | unsigned int pipe = p_state->pipe; | ||
279 | 275 | ||
280 | DRM_DEBUG_DRIVER("Setting layer %d's priority to %d\n", layer, priority); | 276 | DRM_DEBUG_DRIVER("Setting layer %d's priority to %d and pipe %d\n", |
281 | 277 | layer, priority, pipe); | |
282 | regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), | 278 | regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), |
279 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK | | ||
283 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK, | 280 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK, |
281 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(p_state->pipe) | | ||
284 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority)); | 282 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority)); |
285 | 283 | ||
286 | return 0; | 284 | return 0; |
@@ -325,12 +323,15 @@ static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, | |||
325 | static int sun4i_backend_atomic_check(struct sunxi_engine *engine, | 323 | static int sun4i_backend_atomic_check(struct sunxi_engine *engine, |
326 | struct drm_crtc_state *crtc_state) | 324 | struct drm_crtc_state *crtc_state) |
327 | { | 325 | { |
326 | struct drm_plane_state *plane_states[SUN4I_BACKEND_NUM_LAYERS] = { 0 }; | ||
328 | struct drm_atomic_state *state = crtc_state->state; | 327 | struct drm_atomic_state *state = crtc_state->state; |
329 | struct drm_device *drm = state->dev; | 328 | struct drm_device *drm = state->dev; |
330 | struct drm_plane *plane; | 329 | struct drm_plane *plane; |
331 | unsigned int num_planes = 0; | 330 | unsigned int num_planes = 0; |
332 | unsigned int num_alpha_planes = 0; | 331 | unsigned int num_alpha_planes = 0; |
333 | unsigned int num_frontend_planes = 0; | 332 | unsigned int num_frontend_planes = 0; |
333 | unsigned int current_pipe = 0; | ||
334 | unsigned int i; | ||
334 | 335 | ||
335 | DRM_DEBUG_DRIVER("Starting checking our planes\n"); | 336 | DRM_DEBUG_DRIVER("Starting checking our planes\n"); |
336 | 337 | ||
@@ -361,9 +362,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, | |||
361 | if (fb->format->has_alpha) | 362 | if (fb->format->has_alpha) |
362 | num_alpha_planes++; | 363 | num_alpha_planes++; |
363 | 364 | ||
365 | DRM_DEBUG_DRIVER("Plane zpos is %d\n", | ||
366 | plane_state->normalized_zpos); | ||
367 | |||
368 | /* Sort our planes by Zpos */ | ||
369 | plane_states[plane_state->normalized_zpos] = plane_state; | ||
370 | |||
364 | num_planes++; | 371 | num_planes++; |
365 | } | 372 | } |
366 | 373 | ||
374 | /* All our planes were disabled, bail out */ | ||
375 | if (!num_planes) | ||
376 | return 0; | ||
377 | |||
367 | /* | 378 | /* |
368 | * The hardware is a bit unusual here. | 379 | * The hardware is a bit unusual here. |
369 | * | 380 | * |
@@ -400,6 +411,25 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, | |||
400 | return -EINVAL; | 411 | return -EINVAL; |
401 | } | 412 | } |
402 | 413 | ||
414 | /* We can't have an alpha plane at the lowest position */ | ||
415 | if (plane_states[0]->fb->format->has_alpha) | ||
416 | return -EINVAL; | ||
417 | |||
418 | for (i = 1; i < num_planes; i++) { | ||
419 | struct drm_plane_state *p_state = plane_states[i]; | ||
420 | struct drm_framebuffer *fb = p_state->fb; | ||
421 | struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(p_state); | ||
422 | |||
423 | /* | ||
424 | * The only alpha position is the lowest plane of the | ||
425 | * second pipe. | ||
426 | */ | ||
427 | if (fb->format->has_alpha) | ||
428 | current_pipe++; | ||
429 | |||
430 | s_state->pipe = current_pipe; | ||
431 | } | ||
432 | |||
403 | if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) { | 433 | if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) { |
404 | DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n"); | 434 | DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n"); |
405 | return -EINVAL; | 435 | return -EINVAL; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 3957c2ff6870..a0f43b81c64c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c | |||
@@ -359,6 +359,7 @@ static const struct of_device_id sun4i_drv_of_table[] = { | |||
359 | { .compatible = "allwinner,sun7i-a20-display-engine" }, | 359 | { .compatible = "allwinner,sun7i-a20-display-engine" }, |
360 | { .compatible = "allwinner,sun8i-a33-display-engine" }, | 360 | { .compatible = "allwinner,sun8i-a33-display-engine" }, |
361 | { .compatible = "allwinner,sun8i-a83t-display-engine" }, | 361 | { .compatible = "allwinner,sun8i-a83t-display-engine" }, |
362 | { .compatible = "allwinner,sun8i-h3-display-engine" }, | ||
362 | { .compatible = "allwinner,sun8i-v3s-display-engine" }, | 363 | { .compatible = "allwinner,sun8i-v3s-display-engine" }, |
363 | { } | 364 | { } |
364 | }; | 365 | }; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 19be798e4fac..33ad377569ec 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c | |||
@@ -19,13 +19,6 @@ | |||
19 | #include "sun4i_layer.h" | 19 | #include "sun4i_layer.h" |
20 | #include "sunxi_engine.h" | 20 | #include "sunxi_engine.h" |
21 | 21 | ||
22 | struct sun4i_plane_desc { | ||
23 | enum drm_plane_type type; | ||
24 | u8 pipe; | ||
25 | const uint32_t *formats; | ||
26 | uint32_t nformats; | ||
27 | }; | ||
28 | |||
29 | static void sun4i_backend_layer_reset(struct drm_plane *plane) | 22 | static void sun4i_backend_layer_reset(struct drm_plane *plane) |
30 | { | 23 | { |
31 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | 24 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); |
@@ -133,14 +126,7 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { | |||
133 | .update_plane = drm_atomic_helper_update_plane, | 126 | .update_plane = drm_atomic_helper_update_plane, |
134 | }; | 127 | }; |
135 | 128 | ||
136 | static const uint32_t sun4i_backend_layer_formats_primary[] = { | 129 | static const uint32_t sun4i_backend_layer_formats[] = { |
137 | DRM_FORMAT_ARGB8888, | ||
138 | DRM_FORMAT_RGB888, | ||
139 | DRM_FORMAT_RGB565, | ||
140 | DRM_FORMAT_XRGB8888, | ||
141 | }; | ||
142 | |||
143 | static const uint32_t sun4i_backend_layer_formats_overlay[] = { | ||
144 | DRM_FORMAT_ARGB8888, | 130 | DRM_FORMAT_ARGB8888, |
145 | DRM_FORMAT_ARGB4444, | 131 | DRM_FORMAT_ARGB4444, |
146 | DRM_FORMAT_ARGB1555, | 132 | DRM_FORMAT_ARGB1555, |
@@ -151,24 +137,9 @@ static const uint32_t sun4i_backend_layer_formats_overlay[] = { | |||
151 | DRM_FORMAT_XRGB8888, | 137 | DRM_FORMAT_XRGB8888, |
152 | }; | 138 | }; |
153 | 139 | ||
154 | static const struct sun4i_plane_desc sun4i_backend_planes[] = { | ||
155 | { | ||
156 | .type = DRM_PLANE_TYPE_PRIMARY, | ||
157 | .pipe = 0, | ||
158 | .formats = sun4i_backend_layer_formats_primary, | ||
159 | .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary), | ||
160 | }, | ||
161 | { | ||
162 | .type = DRM_PLANE_TYPE_OVERLAY, | ||
163 | .pipe = 1, | ||
164 | .formats = sun4i_backend_layer_formats_overlay, | ||
165 | .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay), | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | 140 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, |
170 | struct sun4i_backend *backend, | 141 | struct sun4i_backend *backend, |
171 | const struct sun4i_plane_desc *plane) | 142 | enum drm_plane_type type) |
172 | { | 143 | { |
173 | struct sun4i_layer *layer; | 144 | struct sun4i_layer *layer; |
174 | int ret; | 145 | int ret; |
@@ -180,8 +151,9 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
180 | /* possible crtcs are set later */ | 151 | /* possible crtcs are set later */ |
181 | ret = drm_universal_plane_init(drm, &layer->plane, 0, | 152 | ret = drm_universal_plane_init(drm, &layer->plane, 0, |
182 | &sun4i_backend_layer_funcs, | 153 | &sun4i_backend_layer_funcs, |
183 | plane->formats, plane->nformats, | 154 | sun4i_backend_layer_formats, |
184 | NULL, plane->type, NULL); | 155 | ARRAY_SIZE(sun4i_backend_layer_formats), |
156 | NULL, type, NULL); | ||
185 | if (ret) { | 157 | if (ret) { |
186 | dev_err(drm->dev, "Couldn't initialize layer\n"); | 158 | dev_err(drm->dev, "Couldn't initialize layer\n"); |
187 | return ERR_PTR(ret); | 159 | return ERR_PTR(ret); |
@@ -191,6 +163,9 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
191 | &sun4i_backend_layer_helper_funcs); | 163 | &sun4i_backend_layer_helper_funcs); |
192 | layer->backend = backend; | 164 | layer->backend = backend; |
193 | 165 | ||
166 | drm_plane_create_zpos_property(&layer->plane, 0, 0, | ||
167 | SUN4I_BACKEND_NUM_LAYERS - 1); | ||
168 | |||
194 | return layer; | 169 | return layer; |
195 | } | 170 | } |
196 | 171 | ||
@@ -207,25 +182,17 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm, | |||
207 | if (!planes) | 182 | if (!planes) |
208 | return ERR_PTR(-ENOMEM); | 183 | return ERR_PTR(-ENOMEM); |
209 | 184 | ||
210 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { | 185 | for (i = 0; i < SUN4I_BACKEND_NUM_LAYERS; i++) { |
211 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; | 186 | enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY; |
212 | struct sun4i_layer *layer; | 187 | struct sun4i_layer *layer; |
213 | 188 | ||
214 | layer = sun4i_layer_init_one(drm, backend, plane); | 189 | layer = sun4i_layer_init_one(drm, backend, type); |
215 | if (IS_ERR(layer)) { | 190 | if (IS_ERR(layer)) { |
216 | dev_err(drm->dev, "Couldn't initialize %s plane\n", | 191 | dev_err(drm->dev, "Couldn't initialize %s plane\n", |
217 | i ? "overlay" : "primary"); | 192 | i ? "overlay" : "primary"); |
218 | return ERR_CAST(layer); | 193 | return ERR_CAST(layer); |
219 | }; | 194 | }; |
220 | 195 | ||
221 | drm_plane_create_zpos_immutable_property(&layer->plane, i); | ||
222 | |||
223 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", | ||
224 | i ? "overlay" : "primary", plane->pipe); | ||
225 | regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i), | ||
226 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, | ||
227 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); | ||
228 | |||
229 | layer->id = i; | 196 | layer->id = i; |
230 | planes[i] = &layer->plane; | 197 | planes[i] = &layer->plane; |
231 | }; | 198 | }; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index 75b4868ba87c..36b20265bd31 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h | |||
@@ -24,6 +24,7 @@ struct sun4i_layer { | |||
24 | 24 | ||
25 | struct sun4i_layer_state { | 25 | struct sun4i_layer_state { |
26 | struct drm_plane_state state; | 26 | struct drm_plane_state state; |
27 | unsigned int pipe; | ||
27 | bool uses_frontend; | 28 | bool uses_frontend; |
28 | }; | 29 | }; |
29 | 30 | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index d8d0684fc8aa..79154f0f674a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | |||
@@ -12,11 +12,158 @@ | |||
12 | #include <linux/regmap.h> | 12 | #include <linux/regmap.h> |
13 | #include <linux/reset.h> | 13 | #include <linux/reset.h> |
14 | 14 | ||
15 | #define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000 | ||
16 | #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0) | ||
17 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8) | ||
18 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC BIT(8) | ||
19 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC BIT(9) | ||
20 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16) | ||
21 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16) | ||
22 | |||
23 | #define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004 | ||
24 | #define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31) | ||
25 | |||
26 | #define SUN8I_HDMI_PHY_READ_EN_REG 0x0010 | ||
27 | #define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545 | ||
28 | |||
29 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014 | ||
30 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47 | ||
31 | |||
32 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG 0x0020 | ||
33 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_SWI BIT(31) | ||
34 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWEND BIT(30) | ||
35 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWENC BIT(29) | ||
36 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW BIT(28) | ||
37 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVRCAL(x) ((x) << 26) | ||
38 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(x) ((x) << 24) | ||
39 | #define SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT BIT(23) | ||
40 | #define SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT BIT(22) | ||
41 | #define SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT BIT(21) | ||
42 | #define SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT BIT(20) | ||
43 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL BIT(19) | ||
44 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG BIT(18) | ||
45 | #define SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS BIT(17) | ||
46 | #define SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN BIT(16) | ||
47 | #define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK GENMASK(15, 12) | ||
48 | #define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL (0xf << 12) | ||
49 | #define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK BIT(11) | ||
50 | #define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 BIT(10) | ||
51 | #define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 BIT(9) | ||
52 | #define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 BIT(8) | ||
53 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK BIT(7) | ||
54 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 BIT(6) | ||
55 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 BIT(5) | ||
56 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 BIT(4) | ||
57 | #define SUN8I_HDMI_PHY_ANA_CFG1_CKEN BIT(3) | ||
58 | #define SUN8I_HDMI_PHY_ANA_CFG1_LDOEN BIT(2) | ||
59 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENVBS BIT(1) | ||
60 | #define SUN8I_HDMI_PHY_ANA_CFG1_ENBI BIT(0) | ||
61 | |||
62 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG 0x0024 | ||
63 | #define SUN8I_HDMI_PHY_ANA_CFG2_M_EN BIT(31) | ||
64 | #define SUN8I_HDMI_PHY_ANA_CFG2_PLLDBEN BIT(30) | ||
65 | #define SUN8I_HDMI_PHY_ANA_CFG2_SEN BIT(29) | ||
66 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDPD BIT(28) | ||
67 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDEN BIT(27) | ||
68 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLRCK BIT(26) | ||
69 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLR(x) ((x) << 23) | ||
70 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK BIT(22) | ||
71 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN BIT(21) | ||
72 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_CD(x) ((x) << 19) | ||
73 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(x) ((x) << 17) | ||
74 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK BIT(16) | ||
75 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW BIT(15) | ||
76 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(x) ((x) << 13) | ||
77 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(x) ((x) << 10) | ||
78 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOSTCK(x) ((x) << 8) | ||
79 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOST(x) ((x) << 6) | ||
80 | #define SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(x) ((x) << 0) | ||
81 | |||
82 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG 0x0028 | ||
83 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOWCK(x) ((x) << 30) | ||
84 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOW(x) ((x) << 28) | ||
85 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(x) ((x) << 18) | ||
86 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(x) ((x) << 14) | ||
87 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMPCK(x) ((x) << 11) | ||
88 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(x) ((x) << 7) | ||
89 | #define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(x) ((x) << 4) | ||
90 | #define SUN8I_HDMI_PHY_ANA_CFG3_SDAPD BIT(3) | ||
91 | #define SUN8I_HDMI_PHY_ANA_CFG3_SDAEN BIT(2) | ||
92 | #define SUN8I_HDMI_PHY_ANA_CFG3_SCLPD BIT(1) | ||
93 | #define SUN8I_HDMI_PHY_ANA_CFG3_SCLEN BIT(0) | ||
94 | |||
95 | #define SUN8I_HDMI_PHY_PLL_CFG1_REG 0x002c | ||
96 | #define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 BIT(31) | ||
97 | #define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD BIT(30) | ||
98 | #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29) | ||
99 | #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28) | ||
100 | #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27) | ||
101 | #define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26) | ||
102 | #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25) | ||
103 | #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22) | ||
104 | #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20) | ||
105 | #define SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN BIT(19) | ||
106 | #define SUN8I_HDMI_PHY_PLL_CFG1_CS BIT(18) | ||
107 | #define SUN8I_HDMI_PHY_PLL_CFG1_CP_S(x) ((x) << 13) | ||
108 | #define SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(x) ((x) << 7) | ||
109 | #define SUN8I_HDMI_PHY_PLL_CFG1_BWS BIT(6) | ||
110 | #define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK GENMASK(5, 0) | ||
111 | #define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT 0 | ||
112 | |||
113 | #define SUN8I_HDMI_PHY_PLL_CFG2_REG 0x0030 | ||
114 | #define SUN8I_HDMI_PHY_PLL_CFG2_SV_H BIT(31) | ||
115 | #define SUN8I_HDMI_PHY_PLL_CFG2_PDCLKSEL(x) ((x) << 29) | ||
116 | #define SUN8I_HDMI_PHY_PLL_CFG2_CLKSTEP(x) ((x) << 27) | ||
117 | #define SUN8I_HDMI_PHY_PLL_CFG2_PSET(x) ((x) << 24) | ||
118 | #define SUN8I_HDMI_PHY_PLL_CFG2_PCLK_SEL BIT(23) | ||
119 | #define SUN8I_HDMI_PHY_PLL_CFG2_AUTOSYNC_DIS BIT(22) | ||
120 | #define SUN8I_HDMI_PHY_PLL_CFG2_VREG2_OUT_EN BIT(21) | ||
121 | #define SUN8I_HDMI_PHY_PLL_CFG2_VREG1_OUT_EN BIT(20) | ||
122 | #define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN BIT(19) | ||
123 | #define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN(x) ((x) << 16) | ||
124 | #define SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(x) ((x) << 12) | ||
125 | #define SUN8I_HDMI_PHY_PLL_CFG2_VCO_RST_IN BIT(11) | ||
126 | #define SUN8I_HDMI_PHY_PLL_CFG2_SINT_FRAC BIT(10) | ||
127 | #define SUN8I_HDMI_PHY_PLL_CFG2_SDIV2 BIT(9) | ||
128 | #define SUN8I_HDMI_PHY_PLL_CFG2_S(x) ((x) << 6) | ||
129 | #define SUN8I_HDMI_PHY_PLL_CFG2_S6P25_7P5 BIT(5) | ||
130 | #define SUN8I_HDMI_PHY_PLL_CFG2_S5_7 BIT(4) | ||
131 | #define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK GENMASK(3, 0) | ||
132 | #define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_SHIFT 0 | ||
133 | #define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV(x) (((x) - 1) << 0) | ||
134 | |||
135 | #define SUN8I_HDMI_PHY_PLL_CFG3_REG 0x0034 | ||
136 | #define SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2 BIT(0) | ||
137 | |||
138 | #define SUN8I_HDMI_PHY_ANA_STS_REG 0x0038 | ||
139 | #define SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT 11 | ||
140 | #define SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK GENMASK(16, 11) | ||
141 | #define SUN8I_HDMI_PHY_ANA_STS_RCALEND2D BIT(7) | ||
142 | #define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK GENMASK(5, 0) | ||
143 | |||
144 | #define SUN8I_HDMI_PHY_CEC_REG 0x003c | ||
145 | |||
146 | struct sun8i_hdmi_phy; | ||
147 | |||
148 | struct sun8i_hdmi_phy_variant { | ||
149 | bool has_phy_clk; | ||
150 | void (*phy_init)(struct sun8i_hdmi_phy *phy); | ||
151 | void (*phy_disable)(struct dw_hdmi *hdmi, | ||
152 | struct sun8i_hdmi_phy *phy); | ||
153 | int (*phy_config)(struct dw_hdmi *hdmi, | ||
154 | struct sun8i_hdmi_phy *phy, | ||
155 | unsigned int clk_rate); | ||
156 | }; | ||
157 | |||
15 | struct sun8i_hdmi_phy { | 158 | struct sun8i_hdmi_phy { |
16 | struct clk *clk_bus; | 159 | struct clk *clk_bus; |
17 | struct clk *clk_mod; | 160 | struct clk *clk_mod; |
18 | struct regmap *regs; | 161 | struct clk *clk_phy; |
19 | struct reset_control *rst_phy; | 162 | struct clk *clk_pll0; |
163 | unsigned int rcal; | ||
164 | struct regmap *regs; | ||
165 | struct reset_control *rst_phy; | ||
166 | struct sun8i_hdmi_phy_variant *variant; | ||
20 | }; | 167 | }; |
21 | 168 | ||
22 | struct sun8i_dw_hdmi { | 169 | struct sun8i_dw_hdmi { |
@@ -41,4 +188,6 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi); | |||
41 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); | 188 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); |
42 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void); | 189 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void); |
43 | 190 | ||
191 | int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev); | ||
192 | |||
44 | #endif /* _SUN8I_DW_HDMI_H_ */ | 193 | #endif /* _SUN8I_DW_HDMI_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index e5bfcdd43ec9..5a52fc489a9d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | |||
@@ -3,47 +3,21 @@ | |||
3 | * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> | 3 | * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/delay.h> | ||
6 | #include <linux/of_address.h> | 7 | #include <linux/of_address.h> |
7 | 8 | ||
8 | #include "sun8i_dw_hdmi.h" | 9 | #include "sun8i_dw_hdmi.h" |
9 | 10 | ||
10 | #define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000 | ||
11 | #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0) | ||
12 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8) | ||
13 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL(val) (val << 8) | ||
14 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16) | ||
15 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16) | ||
16 | |||
17 | #define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004 | ||
18 | #define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31) | ||
19 | |||
20 | #define SUN8I_HDMI_PHY_READ_EN_REG 0x0010 | ||
21 | #define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545 | ||
22 | |||
23 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014 | ||
24 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47 | ||
25 | |||
26 | /* | 11 | /* |
27 | * Address can be actually any value. Here is set to same value as | 12 | * Address can be actually any value. Here is set to same value as |
28 | * it is set in BSP driver. | 13 | * it is set in BSP driver. |
29 | */ | 14 | */ |
30 | #define I2C_ADDR 0x69 | 15 | #define I2C_ADDR 0x69 |
31 | 16 | ||
32 | static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, | 17 | static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi, |
33 | struct drm_display_mode *mode) | 18 | struct sun8i_hdmi_phy *phy, |
19 | unsigned int clk_rate) | ||
34 | { | 20 | { |
35 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; | ||
36 | u32 val = 0; | ||
37 | |||
38 | if ((mode->flags & DRM_MODE_FLAG_NHSYNC) && | ||
39 | (mode->flags & DRM_MODE_FLAG_NHSYNC)) { | ||
40 | val = 0x03; | ||
41 | } | ||
42 | |||
43 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | ||
44 | SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, | ||
45 | SUN8I_HDMI_PHY_DBG_CTRL_POL(val)); | ||
46 | |||
47 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, | 21 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, |
48 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, | 22 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, |
49 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN); | 23 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN); |
@@ -63,21 +37,21 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, | |||
63 | * release any documentation, explanation of this values can | 37 | * release any documentation, explanation of this values can |
64 | * be found in i.MX 6Dual/6Quad Reference Manual. | 38 | * be found in i.MX 6Dual/6Quad Reference Manual. |
65 | */ | 39 | */ |
66 | if (mode->crtc_clock <= 27000) { | 40 | if (clk_rate <= 27000000) { |
67 | dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06); | 41 | dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06); |
68 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); | 42 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); |
69 | dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10); | 43 | dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10); |
70 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); | 44 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); |
71 | dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e); | 45 | dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e); |
72 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); | 46 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); |
73 | } else if (mode->crtc_clock <= 74250) { | 47 | } else if (clk_rate <= 74250000) { |
74 | dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06); | 48 | dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06); |
75 | dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); | 49 | dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); |
76 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); | 50 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); |
77 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); | 51 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); |
78 | dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e); | 52 | dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e); |
79 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); | 53 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); |
80 | } else if (mode->crtc_clock <= 148500) { | 54 | } else if (clk_rate <= 148500000) { |
81 | dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06); | 55 | dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06); |
82 | dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); | 56 | dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); |
83 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); | 57 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); |
@@ -100,12 +74,173 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, | |||
100 | dw_hdmi_phy_gen2_txpwron(hdmi, 1); | 74 | dw_hdmi_phy_gen2_txpwron(hdmi, 1); |
101 | 75 | ||
102 | return 0; | 76 | return 0; |
103 | }; | 77 | } |
104 | 78 | ||
105 | static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | 79 | static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, |
80 | struct sun8i_hdmi_phy *phy, | ||
81 | unsigned int clk_rate) | ||
82 | { | ||
83 | u32 pll_cfg1_init; | ||
84 | u32 pll_cfg2_init; | ||
85 | u32 ana_cfg1_end; | ||
86 | u32 ana_cfg2_init; | ||
87 | u32 ana_cfg3_init; | ||
88 | u32 b_offset = 0; | ||
89 | u32 val; | ||
90 | |||
91 | /* bandwidth / frequency independent settings */ | ||
92 | |||
93 | pll_cfg1_init = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN | | ||
94 | SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN | | ||
95 | SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(7) | | ||
96 | SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(1) | | ||
97 | SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN | | ||
98 | SUN8I_HDMI_PHY_PLL_CFG1_CS | | ||
99 | SUN8I_HDMI_PHY_PLL_CFG1_CP_S(2) | | ||
100 | SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63) | | ||
101 | SUN8I_HDMI_PHY_PLL_CFG1_BWS; | ||
102 | |||
103 | pll_cfg2_init = SUN8I_HDMI_PHY_PLL_CFG2_SV_H | | ||
104 | SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN | | ||
105 | SUN8I_HDMI_PHY_PLL_CFG2_SDIV2; | ||
106 | |||
107 | ana_cfg1_end = SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(1) | | ||
108 | SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT | | ||
109 | SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT | | ||
110 | SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT | | ||
111 | SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT | | ||
112 | SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL | | ||
113 | SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG | | ||
114 | SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS | | ||
115 | SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN | | ||
116 | SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK | | ||
117 | SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL | | ||
118 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK | | ||
119 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | | ||
120 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | | ||
121 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | | ||
122 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 | | ||
123 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | | ||
124 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | | ||
125 | SUN8I_HDMI_PHY_ANA_CFG1_CKEN | | ||
126 | SUN8I_HDMI_PHY_ANA_CFG1_LDOEN | | ||
127 | SUN8I_HDMI_PHY_ANA_CFG1_ENVBS | | ||
128 | SUN8I_HDMI_PHY_ANA_CFG1_ENBI; | ||
129 | |||
130 | ana_cfg2_init = SUN8I_HDMI_PHY_ANA_CFG2_M_EN | | ||
131 | SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK | | ||
132 | SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN | | ||
133 | SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(1) | | ||
134 | SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(1); | ||
135 | |||
136 | ana_cfg3_init = SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(0x3e0) | | ||
137 | SUN8I_HDMI_PHY_ANA_CFG3_SDAEN | | ||
138 | SUN8I_HDMI_PHY_ANA_CFG3_SCLEN; | ||
139 | |||
140 | /* bandwidth / frequency dependent settings */ | ||
141 | if (clk_rate <= 27000000) { | ||
142 | pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | | ||
143 | SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); | ||
144 | pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | | ||
145 | SUN8I_HDMI_PHY_PLL_CFG2_S(4); | ||
146 | ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW; | ||
147 | ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) | | ||
148 | SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal); | ||
149 | ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(3) | | ||
150 | SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(5); | ||
151 | } else if (clk_rate <= 74250000) { | ||
152 | pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | | ||
153 | SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); | ||
154 | pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | | ||
155 | SUN8I_HDMI_PHY_PLL_CFG2_S(5); | ||
156 | ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW; | ||
157 | ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) | | ||
158 | SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal); | ||
159 | ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(5) | | ||
160 | SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(7); | ||
161 | } else if (clk_rate <= 148500000) { | ||
162 | pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | | ||
163 | SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); | ||
164 | pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | | ||
165 | SUN8I_HDMI_PHY_PLL_CFG2_S(6); | ||
166 | ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK | | ||
167 | SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW | | ||
168 | SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(2); | ||
169 | ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(7) | | ||
170 | SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(9); | ||
171 | } else { | ||
172 | b_offset = 2; | ||
173 | pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63); | ||
174 | pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(6) | | ||
175 | SUN8I_HDMI_PHY_PLL_CFG2_S(7); | ||
176 | ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK | | ||
177 | SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW | | ||
178 | SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4); | ||
179 | ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) | | ||
180 | SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13); | ||
181 | } | ||
182 | |||
183 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
184 | SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0); | ||
185 | |||
186 | regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init); | ||
187 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, | ||
188 | (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK, | ||
189 | pll_cfg2_init); | ||
190 | usleep_range(10000, 15000); | ||
191 | regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG3_REG, | ||
192 | SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2); | ||
193 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, | ||
194 | SUN8I_HDMI_PHY_PLL_CFG1_PLLEN, | ||
195 | SUN8I_HDMI_PHY_PLL_CFG1_PLLEN); | ||
196 | msleep(100); | ||
197 | |||
198 | /* get B value */ | ||
199 | regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); | ||
200 | val = (val & SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK) >> | ||
201 | SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT; | ||
202 | val = min(val + b_offset, (u32)0x3f); | ||
203 | |||
204 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, | ||
205 | SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 | | ||
206 | SUN8I_HDMI_PHY_PLL_CFG1_REG_OD, | ||
207 | SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 | | ||
208 | SUN8I_HDMI_PHY_PLL_CFG1_REG_OD); | ||
209 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, | ||
210 | SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK, | ||
211 | val << SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT); | ||
212 | msleep(100); | ||
213 | regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, ana_cfg1_end); | ||
214 | regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG2_REG, ana_cfg2_init); | ||
215 | regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, ana_cfg3_init); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, | ||
221 | struct drm_display_mode *mode) | ||
106 | { | 222 | { |
107 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; | 223 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; |
224 | u32 val = 0; | ||
225 | |||
226 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
227 | val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC; | ||
228 | |||
229 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
230 | val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC; | ||
108 | 231 | ||
232 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | ||
233 | SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val); | ||
234 | |||
235 | if (phy->variant->has_phy_clk) | ||
236 | clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000); | ||
237 | |||
238 | return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000); | ||
239 | }; | ||
240 | |||
241 | static void sun8i_hdmi_phy_disable_a83t(struct dw_hdmi *hdmi, | ||
242 | struct sun8i_hdmi_phy *phy) | ||
243 | { | ||
109 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); | 244 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); |
110 | dw_hdmi_phy_gen2_pddq(hdmi, 1); | 245 | dw_hdmi_phy_gen2_pddq(hdmi, 1); |
111 | 246 | ||
@@ -113,6 +248,23 @@ static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | |||
113 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0); | 248 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0); |
114 | } | 249 | } |
115 | 250 | ||
251 | static void sun8i_hdmi_phy_disable_h3(struct dw_hdmi *hdmi, | ||
252 | struct sun8i_hdmi_phy *phy) | ||
253 | { | ||
254 | regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
255 | SUN8I_HDMI_PHY_ANA_CFG1_LDOEN | | ||
256 | SUN8I_HDMI_PHY_ANA_CFG1_ENVBS | | ||
257 | SUN8I_HDMI_PHY_ANA_CFG1_ENBI); | ||
258 | regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0); | ||
259 | } | ||
260 | |||
261 | static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | ||
262 | { | ||
263 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; | ||
264 | |||
265 | phy->variant->phy_disable(hdmi, phy); | ||
266 | } | ||
267 | |||
116 | static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = { | 268 | static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = { |
117 | .init = &sun8i_hdmi_phy_config, | 269 | .init = &sun8i_hdmi_phy_config, |
118 | .disable = &sun8i_hdmi_phy_disable, | 270 | .disable = &sun8i_hdmi_phy_disable, |
@@ -121,16 +273,8 @@ static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = { | |||
121 | .setup_hpd = &dw_hdmi_phy_setup_hpd, | 273 | .setup_hpd = &dw_hdmi_phy_setup_hpd, |
122 | }; | 274 | }; |
123 | 275 | ||
124 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) | 276 | static void sun8i_hdmi_phy_init_a83t(struct sun8i_hdmi_phy *phy) |
125 | { | 277 | { |
126 | /* enable read access to HDMI controller */ | ||
127 | regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG, | ||
128 | SUN8I_HDMI_PHY_READ_EN_MAGIC); | ||
129 | |||
130 | /* unscramble register offsets */ | ||
131 | regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG, | ||
132 | SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC); | ||
133 | |||
134 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | 278 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, |
135 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK, | 279 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK, |
136 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK); | 280 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK); |
@@ -144,6 +288,91 @@ void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) | |||
144 | SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR)); | 288 | SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR)); |
145 | } | 289 | } |
146 | 290 | ||
291 | static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy) | ||
292 | { | ||
293 | unsigned int val; | ||
294 | |||
295 | regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 0); | ||
296 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
297 | SUN8I_HDMI_PHY_ANA_CFG1_ENBI, | ||
298 | SUN8I_HDMI_PHY_ANA_CFG1_ENBI); | ||
299 | udelay(5); | ||
300 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
301 | SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN, | ||
302 | SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN); | ||
303 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
304 | SUN8I_HDMI_PHY_ANA_CFG1_ENVBS, | ||
305 | SUN8I_HDMI_PHY_ANA_CFG1_ENVBS); | ||
306 | usleep_range(10, 20); | ||
307 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
308 | SUN8I_HDMI_PHY_ANA_CFG1_LDOEN, | ||
309 | SUN8I_HDMI_PHY_ANA_CFG1_LDOEN); | ||
310 | udelay(5); | ||
311 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
312 | SUN8I_HDMI_PHY_ANA_CFG1_CKEN, | ||
313 | SUN8I_HDMI_PHY_ANA_CFG1_CKEN); | ||
314 | usleep_range(40, 100); | ||
315 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
316 | SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL, | ||
317 | SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL); | ||
318 | usleep_range(100, 200); | ||
319 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
320 | SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG, | ||
321 | SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG); | ||
322 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
323 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | | ||
324 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | | ||
325 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2, | ||
326 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | | ||
327 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | | ||
328 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2); | ||
329 | |||
330 | /* wait for calibration to finish */ | ||
331 | regmap_read_poll_timeout(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, val, | ||
332 | (val & SUN8I_HDMI_PHY_ANA_STS_RCALEND2D), | ||
333 | 100, 2000); | ||
334 | |||
335 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
336 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK, | ||
337 | SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK); | ||
338 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, | ||
339 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | | ||
340 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | | ||
341 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | | ||
342 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK, | ||
343 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | | ||
344 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | | ||
345 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | | ||
346 | SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK); | ||
347 | |||
348 | /* enable DDC communication */ | ||
349 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, | ||
350 | SUN8I_HDMI_PHY_ANA_CFG3_SCLEN | | ||
351 | SUN8I_HDMI_PHY_ANA_CFG3_SDAEN, | ||
352 | SUN8I_HDMI_PHY_ANA_CFG3_SCLEN | | ||
353 | SUN8I_HDMI_PHY_ANA_CFG3_SDAEN); | ||
354 | |||
355 | /* set HW control of CEC pins */ | ||
356 | regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0); | ||
357 | |||
358 | /* read calibration data */ | ||
359 | regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); | ||
360 | phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2; | ||
361 | } | ||
362 | |||
363 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) | ||
364 | { | ||
365 | /* enable read access to HDMI controller */ | ||
366 | regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG, | ||
367 | SUN8I_HDMI_PHY_READ_EN_MAGIC); | ||
368 | |||
369 | /* unscramble register offsets */ | ||
370 | regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG, | ||
371 | SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC); | ||
372 | |||
373 | phy->variant->phy_init(phy); | ||
374 | } | ||
375 | |||
147 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void) | 376 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void) |
148 | { | 377 | { |
149 | return &sun8i_hdmi_phy_ops; | 378 | return &sun8i_hdmi_phy_ops; |
@@ -153,24 +382,46 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = { | |||
153 | .reg_bits = 32, | 382 | .reg_bits = 32, |
154 | .val_bits = 32, | 383 | .val_bits = 32, |
155 | .reg_stride = 4, | 384 | .reg_stride = 4, |
156 | .max_register = SUN8I_HDMI_PHY_UNSCRAMBLE_REG, | 385 | .max_register = SUN8I_HDMI_PHY_CEC_REG, |
157 | .name = "phy" | 386 | .name = "phy" |
158 | }; | 387 | }; |
159 | 388 | ||
389 | static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = { | ||
390 | .phy_init = &sun8i_hdmi_phy_init_a83t, | ||
391 | .phy_disable = &sun8i_hdmi_phy_disable_a83t, | ||
392 | .phy_config = &sun8i_hdmi_phy_config_a83t, | ||
393 | }; | ||
394 | |||
395 | static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = { | ||
396 | .has_phy_clk = true, | ||
397 | .phy_init = &sun8i_hdmi_phy_init_h3, | ||
398 | .phy_disable = &sun8i_hdmi_phy_disable_h3, | ||
399 | .phy_config = &sun8i_hdmi_phy_config_h3, | ||
400 | }; | ||
401 | |||
160 | static const struct of_device_id sun8i_hdmi_phy_of_table[] = { | 402 | static const struct of_device_id sun8i_hdmi_phy_of_table[] = { |
161 | { .compatible = "allwinner,sun8i-a83t-hdmi-phy" }, | 403 | { |
404 | .compatible = "allwinner,sun8i-a83t-hdmi-phy", | ||
405 | .data = &sun8i_a83t_hdmi_phy, | ||
406 | }, | ||
407 | { | ||
408 | .compatible = "allwinner,sun8i-h3-hdmi-phy", | ||
409 | .data = &sun8i_h3_hdmi_phy, | ||
410 | }, | ||
162 | { /* sentinel */ } | 411 | { /* sentinel */ } |
163 | }; | 412 | }; |
164 | 413 | ||
165 | int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) | 414 | int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) |
166 | { | 415 | { |
416 | const struct of_device_id *match; | ||
167 | struct device *dev = hdmi->dev; | 417 | struct device *dev = hdmi->dev; |
168 | struct sun8i_hdmi_phy *phy; | 418 | struct sun8i_hdmi_phy *phy; |
169 | struct resource res; | 419 | struct resource res; |
170 | void __iomem *regs; | 420 | void __iomem *regs; |
171 | int ret; | 421 | int ret; |
172 | 422 | ||
173 | if (!of_match_node(sun8i_hdmi_phy_of_table, node)) { | 423 | match = of_match_node(sun8i_hdmi_phy_of_table, node); |
424 | if (!match) { | ||
174 | dev_err(dev, "Incompatible HDMI PHY\n"); | 425 | dev_err(dev, "Incompatible HDMI PHY\n"); |
175 | return -EINVAL; | 426 | return -EINVAL; |
176 | } | 427 | } |
@@ -179,6 +430,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) | |||
179 | if (!phy) | 430 | if (!phy) |
180 | return -ENOMEM; | 431 | return -ENOMEM; |
181 | 432 | ||
433 | phy->variant = (struct sun8i_hdmi_phy_variant *)match->data; | ||
434 | |||
182 | ret = of_address_to_resource(node, 0, &res); | 435 | ret = of_address_to_resource(node, 0, &res); |
183 | if (ret) { | 436 | if (ret) { |
184 | dev_err(dev, "phy: Couldn't get our resources\n"); | 437 | dev_err(dev, "phy: Couldn't get our resources\n"); |
@@ -211,11 +464,26 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) | |||
211 | goto err_put_clk_bus; | 464 | goto err_put_clk_bus; |
212 | } | 465 | } |
213 | 466 | ||
467 | if (phy->variant->has_phy_clk) { | ||
468 | phy->clk_pll0 = of_clk_get_by_name(node, "pll-0"); | ||
469 | if (IS_ERR(phy->clk_pll0)) { | ||
470 | dev_err(dev, "Could not get pll-0 clock\n"); | ||
471 | ret = PTR_ERR(phy->clk_pll0); | ||
472 | goto err_put_clk_mod; | ||
473 | } | ||
474 | |||
475 | ret = sun8i_phy_clk_create(phy, dev); | ||
476 | if (ret) { | ||
477 | dev_err(dev, "Couldn't create the PHY clock\n"); | ||
478 | goto err_put_clk_pll0; | ||
479 | } | ||
480 | } | ||
481 | |||
214 | phy->rst_phy = of_reset_control_get_shared(node, "phy"); | 482 | phy->rst_phy = of_reset_control_get_shared(node, "phy"); |
215 | if (IS_ERR(phy->rst_phy)) { | 483 | if (IS_ERR(phy->rst_phy)) { |
216 | dev_err(dev, "Could not get phy reset control\n"); | 484 | dev_err(dev, "Could not get phy reset control\n"); |
217 | ret = PTR_ERR(phy->rst_phy); | 485 | ret = PTR_ERR(phy->rst_phy); |
218 | goto err_put_clk_mod; | 486 | goto err_put_clk_pll0; |
219 | } | 487 | } |
220 | 488 | ||
221 | ret = reset_control_deassert(phy->rst_phy); | 489 | ret = reset_control_deassert(phy->rst_phy); |
@@ -246,6 +514,9 @@ err_deassert_rst_phy: | |||
246 | reset_control_assert(phy->rst_phy); | 514 | reset_control_assert(phy->rst_phy); |
247 | err_put_rst_phy: | 515 | err_put_rst_phy: |
248 | reset_control_put(phy->rst_phy); | 516 | reset_control_put(phy->rst_phy); |
517 | err_put_clk_pll0: | ||
518 | if (phy->variant->has_phy_clk) | ||
519 | clk_put(phy->clk_pll0); | ||
249 | err_put_clk_mod: | 520 | err_put_clk_mod: |
250 | clk_put(phy->clk_mod); | 521 | clk_put(phy->clk_mod); |
251 | err_put_clk_bus: | 522 | err_put_clk_bus: |
@@ -265,6 +536,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi) | |||
265 | 536 | ||
266 | reset_control_put(phy->rst_phy); | 537 | reset_control_put(phy->rst_phy); |
267 | 538 | ||
539 | if (phy->variant->has_phy_clk) | ||
540 | clk_put(phy->clk_pll0); | ||
268 | clk_put(phy->clk_mod); | 541 | clk_put(phy->clk_mod); |
269 | clk_put(phy->clk_bus); | 542 | clk_put(phy->clk_bus); |
270 | } | 543 | } |
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c new file mode 100644 index 000000000000..faea449812f8 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | |||
@@ -0,0 +1,132 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/clk-provider.h> | ||
7 | |||
8 | #include "sun8i_dw_hdmi.h" | ||
9 | |||
10 | struct sun8i_phy_clk { | ||
11 | struct clk_hw hw; | ||
12 | struct sun8i_hdmi_phy *phy; | ||
13 | }; | ||
14 | |||
15 | static inline struct sun8i_phy_clk *hw_to_phy_clk(struct clk_hw *hw) | ||
16 | { | ||
17 | return container_of(hw, struct sun8i_phy_clk, hw); | ||
18 | } | ||
19 | |||
20 | static int sun8i_phy_clk_determine_rate(struct clk_hw *hw, | ||
21 | struct clk_rate_request *req) | ||
22 | { | ||
23 | unsigned long rate = req->rate; | ||
24 | unsigned long best_rate = 0; | ||
25 | struct clk_hw *parent; | ||
26 | int best_div = 1; | ||
27 | int i; | ||
28 | |||
29 | parent = clk_hw_get_parent(hw); | ||
30 | |||
31 | for (i = 1; i <= 16; i++) { | ||
32 | unsigned long ideal = rate * i; | ||
33 | unsigned long rounded; | ||
34 | |||
35 | rounded = clk_hw_round_rate(parent, ideal); | ||
36 | |||
37 | if (rounded == ideal) { | ||
38 | best_rate = rounded; | ||
39 | best_div = i; | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | if (!best_rate || | ||
44 | abs(rate - rounded / i) < | ||
45 | abs(rate - best_rate / best_div)) { | ||
46 | best_rate = rounded; | ||
47 | best_div = i; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | req->rate = best_rate / best_div; | ||
52 | req->best_parent_rate = best_rate; | ||
53 | req->best_parent_hw = parent; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static unsigned long sun8i_phy_clk_recalc_rate(struct clk_hw *hw, | ||
59 | unsigned long parent_rate) | ||
60 | { | ||
61 | struct sun8i_phy_clk *priv = hw_to_phy_clk(hw); | ||
62 | u32 reg; | ||
63 | |||
64 | regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, ®); | ||
65 | reg = ((reg >> SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_SHIFT) & | ||
66 | SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK) + 1; | ||
67 | |||
68 | return parent_rate / reg; | ||
69 | } | ||
70 | |||
71 | static int sun8i_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
72 | unsigned long parent_rate) | ||
73 | { | ||
74 | struct sun8i_phy_clk *priv = hw_to_phy_clk(hw); | ||
75 | unsigned long best_rate = 0; | ||
76 | u8 best_m = 0, m; | ||
77 | |||
78 | for (m = 1; m <= 16; m++) { | ||
79 | unsigned long tmp_rate = parent_rate / m; | ||
80 | |||
81 | if (tmp_rate > rate) | ||
82 | continue; | ||
83 | |||
84 | if (!best_rate || | ||
85 | (rate - tmp_rate) < (rate - best_rate)) { | ||
86 | best_rate = tmp_rate; | ||
87 | best_m = m; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, | ||
92 | SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK, | ||
93 | SUN8I_HDMI_PHY_PLL_CFG2_PREDIV(best_m)); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static const struct clk_ops sun8i_phy_clk_ops = { | ||
99 | .determine_rate = sun8i_phy_clk_determine_rate, | ||
100 | .recalc_rate = sun8i_phy_clk_recalc_rate, | ||
101 | .set_rate = sun8i_phy_clk_set_rate, | ||
102 | }; | ||
103 | |||
104 | int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev) | ||
105 | { | ||
106 | struct clk_init_data init; | ||
107 | struct sun8i_phy_clk *priv; | ||
108 | const char *parents[1]; | ||
109 | |||
110 | parents[0] = __clk_get_name(phy->clk_pll0); | ||
111 | if (!parents[0]) | ||
112 | return -ENODEV; | ||
113 | |||
114 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
115 | if (!priv) | ||
116 | return -ENOMEM; | ||
117 | |||
118 | init.name = "hdmi-phy-clk"; | ||
119 | init.ops = &sun8i_phy_clk_ops; | ||
120 | init.parent_names = parents; | ||
121 | init.num_parents = 1; | ||
122 | init.flags = CLK_SET_RATE_PARENT; | ||
123 | |||
124 | priv->phy = phy; | ||
125 | priv->hw.init = &init; | ||
126 | |||
127 | phy->clk_phy = devm_clk_register(dev, &priv->hw); | ||
128 | if (IS_ERR(phy->clk_phy)) | ||
129 | return PTR_ERR(phy->clk_phy); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 9b0256d31a61..126899d6f0d3 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c | |||
@@ -492,6 +492,14 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { | |||
492 | .vi_num = 1, | 492 | .vi_num = 1, |
493 | }; | 493 | }; |
494 | 494 | ||
495 | static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { | ||
496 | .ccsc = 0, | ||
497 | .mod_rate = 432000000, | ||
498 | .scaler_mask = 0xf, | ||
499 | .ui_num = 3, | ||
500 | .vi_num = 1, | ||
501 | }; | ||
502 | |||
495 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { | 503 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { |
496 | .vi_num = 2, | 504 | .vi_num = 2, |
497 | .ui_num = 1, | 505 | .ui_num = 1, |
@@ -510,6 +518,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { | |||
510 | .data = &sun8i_a83t_mixer1_cfg, | 518 | .data = &sun8i_a83t_mixer1_cfg, |
511 | }, | 519 | }, |
512 | { | 520 | { |
521 | .compatible = "allwinner,sun8i-h3-de2-mixer-0", | ||
522 | .data = &sun8i_h3_mixer0_cfg, | ||
523 | }, | ||
524 | { | ||
513 | .compatible = "allwinner,sun8i-v3s-de2-mixer", | 525 | .compatible = "allwinner,sun8i-v3s-de2-mixer", |
514 | .data = &sun8i_v3s_mixer_cfg, | 526 | .data = &sun8i_v3s_mixer_cfg, |
515 | }, | 527 | }, |
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 2f0ccd50b54d..9a540330cb79 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c | |||
@@ -211,7 +211,6 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, | |||
211 | struct drm_crtc *crtc = state->crtc; | 211 | struct drm_crtc *crtc = state->crtc; |
212 | struct drm_crtc_state *crtc_state; | 212 | struct drm_crtc_state *crtc_state; |
213 | int min_scale, max_scale; | 213 | int min_scale, max_scale; |
214 | struct drm_rect clip = {}; | ||
215 | 214 | ||
216 | if (!crtc) | 215 | if (!crtc) |
217 | return 0; | 216 | return 0; |
@@ -220,10 +219,6 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, | |||
220 | if (WARN_ON(!crtc_state)) | 219 | if (WARN_ON(!crtc_state)) |
221 | return -EINVAL; | 220 | return -EINVAL; |
222 | 221 | ||
223 | if (crtc_state->enable) | ||
224 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
225 | &clip.x2, &clip.y2); | ||
226 | |||
227 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | 222 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
228 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | 223 | max_scale = DRM_PLANE_HELPER_NO_SCALING; |
229 | 224 | ||
@@ -232,7 +227,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, | |||
232 | max_scale = SUN8I_UI_SCALER_SCALE_MAX; | 227 | max_scale = SUN8I_UI_SCALER_SCALE_MAX; |
233 | } | 228 | } |
234 | 229 | ||
235 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | 230 | return drm_atomic_helper_check_plane_state(state, crtc_state, |
236 | min_scale, max_scale, | 231 | min_scale, max_scale, |
237 | true, true); | 232 | true, true); |
238 | } | 233 | } |
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index eb3bf2d7291a..5877f8ef5895 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c | |||
@@ -239,7 +239,6 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, | |||
239 | struct drm_crtc *crtc = state->crtc; | 239 | struct drm_crtc *crtc = state->crtc; |
240 | struct drm_crtc_state *crtc_state; | 240 | struct drm_crtc_state *crtc_state; |
241 | int min_scale, max_scale; | 241 | int min_scale, max_scale; |
242 | struct drm_rect clip = {}; | ||
243 | 242 | ||
244 | if (!crtc) | 243 | if (!crtc) |
245 | return 0; | 244 | return 0; |
@@ -248,10 +247,6 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, | |||
248 | if (WARN_ON(!crtc_state)) | 247 | if (WARN_ON(!crtc_state)) |
249 | return -EINVAL; | 248 | return -EINVAL; |
250 | 249 | ||
251 | if (crtc_state->enable) | ||
252 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
253 | &clip.x2, &clip.y2); | ||
254 | |||
255 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | 250 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
256 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | 251 | max_scale = DRM_PLANE_HELPER_NO_SCALING; |
257 | 252 | ||
@@ -260,7 +255,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, | |||
260 | max_scale = SUN8I_VI_SCALER_SCALE_MAX; | 255 | max_scale = SUN8I_VI_SCALER_SCALE_MAX; |
261 | } | 256 | } |
262 | 257 | ||
263 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | 258 | return drm_atomic_helper_check_plane_state(state, crtc_state, |
264 | min_scale, max_scale, | 259 | min_scale, max_scale, |
265 | true, true); | 260 | true, true); |
266 | } | 261 | } |
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 7267a01e6f08..a056fbf83b53 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c | |||
@@ -82,7 +82,6 @@ int tegra_plane_state_add(struct tegra_plane *plane, | |||
82 | { | 82 | { |
83 | struct drm_crtc_state *crtc_state; | 83 | struct drm_crtc_state *crtc_state; |
84 | struct tegra_dc_state *tegra; | 84 | struct tegra_dc_state *tegra; |
85 | struct drm_rect clip = {}; | ||
86 | int err; | 85 | int err; |
87 | 86 | ||
88 | /* Propagate errors from allocation or locking failures. */ | 87 | /* Propagate errors from allocation or locking failures. */ |
@@ -90,12 +89,8 @@ int tegra_plane_state_add(struct tegra_plane *plane, | |||
90 | if (IS_ERR(crtc_state)) | 89 | if (IS_ERR(crtc_state)) |
91 | return PTR_ERR(crtc_state); | 90 | return PTR_ERR(crtc_state); |
92 | 91 | ||
93 | if (crtc_state->enable) | ||
94 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
95 | &clip.x2, &clip.y2); | ||
96 | |||
97 | /* Check plane state for visibility and calculate clipping bounds */ | 92 | /* Check plane state for visibility and calculate clipping bounds */ |
98 | err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | 93 | err = drm_atomic_helper_check_plane_state(state, crtc_state, |
99 | 0, INT_MAX, true, true); | 94 | 0, INT_MAX, true, true); |
100 | if (err < 0) | 95 | if (err < 0) |
101 | return err; | 96 | return err; |
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index 13339be843bc..4592a5e3f20b 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig | |||
@@ -23,6 +23,7 @@ config TINYDRM_ILI9225 | |||
23 | config TINYDRM_MI0283QT | 23 | config TINYDRM_MI0283QT |
24 | tristate "DRM support for MI0283QT" | 24 | tristate "DRM support for MI0283QT" |
25 | depends on DRM_TINYDRM && SPI | 25 | depends on DRM_TINYDRM && SPI |
26 | depends on BACKLIGHT_CLASS_DEVICE | ||
26 | select TINYDRM_MIPI_DBI | 27 | select TINYDRM_MIPI_DBI |
27 | help | 28 | help |
28 | DRM driver for the Multi-Inno MI0283QT display panel | 29 | DRM driver for the Multi-Inno MI0283QT display panel |
@@ -54,6 +55,7 @@ config TINYDRM_ST7586 | |||
54 | config TINYDRM_ST7735R | 55 | config TINYDRM_ST7735R |
55 | tristate "DRM support for Sitronix ST7735R display panels" | 56 | tristate "DRM support for Sitronix ST7735R display panels" |
56 | depends on DRM_TINYDRM && SPI | 57 | depends on DRM_TINYDRM && SPI |
58 | depends on BACKLIGHT_CLASS_DEVICE | ||
57 | select TINYDRM_MIPI_DBI | 59 | select TINYDRM_MIPI_DBI |
58 | help | 60 | help |
59 | DRM driver Sitronix ST7735R with one of the following LCDs: | 61 | DRM driver Sitronix ST7735R with one of the following LCDs: |
diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 2c668bd6d997..db397fcb345a 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c | |||
@@ -273,16 +273,20 @@ static void tve200_display_update(struct drm_simple_display_pipe *pipe, | |||
273 | } | 273 | } |
274 | } | 274 | } |
275 | 275 | ||
276 | int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc) | 276 | static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) |
277 | { | 277 | { |
278 | struct drm_crtc *crtc = &pipe->crtc; | ||
279 | struct drm_device *drm = crtc->dev; | ||
278 | struct tve200_drm_dev_private *priv = drm->dev_private; | 280 | struct tve200_drm_dev_private *priv = drm->dev_private; |
279 | 281 | ||
280 | writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN); | 282 | writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN); |
281 | return 0; | 283 | return 0; |
282 | } | 284 | } |
283 | 285 | ||
284 | void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc) | 286 | static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe) |
285 | { | 287 | { |
288 | struct drm_crtc *crtc = &pipe->crtc; | ||
289 | struct drm_device *drm = crtc->dev; | ||
286 | struct tve200_drm_dev_private *priv = drm->dev_private; | 290 | struct tve200_drm_dev_private *priv = drm->dev_private; |
287 | 291 | ||
288 | writel(0, priv->regs + TVE200_INT_EN); | 292 | writel(0, priv->regs + TVE200_INT_EN); |
@@ -300,6 +304,8 @@ static const struct drm_simple_display_pipe_funcs tve200_display_funcs = { | |||
300 | .disable = tve200_display_disable, | 304 | .disable = tve200_display_disable, |
301 | .update = tve200_display_update, | 305 | .update = tve200_display_update, |
302 | .prepare_fb = tve200_display_prepare_fb, | 306 | .prepare_fb = tve200_display_prepare_fb, |
307 | .enable_vblank = tve200_display_enable_vblank, | ||
308 | .disable_vblank = tve200_display_disable_vblank, | ||
303 | }; | 309 | }; |
304 | 310 | ||
305 | int tve200_display_init(struct drm_device *drm) | 311 | int tve200_display_init(struct drm_device *drm) |
diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h index 5c270055bd58..1ba4380f489b 100644 --- a/drivers/gpu/drm/tve200/tve200_drm.h +++ b/drivers/gpu/drm/tve200/tve200_drm.h | |||
@@ -113,8 +113,6 @@ struct tve200_drm_dev_private { | |||
113 | container_of(x, struct tve200_drm_connector, connector) | 113 | container_of(x, struct tve200_drm_connector, connector) |
114 | 114 | ||
115 | int tve200_display_init(struct drm_device *dev); | 115 | int tve200_display_init(struct drm_device *dev); |
116 | int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc); | ||
117 | void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc); | ||
118 | irqreturn_t tve200_irq(int irq, void *data); | 116 | irqreturn_t tve200_irq(int irq, void *data); |
119 | int tve200_connector_init(struct drm_device *dev); | 117 | int tve200_connector_init(struct drm_device *dev); |
120 | int tve200_encoder_init(struct drm_device *dev); | 118 | int tve200_encoder_init(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 44911d921864..ac344ddb23bc 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c | |||
@@ -162,9 +162,6 @@ static struct drm_driver tve200_drm_driver = { | |||
162 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 162 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
163 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 163 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
164 | 164 | ||
165 | .enable_vblank = tve200_enable_vblank, | ||
166 | .disable_vblank = tve200_disable_vblank, | ||
167 | |||
168 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | 165 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
169 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | 166 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
170 | .gem_prime_import = drm_gem_prime_import, | 167 | .gem_prime_import = drm_gem_prime_import, |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 984501e3f0b0..1a6db291d48b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c | |||
@@ -681,7 +681,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) | |||
681 | drift & ~VC4_HDMI_FIFO_CTL_RECENTER); | 681 | drift & ~VC4_HDMI_FIFO_CTL_RECENTER); |
682 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, | 682 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, |
683 | drift | VC4_HDMI_FIFO_CTL_RECENTER); | 683 | drift | VC4_HDMI_FIFO_CTL_RECENTER); |
684 | udelay(1000); | 684 | usleep_range(1000, 1100); |
685 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, | 685 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, |
686 | drift & ~VC4_HDMI_FIFO_CTL_RECENTER); | 686 | drift & ~VC4_HDMI_FIFO_CTL_RECENTER); |
687 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, | 687 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, |
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 4256f294c346..ba60153dddb5 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c | |||
@@ -215,6 +215,7 @@ int vc4_kms_load(struct drm_device *dev) | |||
215 | dev->mode_config.funcs = &vc4_mode_funcs; | 215 | dev->mode_config.funcs = &vc4_mode_funcs; |
216 | dev->mode_config.preferred_depth = 24; | 216 | dev->mode_config.preferred_depth = 24; |
217 | dev->mode_config.async_page_flip = true; | 217 | dev->mode_config.async_page_flip = true; |
218 | dev->mode_config.allow_fb_modifiers = true; | ||
218 | 219 | ||
219 | drm_mode_config_reset(dev); | 220 | drm_mode_config_reset(dev); |
220 | 221 | ||
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 61ad955645a5..c4c7af11fec5 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c | |||
@@ -906,6 +906,32 @@ out: | |||
906 | ctx); | 906 | ctx); |
907 | } | 907 | } |
908 | 908 | ||
909 | static bool vc4_format_mod_supported(struct drm_plane *plane, | ||
910 | uint32_t format, | ||
911 | uint64_t modifier) | ||
912 | { | ||
913 | /* Support T_TILING for RGB formats only. */ | ||
914 | switch (format) { | ||
915 | case DRM_FORMAT_XRGB8888: | ||
916 | case DRM_FORMAT_ARGB8888: | ||
917 | case DRM_FORMAT_ABGR8888: | ||
918 | case DRM_FORMAT_XBGR8888: | ||
919 | case DRM_FORMAT_RGB565: | ||
920 | case DRM_FORMAT_BGR565: | ||
921 | case DRM_FORMAT_ARGB1555: | ||
922 | case DRM_FORMAT_XRGB1555: | ||
923 | return true; | ||
924 | case DRM_FORMAT_YUV422: | ||
925 | case DRM_FORMAT_YVU422: | ||
926 | case DRM_FORMAT_YUV420: | ||
927 | case DRM_FORMAT_YVU420: | ||
928 | case DRM_FORMAT_NV12: | ||
929 | case DRM_FORMAT_NV16: | ||
930 | default: | ||
931 | return (modifier == DRM_FORMAT_MOD_LINEAR); | ||
932 | } | ||
933 | } | ||
934 | |||
909 | static const struct drm_plane_funcs vc4_plane_funcs = { | 935 | static const struct drm_plane_funcs vc4_plane_funcs = { |
910 | .update_plane = vc4_update_plane, | 936 | .update_plane = vc4_update_plane, |
911 | .disable_plane = drm_atomic_helper_disable_plane, | 937 | .disable_plane = drm_atomic_helper_disable_plane, |
@@ -914,6 +940,7 @@ static const struct drm_plane_funcs vc4_plane_funcs = { | |||
914 | .reset = vc4_plane_reset, | 940 | .reset = vc4_plane_reset, |
915 | .atomic_duplicate_state = vc4_plane_duplicate_state, | 941 | .atomic_duplicate_state = vc4_plane_duplicate_state, |
916 | .atomic_destroy_state = vc4_plane_destroy_state, | 942 | .atomic_destroy_state = vc4_plane_destroy_state, |
943 | .format_mod_supported = vc4_format_mod_supported, | ||
917 | }; | 944 | }; |
918 | 945 | ||
919 | struct drm_plane *vc4_plane_init(struct drm_device *dev, | 946 | struct drm_plane *vc4_plane_init(struct drm_device *dev, |
@@ -925,6 +952,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, | |||
925 | u32 num_formats = 0; | 952 | u32 num_formats = 0; |
926 | int ret = 0; | 953 | int ret = 0; |
927 | unsigned i; | 954 | unsigned i; |
955 | static const uint64_t modifiers[] = { | ||
956 | DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, | ||
957 | DRM_FORMAT_MOD_LINEAR, | ||
958 | DRM_FORMAT_MOD_INVALID | ||
959 | }; | ||
928 | 960 | ||
929 | vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), | 961 | vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), |
930 | GFP_KERNEL); | 962 | GFP_KERNEL); |
@@ -945,7 +977,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, | |||
945 | ret = drm_universal_plane_init(dev, plane, 0, | 977 | ret = drm_universal_plane_init(dev, plane, 0, |
946 | &vc4_plane_funcs, | 978 | &vc4_plane_funcs, |
947 | formats, num_formats, | 979 | formats, num_formats, |
948 | NULL, type, NULL); | 980 | modifiers, type, NULL); |
949 | 981 | ||
950 | drm_plane_helper_add(plane, &vc4_plane_helper_funcs); | 982 | drm_plane_helper_add(plane, &vc4_plane_helper_funcs); |
951 | 983 | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 19114a3c5ee4..8cc8c34d67f5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c | |||
@@ -61,9 +61,9 @@ static void virtio_gpu_user_framebuffer_destroy(struct drm_framebuffer *fb) | |||
61 | static int | 61 | static int |
62 | virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb, | 62 | virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb, |
63 | struct drm_file *file_priv, | 63 | struct drm_file *file_priv, |
64 | unsigned flags, unsigned color, | 64 | unsigned int flags, unsigned int color, |
65 | struct drm_clip_rect *clips, | 65 | struct drm_clip_rect *clips, |
66 | unsigned num_clips) | 66 | unsigned int num_clips) |
67 | { | 67 | { |
68 | struct virtio_gpu_framebuffer *virtio_gpu_fb | 68 | struct virtio_gpu_framebuffer *virtio_gpu_fb |
69 | = to_virtio_gpu_framebuffer(fb); | 69 | = to_virtio_gpu_framebuffer(fb); |
@@ -96,6 +96,7 @@ virtio_gpu_framebuffer_init(struct drm_device *dev, | |||
96 | { | 96 | { |
97 | int ret; | 97 | int ret; |
98 | struct virtio_gpu_object *bo; | 98 | struct virtio_gpu_object *bo; |
99 | |||
99 | vgfb->obj = obj; | 100 | vgfb->obj = obj; |
100 | 101 | ||
101 | bo = gem_to_virtio_gpu_obj(obj); | 102 | bo = gem_to_virtio_gpu_obj(obj); |
@@ -387,7 +388,7 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) | |||
387 | for (i = 0 ; i < vgdev->num_scanouts; ++i) | 388 | for (i = 0 ; i < vgdev->num_scanouts; ++i) |
388 | vgdev_output_init(vgdev, i); | 389 | vgdev_output_init(vgdev, i); |
389 | 390 | ||
390 | drm_mode_config_reset(vgdev->ddev); | 391 | drm_mode_config_reset(vgdev->ddev); |
391 | return 0; | 392 | return 0; |
392 | } | 393 | } |
393 | 394 | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 49a3d8d5a249..d9287c144fe5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c | |||
@@ -54,6 +54,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev) | |||
54 | static void virtio_gpu_remove(struct virtio_device *vdev) | 54 | static void virtio_gpu_remove(struct virtio_device *vdev) |
55 | { | 55 | { |
56 | struct drm_device *dev = vdev->priv; | 56 | struct drm_device *dev = vdev->priv; |
57 | |||
57 | drm_put_dev(dev); | 58 | drm_put_dev(dev); |
58 | } | 59 | } |
59 | 60 | ||
@@ -112,7 +113,6 @@ static const struct file_operations virtio_gpu_driver_fops = { | |||
112 | .llseek = noop_llseek, | 113 | .llseek = noop_llseek, |
113 | }; | 114 | }; |
114 | 115 | ||
115 | |||
116 | static struct drm_driver driver = { | 116 | static struct drm_driver driver = { |
117 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC, | 117 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC, |
118 | .load = virtio_gpu_driver_load, | 118 | .load = virtio_gpu_driver_load, |
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index da2fb585fea4..d25c8ca224aa 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h | |||
@@ -246,7 +246,7 @@ int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev); | |||
246 | void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev); | 246 | void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev); |
247 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, | 247 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, |
248 | struct drm_clip_rect *clips, | 248 | struct drm_clip_rect *clips, |
249 | unsigned num_clips); | 249 | unsigned int num_clips); |
250 | /* virtio vg */ | 250 | /* virtio vg */ |
251 | int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev); | 251 | int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev); |
252 | void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev); | 252 | void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev); |
@@ -363,12 +363,12 @@ int virtgpu_gem_prime_pin(struct drm_gem_object *obj); | |||
363 | void virtgpu_gem_prime_unpin(struct drm_gem_object *obj); | 363 | void virtgpu_gem_prime_unpin(struct drm_gem_object *obj); |
364 | struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj); | 364 | struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj); |
365 | struct drm_gem_object *virtgpu_gem_prime_import_sg_table( | 365 | struct drm_gem_object *virtgpu_gem_prime_import_sg_table( |
366 | struct drm_device *dev, struct dma_buf_attachment *attach, | 366 | struct drm_device *dev, struct dma_buf_attachment *attach, |
367 | struct sg_table *sgt); | 367 | struct sg_table *sgt); |
368 | void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj); | 368 | void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj); |
369 | void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | 369 | void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
370 | int virtgpu_gem_prime_mmap(struct drm_gem_object *obj, | 370 | int virtgpu_gem_prime_mmap(struct drm_gem_object *obj, |
371 | struct vm_area_struct *vma); | 371 | struct vm_area_struct *vma); |
372 | 372 | ||
373 | static inline struct virtio_gpu_object* | 373 | static inline struct virtio_gpu_object* |
374 | virtio_gpu_object_ref(struct virtio_gpu_object *bo) | 374 | virtio_gpu_object_ref(struct virtio_gpu_object *bo) |
diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index 15d18fd0c64b..8af69ab58b89 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c | |||
@@ -118,7 +118,7 @@ static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, | |||
118 | 118 | ||
119 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb, | 119 | int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb, |
120 | struct drm_clip_rect *clips, | 120 | struct drm_clip_rect *clips, |
121 | unsigned num_clips) | 121 | unsigned int num_clips) |
122 | { | 122 | { |
123 | struct virtio_gpu_device *vgdev = vgfb->base.dev->dev_private; | 123 | struct virtio_gpu_device *vgdev = vgfb->base.dev->dev_private; |
124 | struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(vgfb->obj); | 124 | struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(vgfb->obj); |
@@ -127,6 +127,7 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb, | |||
127 | int left, right, top, bottom; | 127 | int left, right, top, bottom; |
128 | int i; | 128 | int i; |
129 | int inc = 1; | 129 | int inc = 1; |
130 | |||
130 | if (!num_clips) { | 131 | if (!num_clips) { |
131 | num_clips = 1; | 132 | num_clips = 1; |
132 | clips = &norect; | 133 | clips = &norect; |
@@ -172,6 +173,7 @@ static void virtio_gpu_3d_fillrect(struct fb_info *info, | |||
172 | const struct fb_fillrect *rect) | 173 | const struct fb_fillrect *rect) |
173 | { | 174 | { |
174 | struct virtio_gpu_fbdev *vfbdev = info->par; | 175 | struct virtio_gpu_fbdev *vfbdev = info->par; |
176 | |||
175 | drm_fb_helper_sys_fillrect(info, rect); | 177 | drm_fb_helper_sys_fillrect(info, rect); |
176 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy, | 178 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy, |
177 | rect->width, rect->height); | 179 | rect->width, rect->height); |
@@ -182,6 +184,7 @@ static void virtio_gpu_3d_copyarea(struct fb_info *info, | |||
182 | const struct fb_copyarea *area) | 184 | const struct fb_copyarea *area) |
183 | { | 185 | { |
184 | struct virtio_gpu_fbdev *vfbdev = info->par; | 186 | struct virtio_gpu_fbdev *vfbdev = info->par; |
187 | |||
185 | drm_fb_helper_sys_copyarea(info, area); | 188 | drm_fb_helper_sys_copyarea(info, area); |
186 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy, | 189 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy, |
187 | area->width, area->height); | 190 | area->width, area->height); |
@@ -192,6 +195,7 @@ static void virtio_gpu_3d_imageblit(struct fb_info *info, | |||
192 | const struct fb_image *image) | 195 | const struct fb_image *image) |
193 | { | 196 | { |
194 | struct virtio_gpu_fbdev *vfbdev = info->par; | 197 | struct virtio_gpu_fbdev *vfbdev = info->par; |
198 | |||
195 | drm_fb_helper_sys_imageblit(info, image); | 199 | drm_fb_helper_sys_imageblit(info, image); |
196 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy, | 200 | virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy, |
197 | image->width, image->height); | 201 | image->width, image->height); |
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 92fb27753b9e..0f2768eacaee 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c | |||
@@ -124,6 +124,7 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, | |||
124 | { | 124 | { |
125 | struct drm_gem_object *gobj; | 125 | struct drm_gem_object *gobj; |
126 | struct virtio_gpu_object *obj; | 126 | struct virtio_gpu_object *obj; |
127 | |||
127 | BUG_ON(!offset_p); | 128 | BUG_ON(!offset_p); |
128 | gobj = drm_gem_object_lookup(file_priv, handle); | 129 | gobj = drm_gem_object_lookup(file_priv, handle); |
129 | if (gobj == NULL) | 130 | if (gobj == NULL) |
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 355569a9b5cb..a14e8a2ec682 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c | |||
@@ -83,6 +83,7 @@ static void virtio_gpu_unref_list(struct list_head *head) | |||
83 | struct ttm_validate_buffer *buf; | 83 | struct ttm_validate_buffer *buf; |
84 | struct ttm_buffer_object *bo; | 84 | struct ttm_buffer_object *bo; |
85 | struct virtio_gpu_object *qobj; | 85 | struct virtio_gpu_object *qobj; |
86 | |||
86 | list_for_each_entry(buf, head, head) { | 87 | list_for_each_entry(buf, head, head) { |
87 | bo = buf->bo; | 88 | bo = buf->bo; |
88 | qobj = container_of(bo, struct virtio_gpu_object, tbo); | 89 | qobj = container_of(bo, struct virtio_gpu_object, tbo); |
@@ -478,6 +479,7 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, | |||
478 | int ret; | 479 | int ret; |
479 | struct virtio_gpu_drv_cap_cache *cache_ent; | 480 | struct virtio_gpu_drv_cap_cache *cache_ent; |
480 | void *ptr; | 481 | void *ptr; |
482 | |||
481 | if (vgdev->num_capsets == 0) | 483 | if (vgdev->num_capsets == 0) |
482 | return -ENOSYS; | 484 | return -ENOSYS; |
483 | 485 | ||
@@ -532,33 +534,34 @@ copy_exit: | |||
532 | 534 | ||
533 | struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { | 535 | struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { |
534 | DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, | 536 | DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, |
535 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 537 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
536 | 538 | ||
537 | DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, | 539 | DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, |
538 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 540 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
539 | 541 | ||
540 | DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, | 542 | DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, |
541 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 543 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
542 | 544 | ||
543 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, | 545 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, |
544 | virtio_gpu_resource_create_ioctl, | 546 | virtio_gpu_resource_create_ioctl, |
545 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 547 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
546 | 548 | ||
547 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, | 549 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, |
548 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 550 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
549 | 551 | ||
550 | /* make transfer async to the main ring? - no sure, can we | 552 | /* make transfer async to the main ring? - no sure, can we |
551 | thread these in the underlying GL */ | 553 | * thread these in the underlying GL |
554 | */ | ||
552 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, | 555 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, |
553 | virtio_gpu_transfer_from_host_ioctl, | 556 | virtio_gpu_transfer_from_host_ioctl, |
554 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 557 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
555 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, | 558 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, |
556 | virtio_gpu_transfer_to_host_ioctl, | 559 | virtio_gpu_transfer_to_host_ioctl, |
557 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 560 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
558 | 561 | ||
559 | DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, | 562 | DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, |
560 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 563 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
561 | 564 | ||
562 | DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, | 565 | DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, |
563 | DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), | 566 | DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW), |
564 | }; | 567 | }; |
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 385e0eb9826a..d27a1688714f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c | |||
@@ -25,7 +25,8 @@ | |||
25 | #include "virtgpu_drv.h" | 25 | #include "virtgpu_drv.h" |
26 | 26 | ||
27 | /* Empty Implementations as there should not be any other driver for a virtual | 27 | /* Empty Implementations as there should not be any other driver for a virtual |
28 | * device that might share buffers with virtgpu */ | 28 | * device that might share buffers with virtgpu |
29 | */ | ||
29 | 30 | ||
30 | int virtgpu_gem_prime_pin(struct drm_gem_object *obj) | 31 | int virtgpu_gem_prime_pin(struct drm_gem_object *obj) |
31 | { | 32 | { |
@@ -38,7 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj) | |||
38 | WARN_ONCE(1, "not implemented"); | 39 | WARN_ONCE(1, "not implemented"); |
39 | } | 40 | } |
40 | 41 | ||
41 | |||
42 | struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj) | 42 | struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj) |
43 | { | 43 | { |
44 | WARN_ONCE(1, "not implemented"); | 44 | WARN_ONCE(1, "not implemented"); |
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index ee9839fbae66..fd5d9450878e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c | |||
@@ -177,7 +177,6 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, | |||
177 | struct ttm_mem_reg *mem) | 177 | struct ttm_mem_reg *mem) |
178 | { | 178 | { |
179 | mem->mm_node = (void *)NULL; | 179 | mem->mm_node = (void *)NULL; |
180 | return; | ||
181 | } | 180 | } |
182 | 181 | ||
183 | static int ttm_bo_man_init(struct ttm_mem_type_manager *man, | 182 | static int ttm_bo_man_init(struct ttm_mem_type_manager *man, |
@@ -225,7 +224,7 @@ static int virtio_gpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
225 | man->default_caching = TTM_PL_FLAG_CACHED; | 224 | man->default_caching = TTM_PL_FLAG_CACHED; |
226 | break; | 225 | break; |
227 | default: | 226 | default: |
228 | DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); | 227 | DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type); |
229 | return -EINVAL; | 228 | return -EINVAL; |
230 | } | 229 | } |
231 | return 0; | 230 | return 0; |
@@ -244,7 +243,6 @@ static void virtio_gpu_evict_flags(struct ttm_buffer_object *bo, | |||
244 | placement->busy_placement = &placements; | 243 | placement->busy_placement = &placements; |
245 | placement->num_placement = 1; | 244 | placement->num_placement = 1; |
246 | placement->num_busy_placement = 1; | 245 | placement->num_busy_placement = 1; |
247 | return; | ||
248 | } | 246 | } |
249 | 247 | ||
250 | static int virtio_gpu_verify_access(struct ttm_buffer_object *bo, | 248 | static int virtio_gpu_verify_access(struct ttm_buffer_object *bo, |
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 9eb96fb2c147..48e4f1df6e5d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c | |||
@@ -62,6 +62,7 @@ void virtio_gpu_ctrl_ack(struct virtqueue *vq) | |||
62 | { | 62 | { |
63 | struct drm_device *dev = vq->vdev->priv; | 63 | struct drm_device *dev = vq->vdev->priv; |
64 | struct virtio_gpu_device *vgdev = dev->dev_private; | 64 | struct virtio_gpu_device *vgdev = dev->dev_private; |
65 | |||
65 | schedule_work(&vgdev->ctrlq.dequeue_work); | 66 | schedule_work(&vgdev->ctrlq.dequeue_work); |
66 | } | 67 | } |
67 | 68 | ||
@@ -69,6 +70,7 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq) | |||
69 | { | 70 | { |
70 | struct drm_device *dev = vq->vdev->priv; | 71 | struct drm_device *dev = vq->vdev->priv; |
71 | struct virtio_gpu_device *vgdev = dev->dev_private; | 72 | struct virtio_gpu_device *vgdev = dev->dev_private; |
73 | |||
72 | schedule_work(&vgdev->cursorq.dequeue_work); | 74 | schedule_work(&vgdev->cursorq.dequeue_work); |
73 | } | 75 | } |
74 | 76 | ||
@@ -272,7 +274,7 @@ static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev, | |||
272 | return -ENODEV; | 274 | return -ENODEV; |
273 | 275 | ||
274 | sg_init_one(&vcmd, vbuf->buf, vbuf->size); | 276 | sg_init_one(&vcmd, vbuf->buf, vbuf->size); |
275 | sgs[outcnt+incnt] = &vcmd; | 277 | sgs[outcnt + incnt] = &vcmd; |
276 | outcnt++; | 278 | outcnt++; |
277 | 279 | ||
278 | if (vbuf->data_size) { | 280 | if (vbuf->data_size) { |
@@ -381,7 +383,8 @@ retry: | |||
381 | } | 383 | } |
382 | 384 | ||
383 | /* just create gem objects for userspace and long lived objects, | 385 | /* just create gem objects for userspace and long lived objects, |
384 | just use dma_alloced pages for the queue objects? */ | 386 | * just use dma_alloced pages for the queue objects? |
387 | */ | ||
385 | 388 | ||
386 | /* create a basic resource */ | 389 | /* create a basic resource */ |
387 | void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev, | 390 | void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev, |
@@ -593,7 +596,6 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev, | |||
593 | wake_up(&vgdev->resp_wq); | 596 | wake_up(&vgdev->resp_wq); |
594 | } | 597 | } |
595 | 598 | ||
596 | |||
597 | int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) | 599 | int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) |
598 | { | 600 | { |
599 | struct virtio_gpu_ctrl_hdr *cmd_p; | 601 | struct virtio_gpu_ctrl_hdr *cmd_p; |
@@ -707,8 +709,8 @@ void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, | |||
707 | cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE); | 709 | cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE); |
708 | cmd_p->hdr.ctx_id = cpu_to_le32(id); | 710 | cmd_p->hdr.ctx_id = cpu_to_le32(id); |
709 | cmd_p->nlen = cpu_to_le32(nlen); | 711 | cmd_p->nlen = cpu_to_le32(nlen); |
710 | strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)-1); | 712 | strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1); |
711 | cmd_p->debug_name[sizeof(cmd_p->debug_name)-1] = 0; | 713 | cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0; |
712 | virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); | 714 | virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); |
713 | } | 715 | } |
714 | 716 | ||
@@ -852,6 +854,7 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, | |||
852 | 854 | ||
853 | if (!obj->pages) { | 855 | if (!obj->pages) { |
854 | int ret; | 856 | int ret; |
857 | |||
855 | ret = virtio_gpu_object_get_sg_table(vgdev, obj); | 858 | ret = virtio_gpu_object_get_sg_table(vgdev, obj); |
856 | if (ret) | 859 | if (ret) |
857 | return ret; | 860 | return ret; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 1107d6d03506..34ecc27fc30a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -443,17 +443,12 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, | |||
443 | { | 443 | { |
444 | struct drm_crtc_state *crtc_state = NULL; | 444 | struct drm_crtc_state *crtc_state = NULL; |
445 | struct drm_framebuffer *new_fb = state->fb; | 445 | struct drm_framebuffer *new_fb = state->fb; |
446 | struct drm_rect clip = {}; | ||
447 | int ret; | 446 | int ret; |
448 | 447 | ||
449 | if (state->crtc) | 448 | if (state->crtc) |
450 | crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); | 449 | crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); |
451 | 450 | ||
452 | if (crtc_state && crtc_state->enable) | 451 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
453 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
454 | &clip.x2, &clip.y2); | ||
455 | |||
456 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
457 | DRM_PLANE_HELPER_NO_SCALING, | 452 | DRM_PLANE_HELPER_NO_SCALING, |
458 | DRM_PLANE_HELPER_NO_SCALING, | 453 | DRM_PLANE_HELPER_NO_SCALING, |
459 | false, true); | 454 | false, true); |
diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index 8e1f34274e24..94545adac50d 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c | |||
@@ -55,7 +55,6 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane, | |||
55 | struct drm_framebuffer *fb = plane_state->fb; | 55 | struct drm_framebuffer *fb = plane_state->fb; |
56 | struct drm_crtc *crtc = plane_state->crtc; | 56 | struct drm_crtc *crtc = plane_state->crtc; |
57 | struct drm_crtc_state *crtc_state; | 57 | struct drm_crtc_state *crtc_state; |
58 | struct drm_rect clip = {}; | ||
59 | int min_scale = FRAC_16_16(1, 8); | 58 | int min_scale = FRAC_16_16(1, 8); |
60 | int max_scale = FRAC_16_16(8, 1); | 59 | int max_scale = FRAC_16_16(8, 1); |
61 | 60 | ||
@@ -75,12 +74,8 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane, | |||
75 | if (!plane_state->crtc) | 74 | if (!plane_state->crtc) |
76 | return -EINVAL; | 75 | return -EINVAL; |
77 | 76 | ||
78 | if (crtc_state->enable) | ||
79 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
80 | &clip.x2, &clip.y2); | ||
81 | |||
82 | return drm_atomic_helper_check_plane_state(plane_state, crtc_state, | 77 | return drm_atomic_helper_check_plane_state(plane_state, crtc_state, |
83 | &clip, min_scale, max_scale, | 78 | min_scale, max_scale, |
84 | true, true); | 79 | true, true); |
85 | } | 80 | } |
86 | 81 | ||
@@ -291,7 +286,6 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane, | |||
291 | struct drm_framebuffer *fb = plane_state->fb; | 286 | struct drm_framebuffer *fb = plane_state->fb; |
292 | struct drm_crtc *crtc = plane_state->crtc; | 287 | struct drm_crtc *crtc = plane_state->crtc; |
293 | struct drm_crtc_state *crtc_state; | 288 | struct drm_crtc_state *crtc_state; |
294 | struct drm_rect clip = {}; | ||
295 | 289 | ||
296 | if (!crtc || !fb) | 290 | if (!crtc || !fb) |
297 | return 0; | 291 | return 0; |
@@ -309,12 +303,7 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane, | |||
309 | if (!plane_state->crtc) | 303 | if (!plane_state->crtc) |
310 | return -EINVAL; | 304 | return -EINVAL; |
311 | 305 | ||
312 | if (crtc_state->enable) | ||
313 | drm_mode_get_hv_timing(&crtc_state->mode, | ||
314 | &clip.x2, &clip.y2); | ||
315 | |||
316 | return drm_atomic_helper_check_plane_state(plane_state, crtc_state, | 306 | return drm_atomic_helper_check_plane_state(plane_state, crtc_state, |
317 | &clip, | ||
318 | DRM_PLANE_HELPER_NO_SCALING, | 307 | DRM_PLANE_HELPER_NO_SCALING, |
319 | DRM_PLANE_HELPER_NO_SCALING, | 308 | DRM_PLANE_HELPER_NO_SCALING, |
320 | false, true); | 309 | false, true); |
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index c99d6eaef1ac..711fff9b6803 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include <drm/drm_crtc.h> | 14 | #include <drm/drm_crtc.h> |
15 | 15 | ||
16 | struct analogix_dp_device; | ||
17 | |||
16 | enum analogix_dp_devtype { | 18 | enum analogix_dp_devtype { |
17 | EXYNOS_DP, | 19 | EXYNOS_DP, |
18 | RK3288_DP, | 20 | RK3288_DP, |
@@ -29,6 +31,7 @@ struct analogix_dp_plat_data { | |||
29 | struct drm_panel *panel; | 31 | struct drm_panel *panel; |
30 | struct drm_encoder *encoder; | 32 | struct drm_encoder *encoder; |
31 | struct drm_connector *connector; | 33 | struct drm_connector *connector; |
34 | bool skip_connector; | ||
32 | 35 | ||
33 | int (*power_on)(struct analogix_dp_plat_data *); | 36 | int (*power_on)(struct analogix_dp_plat_data *); |
34 | int (*power_off)(struct analogix_dp_plat_data *); | 37 | int (*power_off)(struct analogix_dp_plat_data *); |
@@ -38,16 +41,17 @@ struct analogix_dp_plat_data { | |||
38 | struct drm_connector *); | 41 | struct drm_connector *); |
39 | }; | 42 | }; |
40 | 43 | ||
41 | int analogix_dp_psr_supported(struct device *dev); | 44 | int analogix_dp_psr_supported(struct analogix_dp_device *dp); |
42 | int analogix_dp_enable_psr(struct device *dev); | 45 | int analogix_dp_enable_psr(struct analogix_dp_device *dp); |
43 | int analogix_dp_disable_psr(struct device *dev); | 46 | int analogix_dp_disable_psr(struct analogix_dp_device *dp); |
44 | 47 | ||
45 | int analogix_dp_resume(struct device *dev); | 48 | int analogix_dp_resume(struct analogix_dp_device *dp); |
46 | int analogix_dp_suspend(struct device *dev); | 49 | int analogix_dp_suspend(struct analogix_dp_device *dp); |
47 | 50 | ||
48 | int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | 51 | struct analogix_dp_device * |
49 | struct analogix_dp_plat_data *plat_data); | 52 | analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, |
50 | void analogix_dp_unbind(struct device *dev, struct device *master, void *data); | 53 | struct analogix_dp_plat_data *plat_data); |
54 | void analogix_dp_unbind(struct analogix_dp_device *dp); | ||
51 | 55 | ||
52 | int analogix_dp_start_crc(struct drm_connector *connector); | 56 | int analogix_dp_start_crc(struct drm_connector *connector); |
53 | int analogix_dp_stop_crc(struct drm_connector *connector); | 57 | int analogix_dp_stop_crc(struct drm_connector *connector); |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 2c711a24c80c..a57a8aa90ffb 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
@@ -754,6 +754,28 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
754 | (new_plane_state) = (__state)->planes[__i].new_state, 1)) | 754 | (new_plane_state) = (__state)->planes[__i].new_state, 1)) |
755 | 755 | ||
756 | /** | 756 | /** |
757 | * for_each_oldnew_plane_in_state_reverse - iterate over all planes in an atomic | ||
758 | * update in reverse order | ||
759 | * @__state: &struct drm_atomic_state pointer | ||
760 | * @plane: &struct drm_plane iteration cursor | ||
761 | * @old_plane_state: &struct drm_plane_state iteration cursor for the old state | ||
762 | * @new_plane_state: &struct drm_plane_state iteration cursor for the new state | ||
763 | * @__i: int iteration cursor, for macro-internal use | ||
764 | * | ||
765 | * This iterates over all planes in an atomic update in reverse order, | ||
766 | * tracking both old and new state. This is useful in places where the | ||
767 | * state delta needs to be considered, for example in atomic check functions. | ||
768 | */ | ||
769 | #define for_each_oldnew_plane_in_state_reverse(__state, plane, old_plane_state, new_plane_state, __i) \ | ||
770 | for ((__i) = ((__state)->dev->mode_config.num_total_plane - 1); \ | ||
771 | (__i) >= 0; \ | ||
772 | (__i)--) \ | ||
773 | for_each_if ((__state)->planes[__i].ptr && \ | ||
774 | ((plane) = (__state)->planes[__i].ptr, \ | ||
775 | (old_plane_state) = (__state)->planes[__i].old_state,\ | ||
776 | (new_plane_state) = (__state)->planes[__i].new_state, 1)) | ||
777 | |||
778 | /** | ||
757 | * for_each_old_plane_in_state - iterate over all planes in an atomic update | 779 | * for_each_old_plane_in_state - iterate over all planes in an atomic update |
758 | * @__state: &struct drm_atomic_state pointer | 780 | * @__state: &struct drm_atomic_state pointer |
759 | * @plane: &struct drm_plane iteration cursor | 781 | * @plane: &struct drm_plane iteration cursor |
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4842ee9485ce..26aaba58d6ce 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
@@ -40,7 +40,6 @@ int drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
40 | struct drm_atomic_state *state); | 40 | struct drm_atomic_state *state); |
41 | int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, | 41 | int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, |
42 | const struct drm_crtc_state *crtc_state, | 42 | const struct drm_crtc_state *crtc_state, |
43 | const struct drm_rect *clip, | ||
44 | int min_scale, | 43 | int min_scale, |
45 | int max_scale, | 44 | int max_scale, |
46 | bool can_position, | 45 | bool can_position, |
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 03a59cbce621..b3b6d302ca8c 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
27 | 27 | ||
28 | struct drm_crtc; | 28 | struct drm_crtc; |
29 | struct drm_plane; | ||
29 | 30 | ||
30 | uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision); | 31 | uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision); |
31 | 32 | ||
@@ -37,4 +38,22 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, | |||
37 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, | 38 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
38 | int gamma_size); | 39 | int gamma_size); |
39 | 40 | ||
41 | enum drm_color_encoding { | ||
42 | DRM_COLOR_YCBCR_BT601, | ||
43 | DRM_COLOR_YCBCR_BT709, | ||
44 | DRM_COLOR_YCBCR_BT2020, | ||
45 | DRM_COLOR_ENCODING_MAX, | ||
46 | }; | ||
47 | |||
48 | enum drm_color_range { | ||
49 | DRM_COLOR_YCBCR_LIMITED_RANGE, | ||
50 | DRM_COLOR_YCBCR_FULL_RANGE, | ||
51 | DRM_COLOR_RANGE_MAX, | ||
52 | }; | ||
53 | |||
54 | int drm_plane_create_color_properties(struct drm_plane *plane, | ||
55 | u32 supported_encodings, | ||
56 | u32 supported_ranges, | ||
57 | enum drm_color_encoding default_encoding, | ||
58 | enum drm_color_range default_range); | ||
40 | #endif | 59 | #endif |
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 8185e3468a23..f7bf4a48b1c3 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
28 | #include <drm/drm_mode_object.h> | 28 | #include <drm/drm_mode_object.h> |
29 | #include <drm/drm_color_mgmt.h> | ||
29 | 30 | ||
30 | struct drm_crtc; | 31 | struct drm_crtc; |
31 | struct drm_printer; | 32 | struct drm_printer; |
@@ -112,6 +113,20 @@ struct drm_plane_state { | |||
112 | unsigned int zpos; | 113 | unsigned int zpos; |
113 | unsigned int normalized_zpos; | 114 | unsigned int normalized_zpos; |
114 | 115 | ||
116 | /** | ||
117 | * @color_encoding: | ||
118 | * | ||
119 | * Color encoding for non RGB formats | ||
120 | */ | ||
121 | enum drm_color_encoding color_encoding; | ||
122 | |||
123 | /** | ||
124 | * @color_range: | ||
125 | * | ||
126 | * Color range for non RGB formats | ||
127 | */ | ||
128 | enum drm_color_range color_range; | ||
129 | |||
115 | /* Clipped coordinates */ | 130 | /* Clipped coordinates */ |
116 | struct drm_rect src, dst; | 131 | struct drm_rect src, dst; |
117 | 132 | ||
@@ -558,6 +573,23 @@ struct drm_plane { | |||
558 | 573 | ||
559 | struct drm_property *zpos_property; | 574 | struct drm_property *zpos_property; |
560 | struct drm_property *rotation_property; | 575 | struct drm_property *rotation_property; |
576 | |||
577 | /** | ||
578 | * @color_encoding_property: | ||
579 | * | ||
580 | * Optional "COLOR_ENCODING" enum property for specifying | ||
581 | * color encoding for non RGB formats. | ||
582 | * See drm_plane_create_color_properties(). | ||
583 | */ | ||
584 | struct drm_property *color_encoding_property; | ||
585 | /** | ||
586 | * @color_range_property: | ||
587 | * | ||
588 | * Optional "COLOR_RANGE" enum property for specifying | ||
589 | * color range for non RGB formats. | ||
590 | * See drm_plane_create_color_properties(). | ||
591 | */ | ||
592 | struct drm_property *color_range_property; | ||
561 | }; | 593 | }; |
562 | 594 | ||
563 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) | 595 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) |
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 8aa49c0ecd4d..28d7ce620729 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h | |||
@@ -43,7 +43,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane, | |||
43 | struct drm_framebuffer *fb, | 43 | struct drm_framebuffer *fb, |
44 | struct drm_rect *src, | 44 | struct drm_rect *src, |
45 | struct drm_rect *dest, | 45 | struct drm_rect *dest, |
46 | const struct drm_rect *clip, | ||
47 | unsigned int rotation, | 46 | unsigned int rotation, |
48 | int min_scale, | 47 | int min_scale, |
49 | int max_scale, | 48 | int max_scale, |
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index 8a522b4bed40..937757a8a568 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h | |||
@@ -237,27 +237,29 @@ static inline bool drm_property_type_is(struct drm_property *property, | |||
237 | return property->flags & type; | 237 | return property->flags & type; |
238 | } | 238 | } |
239 | 239 | ||
240 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, | 240 | struct drm_property *drm_property_create(struct drm_device *dev, |
241 | const char *name, int num_values); | 241 | u32 flags, const char *name, |
242 | struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, | 242 | int num_values); |
243 | const char *name, | 243 | struct drm_property *drm_property_create_enum(struct drm_device *dev, |
244 | u32 flags, const char *name, | ||
244 | const struct drm_prop_enum_list *props, | 245 | const struct drm_prop_enum_list *props, |
245 | int num_values); | 246 | int num_values); |
246 | struct drm_property *drm_property_create_bitmask(struct drm_device *dev, | 247 | struct drm_property *drm_property_create_bitmask(struct drm_device *dev, |
247 | int flags, const char *name, | 248 | u32 flags, const char *name, |
248 | const struct drm_prop_enum_list *props, | 249 | const struct drm_prop_enum_list *props, |
249 | int num_props, | 250 | int num_props, |
250 | uint64_t supported_bits); | 251 | uint64_t supported_bits); |
251 | struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, | 252 | struct drm_property *drm_property_create_range(struct drm_device *dev, |
252 | const char *name, | 253 | u32 flags, const char *name, |
253 | uint64_t min, uint64_t max); | 254 | uint64_t min, uint64_t max); |
254 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, | 255 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, |
255 | int flags, const char *name, | 256 | u32 flags, const char *name, |
256 | int64_t min, int64_t max); | 257 | int64_t min, int64_t max); |
257 | struct drm_property *drm_property_create_object(struct drm_device *dev, | 258 | struct drm_property *drm_property_create_object(struct drm_device *dev, |
258 | int flags, const char *name, uint32_t type); | 259 | u32 flags, const char *name, |
259 | struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags, | 260 | uint32_t type); |
260 | const char *name); | 261 | struct drm_property *drm_property_create_bool(struct drm_device *dev, |
262 | u32 flags, const char *name); | ||
261 | int drm_property_add_enum(struct drm_property *property, int index, | 263 | int drm_property_add_enum(struct drm_property *property, int index, |
262 | uint64_t value, const char *name); | 264 | uint64_t value, const char *name); |
263 | void drm_property_destroy(struct drm_device *dev, struct drm_property *property); | 265 | void drm_property_destroy(struct drm_device *dev, struct drm_property *property); |
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index d9e4c3c3f009..1b4e352143fd 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h | |||
@@ -24,9 +24,30 @@ struct drm_simple_display_pipe_funcs { | |||
24 | /** | 24 | /** |
25 | * @mode_valid: | 25 | * @mode_valid: |
26 | * | 26 | * |
27 | * This function is called to filter out valid modes from the | 27 | * This callback is used to check if a specific mode is valid in the |
28 | * suggestions suggested by the bridge or display. This optional | 28 | * crtc used in this simple display pipe. This should be implemented |
29 | * hook is passed in when initializing the pipeline. | 29 | * if the display pipe has some sort of restriction in the modes |
30 | * it can display. For example, a given display pipe may be responsible | ||
31 | * to set a clock value. If the clock can not produce all the values | ||
32 | * for the available modes then this callback can be used to restrict | ||
33 | * the number of modes to only the ones that can be displayed. Another | ||
34 | * reason can be bandwidth mitigation: the memory port on the display | ||
35 | * controller can have bandwidth limitations not allowing pixel data | ||
36 | * to be fetched at any rate. | ||
37 | * | ||
38 | * This hook is used by the probe helpers to filter the mode list in | ||
39 | * drm_helper_probe_single_connector_modes(), and it is used by the | ||
40 | * atomic helpers to validate modes supplied by userspace in | ||
41 | * drm_atomic_helper_check_modeset(). | ||
42 | * | ||
43 | * This function is optional. | ||
44 | * | ||
45 | * NOTE: | ||
46 | * | ||
47 | * Since this function is both called from the check phase of an atomic | ||
48 | * commit, and the mode validation in the probe paths it is not allowed | ||
49 | * to look at anything else but the passed-in mode, and validate it | ||
50 | * against configuration-invariant hardware constraints. | ||
30 | * | 51 | * |
31 | * RETURNS: | 52 | * RETURNS: |
32 | * | 53 | * |
@@ -107,6 +128,24 @@ struct drm_simple_display_pipe_funcs { | |||
107 | */ | 128 | */ |
108 | void (*cleanup_fb)(struct drm_simple_display_pipe *pipe, | 129 | void (*cleanup_fb)(struct drm_simple_display_pipe *pipe, |
109 | struct drm_plane_state *plane_state); | 130 | struct drm_plane_state *plane_state); |
131 | |||
132 | /** | ||
133 | * @enable_vblank: | ||
134 | * | ||
135 | * Optional, called by &drm_crtc_funcs.enable_vblank. Please read | ||
136 | * the documentation for the &drm_crtc_funcs.enable_vblank hook for | ||
137 | * more details. | ||
138 | */ | ||
139 | int (*enable_vblank)(struct drm_simple_display_pipe *pipe); | ||
140 | |||
141 | /** | ||
142 | * @disable_vblank: | ||
143 | * | ||
144 | * Optional, called by &drm_crtc_funcs.disable_vblank. Please read | ||
145 | * the documentation for the &drm_crtc_funcs.disable_vblank hook for | ||
146 | * more details. | ||
147 | */ | ||
148 | void (*disable_vblank)(struct drm_simple_display_pipe *pipe); | ||
110 | }; | 149 | }; |
111 | 150 | ||
112 | /** | 151 | /** |
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 2c575794fb52..50bcf4214ff9 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h | |||
@@ -363,7 +363,7 @@ struct drm_mode_get_connector { | |||
363 | __u32 pad; | 363 | __u32 pad; |
364 | }; | 364 | }; |
365 | 365 | ||
366 | #define DRM_MODE_PROP_PENDING (1<<0) | 366 | #define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ |
367 | #define DRM_MODE_PROP_RANGE (1<<1) | 367 | #define DRM_MODE_PROP_RANGE (1<<1) |
368 | #define DRM_MODE_PROP_IMMUTABLE (1<<2) | 368 | #define DRM_MODE_PROP_IMMUTABLE (1<<2) |
369 | #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ | 369 | #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ |
@@ -598,8 +598,11 @@ struct drm_mode_crtc_lut { | |||
598 | }; | 598 | }; |
599 | 599 | ||
600 | struct drm_color_ctm { | 600 | struct drm_color_ctm { |
601 | /* Conversion matrix in S31.32 format. */ | 601 | /* |
602 | __s64 matrix[9]; | 602 | * Conversion matrix in S31.32 sign-magnitude |
603 | * (not two's complement!) format. | ||
604 | */ | ||
605 | __u64 matrix[9]; | ||
603 | }; | 606 | }; |
604 | 607 | ||
605 | struct drm_color_lut { | 608 | struct drm_color_lut { |