diff options
73 files changed, 3429 insertions, 2235 deletions
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt index 708f5664a316..383183a89164 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt | |||
@@ -40,6 +40,7 @@ Required properties (all function blocks): | |||
40 | "mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt | 40 | "mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt |
41 | "mediatek,<chip>-disp-mutex" - display mutex | 41 | "mediatek,<chip>-disp-mutex" - display mutex |
42 | "mediatek,<chip>-disp-od" - overdrive | 42 | "mediatek,<chip>-disp-od" - overdrive |
43 | the supported chips are mt2701 and mt8173. | ||
43 | - reg: Physical base address and length of the function block register space | 44 | - reg: Physical base address and length of the function block register space |
44 | - interrupts: The interrupt signal from the function block (required, except for | 45 | - interrupts: The interrupt signal from the function block (required, except for |
45 | merge and split function blocks). | 46 | merge and split function blocks). |
@@ -54,6 +55,7 @@ Required properties (DMA function blocks): | |||
54 | "mediatek,<chip>-disp-ovl" | 55 | "mediatek,<chip>-disp-ovl" |
55 | "mediatek,<chip>-disp-rdma" | 56 | "mediatek,<chip>-disp-rdma" |
56 | "mediatek,<chip>-disp-wdma" | 57 | "mediatek,<chip>-disp-wdma" |
58 | the supported chips are mt2701 and mt8173. | ||
57 | - larb: Should contain a phandle pointing to the local arbiter device as defined | 59 | - larb: Should contain a phandle pointing to the local arbiter device as defined |
58 | in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt | 60 | in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt |
59 | - iommus: Should point to the respective IOMMU block with master port as | 61 | - iommus: Should point to the respective IOMMU block with master port as |
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt index 2b1585a34b85..fadf327c7cdf 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt | |||
@@ -7,6 +7,7 @@ channel output. | |||
7 | 7 | ||
8 | Required properties: | 8 | Required properties: |
9 | - compatible: "mediatek,<chip>-dsi" | 9 | - compatible: "mediatek,<chip>-dsi" |
10 | the supported chips are mt2701 and mt8173. | ||
10 | - reg: Physical base address and length of the controller's registers | 11 | - reg: Physical base address and length of the controller's registers |
11 | - interrupts: The interrupt signal from the function block. | 12 | - interrupts: The interrupt signal from the function block. |
12 | - clocks: device clocks | 13 | - clocks: device clocks |
@@ -25,6 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY. | |||
25 | 26 | ||
26 | Required properties: | 27 | Required properties: |
27 | - compatible: "mediatek,<chip>-mipi-tx" | 28 | - compatible: "mediatek,<chip>-mipi-tx" |
29 | the supported chips are mt2701 and mt8173. | ||
28 | - reg: Physical base address and length of the controller's registers | 30 | - reg: Physical base address and length of the controller's registers |
29 | - clocks: PLL reference clock | 31 | - clocks: PLL reference clock |
30 | - clock-output-names: name of the output clock line to the DSI encoder | 32 | - clock-output-names: name of the output clock line to the DSI encoder |
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 6f972afbdbc3..94f2e701e4d4 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | |||
@@ -1215,7 +1215,7 @@ static int gen8_check_mi_display_flip(struct parser_exec_state *s, | |||
1215 | if (!info->async_flip) | 1215 | if (!info->async_flip) |
1216 | return 0; | 1216 | return 0; |
1217 | 1217 | ||
1218 | if (IS_SKYLAKE(dev_priv)) { | 1218 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
1219 | stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0); | 1219 | stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0); |
1220 | tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & | 1220 | tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & |
1221 | GENMASK(12, 10)) >> 10; | 1221 | GENMASK(12, 10)) >> 10; |
@@ -1243,7 +1243,7 @@ static int gen8_update_plane_mmio_from_mi_display_flip( | |||
1243 | 1243 | ||
1244 | set_mask_bits(&vgpu_vreg(vgpu, info->surf_reg), GENMASK(31, 12), | 1244 | set_mask_bits(&vgpu_vreg(vgpu, info->surf_reg), GENMASK(31, 12), |
1245 | info->surf_val << 12); | 1245 | info->surf_val << 12); |
1246 | if (IS_SKYLAKE(dev_priv)) { | 1246 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
1247 | set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(9, 0), | 1247 | set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(9, 0), |
1248 | info->stride_val); | 1248 | info->stride_val); |
1249 | set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(12, 10), | 1249 | set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(12, 10), |
@@ -1267,7 +1267,7 @@ static int decode_mi_display_flip(struct parser_exec_state *s, | |||
1267 | 1267 | ||
1268 | if (IS_BROADWELL(dev_priv)) | 1268 | if (IS_BROADWELL(dev_priv)) |
1269 | return gen8_decode_mi_display_flip(s, info); | 1269 | return gen8_decode_mi_display_flip(s, info); |
1270 | if (IS_SKYLAKE(dev_priv)) | 1270 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
1271 | return skl_decode_mi_display_flip(s, info); | 1271 | return skl_decode_mi_display_flip(s, info); |
1272 | 1272 | ||
1273 | return -ENODEV; | 1273 | return -ENODEV; |
@@ -1278,7 +1278,9 @@ static int check_mi_display_flip(struct parser_exec_state *s, | |||
1278 | { | 1278 | { |
1279 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | 1279 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; |
1280 | 1280 | ||
1281 | if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) | 1281 | if (IS_BROADWELL(dev_priv) |
1282 | || IS_SKYLAKE(dev_priv) | ||
1283 | || IS_KABYLAKE(dev_priv)) | ||
1282 | return gen8_check_mi_display_flip(s, info); | 1284 | return gen8_check_mi_display_flip(s, info); |
1283 | return -ENODEV; | 1285 | return -ENODEV; |
1284 | } | 1286 | } |
@@ -1289,7 +1291,9 @@ static int update_plane_mmio_from_mi_display_flip( | |||
1289 | { | 1291 | { |
1290 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | 1292 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; |
1291 | 1293 | ||
1292 | if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) | 1294 | if (IS_BROADWELL(dev_priv) |
1295 | || IS_SKYLAKE(dev_priv) | ||
1296 | || IS_KABYLAKE(dev_priv)) | ||
1293 | return gen8_update_plane_mmio_from_mi_display_flip(s, info); | 1297 | return gen8_update_plane_mmio_from_mi_display_flip(s, info); |
1294 | return -ENODEV; | 1298 | return -ENODEV; |
1295 | } | 1299 | } |
@@ -1569,7 +1573,8 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s) | |||
1569 | { | 1573 | { |
1570 | struct intel_gvt *gvt = s->vgpu->gvt; | 1574 | struct intel_gvt *gvt = s->vgpu->gvt; |
1571 | 1575 | ||
1572 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | 1576 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) |
1577 | || IS_KABYLAKE(gvt->dev_priv)) { | ||
1573 | /* BDW decides privilege based on address space */ | 1578 | /* BDW decides privilege based on address space */ |
1574 | if (cmd_val(s, 0) & (1 << 8)) | 1579 | if (cmd_val(s, 0) & (1 << 8)) |
1575 | return 0; | 1580 | return 0; |
@@ -2604,6 +2609,9 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2604 | unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail; | 2609 | unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail; |
2605 | struct parser_exec_state s; | 2610 | struct parser_exec_state s; |
2606 | int ret = 0; | 2611 | int ret = 0; |
2612 | struct intel_vgpu_workload *workload = container_of(wa_ctx, | ||
2613 | struct intel_vgpu_workload, | ||
2614 | wa_ctx); | ||
2607 | 2615 | ||
2608 | /* ring base is page aligned */ | 2616 | /* ring base is page aligned */ |
2609 | if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE))) | 2617 | if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE))) |
@@ -2618,14 +2626,14 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2618 | 2626 | ||
2619 | s.buf_type = RING_BUFFER_INSTRUCTION; | 2627 | s.buf_type = RING_BUFFER_INSTRUCTION; |
2620 | s.buf_addr_type = GTT_BUFFER; | 2628 | s.buf_addr_type = GTT_BUFFER; |
2621 | s.vgpu = wa_ctx->workload->vgpu; | 2629 | s.vgpu = workload->vgpu; |
2622 | s.ring_id = wa_ctx->workload->ring_id; | 2630 | s.ring_id = workload->ring_id; |
2623 | s.ring_start = wa_ctx->indirect_ctx.guest_gma; | 2631 | s.ring_start = wa_ctx->indirect_ctx.guest_gma; |
2624 | s.ring_size = ring_size; | 2632 | s.ring_size = ring_size; |
2625 | s.ring_head = gma_head; | 2633 | s.ring_head = gma_head; |
2626 | s.ring_tail = gma_tail; | 2634 | s.ring_tail = gma_tail; |
2627 | s.rb_va = wa_ctx->indirect_ctx.shadow_va; | 2635 | s.rb_va = wa_ctx->indirect_ctx.shadow_va; |
2628 | s.workload = wa_ctx->workload; | 2636 | s.workload = workload; |
2629 | 2637 | ||
2630 | ret = ip_gma_set(&s, gma_head); | 2638 | ret = ip_gma_set(&s, gma_head); |
2631 | if (ret) | 2639 | if (ret) |
@@ -2708,12 +2716,15 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2708 | { | 2716 | { |
2709 | int ctx_size = wa_ctx->indirect_ctx.size; | 2717 | int ctx_size = wa_ctx->indirect_ctx.size; |
2710 | unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; | 2718 | unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; |
2711 | struct intel_vgpu *vgpu = wa_ctx->workload->vgpu; | 2719 | struct intel_vgpu_workload *workload = container_of(wa_ctx, |
2720 | struct intel_vgpu_workload, | ||
2721 | wa_ctx); | ||
2722 | struct intel_vgpu *vgpu = workload->vgpu; | ||
2712 | struct drm_i915_gem_object *obj; | 2723 | struct drm_i915_gem_object *obj; |
2713 | int ret = 0; | 2724 | int ret = 0; |
2714 | void *map; | 2725 | void *map; |
2715 | 2726 | ||
2716 | obj = i915_gem_object_create(wa_ctx->workload->vgpu->gvt->dev_priv, | 2727 | obj = i915_gem_object_create(workload->vgpu->gvt->dev_priv, |
2717 | roundup(ctx_size + CACHELINE_BYTES, | 2728 | roundup(ctx_size + CACHELINE_BYTES, |
2718 | PAGE_SIZE)); | 2729 | PAGE_SIZE)); |
2719 | if (IS_ERR(obj)) | 2730 | if (IS_ERR(obj)) |
@@ -2733,8 +2744,8 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2733 | goto unmap_src; | 2744 | goto unmap_src; |
2734 | } | 2745 | } |
2735 | 2746 | ||
2736 | ret = copy_gma_to_hva(wa_ctx->workload->vgpu, | 2747 | ret = copy_gma_to_hva(workload->vgpu, |
2737 | wa_ctx->workload->vgpu->gtt.ggtt_mm, | 2748 | workload->vgpu->gtt.ggtt_mm, |
2738 | guest_gma, guest_gma + ctx_size, | 2749 | guest_gma, guest_gma + ctx_size, |
2739 | map); | 2750 | map); |
2740 | if (ret < 0) { | 2751 | if (ret < 0) { |
@@ -2772,7 +2783,10 @@ static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2772 | int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | 2783 | int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) |
2773 | { | 2784 | { |
2774 | int ret; | 2785 | int ret; |
2775 | struct intel_vgpu *vgpu = wa_ctx->workload->vgpu; | 2786 | struct intel_vgpu_workload *workload = container_of(wa_ctx, |
2787 | struct intel_vgpu_workload, | ||
2788 | wa_ctx); | ||
2789 | struct intel_vgpu *vgpu = workload->vgpu; | ||
2776 | 2790 | ||
2777 | if (wa_ctx->indirect_ctx.size == 0) | 2791 | if (wa_ctx->indirect_ctx.size == 0) |
2778 | return 0; | 2792 | return 0; |
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 5419ae6ec633..4cf2b29fbaa1 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c | |||
@@ -161,8 +161,9 @@ static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { | |||
161 | 161 | ||
162 | #define DPCD_HEADER_SIZE 0xb | 162 | #define DPCD_HEADER_SIZE 0xb |
163 | 163 | ||
164 | /* let the virtual display supports DP1.2 */ | ||
164 | static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { | 165 | static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { |
165 | 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 166 | 0x12, 0x014, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
166 | }; | 167 | }; |
167 | 168 | ||
168 | static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | 169 | static void emulate_monitor_status_change(struct intel_vgpu *vgpu) |
@@ -172,9 +173,20 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | |||
172 | SDE_PORTC_HOTPLUG_CPT | | 173 | SDE_PORTC_HOTPLUG_CPT | |
173 | SDE_PORTD_HOTPLUG_CPT); | 174 | SDE_PORTD_HOTPLUG_CPT); |
174 | 175 | ||
175 | if (IS_SKYLAKE(dev_priv)) | 176 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
176 | vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT | | 177 | vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT | |
177 | SDE_PORTE_HOTPLUG_SPT); | 178 | SDE_PORTE_HOTPLUG_SPT); |
179 | vgpu_vreg(vgpu, SKL_FUSE_STATUS) |= | ||
180 | SKL_FUSE_DOWNLOAD_STATUS | | ||
181 | SKL_FUSE_PG0_DIST_STATUS | | ||
182 | SKL_FUSE_PG1_DIST_STATUS | | ||
183 | SKL_FUSE_PG2_DIST_STATUS; | ||
184 | vgpu_vreg(vgpu, LCPLL1_CTL) |= | ||
185 | LCPLL_PLL_ENABLE | | ||
186 | LCPLL_PLL_LOCK; | ||
187 | vgpu_vreg(vgpu, LCPLL2_CTL) |= LCPLL_PLL_ENABLE; | ||
188 | |||
189 | } | ||
178 | 190 | ||
179 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { | 191 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { |
180 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; | 192 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; |
@@ -191,7 +203,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | |||
191 | vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED; | 203 | vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED; |
192 | } | 204 | } |
193 | 205 | ||
194 | if (IS_SKYLAKE(dev_priv) && | 206 | if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && |
195 | intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { | 207 | intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { |
196 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT; | 208 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT; |
197 | } | 209 | } |
@@ -353,7 +365,7 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu) | |||
353 | { | 365 | { |
354 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | 366 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; |
355 | 367 | ||
356 | if (IS_SKYLAKE(dev_priv)) | 368 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
357 | clean_virtual_dp_monitor(vgpu, PORT_D); | 369 | clean_virtual_dp_monitor(vgpu, PORT_D); |
358 | else | 370 | else |
359 | clean_virtual_dp_monitor(vgpu, PORT_B); | 371 | clean_virtual_dp_monitor(vgpu, PORT_B); |
@@ -375,7 +387,7 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution) | |||
375 | 387 | ||
376 | intel_vgpu_init_i2c_edid(vgpu); | 388 | intel_vgpu_init_i2c_edid(vgpu); |
377 | 389 | ||
378 | if (IS_SKYLAKE(dev_priv)) | 390 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
379 | return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D, | 391 | return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D, |
380 | resolution); | 392 | resolution); |
381 | else | 393 | else |
diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index f1f426a97aa9..ce4276a7cf9c 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c | |||
@@ -394,9 +394,11 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |||
394 | 394 | ||
395 | static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) | 395 | static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) |
396 | { | 396 | { |
397 | int ring_id = wa_ctx->workload->ring_id; | 397 | struct intel_vgpu_workload *workload = container_of(wa_ctx, |
398 | struct i915_gem_context *shadow_ctx = | 398 | struct intel_vgpu_workload, |
399 | wa_ctx->workload->vgpu->shadow_ctx; | 399 | wa_ctx); |
400 | int ring_id = workload->ring_id; | ||
401 | struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | ||
400 | struct drm_i915_gem_object *ctx_obj = | 402 | struct drm_i915_gem_object *ctx_obj = |
401 | shadow_ctx->engine[ring_id].state->obj; | 403 | shadow_ctx->engine[ring_id].state->obj; |
402 | struct execlist_ring_context *shadow_ring_context; | 404 | struct execlist_ring_context *shadow_ring_context; |
@@ -680,7 +682,6 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id, | |||
680 | CACHELINE_BYTES; | 682 | CACHELINE_BYTES; |
681 | workload->wa_ctx.per_ctx.guest_gma = | 683 | workload->wa_ctx.per_ctx.guest_gma = |
682 | per_ctx & PER_CTX_ADDR_MASK; | 684 | per_ctx & PER_CTX_ADDR_MASK; |
683 | workload->wa_ctx.workload = workload; | ||
684 | 685 | ||
685 | WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1)); | 686 | WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1)); |
686 | } | 687 | } |
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index da7312715824..69d3d8ddecc2 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c | |||
@@ -2220,7 +2220,8 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt) | |||
2220 | 2220 | ||
2221 | gvt_dbg_core("init gtt\n"); | 2221 | gvt_dbg_core("init gtt\n"); |
2222 | 2222 | ||
2223 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | 2223 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) |
2224 | || IS_KABYLAKE(gvt->dev_priv)) { | ||
2224 | gvt->gtt.pte_ops = &gen8_gtt_pte_ops; | 2225 | gvt->gtt.pte_ops = &gen8_gtt_pte_ops; |
2225 | gvt->gtt.gma_ops = &gen8_gtt_gma_ops; | 2226 | gvt->gtt.gma_ops = &gen8_gtt_gma_ops; |
2226 | gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table; | 2227 | gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table; |
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 3b9d59e457ba..0f3a98865a58 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c | |||
@@ -106,7 +106,8 @@ static void init_device_info(struct intel_gvt *gvt) | |||
106 | struct intel_gvt_device_info *info = &gvt->device_info; | 106 | struct intel_gvt_device_info *info = &gvt->device_info; |
107 | struct pci_dev *pdev = gvt->dev_priv->drm.pdev; | 107 | struct pci_dev *pdev = gvt->dev_priv->drm.pdev; |
108 | 108 | ||
109 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | 109 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) |
110 | || IS_KABYLAKE(gvt->dev_priv)) { | ||
110 | info->max_support_vgpus = 8; | 111 | info->max_support_vgpus = 8; |
111 | info->cfg_space_size = 256; | 112 | info->cfg_space_size = 256; |
112 | info->mmio_size = 2 * 1024 * 1024; | 113 | info->mmio_size = 2 * 1024 * 1024; |
@@ -143,6 +144,11 @@ static int gvt_service_thread(void *data) | |||
143 | intel_gvt_emulate_vblank(gvt); | 144 | intel_gvt_emulate_vblank(gvt); |
144 | mutex_unlock(&gvt->lock); | 145 | mutex_unlock(&gvt->lock); |
145 | } | 146 | } |
147 | |||
148 | if (test_and_clear_bit(INTEL_GVT_REQUEST_SCHED, | ||
149 | (void *)&gvt->service_request)) { | ||
150 | intel_gvt_schedule(gvt); | ||
151 | } | ||
146 | } | 152 | } |
147 | 153 | ||
148 | return 0; | 154 | return 0; |
@@ -196,6 +202,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) | |||
196 | 202 | ||
197 | idr_destroy(&gvt->vgpu_idr); | 203 | idr_destroy(&gvt->vgpu_idr); |
198 | 204 | ||
205 | intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); | ||
206 | |||
199 | kfree(dev_priv->gvt); | 207 | kfree(dev_priv->gvt); |
200 | dev_priv->gvt = NULL; | 208 | dev_priv->gvt = NULL; |
201 | } | 209 | } |
@@ -214,6 +222,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) | |||
214 | int intel_gvt_init_device(struct drm_i915_private *dev_priv) | 222 | int intel_gvt_init_device(struct drm_i915_private *dev_priv) |
215 | { | 223 | { |
216 | struct intel_gvt *gvt; | 224 | struct intel_gvt *gvt; |
225 | struct intel_vgpu *vgpu; | ||
217 | int ret; | 226 | int ret; |
218 | 227 | ||
219 | /* | 228 | /* |
@@ -286,6 +295,14 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) | |||
286 | goto out_clean_types; | 295 | goto out_clean_types; |
287 | } | 296 | } |
288 | 297 | ||
298 | vgpu = intel_gvt_create_idle_vgpu(gvt); | ||
299 | if (IS_ERR(vgpu)) { | ||
300 | ret = PTR_ERR(vgpu); | ||
301 | gvt_err("failed to create idle vgpu\n"); | ||
302 | goto out_clean_types; | ||
303 | } | ||
304 | gvt->idle_vgpu = vgpu; | ||
305 | |||
289 | gvt_dbg_core("gvt device initialization is done\n"); | 306 | gvt_dbg_core("gvt device initialization is done\n"); |
290 | dev_priv->gvt = gvt; | 307 | dev_priv->gvt = gvt; |
291 | return 0; | 308 | return 0; |
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 6dfc48b63b71..806da96b6a92 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h | |||
@@ -138,6 +138,10 @@ struct intel_vgpu_display { | |||
138 | struct intel_vgpu_sbi sbi; | 138 | struct intel_vgpu_sbi sbi; |
139 | }; | 139 | }; |
140 | 140 | ||
141 | struct vgpu_sched_ctl { | ||
142 | int weight; | ||
143 | }; | ||
144 | |||
141 | struct intel_vgpu { | 145 | struct intel_vgpu { |
142 | struct intel_gvt *gvt; | 146 | struct intel_gvt *gvt; |
143 | int id; | 147 | int id; |
@@ -147,6 +151,7 @@ struct intel_vgpu { | |||
147 | bool failsafe; | 151 | bool failsafe; |
148 | bool resetting; | 152 | bool resetting; |
149 | void *sched_data; | 153 | void *sched_data; |
154 | struct vgpu_sched_ctl sched_ctl; | ||
150 | 155 | ||
151 | struct intel_vgpu_fence fence; | 156 | struct intel_vgpu_fence fence; |
152 | struct intel_vgpu_gm gm; | 157 | struct intel_vgpu_gm gm; |
@@ -160,6 +165,7 @@ struct intel_vgpu { | |||
160 | struct list_head workload_q_head[I915_NUM_ENGINES]; | 165 | struct list_head workload_q_head[I915_NUM_ENGINES]; |
161 | struct kmem_cache *workloads; | 166 | struct kmem_cache *workloads; |
162 | atomic_t running_workload_num; | 167 | atomic_t running_workload_num; |
168 | ktime_t last_ctx_submit_time; | ||
163 | DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); | 169 | DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); |
164 | struct i915_gem_context *shadow_ctx; | 170 | struct i915_gem_context *shadow_ctx; |
165 | 171 | ||
@@ -215,6 +221,7 @@ struct intel_vgpu_type { | |||
215 | unsigned int low_gm_size; | 221 | unsigned int low_gm_size; |
216 | unsigned int high_gm_size; | 222 | unsigned int high_gm_size; |
217 | unsigned int fence; | 223 | unsigned int fence; |
224 | unsigned int weight; | ||
218 | enum intel_vgpu_edid resolution; | 225 | enum intel_vgpu_edid resolution; |
219 | }; | 226 | }; |
220 | 227 | ||
@@ -236,6 +243,7 @@ struct intel_gvt { | |||
236 | DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); | 243 | DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); |
237 | struct intel_vgpu_type *types; | 244 | struct intel_vgpu_type *types; |
238 | unsigned int num_types; | 245 | unsigned int num_types; |
246 | struct intel_vgpu *idle_vgpu; | ||
239 | 247 | ||
240 | struct task_struct *service_thread; | 248 | struct task_struct *service_thread; |
241 | wait_queue_head_t service_thread_wq; | 249 | wait_queue_head_t service_thread_wq; |
@@ -249,6 +257,7 @@ static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915) | |||
249 | 257 | ||
250 | enum { | 258 | enum { |
251 | INTEL_GVT_REQUEST_EMULATE_VBLANK = 0, | 259 | INTEL_GVT_REQUEST_EMULATE_VBLANK = 0, |
260 | INTEL_GVT_REQUEST_SCHED = 1, | ||
252 | }; | 261 | }; |
253 | 262 | ||
254 | static inline void intel_gvt_request_service(struct intel_gvt *gvt, | 263 | static inline void intel_gvt_request_service(struct intel_gvt *gvt, |
@@ -322,6 +331,8 @@ struct intel_vgpu_creation_params { | |||
322 | __u64 resolution; | 331 | __u64 resolution; |
323 | __s32 primary; | 332 | __s32 primary; |
324 | __u64 vgpu_id; | 333 | __u64 vgpu_id; |
334 | |||
335 | __u32 weight; | ||
325 | }; | 336 | }; |
326 | 337 | ||
327 | int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, | 338 | int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, |
@@ -376,6 +387,8 @@ static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu, | |||
376 | int intel_gvt_init_vgpu_types(struct intel_gvt *gvt); | 387 | int intel_gvt_init_vgpu_types(struct intel_gvt *gvt); |
377 | void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt); | 388 | void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt); |
378 | 389 | ||
390 | struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt); | ||
391 | void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu); | ||
379 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | 392 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, |
380 | struct intel_vgpu_type *type); | 393 | struct intel_vgpu_type *type); |
381 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu); | 394 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu); |
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index eaff45d417e8..68600a3c46e5 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c | |||
@@ -68,6 +68,8 @@ unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt) | |||
68 | return D_BDW; | 68 | return D_BDW; |
69 | else if (IS_SKYLAKE(gvt->dev_priv)) | 69 | else if (IS_SKYLAKE(gvt->dev_priv)) |
70 | return D_SKL; | 70 | return D_SKL; |
71 | else if (IS_KABYLAKE(gvt->dev_priv)) | ||
72 | return D_KBL; | ||
71 | 73 | ||
72 | return 0; | 74 | return 0; |
73 | } | 75 | } |
@@ -234,7 +236,8 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu, | |||
234 | old = vgpu_vreg(vgpu, offset); | 236 | old = vgpu_vreg(vgpu, offset); |
235 | new = CALC_MODE_MASK_REG(old, *(u32 *)p_data); | 237 | new = CALC_MODE_MASK_REG(old, *(u32 *)p_data); |
236 | 238 | ||
237 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { | 239 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) |
240 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) { | ||
238 | switch (offset) { | 241 | switch (offset) { |
239 | case FORCEWAKE_RENDER_GEN9_REG: | 242 | case FORCEWAKE_RENDER_GEN9_REG: |
240 | ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG; | 243 | ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG; |
@@ -823,8 +826,9 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu, | |||
823 | write_vreg(vgpu, offset, p_data, bytes); | 826 | write_vreg(vgpu, offset, p_data, bytes); |
824 | data = vgpu_vreg(vgpu, offset); | 827 | data = vgpu_vreg(vgpu, offset); |
825 | 828 | ||
826 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) && | 829 | if ((IS_SKYLAKE(vgpu->gvt->dev_priv) |
827 | offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) { | 830 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) |
831 | && offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) { | ||
828 | /* SKL DPB/C/D aux ctl register changed */ | 832 | /* SKL DPB/C/D aux ctl register changed */ |
829 | return 0; | 833 | return 0; |
830 | } else if (IS_BROADWELL(vgpu->gvt->dev_priv) && | 834 | } else if (IS_BROADWELL(vgpu->gvt->dev_priv) && |
@@ -1303,7 +1307,8 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
1303 | 1307 | ||
1304 | switch (cmd) { | 1308 | switch (cmd) { |
1305 | case GEN9_PCODE_READ_MEM_LATENCY: | 1309 | case GEN9_PCODE_READ_MEM_LATENCY: |
1306 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { | 1310 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) |
1311 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) { | ||
1307 | /** | 1312 | /** |
1308 | * "Read memory latency" command on gen9. | 1313 | * "Read memory latency" command on gen9. |
1309 | * Below memory latency values are read | 1314 | * Below memory latency values are read |
@@ -1316,7 +1321,8 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
1316 | } | 1321 | } |
1317 | break; | 1322 | break; |
1318 | case SKL_PCODE_CDCLK_CONTROL: | 1323 | case SKL_PCODE_CDCLK_CONTROL: |
1319 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) | 1324 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) |
1325 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) | ||
1320 | *data0 = SKL_CDCLK_READY_FOR_CHANGE; | 1326 | *data0 = SKL_CDCLK_READY_FOR_CHANGE; |
1321 | break; | 1327 | break; |
1322 | case GEN6_PCODE_READ_RC6VIDS: | 1328 | case GEN6_PCODE_READ_RC6VIDS: |
@@ -1410,6 +1416,7 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
1410 | 1416 | ||
1411 | execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; | 1417 | execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; |
1412 | if (execlist->elsp_dwords.index == 3) { | 1418 | if (execlist->elsp_dwords.index == 3) { |
1419 | vgpu->last_ctx_submit_time = ktime_get(); | ||
1413 | ret = intel_vgpu_submit_execlist(vgpu, ring_id); | 1420 | ret = intel_vgpu_submit_execlist(vgpu, ring_id); |
1414 | if(ret) | 1421 | if(ret) |
1415 | gvt_vgpu_err("fail submit workload on ring %d\n", | 1422 | gvt_vgpu_err("fail submit workload on ring %d\n", |
@@ -2584,219 +2591,232 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) | |||
2584 | MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); | 2591 | MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); |
2585 | MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL); | 2592 | MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL); |
2586 | 2593 | ||
2587 | MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | 2594 | MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL, |
2588 | MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | 2595 | dp_aux_ch_ctl_mmio_write); |
2589 | MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | 2596 | MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL, |
2597 | dp_aux_ch_ctl_mmio_write); | ||
2598 | MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL, | ||
2599 | dp_aux_ch_ctl_mmio_write); | ||
2590 | 2600 | ||
2591 | MMIO_D(HSW_PWR_WELL_BIOS, D_SKL); | 2601 | MMIO_D(HSW_PWR_WELL_BIOS, D_SKL_PLUS); |
2592 | MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write); | 2602 | MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL_PLUS, NULL, |
2603 | skl_power_well_ctl_write); | ||
2604 | MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL_PLUS, NULL, mailbox_write); | ||
2593 | 2605 | ||
2594 | MMIO_D(0xa210, D_SKL_PLUS); | 2606 | MMIO_D(0xa210, D_SKL_PLUS); |
2595 | MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); | 2607 | MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); |
2596 | MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); | 2608 | MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); |
2597 | MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); | 2609 | MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); |
2598 | MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write); | 2610 | MMIO_DH(0x4ddc, D_SKL_PLUS, NULL, skl_misc_ctl_write); |
2599 | MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write); | 2611 | MMIO_DH(0x42080, D_SKL_PLUS, NULL, skl_misc_ctl_write); |
2600 | MMIO_D(0x45504, D_SKL); | 2612 | MMIO_D(0x45504, D_SKL_PLUS); |
2601 | MMIO_D(0x45520, D_SKL); | 2613 | MMIO_D(0x45520, D_SKL_PLUS); |
2602 | MMIO_D(0x46000, D_SKL); | 2614 | MMIO_D(0x46000, D_SKL_PLUS); |
2603 | MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write); | 2615 | MMIO_DH(0x46010, D_SKL | D_KBL, NULL, skl_lcpll_write); |
2604 | MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write); | 2616 | MMIO_DH(0x46014, D_SKL | D_KBL, NULL, skl_lcpll_write); |
2605 | MMIO_D(0x6C040, D_SKL); | 2617 | MMIO_D(0x6C040, D_SKL | D_KBL); |
2606 | MMIO_D(0x6C048, D_SKL); | 2618 | MMIO_D(0x6C048, D_SKL | D_KBL); |
2607 | MMIO_D(0x6C050, D_SKL); | 2619 | MMIO_D(0x6C050, D_SKL | D_KBL); |
2608 | MMIO_D(0x6C044, D_SKL); | 2620 | MMIO_D(0x6C044, D_SKL | D_KBL); |
2609 | MMIO_D(0x6C04C, D_SKL); | 2621 | MMIO_D(0x6C04C, D_SKL | D_KBL); |
2610 | MMIO_D(0x6C054, D_SKL); | 2622 | MMIO_D(0x6C054, D_SKL | D_KBL); |
2611 | MMIO_D(0x6c058, D_SKL); | 2623 | MMIO_D(0x6c058, D_SKL | D_KBL); |
2612 | MMIO_D(0x6c05c, D_SKL); | 2624 | MMIO_D(0x6c05c, D_SKL | D_KBL); |
2613 | MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL); | 2625 | MMIO_DH(0X6c060, D_SKL | D_KBL, dpll_status_read, NULL); |
2614 | 2626 | ||
2615 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write); | 2627 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write); |
2616 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write); | 2628 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write); |
2617 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write); | 2629 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write); |
2618 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write); | 2630 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write); |
2619 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write); | 2631 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write); |
2620 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write); | 2632 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write); |
2621 | 2633 | ||
2622 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write); | 2634 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write); |
2623 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write); | 2635 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write); |
2624 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write); | 2636 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write); |
2625 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write); | 2637 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write); |
2626 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write); | 2638 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write); |
2627 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write); | 2639 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write); |
2628 | 2640 | ||
2629 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write); | 2641 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write); |
2630 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write); | 2642 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write); |
2631 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write); | 2643 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write); |
2632 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write); | 2644 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write); |
2633 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write); | 2645 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write); |
2634 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write); | 2646 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write); |
2635 | 2647 | ||
2636 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); | 2648 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL_PLUS, NULL, NULL); |
2637 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); | 2649 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); |
2638 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); | 2650 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); |
2639 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); | 2651 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); |
2640 | 2652 | ||
2641 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); | 2653 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL_PLUS, NULL, NULL); |
2642 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); | 2654 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); |
2643 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); | 2655 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); |
2644 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); | 2656 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); |
2645 | 2657 | ||
2646 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); | 2658 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL_PLUS, NULL, NULL); |
2647 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); | 2659 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); |
2648 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); | 2660 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); |
2649 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); | 2661 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); |
2650 | 2662 | ||
2651 | MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL); | 2663 | MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL_PLUS, NULL, NULL); |
2652 | MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL); | 2664 | MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL_PLUS, NULL, NULL); |
2653 | MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL); | 2665 | MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL_PLUS, NULL, NULL); |
2654 | 2666 | ||
2655 | MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2667 | MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2656 | MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2668 | MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2657 | MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2669 | MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2658 | 2670 | ||
2659 | MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2671 | MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2660 | MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2672 | MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2661 | MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2673 | MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2662 | 2674 | ||
2663 | MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2675 | MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2664 | MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2676 | MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2665 | MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2677 | MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2666 | 2678 | ||
2667 | MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2679 | MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2668 | MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2680 | MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2669 | MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | 2681 | MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2670 | 2682 | ||
2671 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL); | 2683 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL_PLUS, NULL, NULL); |
2672 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL); | 2684 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); |
2673 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL); | 2685 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); |
2674 | 2686 | ||
2675 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL); | 2687 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL_PLUS, NULL, NULL); |
2676 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL); | 2688 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); |
2677 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL); | 2689 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); |
2678 | 2690 | ||
2679 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL); | 2691 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL_PLUS, NULL, NULL); |
2680 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL); | 2692 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); |
2681 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL); | 2693 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); |
2682 | 2694 | ||
2683 | MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL); | 2695 | MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL_PLUS, NULL, NULL); |
2684 | MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL); | 2696 | MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL_PLUS, NULL, NULL); |
2685 | MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL); | 2697 | MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL_PLUS, NULL, NULL); |
2686 | 2698 | ||
2687 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); | 2699 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL_PLUS, NULL, NULL); |
2688 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); | 2700 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); |
2689 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); | 2701 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); |
2690 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); | 2702 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); |
2691 | 2703 | ||
2692 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); | 2704 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL_PLUS, NULL, NULL); |
2693 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); | 2705 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); |
2694 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); | 2706 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); |
2695 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); | 2707 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); |
2696 | 2708 | ||
2697 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); | 2709 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL_PLUS, NULL, NULL); |
2698 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); | 2710 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); |
2699 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); | 2711 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); |
2700 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); | 2712 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); |
2701 | 2713 | ||
2702 | MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL); | 2714 | MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); |
2703 | MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL); | 2715 | MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); |
2704 | MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL); | 2716 | MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); |
2705 | MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL); | 2717 | MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL_PLUS, NULL, NULL); |
2706 | 2718 | ||
2707 | MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL); | 2719 | MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); |
2708 | MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL); | 2720 | MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); |
2709 | MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL); | 2721 | MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); |
2710 | MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL); | 2722 | MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL_PLUS, NULL, NULL); |
2711 | 2723 | ||
2712 | MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL); | 2724 | MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); |
2713 | MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL); | 2725 | MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); |
2714 | MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL); | 2726 | MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); |
2715 | MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL); | 2727 | MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL_PLUS, NULL, NULL); |
2716 | 2728 | ||
2717 | MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL); | 2729 | MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); |
2718 | MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL); | 2730 | MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); |
2719 | MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL); | 2731 | MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); |
2720 | MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL); | 2732 | MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL_PLUS, NULL, NULL); |
2721 | 2733 | ||
2722 | MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL); | 2734 | MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); |
2723 | MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL); | 2735 | MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); |
2724 | MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL); | 2736 | MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); |
2725 | MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL); | 2737 | MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL_PLUS, NULL, NULL); |
2726 | 2738 | ||
2727 | MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL); | 2739 | MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); |
2728 | MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL); | 2740 | MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); |
2729 | MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL); | 2741 | MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); |
2730 | MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL); | 2742 | MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL_PLUS, NULL, NULL); |
2731 | 2743 | ||
2732 | MMIO_D(0x70380, D_SKL); | 2744 | MMIO_D(0x70380, D_SKL_PLUS); |
2733 | MMIO_D(0x71380, D_SKL); | 2745 | MMIO_D(0x71380, D_SKL_PLUS); |
2734 | MMIO_D(0x72380, D_SKL); | 2746 | MMIO_D(0x72380, D_SKL_PLUS); |
2735 | MMIO_D(0x7039c, D_SKL); | 2747 | MMIO_D(0x7039c, D_SKL_PLUS); |
2736 | 2748 | ||
2737 | MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL); | 2749 | MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL_PLUS, NULL, NULL); |
2738 | MMIO_D(0x8f074, D_SKL); | 2750 | MMIO_D(0x8f074, D_SKL | D_KBL); |
2739 | MMIO_D(0x8f004, D_SKL); | 2751 | MMIO_D(0x8f004, D_SKL | D_KBL); |
2740 | MMIO_D(0x8f034, D_SKL); | 2752 | MMIO_D(0x8f034, D_SKL | D_KBL); |
2741 | 2753 | ||
2742 | MMIO_D(0xb11c, D_SKL); | 2754 | MMIO_D(0xb11c, D_SKL | D_KBL); |
2743 | 2755 | ||
2744 | MMIO_D(0x51000, D_SKL); | 2756 | MMIO_D(0x51000, D_SKL | D_KBL); |
2745 | MMIO_D(0x6c00c, D_SKL); | 2757 | MMIO_D(0x6c00c, D_SKL_PLUS); |
2746 | 2758 | ||
2747 | MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL); | 2759 | MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL); |
2748 | MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL); | 2760 | MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL); |
2749 | 2761 | ||
2750 | MMIO_D(0xd08, D_SKL); | 2762 | MMIO_D(0xd08, D_SKL_PLUS); |
2751 | MMIO_DFH(0x20e0, D_SKL, F_MODE_MASK, NULL, NULL); | 2763 | MMIO_DFH(0x20e0, D_SKL_PLUS, F_MODE_MASK, NULL, NULL); |
2752 | MMIO_DFH(0x20ec, D_SKL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); | 2764 | MMIO_DFH(0x20ec, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); |
2753 | 2765 | ||
2754 | /* TRTT */ | 2766 | /* TRTT */ |
2755 | MMIO_DFH(0x4de0, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2767 | MMIO_DFH(0x4de0, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL); |
2756 | MMIO_DFH(0x4de4, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2768 | MMIO_DFH(0x4de4, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL); |
2757 | MMIO_DFH(0x4de8, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2769 | MMIO_DFH(0x4de8, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL); |
2758 | MMIO_DFH(0x4dec, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2770 | MMIO_DFH(0x4dec, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL); |
2759 | MMIO_DFH(0x4df0, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2771 | MMIO_DFH(0x4df0, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL); |
2760 | MMIO_DFH(0x4df4, D_SKL, F_CMD_ACCESS, NULL, gen9_trtte_write); | 2772 | MMIO_DFH(0x4df4, D_SKL | D_KBL, F_CMD_ACCESS, NULL, gen9_trtte_write); |
2761 | MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write); | 2773 | MMIO_DH(0x4dfc, D_SKL | D_KBL, NULL, gen9_trtt_chicken_write); |
2762 | 2774 | ||
2763 | MMIO_D(0x45008, D_SKL); | 2775 | MMIO_D(0x45008, D_SKL | D_KBL); |
2764 | 2776 | ||
2765 | MMIO_D(0x46430, D_SKL); | 2777 | MMIO_D(0x46430, D_SKL | D_KBL); |
2766 | 2778 | ||
2767 | MMIO_D(0x46520, D_SKL); | 2779 | MMIO_D(0x46520, D_SKL | D_KBL); |
2768 | 2780 | ||
2769 | MMIO_D(0xc403c, D_SKL); | 2781 | MMIO_D(0xc403c, D_SKL | D_KBL); |
2770 | MMIO_D(0xb004, D_SKL); | 2782 | MMIO_D(0xb004, D_SKL_PLUS); |
2771 | MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write); | 2783 | MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write); |
2772 | 2784 | ||
2773 | MMIO_D(0x65900, D_SKL); | 2785 | MMIO_D(0x65900, D_SKL_PLUS); |
2774 | MMIO_D(0x1082c0, D_SKL); | 2786 | MMIO_D(0x1082c0, D_SKL | D_KBL); |
2775 | MMIO_D(0x4068, D_SKL); | 2787 | MMIO_D(0x4068, D_SKL | D_KBL); |
2776 | MMIO_D(0x67054, D_SKL); | 2788 | MMIO_D(0x67054, D_SKL | D_KBL); |
2777 | MMIO_D(0x6e560, D_SKL); | 2789 | MMIO_D(0x6e560, D_SKL | D_KBL); |
2778 | MMIO_D(0x6e554, D_SKL); | 2790 | MMIO_D(0x6e554, D_SKL | D_KBL); |
2779 | MMIO_D(0x2b20, D_SKL); | 2791 | MMIO_D(0x2b20, D_SKL | D_KBL); |
2780 | MMIO_D(0x65f00, D_SKL); | 2792 | MMIO_D(0x65f00, D_SKL | D_KBL); |
2781 | MMIO_D(0x65f08, D_SKL); | 2793 | MMIO_D(0x65f08, D_SKL | D_KBL); |
2782 | MMIO_D(0x320f0, D_SKL); | 2794 | MMIO_D(0x320f0, D_SKL | D_KBL); |
2783 | 2795 | ||
2784 | MMIO_DFH(_REG_VCS2_EXCC, D_SKL, F_CMD_ACCESS, NULL, NULL); | 2796 | MMIO_DFH(_REG_VCS2_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); |
2785 | MMIO_D(0x70034, D_SKL); | 2797 | MMIO_DFH(_REG_VECS_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); |
2786 | MMIO_D(0x71034, D_SKL); | 2798 | MMIO_D(0x70034, D_SKL_PLUS); |
2787 | MMIO_D(0x72034, D_SKL); | 2799 | MMIO_D(0x71034, D_SKL_PLUS); |
2788 | 2800 | MMIO_D(0x72034, D_SKL_PLUS); | |
2789 | MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL); | 2801 | |
2790 | MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL); | 2802 | MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL_PLUS); |
2791 | MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL); | 2803 | MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL_PLUS); |
2792 | MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL); | 2804 | MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL_PLUS); |
2793 | MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL); | 2805 | MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL_PLUS); |
2794 | MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL); | 2806 | MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL_PLUS); |
2795 | 2807 | MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL_PLUS); | |
2796 | MMIO_D(0x44500, D_SKL); | 2808 | |
2809 | MMIO_D(0x44500, D_SKL_PLUS); | ||
2797 | MMIO_DFH(GEN9_CSFE_CHICKEN1_RCS, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); | 2810 | MMIO_DFH(GEN9_CSFE_CHICKEN1_RCS, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); |
2798 | MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL, F_MODE_MASK | F_CMD_ACCESS, | 2811 | MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL | D_KBL, F_MODE_MASK | F_CMD_ACCESS, |
2799 | NULL, NULL); | 2812 | NULL, NULL); |
2813 | |||
2814 | MMIO_D(0x4ab8, D_KBL); | ||
2815 | MMIO_D(0x940c, D_SKL_PLUS); | ||
2816 | MMIO_D(0x2248, D_SKL_PLUS | D_KBL); | ||
2817 | MMIO_D(0x4ab0, D_SKL | D_KBL); | ||
2818 | MMIO_D(0x20d4, D_SKL | D_KBL); | ||
2819 | |||
2800 | return 0; | 2820 | return 0; |
2801 | } | 2821 | } |
2802 | 2822 | ||
@@ -2873,7 +2893,8 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt) | |||
2873 | ret = init_broadwell_mmio_info(gvt); | 2893 | ret = init_broadwell_mmio_info(gvt); |
2874 | if (ret) | 2894 | if (ret) |
2875 | goto err; | 2895 | goto err; |
2876 | } else if (IS_SKYLAKE(dev_priv)) { | 2896 | } else if (IS_SKYLAKE(dev_priv) |
2897 | || IS_KABYLAKE(dev_priv)) { | ||
2877 | ret = init_broadwell_mmio_info(gvt); | 2898 | ret = init_broadwell_mmio_info(gvt); |
2878 | if (ret) | 2899 | if (ret) |
2879 | goto err; | 2900 | goto err; |
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c index 92bb247e3478..9d6812f0957f 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.c +++ b/drivers/gpu/drm/i915/gvt/interrupt.c | |||
@@ -580,7 +580,7 @@ static void gen8_init_irq( | |||
580 | 580 | ||
581 | SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | 581 | SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); |
582 | SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | 582 | SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); |
583 | } else if (IS_SKYLAKE(gvt->dev_priv)) { | 583 | } else if (IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv)) { |
584 | SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT); | 584 | SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT); |
585 | SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT); | 585 | SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT); |
586 | SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT); | 586 | SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT); |
@@ -690,7 +690,8 @@ int intel_gvt_init_irq(struct intel_gvt *gvt) | |||
690 | 690 | ||
691 | gvt_dbg_core("init irq framework\n"); | 691 | gvt_dbg_core("init irq framework\n"); |
692 | 692 | ||
693 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | 693 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) |
694 | || IS_KABYLAKE(gvt->dev_priv)) { | ||
694 | irq->ops = &gen8_irq_ops; | 695 | irq->ops = &gen8_irq_ops; |
695 | irq->irq_map = gen8_irq_map; | 696 | irq->irq_map = gen8_irq_map; |
696 | } else { | 697 | } else { |
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 1ea3eb270de8..5f55d89a0959 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c | |||
@@ -295,10 +295,12 @@ static ssize_t description_show(struct kobject *kobj, struct device *dev, | |||
295 | return 0; | 295 | return 0; |
296 | 296 | ||
297 | return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" | 297 | return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" |
298 | "fence: %d\nresolution: %s\n", | 298 | "fence: %d\nresolution: %s\n" |
299 | "weight: %d\n", | ||
299 | BYTES_TO_MB(type->low_gm_size), | 300 | BYTES_TO_MB(type->low_gm_size), |
300 | BYTES_TO_MB(type->high_gm_size), | 301 | BYTES_TO_MB(type->high_gm_size), |
301 | type->fence, vgpu_edid_str(type->resolution)); | 302 | type->fence, vgpu_edid_str(type->resolution), |
303 | type->weight); | ||
302 | } | 304 | } |
303 | 305 | ||
304 | static MDEV_TYPE_ATTR_RO(available_instances); | 306 | static MDEV_TYPE_ATTR_RO(available_instances); |
@@ -1146,8 +1148,40 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd, | |||
1146 | return 0; | 1148 | return 0; |
1147 | } | 1149 | } |
1148 | 1150 | ||
1151 | static ssize_t | ||
1152 | vgpu_id_show(struct device *dev, struct device_attribute *attr, | ||
1153 | char *buf) | ||
1154 | { | ||
1155 | struct mdev_device *mdev = mdev_from_dev(dev); | ||
1156 | |||
1157 | if (mdev) { | ||
1158 | struct intel_vgpu *vgpu = (struct intel_vgpu *) | ||
1159 | mdev_get_drvdata(mdev); | ||
1160 | return sprintf(buf, "%d\n", vgpu->id); | ||
1161 | } | ||
1162 | return sprintf(buf, "\n"); | ||
1163 | } | ||
1164 | |||
1165 | static DEVICE_ATTR_RO(vgpu_id); | ||
1166 | |||
1167 | static struct attribute *intel_vgpu_attrs[] = { | ||
1168 | &dev_attr_vgpu_id.attr, | ||
1169 | NULL | ||
1170 | }; | ||
1171 | |||
1172 | static const struct attribute_group intel_vgpu_group = { | ||
1173 | .name = "intel_vgpu", | ||
1174 | .attrs = intel_vgpu_attrs, | ||
1175 | }; | ||
1176 | |||
1177 | static const struct attribute_group *intel_vgpu_groups[] = { | ||
1178 | &intel_vgpu_group, | ||
1179 | NULL, | ||
1180 | }; | ||
1181 | |||
1149 | static const struct mdev_parent_ops intel_vgpu_ops = { | 1182 | static const struct mdev_parent_ops intel_vgpu_ops = { |
1150 | .supported_type_groups = intel_vgpu_type_groups, | 1183 | .supported_type_groups = intel_vgpu_type_groups, |
1184 | .mdev_attr_groups = intel_vgpu_groups, | ||
1151 | .create = intel_vgpu_create, | 1185 | .create = intel_vgpu_create, |
1152 | .remove = intel_vgpu_remove, | 1186 | .remove = intel_vgpu_remove, |
1153 | 1187 | ||
@@ -1339,13 +1373,6 @@ static int kvmgt_guest_init(struct mdev_device *mdev) | |||
1339 | 1373 | ||
1340 | static bool kvmgt_guest_exit(struct kvmgt_guest_info *info) | 1374 | static bool kvmgt_guest_exit(struct kvmgt_guest_info *info) |
1341 | { | 1375 | { |
1342 | struct intel_vgpu *vgpu = info->vgpu; | ||
1343 | |||
1344 | if (!info) { | ||
1345 | gvt_vgpu_err("kvmgt_guest_info invalid\n"); | ||
1346 | return false; | ||
1347 | } | ||
1348 | |||
1349 | kvm_page_track_unregister_notifier(info->kvm, &info->track_node); | 1376 | kvm_page_track_unregister_notifier(info->kvm, &info->track_node); |
1350 | kvmgt_protect_table_destroy(info); | 1377 | kvmgt_protect_table_destroy(info); |
1351 | gvt_cache_destroy(info->vgpu); | 1378 | gvt_cache_destroy(info->vgpu); |
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index a3a027025cd0..7edd66f38ef9 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h | |||
@@ -44,20 +44,21 @@ struct intel_vgpu; | |||
44 | #define D_HSW (1 << 2) | 44 | #define D_HSW (1 << 2) |
45 | #define D_BDW (1 << 3) | 45 | #define D_BDW (1 << 3) |
46 | #define D_SKL (1 << 4) | 46 | #define D_SKL (1 << 4) |
47 | #define D_KBL (1 << 5) | ||
47 | 48 | ||
48 | #define D_GEN9PLUS (D_SKL) | 49 | #define D_GEN9PLUS (D_SKL | D_KBL) |
49 | #define D_GEN8PLUS (D_BDW | D_SKL) | 50 | #define D_GEN8PLUS (D_BDW | D_SKL | D_KBL) |
50 | #define D_GEN75PLUS (D_HSW | D_BDW | D_SKL) | 51 | #define D_GEN75PLUS (D_HSW | D_BDW | D_SKL | D_KBL) |
51 | #define D_GEN7PLUS (D_IVB | D_HSW | D_BDW | D_SKL) | 52 | #define D_GEN7PLUS (D_IVB | D_HSW | D_BDW | D_SKL | D_KBL) |
52 | 53 | ||
53 | #define D_SKL_PLUS (D_SKL) | 54 | #define D_SKL_PLUS (D_SKL | D_KBL) |
54 | #define D_BDW_PLUS (D_BDW | D_SKL) | 55 | #define D_BDW_PLUS (D_BDW | D_SKL | D_KBL) |
55 | #define D_HSW_PLUS (D_HSW | D_BDW | D_SKL) | 56 | #define D_HSW_PLUS (D_HSW | D_BDW | D_SKL | D_KBL) |
56 | #define D_IVB_PLUS (D_IVB | D_HSW | D_BDW | D_SKL) | 57 | #define D_IVB_PLUS (D_IVB | D_HSW | D_BDW | D_SKL | D_KBL) |
57 | 58 | ||
58 | #define D_PRE_BDW (D_SNB | D_IVB | D_HSW) | 59 | #define D_PRE_BDW (D_SNB | D_IVB | D_HSW) |
59 | #define D_PRE_SKL (D_SNB | D_IVB | D_HSW | D_BDW) | 60 | #define D_PRE_SKL (D_SNB | D_IVB | D_HSW | D_BDW) |
60 | #define D_ALL (D_SNB | D_IVB | D_HSW | D_BDW | D_SKL) | 61 | #define D_ALL (D_SNB | D_IVB | D_HSW | D_BDW | D_SKL | D_KBL) |
61 | 62 | ||
62 | struct intel_gvt_mmio_info { | 63 | struct intel_gvt_mmio_info { |
63 | u32 offset; | 64 | u32 offset; |
diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index 95ee091ce085..e24e57afc45e 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c | |||
@@ -126,6 +126,18 @@ static struct render_mmio gen9_render_mmio_list[] = { | |||
126 | {VCS2, _MMIO(0x1c028), 0xffff, false}, | 126 | {VCS2, _MMIO(0x1c028), 0xffff, false}, |
127 | 127 | ||
128 | {VECS, _MMIO(0x1a028), 0xffff, false}, | 128 | {VECS, _MMIO(0x1a028), 0xffff, false}, |
129 | |||
130 | {RCS, _MMIO(0x7304), 0xffff, true}, | ||
131 | {RCS, _MMIO(0x2248), 0x0, false}, | ||
132 | {RCS, _MMIO(0x940c), 0x0, false}, | ||
133 | {RCS, _MMIO(0x4ab8), 0x0, false}, | ||
134 | |||
135 | {RCS, _MMIO(0x4ab0), 0x0, false}, | ||
136 | {RCS, _MMIO(0x20d4), 0x0, false}, | ||
137 | |||
138 | {RCS, _MMIO(0xb004), 0x0, false}, | ||
139 | {RCS, _MMIO(0x20a0), 0x0, false}, | ||
140 | {RCS, _MMIO(0x20e4), 0xffff, false}, | ||
129 | }; | 141 | }; |
130 | 142 | ||
131 | static u32 gen9_render_mocs[I915_NUM_ENGINES][64]; | 143 | static u32 gen9_render_mocs[I915_NUM_ENGINES][64]; |
@@ -159,7 +171,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) | |||
159 | */ | 171 | */ |
160 | fw = intel_uncore_forcewake_for_reg(dev_priv, reg, | 172 | fw = intel_uncore_forcewake_for_reg(dev_priv, reg, |
161 | FW_REG_READ | FW_REG_WRITE); | 173 | FW_REG_READ | FW_REG_WRITE); |
162 | if (ring_id == RCS && IS_SKYLAKE(dev_priv)) | 174 | if (ring_id == RCS && (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) |
163 | fw |= FORCEWAKE_RENDER; | 175 | fw |= FORCEWAKE_RENDER; |
164 | 176 | ||
165 | intel_uncore_forcewake_get(dev_priv, fw); | 177 | intel_uncore_forcewake_get(dev_priv, fw); |
@@ -192,7 +204,7 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id) | |||
192 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) | 204 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) |
193 | return; | 205 | return; |
194 | 206 | ||
195 | if (!IS_SKYLAKE(dev_priv)) | 207 | if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) |
196 | return; | 208 | return; |
197 | 209 | ||
198 | offset.reg = regs[ring_id]; | 210 | offset.reg = regs[ring_id]; |
@@ -230,7 +242,7 @@ static void restore_mocs(struct intel_vgpu *vgpu, int ring_id) | |||
230 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) | 242 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) |
231 | return; | 243 | return; |
232 | 244 | ||
233 | if (!IS_SKYLAKE(dev_priv)) | 245 | if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) |
234 | return; | 246 | return; |
235 | 247 | ||
236 | offset.reg = regs[ring_id]; | 248 | offset.reg = regs[ring_id]; |
@@ -265,7 +277,8 @@ void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id) | |||
265 | u32 inhibit_mask = | 277 | u32 inhibit_mask = |
266 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); | 278 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); |
267 | 279 | ||
268 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { | 280 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) |
281 | || IS_KABYLAKE(vgpu->gvt->dev_priv)) { | ||
269 | mmio = gen9_render_mmio_list; | 282 | mmio = gen9_render_mmio_list; |
270 | array_size = ARRAY_SIZE(gen9_render_mmio_list); | 283 | array_size = ARRAY_SIZE(gen9_render_mmio_list); |
271 | load_mocs(vgpu, ring_id); | 284 | load_mocs(vgpu, ring_id); |
@@ -312,7 +325,7 @@ void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id) | |||
312 | u32 v; | 325 | u32 v; |
313 | int i, array_size; | 326 | int i, array_size; |
314 | 327 | ||
315 | if (IS_SKYLAKE(dev_priv)) { | 328 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
316 | mmio = gen9_render_mmio_list; | 329 | mmio = gen9_render_mmio_list; |
317 | array_size = ARRAY_SIZE(gen9_render_mmio_list); | 330 | array_size = ARRAY_SIZE(gen9_render_mmio_list); |
318 | restore_mocs(vgpu, ring_id); | 331 | restore_mocs(vgpu, ring_id); |
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 34b9acdf3479..f84959170674 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c | |||
@@ -47,11 +47,87 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) | |||
47 | return false; | 47 | return false; |
48 | } | 48 | } |
49 | 49 | ||
50 | struct vgpu_sched_data { | ||
51 | struct list_head lru_list; | ||
52 | struct intel_vgpu *vgpu; | ||
53 | |||
54 | ktime_t sched_in_time; | ||
55 | ktime_t sched_out_time; | ||
56 | ktime_t sched_time; | ||
57 | ktime_t left_ts; | ||
58 | ktime_t allocated_ts; | ||
59 | |||
60 | struct vgpu_sched_ctl sched_ctl; | ||
61 | }; | ||
62 | |||
63 | struct gvt_sched_data { | ||
64 | struct intel_gvt *gvt; | ||
65 | struct hrtimer timer; | ||
66 | unsigned long period; | ||
67 | struct list_head lru_runq_head; | ||
68 | }; | ||
69 | |||
70 | static void vgpu_update_timeslice(struct intel_vgpu *pre_vgpu) | ||
71 | { | ||
72 | ktime_t delta_ts; | ||
73 | struct vgpu_sched_data *vgpu_data = pre_vgpu->sched_data; | ||
74 | |||
75 | delta_ts = vgpu_data->sched_out_time - vgpu_data->sched_in_time; | ||
76 | |||
77 | vgpu_data->sched_time += delta_ts; | ||
78 | vgpu_data->left_ts -= delta_ts; | ||
79 | } | ||
80 | |||
81 | #define GVT_TS_BALANCE_PERIOD_MS 100 | ||
82 | #define GVT_TS_BALANCE_STAGE_NUM 10 | ||
83 | |||
84 | static void gvt_balance_timeslice(struct gvt_sched_data *sched_data) | ||
85 | { | ||
86 | struct vgpu_sched_data *vgpu_data; | ||
87 | struct list_head *pos; | ||
88 | static uint64_t stage_check; | ||
89 | int stage = stage_check++ % GVT_TS_BALANCE_STAGE_NUM; | ||
90 | |||
91 | /* The timeslice accumulation reset at stage 0, which is | ||
92 | * allocated again without adding previous debt. | ||
93 | */ | ||
94 | if (stage == 0) { | ||
95 | int total_weight = 0; | ||
96 | ktime_t fair_timeslice; | ||
97 | |||
98 | list_for_each(pos, &sched_data->lru_runq_head) { | ||
99 | vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list); | ||
100 | total_weight += vgpu_data->sched_ctl.weight; | ||
101 | } | ||
102 | |||
103 | list_for_each(pos, &sched_data->lru_runq_head) { | ||
104 | vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list); | ||
105 | fair_timeslice = ms_to_ktime(GVT_TS_BALANCE_PERIOD_MS) * | ||
106 | vgpu_data->sched_ctl.weight / | ||
107 | total_weight; | ||
108 | |||
109 | vgpu_data->allocated_ts = fair_timeslice; | ||
110 | vgpu_data->left_ts = vgpu_data->allocated_ts; | ||
111 | } | ||
112 | } else { | ||
113 | list_for_each(pos, &sched_data->lru_runq_head) { | ||
114 | vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list); | ||
115 | |||
116 | /* timeslice for next 100ms should add the left/debt | ||
117 | * slice of previous stages. | ||
118 | */ | ||
119 | vgpu_data->left_ts += vgpu_data->allocated_ts; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
50 | static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) | 124 | static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) |
51 | { | 125 | { |
52 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | 126 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; |
53 | enum intel_engine_id i; | 127 | enum intel_engine_id i; |
54 | struct intel_engine_cs *engine; | 128 | struct intel_engine_cs *engine; |
129 | struct vgpu_sched_data *vgpu_data; | ||
130 | ktime_t cur_time; | ||
55 | 131 | ||
56 | /* no target to schedule */ | 132 | /* no target to schedule */ |
57 | if (!scheduler->next_vgpu) | 133 | if (!scheduler->next_vgpu) |
@@ -77,6 +153,15 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) | |||
77 | gvt_dbg_sched("switch to next vgpu %d\n", | 153 | gvt_dbg_sched("switch to next vgpu %d\n", |
78 | scheduler->next_vgpu->id); | 154 | scheduler->next_vgpu->id); |
79 | 155 | ||
156 | cur_time = ktime_get(); | ||
157 | if (scheduler->current_vgpu) { | ||
158 | vgpu_data = scheduler->current_vgpu->sched_data; | ||
159 | vgpu_data->sched_out_time = cur_time; | ||
160 | vgpu_update_timeslice(scheduler->current_vgpu); | ||
161 | } | ||
162 | vgpu_data = scheduler->next_vgpu->sched_data; | ||
163 | vgpu_data->sched_in_time = cur_time; | ||
164 | |||
80 | /* switch current vgpu */ | 165 | /* switch current vgpu */ |
81 | scheduler->current_vgpu = scheduler->next_vgpu; | 166 | scheduler->current_vgpu = scheduler->next_vgpu; |
82 | scheduler->next_vgpu = NULL; | 167 | scheduler->next_vgpu = NULL; |
@@ -88,62 +173,61 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) | |||
88 | wake_up(&scheduler->waitq[i]); | 173 | wake_up(&scheduler->waitq[i]); |
89 | } | 174 | } |
90 | 175 | ||
91 | struct tbs_vgpu_data { | 176 | static struct intel_vgpu *find_busy_vgpu(struct gvt_sched_data *sched_data) |
92 | struct list_head list; | ||
93 | struct intel_vgpu *vgpu; | ||
94 | /* put some per-vgpu sched stats here */ | ||
95 | }; | ||
96 | |||
97 | struct tbs_sched_data { | ||
98 | struct intel_gvt *gvt; | ||
99 | struct delayed_work work; | ||
100 | unsigned long period; | ||
101 | struct list_head runq_head; | ||
102 | }; | ||
103 | |||
104 | #define GVT_DEFAULT_TIME_SLICE (msecs_to_jiffies(1)) | ||
105 | |||
106 | static void tbs_sched_func(struct work_struct *work) | ||
107 | { | 177 | { |
108 | struct tbs_sched_data *sched_data = container_of(work, | 178 | struct vgpu_sched_data *vgpu_data; |
109 | struct tbs_sched_data, work.work); | ||
110 | struct tbs_vgpu_data *vgpu_data; | ||
111 | |||
112 | struct intel_gvt *gvt = sched_data->gvt; | ||
113 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
114 | |||
115 | struct intel_vgpu *vgpu = NULL; | 179 | struct intel_vgpu *vgpu = NULL; |
116 | struct list_head *pos, *head; | 180 | struct list_head *head = &sched_data->lru_runq_head; |
117 | 181 | struct list_head *pos; | |
118 | mutex_lock(&gvt->lock); | ||
119 | |||
120 | /* no vgpu or has already had a target */ | ||
121 | if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu) | ||
122 | goto out; | ||
123 | |||
124 | if (scheduler->current_vgpu) { | ||
125 | vgpu_data = scheduler->current_vgpu->sched_data; | ||
126 | head = &vgpu_data->list; | ||
127 | } else { | ||
128 | head = &sched_data->runq_head; | ||
129 | } | ||
130 | 182 | ||
131 | /* search a vgpu with pending workload */ | 183 | /* search a vgpu with pending workload */ |
132 | list_for_each(pos, head) { | 184 | list_for_each(pos, head) { |
133 | if (pos == &sched_data->runq_head) | ||
134 | continue; | ||
135 | 185 | ||
136 | vgpu_data = container_of(pos, struct tbs_vgpu_data, list); | 186 | vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list); |
137 | if (!vgpu_has_pending_workload(vgpu_data->vgpu)) | 187 | if (!vgpu_has_pending_workload(vgpu_data->vgpu)) |
138 | continue; | 188 | continue; |
139 | 189 | ||
140 | vgpu = vgpu_data->vgpu; | 190 | /* Return the vGPU only if it has time slice left */ |
141 | break; | 191 | if (vgpu_data->left_ts > 0) { |
192 | vgpu = vgpu_data->vgpu; | ||
193 | break; | ||
194 | } | ||
142 | } | 195 | } |
143 | 196 | ||
197 | return vgpu; | ||
198 | } | ||
199 | |||
200 | /* in nanosecond */ | ||
201 | #define GVT_DEFAULT_TIME_SLICE 1000000 | ||
202 | |||
203 | static void tbs_sched_func(struct gvt_sched_data *sched_data) | ||
204 | { | ||
205 | struct intel_gvt *gvt = sched_data->gvt; | ||
206 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
207 | struct vgpu_sched_data *vgpu_data; | ||
208 | struct intel_vgpu *vgpu = NULL; | ||
209 | static uint64_t timer_check; | ||
210 | |||
211 | if (!(timer_check++ % GVT_TS_BALANCE_PERIOD_MS)) | ||
212 | gvt_balance_timeslice(sched_data); | ||
213 | |||
214 | /* no active vgpu or has already had a target */ | ||
215 | if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu) | ||
216 | goto out; | ||
217 | |||
218 | vgpu = find_busy_vgpu(sched_data); | ||
144 | if (vgpu) { | 219 | if (vgpu) { |
145 | scheduler->next_vgpu = vgpu; | 220 | scheduler->next_vgpu = vgpu; |
221 | |||
222 | /* Move the last used vGPU to the tail of lru_list */ | ||
223 | vgpu_data = vgpu->sched_data; | ||
224 | list_del_init(&vgpu_data->lru_list); | ||
225 | list_add_tail(&vgpu_data->lru_list, | ||
226 | &sched_data->lru_runq_head); | ||
227 | |||
146 | gvt_dbg_sched("pick next vgpu %d\n", vgpu->id); | 228 | gvt_dbg_sched("pick next vgpu %d\n", vgpu->id); |
229 | } else { | ||
230 | scheduler->next_vgpu = gvt->idle_vgpu; | ||
147 | } | 231 | } |
148 | out: | 232 | out: |
149 | if (scheduler->next_vgpu) { | 233 | if (scheduler->next_vgpu) { |
@@ -151,34 +235,49 @@ out: | |||
151 | scheduler->next_vgpu->id); | 235 | scheduler->next_vgpu->id); |
152 | try_to_schedule_next_vgpu(gvt); | 236 | try_to_schedule_next_vgpu(gvt); |
153 | } | 237 | } |
238 | } | ||
154 | 239 | ||
155 | /* | 240 | void intel_gvt_schedule(struct intel_gvt *gvt) |
156 | * still have vgpu on runq | 241 | { |
157 | * or last schedule haven't finished due to running workload | 242 | struct gvt_sched_data *sched_data = gvt->scheduler.sched_data; |
158 | */ | ||
159 | if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu) | ||
160 | schedule_delayed_work(&sched_data->work, sched_data->period); | ||
161 | 243 | ||
244 | mutex_lock(&gvt->lock); | ||
245 | tbs_sched_func(sched_data); | ||
162 | mutex_unlock(&gvt->lock); | 246 | mutex_unlock(&gvt->lock); |
163 | } | 247 | } |
164 | 248 | ||
249 | static enum hrtimer_restart tbs_timer_fn(struct hrtimer *timer_data) | ||
250 | { | ||
251 | struct gvt_sched_data *data; | ||
252 | |||
253 | data = container_of(timer_data, struct gvt_sched_data, timer); | ||
254 | |||
255 | intel_gvt_request_service(data->gvt, INTEL_GVT_REQUEST_SCHED); | ||
256 | |||
257 | hrtimer_add_expires_ns(&data->timer, data->period); | ||
258 | |||
259 | return HRTIMER_RESTART; | ||
260 | } | ||
261 | |||
165 | static int tbs_sched_init(struct intel_gvt *gvt) | 262 | static int tbs_sched_init(struct intel_gvt *gvt) |
166 | { | 263 | { |
167 | struct intel_gvt_workload_scheduler *scheduler = | 264 | struct intel_gvt_workload_scheduler *scheduler = |
168 | &gvt->scheduler; | 265 | &gvt->scheduler; |
169 | 266 | ||
170 | struct tbs_sched_data *data; | 267 | struct gvt_sched_data *data; |
171 | 268 | ||
172 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 269 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
173 | if (!data) | 270 | if (!data) |
174 | return -ENOMEM; | 271 | return -ENOMEM; |
175 | 272 | ||
176 | INIT_LIST_HEAD(&data->runq_head); | 273 | INIT_LIST_HEAD(&data->lru_runq_head); |
177 | INIT_DELAYED_WORK(&data->work, tbs_sched_func); | 274 | hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
275 | data->timer.function = tbs_timer_fn; | ||
178 | data->period = GVT_DEFAULT_TIME_SLICE; | 276 | data->period = GVT_DEFAULT_TIME_SLICE; |
179 | data->gvt = gvt; | 277 | data->gvt = gvt; |
180 | 278 | ||
181 | scheduler->sched_data = data; | 279 | scheduler->sched_data = data; |
280 | |||
182 | return 0; | 281 | return 0; |
183 | } | 282 | } |
184 | 283 | ||
@@ -186,25 +285,28 @@ static void tbs_sched_clean(struct intel_gvt *gvt) | |||
186 | { | 285 | { |
187 | struct intel_gvt_workload_scheduler *scheduler = | 286 | struct intel_gvt_workload_scheduler *scheduler = |
188 | &gvt->scheduler; | 287 | &gvt->scheduler; |
189 | struct tbs_sched_data *data = scheduler->sched_data; | 288 | struct gvt_sched_data *data = scheduler->sched_data; |
289 | |||
290 | hrtimer_cancel(&data->timer); | ||
190 | 291 | ||
191 | cancel_delayed_work(&data->work); | ||
192 | kfree(data); | 292 | kfree(data); |
193 | scheduler->sched_data = NULL; | 293 | scheduler->sched_data = NULL; |
194 | } | 294 | } |
195 | 295 | ||
196 | static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) | 296 | static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) |
197 | { | 297 | { |
198 | struct tbs_vgpu_data *data; | 298 | struct vgpu_sched_data *data; |
199 | 299 | ||
200 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 300 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
201 | if (!data) | 301 | if (!data) |
202 | return -ENOMEM; | 302 | return -ENOMEM; |
203 | 303 | ||
304 | data->sched_ctl.weight = vgpu->sched_ctl.weight; | ||
204 | data->vgpu = vgpu; | 305 | data->vgpu = vgpu; |
205 | INIT_LIST_HEAD(&data->list); | 306 | INIT_LIST_HEAD(&data->lru_list); |
206 | 307 | ||
207 | vgpu->sched_data = data; | 308 | vgpu->sched_data = data; |
309 | |||
208 | return 0; | 310 | return 0; |
209 | } | 311 | } |
210 | 312 | ||
@@ -216,21 +318,24 @@ static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu) | |||
216 | 318 | ||
217 | static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) | 319 | static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) |
218 | { | 320 | { |
219 | struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data; | 321 | struct gvt_sched_data *sched_data = vgpu->gvt->scheduler.sched_data; |
220 | struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; | 322 | struct vgpu_sched_data *vgpu_data = vgpu->sched_data; |
221 | 323 | ||
222 | if (!list_empty(&vgpu_data->list)) | 324 | if (!list_empty(&vgpu_data->lru_list)) |
223 | return; | 325 | return; |
224 | 326 | ||
225 | list_add_tail(&vgpu_data->list, &sched_data->runq_head); | 327 | list_add_tail(&vgpu_data->lru_list, &sched_data->lru_runq_head); |
226 | schedule_delayed_work(&sched_data->work, 0); | 328 | |
329 | if (!hrtimer_active(&sched_data->timer)) | ||
330 | hrtimer_start(&sched_data->timer, ktime_add_ns(ktime_get(), | ||
331 | sched_data->period), HRTIMER_MODE_ABS); | ||
227 | } | 332 | } |
228 | 333 | ||
229 | static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) | 334 | static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) |
230 | { | 335 | { |
231 | struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; | 336 | struct vgpu_sched_data *vgpu_data = vgpu->sched_data; |
232 | 337 | ||
233 | list_del_init(&vgpu_data->list); | 338 | list_del_init(&vgpu_data->lru_list); |
234 | } | 339 | } |
235 | 340 | ||
236 | static struct intel_gvt_sched_policy_ops tbs_schedule_ops = { | 341 | static struct intel_gvt_sched_policy_ops tbs_schedule_ops = { |
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.h b/drivers/gpu/drm/i915/gvt/sched_policy.h index bb8b9097e41a..ba00a5f7455f 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.h +++ b/drivers/gpu/drm/i915/gvt/sched_policy.h | |||
@@ -43,6 +43,8 @@ struct intel_gvt_sched_policy_ops { | |||
43 | void (*stop_schedule)(struct intel_vgpu *vgpu); | 43 | void (*stop_schedule)(struct intel_vgpu *vgpu); |
44 | }; | 44 | }; |
45 | 45 | ||
46 | void intel_gvt_schedule(struct intel_gvt *gvt); | ||
47 | |||
46 | int intel_gvt_init_sched_policy(struct intel_gvt *gvt); | 48 | int intel_gvt_init_sched_policy(struct intel_gvt *gvt); |
47 | 49 | ||
48 | void intel_gvt_clean_sched_policy(struct intel_gvt *gvt); | 50 | void intel_gvt_clean_sched_policy(struct intel_gvt *gvt); |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index ad8876bd15b3..375038252761 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
@@ -448,7 +448,8 @@ static int workload_thread(void *priv) | |||
448 | struct intel_vgpu_workload *workload = NULL; | 448 | struct intel_vgpu_workload *workload = NULL; |
449 | struct intel_vgpu *vgpu = NULL; | 449 | struct intel_vgpu *vgpu = NULL; |
450 | int ret; | 450 | int ret; |
451 | bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); | 451 | bool need_force_wake = IS_SKYLAKE(gvt->dev_priv) |
452 | || IS_KABYLAKE(gvt->dev_priv); | ||
452 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | 453 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
453 | 454 | ||
454 | kfree(p); | 455 | kfree(p); |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 2833dfa8c9ae..2cd725c0573e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h | |||
@@ -67,7 +67,6 @@ struct shadow_per_ctx { | |||
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct intel_shadow_wa_ctx { | 69 | struct intel_shadow_wa_ctx { |
70 | struct intel_vgpu_workload *workload; | ||
71 | struct shadow_indirect_ctx indirect_ctx; | 70 | struct shadow_indirect_ctx indirect_ctx; |
72 | struct shadow_per_ctx per_ctx; | 71 | struct shadow_per_ctx per_ctx; |
73 | 72 | ||
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 41cfa5ccae84..6ba02525e905 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c | |||
@@ -64,18 +64,28 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu) | |||
64 | WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); | 64 | WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); |
65 | } | 65 | } |
66 | 66 | ||
67 | #define VGPU_MAX_WEIGHT 16 | ||
68 | #define VGPU_WEIGHT(vgpu_num) \ | ||
69 | (VGPU_MAX_WEIGHT / (vgpu_num)) | ||
70 | |||
67 | static struct { | 71 | static struct { |
68 | unsigned int low_mm; | 72 | unsigned int low_mm; |
69 | unsigned int high_mm; | 73 | unsigned int high_mm; |
70 | unsigned int fence; | 74 | unsigned int fence; |
75 | |||
76 | /* A vGPU with a weight of 8 will get twice as much GPU as a vGPU | ||
77 | * with a weight of 4 on a contended host, different vGPU type has | ||
78 | * different weight set. Legal weights range from 1 to 16. | ||
79 | */ | ||
80 | unsigned int weight; | ||
71 | enum intel_vgpu_edid edid; | 81 | enum intel_vgpu_edid edid; |
72 | char *name; | 82 | char *name; |
73 | } vgpu_types[] = { | 83 | } vgpu_types[] = { |
74 | /* Fixed vGPU type table */ | 84 | /* Fixed vGPU type table */ |
75 | { MB_TO_BYTES(64), MB_TO_BYTES(512), 4, GVT_EDID_1024_768, "8" }, | 85 | { MB_TO_BYTES(64), MB_TO_BYTES(384), 4, VGPU_WEIGHT(8), GVT_EDID_1024_768, "8" }, |
76 | { MB_TO_BYTES(128), MB_TO_BYTES(512), 4, GVT_EDID_1920_1200, "4" }, | 86 | { MB_TO_BYTES(128), MB_TO_BYTES(512), 4, VGPU_WEIGHT(4), GVT_EDID_1920_1200, "4" }, |
77 | { MB_TO_BYTES(256), MB_TO_BYTES(1024), 4, GVT_EDID_1920_1200, "2" }, | 87 | { MB_TO_BYTES(256), MB_TO_BYTES(1024), 4, VGPU_WEIGHT(2), GVT_EDID_1920_1200, "2" }, |
78 | { MB_TO_BYTES(512), MB_TO_BYTES(2048), 4, GVT_EDID_1920_1200, "1" }, | 88 | { MB_TO_BYTES(512), MB_TO_BYTES(2048), 4, VGPU_WEIGHT(1), GVT_EDID_1920_1200, "1" }, |
79 | }; | 89 | }; |
80 | 90 | ||
81 | /** | 91 | /** |
@@ -120,6 +130,12 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) | |||
120 | gvt->types[i].low_gm_size = vgpu_types[i].low_mm; | 130 | gvt->types[i].low_gm_size = vgpu_types[i].low_mm; |
121 | gvt->types[i].high_gm_size = vgpu_types[i].high_mm; | 131 | gvt->types[i].high_gm_size = vgpu_types[i].high_mm; |
122 | gvt->types[i].fence = vgpu_types[i].fence; | 132 | gvt->types[i].fence = vgpu_types[i].fence; |
133 | |||
134 | if (vgpu_types[i].weight < 1 || | ||
135 | vgpu_types[i].weight > VGPU_MAX_WEIGHT) | ||
136 | return -EINVAL; | ||
137 | |||
138 | gvt->types[i].weight = vgpu_types[i].weight; | ||
123 | gvt->types[i].resolution = vgpu_types[i].edid; | 139 | gvt->types[i].resolution = vgpu_types[i].edid; |
124 | gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm, | 140 | gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm, |
125 | high_avail / vgpu_types[i].high_mm); | 141 | high_avail / vgpu_types[i].high_mm); |
@@ -131,11 +147,12 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) | |||
131 | sprintf(gvt->types[i].name, "GVTg_V5_%s", | 147 | sprintf(gvt->types[i].name, "GVTg_V5_%s", |
132 | vgpu_types[i].name); | 148 | vgpu_types[i].name); |
133 | 149 | ||
134 | gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u res %s\n", | 150 | gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u weight %u res %s\n", |
135 | i, gvt->types[i].name, | 151 | i, gvt->types[i].name, |
136 | gvt->types[i].avail_instance, | 152 | gvt->types[i].avail_instance, |
137 | gvt->types[i].low_gm_size, | 153 | gvt->types[i].low_gm_size, |
138 | gvt->types[i].high_gm_size, gvt->types[i].fence, | 154 | gvt->types[i].high_gm_size, gvt->types[i].fence, |
155 | gvt->types[i].weight, | ||
139 | vgpu_edid_str(gvt->types[i].resolution)); | 156 | vgpu_edid_str(gvt->types[i].resolution)); |
140 | } | 157 | } |
141 | 158 | ||
@@ -216,6 +233,59 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) | |||
216 | mutex_unlock(&gvt->lock); | 233 | mutex_unlock(&gvt->lock); |
217 | } | 234 | } |
218 | 235 | ||
236 | #define IDLE_VGPU_IDR 0 | ||
237 | |||
238 | /** | ||
239 | * intel_gvt_create_idle_vgpu - create an idle virtual GPU | ||
240 | * @gvt: GVT device | ||
241 | * | ||
242 | * This function is called when user wants to create an idle virtual GPU. | ||
243 | * | ||
244 | * Returns: | ||
245 | * pointer to intel_vgpu, error pointer if failed. | ||
246 | */ | ||
247 | struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt) | ||
248 | { | ||
249 | struct intel_vgpu *vgpu; | ||
250 | enum intel_engine_id i; | ||
251 | int ret; | ||
252 | |||
253 | vgpu = vzalloc(sizeof(*vgpu)); | ||
254 | if (!vgpu) | ||
255 | return ERR_PTR(-ENOMEM); | ||
256 | |||
257 | vgpu->id = IDLE_VGPU_IDR; | ||
258 | vgpu->gvt = gvt; | ||
259 | |||
260 | for (i = 0; i < I915_NUM_ENGINES; i++) | ||
261 | INIT_LIST_HEAD(&vgpu->workload_q_head[i]); | ||
262 | |||
263 | ret = intel_vgpu_init_sched_policy(vgpu); | ||
264 | if (ret) | ||
265 | goto out_free_vgpu; | ||
266 | |||
267 | vgpu->active = false; | ||
268 | |||
269 | return vgpu; | ||
270 | |||
271 | out_free_vgpu: | ||
272 | vfree(vgpu); | ||
273 | return ERR_PTR(ret); | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * intel_gvt_destroy_vgpu - destroy an idle virtual GPU | ||
278 | * @vgpu: virtual GPU | ||
279 | * | ||
280 | * This function is called when user wants to destroy an idle virtual GPU. | ||
281 | * | ||
282 | */ | ||
283 | void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu) | ||
284 | { | ||
285 | intel_vgpu_clean_sched_policy(vgpu); | ||
286 | vfree(vgpu); | ||
287 | } | ||
288 | |||
219 | static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, | 289 | static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, |
220 | struct intel_vgpu_creation_params *param) | 290 | struct intel_vgpu_creation_params *param) |
221 | { | 291 | { |
@@ -232,13 +302,15 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, | |||
232 | 302 | ||
233 | mutex_lock(&gvt->lock); | 303 | mutex_lock(&gvt->lock); |
234 | 304 | ||
235 | ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL); | 305 | ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU, |
306 | GFP_KERNEL); | ||
236 | if (ret < 0) | 307 | if (ret < 0) |
237 | goto out_free_vgpu; | 308 | goto out_free_vgpu; |
238 | 309 | ||
239 | vgpu->id = ret; | 310 | vgpu->id = ret; |
240 | vgpu->handle = param->handle; | 311 | vgpu->handle = param->handle; |
241 | vgpu->gvt = gvt; | 312 | vgpu->gvt = gvt; |
313 | vgpu->sched_ctl.weight = param->weight; | ||
242 | bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); | 314 | bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); |
243 | 315 | ||
244 | intel_vgpu_init_cfg_space(vgpu, param->primary); | 316 | intel_vgpu_init_cfg_space(vgpu, param->primary); |
@@ -325,6 +397,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | |||
325 | param.low_gm_sz = type->low_gm_size; | 397 | param.low_gm_sz = type->low_gm_size; |
326 | param.high_gm_sz = type->high_gm_size; | 398 | param.high_gm_sz = type->high_gm_size; |
327 | param.fence_sz = type->fence; | 399 | param.fence_sz = type->fence; |
400 | param.weight = type->weight; | ||
328 | param.resolution = type->resolution; | 401 | param.resolution = type->resolution; |
329 | 402 | ||
330 | /* XXX current param based on MB */ | 403 | /* XXX current param based on MB */ |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 47e707d83c4d..d689e511744e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -1012,9 +1012,12 @@ static int gpu_state_release(struct inode *inode, struct file *file) | |||
1012 | 1012 | ||
1013 | static int i915_gpu_info_open(struct inode *inode, struct file *file) | 1013 | static int i915_gpu_info_open(struct inode *inode, struct file *file) |
1014 | { | 1014 | { |
1015 | struct drm_i915_private *i915 = inode->i_private; | ||
1015 | struct i915_gpu_state *gpu; | 1016 | struct i915_gpu_state *gpu; |
1016 | 1017 | ||
1017 | gpu = i915_capture_gpu_state(inode->i_private); | 1018 | intel_runtime_pm_get(i915); |
1019 | gpu = i915_capture_gpu_state(i915); | ||
1020 | intel_runtime_pm_put(i915); | ||
1018 | if (!gpu) | 1021 | if (!gpu) |
1019 | return -ENOMEM; | 1022 | return -ENOMEM; |
1020 | 1023 | ||
@@ -1459,16 +1462,14 @@ static int ironlake_drpc_info(struct seq_file *m) | |||
1459 | 1462 | ||
1460 | static int i915_forcewake_domains(struct seq_file *m, void *data) | 1463 | static int i915_forcewake_domains(struct seq_file *m, void *data) |
1461 | { | 1464 | { |
1462 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 1465 | struct drm_i915_private *i915 = node_to_i915(m->private); |
1463 | struct intel_uncore_forcewake_domain *fw_domain; | 1466 | struct intel_uncore_forcewake_domain *fw_domain; |
1467 | unsigned int tmp; | ||
1464 | 1468 | ||
1465 | spin_lock_irq(&dev_priv->uncore.lock); | 1469 | for_each_fw_domain(fw_domain, i915, tmp) |
1466 | for_each_fw_domain(fw_domain, dev_priv) { | ||
1467 | seq_printf(m, "%s.wake_count = %u\n", | 1470 | seq_printf(m, "%s.wake_count = %u\n", |
1468 | intel_uncore_forcewake_domain_to_str(fw_domain->id), | 1471 | intel_uncore_forcewake_domain_to_str(fw_domain->id), |
1469 | fw_domain->wake_count); | 1472 | READ_ONCE(fw_domain->wake_count)); |
1470 | } | ||
1471 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
1472 | 1473 | ||
1473 | return 0; | 1474 | return 0; |
1474 | } | 1475 | } |
@@ -1938,9 +1939,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | |||
1938 | 1939 | ||
1939 | static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring) | 1940 | static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring) |
1940 | { | 1941 | { |
1941 | seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u, last head: %d)", | 1942 | seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u)", |
1942 | ring->space, ring->head, ring->tail, | 1943 | ring->space, ring->head, ring->tail); |
1943 | ring->last_retired_head); | ||
1944 | } | 1944 | } |
1945 | 1945 | ||
1946 | static int i915_context_status(struct seq_file *m, void *unused) | 1946 | static int i915_context_status(struct seq_file *m, void *unused) |
@@ -2474,9 +2474,9 @@ static void i915_guc_client_info(struct seq_file *m, | |||
2474 | enum intel_engine_id id; | 2474 | enum intel_engine_id id; |
2475 | uint64_t tot = 0; | 2475 | uint64_t tot = 0; |
2476 | 2476 | ||
2477 | seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", | 2477 | seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n", |
2478 | client->priority, client->ctx_index, client->proc_desc_offset); | 2478 | client->priority, client->stage_id, client->proc_desc_offset); |
2479 | seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n", | 2479 | seq_printf(m, "\tDoorbell id %d, offset: 0x%lx, cookie 0x%x\n", |
2480 | client->doorbell_id, client->doorbell_offset, client->doorbell_cookie); | 2480 | client->doorbell_id, client->doorbell_offset, client->doorbell_cookie); |
2481 | seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", | 2481 | seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", |
2482 | client->wq_size, client->wq_offset, client->wq_tail); | 2482 | client->wq_size, client->wq_offset, client->wq_tail); |
@@ -2511,7 +2511,7 @@ static int i915_guc_info(struct seq_file *m, void *data) | |||
2511 | } | 2511 | } |
2512 | 2512 | ||
2513 | seq_printf(m, "Doorbell map:\n"); | 2513 | seq_printf(m, "Doorbell map:\n"); |
2514 | seq_printf(m, "\t%*pb\n", GUC_MAX_DOORBELLS, guc->doorbell_bitmap); | 2514 | seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); |
2515 | seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline); | 2515 | seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline); |
2516 | 2516 | ||
2517 | seq_printf(m, "GuC total action count: %llu\n", guc->action_count); | 2517 | seq_printf(m, "GuC total action count: %llu\n", guc->action_count); |
@@ -4129,7 +4129,9 @@ i915_wedged_get(void *data, u64 *val) | |||
4129 | static int | 4129 | static int |
4130 | i915_wedged_set(void *data, u64 val) | 4130 | i915_wedged_set(void *data, u64 val) |
4131 | { | 4131 | { |
4132 | struct drm_i915_private *dev_priv = data; | 4132 | struct drm_i915_private *i915 = data; |
4133 | struct intel_engine_cs *engine; | ||
4134 | unsigned int tmp; | ||
4133 | 4135 | ||
4134 | /* | 4136 | /* |
4135 | * There is no safeguard against this debugfs entry colliding | 4137 | * There is no safeguard against this debugfs entry colliding |
@@ -4139,13 +4141,17 @@ i915_wedged_set(void *data, u64 val) | |||
4139 | * while it is writing to 'i915_wedged' | 4141 | * while it is writing to 'i915_wedged' |
4140 | */ | 4142 | */ |
4141 | 4143 | ||
4142 | if (i915_reset_backoff(&dev_priv->gpu_error)) | 4144 | if (i915_reset_backoff(&i915->gpu_error)) |
4143 | return -EAGAIN; | 4145 | return -EAGAIN; |
4144 | 4146 | ||
4145 | i915_handle_error(dev_priv, val, | 4147 | for_each_engine_masked(engine, i915, val, tmp) { |
4146 | "Manually setting wedged to %llu", val); | 4148 | engine->hangcheck.seqno = intel_engine_get_seqno(engine); |
4149 | engine->hangcheck.stalled = true; | ||
4150 | } | ||
4151 | |||
4152 | i915_handle_error(i915, val, "Manually setting wedged to %llu", val); | ||
4147 | 4153 | ||
4148 | wait_on_bit(&dev_priv->gpu_error.flags, | 4154 | wait_on_bit(&i915->gpu_error.flags, |
4149 | I915_RESET_HANDOFF, | 4155 | I915_RESET_HANDOFF, |
4150 | TASK_UNINTERRUPTIBLE); | 4156 | TASK_UNINTERRUPTIBLE); |
4151 | 4157 | ||
@@ -4173,10 +4179,6 @@ fault_irq_set(struct drm_i915_private *i915, | |||
4173 | if (err) | 4179 | if (err) |
4174 | goto err_unlock; | 4180 | goto err_unlock; |
4175 | 4181 | ||
4176 | /* Retire to kick idle work */ | ||
4177 | i915_gem_retire_requests(i915); | ||
4178 | GEM_BUG_ON(i915->gt.active_requests); | ||
4179 | |||
4180 | *irq = val; | 4182 | *irq = val; |
4181 | mutex_unlock(&i915->drm.struct_mutex); | 4183 | mutex_unlock(&i915->drm.struct_mutex); |
4182 | 4184 | ||
@@ -4280,7 +4282,7 @@ i915_drop_caches_set(void *data, u64 val) | |||
4280 | goto unlock; | 4282 | goto unlock; |
4281 | } | 4283 | } |
4282 | 4284 | ||
4283 | if (val & (DROP_RETIRE | DROP_ACTIVE)) | 4285 | if (val & DROP_RETIRE) |
4284 | i915_gem_retire_requests(dev_priv); | 4286 | i915_gem_retire_requests(dev_priv); |
4285 | 4287 | ||
4286 | lockdep_set_current_reclaim_state(GFP_KERNEL); | 4288 | lockdep_set_current_reclaim_state(GFP_KERNEL); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 98b17070a123..c616b4e755bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -549,6 +549,7 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { | |||
549 | static void i915_gem_fini(struct drm_i915_private *dev_priv) | 549 | static void i915_gem_fini(struct drm_i915_private *dev_priv) |
550 | { | 550 | { |
551 | mutex_lock(&dev_priv->drm.struct_mutex); | 551 | mutex_lock(&dev_priv->drm.struct_mutex); |
552 | intel_uc_fini_hw(dev_priv); | ||
552 | i915_gem_cleanup_engines(dev_priv); | 553 | i915_gem_cleanup_engines(dev_priv); |
553 | i915_gem_context_fini(dev_priv); | 554 | i915_gem_context_fini(dev_priv); |
554 | mutex_unlock(&dev_priv->drm.struct_mutex); | 555 | mutex_unlock(&dev_priv->drm.struct_mutex); |
@@ -609,7 +610,7 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
609 | 610 | ||
610 | ret = i915_gem_init(dev_priv); | 611 | ret = i915_gem_init(dev_priv); |
611 | if (ret) | 612 | if (ret) |
612 | goto cleanup_irq; | 613 | goto cleanup_uc; |
613 | 614 | ||
614 | intel_modeset_gem_init(dev); | 615 | intel_modeset_gem_init(dev); |
615 | 616 | ||
@@ -631,9 +632,9 @@ cleanup_gem: | |||
631 | if (i915_gem_suspend(dev_priv)) | 632 | if (i915_gem_suspend(dev_priv)) |
632 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); | 633 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); |
633 | i915_gem_fini(dev_priv); | 634 | i915_gem_fini(dev_priv); |
635 | cleanup_uc: | ||
636 | intel_uc_fini_fw(dev_priv); | ||
634 | cleanup_irq: | 637 | cleanup_irq: |
635 | intel_guc_fini(dev_priv); | ||
636 | intel_huc_fini(dev_priv); | ||
637 | drm_irq_uninstall(dev); | 638 | drm_irq_uninstall(dev); |
638 | intel_teardown_gmbus(dev_priv); | 639 | intel_teardown_gmbus(dev_priv); |
639 | cleanup_csr: | 640 | cleanup_csr: |
@@ -1351,9 +1352,8 @@ void i915_driver_unload(struct drm_device *dev) | |||
1351 | /* Flush any outstanding unpin_work. */ | 1352 | /* Flush any outstanding unpin_work. */ |
1352 | drain_workqueue(dev_priv->wq); | 1353 | drain_workqueue(dev_priv->wq); |
1353 | 1354 | ||
1354 | intel_guc_fini(dev_priv); | ||
1355 | intel_huc_fini(dev_priv); | ||
1356 | i915_gem_fini(dev_priv); | 1355 | i915_gem_fini(dev_priv); |
1356 | intel_uc_fini_fw(dev_priv); | ||
1357 | intel_fbc_cleanup_cfb(dev_priv); | 1357 | intel_fbc_cleanup_cfb(dev_priv); |
1358 | 1358 | ||
1359 | intel_power_domains_fini(dev_priv); | 1359 | intel_power_domains_fini(dev_priv); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a5947a496d0a..c9b0949f6c1a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -79,26 +79,8 @@ | |||
79 | 79 | ||
80 | #define DRIVER_NAME "i915" | 80 | #define DRIVER_NAME "i915" |
81 | #define DRIVER_DESC "Intel Graphics" | 81 | #define DRIVER_DESC "Intel Graphics" |
82 | #define DRIVER_DATE "20170320" | 82 | #define DRIVER_DATE "20170403" |
83 | #define DRIVER_TIMESTAMP 1489994464 | 83 | #define DRIVER_TIMESTAMP 1491198738 |
84 | |||
85 | #undef WARN_ON | ||
86 | /* Many gcc seem to no see through this and fall over :( */ | ||
87 | #if 0 | ||
88 | #define WARN_ON(x) ({ \ | ||
89 | bool __i915_warn_cond = (x); \ | ||
90 | if (__builtin_constant_p(__i915_warn_cond)) \ | ||
91 | BUILD_BUG_ON(__i915_warn_cond); \ | ||
92 | WARN(__i915_warn_cond, "WARN_ON(" #x ")"); }) | ||
93 | #else | ||
94 | #define WARN_ON(x) WARN((x), "%s", "WARN_ON(" __stringify(x) ")") | ||
95 | #endif | ||
96 | |||
97 | #undef WARN_ON_ONCE | ||
98 | #define WARN_ON_ONCE(x) WARN_ONCE((x), "%s", "WARN_ON_ONCE(" __stringify(x) ")") | ||
99 | |||
100 | #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ | ||
101 | (long) (x), __func__); | ||
102 | 84 | ||
103 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and | 85 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and |
104 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions | 86 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions |
@@ -703,9 +685,9 @@ enum forcewake_domain_id { | |||
703 | }; | 685 | }; |
704 | 686 | ||
705 | enum forcewake_domains { | 687 | enum forcewake_domains { |
706 | FORCEWAKE_RENDER = (1 << FW_DOMAIN_ID_RENDER), | 688 | FORCEWAKE_RENDER = BIT(FW_DOMAIN_ID_RENDER), |
707 | FORCEWAKE_BLITTER = (1 << FW_DOMAIN_ID_BLITTER), | 689 | FORCEWAKE_BLITTER = BIT(FW_DOMAIN_ID_BLITTER), |
708 | FORCEWAKE_MEDIA = (1 << FW_DOMAIN_ID_MEDIA), | 690 | FORCEWAKE_MEDIA = BIT(FW_DOMAIN_ID_MEDIA), |
709 | FORCEWAKE_ALL = (FORCEWAKE_RENDER | | 691 | FORCEWAKE_ALL = (FORCEWAKE_RENDER | |
710 | FORCEWAKE_BLITTER | | 692 | FORCEWAKE_BLITTER | |
711 | FORCEWAKE_MEDIA) | 693 | FORCEWAKE_MEDIA) |
@@ -732,21 +714,25 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, | |||
732 | 714 | ||
733 | struct intel_uncore_funcs { | 715 | struct intel_uncore_funcs { |
734 | void (*force_wake_get)(struct drm_i915_private *dev_priv, | 716 | void (*force_wake_get)(struct drm_i915_private *dev_priv, |
735 | enum forcewake_domains domains); | 717 | enum forcewake_domains domains); |
736 | void (*force_wake_put)(struct drm_i915_private *dev_priv, | 718 | void (*force_wake_put)(struct drm_i915_private *dev_priv, |
737 | enum forcewake_domains domains); | 719 | enum forcewake_domains domains); |
738 | 720 | ||
739 | uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); | 721 | uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, |
740 | uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); | 722 | i915_reg_t r, bool trace); |
741 | uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); | 723 | uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, |
742 | uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); | 724 | i915_reg_t r, bool trace); |
743 | 725 | uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, | |
744 | void (*mmio_writeb)(struct drm_i915_private *dev_priv, i915_reg_t r, | 726 | i915_reg_t r, bool trace); |
745 | uint8_t val, bool trace); | 727 | uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, |
746 | void (*mmio_writew)(struct drm_i915_private *dev_priv, i915_reg_t r, | 728 | i915_reg_t r, bool trace); |
747 | uint16_t val, bool trace); | 729 | |
748 | void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r, | 730 | void (*mmio_writeb)(struct drm_i915_private *dev_priv, |
749 | uint32_t val, bool trace); | 731 | i915_reg_t r, uint8_t val, bool trace); |
732 | void (*mmio_writew)(struct drm_i915_private *dev_priv, | ||
733 | i915_reg_t r, uint16_t val, bool trace); | ||
734 | void (*mmio_writel)(struct drm_i915_private *dev_priv, | ||
735 | i915_reg_t r, uint32_t val, bool trace); | ||
750 | }; | 736 | }; |
751 | 737 | ||
752 | struct intel_forcewake_range { | 738 | struct intel_forcewake_range { |
@@ -770,32 +756,35 @@ struct intel_uncore { | |||
770 | enum forcewake_domains fw_domains; | 756 | enum forcewake_domains fw_domains; |
771 | enum forcewake_domains fw_domains_active; | 757 | enum forcewake_domains fw_domains_active; |
772 | 758 | ||
759 | u32 fw_set; | ||
760 | u32 fw_clear; | ||
761 | u32 fw_reset; | ||
762 | |||
773 | struct intel_uncore_forcewake_domain { | 763 | struct intel_uncore_forcewake_domain { |
774 | struct drm_i915_private *i915; | ||
775 | enum forcewake_domain_id id; | 764 | enum forcewake_domain_id id; |
776 | enum forcewake_domains mask; | 765 | enum forcewake_domains mask; |
777 | unsigned wake_count; | 766 | unsigned wake_count; |
778 | struct hrtimer timer; | 767 | struct hrtimer timer; |
779 | i915_reg_t reg_set; | 768 | i915_reg_t reg_set; |
780 | u32 val_set; | ||
781 | u32 val_clear; | ||
782 | i915_reg_t reg_ack; | 769 | i915_reg_t reg_ack; |
783 | i915_reg_t reg_post; | ||
784 | u32 val_reset; | ||
785 | } fw_domain[FW_DOMAIN_ID_COUNT]; | 770 | } fw_domain[FW_DOMAIN_ID_COUNT]; |
786 | 771 | ||
787 | int unclaimed_mmio_check; | 772 | int unclaimed_mmio_check; |
788 | }; | 773 | }; |
789 | 774 | ||
775 | #define __mask_next_bit(mask) ({ \ | ||
776 | int __idx = ffs(mask) - 1; \ | ||
777 | mask &= ~BIT(__idx); \ | ||
778 | __idx; \ | ||
779 | }) | ||
780 | |||
790 | /* Iterate over initialised fw domains */ | 781 | /* Iterate over initialised fw domains */ |
791 | #define for_each_fw_domain_masked(domain__, mask__, dev_priv__) \ | 782 | #define for_each_fw_domain_masked(domain__, mask__, dev_priv__, tmp__) \ |
792 | for ((domain__) = &(dev_priv__)->uncore.fw_domain[0]; \ | 783 | for (tmp__ = (mask__); \ |
793 | (domain__) < &(dev_priv__)->uncore.fw_domain[FW_DOMAIN_ID_COUNT]; \ | 784 | tmp__ ? (domain__ = &(dev_priv__)->uncore.fw_domain[__mask_next_bit(tmp__)]), 1 : 0;) |
794 | (domain__)++) \ | ||
795 | for_each_if ((mask__) & (domain__)->mask) | ||
796 | 785 | ||
797 | #define for_each_fw_domain(domain__, dev_priv__) \ | 786 | #define for_each_fw_domain(domain__, dev_priv__, tmp__) \ |
798 | for_each_fw_domain_masked(domain__, FORCEWAKE_ALL, dev_priv__) | 787 | for_each_fw_domain_masked(domain__, (dev_priv__)->uncore.fw_domains, dev_priv__, tmp__) |
799 | 788 | ||
800 | #define CSR_VERSION(major, minor) ((major) << 16 | (minor)) | 789 | #define CSR_VERSION(major, minor) ((major) << 16 | (minor)) |
801 | #define CSR_VERSION_MAJOR(version) ((version) >> 16) | 790 | #define CSR_VERSION_MAJOR(version) ((version) >> 16) |
@@ -846,6 +835,7 @@ struct intel_csr { | |||
846 | func(has_resource_streamer); \ | 835 | func(has_resource_streamer); \ |
847 | func(has_runtime_pm); \ | 836 | func(has_runtime_pm); \ |
848 | func(has_snoop); \ | 837 | func(has_snoop); \ |
838 | func(unfenced_needs_alignment); \ | ||
849 | func(cursor_needs_physical); \ | 839 | func(cursor_needs_physical); \ |
850 | func(hws_needs_physical); \ | 840 | func(hws_needs_physical); \ |
851 | func(overlay_needs_physical); \ | 841 | func(overlay_needs_physical); \ |
@@ -2578,12 +2568,6 @@ static inline struct drm_i915_private *huc_to_i915(struct intel_huc *huc) | |||
2578 | (id__)++) \ | 2568 | (id__)++) \ |
2579 | for_each_if ((engine__) = (dev_priv__)->engine[(id__)]) | 2569 | for_each_if ((engine__) = (dev_priv__)->engine[(id__)]) |
2580 | 2570 | ||
2581 | #define __mask_next_bit(mask) ({ \ | ||
2582 | int __idx = ffs(mask) - 1; \ | ||
2583 | mask &= ~BIT(__idx); \ | ||
2584 | __idx; \ | ||
2585 | }) | ||
2586 | |||
2587 | /* Iterator over subset of engines selected by mask */ | 2571 | /* Iterator over subset of engines selected by mask */ |
2588 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ | 2572 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ |
2589 | for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ | 2573 | for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ |
@@ -3956,14 +3940,14 @@ u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, | |||
3956 | #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) | 3940 | #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) |
3957 | 3941 | ||
3958 | #define __raw_read(x, s) \ | 3942 | #define __raw_read(x, s) \ |
3959 | static inline uint##x##_t __raw_i915_read##x(struct drm_i915_private *dev_priv, \ | 3943 | static inline uint##x##_t __raw_i915_read##x(const struct drm_i915_private *dev_priv, \ |
3960 | i915_reg_t reg) \ | 3944 | i915_reg_t reg) \ |
3961 | { \ | 3945 | { \ |
3962 | return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \ | 3946 | return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \ |
3963 | } | 3947 | } |
3964 | 3948 | ||
3965 | #define __raw_write(x, s) \ | 3949 | #define __raw_write(x, s) \ |
3966 | static inline void __raw_i915_write##x(struct drm_i915_private *dev_priv, \ | 3950 | static inline void __raw_i915_write##x(const struct drm_i915_private *dev_priv, \ |
3967 | i915_reg_t reg, uint##x##_t val) \ | 3951 | i915_reg_t reg, uint##x##_t val) \ |
3968 | { \ | 3952 | { \ |
3969 | write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \ | 3953 | write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 58e1db77d70e..bbc6f1c9f175 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2321,7 +2321,7 @@ rebuild_st: | |||
2321 | st->nents = 0; | 2321 | st->nents = 0; |
2322 | for (i = 0; i < page_count; i++) { | 2322 | for (i = 0; i < page_count; i++) { |
2323 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); | 2323 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); |
2324 | if (IS_ERR(page)) { | 2324 | if (unlikely(IS_ERR(page))) { |
2325 | i915_gem_shrink(dev_priv, | 2325 | i915_gem_shrink(dev_priv, |
2326 | page_count, | 2326 | page_count, |
2327 | I915_SHRINK_BOUND | | 2327 | I915_SHRINK_BOUND | |
@@ -2329,12 +2329,21 @@ rebuild_st: | |||
2329 | I915_SHRINK_PURGEABLE); | 2329 | I915_SHRINK_PURGEABLE); |
2330 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); | 2330 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); |
2331 | } | 2331 | } |
2332 | if (IS_ERR(page)) { | 2332 | if (unlikely(IS_ERR(page))) { |
2333 | gfp_t reclaim; | ||
2334 | |||
2333 | /* We've tried hard to allocate the memory by reaping | 2335 | /* We've tried hard to allocate the memory by reaping |
2334 | * our own buffer, now let the real VM do its job and | 2336 | * our own buffer, now let the real VM do its job and |
2335 | * go down in flames if truly OOM. | 2337 | * go down in flames if truly OOM. |
2338 | * | ||
2339 | * However, since graphics tend to be disposable, | ||
2340 | * defer the oom here by reporting the ENOMEM back | ||
2341 | * to userspace. | ||
2336 | */ | 2342 | */ |
2337 | page = shmem_read_mapping_page(mapping, i); | 2343 | reclaim = mapping_gfp_constraint(mapping, 0); |
2344 | reclaim |= __GFP_NORETRY; /* reclaim, but no oom */ | ||
2345 | |||
2346 | page = shmem_read_mapping_page_gfp(mapping, i, reclaim); | ||
2338 | if (IS_ERR(page)) { | 2347 | if (IS_ERR(page)) { |
2339 | ret = PTR_ERR(page); | 2348 | ret = PTR_ERR(page); |
2340 | goto err_sg; | 2349 | goto err_sg; |
@@ -2989,10 +2998,15 @@ void i915_gem_set_wedged(struct drm_i915_private *dev_priv) | |||
2989 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 2998 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
2990 | set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); | 2999 | set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); |
2991 | 3000 | ||
3001 | /* Retire completed requests first so the list of inflight/incomplete | ||
3002 | * requests is accurate and we don't try and mark successful requests | ||
3003 | * as in error during __i915_gem_set_wedged_BKL(). | ||
3004 | */ | ||
3005 | i915_gem_retire_requests(dev_priv); | ||
3006 | |||
2992 | stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); | 3007 | stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); |
2993 | 3008 | ||
2994 | i915_gem_context_lost(dev_priv); | 3009 | i915_gem_context_lost(dev_priv); |
2995 | i915_gem_retire_requests(dev_priv); | ||
2996 | 3010 | ||
2997 | mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); | 3011 | mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); |
2998 | } | 3012 | } |
@@ -3098,9 +3112,7 @@ i915_gem_idle_work_handler(struct work_struct *work) | |||
3098 | * Wait for last execlists context complete, but bail out in case a | 3112 | * Wait for last execlists context complete, but bail out in case a |
3099 | * new request is submitted. | 3113 | * new request is submitted. |
3100 | */ | 3114 | */ |
3101 | wait_for(READ_ONCE(dev_priv->gt.active_requests) || | 3115 | wait_for(intel_engines_are_idle(dev_priv), 10); |
3102 | intel_engines_are_idle(dev_priv), | ||
3103 | 10); | ||
3104 | if (READ_ONCE(dev_priv->gt.active_requests)) | 3116 | if (READ_ONCE(dev_priv->gt.active_requests)) |
3105 | return; | 3117 | return; |
3106 | 3118 | ||
@@ -3259,6 +3271,29 @@ static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags) | |||
3259 | return 0; | 3271 | return 0; |
3260 | } | 3272 | } |
3261 | 3273 | ||
3274 | static int wait_for_engine(struct intel_engine_cs *engine, int timeout_ms) | ||
3275 | { | ||
3276 | return wait_for(intel_engine_is_idle(engine), timeout_ms); | ||
3277 | } | ||
3278 | |||
3279 | static int wait_for_engines(struct drm_i915_private *i915) | ||
3280 | { | ||
3281 | struct intel_engine_cs *engine; | ||
3282 | enum intel_engine_id id; | ||
3283 | |||
3284 | for_each_engine(engine, i915, id) { | ||
3285 | if (GEM_WARN_ON(wait_for_engine(engine, 50))) { | ||
3286 | i915_gem_set_wedged(i915); | ||
3287 | return -EIO; | ||
3288 | } | ||
3289 | |||
3290 | GEM_BUG_ON(intel_engine_get_seqno(engine) != | ||
3291 | intel_engine_last_submit(engine)); | ||
3292 | } | ||
3293 | |||
3294 | return 0; | ||
3295 | } | ||
3296 | |||
3262 | int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) | 3297 | int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) |
3263 | { | 3298 | { |
3264 | int ret; | 3299 | int ret; |
@@ -3273,13 +3308,16 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) | |||
3273 | if (ret) | 3308 | if (ret) |
3274 | return ret; | 3309 | return ret; |
3275 | } | 3310 | } |
3311 | |||
3312 | i915_gem_retire_requests(i915); | ||
3313 | GEM_BUG_ON(i915->gt.active_requests); | ||
3314 | |||
3315 | ret = wait_for_engines(i915); | ||
3276 | } else { | 3316 | } else { |
3277 | ret = wait_for_timeline(&i915->gt.global_timeline, flags); | 3317 | ret = wait_for_timeline(&i915->gt.global_timeline, flags); |
3278 | if (ret) | ||
3279 | return ret; | ||
3280 | } | 3318 | } |
3281 | 3319 | ||
3282 | return 0; | 3320 | return ret; |
3283 | } | 3321 | } |
3284 | 3322 | ||
3285 | /** Flushes the GTT write domain for the object if it's dirty. */ | 3323 | /** Flushes the GTT write domain for the object if it's dirty. */ |
@@ -3307,8 +3345,14 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) | |||
3307 | * system agents we cannot reproduce this behaviour). | 3345 | * system agents we cannot reproduce this behaviour). |
3308 | */ | 3346 | */ |
3309 | wmb(); | 3347 | wmb(); |
3310 | if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) | 3348 | if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) { |
3311 | POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); | 3349 | if (intel_runtime_pm_get_if_in_use(dev_priv)) { |
3350 | spin_lock_irq(&dev_priv->uncore.lock); | ||
3351 | POSTING_READ_FW(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); | ||
3352 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
3353 | intel_runtime_pm_put(dev_priv); | ||
3354 | } | ||
3355 | } | ||
3312 | 3356 | ||
3313 | intel_fb_obj_flush(obj, write_origin(obj, I915_GEM_DOMAIN_GTT)); | 3357 | intel_fb_obj_flush(obj, write_origin(obj, I915_GEM_DOMAIN_GTT)); |
3314 | 3358 | ||
@@ -4408,9 +4452,6 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) | |||
4408 | if (ret) | 4452 | if (ret) |
4409 | goto err_unlock; | 4453 | goto err_unlock; |
4410 | 4454 | ||
4411 | i915_gem_retire_requests(dev_priv); | ||
4412 | GEM_BUG_ON(dev_priv->gt.active_requests); | ||
4413 | |||
4414 | assert_kernel_context_is_current(dev_priv); | 4455 | assert_kernel_context_is_current(dev_priv); |
4415 | i915_gem_context_lost(dev_priv); | 4456 | i915_gem_context_lost(dev_priv); |
4416 | mutex_unlock(&dev->struct_mutex); | 4457 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_gem_clflush.c b/drivers/gpu/drm/i915/i915_gem_clflush.c index d925fb582ba7..ffd01e02fe94 100644 --- a/drivers/gpu/drm/i915/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/i915_gem_clflush.c | |||
@@ -168,7 +168,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj, | |||
168 | 168 | ||
169 | i915_sw_fence_await_reservation(&clflush->wait, | 169 | i915_sw_fence_await_reservation(&clflush->wait, |
170 | obj->resv, NULL, | 170 | obj->resv, NULL, |
171 | false, I915_FENCE_TIMEOUT, | 171 | true, I915_FENCE_TIMEOUT, |
172 | GFP_KERNEL); | 172 | GFP_KERNEL); |
173 | 173 | ||
174 | reservation_object_lock(obj->resv, NULL); | 174 | reservation_object_lock(obj->resv, NULL); |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 486051ed681d..8bd0c4966913 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -576,25 +576,25 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) | |||
576 | } | 576 | } |
577 | 577 | ||
578 | static inline int | 578 | static inline int |
579 | mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) | 579 | mi_set_context(struct drm_i915_gem_request *req, u32 flags) |
580 | { | 580 | { |
581 | struct drm_i915_private *dev_priv = req->i915; | 581 | struct drm_i915_private *dev_priv = req->i915; |
582 | struct intel_engine_cs *engine = req->engine; | 582 | struct intel_engine_cs *engine = req->engine; |
583 | enum intel_engine_id id; | 583 | enum intel_engine_id id; |
584 | u32 *cs, flags = hw_flags | MI_MM_SPACE_GTT; | ||
585 | const int num_rings = | 584 | const int num_rings = |
586 | /* Use an extended w/a on ivb+ if signalling from other rings */ | 585 | /* Use an extended w/a on gen7 if signalling from other rings */ |
587 | i915.semaphores ? | 586 | (i915.semaphores && INTEL_GEN(dev_priv) == 7) ? |
588 | INTEL_INFO(dev_priv)->num_rings - 1 : | 587 | INTEL_INFO(dev_priv)->num_rings - 1 : |
589 | 0; | 588 | 0; |
590 | int len; | 589 | int len; |
590 | u32 *cs; | ||
591 | 591 | ||
592 | /* These flags are for resource streamer on HSW+ */ | 592 | flags |= MI_MM_SPACE_GTT; |
593 | if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8) | 593 | if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8) |
594 | flags |= (HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN); | 594 | /* These flags are for resource streamer on HSW+ */ |
595 | else if (INTEL_GEN(dev_priv) < 8) | 595 | flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN; |
596 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); | 596 | else |
597 | 597 | flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN; | |
598 | 598 | ||
599 | len = 4; | 599 | len = 4; |
600 | if (INTEL_GEN(dev_priv) >= 7) | 600 | if (INTEL_GEN(dev_priv) >= 7) |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 2da3a94fc9f3..51e365f70464 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
@@ -196,7 +196,6 @@ search_again: | |||
196 | if (ret) | 196 | if (ret) |
197 | return ret; | 197 | return ret; |
198 | 198 | ||
199 | i915_gem_retire_requests(dev_priv); | ||
200 | goto search_again; | 199 | goto search_again; |
201 | 200 | ||
202 | found: | 201 | found: |
@@ -383,7 +382,6 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) | |||
383 | if (ret) | 382 | if (ret) |
384 | return ret; | 383 | return ret; |
385 | 384 | ||
386 | i915_gem_retire_requests(dev_priv); | ||
387 | WARN_ON(!list_empty(&vm->active_list)); | 385 | WARN_ON(!list_empty(&vm->active_list)); |
388 | } | 386 | } |
389 | 387 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index dd7181ed5eca..a3e59c8ef27b 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -890,6 +890,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *engine, | |||
890 | struct list_head ordered_vmas; | 890 | struct list_head ordered_vmas; |
891 | struct list_head pinned_vmas; | 891 | struct list_head pinned_vmas; |
892 | bool has_fenced_gpu_access = INTEL_GEN(engine->i915) < 4; | 892 | bool has_fenced_gpu_access = INTEL_GEN(engine->i915) < 4; |
893 | bool needs_unfenced_map = INTEL_INFO(engine->i915)->unfenced_needs_alignment; | ||
893 | int retry; | 894 | int retry; |
894 | 895 | ||
895 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; | 896 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; |
@@ -910,7 +911,8 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *engine, | |||
910 | if (!has_fenced_gpu_access) | 911 | if (!has_fenced_gpu_access) |
911 | entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE; | 912 | entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE; |
912 | need_fence = | 913 | need_fence = |
913 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | 914 | (entry->flags & EXEC_OBJECT_NEEDS_FENCE || |
915 | needs_unfenced_map) && | ||
914 | i915_gem_object_is_tiled(obj); | 916 | i915_gem_object_is_tiled(obj); |
915 | need_mappable = need_fence || need_reloc_mappable(vma); | 917 | need_mappable = need_fence || need_reloc_mappable(vma); |
916 | 918 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index cee9c4fec52a..8bab4aea63e6 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -2364,7 +2364,7 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, | |||
2364 | struct i915_ggtt *ggtt = &dev_priv->ggtt; | 2364 | struct i915_ggtt *ggtt = &dev_priv->ggtt; |
2365 | 2365 | ||
2366 | if (unlikely(ggtt->do_idle_maps)) { | 2366 | if (unlikely(ggtt->do_idle_maps)) { |
2367 | if (i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED)) { | 2367 | if (i915_gem_wait_for_idle(dev_priv, 0)) { |
2368 | DRM_ERROR("Failed to wait for idle; VT'd may hang.\n"); | 2368 | DRM_ERROR("Failed to wait for idle; VT'd may hang.\n"); |
2369 | /* Wait a bit, in hopes it avoids the hang */ | 2369 | /* Wait a bit, in hopes it avoids the hang */ |
2370 | udelay(10); | 2370 | udelay(10); |
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 0e8d1010cecb..6348353b91ec 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c | |||
@@ -37,6 +37,17 @@ static const char *i915_fence_get_driver_name(struct dma_fence *fence) | |||
37 | 37 | ||
38 | static const char *i915_fence_get_timeline_name(struct dma_fence *fence) | 38 | static const char *i915_fence_get_timeline_name(struct dma_fence *fence) |
39 | { | 39 | { |
40 | /* The timeline struct (as part of the ppgtt underneath a context) | ||
41 | * may be freed when the request is no longer in use by the GPU. | ||
42 | * We could extend the life of a context to beyond that of all | ||
43 | * fences, possibly keeping the hw resource around indefinitely, | ||
44 | * or we just give them a false name. Since | ||
45 | * dma_fence_ops.get_timeline_name is a debug feature, the occasional | ||
46 | * lie seems justifiable. | ||
47 | */ | ||
48 | if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) | ||
49 | return "signaled"; | ||
50 | |||
40 | return to_request(fence)->timeline->common->name; | 51 | return to_request(fence)->timeline->common->name; |
41 | } | 52 | } |
42 | 53 | ||
@@ -180,7 +191,6 @@ i915_priotree_init(struct i915_priotree *pt) | |||
180 | 191 | ||
181 | static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | 192 | static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) |
182 | { | 193 | { |
183 | struct i915_gem_timeline *timeline = &i915->gt.global_timeline; | ||
184 | struct intel_engine_cs *engine; | 194 | struct intel_engine_cs *engine; |
185 | enum intel_engine_id id; | 195 | enum intel_engine_id id; |
186 | int ret; | 196 | int ret; |
@@ -192,15 +202,10 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | |||
192 | if (ret) | 202 | if (ret) |
193 | return ret; | 203 | return ret; |
194 | 204 | ||
195 | i915_gem_retire_requests(i915); | ||
196 | GEM_BUG_ON(i915->gt.active_requests > 1); | ||
197 | |||
198 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ | 205 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ |
199 | for_each_engine(engine, i915, id) { | 206 | for_each_engine(engine, i915, id) { |
200 | struct intel_timeline *tl = &timeline->engine[id]; | 207 | struct i915_gem_timeline *timeline; |
201 | 208 | struct intel_timeline *tl = engine->timeline; | |
202 | if (wait_for(intel_engine_is_idle(engine), 50)) | ||
203 | return -EBUSY; | ||
204 | 209 | ||
205 | if (!i915_seqno_passed(seqno, tl->seqno)) { | 210 | if (!i915_seqno_passed(seqno, tl->seqno)) { |
206 | /* spin until threads are complete */ | 211 | /* spin until threads are complete */ |
@@ -211,14 +216,10 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | |||
211 | /* Finally reset hw state */ | 216 | /* Finally reset hw state */ |
212 | tl->seqno = seqno; | 217 | tl->seqno = seqno; |
213 | intel_engine_init_global_seqno(engine, seqno); | 218 | intel_engine_init_global_seqno(engine, seqno); |
214 | } | ||
215 | 219 | ||
216 | list_for_each_entry(timeline, &i915->gt.timelines, link) { | 220 | list_for_each_entry(timeline, &i915->gt.timelines, link) |
217 | for_each_engine(engine, i915, id) { | 221 | memset(timeline->engine[id].sync_seqno, 0, |
218 | struct intel_timeline *tl = &timeline->engine[id]; | 222 | sizeof(timeline->engine[id].sync_seqno)); |
219 | |||
220 | memset(tl->sync_seqno, 0, sizeof(tl->sync_seqno)); | ||
221 | } | ||
222 | } | 223 | } |
223 | 224 | ||
224 | return 0; | 225 | return 0; |
@@ -295,7 +296,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) | |||
295 | * completion order. | 296 | * completion order. |
296 | */ | 297 | */ |
297 | list_del(&request->ring_link); | 298 | list_del(&request->ring_link); |
298 | request->ring->last_retired_head = request->postfix; | 299 | request->ring->head = request->postfix; |
299 | if (!--request->i915->gt.active_requests) { | 300 | if (!--request->i915->gt.active_requests) { |
300 | GEM_BUG_ON(!request->i915->gt.awake); | 301 | GEM_BUG_ON(!request->i915->gt.awake); |
301 | mod_delayed_work(request->i915->wq, | 302 | mod_delayed_work(request->i915->wq, |
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 832ac9e45801..1642fff9cf13 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c | |||
@@ -30,16 +30,25 @@ | |||
30 | /** | 30 | /** |
31 | * DOC: GuC-based command submission | 31 | * DOC: GuC-based command submission |
32 | * | 32 | * |
33 | * i915_guc_client: | 33 | * GuC client: |
34 | * We use the term client to avoid confusion with contexts. A i915_guc_client is | 34 | * A i915_guc_client refers to a submission path through GuC. Currently, there |
35 | * equivalent to GuC object guc_context_desc. This context descriptor is | 35 | * is only one of these (the execbuf_client) and this one is charged with all |
36 | * allocated from a pool of 1024 entries. Kernel driver will allocate doorbell | 36 | * submissions to the GuC. This struct is the owner of a doorbell, a process |
37 | * and workqueue for it. Also the process descriptor (guc_process_desc), which | 37 | * descriptor and a workqueue (all of them inside a single gem object that |
38 | * is mapped to client space. So the client can write Work Item then ring the | 38 | * contains all required pages for these elements). |
39 | * doorbell. | ||
40 | * | 39 | * |
41 | * To simplify the implementation, we allocate one gem object that contains all | 40 | * GuC stage descriptor: |
42 | * pages for doorbell, process descriptor and workqueue. | 41 | * During initialization, the driver allocates a static pool of 1024 such |
42 | * descriptors, and shares them with the GuC. | ||
43 | * Currently, there exists a 1:1 mapping between a i915_guc_client and a | ||
44 | * guc_stage_desc (via the client's stage_id), so effectively only one | ||
45 | * gets used. This stage descriptor lets the GuC know about the doorbell, | ||
46 | * workqueue and process descriptor. Theoretically, it also lets the GuC | ||
47 | * know about our HW contexts (context ID, etc...), but we actually | ||
48 | * employ a kind of submission where the GuC uses the LRCA sent via the work | ||
49 | * item instead (the single guc_stage_desc associated to execbuf client | ||
50 | * contains information about the default kernel context only, but this is | ||
51 | * essentially unused). This is called a "proxy" submission. | ||
43 | * | 52 | * |
44 | * The Scratch registers: | 53 | * The Scratch registers: |
45 | * There are 16 MMIO-based registers start from 0xC180. The kernel driver writes | 54 | * There are 16 MMIO-based registers start from 0xC180. The kernel driver writes |
@@ -62,34 +71,91 @@ | |||
62 | * ELSP context descriptor dword into Work Item. | 71 | * ELSP context descriptor dword into Work Item. |
63 | * See guc_wq_item_append() | 72 | * See guc_wq_item_append() |
64 | * | 73 | * |
74 | * ADS: | ||
75 | * The Additional Data Struct (ADS) has pointers for different buffers used by | ||
76 | * the GuC. One single gem object contains the ADS struct itself (guc_ads), the | ||
77 | * scheduling policies (guc_policies), a structure describing a collection of | ||
78 | * register sets (guc_mmio_reg_state) and some extra pages for the GuC to save | ||
79 | * its internal state for sleep. | ||
80 | * | ||
65 | */ | 81 | */ |
66 | 82 | ||
83 | static inline bool is_high_priority(struct i915_guc_client* client) | ||
84 | { | ||
85 | return client->priority <= GUC_CLIENT_PRIORITY_HIGH; | ||
86 | } | ||
87 | |||
88 | static int __reserve_doorbell(struct i915_guc_client *client) | ||
89 | { | ||
90 | unsigned long offset; | ||
91 | unsigned long end; | ||
92 | u16 id; | ||
93 | |||
94 | GEM_BUG_ON(client->doorbell_id != GUC_DOORBELL_INVALID); | ||
95 | |||
96 | /* | ||
97 | * The bitmap tracks which doorbell registers are currently in use. | ||
98 | * It is split into two halves; the first half is used for normal | ||
99 | * priority contexts, the second half for high-priority ones. | ||
100 | */ | ||
101 | offset = 0; | ||
102 | end = GUC_NUM_DOORBELLS/2; | ||
103 | if (is_high_priority(client)) { | ||
104 | offset = end; | ||
105 | end += offset; | ||
106 | } | ||
107 | |||
108 | id = find_next_zero_bit(client->guc->doorbell_bitmap, offset, end); | ||
109 | if (id == end) | ||
110 | return -ENOSPC; | ||
111 | |||
112 | __set_bit(id, client->guc->doorbell_bitmap); | ||
113 | client->doorbell_id = id; | ||
114 | DRM_DEBUG_DRIVER("client %u (high prio=%s) reserved doorbell: %d\n", | ||
115 | client->stage_id, yesno(is_high_priority(client)), | ||
116 | id); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static void __unreserve_doorbell(struct i915_guc_client *client) | ||
121 | { | ||
122 | GEM_BUG_ON(client->doorbell_id == GUC_DOORBELL_INVALID); | ||
123 | |||
124 | __clear_bit(client->doorbell_id, client->guc->doorbell_bitmap); | ||
125 | client->doorbell_id = GUC_DOORBELL_INVALID; | ||
126 | } | ||
127 | |||
67 | /* | 128 | /* |
68 | * Tell the GuC to allocate or deallocate a specific doorbell | 129 | * Tell the GuC to allocate or deallocate a specific doorbell |
69 | */ | 130 | */ |
70 | 131 | ||
71 | static int guc_allocate_doorbell(struct intel_guc *guc, | 132 | static int __guc_allocate_doorbell(struct intel_guc *guc, u32 stage_id) |
72 | struct i915_guc_client *client) | ||
73 | { | 133 | { |
74 | u32 action[] = { | 134 | u32 action[] = { |
75 | INTEL_GUC_ACTION_ALLOCATE_DOORBELL, | 135 | INTEL_GUC_ACTION_ALLOCATE_DOORBELL, |
76 | client->ctx_index | 136 | stage_id |
77 | }; | 137 | }; |
78 | 138 | ||
79 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 139 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
80 | } | 140 | } |
81 | 141 | ||
82 | static int guc_release_doorbell(struct intel_guc *guc, | 142 | static int __guc_deallocate_doorbell(struct intel_guc *guc, u32 stage_id) |
83 | struct i915_guc_client *client) | ||
84 | { | 143 | { |
85 | u32 action[] = { | 144 | u32 action[] = { |
86 | INTEL_GUC_ACTION_DEALLOCATE_DOORBELL, | 145 | INTEL_GUC_ACTION_DEALLOCATE_DOORBELL, |
87 | client->ctx_index | 146 | stage_id |
88 | }; | 147 | }; |
89 | 148 | ||
90 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 149 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
91 | } | 150 | } |
92 | 151 | ||
152 | static struct guc_stage_desc *__get_stage_desc(struct i915_guc_client *client) | ||
153 | { | ||
154 | struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; | ||
155 | |||
156 | return &base[client->stage_id]; | ||
157 | } | ||
158 | |||
93 | /* | 159 | /* |
94 | * Initialise, update, or clear doorbell data shared with the GuC | 160 | * Initialise, update, or clear doorbell data shared with the GuC |
95 | * | 161 | * |
@@ -97,107 +163,129 @@ static int guc_release_doorbell(struct intel_guc *guc, | |||
97 | * client object which contains the page being used for the doorbell | 163 | * client object which contains the page being used for the doorbell |
98 | */ | 164 | */ |
99 | 165 | ||
100 | static int guc_update_doorbell_id(struct intel_guc *guc, | 166 | static void __update_doorbell_desc(struct i915_guc_client *client, u16 new_id) |
101 | struct i915_guc_client *client, | ||
102 | u16 new_id) | ||
103 | { | 167 | { |
104 | struct sg_table *sg = guc->ctx_pool_vma->pages; | 168 | struct guc_stage_desc *desc; |
105 | void *doorbell_bitmap = guc->doorbell_bitmap; | ||
106 | struct guc_doorbell_info *doorbell; | ||
107 | struct guc_context_desc desc; | ||
108 | size_t len; | ||
109 | 169 | ||
110 | doorbell = client->vaddr + client->doorbell_offset; | 170 | /* Update the GuC's idea of the doorbell ID */ |
171 | desc = __get_stage_desc(client); | ||
172 | desc->db_id = new_id; | ||
173 | } | ||
111 | 174 | ||
112 | if (client->doorbell_id != GUC_INVALID_DOORBELL_ID && | 175 | static struct guc_doorbell_info *__get_doorbell(struct i915_guc_client *client) |
113 | test_bit(client->doorbell_id, doorbell_bitmap)) { | 176 | { |
114 | /* Deactivate the old doorbell */ | 177 | return client->vaddr + client->doorbell_offset; |
115 | doorbell->db_status = GUC_DOORBELL_DISABLED; | 178 | } |
116 | (void)guc_release_doorbell(guc, client); | ||
117 | __clear_bit(client->doorbell_id, doorbell_bitmap); | ||
118 | } | ||
119 | 179 | ||
120 | /* Update the GuC's idea of the doorbell ID */ | 180 | static bool has_doorbell(struct i915_guc_client *client) |
121 | len = sg_pcopy_to_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), | 181 | { |
122 | sizeof(desc) * client->ctx_index); | 182 | if (client->doorbell_id == GUC_DOORBELL_INVALID) |
123 | if (len != sizeof(desc)) | 183 | return false; |
124 | return -EFAULT; | ||
125 | desc.db_id = new_id; | ||
126 | len = sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), | ||
127 | sizeof(desc) * client->ctx_index); | ||
128 | if (len != sizeof(desc)) | ||
129 | return -EFAULT; | ||
130 | |||
131 | client->doorbell_id = new_id; | ||
132 | if (new_id == GUC_INVALID_DOORBELL_ID) | ||
133 | return 0; | ||
134 | 184 | ||
135 | /* Activate the new doorbell */ | 185 | return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); |
136 | __set_bit(new_id, doorbell_bitmap); | 186 | } |
187 | |||
188 | static int __create_doorbell(struct i915_guc_client *client) | ||
189 | { | ||
190 | struct guc_doorbell_info *doorbell; | ||
191 | int err; | ||
192 | |||
193 | doorbell = __get_doorbell(client); | ||
137 | doorbell->db_status = GUC_DOORBELL_ENABLED; | 194 | doorbell->db_status = GUC_DOORBELL_ENABLED; |
138 | doorbell->cookie = client->doorbell_cookie; | 195 | doorbell->cookie = client->doorbell_cookie; |
139 | return guc_allocate_doorbell(guc, client); | 196 | |
197 | err = __guc_allocate_doorbell(client->guc, client->stage_id); | ||
198 | if (err) { | ||
199 | doorbell->db_status = GUC_DOORBELL_DISABLED; | ||
200 | doorbell->cookie = 0; | ||
201 | } | ||
202 | return err; | ||
140 | } | 203 | } |
141 | 204 | ||
142 | static void guc_disable_doorbell(struct intel_guc *guc, | 205 | static int __destroy_doorbell(struct i915_guc_client *client) |
143 | struct i915_guc_client *client) | ||
144 | { | 206 | { |
145 | (void)guc_update_doorbell_id(guc, client, GUC_INVALID_DOORBELL_ID); | 207 | struct drm_i915_private *dev_priv = guc_to_i915(client->guc); |
208 | struct guc_doorbell_info *doorbell; | ||
209 | u16 db_id = client->doorbell_id; | ||
146 | 210 | ||
147 | /* XXX: wait for any interrupts */ | 211 | GEM_BUG_ON(db_id >= GUC_DOORBELL_INVALID); |
148 | /* XXX: wait for workqueue to drain */ | 212 | |
213 | doorbell = __get_doorbell(client); | ||
214 | doorbell->db_status = GUC_DOORBELL_DISABLED; | ||
215 | doorbell->cookie = 0; | ||
216 | |||
217 | /* Doorbell release flow requires that we wait for GEN8_DRB_VALID bit | ||
218 | * to go to zero after updating db_status before we call the GuC to | ||
219 | * release the doorbell */ | ||
220 | if (wait_for_us(!(I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID), 10)) | ||
221 | WARN_ONCE(true, "Doorbell never became invalid after disable\n"); | ||
222 | |||
223 | return __guc_deallocate_doorbell(client->guc, client->stage_id); | ||
149 | } | 224 | } |
150 | 225 | ||
151 | static uint16_t | 226 | static int create_doorbell(struct i915_guc_client *client) |
152 | select_doorbell_register(struct intel_guc *guc, uint32_t priority) | ||
153 | { | 227 | { |
154 | /* | 228 | int ret; |
155 | * The bitmap tracks which doorbell registers are currently in use. | ||
156 | * It is split into two halves; the first half is used for normal | ||
157 | * priority contexts, the second half for high-priority ones. | ||
158 | * Note that logically higher priorities are numerically less than | ||
159 | * normal ones, so the test below means "is it high-priority?" | ||
160 | */ | ||
161 | const bool hi_pri = (priority <= GUC_CTX_PRIORITY_HIGH); | ||
162 | const uint16_t half = GUC_MAX_DOORBELLS / 2; | ||
163 | const uint16_t start = hi_pri ? half : 0; | ||
164 | const uint16_t end = start + half; | ||
165 | uint16_t id; | ||
166 | 229 | ||
167 | id = find_next_zero_bit(guc->doorbell_bitmap, end, start); | 230 | ret = __reserve_doorbell(client); |
168 | if (id == end) | 231 | if (ret) |
169 | id = GUC_INVALID_DOORBELL_ID; | 232 | return ret; |
170 | 233 | ||
171 | DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n", | 234 | __update_doorbell_desc(client, client->doorbell_id); |
172 | hi_pri ? "high" : "normal", id); | 235 | |
236 | ret = __create_doorbell(client); | ||
237 | if (ret) | ||
238 | goto err; | ||
239 | |||
240 | return 0; | ||
173 | 241 | ||
174 | return id; | 242 | err: |
243 | __update_doorbell_desc(client, GUC_DOORBELL_INVALID); | ||
244 | __unreserve_doorbell(client); | ||
245 | return ret; | ||
175 | } | 246 | } |
176 | 247 | ||
177 | /* | 248 | static int destroy_doorbell(struct i915_guc_client *client) |
178 | * Select, assign and relase doorbell cachelines | 249 | { |
179 | * | 250 | int err; |
180 | * These functions track which doorbell cachelines are in use. | 251 | |
181 | * The data they manipulate is protected by the intel_guc_send lock. | 252 | GEM_BUG_ON(!has_doorbell(client)); |
182 | */ | 253 | |
254 | /* XXX: wait for any interrupts */ | ||
255 | /* XXX: wait for workqueue to drain */ | ||
256 | |||
257 | err = __destroy_doorbell(client); | ||
258 | if (err) | ||
259 | return err; | ||
260 | |||
261 | __update_doorbell_desc(client, GUC_DOORBELL_INVALID); | ||
262 | |||
263 | __unreserve_doorbell(client); | ||
183 | 264 | ||
184 | static uint32_t select_doorbell_cacheline(struct intel_guc *guc) | 265 | return 0; |
266 | } | ||
267 | |||
268 | static unsigned long __select_cacheline(struct intel_guc* guc) | ||
185 | { | 269 | { |
186 | const uint32_t cacheline_size = cache_line_size(); | 270 | unsigned long offset; |
187 | uint32_t offset; | ||
188 | 271 | ||
189 | /* Doorbell uses a single cache line within a page */ | 272 | /* Doorbell uses a single cache line within a page */ |
190 | offset = offset_in_page(guc->db_cacheline); | 273 | offset = offset_in_page(guc->db_cacheline); |
191 | 274 | ||
192 | /* Moving to next cache line to reduce contention */ | 275 | /* Moving to next cache line to reduce contention */ |
193 | guc->db_cacheline += cacheline_size; | 276 | guc->db_cacheline += cache_line_size(); |
194 | |||
195 | DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n", | ||
196 | offset, guc->db_cacheline, cacheline_size); | ||
197 | 277 | ||
278 | DRM_DEBUG_DRIVER("reserved cacheline 0x%lx, next 0x%x, linesize %u\n", | ||
279 | offset, guc->db_cacheline, cache_line_size()); | ||
198 | return offset; | 280 | return offset; |
199 | } | 281 | } |
200 | 282 | ||
283 | static inline struct guc_process_desc * | ||
284 | __get_process_desc(struct i915_guc_client *client) | ||
285 | { | ||
286 | return client->vaddr + client->proc_desc_offset; | ||
287 | } | ||
288 | |||
201 | /* | 289 | /* |
202 | * Initialise the process descriptor shared with the GuC firmware. | 290 | * Initialise the process descriptor shared with the GuC firmware. |
203 | */ | 291 | */ |
@@ -206,9 +294,7 @@ static void guc_proc_desc_init(struct intel_guc *guc, | |||
206 | { | 294 | { |
207 | struct guc_process_desc *desc; | 295 | struct guc_process_desc *desc; |
208 | 296 | ||
209 | desc = client->vaddr + client->proc_desc_offset; | 297 | desc = memset(__get_process_desc(client), 0, sizeof(*desc)); |
210 | |||
211 | memset(desc, 0, sizeof(*desc)); | ||
212 | 298 | ||
213 | /* | 299 | /* |
214 | * XXX: pDoorbell and WQVBaseAddress are pointers in process address | 300 | * XXX: pDoorbell and WQVBaseAddress are pointers in process address |
@@ -219,42 +305,41 @@ static void guc_proc_desc_init(struct intel_guc *guc, | |||
219 | desc->wq_base_addr = 0; | 305 | desc->wq_base_addr = 0; |
220 | desc->db_base_addr = 0; | 306 | desc->db_base_addr = 0; |
221 | 307 | ||
222 | desc->context_id = client->ctx_index; | 308 | desc->stage_id = client->stage_id; |
223 | desc->wq_size_bytes = client->wq_size; | 309 | desc->wq_size_bytes = client->wq_size; |
224 | desc->wq_status = WQ_STATUS_ACTIVE; | 310 | desc->wq_status = WQ_STATUS_ACTIVE; |
225 | desc->priority = client->priority; | 311 | desc->priority = client->priority; |
226 | } | 312 | } |
227 | 313 | ||
228 | /* | 314 | /* |
229 | * Initialise/clear the context descriptor shared with the GuC firmware. | 315 | * Initialise/clear the stage descriptor shared with the GuC firmware. |
230 | * | 316 | * |
231 | * This descriptor tells the GuC where (in GGTT space) to find the important | 317 | * This descriptor tells the GuC where (in GGTT space) to find the important |
232 | * data structures relating to this client (doorbell, process descriptor, | 318 | * data structures relating to this client (doorbell, process descriptor, |
233 | * write queue, etc). | 319 | * write queue, etc). |
234 | */ | 320 | */ |
235 | 321 | static void guc_stage_desc_init(struct intel_guc *guc, | |
236 | static void guc_ctx_desc_init(struct intel_guc *guc, | 322 | struct i915_guc_client *client) |
237 | struct i915_guc_client *client) | ||
238 | { | 323 | { |
239 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 324 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
240 | struct intel_engine_cs *engine; | 325 | struct intel_engine_cs *engine; |
241 | struct i915_gem_context *ctx = client->owner; | 326 | struct i915_gem_context *ctx = client->owner; |
242 | struct guc_context_desc desc; | 327 | struct guc_stage_desc *desc; |
243 | struct sg_table *sg; | ||
244 | unsigned int tmp; | 328 | unsigned int tmp; |
245 | u32 gfx_addr; | 329 | u32 gfx_addr; |
246 | 330 | ||
247 | memset(&desc, 0, sizeof(desc)); | 331 | desc = __get_stage_desc(client); |
332 | memset(desc, 0, sizeof(*desc)); | ||
248 | 333 | ||
249 | desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL; | 334 | desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL; |
250 | desc.context_id = client->ctx_index; | 335 | desc->stage_id = client->stage_id; |
251 | desc.priority = client->priority; | 336 | desc->priority = client->priority; |
252 | desc.db_id = client->doorbell_id; | 337 | desc->db_id = client->doorbell_id; |
253 | 338 | ||
254 | for_each_engine_masked(engine, dev_priv, client->engines, tmp) { | 339 | for_each_engine_masked(engine, dev_priv, client->engines, tmp) { |
255 | struct intel_context *ce = &ctx->engine[engine->id]; | 340 | struct intel_context *ce = &ctx->engine[engine->id]; |
256 | uint32_t guc_engine_id = engine->guc_id; | 341 | uint32_t guc_engine_id = engine->guc_id; |
257 | struct guc_execlist_context *lrc = &desc.lrc[guc_engine_id]; | 342 | struct guc_execlist_context *lrc = &desc->lrc[guc_engine_id]; |
258 | 343 | ||
259 | /* TODO: We have a design issue to be solved here. Only when we | 344 | /* TODO: We have a design issue to be solved here. Only when we |
260 | * receive the first batch, we know which engine is used by the | 345 | * receive the first batch, we know which engine is used by the |
@@ -266,12 +351,22 @@ static void guc_ctx_desc_init(struct intel_guc *guc, | |||
266 | if (!ce->state) | 351 | if (!ce->state) |
267 | break; /* XXX: continue? */ | 352 | break; /* XXX: continue? */ |
268 | 353 | ||
354 | /* | ||
355 | * XXX: When this is a GUC_STAGE_DESC_ATTR_KERNEL client (proxy | ||
356 | * submission or, in other words, not using a direct submission | ||
357 | * model) the KMD's LRCA is not used for any work submission. | ||
358 | * Instead, the GuC uses the LRCA of the user mode context (see | ||
359 | * guc_wq_item_append below). | ||
360 | */ | ||
269 | lrc->context_desc = lower_32_bits(ce->lrc_desc); | 361 | lrc->context_desc = lower_32_bits(ce->lrc_desc); |
270 | 362 | ||
271 | /* The state page is after PPHWSP */ | 363 | /* The state page is after PPHWSP */ |
272 | lrc->ring_lcra = | 364 | lrc->ring_lrca = |
273 | guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; | 365 | guc_ggtt_offset(ce->state) + LRC_STATE_PN * PAGE_SIZE; |
274 | lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | | 366 | |
367 | /* XXX: In direct submission, the GuC wants the HW context id | ||
368 | * here. In proxy submission, it wants the stage id */ | ||
369 | lrc->context_id = (client->stage_id << GUC_ELC_CTXID_OFFSET) | | ||
275 | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); | 370 | (guc_engine_id << GUC_ELC_ENGINE_OFFSET); |
276 | 371 | ||
277 | lrc->ring_begin = guc_ggtt_offset(ce->ring->vma); | 372 | lrc->ring_begin = guc_ggtt_offset(ce->ring->vma); |
@@ -279,50 +374,36 @@ static void guc_ctx_desc_init(struct intel_guc *guc, | |||
279 | lrc->ring_next_free_location = lrc->ring_begin; | 374 | lrc->ring_next_free_location = lrc->ring_begin; |
280 | lrc->ring_current_tail_pointer_value = 0; | 375 | lrc->ring_current_tail_pointer_value = 0; |
281 | 376 | ||
282 | desc.engines_used |= (1 << guc_engine_id); | 377 | desc->engines_used |= (1 << guc_engine_id); |
283 | } | 378 | } |
284 | 379 | ||
285 | DRM_DEBUG_DRIVER("Host engines 0x%x => GuC engines used 0x%x\n", | 380 | DRM_DEBUG_DRIVER("Host engines 0x%x => GuC engines used 0x%x\n", |
286 | client->engines, desc.engines_used); | 381 | client->engines, desc->engines_used); |
287 | WARN_ON(desc.engines_used == 0); | 382 | WARN_ON(desc->engines_used == 0); |
288 | 383 | ||
289 | /* | 384 | /* |
290 | * The doorbell, process descriptor, and workqueue are all parts | 385 | * The doorbell, process descriptor, and workqueue are all parts |
291 | * of the client object, which the GuC will reference via the GGTT | 386 | * of the client object, which the GuC will reference via the GGTT |
292 | */ | 387 | */ |
293 | gfx_addr = guc_ggtt_offset(client->vma); | 388 | gfx_addr = guc_ggtt_offset(client->vma); |
294 | desc.db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + | 389 | desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + |
295 | client->doorbell_offset; | 390 | client->doorbell_offset; |
296 | desc.db_trigger_cpu = | 391 | desc->db_trigger_cpu = (uintptr_t)__get_doorbell(client); |
297 | (uintptr_t)client->vaddr + client->doorbell_offset; | 392 | desc->db_trigger_uk = gfx_addr + client->doorbell_offset; |
298 | desc.db_trigger_uk = gfx_addr + client->doorbell_offset; | 393 | desc->process_desc = gfx_addr + client->proc_desc_offset; |
299 | desc.process_desc = gfx_addr + client->proc_desc_offset; | 394 | desc->wq_addr = gfx_addr + client->wq_offset; |
300 | desc.wq_addr = gfx_addr + client->wq_offset; | 395 | desc->wq_size = client->wq_size; |
301 | desc.wq_size = client->wq_size; | ||
302 | |||
303 | /* | ||
304 | * XXX: Take LRCs from an existing context if this is not an | ||
305 | * IsKMDCreatedContext client | ||
306 | */ | ||
307 | desc.desc_private = (uintptr_t)client; | ||
308 | 396 | ||
309 | /* Pool context is pinned already */ | 397 | desc->desc_private = (uintptr_t)client; |
310 | sg = guc->ctx_pool_vma->pages; | ||
311 | sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), | ||
312 | sizeof(desc) * client->ctx_index); | ||
313 | } | 398 | } |
314 | 399 | ||
315 | static void guc_ctx_desc_fini(struct intel_guc *guc, | 400 | static void guc_stage_desc_fini(struct intel_guc *guc, |
316 | struct i915_guc_client *client) | 401 | struct i915_guc_client *client) |
317 | { | 402 | { |
318 | struct guc_context_desc desc; | 403 | struct guc_stage_desc *desc; |
319 | struct sg_table *sg; | ||
320 | |||
321 | memset(&desc, 0, sizeof(desc)); | ||
322 | 404 | ||
323 | sg = guc->ctx_pool_vma->pages; | 405 | desc = __get_stage_desc(client); |
324 | sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc), | 406 | memset(desc, 0, sizeof(*desc)); |
325 | sizeof(desc) * client->ctx_index); | ||
326 | } | 407 | } |
327 | 408 | ||
328 | /** | 409 | /** |
@@ -345,8 +426,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) | |||
345 | { | 426 | { |
346 | const size_t wqi_size = sizeof(struct guc_wq_item); | 427 | const size_t wqi_size = sizeof(struct guc_wq_item); |
347 | struct i915_guc_client *client = request->i915->guc.execbuf_client; | 428 | struct i915_guc_client *client = request->i915->guc.execbuf_client; |
348 | struct guc_process_desc *desc = client->vaddr + | 429 | struct guc_process_desc *desc = __get_process_desc(client); |
349 | client->proc_desc_offset; | ||
350 | u32 freespace; | 430 | u32 freespace; |
351 | int ret; | 431 | int ret; |
352 | 432 | ||
@@ -391,19 +471,17 @@ static void guc_wq_item_append(struct i915_guc_client *client, | |||
391 | const size_t wqi_size = sizeof(struct guc_wq_item); | 471 | const size_t wqi_size = sizeof(struct guc_wq_item); |
392 | const u32 wqi_len = wqi_size/sizeof(u32) - 1; | 472 | const u32 wqi_len = wqi_size/sizeof(u32) - 1; |
393 | struct intel_engine_cs *engine = rq->engine; | 473 | struct intel_engine_cs *engine = rq->engine; |
394 | struct guc_process_desc *desc; | 474 | struct guc_process_desc *desc = __get_process_desc(client); |
395 | struct guc_wq_item *wqi; | 475 | struct guc_wq_item *wqi; |
396 | u32 freespace, tail, wq_off; | 476 | u32 freespace, tail, wq_off; |
397 | 477 | ||
398 | desc = client->vaddr + client->proc_desc_offset; | ||
399 | |||
400 | /* Free space is guaranteed, see i915_guc_wq_reserve() above */ | 478 | /* Free space is guaranteed, see i915_guc_wq_reserve() above */ |
401 | freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); | 479 | freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); |
402 | GEM_BUG_ON(freespace < wqi_size); | 480 | GEM_BUG_ON(freespace < wqi_size); |
403 | 481 | ||
404 | /* The GuC firmware wants the tail index in QWords, not bytes */ | 482 | /* The GuC firmware wants the tail index in QWords, not bytes */ |
405 | tail = rq->tail; | 483 | tail = rq->tail; |
406 | GEM_BUG_ON(tail & 7); | 484 | assert_ring_tail_valid(rq->ring, rq->tail); |
407 | tail >>= 3; | 485 | tail >>= 3; |
408 | GEM_BUG_ON(tail > WQ_RING_TAIL_MAX); | 486 | GEM_BUG_ON(tail > WQ_RING_TAIL_MAX); |
409 | 487 | ||
@@ -436,19 +514,27 @@ static void guc_wq_item_append(struct i915_guc_client *client, | |||
436 | /* The GuC wants only the low-order word of the context descriptor */ | 514 | /* The GuC wants only the low-order word of the context descriptor */ |
437 | wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine); | 515 | wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine); |
438 | 516 | ||
439 | wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT; | 517 | wqi->submit_element_info = tail << WQ_RING_TAIL_SHIFT; |
440 | wqi->fence_id = rq->global_seqno; | 518 | wqi->fence_id = rq->global_seqno; |
441 | } | 519 | } |
442 | 520 | ||
521 | static void guc_reset_wq(struct i915_guc_client *client) | ||
522 | { | ||
523 | struct guc_process_desc *desc = __get_process_desc(client); | ||
524 | |||
525 | desc->head = 0; | ||
526 | desc->tail = 0; | ||
527 | |||
528 | client->wq_tail = 0; | ||
529 | } | ||
530 | |||
443 | static int guc_ring_doorbell(struct i915_guc_client *client) | 531 | static int guc_ring_doorbell(struct i915_guc_client *client) |
444 | { | 532 | { |
445 | struct guc_process_desc *desc; | 533 | struct guc_process_desc *desc = __get_process_desc(client); |
446 | union guc_doorbell_qw db_cmp, db_exc, db_ret; | 534 | union guc_doorbell_qw db_cmp, db_exc, db_ret; |
447 | union guc_doorbell_qw *db; | 535 | union guc_doorbell_qw *db; |
448 | int attempt = 2, ret = -EAGAIN; | 536 | int attempt = 2, ret = -EAGAIN; |
449 | 537 | ||
450 | desc = client->vaddr + client->proc_desc_offset; | ||
451 | |||
452 | /* Update the tail so it is visible to GuC */ | 538 | /* Update the tail so it is visible to GuC */ |
453 | desc->tail = client->wq_tail; | 539 | desc->tail = client->wq_tail; |
454 | 540 | ||
@@ -463,7 +549,7 @@ static int guc_ring_doorbell(struct i915_guc_client *client) | |||
463 | db_exc.cookie = 1; | 549 | db_exc.cookie = 1; |
464 | 550 | ||
465 | /* pointer of current doorbell cacheline */ | 551 | /* pointer of current doorbell cacheline */ |
466 | db = client->vaddr + client->doorbell_offset; | 552 | db = (union guc_doorbell_qw *)__get_doorbell(client); |
467 | 553 | ||
468 | while (attempt--) { | 554 | while (attempt--) { |
469 | /* lets ring the doorbell */ | 555 | /* lets ring the doorbell */ |
@@ -573,23 +659,10 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) | |||
573 | { | 659 | { |
574 | struct execlist_port *port = engine->execlist_port; | 660 | struct execlist_port *port = engine->execlist_port; |
575 | struct drm_i915_gem_request *last = port[0].request; | 661 | struct drm_i915_gem_request *last = port[0].request; |
576 | unsigned long flags; | ||
577 | struct rb_node *rb; | 662 | struct rb_node *rb; |
578 | bool submit = false; | 663 | bool submit = false; |
579 | 664 | ||
580 | /* After execlist_first is updated, the tasklet will be rescheduled. | 665 | spin_lock_irq(&engine->timeline->lock); |
581 | * | ||
582 | * If we are currently running (inside the tasklet) and a third | ||
583 | * party queues a request and so updates engine->execlist_first under | ||
584 | * the spinlock (which we have elided), it will atomically set the | ||
585 | * TASKLET_SCHED flag causing the us to be re-executed and pick up | ||
586 | * the change in state (the update to TASKLET_SCHED incurs a memory | ||
587 | * barrier making this cross-cpu checking safe). | ||
588 | */ | ||
589 | if (!READ_ONCE(engine->execlist_first)) | ||
590 | return false; | ||
591 | |||
592 | spin_lock_irqsave(&engine->timeline->lock, flags); | ||
593 | rb = engine->execlist_first; | 666 | rb = engine->execlist_first; |
594 | while (rb) { | 667 | while (rb) { |
595 | struct drm_i915_gem_request *rq = | 668 | struct drm_i915_gem_request *rq = |
@@ -609,8 +682,8 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) | |||
609 | RB_CLEAR_NODE(&rq->priotree.node); | 682 | RB_CLEAR_NODE(&rq->priotree.node); |
610 | rq->priotree.priority = INT_MAX; | 683 | rq->priotree.priority = INT_MAX; |
611 | 684 | ||
612 | trace_i915_gem_request_in(rq, port - engine->execlist_port); | ||
613 | i915_guc_submit(rq); | 685 | i915_guc_submit(rq); |
686 | trace_i915_gem_request_in(rq, port - engine->execlist_port); | ||
614 | last = rq; | 687 | last = rq; |
615 | submit = true; | 688 | submit = true; |
616 | } | 689 | } |
@@ -619,7 +692,7 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) | |||
619 | nested_enable_signaling(last); | 692 | nested_enable_signaling(last); |
620 | engine->execlist_first = rb; | 693 | engine->execlist_first = rb; |
621 | } | 694 | } |
622 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 695 | spin_unlock_irq(&engine->timeline->lock); |
623 | 696 | ||
624 | return submit; | 697 | return submit; |
625 | } | 698 | } |
@@ -695,93 +768,100 @@ err: | |||
695 | return vma; | 768 | return vma; |
696 | } | 769 | } |
697 | 770 | ||
698 | static void | 771 | /* Check that a doorbell register is in the expected state */ |
699 | guc_client_free(struct drm_i915_private *dev_priv, | 772 | static bool doorbell_ok(struct intel_guc *guc, u16 db_id) |
700 | struct i915_guc_client *client) | ||
701 | { | 773 | { |
702 | struct intel_guc *guc = &dev_priv->guc; | 774 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
703 | 775 | u32 drbregl; | |
704 | if (!client) | 776 | bool valid; |
705 | return; | ||
706 | |||
707 | /* | ||
708 | * XXX: wait for any outstanding submissions before freeing memory. | ||
709 | * Be sure to drop any locks | ||
710 | */ | ||
711 | 777 | ||
712 | if (client->vaddr) { | 778 | GEM_BUG_ON(db_id >= GUC_DOORBELL_INVALID); |
713 | /* | ||
714 | * If we got as far as setting up a doorbell, make sure we | ||
715 | * shut it down before unmapping & deallocating the memory. | ||
716 | */ | ||
717 | guc_disable_doorbell(guc, client); | ||
718 | 779 | ||
719 | i915_gem_object_unpin_map(client->vma->obj); | 780 | drbregl = I915_READ(GEN8_DRBREGL(db_id)); |
720 | } | 781 | valid = drbregl & GEN8_DRB_VALID; |
721 | 782 | ||
722 | i915_vma_unpin_and_release(&client->vma); | 783 | if (test_bit(db_id, guc->doorbell_bitmap) == valid) |
784 | return true; | ||
723 | 785 | ||
724 | if (client->ctx_index != GUC_INVALID_CTX_ID) { | 786 | DRM_DEBUG_DRIVER("Doorbell %d has unexpected state (0x%x): valid=%s\n", |
725 | guc_ctx_desc_fini(guc, client); | 787 | db_id, drbregl, yesno(valid)); |
726 | ida_simple_remove(&guc->ctx_ids, client->ctx_index); | ||
727 | } | ||
728 | 788 | ||
729 | kfree(client); | 789 | return false; |
730 | } | 790 | } |
731 | 791 | ||
732 | /* Check that a doorbell register is in the expected state */ | 792 | /* |
733 | static bool guc_doorbell_check(struct intel_guc *guc, uint16_t db_id) | 793 | * If the GuC thinks that the doorbell is unassigned (e.g. because we reset and |
794 | * reloaded the GuC FW) we can use this function to tell the GuC to reassign the | ||
795 | * doorbell to the rightful owner. | ||
796 | */ | ||
797 | static int __reset_doorbell(struct i915_guc_client* client, u16 db_id) | ||
734 | { | 798 | { |
735 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 799 | int err; |
736 | i915_reg_t drbreg = GEN8_DRBREGL(db_id); | ||
737 | uint32_t value = I915_READ(drbreg); | ||
738 | bool enabled = (value & GUC_DOORBELL_ENABLED) != 0; | ||
739 | bool expected = test_bit(db_id, guc->doorbell_bitmap); | ||
740 | |||
741 | if (enabled == expected) | ||
742 | return true; | ||
743 | 800 | ||
744 | DRM_DEBUG_DRIVER("Doorbell %d (reg 0x%x) 0x%x, should be %s\n", | 801 | __update_doorbell_desc(client, db_id); |
745 | db_id, drbreg.reg, value, | 802 | err = __create_doorbell(client); |
746 | expected ? "active" : "inactive"); | 803 | if (!err) |
804 | err = __destroy_doorbell(client); | ||
747 | 805 | ||
748 | return false; | 806 | return err; |
749 | } | 807 | } |
750 | 808 | ||
751 | /* | 809 | /* |
752 | * Borrow the first client to set up & tear down each unused doorbell | 810 | * Set up & tear down each unused doorbell in turn, to ensure that all doorbell |
753 | * in turn, to ensure that all doorbell h/w is (re)initialised. | 811 | * HW is (re)initialised. For that end, we might have to borrow the first |
812 | * client. Also, tell GuC about all the doorbells in use by all clients. | ||
813 | * We do this because the KMD, the GuC and the doorbell HW can easily go out of | ||
814 | * sync (e.g. we can reset the GuC, but not the doorbel HW). | ||
754 | */ | 815 | */ |
755 | static void guc_init_doorbell_hw(struct intel_guc *guc) | 816 | static int guc_init_doorbell_hw(struct intel_guc *guc) |
756 | { | 817 | { |
757 | struct i915_guc_client *client = guc->execbuf_client; | 818 | struct i915_guc_client *client = guc->execbuf_client; |
758 | uint16_t db_id; | 819 | bool recreate_first_client = false; |
759 | int i, err; | 820 | u16 db_id; |
760 | 821 | int ret; | |
761 | guc_disable_doorbell(guc, client); | ||
762 | 822 | ||
763 | for (i = 0; i < GUC_MAX_DOORBELLS; ++i) { | 823 | /* For unused doorbells, make sure they are disabled */ |
764 | /* Skip if doorbell is OK */ | 824 | for_each_clear_bit(db_id, guc->doorbell_bitmap, GUC_NUM_DOORBELLS) { |
765 | if (guc_doorbell_check(guc, i)) | 825 | if (doorbell_ok(guc, db_id)) |
766 | continue; | 826 | continue; |
767 | 827 | ||
768 | err = guc_update_doorbell_id(guc, client, i); | 828 | if (has_doorbell(client)) { |
769 | if (err) | 829 | /* Borrow execbuf_client (we will recreate it later) */ |
770 | DRM_DEBUG_DRIVER("Doorbell %d update failed, err %d\n", | 830 | destroy_doorbell(client); |
771 | i, err); | 831 | recreate_first_client = true; |
832 | } | ||
833 | |||
834 | ret = __reset_doorbell(client, db_id); | ||
835 | WARN(ret, "Doorbell %u reset failed, err %d\n", db_id, ret); | ||
772 | } | 836 | } |
773 | 837 | ||
774 | db_id = select_doorbell_register(guc, client->priority); | 838 | if (recreate_first_client) { |
775 | WARN_ON(db_id == GUC_INVALID_DOORBELL_ID); | 839 | ret = __reserve_doorbell(client); |
840 | if (unlikely(ret)) { | ||
841 | DRM_ERROR("Couldn't re-reserve first client db: %d\n", ret); | ||
842 | return ret; | ||
843 | } | ||
844 | |||
845 | __update_doorbell_desc(client, client->doorbell_id); | ||
846 | } | ||
776 | 847 | ||
777 | err = guc_update_doorbell_id(guc, client, db_id); | 848 | /* Now for every client (and not only execbuf_client) make sure their |
778 | if (err) | 849 | * doorbells are known by the GuC */ |
779 | DRM_WARN("Failed to restore doorbell to %d, err %d\n", | 850 | //for (client = client_list; client != NULL; client = client->next) |
780 | db_id, err); | 851 | { |
852 | ret = __create_doorbell(client); | ||
853 | if (ret) { | ||
854 | DRM_ERROR("Couldn't recreate client %u doorbell: %d\n", | ||
855 | client->stage_id, ret); | ||
856 | return ret; | ||
857 | } | ||
858 | } | ||
781 | 859 | ||
782 | /* Read back & verify all doorbell registers */ | 860 | /* Read back & verify all (used & unused) doorbell registers */ |
783 | for (i = 0; i < GUC_MAX_DOORBELLS; ++i) | 861 | for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) |
784 | (void)guc_doorbell_check(guc, i); | 862 | WARN_ON(!doorbell_ok(guc, db_id)); |
863 | |||
864 | return 0; | ||
785 | } | 865 | } |
786 | 866 | ||
787 | /** | 867 | /** |
@@ -807,49 +887,46 @@ guc_client_alloc(struct drm_i915_private *dev_priv, | |||
807 | struct intel_guc *guc = &dev_priv->guc; | 887 | struct intel_guc *guc = &dev_priv->guc; |
808 | struct i915_vma *vma; | 888 | struct i915_vma *vma; |
809 | void *vaddr; | 889 | void *vaddr; |
810 | uint16_t db_id; | 890 | int ret; |
811 | 891 | ||
812 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 892 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
813 | if (!client) | 893 | if (!client) |
814 | return NULL; | 894 | return ERR_PTR(-ENOMEM); |
815 | 895 | ||
816 | client->owner = ctx; | ||
817 | client->guc = guc; | 896 | client->guc = guc; |
897 | client->owner = ctx; | ||
818 | client->engines = engines; | 898 | client->engines = engines; |
819 | client->priority = priority; | 899 | client->priority = priority; |
820 | client->doorbell_id = GUC_INVALID_DOORBELL_ID; | 900 | client->doorbell_id = GUC_DOORBELL_INVALID; |
901 | client->wq_offset = GUC_DB_SIZE; | ||
902 | client->wq_size = GUC_WQ_SIZE; | ||
903 | spin_lock_init(&client->wq_lock); | ||
821 | 904 | ||
822 | client->ctx_index = (uint32_t)ida_simple_get(&guc->ctx_ids, 0, | 905 | ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, |
823 | GUC_MAX_GPU_CONTEXTS, GFP_KERNEL); | 906 | GFP_KERNEL); |
824 | if (client->ctx_index >= GUC_MAX_GPU_CONTEXTS) { | 907 | if (ret < 0) |
825 | client->ctx_index = GUC_INVALID_CTX_ID; | 908 | goto err_client; |
826 | goto err; | 909 | |
827 | } | 910 | client->stage_id = ret; |
828 | 911 | ||
829 | /* The first page is doorbell/proc_desc. Two followed pages are wq. */ | 912 | /* The first page is doorbell/proc_desc. Two followed pages are wq. */ |
830 | vma = intel_guc_allocate_vma(guc, GUC_DB_SIZE + GUC_WQ_SIZE); | 913 | vma = intel_guc_allocate_vma(guc, GUC_DB_SIZE + GUC_WQ_SIZE); |
831 | if (IS_ERR(vma)) | 914 | if (IS_ERR(vma)) { |
832 | goto err; | 915 | ret = PTR_ERR(vma); |
916 | goto err_id; | ||
917 | } | ||
833 | 918 | ||
834 | /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ | 919 | /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ |
835 | client->vma = vma; | 920 | client->vma = vma; |
836 | 921 | ||
837 | vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); | 922 | vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); |
838 | if (IS_ERR(vaddr)) | 923 | if (IS_ERR(vaddr)) { |
839 | goto err; | 924 | ret = PTR_ERR(vaddr); |
840 | 925 | goto err_vma; | |
926 | } | ||
841 | client->vaddr = vaddr; | 927 | client->vaddr = vaddr; |
842 | 928 | ||
843 | spin_lock_init(&client->wq_lock); | 929 | client->doorbell_offset = __select_cacheline(guc); |
844 | client->wq_offset = GUC_DB_SIZE; | ||
845 | client->wq_size = GUC_WQ_SIZE; | ||
846 | |||
847 | db_id = select_doorbell_register(guc, client->priority); | ||
848 | if (db_id == GUC_INVALID_DOORBELL_ID) | ||
849 | /* XXX: evict a doorbell instead? */ | ||
850 | goto err; | ||
851 | |||
852 | client->doorbell_offset = select_doorbell_cacheline(guc); | ||
853 | 930 | ||
854 | /* | 931 | /* |
855 | * Since the doorbell only requires a single cacheline, we can save | 932 | * Since the doorbell only requires a single cacheline, we can save |
@@ -862,28 +939,47 @@ guc_client_alloc(struct drm_i915_private *dev_priv, | |||
862 | client->proc_desc_offset = (GUC_DB_SIZE / 2); | 939 | client->proc_desc_offset = (GUC_DB_SIZE / 2); |
863 | 940 | ||
864 | guc_proc_desc_init(guc, client); | 941 | guc_proc_desc_init(guc, client); |
865 | guc_ctx_desc_init(guc, client); | 942 | guc_stage_desc_init(guc, client); |
866 | 943 | ||
867 | /* For runtime client allocation we need to enable the doorbell. Not | 944 | ret = create_doorbell(client); |
868 | * required yet for the static execbuf_client as this special kernel | 945 | if (ret) |
869 | * client is enabled from i915_guc_submission_enable(). | 946 | goto err_vaddr; |
870 | * | ||
871 | * guc_update_doorbell_id(guc, client, db_id); | ||
872 | */ | ||
873 | 947 | ||
874 | DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: ctx_index %u\n", | 948 | DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: stage_id %u\n", |
875 | priority, client, client->engines, client->ctx_index); | 949 | priority, client, client->engines, client->stage_id); |
876 | DRM_DEBUG_DRIVER("doorbell id %u, cacheline offset 0x%x\n", | 950 | DRM_DEBUG_DRIVER("doorbell id %u, cacheline offset 0x%lx\n", |
877 | client->doorbell_id, client->doorbell_offset); | 951 | client->doorbell_id, client->doorbell_offset); |
878 | 952 | ||
879 | return client; | 953 | return client; |
880 | 954 | ||
881 | err: | 955 | err_vaddr: |
882 | guc_client_free(dev_priv, client); | 956 | i915_gem_object_unpin_map(client->vma->obj); |
883 | return NULL; | 957 | err_vma: |
958 | i915_vma_unpin_and_release(&client->vma); | ||
959 | err_id: | ||
960 | ida_simple_remove(&guc->stage_ids, client->stage_id); | ||
961 | err_client: | ||
962 | kfree(client); | ||
963 | return ERR_PTR(ret); | ||
884 | } | 964 | } |
885 | 965 | ||
966 | static void guc_client_free(struct i915_guc_client *client) | ||
967 | { | ||
968 | /* | ||
969 | * XXX: wait for any outstanding submissions before freeing memory. | ||
970 | * Be sure to drop any locks | ||
971 | */ | ||
886 | 972 | ||
973 | /* FIXME: in many cases, by the time we get here the GuC has been | ||
974 | * reset, so we cannot destroy the doorbell properly. Ignore the | ||
975 | * error message for now */ | ||
976 | destroy_doorbell(client); | ||
977 | guc_stage_desc_fini(client->guc, client); | ||
978 | i915_gem_object_unpin_map(client->vma->obj); | ||
979 | i915_vma_unpin_and_release(&client->vma); | ||
980 | ida_simple_remove(&client->guc->stage_ids, client->stage_id); | ||
981 | kfree(client); | ||
982 | } | ||
887 | 983 | ||
888 | static void guc_policies_init(struct guc_policies *policies) | 984 | static void guc_policies_init(struct guc_policies *policies) |
889 | { | 985 | { |
@@ -893,7 +989,7 @@ static void guc_policies_init(struct guc_policies *policies) | |||
893 | policies->dpc_promote_time = 500000; | 989 | policies->dpc_promote_time = 500000; |
894 | policies->max_num_work_items = POLICY_MAX_NUM_WI; | 990 | policies->max_num_work_items = POLICY_MAX_NUM_WI; |
895 | 991 | ||
896 | for (p = 0; p < GUC_CTX_PRIORITY_NUM; p++) { | 992 | for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) { |
897 | for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { | 993 | for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { |
898 | policy = &policies->policy[p][i]; | 994 | policy = &policies->policy[p][i]; |
899 | 995 | ||
@@ -907,7 +1003,7 @@ static void guc_policies_init(struct guc_policies *policies) | |||
907 | policies->is_valid = 1; | 1003 | policies->is_valid = 1; |
908 | } | 1004 | } |
909 | 1005 | ||
910 | static void guc_addon_create(struct intel_guc *guc) | 1006 | static int guc_ads_create(struct intel_guc *guc) |
911 | { | 1007 | { |
912 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 1008 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
913 | struct i915_vma *vma; | 1009 | struct i915_vma *vma; |
@@ -923,14 +1019,13 @@ static void guc_addon_create(struct intel_guc *guc) | |||
923 | enum intel_engine_id id; | 1019 | enum intel_engine_id id; |
924 | u32 base; | 1020 | u32 base; |
925 | 1021 | ||
926 | vma = guc->ads_vma; | 1022 | GEM_BUG_ON(guc->ads_vma); |
927 | if (!vma) { | ||
928 | vma = intel_guc_allocate_vma(guc, PAGE_ALIGN(sizeof(*blob))); | ||
929 | if (IS_ERR(vma)) | ||
930 | return; | ||
931 | 1023 | ||
932 | guc->ads_vma = vma; | 1024 | vma = intel_guc_allocate_vma(guc, PAGE_ALIGN(sizeof(*blob))); |
933 | } | 1025 | if (IS_ERR(vma)) |
1026 | return PTR_ERR(vma); | ||
1027 | |||
1028 | guc->ads_vma = vma; | ||
934 | 1029 | ||
935 | page = i915_vma_first_page(vma); | 1030 | page = i915_vma_first_page(vma); |
936 | blob = kmap(page); | 1031 | blob = kmap(page); |
@@ -940,11 +1035,11 @@ static void guc_addon_create(struct intel_guc *guc) | |||
940 | 1035 | ||
941 | /* MMIO reg state */ | 1036 | /* MMIO reg state */ |
942 | for_each_engine(engine, dev_priv, id) { | 1037 | for_each_engine(engine, dev_priv, id) { |
943 | blob->reg_state.mmio_white_list[engine->guc_id].mmio_start = | 1038 | blob->reg_state.white_list[engine->guc_id].mmio_start = |
944 | engine->mmio_base + GUC_MMIO_WHITE_LIST_START; | 1039 | engine->mmio_base + GUC_MMIO_WHITE_LIST_START; |
945 | 1040 | ||
946 | /* Nothing to be saved or restored for now. */ | 1041 | /* Nothing to be saved or restored for now. */ |
947 | blob->reg_state.mmio_white_list[engine->guc_id].count = 0; | 1042 | blob->reg_state.white_list[engine->guc_id].count = 0; |
948 | } | 1043 | } |
949 | 1044 | ||
950 | /* | 1045 | /* |
@@ -967,67 +1062,75 @@ static void guc_addon_create(struct intel_guc *guc) | |||
967 | blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); | 1062 | blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); |
968 | 1063 | ||
969 | kunmap(page); | 1064 | kunmap(page); |
1065 | |||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static void guc_ads_destroy(struct intel_guc *guc) | ||
1070 | { | ||
1071 | i915_vma_unpin_and_release(&guc->ads_vma); | ||
970 | } | 1072 | } |
971 | 1073 | ||
972 | /* | 1074 | /* |
973 | * Set up the memory resources to be shared with the GuC. At this point, | 1075 | * Set up the memory resources to be shared with the GuC (via the GGTT) |
974 | * we require just one object that can be mapped through the GGTT. | 1076 | * at firmware loading time. |
975 | */ | 1077 | */ |
976 | int i915_guc_submission_init(struct drm_i915_private *dev_priv) | 1078 | int i915_guc_submission_init(struct drm_i915_private *dev_priv) |
977 | { | 1079 | { |
978 | const size_t ctxsize = sizeof(struct guc_context_desc); | ||
979 | const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize; | ||
980 | const size_t gemsize = round_up(poolsize, PAGE_SIZE); | ||
981 | struct intel_guc *guc = &dev_priv->guc; | 1080 | struct intel_guc *guc = &dev_priv->guc; |
982 | struct i915_vma *vma; | 1081 | struct i915_vma *vma; |
1082 | void *vaddr; | ||
1083 | int ret; | ||
983 | 1084 | ||
984 | if (!HAS_GUC_SCHED(dev_priv)) | 1085 | if (guc->stage_desc_pool) |
985 | return 0; | 1086 | return 0; |
986 | 1087 | ||
987 | /* Wipe bitmap & delete client in case of reinitialisation */ | 1088 | vma = intel_guc_allocate_vma(guc, |
988 | bitmap_clear(guc->doorbell_bitmap, 0, GUC_MAX_DOORBELLS); | 1089 | PAGE_ALIGN(sizeof(struct guc_stage_desc) * |
989 | i915_guc_submission_disable(dev_priv); | 1090 | GUC_MAX_STAGE_DESCRIPTORS)); |
990 | |||
991 | if (!i915.enable_guc_submission) | ||
992 | return 0; /* not enabled */ | ||
993 | |||
994 | if (guc->ctx_pool_vma) | ||
995 | return 0; /* already allocated */ | ||
996 | |||
997 | vma = intel_guc_allocate_vma(guc, gemsize); | ||
998 | if (IS_ERR(vma)) | 1091 | if (IS_ERR(vma)) |
999 | return PTR_ERR(vma); | 1092 | return PTR_ERR(vma); |
1000 | 1093 | ||
1001 | guc->ctx_pool_vma = vma; | 1094 | guc->stage_desc_pool = vma; |
1002 | ida_init(&guc->ctx_ids); | 1095 | |
1003 | intel_guc_log_create(guc); | 1096 | vaddr = i915_gem_object_pin_map(guc->stage_desc_pool->obj, I915_MAP_WB); |
1004 | guc_addon_create(guc); | 1097 | if (IS_ERR(vaddr)) { |
1005 | 1098 | ret = PTR_ERR(vaddr); | |
1006 | guc->execbuf_client = guc_client_alloc(dev_priv, | 1099 | goto err_vma; |
1007 | INTEL_INFO(dev_priv)->ring_mask, | ||
1008 | GUC_CTX_PRIORITY_KMD_NORMAL, | ||
1009 | dev_priv->kernel_context); | ||
1010 | if (!guc->execbuf_client) { | ||
1011 | DRM_ERROR("Failed to create GuC client for execbuf!\n"); | ||
1012 | goto err; | ||
1013 | } | 1100 | } |
1014 | 1101 | ||
1102 | guc->stage_desc_pool_vaddr = vaddr; | ||
1103 | |||
1104 | ret = intel_guc_log_create(guc); | ||
1105 | if (ret < 0) | ||
1106 | goto err_vaddr; | ||
1107 | |||
1108 | ret = guc_ads_create(guc); | ||
1109 | if (ret < 0) | ||
1110 | goto err_log; | ||
1111 | |||
1112 | ida_init(&guc->stage_ids); | ||
1113 | |||
1015 | return 0; | 1114 | return 0; |
1016 | 1115 | ||
1017 | err: | 1116 | err_log: |
1018 | i915_guc_submission_fini(dev_priv); | 1117 | intel_guc_log_destroy(guc); |
1019 | return -ENOMEM; | 1118 | err_vaddr: |
1119 | i915_gem_object_unpin_map(guc->stage_desc_pool->obj); | ||
1120 | err_vma: | ||
1121 | i915_vma_unpin_and_release(&guc->stage_desc_pool); | ||
1122 | return ret; | ||
1020 | } | 1123 | } |
1021 | 1124 | ||
1022 | static void guc_reset_wq(struct i915_guc_client *client) | 1125 | void i915_guc_submission_fini(struct drm_i915_private *dev_priv) |
1023 | { | 1126 | { |
1024 | struct guc_process_desc *desc = client->vaddr + | 1127 | struct intel_guc *guc = &dev_priv->guc; |
1025 | client->proc_desc_offset; | ||
1026 | |||
1027 | desc->head = 0; | ||
1028 | desc->tail = 0; | ||
1029 | 1128 | ||
1030 | client->wq_tail = 0; | 1129 | ida_destroy(&guc->stage_ids); |
1130 | guc_ads_destroy(guc); | ||
1131 | intel_guc_log_destroy(guc); | ||
1132 | i915_gem_object_unpin_map(guc->stage_desc_pool->obj); | ||
1133 | i915_vma_unpin_and_release(&guc->stage_desc_pool); | ||
1031 | } | 1134 | } |
1032 | 1135 | ||
1033 | static void guc_interrupts_capture(struct drm_i915_private *dev_priv) | 1136 | static void guc_interrupts_capture(struct drm_i915_private *dev_priv) |
@@ -1072,20 +1175,60 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv) | |||
1072 | dev_priv->rps.pm_intrmsk_mbz &= ~GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; | 1175 | dev_priv->rps.pm_intrmsk_mbz &= ~GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; |
1073 | } | 1176 | } |
1074 | 1177 | ||
1178 | static void guc_interrupts_release(struct drm_i915_private *dev_priv) | ||
1179 | { | ||
1180 | struct intel_engine_cs *engine; | ||
1181 | enum intel_engine_id id; | ||
1182 | int irqs; | ||
1183 | |||
1184 | /* | ||
1185 | * tell all command streamers NOT to forward interrupts or vblank | ||
1186 | * to GuC. | ||
1187 | */ | ||
1188 | irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); | ||
1189 | irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); | ||
1190 | for_each_engine(engine, dev_priv, id) | ||
1191 | I915_WRITE(RING_MODE_GEN7(engine), irqs); | ||
1192 | |||
1193 | /* route all GT interrupts to the host */ | ||
1194 | I915_WRITE(GUC_BCS_RCS_IER, 0); | ||
1195 | I915_WRITE(GUC_VCS2_VCS1_IER, 0); | ||
1196 | I915_WRITE(GUC_WD_VECS_IER, 0); | ||
1197 | |||
1198 | dev_priv->rps.pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; | ||
1199 | dev_priv->rps.pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; | ||
1200 | } | ||
1201 | |||
1075 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv) | 1202 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv) |
1076 | { | 1203 | { |
1077 | struct intel_guc *guc = &dev_priv->guc; | 1204 | struct intel_guc *guc = &dev_priv->guc; |
1078 | struct i915_guc_client *client = guc->execbuf_client; | 1205 | struct i915_guc_client *client = guc->execbuf_client; |
1079 | struct intel_engine_cs *engine; | 1206 | struct intel_engine_cs *engine; |
1080 | enum intel_engine_id id; | 1207 | enum intel_engine_id id; |
1208 | int err; | ||
1209 | |||
1210 | if (!client) { | ||
1211 | client = guc_client_alloc(dev_priv, | ||
1212 | INTEL_INFO(dev_priv)->ring_mask, | ||
1213 | GUC_CLIENT_PRIORITY_KMD_NORMAL, | ||
1214 | dev_priv->kernel_context); | ||
1215 | if (IS_ERR(client)) { | ||
1216 | DRM_ERROR("Failed to create GuC client for execbuf!\n"); | ||
1217 | return PTR_ERR(client); | ||
1218 | } | ||
1081 | 1219 | ||
1082 | if (!client) | 1220 | guc->execbuf_client = client; |
1083 | return -ENODEV; | 1221 | } |
1084 | 1222 | ||
1085 | intel_guc_sample_forcewake(guc); | 1223 | err = intel_guc_sample_forcewake(guc); |
1224 | if (err) | ||
1225 | goto err_execbuf_client; | ||
1086 | 1226 | ||
1087 | guc_reset_wq(client); | 1227 | guc_reset_wq(client); |
1088 | guc_init_doorbell_hw(guc); | 1228 | |
1229 | err = guc_init_doorbell_hw(guc); | ||
1230 | if (err) | ||
1231 | goto err_execbuf_client; | ||
1089 | 1232 | ||
1090 | /* Take over from manual control of ELSP (execlists) */ | 1233 | /* Take over from manual control of ELSP (execlists) */ |
1091 | guc_interrupts_capture(dev_priv); | 1234 | guc_interrupts_capture(dev_priv); |
@@ -1112,30 +1255,11 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) | |||
1112 | } | 1255 | } |
1113 | 1256 | ||
1114 | return 0; | 1257 | return 0; |
1115 | } | ||
1116 | 1258 | ||
1117 | static void guc_interrupts_release(struct drm_i915_private *dev_priv) | 1259 | err_execbuf_client: |
1118 | { | 1260 | guc_client_free(guc->execbuf_client); |
1119 | struct intel_engine_cs *engine; | 1261 | guc->execbuf_client = NULL; |
1120 | enum intel_engine_id id; | 1262 | return err; |
1121 | int irqs; | ||
1122 | |||
1123 | /* | ||
1124 | * tell all command streamers NOT to forward interrupts or vblank | ||
1125 | * to GuC. | ||
1126 | */ | ||
1127 | irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); | ||
1128 | irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); | ||
1129 | for_each_engine(engine, dev_priv, id) | ||
1130 | I915_WRITE(RING_MODE_GEN7(engine), irqs); | ||
1131 | |||
1132 | /* route all GT interrupts to the host */ | ||
1133 | I915_WRITE(GUC_BCS_RCS_IER, 0); | ||
1134 | I915_WRITE(GUC_VCS2_VCS1_IER, 0); | ||
1135 | I915_WRITE(GUC_WD_VECS_IER, 0); | ||
1136 | |||
1137 | dev_priv->rps.pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; | ||
1138 | dev_priv->rps.pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; | ||
1139 | } | 1263 | } |
1140 | 1264 | ||
1141 | void i915_guc_submission_disable(struct drm_i915_private *dev_priv) | 1265 | void i915_guc_submission_disable(struct drm_i915_private *dev_priv) |
@@ -1144,30 +1268,11 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv) | |||
1144 | 1268 | ||
1145 | guc_interrupts_release(dev_priv); | 1269 | guc_interrupts_release(dev_priv); |
1146 | 1270 | ||
1147 | if (!guc->execbuf_client) | ||
1148 | return; | ||
1149 | |||
1150 | /* Revert back to manual ELSP submission */ | 1271 | /* Revert back to manual ELSP submission */ |
1151 | intel_engines_reset_default_submission(dev_priv); | 1272 | intel_engines_reset_default_submission(dev_priv); |
1152 | } | ||
1153 | |||
1154 | void i915_guc_submission_fini(struct drm_i915_private *dev_priv) | ||
1155 | { | ||
1156 | struct intel_guc *guc = &dev_priv->guc; | ||
1157 | struct i915_guc_client *client; | ||
1158 | 1273 | ||
1159 | client = fetch_and_zero(&guc->execbuf_client); | 1274 | guc_client_free(guc->execbuf_client); |
1160 | if (!client) | 1275 | guc->execbuf_client = NULL; |
1161 | return; | ||
1162 | |||
1163 | guc_client_free(dev_priv, client); | ||
1164 | |||
1165 | i915_vma_unpin_and_release(&guc->ads_vma); | ||
1166 | i915_vma_unpin_and_release(&guc->log.vma); | ||
1167 | |||
1168 | if (guc->ctx_pool_vma) | ||
1169 | ida_destroy(&guc->ctx_ids); | ||
1170 | i915_vma_unpin_and_release(&guc->ctx_pool_vma); | ||
1171 | } | 1276 | } |
1172 | 1277 | ||
1173 | /** | 1278 | /** |
@@ -1196,7 +1301,6 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv) | |||
1196 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); | 1301 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
1197 | } | 1302 | } |
1198 | 1303 | ||
1199 | |||
1200 | /** | 1304 | /** |
1201 | * intel_guc_resume() - notify GuC resuming from suspend state | 1305 | * intel_guc_resume() - notify GuC resuming from suspend state |
1202 | * @dev_priv: i915 device private | 1306 | * @dev_priv: i915 device private |
@@ -1222,5 +1326,3 @@ int intel_guc_resume(struct drm_i915_private *dev_priv) | |||
1222 | 1326 | ||
1223 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); | 1327 | return intel_guc_send(guc, data, ARRAY_SIZE(data)); |
1224 | } | 1328 | } |
1225 | |||
1226 | |||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8163d5024ff8..d9d196977f4a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1742,8 +1742,8 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) | |||
1742 | I915_WRITE(SOFT_SCRATCH(15), msg & ~flush); | 1742 | I915_WRITE(SOFT_SCRATCH(15), msg & ~flush); |
1743 | 1743 | ||
1744 | /* Handle flush interrupt in bottom half */ | 1744 | /* Handle flush interrupt in bottom half */ |
1745 | queue_work(dev_priv->guc.log.flush_wq, | 1745 | queue_work(dev_priv->guc.log.runtime.flush_wq, |
1746 | &dev_priv->guc.log.flush_work); | 1746 | &dev_priv->guc.log.runtime.flush_work); |
1747 | 1747 | ||
1748 | dev_priv->guc.log.flush_interrupt_count++; | 1748 | dev_priv->guc.log.flush_interrupt_count++; |
1749 | } else { | 1749 | } else { |
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 732101ed57fb..f87b0c4e564d 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c | |||
@@ -61,6 +61,7 @@ | |||
61 | .has_overlay = 1, .overlay_needs_physical = 1, \ | 61 | .has_overlay = 1, .overlay_needs_physical = 1, \ |
62 | .has_gmch_display = 1, \ | 62 | .has_gmch_display = 1, \ |
63 | .hws_needs_physical = 1, \ | 63 | .hws_needs_physical = 1, \ |
64 | .unfenced_needs_alignment = 1, \ | ||
64 | .ring_mask = RENDER_RING, \ | 65 | .ring_mask = RENDER_RING, \ |
65 | GEN_DEFAULT_PIPEOFFSETS, \ | 66 | GEN_DEFAULT_PIPEOFFSETS, \ |
66 | CURSOR_OFFSETS | 67 | CURSOR_OFFSETS |
@@ -102,6 +103,7 @@ static const struct intel_device_info intel_i915g_info = { | |||
102 | .platform = INTEL_I915G, .cursor_needs_physical = 1, | 103 | .platform = INTEL_I915G, .cursor_needs_physical = 1, |
103 | .has_overlay = 1, .overlay_needs_physical = 1, | 104 | .has_overlay = 1, .overlay_needs_physical = 1, |
104 | .hws_needs_physical = 1, | 105 | .hws_needs_physical = 1, |
106 | .unfenced_needs_alignment = 1, | ||
105 | }; | 107 | }; |
106 | 108 | ||
107 | static const struct intel_device_info intel_i915gm_info = { | 109 | static const struct intel_device_info intel_i915gm_info = { |
@@ -113,6 +115,7 @@ static const struct intel_device_info intel_i915gm_info = { | |||
113 | .supports_tv = 1, | 115 | .supports_tv = 1, |
114 | .has_fbc = 1, | 116 | .has_fbc = 1, |
115 | .hws_needs_physical = 1, | 117 | .hws_needs_physical = 1, |
118 | .unfenced_needs_alignment = 1, | ||
116 | }; | 119 | }; |
117 | 120 | ||
118 | static const struct intel_device_info intel_i945g_info = { | 121 | static const struct intel_device_info intel_i945g_info = { |
@@ -121,6 +124,7 @@ static const struct intel_device_info intel_i945g_info = { | |||
121 | .has_hotplug = 1, .cursor_needs_physical = 1, | 124 | .has_hotplug = 1, .cursor_needs_physical = 1, |
122 | .has_overlay = 1, .overlay_needs_physical = 1, | 125 | .has_overlay = 1, .overlay_needs_physical = 1, |
123 | .hws_needs_physical = 1, | 126 | .hws_needs_physical = 1, |
127 | .unfenced_needs_alignment = 1, | ||
124 | }; | 128 | }; |
125 | 129 | ||
126 | static const struct intel_device_info intel_i945gm_info = { | 130 | static const struct intel_device_info intel_i945gm_info = { |
@@ -131,6 +135,7 @@ static const struct intel_device_info intel_i945gm_info = { | |||
131 | .supports_tv = 1, | 135 | .supports_tv = 1, |
132 | .has_fbc = 1, | 136 | .has_fbc = 1, |
133 | .hws_needs_physical = 1, | 137 | .hws_needs_physical = 1, |
138 | .unfenced_needs_alignment = 1, | ||
134 | }; | 139 | }; |
135 | 140 | ||
136 | static const struct intel_device_info intel_g33_info = { | 141 | static const struct intel_device_info intel_g33_info = { |
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 8c121187ff39..060b171480d5 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c | |||
@@ -1705,7 +1705,7 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv, | |||
1705 | */ | 1705 | */ |
1706 | if (WARN_ON(stream->sample_flags != props->sample_flags)) { | 1706 | if (WARN_ON(stream->sample_flags != props->sample_flags)) { |
1707 | ret = -ENODEV; | 1707 | ret = -ENODEV; |
1708 | goto err_alloc; | 1708 | goto err_flags; |
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | list_add(&stream->link, &dev_priv->perf.streams); | 1711 | list_add(&stream->link, &dev_priv->perf.streams); |
@@ -1728,6 +1728,7 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv, | |||
1728 | 1728 | ||
1729 | err_open: | 1729 | err_open: |
1730 | list_del(&stream->link); | 1730 | list_del(&stream->link); |
1731 | err_flags: | ||
1731 | if (stream->ops->destroy) | 1732 | if (stream->ops->destroy) |
1732 | stream->ops->destroy(stream); | 1733 | stream->ops->destroy(stream); |
1733 | err_alloc: | 1734 | err_alloc: |
@@ -1793,6 +1794,11 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv, | |||
1793 | if (ret) | 1794 | if (ret) |
1794 | return ret; | 1795 | return ret; |
1795 | 1796 | ||
1797 | if (id == 0 || id >= DRM_I915_PERF_PROP_MAX) { | ||
1798 | DRM_DEBUG("Unknown i915 perf property ID\n"); | ||
1799 | return -EINVAL; | ||
1800 | } | ||
1801 | |||
1796 | switch ((enum drm_i915_perf_property_id)id) { | 1802 | switch ((enum drm_i915_perf_property_id)id) { |
1797 | case DRM_I915_PERF_PROP_CTX_HANDLE: | 1803 | case DRM_I915_PERF_PROP_CTX_HANDLE: |
1798 | props->single_context = 1; | 1804 | props->single_context = 1; |
@@ -1862,9 +1868,8 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv, | |||
1862 | props->oa_periodic = true; | 1868 | props->oa_periodic = true; |
1863 | props->oa_period_exponent = value; | 1869 | props->oa_period_exponent = value; |
1864 | break; | 1870 | break; |
1865 | default: | 1871 | case DRM_I915_PERF_PROP_MAX: |
1866 | MISSING_CASE(id); | 1872 | MISSING_CASE(id); |
1867 | DRM_DEBUG("Unknown i915 perf property ID\n"); | ||
1868 | return -EINVAL; | 1873 | return -EINVAL; |
1869 | } | 1874 | } |
1870 | 1875 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 04c8f69fcc62..11b12f412492 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -7829,7 +7829,14 @@ enum { | |||
7829 | #define TRANS_DDI_EDP_INPUT_B_ONOFF (5<<12) | 7829 | #define TRANS_DDI_EDP_INPUT_B_ONOFF (5<<12) |
7830 | #define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) | 7830 | #define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) |
7831 | #define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1<<8) | 7831 | #define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1<<8) |
7832 | #define TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE (1<<7) | ||
7833 | #define TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ (1<<6) | ||
7832 | #define TRANS_DDI_BFI_ENABLE (1<<4) | 7834 | #define TRANS_DDI_BFI_ENABLE (1<<4) |
7835 | #define TRANS_DDI_HIGH_TMDS_CHAR_RATE (1<<4) | ||
7836 | #define TRANS_DDI_HDMI_SCRAMBLING (1<<0) | ||
7837 | #define TRANS_DDI_HDMI_SCRAMBLING_MASK (TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE \ | ||
7838 | | TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ \ | ||
7839 | | TRANS_DDI_HDMI_SCRAMBLING) | ||
7833 | 7840 | ||
7834 | /* DisplayPort Transport Control */ | 7841 | /* DisplayPort Transport Control */ |
7835 | #define _DP_TP_CTL_A 0x64040 | 7842 | #define _DP_TP_CTL_A 0x64040 |
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 94a3a3299910..c5455d36b617 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h | |||
@@ -25,6 +25,24 @@ | |||
25 | #ifndef __I915_UTILS_H | 25 | #ifndef __I915_UTILS_H |
26 | #define __I915_UTILS_H | 26 | #define __I915_UTILS_H |
27 | 27 | ||
28 | #undef WARN_ON | ||
29 | /* Many gcc seem to no see through this and fall over :( */ | ||
30 | #if 0 | ||
31 | #define WARN_ON(x) ({ \ | ||
32 | bool __i915_warn_cond = (x); \ | ||
33 | if (__builtin_constant_p(__i915_warn_cond)) \ | ||
34 | BUILD_BUG_ON(__i915_warn_cond); \ | ||
35 | WARN(__i915_warn_cond, "WARN_ON(" #x ")"); }) | ||
36 | #else | ||
37 | #define WARN_ON(x) WARN((x), "%s", "WARN_ON(" __stringify(x) ")") | ||
38 | #endif | ||
39 | |||
40 | #undef WARN_ON_ONCE | ||
41 | #define WARN_ON_ONCE(x) WARN_ONCE((x), "%s", "WARN_ON_ONCE(" __stringify(x) ")") | ||
42 | |||
43 | #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ | ||
44 | (long)(x), __func__) | ||
45 | |||
28 | #if GCC_VERSION >= 70000 | 46 | #if GCC_VERSION >= 70000 |
29 | #define add_overflows(A, B) \ | 47 | #define add_overflows(A, B) \ |
30 | __builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0) | 48 | __builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0) |
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index ba986edee312..b6ea192ad550 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
@@ -47,11 +47,12 @@ static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b) | |||
47 | unsigned int intel_engine_wakeup(struct intel_engine_cs *engine) | 47 | unsigned int intel_engine_wakeup(struct intel_engine_cs *engine) |
48 | { | 48 | { |
49 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 49 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
50 | unsigned long flags; | ||
50 | unsigned int result; | 51 | unsigned int result; |
51 | 52 | ||
52 | spin_lock_irq(&b->irq_lock); | 53 | spin_lock_irqsave(&b->irq_lock, flags); |
53 | result = __intel_breadcrumbs_wakeup(b); | 54 | result = __intel_breadcrumbs_wakeup(b); |
54 | spin_unlock_irq(&b->irq_lock); | 55 | spin_unlock_irqrestore(&b->irq_lock, flags); |
55 | 56 | ||
56 | return result; | 57 | return result; |
57 | } | 58 | } |
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index c2cc33f3d888..dd3ad52b7dfe 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c | |||
@@ -1442,16 +1442,33 @@ static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, | |||
1442 | if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) | 1442 | if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) |
1443 | pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); | 1443 | pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); |
1444 | 1444 | ||
1445 | /* BSpec says "Do not use DisplayPort with CDCLK less than | 1445 | /* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz, |
1446 | * 432 MHz, audio enabled, port width x4, and link rate | 1446 | * audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else |
1447 | * HBR2 (5.4 GHz), or else there may be audio corruption or | 1447 | * there may be audio corruption or screen corruption." This cdclk |
1448 | * screen corruption." | 1448 | * restriction for GLK is 316.8 MHz and since GLK can output two |
1449 | * pixels per clock, the pixel rate becomes 2 * 316.8 MHz. | ||
1449 | */ | 1450 | */ |
1450 | if (intel_crtc_has_dp_encoder(crtc_state) && | 1451 | if (intel_crtc_has_dp_encoder(crtc_state) && |
1451 | crtc_state->has_audio && | 1452 | crtc_state->has_audio && |
1452 | crtc_state->port_clock >= 540000 && | 1453 | crtc_state->port_clock >= 540000 && |
1453 | crtc_state->lane_count == 4) | 1454 | crtc_state->lane_count == 4) { |
1454 | pixel_rate = max(432000, pixel_rate); | 1455 | if (IS_GEMINILAKE(dev_priv)) |
1456 | pixel_rate = max(2 * 316800, pixel_rate); | ||
1457 | else | ||
1458 | pixel_rate = max(432000, pixel_rate); | ||
1459 | } | ||
1460 | |||
1461 | /* According to BSpec, "The CD clock frequency must be at least twice | ||
1462 | * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default. | ||
1463 | * The check for GLK has to be adjusted as the platform can output | ||
1464 | * two pixels per clock. | ||
1465 | */ | ||
1466 | if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) { | ||
1467 | if (IS_GEMINILAKE(dev_priv)) | ||
1468 | pixel_rate = max(2 * 2 * 96000, pixel_rate); | ||
1469 | else | ||
1470 | pixel_rate = max(2 * 96000, pixel_rate); | ||
1471 | } | ||
1455 | 1472 | ||
1456 | return pixel_rate; | 1473 | return pixel_rate; |
1457 | } | 1474 | } |
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 36832257cc9b..1575bde0cf90 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c | |||
@@ -49,7 +49,7 @@ MODULE_FIRMWARE(I915_CSR_SKL); | |||
49 | MODULE_FIRMWARE(I915_CSR_BXT); | 49 | MODULE_FIRMWARE(I915_CSR_BXT); |
50 | #define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) | 50 | #define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) |
51 | 51 | ||
52 | #define FIRMWARE_URL "https://01.org/linuxgraphics/intel-linux-graphics-firmwares" | 52 | #define FIRMWARE_URL "https://01.org/linuxgraphics/downloads/firmware" |
53 | 53 | ||
54 | 54 | ||
55 | 55 | ||
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d8214ba8da14..0914ad96a71b 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -539,7 +539,7 @@ intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv, | |||
539 | * values in advance. This function programs the correct values for | 539 | * values in advance. This function programs the correct values for |
540 | * DP/eDP/FDI use cases. | 540 | * DP/eDP/FDI use cases. |
541 | */ | 541 | */ |
542 | void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) | 542 | static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) |
543 | { | 543 | { |
544 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 544 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
545 | u32 iboost_bit = 0; | 545 | u32 iboost_bit = 0; |
@@ -806,7 +806,7 @@ void hsw_fdi_link_train(struct intel_crtc *crtc, | |||
806 | DP_TP_CTL_ENABLE); | 806 | DP_TP_CTL_ENABLE); |
807 | } | 807 | } |
808 | 808 | ||
809 | void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) | 809 | static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) |
810 | { | 810 | { |
811 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | 811 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
812 | struct intel_digital_port *intel_dig_port = | 812 | struct intel_digital_port *intel_dig_port = |
@@ -837,7 +837,8 @@ intel_ddi_get_crtc_encoder(struct intel_crtc *crtc) | |||
837 | return ret; | 837 | return ret; |
838 | } | 838 | } |
839 | 839 | ||
840 | static struct intel_encoder * | 840 | /* Finds the only possible encoder associated with the given CRTC. */ |
841 | struct intel_encoder * | ||
841 | intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state) | 842 | intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state) |
842 | { | 843 | { |
843 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 844 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
@@ -1127,72 +1128,6 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, | |||
1127 | bxt_ddi_clock_get(encoder, pipe_config); | 1128 | bxt_ddi_clock_get(encoder, pipe_config); |
1128 | } | 1129 | } |
1129 | 1130 | ||
1130 | static bool | ||
1131 | hsw_ddi_pll_select(struct intel_crtc *intel_crtc, | ||
1132 | struct intel_crtc_state *crtc_state, | ||
1133 | struct intel_encoder *encoder) | ||
1134 | { | ||
1135 | struct intel_shared_dpll *pll; | ||
1136 | |||
1137 | pll = intel_get_shared_dpll(intel_crtc, crtc_state, | ||
1138 | encoder); | ||
1139 | if (!pll) | ||
1140 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", | ||
1141 | pipe_name(intel_crtc->pipe)); | ||
1142 | |||
1143 | return pll; | ||
1144 | } | ||
1145 | |||
1146 | static bool | ||
1147 | skl_ddi_pll_select(struct intel_crtc *intel_crtc, | ||
1148 | struct intel_crtc_state *crtc_state, | ||
1149 | struct intel_encoder *encoder) | ||
1150 | { | ||
1151 | struct intel_shared_dpll *pll; | ||
1152 | |||
1153 | pll = intel_get_shared_dpll(intel_crtc, crtc_state, encoder); | ||
1154 | if (pll == NULL) { | ||
1155 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", | ||
1156 | pipe_name(intel_crtc->pipe)); | ||
1157 | return false; | ||
1158 | } | ||
1159 | |||
1160 | return true; | ||
1161 | } | ||
1162 | |||
1163 | static bool | ||
1164 | bxt_ddi_pll_select(struct intel_crtc *intel_crtc, | ||
1165 | struct intel_crtc_state *crtc_state, | ||
1166 | struct intel_encoder *encoder) | ||
1167 | { | ||
1168 | return !!intel_get_shared_dpll(intel_crtc, crtc_state, encoder); | ||
1169 | } | ||
1170 | |||
1171 | /* | ||
1172 | * Tries to find a *shared* PLL for the CRTC and store it in | ||
1173 | * intel_crtc->ddi_pll_sel. | ||
1174 | * | ||
1175 | * For private DPLLs, compute_config() should do the selection for us. This | ||
1176 | * function should be folded into compute_config() eventually. | ||
1177 | */ | ||
1178 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, | ||
1179 | struct intel_crtc_state *crtc_state) | ||
1180 | { | ||
1181 | struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | ||
1182 | struct intel_encoder *encoder = | ||
1183 | intel_ddi_get_crtc_new_encoder(crtc_state); | ||
1184 | |||
1185 | if (IS_GEN9_BC(dev_priv)) | ||
1186 | return skl_ddi_pll_select(intel_crtc, crtc_state, | ||
1187 | encoder); | ||
1188 | else if (IS_GEN9_LP(dev_priv)) | ||
1189 | return bxt_ddi_pll_select(intel_crtc, crtc_state, | ||
1190 | encoder); | ||
1191 | else | ||
1192 | return hsw_ddi_pll_select(intel_crtc, crtc_state, | ||
1193 | encoder); | ||
1194 | } | ||
1195 | |||
1196 | void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state) | 1131 | void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state) |
1197 | { | 1132 | { |
1198 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 1133 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
@@ -1309,6 +1244,11 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) | |||
1309 | temp |= TRANS_DDI_MODE_SELECT_HDMI; | 1244 | temp |= TRANS_DDI_MODE_SELECT_HDMI; |
1310 | else | 1245 | else |
1311 | temp |= TRANS_DDI_MODE_SELECT_DVI; | 1246 | temp |= TRANS_DDI_MODE_SELECT_DVI; |
1247 | |||
1248 | if (crtc_state->hdmi_scrambling) | ||
1249 | temp |= TRANS_DDI_HDMI_SCRAMBLING_MASK; | ||
1250 | if (crtc_state->hdmi_high_tmds_clock_ratio) | ||
1251 | temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE; | ||
1312 | } else if (type == INTEL_OUTPUT_ANALOG) { | 1252 | } else if (type == INTEL_OUTPUT_ANALOG) { |
1313 | temp |= TRANS_DDI_MODE_SELECT_FDI; | 1253 | temp |= TRANS_DDI_MODE_SELECT_FDI; |
1314 | temp |= (crtc_state->fdi_lanes - 1) << 1; | 1254 | temp |= (crtc_state->fdi_lanes - 1) << 1; |
@@ -1676,8 +1616,8 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) | |||
1676 | return DDI_BUF_TRANS_SELECT(level); | 1616 | return DDI_BUF_TRANS_SELECT(level); |
1677 | } | 1617 | } |
1678 | 1618 | ||
1679 | void intel_ddi_clk_select(struct intel_encoder *encoder, | 1619 | static void intel_ddi_clk_select(struct intel_encoder *encoder, |
1680 | struct intel_shared_dpll *pll) | 1620 | struct intel_shared_dpll *pll) |
1681 | { | 1621 | { |
1682 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 1622 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
1683 | enum port port = intel_ddi_get_encoder_port(encoder); | 1623 | enum port port = intel_ddi_get_encoder_port(encoder); |
@@ -1881,6 +1821,12 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder, | |||
1881 | if (type == INTEL_OUTPUT_HDMI) { | 1821 | if (type == INTEL_OUTPUT_HDMI) { |
1882 | struct intel_digital_port *intel_dig_port = | 1822 | struct intel_digital_port *intel_dig_port = |
1883 | enc_to_dig_port(encoder); | 1823 | enc_to_dig_port(encoder); |
1824 | bool clock_ratio = pipe_config->hdmi_high_tmds_clock_ratio; | ||
1825 | bool scrambling = pipe_config->hdmi_scrambling; | ||
1826 | |||
1827 | intel_hdmi_handle_sink_scrambling(intel_encoder, | ||
1828 | conn_state->connector, | ||
1829 | clock_ratio, scrambling); | ||
1884 | 1830 | ||
1885 | /* In HDMI/DVI mode, the port width, and swing/emphasis values | 1831 | /* In HDMI/DVI mode, the port width, and swing/emphasis values |
1886 | * are ignored so nothing special needs to be done besides | 1832 | * are ignored so nothing special needs to be done besides |
@@ -1914,6 +1860,12 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder, | |||
1914 | if (old_crtc_state->has_audio) | 1860 | if (old_crtc_state->has_audio) |
1915 | intel_audio_codec_disable(intel_encoder); | 1861 | intel_audio_codec_disable(intel_encoder); |
1916 | 1862 | ||
1863 | if (type == INTEL_OUTPUT_HDMI) { | ||
1864 | intel_hdmi_handle_sink_scrambling(intel_encoder, | ||
1865 | old_conn_state->connector, | ||
1866 | false, false); | ||
1867 | } | ||
1868 | |||
1917 | if (type == INTEL_OUTPUT_EDP) { | 1869 | if (type == INTEL_OUTPUT_EDP) { |
1918 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1870 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
1919 | 1871 | ||
@@ -2040,6 +1992,12 @@ void intel_ddi_get_config(struct intel_encoder *encoder, | |||
2040 | 1992 | ||
2041 | if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) | 1993 | if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) |
2042 | pipe_config->has_infoframe = true; | 1994 | pipe_config->has_infoframe = true; |
1995 | |||
1996 | if ((temp & TRANS_DDI_HDMI_SCRAMBLING_MASK) == | ||
1997 | TRANS_DDI_HDMI_SCRAMBLING_MASK) | ||
1998 | pipe_config->hdmi_scrambling = true; | ||
1999 | if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE) | ||
2000 | pipe_config->hdmi_high_tmds_clock_ratio = true; | ||
2043 | /* fall through */ | 2001 | /* fall through */ |
2044 | case TRANS_DDI_MODE_SELECT_DVI: | 2002 | case TRANS_DDI_MODE_SELECT_DVI: |
2045 | pipe_config->lane_count = 4; | 2003 | pipe_config->lane_count = 4; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e27ea89efd67..81baa5a9780c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1997,7 +1997,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) | |||
1997 | unsigned int cpp = fb->format->cpp[plane]; | 1997 | unsigned int cpp = fb->format->cpp[plane]; |
1998 | 1998 | ||
1999 | switch (fb->modifier) { | 1999 | switch (fb->modifier) { |
2000 | case DRM_FORMAT_MOD_NONE: | 2000 | case DRM_FORMAT_MOD_LINEAR: |
2001 | return cpp; | 2001 | return cpp; |
2002 | case I915_FORMAT_MOD_X_TILED: | 2002 | case I915_FORMAT_MOD_X_TILED: |
2003 | if (IS_GEN2(dev_priv)) | 2003 | if (IS_GEN2(dev_priv)) |
@@ -2033,7 +2033,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) | |||
2033 | static unsigned int | 2033 | static unsigned int |
2034 | intel_tile_height(const struct drm_framebuffer *fb, int plane) | 2034 | intel_tile_height(const struct drm_framebuffer *fb, int plane) |
2035 | { | 2035 | { |
2036 | if (fb->modifier == DRM_FORMAT_MOD_NONE) | 2036 | if (fb->modifier == DRM_FORMAT_MOD_LINEAR) |
2037 | return 1; | 2037 | return 1; |
2038 | else | 2038 | else |
2039 | return intel_tile_size(to_i915(fb->dev)) / | 2039 | return intel_tile_size(to_i915(fb->dev)) / |
@@ -2107,7 +2107,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, | |||
2107 | return 4096; | 2107 | return 4096; |
2108 | 2108 | ||
2109 | switch (fb->modifier) { | 2109 | switch (fb->modifier) { |
2110 | case DRM_FORMAT_MOD_NONE: | 2110 | case DRM_FORMAT_MOD_LINEAR: |
2111 | return intel_linear_alignment(dev_priv); | 2111 | return intel_linear_alignment(dev_priv); |
2112 | case I915_FORMAT_MOD_X_TILED: | 2112 | case I915_FORMAT_MOD_X_TILED: |
2113 | if (INTEL_GEN(dev_priv) >= 9) | 2113 | if (INTEL_GEN(dev_priv) >= 9) |
@@ -2290,7 +2290,7 @@ static u32 intel_adjust_tile_offset(int *x, int *y, | |||
2290 | 2290 | ||
2291 | WARN_ON(new_offset > old_offset); | 2291 | WARN_ON(new_offset > old_offset); |
2292 | 2292 | ||
2293 | if (fb->modifier != DRM_FORMAT_MOD_NONE) { | 2293 | if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { |
2294 | unsigned int tile_size, tile_width, tile_height; | 2294 | unsigned int tile_size, tile_width, tile_height; |
2295 | unsigned int pitch_tiles; | 2295 | unsigned int pitch_tiles; |
2296 | 2296 | ||
@@ -2345,7 +2345,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, | |||
2345 | if (alignment) | 2345 | if (alignment) |
2346 | alignment--; | 2346 | alignment--; |
2347 | 2347 | ||
2348 | if (fb_modifier != DRM_FORMAT_MOD_NONE) { | 2348 | if (fb_modifier != DRM_FORMAT_MOD_LINEAR) { |
2349 | unsigned int tile_size, tile_width, tile_height; | 2349 | unsigned int tile_size, tile_width, tile_height; |
2350 | unsigned int tile_rows, tiles, pitch_tiles; | 2350 | unsigned int tile_rows, tiles, pitch_tiles; |
2351 | 2351 | ||
@@ -2471,7 +2471,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, | |||
2471 | DRM_ROTATE_0, tile_size); | 2471 | DRM_ROTATE_0, tile_size); |
2472 | offset /= tile_size; | 2472 | offset /= tile_size; |
2473 | 2473 | ||
2474 | if (fb->modifier != DRM_FORMAT_MOD_NONE) { | 2474 | if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { |
2475 | unsigned int tile_width, tile_height; | 2475 | unsigned int tile_width, tile_height; |
2476 | unsigned int pitch_tiles; | 2476 | unsigned int pitch_tiles; |
2477 | struct drm_rect r; | 2477 | struct drm_rect r; |
@@ -2803,7 +2803,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane, | |||
2803 | int cpp = fb->format->cpp[plane]; | 2803 | int cpp = fb->format->cpp[plane]; |
2804 | 2804 | ||
2805 | switch (fb->modifier) { | 2805 | switch (fb->modifier) { |
2806 | case DRM_FORMAT_MOD_NONE: | 2806 | case DRM_FORMAT_MOD_LINEAR: |
2807 | case I915_FORMAT_MOD_X_TILED: | 2807 | case I915_FORMAT_MOD_X_TILED: |
2808 | switch (cpp) { | 2808 | switch (cpp) { |
2809 | case 8: | 2809 | case 8: |
@@ -2962,28 +2962,27 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) | |||
2962 | return 0; | 2962 | return 0; |
2963 | } | 2963 | } |
2964 | 2964 | ||
2965 | static void i9xx_update_primary_plane(struct drm_plane *primary, | 2965 | static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, |
2966 | const struct intel_crtc_state *crtc_state, | 2966 | const struct intel_plane_state *plane_state) |
2967 | const struct intel_plane_state *plane_state) | ||
2968 | { | 2967 | { |
2969 | struct drm_i915_private *dev_priv = to_i915(primary->dev); | 2968 | struct drm_i915_private *dev_priv = |
2970 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | 2969 | to_i915(plane_state->base.plane->dev); |
2971 | struct drm_framebuffer *fb = plane_state->base.fb; | 2970 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
2972 | int plane = intel_crtc->plane; | 2971 | const struct drm_framebuffer *fb = plane_state->base.fb; |
2973 | u32 linear_offset; | ||
2974 | u32 dspcntr; | ||
2975 | i915_reg_t reg = DSPCNTR(plane); | ||
2976 | unsigned int rotation = plane_state->base.rotation; | 2972 | unsigned int rotation = plane_state->base.rotation; |
2977 | int x = plane_state->base.src.x1 >> 16; | 2973 | u32 dspcntr; |
2978 | int y = plane_state->base.src.y1 >> 16; | ||
2979 | unsigned long irqflags; | ||
2980 | 2974 | ||
2981 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 2975 | dspcntr = DISPLAY_PLANE_ENABLE | DISPPLANE_GAMMA_ENABLE; |
2976 | |||
2977 | if (IS_G4X(dev_priv) || IS_GEN5(dev_priv) || | ||
2978 | IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) | ||
2979 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | ||
2982 | 2980 | ||
2983 | dspcntr |= DISPLAY_PLANE_ENABLE; | 2981 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
2982 | dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; | ||
2984 | 2983 | ||
2985 | if (INTEL_GEN(dev_priv) < 4) { | 2984 | if (INTEL_GEN(dev_priv) < 4) { |
2986 | if (intel_crtc->pipe == PIPE_B) | 2985 | if (crtc->pipe == PIPE_B) |
2987 | dspcntr |= DISPPLANE_SEL_PIPE_B; | 2986 | dspcntr |= DISPPLANE_SEL_PIPE_B; |
2988 | } | 2987 | } |
2989 | 2988 | ||
@@ -3010,7 +3009,8 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, | |||
3010 | dspcntr |= DISPPLANE_RGBX101010; | 3009 | dspcntr |= DISPPLANE_RGBX101010; |
3011 | break; | 3010 | break; |
3012 | default: | 3011 | default: |
3013 | BUG(); | 3012 | MISSING_CASE(fb->format->format); |
3013 | return 0; | ||
3014 | } | 3014 | } |
3015 | 3015 | ||
3016 | if (INTEL_GEN(dev_priv) >= 4 && | 3016 | if (INTEL_GEN(dev_priv) >= 4 && |
@@ -3023,25 +3023,66 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, | |||
3023 | if (rotation & DRM_REFLECT_X) | 3023 | if (rotation & DRM_REFLECT_X) |
3024 | dspcntr |= DISPPLANE_MIRROR; | 3024 | dspcntr |= DISPPLANE_MIRROR; |
3025 | 3025 | ||
3026 | if (IS_G4X(dev_priv)) | 3026 | return dspcntr; |
3027 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | 3027 | } |
3028 | 3028 | ||
3029 | intel_add_fb_offsets(&x, &y, plane_state, 0); | 3029 | int i9xx_check_plane_surface(struct intel_plane_state *plane_state) |
3030 | { | ||
3031 | struct drm_i915_private *dev_priv = | ||
3032 | to_i915(plane_state->base.plane->dev); | ||
3033 | int src_x = plane_state->base.src.x1 >> 16; | ||
3034 | int src_y = plane_state->base.src.y1 >> 16; | ||
3035 | u32 offset; | ||
3036 | |||
3037 | intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); | ||
3030 | 3038 | ||
3031 | if (INTEL_GEN(dev_priv) >= 4) | 3039 | if (INTEL_GEN(dev_priv) >= 4) |
3032 | intel_crtc->dspaddr_offset = | 3040 | offset = intel_compute_tile_offset(&src_x, &src_y, |
3033 | intel_compute_tile_offset(&x, &y, plane_state, 0); | 3041 | plane_state, 0); |
3042 | else | ||
3043 | offset = 0; | ||
3044 | |||
3045 | /* HSW/BDW do this automagically in hardware */ | ||
3046 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { | ||
3047 | unsigned int rotation = plane_state->base.rotation; | ||
3048 | int src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
3049 | int src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
3034 | 3050 | ||
3035 | if (rotation & DRM_ROTATE_180) { | 3051 | if (rotation & DRM_ROTATE_180) { |
3036 | x += crtc_state->pipe_src_w - 1; | 3052 | src_x += src_w - 1; |
3037 | y += crtc_state->pipe_src_h - 1; | 3053 | src_y += src_h - 1; |
3038 | } else if (rotation & DRM_REFLECT_X) { | 3054 | } else if (rotation & DRM_REFLECT_X) { |
3039 | x += crtc_state->pipe_src_w - 1; | 3055 | src_x += src_w - 1; |
3056 | } | ||
3040 | } | 3057 | } |
3041 | 3058 | ||
3059 | plane_state->main.offset = offset; | ||
3060 | plane_state->main.x = src_x; | ||
3061 | plane_state->main.y = src_y; | ||
3062 | |||
3063 | return 0; | ||
3064 | } | ||
3065 | |||
3066 | static void i9xx_update_primary_plane(struct drm_plane *primary, | ||
3067 | const struct intel_crtc_state *crtc_state, | ||
3068 | const struct intel_plane_state *plane_state) | ||
3069 | { | ||
3070 | struct drm_i915_private *dev_priv = to_i915(primary->dev); | ||
3071 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | ||
3072 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
3073 | int plane = intel_crtc->plane; | ||
3074 | u32 linear_offset; | ||
3075 | u32 dspcntr = plane_state->ctl; | ||
3076 | i915_reg_t reg = DSPCNTR(plane); | ||
3077 | int x = plane_state->main.x; | ||
3078 | int y = plane_state->main.y; | ||
3079 | unsigned long irqflags; | ||
3080 | |||
3042 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); | 3081 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); |
3043 | 3082 | ||
3044 | if (INTEL_GEN(dev_priv) < 4) | 3083 | if (INTEL_GEN(dev_priv) >= 4) |
3084 | intel_crtc->dspaddr_offset = plane_state->main.offset; | ||
3085 | else | ||
3045 | intel_crtc->dspaddr_offset = linear_offset; | 3086 | intel_crtc->dspaddr_offset = linear_offset; |
3046 | 3087 | ||
3047 | intel_crtc->adjusted_x = x; | 3088 | intel_crtc->adjusted_x = x; |
@@ -3068,7 +3109,12 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, | |||
3068 | I915_WRITE_FW(reg, dspcntr); | 3109 | I915_WRITE_FW(reg, dspcntr); |
3069 | 3110 | ||
3070 | I915_WRITE_FW(DSPSTRIDE(plane), fb->pitches[0]); | 3111 | I915_WRITE_FW(DSPSTRIDE(plane), fb->pitches[0]); |
3071 | if (INTEL_GEN(dev_priv) >= 4) { | 3112 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
3113 | I915_WRITE_FW(DSPSURF(plane), | ||
3114 | intel_plane_ggtt_offset(plane_state) + | ||
3115 | intel_crtc->dspaddr_offset); | ||
3116 | I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x); | ||
3117 | } else if (INTEL_GEN(dev_priv) >= 4) { | ||
3072 | I915_WRITE_FW(DSPSURF(plane), | 3118 | I915_WRITE_FW(DSPSURF(plane), |
3073 | intel_plane_ggtt_offset(plane_state) + | 3119 | intel_plane_ggtt_offset(plane_state) + |
3074 | intel_crtc->dspaddr_offset); | 3120 | intel_crtc->dspaddr_offset); |
@@ -3105,101 +3151,10 @@ static void i9xx_disable_primary_plane(struct drm_plane *primary, | |||
3105 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 3151 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
3106 | } | 3152 | } |
3107 | 3153 | ||
3108 | static void ironlake_update_primary_plane(struct drm_plane *primary, | ||
3109 | const struct intel_crtc_state *crtc_state, | ||
3110 | const struct intel_plane_state *plane_state) | ||
3111 | { | ||
3112 | struct drm_device *dev = primary->dev; | ||
3113 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
3114 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | ||
3115 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
3116 | int plane = intel_crtc->plane; | ||
3117 | u32 linear_offset; | ||
3118 | u32 dspcntr; | ||
3119 | i915_reg_t reg = DSPCNTR(plane); | ||
3120 | unsigned int rotation = plane_state->base.rotation; | ||
3121 | int x = plane_state->base.src.x1 >> 16; | ||
3122 | int y = plane_state->base.src.y1 >> 16; | ||
3123 | unsigned long irqflags; | ||
3124 | |||
3125 | dspcntr = DISPPLANE_GAMMA_ENABLE; | ||
3126 | dspcntr |= DISPLAY_PLANE_ENABLE; | ||
3127 | |||
3128 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||
3129 | dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; | ||
3130 | |||
3131 | switch (fb->format->format) { | ||
3132 | case DRM_FORMAT_C8: | ||
3133 | dspcntr |= DISPPLANE_8BPP; | ||
3134 | break; | ||
3135 | case DRM_FORMAT_RGB565: | ||
3136 | dspcntr |= DISPPLANE_BGRX565; | ||
3137 | break; | ||
3138 | case DRM_FORMAT_XRGB8888: | ||
3139 | dspcntr |= DISPPLANE_BGRX888; | ||
3140 | break; | ||
3141 | case DRM_FORMAT_XBGR8888: | ||
3142 | dspcntr |= DISPPLANE_RGBX888; | ||
3143 | break; | ||
3144 | case DRM_FORMAT_XRGB2101010: | ||
3145 | dspcntr |= DISPPLANE_BGRX101010; | ||
3146 | break; | ||
3147 | case DRM_FORMAT_XBGR2101010: | ||
3148 | dspcntr |= DISPPLANE_RGBX101010; | ||
3149 | break; | ||
3150 | default: | ||
3151 | BUG(); | ||
3152 | } | ||
3153 | |||
3154 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | ||
3155 | dspcntr |= DISPPLANE_TILED; | ||
3156 | |||
3157 | if (rotation & DRM_ROTATE_180) | ||
3158 | dspcntr |= DISPPLANE_ROTATE_180; | ||
3159 | |||
3160 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) | ||
3161 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | ||
3162 | |||
3163 | intel_add_fb_offsets(&x, &y, plane_state, 0); | ||
3164 | |||
3165 | intel_crtc->dspaddr_offset = | ||
3166 | intel_compute_tile_offset(&x, &y, plane_state, 0); | ||
3167 | |||
3168 | /* HSW+ does this automagically in hardware */ | ||
3169 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) && | ||
3170 | rotation & DRM_ROTATE_180) { | ||
3171 | x += crtc_state->pipe_src_w - 1; | ||
3172 | y += crtc_state->pipe_src_h - 1; | ||
3173 | } | ||
3174 | |||
3175 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); | ||
3176 | |||
3177 | intel_crtc->adjusted_x = x; | ||
3178 | intel_crtc->adjusted_y = y; | ||
3179 | |||
3180 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | ||
3181 | |||
3182 | I915_WRITE_FW(reg, dspcntr); | ||
3183 | |||
3184 | I915_WRITE_FW(DSPSTRIDE(plane), fb->pitches[0]); | ||
3185 | I915_WRITE_FW(DSPSURF(plane), | ||
3186 | intel_plane_ggtt_offset(plane_state) + | ||
3187 | intel_crtc->dspaddr_offset); | ||
3188 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { | ||
3189 | I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x); | ||
3190 | } else { | ||
3191 | I915_WRITE_FW(DSPTILEOFF(plane), (y << 16) | x); | ||
3192 | I915_WRITE_FW(DSPLINOFF(plane), linear_offset); | ||
3193 | } | ||
3194 | POSTING_READ_FW(reg); | ||
3195 | |||
3196 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | ||
3197 | } | ||
3198 | |||
3199 | static u32 | 3154 | static u32 |
3200 | intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane) | 3155 | intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane) |
3201 | { | 3156 | { |
3202 | if (fb->modifier == DRM_FORMAT_MOD_NONE) | 3157 | if (fb->modifier == DRM_FORMAT_MOD_LINEAR) |
3203 | return 64; | 3158 | return 64; |
3204 | else | 3159 | else |
3205 | return intel_tile_width_bytes(fb, plane); | 3160 | return intel_tile_width_bytes(fb, plane); |
@@ -3254,7 +3209,7 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, | |||
3254 | return stride; | 3209 | return stride; |
3255 | } | 3210 | } |
3256 | 3211 | ||
3257 | u32 skl_plane_ctl_format(uint32_t pixel_format) | 3212 | static u32 skl_plane_ctl_format(uint32_t pixel_format) |
3258 | { | 3213 | { |
3259 | switch (pixel_format) { | 3214 | switch (pixel_format) { |
3260 | case DRM_FORMAT_C8: | 3215 | case DRM_FORMAT_C8: |
@@ -3295,10 +3250,10 @@ u32 skl_plane_ctl_format(uint32_t pixel_format) | |||
3295 | return 0; | 3250 | return 0; |
3296 | } | 3251 | } |
3297 | 3252 | ||
3298 | u32 skl_plane_ctl_tiling(uint64_t fb_modifier) | 3253 | static u32 skl_plane_ctl_tiling(uint64_t fb_modifier) |
3299 | { | 3254 | { |
3300 | switch (fb_modifier) { | 3255 | switch (fb_modifier) { |
3301 | case DRM_FORMAT_MOD_NONE: | 3256 | case DRM_FORMAT_MOD_LINEAR: |
3302 | break; | 3257 | break; |
3303 | case I915_FORMAT_MOD_X_TILED: | 3258 | case I915_FORMAT_MOD_X_TILED: |
3304 | return PLANE_CTL_TILED_X; | 3259 | return PLANE_CTL_TILED_X; |
@@ -3313,7 +3268,7 @@ u32 skl_plane_ctl_tiling(uint64_t fb_modifier) | |||
3313 | return 0; | 3268 | return 0; |
3314 | } | 3269 | } |
3315 | 3270 | ||
3316 | u32 skl_plane_ctl_rotation(unsigned int rotation) | 3271 | static u32 skl_plane_ctl_rotation(unsigned int rotation) |
3317 | { | 3272 | { |
3318 | switch (rotation) { | 3273 | switch (rotation) { |
3319 | case DRM_ROTATE_0: | 3274 | case DRM_ROTATE_0: |
@@ -3335,6 +3290,37 @@ u32 skl_plane_ctl_rotation(unsigned int rotation) | |||
3335 | return 0; | 3290 | return 0; |
3336 | } | 3291 | } |
3337 | 3292 | ||
3293 | u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, | ||
3294 | const struct intel_plane_state *plane_state) | ||
3295 | { | ||
3296 | struct drm_i915_private *dev_priv = | ||
3297 | to_i915(plane_state->base.plane->dev); | ||
3298 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
3299 | unsigned int rotation = plane_state->base.rotation; | ||
3300 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | ||
3301 | u32 plane_ctl; | ||
3302 | |||
3303 | plane_ctl = PLANE_CTL_ENABLE; | ||
3304 | |||
3305 | if (!IS_GEMINILAKE(dev_priv)) { | ||
3306 | plane_ctl |= | ||
3307 | PLANE_CTL_PIPE_GAMMA_ENABLE | | ||
3308 | PLANE_CTL_PIPE_CSC_ENABLE | | ||
3309 | PLANE_CTL_PLANE_GAMMA_DISABLE; | ||
3310 | } | ||
3311 | |||
3312 | plane_ctl |= skl_plane_ctl_format(fb->format->format); | ||
3313 | plane_ctl |= skl_plane_ctl_tiling(fb->modifier); | ||
3314 | plane_ctl |= skl_plane_ctl_rotation(rotation); | ||
3315 | |||
3316 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | ||
3317 | plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; | ||
3318 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | ||
3319 | plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; | ||
3320 | |||
3321 | return plane_ctl; | ||
3322 | } | ||
3323 | |||
3338 | static void skylake_update_primary_plane(struct drm_plane *plane, | 3324 | static void skylake_update_primary_plane(struct drm_plane *plane, |
3339 | const struct intel_crtc_state *crtc_state, | 3325 | const struct intel_crtc_state *crtc_state, |
3340 | const struct intel_plane_state *plane_state) | 3326 | const struct intel_plane_state *plane_state) |
@@ -3345,7 +3331,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, | |||
3345 | struct drm_framebuffer *fb = plane_state->base.fb; | 3331 | struct drm_framebuffer *fb = plane_state->base.fb; |
3346 | enum plane_id plane_id = to_intel_plane(plane)->id; | 3332 | enum plane_id plane_id = to_intel_plane(plane)->id; |
3347 | enum pipe pipe = to_intel_plane(plane)->pipe; | 3333 | enum pipe pipe = to_intel_plane(plane)->pipe; |
3348 | u32 plane_ctl; | 3334 | u32 plane_ctl = plane_state->ctl; |
3349 | unsigned int rotation = plane_state->base.rotation; | 3335 | unsigned int rotation = plane_state->base.rotation; |
3350 | u32 stride = skl_plane_stride(fb, 0, rotation); | 3336 | u32 stride = skl_plane_stride(fb, 0, rotation); |
3351 | u32 surf_addr = plane_state->main.offset; | 3337 | u32 surf_addr = plane_state->main.offset; |
@@ -3360,19 +3346,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane, | |||
3360 | int dst_h = drm_rect_height(&plane_state->base.dst); | 3346 | int dst_h = drm_rect_height(&plane_state->base.dst); |
3361 | unsigned long irqflags; | 3347 | unsigned long irqflags; |
3362 | 3348 | ||
3363 | plane_ctl = PLANE_CTL_ENABLE; | ||
3364 | |||
3365 | if (!IS_GEMINILAKE(dev_priv)) { | ||
3366 | plane_ctl |= | ||
3367 | PLANE_CTL_PIPE_GAMMA_ENABLE | | ||
3368 | PLANE_CTL_PIPE_CSC_ENABLE | | ||
3369 | PLANE_CTL_PLANE_GAMMA_DISABLE; | ||
3370 | } | ||
3371 | |||
3372 | plane_ctl |= skl_plane_ctl_format(fb->format->format); | ||
3373 | plane_ctl |= skl_plane_ctl_tiling(fb->modifier); | ||
3374 | plane_ctl |= skl_plane_ctl_rotation(rotation); | ||
3375 | |||
3376 | /* Sizes are 0 based */ | 3349 | /* Sizes are 0 based */ |
3377 | src_w--; | 3350 | src_w--; |
3378 | src_h--; | 3351 | src_h--; |
@@ -6317,6 +6290,17 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) | |||
6317 | static void compute_m_n(unsigned int m, unsigned int n, | 6290 | static void compute_m_n(unsigned int m, unsigned int n, |
6318 | uint32_t *ret_m, uint32_t *ret_n) | 6291 | uint32_t *ret_m, uint32_t *ret_n) |
6319 | { | 6292 | { |
6293 | /* | ||
6294 | * Reduce M/N as much as possible without loss in precision. Several DP | ||
6295 | * dongles in particular seem to be fussy about too large *link* M/N | ||
6296 | * values. The passed in values are more likely to have the least | ||
6297 | * significant bits zero than M after rounding below, so do this first. | ||
6298 | */ | ||
6299 | while ((m & 1) == 0 && (n & 1) == 0) { | ||
6300 | m >>= 1; | ||
6301 | n >>= 1; | ||
6302 | } | ||
6303 | |||
6320 | *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); | 6304 | *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); |
6321 | *ret_m = div_u64((uint64_t) m * *ret_n, n); | 6305 | *ret_m = div_u64((uint64_t) m * *ret_n, n); |
6322 | intel_reduce_m_n_ratio(ret_m, ret_n); | 6306 | intel_reduce_m_n_ratio(ret_m, ret_n); |
@@ -8406,7 +8390,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, | |||
8406 | tiling = val & PLANE_CTL_TILED_MASK; | 8390 | tiling = val & PLANE_CTL_TILED_MASK; |
8407 | switch (tiling) { | 8391 | switch (tiling) { |
8408 | case PLANE_CTL_TILED_LINEAR: | 8392 | case PLANE_CTL_TILED_LINEAR: |
8409 | fb->modifier = DRM_FORMAT_MOD_NONE; | 8393 | fb->modifier = DRM_FORMAT_MOD_LINEAR; |
8410 | break; | 8394 | break; |
8411 | case PLANE_CTL_TILED_X: | 8395 | case PLANE_CTL_TILED_X: |
8412 | plane_config->tiling = I915_TILING_X; | 8396 | plane_config->tiling = I915_TILING_X; |
@@ -8862,8 +8846,14 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, | |||
8862 | struct intel_crtc_state *crtc_state) | 8846 | struct intel_crtc_state *crtc_state) |
8863 | { | 8847 | { |
8864 | if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) { | 8848 | if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) { |
8865 | if (!intel_ddi_pll_select(crtc, crtc_state)) | 8849 | struct intel_encoder *encoder = |
8850 | intel_ddi_get_crtc_new_encoder(crtc_state); | ||
8851 | |||
8852 | if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) { | ||
8853 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", | ||
8854 | pipe_name(crtc->pipe)); | ||
8866 | return -EINVAL; | 8855 | return -EINVAL; |
8856 | } | ||
8867 | } | 8857 | } |
8868 | 8858 | ||
8869 | crtc->lowfreq_avail = false; | 8859 | crtc->lowfreq_avail = false; |
@@ -9159,6 +9149,31 @@ out: | |||
9159 | return active; | 9149 | return active; |
9160 | } | 9150 | } |
9161 | 9151 | ||
9152 | static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, | ||
9153 | const struct intel_plane_state *plane_state) | ||
9154 | { | ||
9155 | unsigned int width = plane_state->base.crtc_w; | ||
9156 | unsigned int stride = roundup_pow_of_two(width) * 4; | ||
9157 | |||
9158 | switch (stride) { | ||
9159 | default: | ||
9160 | WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n", | ||
9161 | width, stride); | ||
9162 | stride = 256; | ||
9163 | /* fallthrough */ | ||
9164 | case 256: | ||
9165 | case 512: | ||
9166 | case 1024: | ||
9167 | case 2048: | ||
9168 | break; | ||
9169 | } | ||
9170 | |||
9171 | return CURSOR_ENABLE | | ||
9172 | CURSOR_GAMMA_ENABLE | | ||
9173 | CURSOR_FORMAT_ARGB | | ||
9174 | CURSOR_STRIDE(stride); | ||
9175 | } | ||
9176 | |||
9162 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base, | 9177 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base, |
9163 | const struct intel_plane_state *plane_state) | 9178 | const struct intel_plane_state *plane_state) |
9164 | { | 9179 | { |
@@ -9170,26 +9185,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base, | |||
9170 | if (plane_state && plane_state->base.visible) { | 9185 | if (plane_state && plane_state->base.visible) { |
9171 | unsigned int width = plane_state->base.crtc_w; | 9186 | unsigned int width = plane_state->base.crtc_w; |
9172 | unsigned int height = plane_state->base.crtc_h; | 9187 | unsigned int height = plane_state->base.crtc_h; |
9173 | unsigned int stride = roundup_pow_of_two(width) * 4; | ||
9174 | |||
9175 | switch (stride) { | ||
9176 | default: | ||
9177 | WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n", | ||
9178 | width, stride); | ||
9179 | stride = 256; | ||
9180 | /* fallthrough */ | ||
9181 | case 256: | ||
9182 | case 512: | ||
9183 | case 1024: | ||
9184 | case 2048: | ||
9185 | break; | ||
9186 | } | ||
9187 | |||
9188 | cntl |= CURSOR_ENABLE | | ||
9189 | CURSOR_GAMMA_ENABLE | | ||
9190 | CURSOR_FORMAT_ARGB | | ||
9191 | CURSOR_STRIDE(stride); | ||
9192 | 9188 | ||
9189 | cntl = plane_state->ctl; | ||
9193 | size = (height << 12) | width; | 9190 | size = (height << 12) | width; |
9194 | } | 9191 | } |
9195 | 9192 | ||
@@ -9222,6 +9219,43 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base, | |||
9222 | } | 9219 | } |
9223 | } | 9220 | } |
9224 | 9221 | ||
9222 | static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, | ||
9223 | const struct intel_plane_state *plane_state) | ||
9224 | { | ||
9225 | struct drm_i915_private *dev_priv = | ||
9226 | to_i915(plane_state->base.plane->dev); | ||
9227 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | ||
9228 | enum pipe pipe = crtc->pipe; | ||
9229 | u32 cntl; | ||
9230 | |||
9231 | cntl = MCURSOR_GAMMA_ENABLE; | ||
9232 | |||
9233 | if (HAS_DDI(dev_priv)) | ||
9234 | cntl |= CURSOR_PIPE_CSC_ENABLE; | ||
9235 | |||
9236 | cntl |= pipe << 28; /* Connect to correct pipe */ | ||
9237 | |||
9238 | switch (plane_state->base.crtc_w) { | ||
9239 | case 64: | ||
9240 | cntl |= CURSOR_MODE_64_ARGB_AX; | ||
9241 | break; | ||
9242 | case 128: | ||
9243 | cntl |= CURSOR_MODE_128_ARGB_AX; | ||
9244 | break; | ||
9245 | case 256: | ||
9246 | cntl |= CURSOR_MODE_256_ARGB_AX; | ||
9247 | break; | ||
9248 | default: | ||
9249 | MISSING_CASE(plane_state->base.crtc_w); | ||
9250 | return 0; | ||
9251 | } | ||
9252 | |||
9253 | if (plane_state->base.rotation & DRM_ROTATE_180) | ||
9254 | cntl |= CURSOR_ROTATE_180; | ||
9255 | |||
9256 | return cntl; | ||
9257 | } | ||
9258 | |||
9225 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, | 9259 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, |
9226 | const struct intel_plane_state *plane_state) | 9260 | const struct intel_plane_state *plane_state) |
9227 | { | 9261 | { |
@@ -9231,30 +9265,8 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, | |||
9231 | int pipe = intel_crtc->pipe; | 9265 | int pipe = intel_crtc->pipe; |
9232 | uint32_t cntl = 0; | 9266 | uint32_t cntl = 0; |
9233 | 9267 | ||
9234 | if (plane_state && plane_state->base.visible) { | 9268 | if (plane_state && plane_state->base.visible) |
9235 | cntl = MCURSOR_GAMMA_ENABLE; | 9269 | cntl = plane_state->ctl; |
9236 | switch (plane_state->base.crtc_w) { | ||
9237 | case 64: | ||
9238 | cntl |= CURSOR_MODE_64_ARGB_AX; | ||
9239 | break; | ||
9240 | case 128: | ||
9241 | cntl |= CURSOR_MODE_128_ARGB_AX; | ||
9242 | break; | ||
9243 | case 256: | ||
9244 | cntl |= CURSOR_MODE_256_ARGB_AX; | ||
9245 | break; | ||
9246 | default: | ||
9247 | MISSING_CASE(plane_state->base.crtc_w); | ||
9248 | return; | ||
9249 | } | ||
9250 | cntl |= pipe << 28; /* Connect to correct pipe */ | ||
9251 | |||
9252 | if (HAS_DDI(dev_priv)) | ||
9253 | cntl |= CURSOR_PIPE_CSC_ENABLE; | ||
9254 | |||
9255 | if (plane_state->base.rotation & DRM_ROTATE_180) | ||
9256 | cntl |= CURSOR_ROTATE_180; | ||
9257 | } | ||
9258 | 9270 | ||
9259 | if (intel_crtc->cursor_cntl != cntl) { | 9271 | if (intel_crtc->cursor_cntl != cntl) { |
9260 | I915_WRITE_FW(CURCNTR(pipe), cntl); | 9272 | I915_WRITE_FW(CURCNTR(pipe), cntl); |
@@ -10354,7 +10366,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, | |||
10354 | ctl = I915_READ(PLANE_CTL(pipe, 0)); | 10366 | ctl = I915_READ(PLANE_CTL(pipe, 0)); |
10355 | ctl &= ~PLANE_CTL_TILED_MASK; | 10367 | ctl &= ~PLANE_CTL_TILED_MASK; |
10356 | switch (fb->modifier) { | 10368 | switch (fb->modifier) { |
10357 | case DRM_FORMAT_MOD_NONE: | 10369 | case DRM_FORMAT_MOD_LINEAR: |
10358 | break; | 10370 | break; |
10359 | case I915_FORMAT_MOD_X_TILED: | 10371 | case I915_FORMAT_MOD_X_TILED: |
10360 | ctl |= PLANE_CTL_TILED_X; | 10372 | ctl |= PLANE_CTL_TILED_X; |
@@ -11709,6 +11721,9 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11709 | if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || | 11721 | if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || |
11710 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) | 11722 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
11711 | PIPE_CONF_CHECK_I(limited_color_range); | 11723 | PIPE_CONF_CHECK_I(limited_color_range); |
11724 | |||
11725 | PIPE_CONF_CHECK_I(hdmi_scrambling); | ||
11726 | PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio); | ||
11712 | PIPE_CONF_CHECK_I(has_infoframe); | 11727 | PIPE_CONF_CHECK_I(has_infoframe); |
11713 | 11728 | ||
11714 | PIPE_CONF_CHECK_I(has_audio); | 11729 | PIPE_CONF_CHECK_I(has_audio); |
@@ -13344,6 +13359,14 @@ intel_check_primary_plane(struct drm_plane *plane, | |||
13344 | ret = skl_check_plane_surface(state); | 13359 | ret = skl_check_plane_surface(state); |
13345 | if (ret) | 13360 | if (ret) |
13346 | return ret; | 13361 | return ret; |
13362 | |||
13363 | state->ctl = skl_plane_ctl(crtc_state, state); | ||
13364 | } else { | ||
13365 | ret = i9xx_check_plane_surface(state); | ||
13366 | if (ret) | ||
13367 | return ret; | ||
13368 | |||
13369 | state->ctl = i9xx_plane_ctl(crtc_state, state); | ||
13347 | } | 13370 | } |
13348 | 13371 | ||
13349 | return 0; | 13372 | return 0; |
@@ -13603,12 +13626,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
13603 | 13626 | ||
13604 | primary->update_plane = skylake_update_primary_plane; | 13627 | primary->update_plane = skylake_update_primary_plane; |
13605 | primary->disable_plane = skylake_disable_primary_plane; | 13628 | primary->disable_plane = skylake_disable_primary_plane; |
13606 | } else if (HAS_PCH_SPLIT(dev_priv)) { | ||
13607 | intel_primary_formats = i965_primary_formats; | ||
13608 | num_formats = ARRAY_SIZE(i965_primary_formats); | ||
13609 | |||
13610 | primary->update_plane = ironlake_update_primary_plane; | ||
13611 | primary->disable_plane = i9xx_disable_primary_plane; | ||
13612 | } else if (INTEL_GEN(dev_priv) >= 4) { | 13629 | } else if (INTEL_GEN(dev_priv) >= 4) { |
13613 | intel_primary_formats = i965_primary_formats; | 13630 | intel_primary_formats = i965_primary_formats; |
13614 | num_formats = ARRAY_SIZE(i965_primary_formats); | 13631 | num_formats = ARRAY_SIZE(i965_primary_formats); |
@@ -13680,6 +13697,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13680 | struct intel_crtc_state *crtc_state, | 13697 | struct intel_crtc_state *crtc_state, |
13681 | struct intel_plane_state *state) | 13698 | struct intel_plane_state *state) |
13682 | { | 13699 | { |
13700 | struct drm_i915_private *dev_priv = to_i915(plane->dev); | ||
13683 | struct drm_framebuffer *fb = state->base.fb; | 13701 | struct drm_framebuffer *fb = state->base.fb; |
13684 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 13702 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
13685 | enum pipe pipe = to_intel_plane(plane)->pipe; | 13703 | enum pipe pipe = to_intel_plane(plane)->pipe; |
@@ -13699,7 +13717,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13699 | return 0; | 13717 | return 0; |
13700 | 13718 | ||
13701 | /* Check for which cursor types we support */ | 13719 | /* Check for which cursor types we support */ |
13702 | if (!cursor_size_ok(to_i915(plane->dev), state->base.crtc_w, | 13720 | if (!cursor_size_ok(dev_priv, state->base.crtc_w, |
13703 | state->base.crtc_h)) { | 13721 | state->base.crtc_h)) { |
13704 | DRM_DEBUG("Cursor dimension %dx%d not supported\n", | 13722 | DRM_DEBUG("Cursor dimension %dx%d not supported\n", |
13705 | state->base.crtc_w, state->base.crtc_h); | 13723 | state->base.crtc_w, state->base.crtc_h); |
@@ -13712,7 +13730,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13712 | return -ENOMEM; | 13730 | return -ENOMEM; |
13713 | } | 13731 | } |
13714 | 13732 | ||
13715 | if (fb->modifier != DRM_FORMAT_MOD_NONE) { | 13733 | if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { |
13716 | DRM_DEBUG_KMS("cursor cannot be tiled\n"); | 13734 | DRM_DEBUG_KMS("cursor cannot be tiled\n"); |
13717 | return -EINVAL; | 13735 | return -EINVAL; |
13718 | } | 13736 | } |
@@ -13727,12 +13745,17 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13727 | * display power well must be turned off and on again. | 13745 | * display power well must be turned off and on again. |
13728 | * Refuse the put the cursor into that compromised position. | 13746 | * Refuse the put the cursor into that compromised position. |
13729 | */ | 13747 | */ |
13730 | if (IS_CHERRYVIEW(to_i915(plane->dev)) && pipe == PIPE_C && | 13748 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C && |
13731 | state->base.visible && state->base.crtc_x < 0) { | 13749 | state->base.visible && state->base.crtc_x < 0) { |
13732 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); | 13750 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); |
13733 | return -EINVAL; | 13751 | return -EINVAL; |
13734 | } | 13752 | } |
13735 | 13753 | ||
13754 | if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) | ||
13755 | state->ctl = i845_cursor_ctl(crtc_state, state); | ||
13756 | else | ||
13757 | state->ctl = i9xx_cursor_ctl(crtc_state, state); | ||
13758 | |||
13736 | return 0; | 13759 | return 0; |
13737 | } | 13760 | } |
13738 | 13761 | ||
@@ -14368,7 +14391,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, | |||
14368 | mode_cmd->modifier[0]); | 14391 | mode_cmd->modifier[0]); |
14369 | goto err; | 14392 | goto err; |
14370 | } | 14393 | } |
14371 | case DRM_FORMAT_MOD_NONE: | 14394 | case DRM_FORMAT_MOD_LINEAR: |
14372 | case I915_FORMAT_MOD_X_TILED: | 14395 | case I915_FORMAT_MOD_X_TILED: |
14373 | break; | 14396 | break; |
14374 | default: | 14397 | default: |
@@ -14391,7 +14414,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, | |||
14391 | mode_cmd->pixel_format); | 14414 | mode_cmd->pixel_format); |
14392 | if (mode_cmd->pitches[0] > pitch_limit) { | 14415 | if (mode_cmd->pitches[0] > pitch_limit) { |
14393 | DRM_DEBUG_KMS("%s pitch (%u) must be at most %d\n", | 14416 | DRM_DEBUG_KMS("%s pitch (%u) must be at most %d\n", |
14394 | mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ? | 14417 | mode_cmd->modifier[0] != DRM_FORMAT_MOD_LINEAR ? |
14395 | "tiled" : "linear", | 14418 | "tiled" : "linear", |
14396 | mode_cmd->pitches[0], pitch_limit); | 14419 | mode_cmd->pitches[0], pitch_limit); |
14397 | goto err; | 14420 | goto err; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 51228fe4283b..313fad059bfa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -398,6 +398,9 @@ struct intel_plane_state { | |||
398 | int x, y; | 398 | int x, y; |
399 | } aux; | 399 | } aux; |
400 | 400 | ||
401 | /* plane control register */ | ||
402 | u32 ctl; | ||
403 | |||
401 | /* | 404 | /* |
402 | * scaler_id | 405 | * scaler_id |
403 | * = -1 : not using a scaler | 406 | * = -1 : not using a scaler |
@@ -729,6 +732,12 @@ struct intel_crtc_state { | |||
729 | 732 | ||
730 | /* bitmask of visible planes (enum plane_id) */ | 733 | /* bitmask of visible planes (enum plane_id) */ |
731 | u8 active_planes; | 734 | u8 active_planes; |
735 | |||
736 | /* HDMI scrambling status */ | ||
737 | bool hdmi_scrambling; | ||
738 | |||
739 | /* HDMI High TMDS char rate ratio */ | ||
740 | bool hdmi_high_tmds_clock_ratio; | ||
732 | }; | 741 | }; |
733 | 742 | ||
734 | struct intel_crtc { | 743 | struct intel_crtc { |
@@ -1220,12 +1229,9 @@ void intel_crt_init(struct drm_i915_private *dev_priv); | |||
1220 | void intel_crt_reset(struct drm_encoder *encoder); | 1229 | void intel_crt_reset(struct drm_encoder *encoder); |
1221 | 1230 | ||
1222 | /* intel_ddi.c */ | 1231 | /* intel_ddi.c */ |
1223 | void intel_ddi_clk_select(struct intel_encoder *encoder, | ||
1224 | struct intel_shared_dpll *pll); | ||
1225 | void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, | 1232 | void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, |
1226 | struct intel_crtc_state *old_crtc_state, | 1233 | struct intel_crtc_state *old_crtc_state, |
1227 | struct drm_connector_state *old_conn_state); | 1234 | struct drm_connector_state *old_conn_state); |
1228 | void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder); | ||
1229 | void hsw_fdi_link_train(struct intel_crtc *crtc, | 1235 | void hsw_fdi_link_train(struct intel_crtc *crtc, |
1230 | const struct intel_crtc_state *crtc_state); | 1236 | const struct intel_crtc_state *crtc_state); |
1231 | void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); | 1237 | void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); |
@@ -1236,8 +1242,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, | |||
1236 | enum transcoder cpu_transcoder); | 1242 | enum transcoder cpu_transcoder); |
1237 | void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state); | 1243 | void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state); |
1238 | void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state); | 1244 | void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state); |
1239 | bool intel_ddi_pll_select(struct intel_crtc *crtc, | 1245 | struct intel_encoder * |
1240 | struct intel_crtc_state *crtc_state); | 1246 | intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state); |
1241 | void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state); | 1247 | void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state); |
1242 | void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); | 1248 | void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); |
1243 | bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); | 1249 | bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); |
@@ -1246,7 +1252,6 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, | |||
1246 | void intel_ddi_get_config(struct intel_encoder *encoder, | 1252 | void intel_ddi_get_config(struct intel_encoder *encoder, |
1247 | struct intel_crtc_state *pipe_config); | 1253 | struct intel_crtc_state *pipe_config); |
1248 | 1254 | ||
1249 | void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); | ||
1250 | void intel_ddi_clock_get(struct intel_encoder *encoder, | 1255 | void intel_ddi_clock_get(struct intel_encoder *encoder, |
1251 | struct intel_crtc_state *pipe_config); | 1256 | struct intel_crtc_state *pipe_config); |
1252 | void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, | 1257 | void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, |
@@ -1445,12 +1450,12 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) | |||
1445 | return i915_ggtt_offset(state->vma); | 1450 | return i915_ggtt_offset(state->vma); |
1446 | } | 1451 | } |
1447 | 1452 | ||
1448 | u32 skl_plane_ctl_format(uint32_t pixel_format); | 1453 | u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, |
1449 | u32 skl_plane_ctl_tiling(uint64_t fb_modifier); | 1454 | const struct intel_plane_state *plane_state); |
1450 | u32 skl_plane_ctl_rotation(unsigned int rotation); | ||
1451 | u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, | 1455 | u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, |
1452 | unsigned int rotation); | 1456 | unsigned int rotation); |
1453 | int skl_check_plane_surface(struct intel_plane_state *plane_state); | 1457 | int skl_check_plane_surface(struct intel_plane_state *plane_state); |
1458 | int i9xx_check_plane_surface(struct intel_plane_state *plane_state); | ||
1454 | 1459 | ||
1455 | /* intel_csr.c */ | 1460 | /* intel_csr.c */ |
1456 | void intel_csr_ucode_init(struct drm_i915_private *); | 1461 | void intel_csr_ucode_init(struct drm_i915_private *); |
@@ -1620,6 +1625,10 @@ struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); | |||
1620 | bool intel_hdmi_compute_config(struct intel_encoder *encoder, | 1625 | bool intel_hdmi_compute_config(struct intel_encoder *encoder, |
1621 | struct intel_crtc_state *pipe_config, | 1626 | struct intel_crtc_state *pipe_config, |
1622 | struct drm_connector_state *conn_state); | 1627 | struct drm_connector_state *conn_state); |
1628 | void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder, | ||
1629 | struct drm_connector *connector, | ||
1630 | bool high_tmds_clock_ratio, | ||
1631 | bool scrambling); | ||
1623 | void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); | 1632 | void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); |
1624 | 1633 | ||
1625 | 1634 | ||
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 4200faa520c7..854e8e0c836b 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
@@ -36,45 +36,45 @@ static const struct engine_info { | |||
36 | int (*init_execlists)(struct intel_engine_cs *engine); | 36 | int (*init_execlists)(struct intel_engine_cs *engine); |
37 | } intel_engines[] = { | 37 | } intel_engines[] = { |
38 | [RCS] = { | 38 | [RCS] = { |
39 | .name = "render ring", | 39 | .name = "rcs", |
40 | .exec_id = I915_EXEC_RENDER, | ||
41 | .hw_id = RCS_HW, | 40 | .hw_id = RCS_HW, |
41 | .exec_id = I915_EXEC_RENDER, | ||
42 | .mmio_base = RENDER_RING_BASE, | 42 | .mmio_base = RENDER_RING_BASE, |
43 | .irq_shift = GEN8_RCS_IRQ_SHIFT, | 43 | .irq_shift = GEN8_RCS_IRQ_SHIFT, |
44 | .init_execlists = logical_render_ring_init, | 44 | .init_execlists = logical_render_ring_init, |
45 | .init_legacy = intel_init_render_ring_buffer, | 45 | .init_legacy = intel_init_render_ring_buffer, |
46 | }, | 46 | }, |
47 | [BCS] = { | 47 | [BCS] = { |
48 | .name = "blitter ring", | 48 | .name = "bcs", |
49 | .exec_id = I915_EXEC_BLT, | ||
50 | .hw_id = BCS_HW, | 49 | .hw_id = BCS_HW, |
50 | .exec_id = I915_EXEC_BLT, | ||
51 | .mmio_base = BLT_RING_BASE, | 51 | .mmio_base = BLT_RING_BASE, |
52 | .irq_shift = GEN8_BCS_IRQ_SHIFT, | 52 | .irq_shift = GEN8_BCS_IRQ_SHIFT, |
53 | .init_execlists = logical_xcs_ring_init, | 53 | .init_execlists = logical_xcs_ring_init, |
54 | .init_legacy = intel_init_blt_ring_buffer, | 54 | .init_legacy = intel_init_blt_ring_buffer, |
55 | }, | 55 | }, |
56 | [VCS] = { | 56 | [VCS] = { |
57 | .name = "bsd ring", | 57 | .name = "vcs", |
58 | .exec_id = I915_EXEC_BSD, | ||
59 | .hw_id = VCS_HW, | 58 | .hw_id = VCS_HW, |
59 | .exec_id = I915_EXEC_BSD, | ||
60 | .mmio_base = GEN6_BSD_RING_BASE, | 60 | .mmio_base = GEN6_BSD_RING_BASE, |
61 | .irq_shift = GEN8_VCS1_IRQ_SHIFT, | 61 | .irq_shift = GEN8_VCS1_IRQ_SHIFT, |
62 | .init_execlists = logical_xcs_ring_init, | 62 | .init_execlists = logical_xcs_ring_init, |
63 | .init_legacy = intel_init_bsd_ring_buffer, | 63 | .init_legacy = intel_init_bsd_ring_buffer, |
64 | }, | 64 | }, |
65 | [VCS2] = { | 65 | [VCS2] = { |
66 | .name = "bsd2 ring", | 66 | .name = "vcs2", |
67 | .exec_id = I915_EXEC_BSD, | ||
68 | .hw_id = VCS2_HW, | 67 | .hw_id = VCS2_HW, |
68 | .exec_id = I915_EXEC_BSD, | ||
69 | .mmio_base = GEN8_BSD2_RING_BASE, | 69 | .mmio_base = GEN8_BSD2_RING_BASE, |
70 | .irq_shift = GEN8_VCS2_IRQ_SHIFT, | 70 | .irq_shift = GEN8_VCS2_IRQ_SHIFT, |
71 | .init_execlists = logical_xcs_ring_init, | 71 | .init_execlists = logical_xcs_ring_init, |
72 | .init_legacy = intel_init_bsd2_ring_buffer, | 72 | .init_legacy = intel_init_bsd2_ring_buffer, |
73 | }, | 73 | }, |
74 | [VECS] = { | 74 | [VECS] = { |
75 | .name = "video enhancement ring", | 75 | .name = "vecs", |
76 | .exec_id = I915_EXEC_VEBOX, | ||
77 | .hw_id = VECS_HW, | 76 | .hw_id = VECS_HW, |
77 | .exec_id = I915_EXEC_VEBOX, | ||
78 | .mmio_base = VEBOX_RING_BASE, | 78 | .mmio_base = VEBOX_RING_BASE, |
79 | .irq_shift = GEN8_VECS_IRQ_SHIFT, | 79 | .irq_shift = GEN8_VECS_IRQ_SHIFT, |
80 | .init_execlists = logical_xcs_ring_init, | 80 | .init_execlists = logical_xcs_ring_init, |
@@ -242,12 +242,12 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) | |||
242 | void *semaphores; | 242 | void *semaphores; |
243 | 243 | ||
244 | /* Semaphores are in noncoherent memory, flush to be safe */ | 244 | /* Semaphores are in noncoherent memory, flush to be safe */ |
245 | semaphores = kmap(page); | 245 | semaphores = kmap_atomic(page); |
246 | memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), | 246 | memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), |
247 | 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); | 247 | 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); |
248 | drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), | 248 | drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), |
249 | I915_NUM_ENGINES * gen8_semaphore_seqno_size); | 249 | I915_NUM_ENGINES * gen8_semaphore_seqno_size); |
250 | kunmap(page); | 250 | kunmap_atomic(semaphores); |
251 | } | 251 | } |
252 | 252 | ||
253 | intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); | 253 | intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); |
@@ -1111,6 +1111,15 @@ bool intel_engines_are_idle(struct drm_i915_private *dev_priv) | |||
1111 | struct intel_engine_cs *engine; | 1111 | struct intel_engine_cs *engine; |
1112 | enum intel_engine_id id; | 1112 | enum intel_engine_id id; |
1113 | 1113 | ||
1114 | if (READ_ONCE(dev_priv->gt.active_requests)) | ||
1115 | return false; | ||
1116 | |||
1117 | /* If the driver is wedged, HW state may be very inconsistent and | ||
1118 | * report that it is still busy, even though we have stopped using it. | ||
1119 | */ | ||
1120 | if (i915_terminally_wedged(&dev_priv->gpu_error)) | ||
1121 | return true; | ||
1122 | |||
1114 | for_each_engine(engine, dev_priv, id) { | 1123 | for_each_engine(engine, dev_priv, id) { |
1115 | if (!intel_engine_is_idle(engine)) | 1124 | if (!intel_engine_is_idle(engine)) |
1116 | return false; | 1125 | return false; |
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 25691f0e4c50..cb36cbf3818f 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h | |||
@@ -26,14 +26,14 @@ | |||
26 | #define GFXCORE_FAMILY_GEN9 12 | 26 | #define GFXCORE_FAMILY_GEN9 12 |
27 | #define GFXCORE_FAMILY_UNKNOWN 0x7fffffff | 27 | #define GFXCORE_FAMILY_UNKNOWN 0x7fffffff |
28 | 28 | ||
29 | #define GUC_CTX_PRIORITY_KMD_HIGH 0 | 29 | #define GUC_CLIENT_PRIORITY_KMD_HIGH 0 |
30 | #define GUC_CTX_PRIORITY_HIGH 1 | 30 | #define GUC_CLIENT_PRIORITY_HIGH 1 |
31 | #define GUC_CTX_PRIORITY_KMD_NORMAL 2 | 31 | #define GUC_CLIENT_PRIORITY_KMD_NORMAL 2 |
32 | #define GUC_CTX_PRIORITY_NORMAL 3 | 32 | #define GUC_CLIENT_PRIORITY_NORMAL 3 |
33 | #define GUC_CTX_PRIORITY_NUM 4 | 33 | #define GUC_CLIENT_PRIORITY_NUM 4 |
34 | 34 | ||
35 | #define GUC_MAX_GPU_CONTEXTS 1024 | 35 | #define GUC_MAX_STAGE_DESCRIPTORS 1024 |
36 | #define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS | 36 | #define GUC_INVALID_STAGE_ID GUC_MAX_STAGE_DESCRIPTORS |
37 | 37 | ||
38 | #define GUC_RENDER_ENGINE 0 | 38 | #define GUC_RENDER_ENGINE 0 |
39 | #define GUC_VIDEO_ENGINE 1 | 39 | #define GUC_VIDEO_ENGINE 1 |
@@ -68,14 +68,14 @@ | |||
68 | #define GUC_DOORBELL_ENABLED 1 | 68 | #define GUC_DOORBELL_ENABLED 1 |
69 | #define GUC_DOORBELL_DISABLED 0 | 69 | #define GUC_DOORBELL_DISABLED 0 |
70 | 70 | ||
71 | #define GUC_CTX_DESC_ATTR_ACTIVE (1 << 0) | 71 | #define GUC_STAGE_DESC_ATTR_ACTIVE BIT(0) |
72 | #define GUC_CTX_DESC_ATTR_PENDING_DB (1 << 1) | 72 | #define GUC_STAGE_DESC_ATTR_PENDING_DB BIT(1) |
73 | #define GUC_CTX_DESC_ATTR_KERNEL (1 << 2) | 73 | #define GUC_STAGE_DESC_ATTR_KERNEL BIT(2) |
74 | #define GUC_CTX_DESC_ATTR_PREEMPT (1 << 3) | 74 | #define GUC_STAGE_DESC_ATTR_PREEMPT BIT(3) |
75 | #define GUC_CTX_DESC_ATTR_RESET (1 << 4) | 75 | #define GUC_STAGE_DESC_ATTR_RESET BIT(4) |
76 | #define GUC_CTX_DESC_ATTR_WQLOCKED (1 << 5) | 76 | #define GUC_STAGE_DESC_ATTR_WQLOCKED BIT(5) |
77 | #define GUC_CTX_DESC_ATTR_PCH (1 << 6) | 77 | #define GUC_STAGE_DESC_ATTR_PCH BIT(6) |
78 | #define GUC_CTX_DESC_ATTR_TERMINATED (1 << 7) | 78 | #define GUC_STAGE_DESC_ATTR_TERMINATED BIT(7) |
79 | 79 | ||
80 | /* The guc control data is 10 DWORDs */ | 80 | /* The guc control data is 10 DWORDs */ |
81 | #define GUC_CTL_CTXINFO 0 | 81 | #define GUC_CTL_CTXINFO 0 |
@@ -241,8 +241,8 @@ union guc_doorbell_qw { | |||
241 | u64 value_qw; | 241 | u64 value_qw; |
242 | } __packed; | 242 | } __packed; |
243 | 243 | ||
244 | #define GUC_MAX_DOORBELLS 256 | 244 | #define GUC_NUM_DOORBELLS 256 |
245 | #define GUC_INVALID_DOORBELL_ID (GUC_MAX_DOORBELLS) | 245 | #define GUC_DOORBELL_INVALID (GUC_NUM_DOORBELLS) |
246 | 246 | ||
247 | #define GUC_DB_SIZE (PAGE_SIZE) | 247 | #define GUC_DB_SIZE (PAGE_SIZE) |
248 | #define GUC_WQ_SIZE (PAGE_SIZE * 2) | 248 | #define GUC_WQ_SIZE (PAGE_SIZE * 2) |
@@ -251,12 +251,12 @@ union guc_doorbell_qw { | |||
251 | struct guc_wq_item { | 251 | struct guc_wq_item { |
252 | u32 header; | 252 | u32 header; |
253 | u32 context_desc; | 253 | u32 context_desc; |
254 | u32 ring_tail; | 254 | u32 submit_element_info; |
255 | u32 fence_id; | 255 | u32 fence_id; |
256 | } __packed; | 256 | } __packed; |
257 | 257 | ||
258 | struct guc_process_desc { | 258 | struct guc_process_desc { |
259 | u32 context_id; | 259 | u32 stage_id; |
260 | u64 db_base_addr; | 260 | u64 db_base_addr; |
261 | u32 head; | 261 | u32 head; |
262 | u32 tail; | 262 | u32 tail; |
@@ -278,7 +278,7 @@ struct guc_execlist_context { | |||
278 | u32 context_desc; | 278 | u32 context_desc; |
279 | u32 context_id; | 279 | u32 context_id; |
280 | u32 ring_status; | 280 | u32 ring_status; |
281 | u32 ring_lcra; | 281 | u32 ring_lrca; |
282 | u32 ring_begin; | 282 | u32 ring_begin; |
283 | u32 ring_end; | 283 | u32 ring_end; |
284 | u32 ring_next_free_location; | 284 | u32 ring_next_free_location; |
@@ -289,10 +289,18 @@ struct guc_execlist_context { | |||
289 | u16 engine_submit_queue_count; | 289 | u16 engine_submit_queue_count; |
290 | } __packed; | 290 | } __packed; |
291 | 291 | ||
292 | /*Context descriptor for communicating between uKernel and Driver*/ | 292 | /* |
293 | struct guc_context_desc { | 293 | * This structure describes a stage set arranged for a particular communication |
294 | * between uKernel (GuC) and Driver (KMD). Technically, this is known as a | ||
295 | * "GuC Context descriptor" in the specs, but we use the term "stage descriptor" | ||
296 | * to avoid confusion with all the other things already named "context" in the | ||
297 | * driver. A static pool of these descriptors are stored inside a GEM object | ||
298 | * (stage_desc_pool) which is held for the entire lifetime of our interaction | ||
299 | * with the GuC, being allocated before the GuC is loaded with its firmware. | ||
300 | */ | ||
301 | struct guc_stage_desc { | ||
294 | u32 sched_common_area; | 302 | u32 sched_common_area; |
295 | u32 context_id; | 303 | u32 stage_id; |
296 | u32 pas_id; | 304 | u32 pas_id; |
297 | u8 engines_used; | 305 | u8 engines_used; |
298 | u64 db_trigger_cpu; | 306 | u64 db_trigger_cpu; |
@@ -359,7 +367,7 @@ struct guc_policy { | |||
359 | } __packed; | 367 | } __packed; |
360 | 368 | ||
361 | struct guc_policies { | 369 | struct guc_policies { |
362 | struct guc_policy policy[GUC_CTX_PRIORITY_NUM][GUC_MAX_ENGINES_NUM]; | 370 | struct guc_policy policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINES_NUM]; |
363 | 371 | ||
364 | /* In micro seconds. How much time to allow before DPC processing is | 372 | /* In micro seconds. How much time to allow before DPC processing is |
365 | * called back via interrupt (to prevent DPC queue drain starving). | 373 | * called back via interrupt (to prevent DPC queue drain starving). |
@@ -401,16 +409,17 @@ struct guc_mmio_regset { | |||
401 | u32 number_of_registers; | 409 | u32 number_of_registers; |
402 | } __packed; | 410 | } __packed; |
403 | 411 | ||
412 | /* MMIO registers that are set as non privileged */ | ||
413 | struct mmio_white_list { | ||
414 | u32 mmio_start; | ||
415 | u32 offsets[GUC_MMIO_WHITE_LIST_MAX]; | ||
416 | u32 count; | ||
417 | } __packed; | ||
418 | |||
404 | struct guc_mmio_reg_state { | 419 | struct guc_mmio_reg_state { |
405 | struct guc_mmio_regset global_reg; | 420 | struct guc_mmio_regset global_reg; |
406 | struct guc_mmio_regset engine_reg[GUC_MAX_ENGINES_NUM]; | 421 | struct guc_mmio_regset engine_reg[GUC_MAX_ENGINES_NUM]; |
407 | 422 | struct mmio_white_list white_list[GUC_MAX_ENGINES_NUM]; | |
408 | /* MMIO registers that are set as non privileged */ | ||
409 | struct __packed { | ||
410 | u32 mmio_start; | ||
411 | u32 offsets[GUC_MMIO_WHITE_LIST_MAX]; | ||
412 | u32 count; | ||
413 | } mmio_white_list[GUC_MAX_ENGINES_NUM]; | ||
414 | } __packed; | 423 | } __packed; |
415 | 424 | ||
416 | /* GuC Additional Data Struct */ | 425 | /* GuC Additional Data Struct */ |
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 2f270d02894c..8a1a023e48b2 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c | |||
@@ -73,22 +73,6 @@ MODULE_FIRMWARE(I915_BXT_GUC_UCODE); | |||
73 | #define I915_KBL_GUC_UCODE GUC_FW_PATH(kbl, KBL_FW_MAJOR, KBL_FW_MINOR) | 73 | #define I915_KBL_GUC_UCODE GUC_FW_PATH(kbl, KBL_FW_MAJOR, KBL_FW_MINOR) |
74 | MODULE_FIRMWARE(I915_KBL_GUC_UCODE); | 74 | MODULE_FIRMWARE(I915_KBL_GUC_UCODE); |
75 | 75 | ||
76 | /* User-friendly representation of an enum */ | ||
77 | const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) | ||
78 | { | ||
79 | switch (status) { | ||
80 | case INTEL_UC_FIRMWARE_FAIL: | ||
81 | return "FAIL"; | ||
82 | case INTEL_UC_FIRMWARE_NONE: | ||
83 | return "NONE"; | ||
84 | case INTEL_UC_FIRMWARE_PENDING: | ||
85 | return "PENDING"; | ||
86 | case INTEL_UC_FIRMWARE_SUCCESS: | ||
87 | return "SUCCESS"; | ||
88 | default: | ||
89 | return "UNKNOWN!"; | ||
90 | } | ||
91 | }; | ||
92 | 76 | ||
93 | static u32 get_gttype(struct drm_i915_private *dev_priv) | 77 | static u32 get_gttype(struct drm_i915_private *dev_priv) |
94 | { | 78 | { |
@@ -148,16 +132,14 @@ static void guc_params_init(struct drm_i915_private *dev_priv) | |||
148 | } else | 132 | } else |
149 | params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; | 133 | params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; |
150 | 134 | ||
151 | if (guc->ads_vma) { | 135 | /* If GuC submission is enabled, set up additional parameters here */ |
136 | if (i915.enable_guc_submission) { | ||
152 | u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; | 137 | u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; |
138 | u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); | ||
139 | u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; | ||
140 | |||
153 | params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; | 141 | params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; |
154 | params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; | 142 | params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; |
155 | } | ||
156 | |||
157 | /* If GuC submission is enabled, set up additional parameters here */ | ||
158 | if (i915.enable_guc_submission) { | ||
159 | u32 pgs = guc_ggtt_offset(dev_priv->guc.ctx_pool_vma); | ||
160 | u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16; | ||
161 | 143 | ||
162 | pgs >>= PAGE_SHIFT; | 144 | pgs >>= PAGE_SHIFT; |
163 | params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) | | 145 | params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) | |
@@ -430,24 +412,3 @@ int intel_guc_select_fw(struct intel_guc *guc) | |||
430 | 412 | ||
431 | return 0; | 413 | return 0; |
432 | } | 414 | } |
433 | |||
434 | /** | ||
435 | * intel_guc_fini() - clean up all allocated resources | ||
436 | * @dev_priv: i915 device private | ||
437 | */ | ||
438 | void intel_guc_fini(struct drm_i915_private *dev_priv) | ||
439 | { | ||
440 | struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; | ||
441 | struct drm_i915_gem_object *obj; | ||
442 | |||
443 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
444 | i915_guc_submission_disable(dev_priv); | ||
445 | i915_guc_submission_fini(dev_priv); | ||
446 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
447 | |||
448 | obj = fetch_and_zero(&guc_fw->obj); | ||
449 | if (obj) | ||
450 | i915_gem_object_put(obj); | ||
451 | |||
452 | guc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; | ||
453 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c index 5c0f9a49da0e..6fb63a3c65b0 100644 --- a/drivers/gpu/drm/i915/intel_guc_log.c +++ b/drivers/gpu/drm/i915/intel_guc_log.c | |||
@@ -66,7 +66,6 @@ static int guc_log_control(struct intel_guc *guc, u32 control_val) | |||
66 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 66 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
67 | } | 67 | } |
68 | 68 | ||
69 | |||
70 | /* | 69 | /* |
71 | * Sub buffer switch callback. Called whenever relay has to switch to a new | 70 | * Sub buffer switch callback. Called whenever relay has to switch to a new |
72 | * sub buffer, relay stays on the same sub buffer if 0 is returned. | 71 | * sub buffer, relay stays on the same sub buffer if 0 is returned. |
@@ -139,45 +138,15 @@ static struct rchan_callbacks relay_callbacks = { | |||
139 | .remove_buf_file = remove_buf_file_callback, | 138 | .remove_buf_file = remove_buf_file_callback, |
140 | }; | 139 | }; |
141 | 140 | ||
142 | static void guc_log_remove_relay_file(struct intel_guc *guc) | 141 | static int guc_log_relay_file_create(struct intel_guc *guc) |
143 | { | ||
144 | relay_close(guc->log.relay_chan); | ||
145 | } | ||
146 | |||
147 | static int guc_log_create_relay_channel(struct intel_guc *guc) | ||
148 | { | ||
149 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
150 | struct rchan *guc_log_relay_chan; | ||
151 | size_t n_subbufs, subbuf_size; | ||
152 | |||
153 | /* Keep the size of sub buffers same as shared log buffer */ | ||
154 | subbuf_size = guc->log.vma->obj->base.size; | ||
155 | |||
156 | /* Store up to 8 snapshots, which is large enough to buffer sufficient | ||
157 | * boot time logs and provides enough leeway to User, in terms of | ||
158 | * latency, for consuming the logs from relay. Also doesn't take | ||
159 | * up too much memory. | ||
160 | */ | ||
161 | n_subbufs = 8; | ||
162 | |||
163 | guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, | ||
164 | n_subbufs, &relay_callbacks, dev_priv); | ||
165 | if (!guc_log_relay_chan) { | ||
166 | DRM_ERROR("Couldn't create relay chan for GuC logging\n"); | ||
167 | return -ENOMEM; | ||
168 | } | ||
169 | |||
170 | GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); | ||
171 | guc->log.relay_chan = guc_log_relay_chan; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int guc_log_create_relay_file(struct intel_guc *guc) | ||
176 | { | 142 | { |
177 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 143 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
178 | struct dentry *log_dir; | 144 | struct dentry *log_dir; |
179 | int ret; | 145 | int ret; |
180 | 146 | ||
147 | if (i915.guc_log_level < 0) | ||
148 | return 0; | ||
149 | |||
181 | /* For now create the log file in /sys/kernel/debug/dri/0 dir */ | 150 | /* For now create the log file in /sys/kernel/debug/dri/0 dir */ |
182 | log_dir = dev_priv->drm.primary->debugfs_root; | 151 | log_dir = dev_priv->drm.primary->debugfs_root; |
183 | 152 | ||
@@ -197,8 +166,8 @@ static int guc_log_create_relay_file(struct intel_guc *guc) | |||
197 | return -ENODEV; | 166 | return -ENODEV; |
198 | } | 167 | } |
199 | 168 | ||
200 | ret = relay_late_setup_files(guc->log.relay_chan, "guc_log", log_dir); | 169 | ret = relay_late_setup_files(guc->log.runtime.relay_chan, "guc_log", log_dir); |
201 | if (ret) { | 170 | if (ret < 0 && ret != -EEXIST) { |
202 | DRM_ERROR("Couldn't associate relay chan with file %d\n", ret); | 171 | DRM_ERROR("Couldn't associate relay chan with file %d\n", ret); |
203 | return ret; | 172 | return ret; |
204 | } | 173 | } |
@@ -214,15 +183,15 @@ static void guc_move_to_next_buf(struct intel_guc *guc) | |||
214 | smp_wmb(); | 183 | smp_wmb(); |
215 | 184 | ||
216 | /* All data has been written, so now move the offset of sub buffer. */ | 185 | /* All data has been written, so now move the offset of sub buffer. */ |
217 | relay_reserve(guc->log.relay_chan, guc->log.vma->obj->base.size); | 186 | relay_reserve(guc->log.runtime.relay_chan, guc->log.vma->obj->base.size); |
218 | 187 | ||
219 | /* Switch to the next sub buffer */ | 188 | /* Switch to the next sub buffer */ |
220 | relay_flush(guc->log.relay_chan); | 189 | relay_flush(guc->log.runtime.relay_chan); |
221 | } | 190 | } |
222 | 191 | ||
223 | static void *guc_get_write_buffer(struct intel_guc *guc) | 192 | static void *guc_get_write_buffer(struct intel_guc *guc) |
224 | { | 193 | { |
225 | if (!guc->log.relay_chan) | 194 | if (!guc->log.runtime.relay_chan) |
226 | return NULL; | 195 | return NULL; |
227 | 196 | ||
228 | /* Just get the base address of a new sub buffer and copy data into it | 197 | /* Just get the base address of a new sub buffer and copy data into it |
@@ -233,7 +202,7 @@ static void *guc_get_write_buffer(struct intel_guc *guc) | |||
233 | * done without using relay_reserve() along with relay_write(). So its | 202 | * done without using relay_reserve() along with relay_write(). So its |
234 | * better to use relay_reserve() alone. | 203 | * better to use relay_reserve() alone. |
235 | */ | 204 | */ |
236 | return relay_reserve(guc->log.relay_chan, 0); | 205 | return relay_reserve(guc->log.runtime.relay_chan, 0); |
237 | } | 206 | } |
238 | 207 | ||
239 | static bool guc_check_log_buf_overflow(struct intel_guc *guc, | 208 | static bool guc_check_log_buf_overflow(struct intel_guc *guc, |
@@ -284,11 +253,11 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
284 | void *src_data, *dst_data; | 253 | void *src_data, *dst_data; |
285 | bool new_overflow; | 254 | bool new_overflow; |
286 | 255 | ||
287 | if (WARN_ON(!guc->log.buf_addr)) | 256 | if (WARN_ON(!guc->log.runtime.buf_addr)) |
288 | return; | 257 | return; |
289 | 258 | ||
290 | /* Get the pointer to shared GuC log buffer */ | 259 | /* Get the pointer to shared GuC log buffer */ |
291 | log_buf_state = src_data = guc->log.buf_addr; | 260 | log_buf_state = src_data = guc->log.runtime.buf_addr; |
292 | 261 | ||
293 | /* Get the pointer to local buffer to store the logs */ | 262 | /* Get the pointer to local buffer to store the logs */ |
294 | log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc); | 263 | log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc); |
@@ -371,153 +340,113 @@ static void guc_read_update_log_buffer(struct intel_guc *guc) | |||
371 | } | 340 | } |
372 | } | 341 | } |
373 | 342 | ||
374 | static void guc_log_cleanup(struct intel_guc *guc) | ||
375 | { | ||
376 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | ||
377 | |||
378 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | ||
379 | |||
380 | /* First disable the flush interrupt */ | ||
381 | gen9_disable_guc_interrupts(dev_priv); | ||
382 | |||
383 | if (guc->log.flush_wq) | ||
384 | destroy_workqueue(guc->log.flush_wq); | ||
385 | |||
386 | guc->log.flush_wq = NULL; | ||
387 | |||
388 | if (guc->log.relay_chan) | ||
389 | guc_log_remove_relay_file(guc); | ||
390 | |||
391 | guc->log.relay_chan = NULL; | ||
392 | |||
393 | if (guc->log.buf_addr) | ||
394 | i915_gem_object_unpin_map(guc->log.vma->obj); | ||
395 | |||
396 | guc->log.buf_addr = NULL; | ||
397 | } | ||
398 | |||
399 | static void capture_logs_work(struct work_struct *work) | 343 | static void capture_logs_work(struct work_struct *work) |
400 | { | 344 | { |
401 | struct intel_guc *guc = | 345 | struct intel_guc *guc = |
402 | container_of(work, struct intel_guc, log.flush_work); | 346 | container_of(work, struct intel_guc, log.runtime.flush_work); |
403 | 347 | ||
404 | guc_log_capture_logs(guc); | 348 | guc_log_capture_logs(guc); |
405 | } | 349 | } |
406 | 350 | ||
407 | static int guc_log_create_extras(struct intel_guc *guc) | 351 | static bool guc_log_has_runtime(struct intel_guc *guc) |
352 | { | ||
353 | return guc->log.runtime.buf_addr != NULL; | ||
354 | } | ||
355 | |||
356 | static int guc_log_runtime_create(struct intel_guc *guc) | ||
408 | { | 357 | { |
409 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 358 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
410 | void *vaddr; | 359 | void *vaddr; |
411 | int ret; | 360 | struct rchan *guc_log_relay_chan; |
361 | size_t n_subbufs, subbuf_size; | ||
362 | int ret = 0; | ||
412 | 363 | ||
413 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 364 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
414 | 365 | ||
415 | /* Nothing to do */ | 366 | GEM_BUG_ON(guc_log_has_runtime(guc)); |
416 | if (i915.guc_log_level < 0) | ||
417 | return 0; | ||
418 | |||
419 | if (!guc->log.buf_addr) { | ||
420 | /* Create a WC (Uncached for read) vmalloc mapping of log | ||
421 | * buffer pages, so that we can directly get the data | ||
422 | * (up-to-date) from memory. | ||
423 | */ | ||
424 | vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC); | ||
425 | if (IS_ERR(vaddr)) { | ||
426 | ret = PTR_ERR(vaddr); | ||
427 | DRM_ERROR("Couldn't map log buffer pages %d\n", ret); | ||
428 | return ret; | ||
429 | } | ||
430 | 367 | ||
431 | guc->log.buf_addr = vaddr; | 368 | /* Create a WC (Uncached for read) vmalloc mapping of log |
369 | * buffer pages, so that we can directly get the data | ||
370 | * (up-to-date) from memory. | ||
371 | */ | ||
372 | vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC); | ||
373 | if (IS_ERR(vaddr)) { | ||
374 | DRM_ERROR("Couldn't map log buffer pages %d\n", ret); | ||
375 | return PTR_ERR(vaddr); | ||
432 | } | 376 | } |
433 | 377 | ||
434 | if (!guc->log.relay_chan) { | 378 | guc->log.runtime.buf_addr = vaddr; |
435 | /* Create a relay channel, so that we have buffers for storing | ||
436 | * the GuC firmware logs, the channel will be linked with a file | ||
437 | * later on when debugfs is registered. | ||
438 | */ | ||
439 | ret = guc_log_create_relay_channel(guc); | ||
440 | if (ret) | ||
441 | return ret; | ||
442 | } | ||
443 | 379 | ||
444 | if (!guc->log.flush_wq) { | 380 | /* Keep the size of sub buffers same as shared log buffer */ |
445 | INIT_WORK(&guc->log.flush_work, capture_logs_work); | 381 | subbuf_size = guc->log.vma->obj->base.size; |
446 | |||
447 | /* | ||
448 | * GuC log buffer flush work item has to do register access to | ||
449 | * send the ack to GuC and this work item, if not synced before | ||
450 | * suspend, can potentially get executed after the GFX device is | ||
451 | * suspended. | ||
452 | * By marking the WQ as freezable, we don't have to bother about | ||
453 | * flushing of this work item from the suspend hooks, the pending | ||
454 | * work item if any will be either executed before the suspend | ||
455 | * or scheduled later on resume. This way the handling of work | ||
456 | * item can be kept same between system suspend & rpm suspend. | ||
457 | */ | ||
458 | guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log", | ||
459 | WQ_HIGHPRI | WQ_FREEZABLE); | ||
460 | if (guc->log.flush_wq == NULL) { | ||
461 | DRM_ERROR("Couldn't allocate the wq for GuC logging\n"); | ||
462 | return -ENOMEM; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | void intel_guc_log_create(struct intel_guc *guc) | ||
470 | { | ||
471 | struct i915_vma *vma; | ||
472 | unsigned long offset; | ||
473 | uint32_t size, flags; | ||
474 | 382 | ||
475 | if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) | 383 | /* Store up to 8 snapshots, which is large enough to buffer sufficient |
476 | i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; | 384 | * boot time logs and provides enough leeway to User, in terms of |
385 | * latency, for consuming the logs from relay. Also doesn't take | ||
386 | * up too much memory. | ||
387 | */ | ||
388 | n_subbufs = 8; | ||
477 | 389 | ||
478 | /* The first page is to save log buffer state. Allocate one | 390 | /* Create a relay channel, so that we have buffers for storing |
479 | * extra page for others in case for overlap */ | 391 | * the GuC firmware logs, the channel will be linked with a file |
480 | size = (1 + GUC_LOG_DPC_PAGES + 1 + | 392 | * later on when debugfs is registered. |
481 | GUC_LOG_ISR_PAGES + 1 + | 393 | */ |
482 | GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT; | 394 | guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, |
395 | n_subbufs, &relay_callbacks, dev_priv); | ||
396 | if (!guc_log_relay_chan) { | ||
397 | DRM_ERROR("Couldn't create relay chan for GuC logging\n"); | ||
483 | 398 | ||
484 | vma = guc->log.vma; | 399 | ret = -ENOMEM; |
485 | if (!vma) { | 400 | goto err_vaddr; |
486 | /* We require SSE 4.1 for fast reads from the GuC log buffer and | 401 | } |
487 | * it should be present on the chipsets supporting GuC based | ||
488 | * submisssions. | ||
489 | */ | ||
490 | if (WARN_ON(!i915_has_memcpy_from_wc())) { | ||
491 | /* logging will not be enabled */ | ||
492 | i915.guc_log_level = -1; | ||
493 | return; | ||
494 | } | ||
495 | 402 | ||
496 | vma = intel_guc_allocate_vma(guc, size); | 403 | GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); |
497 | if (IS_ERR(vma)) { | 404 | guc->log.runtime.relay_chan = guc_log_relay_chan; |
498 | /* logging will be off */ | 405 | |
499 | i915.guc_log_level = -1; | 406 | INIT_WORK(&guc->log.runtime.flush_work, capture_logs_work); |
500 | return; | 407 | |
501 | } | 408 | /* |
409 | * GuC log buffer flush work item has to do register access to | ||
410 | * send the ack to GuC and this work item, if not synced before | ||
411 | * suspend, can potentially get executed after the GFX device is | ||
412 | * suspended. | ||
413 | * By marking the WQ as freezable, we don't have to bother about | ||
414 | * flushing of this work item from the suspend hooks, the pending | ||
415 | * work item if any will be either executed before the suspend | ||
416 | * or scheduled later on resume. This way the handling of work | ||
417 | * item can be kept same between system suspend & rpm suspend. | ||
418 | */ | ||
419 | guc->log.runtime.flush_wq = alloc_ordered_workqueue("i915-guc_log", | ||
420 | WQ_HIGHPRI | WQ_FREEZABLE); | ||
421 | if (!guc->log.runtime.flush_wq) { | ||
422 | DRM_ERROR("Couldn't allocate the wq for GuC logging\n"); | ||
423 | ret = -ENOMEM; | ||
424 | goto err_relaychan; | ||
425 | } | ||
502 | 426 | ||
503 | guc->log.vma = vma; | 427 | return 0; |
504 | 428 | ||
505 | if (guc_log_create_extras(guc)) { | 429 | err_relaychan: |
506 | guc_log_cleanup(guc); | 430 | relay_close(guc->log.runtime.relay_chan); |
507 | i915_vma_unpin_and_release(&guc->log.vma); | 431 | err_vaddr: |
508 | i915.guc_log_level = -1; | 432 | i915_gem_object_unpin_map(guc->log.vma->obj); |
509 | return; | 433 | guc->log.runtime.buf_addr = NULL; |
510 | } | 434 | return ret; |
511 | } | 435 | } |
512 | 436 | ||
513 | /* each allocated unit is a page */ | 437 | static void guc_log_runtime_destroy(struct intel_guc *guc) |
514 | flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | | 438 | { |
515 | (GUC_LOG_DPC_PAGES << GUC_LOG_DPC_SHIFT) | | 439 | /* |
516 | (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | | 440 | * It's possible that the runtime stuff was never allocated because |
517 | (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); | 441 | * guc_log_level was < 0 at the time |
442 | **/ | ||
443 | if (!guc_log_has_runtime(guc)) | ||
444 | return; | ||
518 | 445 | ||
519 | offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */ | 446 | destroy_workqueue(guc->log.runtime.flush_wq); |
520 | guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; | 447 | relay_close(guc->log.runtime.relay_chan); |
448 | i915_gem_object_unpin_map(guc->log.vma->obj); | ||
449 | guc->log.runtime.buf_addr = NULL; | ||
521 | } | 450 | } |
522 | 451 | ||
523 | static int guc_log_late_setup(struct intel_guc *guc) | 452 | static int guc_log_late_setup(struct intel_guc *guc) |
@@ -527,24 +456,25 @@ static int guc_log_late_setup(struct intel_guc *guc) | |||
527 | 456 | ||
528 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 457 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
529 | 458 | ||
530 | if (i915.guc_log_level < 0) | 459 | if (!guc_log_has_runtime(guc)) { |
531 | return -EINVAL; | 460 | /* If log_level was set as -1 at boot time, then setup needed to |
532 | 461 | * handle log buffer flush interrupts would not have been done yet, | |
533 | /* If log_level was set as -1 at boot time, then setup needed to | 462 | * so do that now. |
534 | * handle log buffer flush interrupts would not have been done yet, | 463 | */ |
535 | * so do that now. | 464 | ret = guc_log_runtime_create(guc); |
536 | */ | 465 | if (ret) |
537 | ret = guc_log_create_extras(guc); | 466 | goto err; |
538 | if (ret) | 467 | } |
539 | goto err; | ||
540 | 468 | ||
541 | ret = guc_log_create_relay_file(guc); | 469 | ret = guc_log_relay_file_create(guc); |
542 | if (ret) | 470 | if (ret) |
543 | goto err; | 471 | goto err_runtime; |
544 | 472 | ||
545 | return 0; | 473 | return 0; |
474 | |||
475 | err_runtime: | ||
476 | guc_log_runtime_destroy(guc); | ||
546 | err: | 477 | err: |
547 | guc_log_cleanup(guc); | ||
548 | /* logging will remain off */ | 478 | /* logging will remain off */ |
549 | i915.guc_log_level = -1; | 479 | i915.guc_log_level = -1; |
550 | return ret; | 480 | return ret; |
@@ -577,7 +507,7 @@ static void guc_flush_logs(struct intel_guc *guc) | |||
577 | /* Before initiating the forceful flush, wait for any pending/ongoing | 507 | /* Before initiating the forceful flush, wait for any pending/ongoing |
578 | * flush to complete otherwise forceful flush may not actually happen. | 508 | * flush to complete otherwise forceful flush may not actually happen. |
579 | */ | 509 | */ |
580 | flush_work(&guc->log.flush_work); | 510 | flush_work(&guc->log.runtime.flush_work); |
581 | 511 | ||
582 | /* Ask GuC to update the log buffer state */ | 512 | /* Ask GuC to update the log buffer state */ |
583 | guc_log_flush(guc); | 513 | guc_log_flush(guc); |
@@ -586,6 +516,72 @@ static void guc_flush_logs(struct intel_guc *guc) | |||
586 | guc_log_capture_logs(guc); | 516 | guc_log_capture_logs(guc); |
587 | } | 517 | } |
588 | 518 | ||
519 | int intel_guc_log_create(struct intel_guc *guc) | ||
520 | { | ||
521 | struct i915_vma *vma; | ||
522 | unsigned long offset; | ||
523 | uint32_t size, flags; | ||
524 | int ret; | ||
525 | |||
526 | GEM_BUG_ON(guc->log.vma); | ||
527 | |||
528 | if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) | ||
529 | i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; | ||
530 | |||
531 | /* The first page is to save log buffer state. Allocate one | ||
532 | * extra page for others in case for overlap */ | ||
533 | size = (1 + GUC_LOG_DPC_PAGES + 1 + | ||
534 | GUC_LOG_ISR_PAGES + 1 + | ||
535 | GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT; | ||
536 | |||
537 | /* We require SSE 4.1 for fast reads from the GuC log buffer and | ||
538 | * it should be present on the chipsets supporting GuC based | ||
539 | * submisssions. | ||
540 | */ | ||
541 | if (WARN_ON(!i915_has_memcpy_from_wc())) { | ||
542 | ret = -EINVAL; | ||
543 | goto err; | ||
544 | } | ||
545 | |||
546 | vma = intel_guc_allocate_vma(guc, size); | ||
547 | if (IS_ERR(vma)) { | ||
548 | ret = PTR_ERR(vma); | ||
549 | goto err; | ||
550 | } | ||
551 | |||
552 | guc->log.vma = vma; | ||
553 | |||
554 | if (i915.guc_log_level >= 0) { | ||
555 | ret = guc_log_runtime_create(guc); | ||
556 | if (ret < 0) | ||
557 | goto err_vma; | ||
558 | } | ||
559 | |||
560 | /* each allocated unit is a page */ | ||
561 | flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | | ||
562 | (GUC_LOG_DPC_PAGES << GUC_LOG_DPC_SHIFT) | | ||
563 | (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | | ||
564 | (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); | ||
565 | |||
566 | offset = guc_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */ | ||
567 | guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; | ||
568 | |||
569 | return 0; | ||
570 | |||
571 | err_vma: | ||
572 | i915_vma_unpin_and_release(&guc->log.vma); | ||
573 | err: | ||
574 | /* logging will be off */ | ||
575 | i915.guc_log_level = -1; | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | void intel_guc_log_destroy(struct intel_guc *guc) | ||
580 | { | ||
581 | guc_log_runtime_destroy(guc); | ||
582 | i915_vma_unpin_and_release(&guc->log.vma); | ||
583 | } | ||
584 | |||
589 | int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) | 585 | int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) |
590 | { | 586 | { |
591 | struct intel_guc *guc = &dev_priv->guc; | 587 | struct intel_guc *guc = &dev_priv->guc; |
@@ -609,17 +605,22 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) | |||
609 | return ret; | 605 | return ret; |
610 | } | 606 | } |
611 | 607 | ||
612 | i915.guc_log_level = log_param.verbosity; | 608 | if (log_param.logging_enabled) { |
609 | i915.guc_log_level = log_param.verbosity; | ||
613 | 610 | ||
614 | /* If log_level was set as -1 at boot time, then the relay channel file | 611 | /* If log_level was set as -1 at boot time, then the relay channel file |
615 | * wouldn't have been created by now and interrupts also would not have | 612 | * wouldn't have been created by now and interrupts also would not have |
616 | * been enabled. | 613 | * been enabled. Try again now, just in case. |
617 | */ | 614 | */ |
618 | if (!dev_priv->guc.log.relay_chan) { | ||
619 | ret = guc_log_late_setup(guc); | 615 | ret = guc_log_late_setup(guc); |
620 | if (!ret) | 616 | if (ret < 0) { |
621 | gen9_enable_guc_interrupts(dev_priv); | 617 | DRM_DEBUG_DRIVER("GuC log late setup failed %d\n", ret); |
622 | } else if (!log_param.logging_enabled) { | 618 | return ret; |
619 | } | ||
620 | |||
621 | /* GuC logging is currently the only user of Guc2Host interrupts */ | ||
622 | gen9_enable_guc_interrupts(dev_priv); | ||
623 | } else { | ||
623 | /* Once logging is disabled, GuC won't generate logs & send an | 624 | /* Once logging is disabled, GuC won't generate logs & send an |
624 | * interrupt. But there could be some data in the log buffer | 625 | * interrupt. But there could be some data in the log buffer |
625 | * which is yet to be captured. So request GuC to update the log | 626 | * which is yet to be captured. So request GuC to update the log |
@@ -629,9 +630,6 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) | |||
629 | 630 | ||
630 | /* As logging is disabled, update log level to reflect that */ | 631 | /* As logging is disabled, update log level to reflect that */ |
631 | i915.guc_log_level = -1; | 632 | i915.guc_log_level = -1; |
632 | } else { | ||
633 | /* In case interrupts were disabled, enable them now */ | ||
634 | gen9_enable_guc_interrupts(dev_priv); | ||
635 | } | 633 | } |
636 | 634 | ||
637 | return ret; | 635 | return ret; |
@@ -639,7 +637,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) | |||
639 | 637 | ||
640 | void i915_guc_log_register(struct drm_i915_private *dev_priv) | 638 | void i915_guc_log_register(struct drm_i915_private *dev_priv) |
641 | { | 639 | { |
642 | if (!i915.enable_guc_submission) | 640 | if (!i915.enable_guc_submission || i915.guc_log_level < 0) |
643 | return; | 641 | return; |
644 | 642 | ||
645 | mutex_lock(&dev_priv->drm.struct_mutex); | 643 | mutex_lock(&dev_priv->drm.struct_mutex); |
@@ -653,6 +651,8 @@ void i915_guc_log_unregister(struct drm_i915_private *dev_priv) | |||
653 | return; | 651 | return; |
654 | 652 | ||
655 | mutex_lock(&dev_priv->drm.struct_mutex); | 653 | mutex_lock(&dev_priv->drm.struct_mutex); |
656 | guc_log_cleanup(&dev_priv->guc); | 654 | /* GuC logging is currently the only user of Guc2Host interrupts */ |
655 | gen9_disable_guc_interrupts(dev_priv); | ||
656 | guc_log_runtime_destroy(&dev_priv->guc); | ||
657 | mutex_unlock(&dev_priv->drm.struct_mutex); | 657 | mutex_unlock(&dev_priv->drm.struct_mutex); |
658 | } | 658 | } |
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index 8c04eca84351..e1ab6432a914 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c | |||
@@ -45,6 +45,8 @@ static bool is_supported_device(struct drm_i915_private *dev_priv) | |||
45 | return true; | 45 | return true; |
46 | if (IS_SKYLAKE(dev_priv)) | 46 | if (IS_SKYLAKE(dev_priv)) |
47 | return true; | 47 | return true; |
48 | if (IS_KABYLAKE(dev_priv) && INTEL_DEVID(dev_priv) == 0x591D) | ||
49 | return true; | ||
48 | return false; | 50 | return false; |
49 | } | 51 | } |
50 | 52 | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 3eec74ca5116..1d623b5e09d6 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <drm/drm_atomic_helper.h> | 34 | #include <drm/drm_atomic_helper.h> |
35 | #include <drm/drm_crtc.h> | 35 | #include <drm/drm_crtc.h> |
36 | #include <drm/drm_edid.h> | 36 | #include <drm/drm_edid.h> |
37 | #include <drm/drm_scdc_helper.h> | ||
37 | #include "intel_drv.h" | 38 | #include "intel_drv.h" |
38 | #include <drm/i915_drm.h> | 39 | #include <drm/i915_drm.h> |
39 | #include <drm/intel_lpe_audio.h> | 40 | #include <drm/intel_lpe_audio.h> |
@@ -1208,6 +1209,8 @@ static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv) | |||
1208 | { | 1209 | { |
1209 | if (IS_G4X(dev_priv)) | 1210 | if (IS_G4X(dev_priv)) |
1210 | return 165000; | 1211 | return 165000; |
1212 | else if (IS_GEMINILAKE(dev_priv)) | ||
1213 | return 594000; | ||
1211 | else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) | 1214 | else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) |
1212 | return 300000; | 1215 | return 300000; |
1213 | else | 1216 | else |
@@ -1334,6 +1337,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, | |||
1334 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | 1337 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
1335 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 1338 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
1336 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | 1339 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
1340 | struct drm_scdc *scdc = &conn_state->connector->display_info.hdmi.scdc; | ||
1337 | int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; | 1341 | int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; |
1338 | int clock_12bpc = clock_8bpc * 3 / 2; | 1342 | int clock_12bpc = clock_8bpc * 3 / 2; |
1339 | int desired_bpp; | 1343 | int desired_bpp; |
@@ -1403,6 +1407,16 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, | |||
1403 | 1407 | ||
1404 | pipe_config->lane_count = 4; | 1408 | pipe_config->lane_count = 4; |
1405 | 1409 | ||
1410 | if (scdc->scrambling.supported && IS_GEMINILAKE(dev_priv)) { | ||
1411 | if (scdc->scrambling.low_rates) | ||
1412 | pipe_config->hdmi_scrambling = true; | ||
1413 | |||
1414 | if (pipe_config->port_clock > 340000) { | ||
1415 | pipe_config->hdmi_scrambling = true; | ||
1416 | pipe_config->hdmi_high_tmds_clock_ratio = true; | ||
1417 | } | ||
1418 | } | ||
1419 | |||
1406 | return true; | 1420 | return true; |
1407 | } | 1421 | } |
1408 | 1422 | ||
@@ -1812,6 +1826,57 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c | |||
1812 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; | 1826 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; |
1813 | } | 1827 | } |
1814 | 1828 | ||
1829 | /* | ||
1830 | * intel_hdmi_handle_sink_scrambling: handle sink scrambling/clock ratio setup | ||
1831 | * @encoder: intel_encoder | ||
1832 | * @connector: drm_connector | ||
1833 | * @high_tmds_clock_ratio = bool to indicate if the function needs to set | ||
1834 | * or reset the high tmds clock ratio for scrambling | ||
1835 | * @scrambling: bool to Indicate if the function needs to set or reset | ||
1836 | * sink scrambling | ||
1837 | * | ||
1838 | * This function handles scrambling on HDMI 2.0 capable sinks. | ||
1839 | * If required clock rate is > 340 Mhz && scrambling is supported by sink | ||
1840 | * it enables scrambling. This should be called before enabling the HDMI | ||
1841 | * 2.0 port, as the sink can choose to disable the scrambling if it doesn't | ||
1842 | * detect a scrambled clock within 100 ms. | ||
1843 | */ | ||
1844 | void intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, | ||
1845 | struct drm_connector *connector, | ||
1846 | bool high_tmds_clock_ratio, | ||
1847 | bool scrambling) | ||
1848 | { | ||
1849 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | ||
1850 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
1851 | struct drm_scrambling *sink_scrambling = | ||
1852 | &connector->display_info.hdmi.scdc.scrambling; | ||
1853 | struct i2c_adapter *adptr = intel_gmbus_get_adapter(dev_priv, | ||
1854 | intel_hdmi->ddc_bus); | ||
1855 | bool ret; | ||
1856 | |||
1857 | if (!sink_scrambling->supported) | ||
1858 | return; | ||
1859 | |||
1860 | DRM_DEBUG_KMS("Setting sink scrambling for enc:%s connector:%s\n", | ||
1861 | encoder->base.name, connector->name); | ||
1862 | |||
1863 | /* Set TMDS bit clock ratio to 1/40 or 1/10 */ | ||
1864 | ret = drm_scdc_set_high_tmds_clock_ratio(adptr, high_tmds_clock_ratio); | ||
1865 | if (!ret) { | ||
1866 | DRM_ERROR("Set TMDS ratio failed\n"); | ||
1867 | return; | ||
1868 | } | ||
1869 | |||
1870 | /* Enable/disable sink scrambling */ | ||
1871 | ret = drm_scdc_set_scrambling(adptr, scrambling); | ||
1872 | if (!ret) { | ||
1873 | DRM_ERROR("Set sink scrambling failed\n"); | ||
1874 | return; | ||
1875 | } | ||
1876 | |||
1877 | DRM_DEBUG_KMS("sink scrambling handled\n"); | ||
1878 | } | ||
1879 | |||
1815 | static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, | 1880 | static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, |
1816 | enum port port) | 1881 | enum port port) |
1817 | { | 1882 | { |
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 7af900bcdc05..9ee819666a4c 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c | |||
@@ -251,24 +251,6 @@ fail: | |||
251 | } | 251 | } |
252 | 252 | ||
253 | /** | 253 | /** |
254 | * intel_huc_fini() - clean up resources allocated for HuC | ||
255 | * @dev_priv: the drm_i915_private device | ||
256 | * | ||
257 | * Cleans up by releasing the huc firmware GEM obj. | ||
258 | */ | ||
259 | void intel_huc_fini(struct drm_i915_private *dev_priv) | ||
260 | { | ||
261 | struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; | ||
262 | struct drm_i915_gem_object *obj; | ||
263 | |||
264 | obj = fetch_and_zero(&huc_fw->obj); | ||
265 | if (obj) | ||
266 | i915_gem_object_put(obj); | ||
267 | |||
268 | huc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * intel_guc_auth_huc() - authenticate ucode | 254 | * intel_guc_auth_huc() - authenticate ucode |
273 | * @dev_priv: the drm_i915_device | 255 | * @dev_priv: the drm_i915_device |
274 | * | 256 | * |
diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 7a5b41b1c024..d8ca187ae001 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c | |||
@@ -331,6 +331,7 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) | |||
331 | * audio driver and i915 | 331 | * audio driver and i915 |
332 | * @dev_priv: the i915 drm device private data | 332 | * @dev_priv: the i915 drm device private data |
333 | * @eld : ELD data | 333 | * @eld : ELD data |
334 | * @pipe: pipe id | ||
334 | * @port: port id | 335 | * @port: port id |
335 | * @tmds_clk_speed: tmds clock frequency in Hz | 336 | * @tmds_clk_speed: tmds clock frequency in Hz |
336 | * | 337 | * |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 77168e673e0a..c8f7c631fc1f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -326,7 +326,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq) | |||
326 | rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; | 326 | rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; |
327 | u32 *reg_state = ce->lrc_reg_state; | 327 | u32 *reg_state = ce->lrc_reg_state; |
328 | 328 | ||
329 | GEM_BUG_ON(!IS_ALIGNED(rq->tail, 8)); | 329 | assert_ring_tail_valid(rq->ring, rq->tail); |
330 | reg_state[CTX_RING_TAIL+1] = rq->tail; | 330 | reg_state[CTX_RING_TAIL+1] = rq->tail; |
331 | 331 | ||
332 | /* True 32b PPGTT with dynamic page allocation: update PDP | 332 | /* True 32b PPGTT with dynamic page allocation: update PDP |
@@ -399,22 +399,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
399 | { | 399 | { |
400 | struct drm_i915_gem_request *last; | 400 | struct drm_i915_gem_request *last; |
401 | struct execlist_port *port = engine->execlist_port; | 401 | struct execlist_port *port = engine->execlist_port; |
402 | unsigned long flags; | ||
403 | struct rb_node *rb; | 402 | struct rb_node *rb; |
404 | bool submit = false; | 403 | bool submit = false; |
405 | 404 | ||
406 | /* After execlist_first is updated, the tasklet will be rescheduled. | ||
407 | * | ||
408 | * If we are currently running (inside the tasklet) and a third | ||
409 | * party queues a request and so updates engine->execlist_first under | ||
410 | * the spinlock (which we have elided), it will atomically set the | ||
411 | * TASKLET_SCHED flag causing the us to be re-executed and pick up | ||
412 | * the change in state (the update to TASKLET_SCHED incurs a memory | ||
413 | * barrier making this cross-cpu checking safe). | ||
414 | */ | ||
415 | if (!READ_ONCE(engine->execlist_first)) | ||
416 | return; | ||
417 | |||
418 | last = port->request; | 405 | last = port->request; |
419 | if (last) | 406 | if (last) |
420 | /* WaIdleLiteRestore:bdw,skl | 407 | /* WaIdleLiteRestore:bdw,skl |
@@ -448,7 +435,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
448 | * and context switches) submission. | 435 | * and context switches) submission. |
449 | */ | 436 | */ |
450 | 437 | ||
451 | spin_lock_irqsave(&engine->timeline->lock, flags); | 438 | spin_lock_irq(&engine->timeline->lock); |
452 | rb = engine->execlist_first; | 439 | rb = engine->execlist_first; |
453 | while (rb) { | 440 | while (rb) { |
454 | struct drm_i915_gem_request *cursor = | 441 | struct drm_i915_gem_request *cursor = |
@@ -500,7 +487,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
500 | i915_gem_request_assign(&port->request, last); | 487 | i915_gem_request_assign(&port->request, last); |
501 | engine->execlist_first = rb; | 488 | engine->execlist_first = rb; |
502 | } | 489 | } |
503 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 490 | spin_unlock_irq(&engine->timeline->lock); |
504 | 491 | ||
505 | if (submit) | 492 | if (submit) |
506 | execlists_submit_ports(engine); | 493 | execlists_submit_ports(engine); |
@@ -530,24 +517,36 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
530 | 517 | ||
531 | intel_uncore_forcewake_get(dev_priv, engine->fw_domains); | 518 | intel_uncore_forcewake_get(dev_priv, engine->fw_domains); |
532 | 519 | ||
533 | while (test_and_clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) { | 520 | /* Prefer doing test_and_clear_bit() as a two stage operation to avoid |
521 | * imposing the cost of a locked atomic transaction when submitting a | ||
522 | * new request (outside of the context-switch interrupt). | ||
523 | */ | ||
524 | while (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) { | ||
534 | u32 __iomem *csb_mmio = | 525 | u32 __iomem *csb_mmio = |
535 | dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); | 526 | dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); |
536 | u32 __iomem *buf = | 527 | u32 __iomem *buf = |
537 | dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)); | 528 | dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)); |
538 | unsigned int csb, head, tail; | 529 | unsigned int head, tail; |
539 | 530 | ||
540 | csb = readl(csb_mmio); | 531 | /* The write will be ordered by the uncached read (itself |
541 | head = GEN8_CSB_READ_PTR(csb); | 532 | * a memory barrier), so we do not need another in the form |
542 | tail = GEN8_CSB_WRITE_PTR(csb); | 533 | * of a locked instruction. The race between the interrupt |
543 | if (head == tail) | 534 | * handler and the split test/clear is harmless as we order |
544 | break; | 535 | * our clear before the CSB read. If the interrupt arrived |
536 | * first between the test and the clear, we read the updated | ||
537 | * CSB and clear the bit. If the interrupt arrives as we read | ||
538 | * the CSB or later (i.e. after we had cleared the bit) the bit | ||
539 | * is set and we do a new loop. | ||
540 | */ | ||
541 | __clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | ||
542 | head = readl(csb_mmio); | ||
543 | tail = GEN8_CSB_WRITE_PTR(head); | ||
544 | head = GEN8_CSB_READ_PTR(head); | ||
545 | while (head != tail) { | ||
546 | unsigned int status; | ||
545 | 547 | ||
546 | if (tail < head) | 548 | if (++head == GEN8_CSB_ENTRIES) |
547 | tail += GEN8_CSB_ENTRIES; | 549 | head = 0; |
548 | do { | ||
549 | unsigned int idx = ++head % GEN8_CSB_ENTRIES; | ||
550 | unsigned int status = readl(buf + 2 * idx); | ||
551 | 550 | ||
552 | /* We are flying near dragons again. | 551 | /* We are flying near dragons again. |
553 | * | 552 | * |
@@ -566,11 +565,12 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
566 | * status notifier. | 565 | * status notifier. |
567 | */ | 566 | */ |
568 | 567 | ||
568 | status = readl(buf + 2 * head); | ||
569 | if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) | 569 | if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) |
570 | continue; | 570 | continue; |
571 | 571 | ||
572 | /* Check the context/desc id for this event matches */ | 572 | /* Check the context/desc id for this event matches */ |
573 | GEM_DEBUG_BUG_ON(readl(buf + 2 * idx + 1) != | 573 | GEM_DEBUG_BUG_ON(readl(buf + 2 * head + 1) != |
574 | port[0].context_id); | 574 | port[0].context_id); |
575 | 575 | ||
576 | GEM_BUG_ON(port[0].count == 0); | 576 | GEM_BUG_ON(port[0].count == 0); |
@@ -588,10 +588,9 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
588 | 588 | ||
589 | GEM_BUG_ON(port[0].count == 0 && | 589 | GEM_BUG_ON(port[0].count == 0 && |
590 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); | 590 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); |
591 | } while (head < tail); | 591 | } |
592 | 592 | ||
593 | writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, | 593 | writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), |
594 | GEN8_CSB_WRITE_PTR(csb) << 8), | ||
595 | csb_mmio); | 594 | csb_mmio); |
596 | } | 595 | } |
597 | 596 | ||
@@ -647,15 +646,14 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) | |||
647 | static struct intel_engine_cs * | 646 | static struct intel_engine_cs * |
648 | pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked) | 647 | pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked) |
649 | { | 648 | { |
650 | struct intel_engine_cs *engine; | 649 | struct intel_engine_cs *engine = |
650 | container_of(pt, struct drm_i915_gem_request, priotree)->engine; | ||
651 | |||
652 | GEM_BUG_ON(!locked); | ||
651 | 653 | ||
652 | engine = container_of(pt, | ||
653 | struct drm_i915_gem_request, | ||
654 | priotree)->engine; | ||
655 | if (engine != locked) { | 654 | if (engine != locked) { |
656 | if (locked) | 655 | spin_unlock(&locked->timeline->lock); |
657 | spin_unlock_irq(&locked->timeline->lock); | 656 | spin_lock(&engine->timeline->lock); |
658 | spin_lock_irq(&engine->timeline->lock); | ||
659 | } | 657 | } |
660 | 658 | ||
661 | return engine; | 659 | return engine; |
@@ -663,7 +661,7 @@ pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked) | |||
663 | 661 | ||
664 | static void execlists_schedule(struct drm_i915_gem_request *request, int prio) | 662 | static void execlists_schedule(struct drm_i915_gem_request *request, int prio) |
665 | { | 663 | { |
666 | struct intel_engine_cs *engine = NULL; | 664 | struct intel_engine_cs *engine; |
667 | struct i915_dependency *dep, *p; | 665 | struct i915_dependency *dep, *p; |
668 | struct i915_dependency stack; | 666 | struct i915_dependency stack; |
669 | LIST_HEAD(dfs); | 667 | LIST_HEAD(dfs); |
@@ -697,26 +695,23 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) | |||
697 | list_for_each_entry_safe(dep, p, &dfs, dfs_link) { | 695 | list_for_each_entry_safe(dep, p, &dfs, dfs_link) { |
698 | struct i915_priotree *pt = dep->signaler; | 696 | struct i915_priotree *pt = dep->signaler; |
699 | 697 | ||
700 | list_for_each_entry(p, &pt->signalers_list, signal_link) | 698 | /* Within an engine, there can be no cycle, but we may |
699 | * refer to the same dependency chain multiple times | ||
700 | * (redundant dependencies are not eliminated) and across | ||
701 | * engines. | ||
702 | */ | ||
703 | list_for_each_entry(p, &pt->signalers_list, signal_link) { | ||
704 | GEM_BUG_ON(p->signaler->priority < pt->priority); | ||
701 | if (prio > READ_ONCE(p->signaler->priority)) | 705 | if (prio > READ_ONCE(p->signaler->priority)) |
702 | list_move_tail(&p->dfs_link, &dfs); | 706 | list_move_tail(&p->dfs_link, &dfs); |
707 | } | ||
703 | 708 | ||
704 | list_safe_reset_next(dep, p, dfs_link); | 709 | list_safe_reset_next(dep, p, dfs_link); |
705 | if (!RB_EMPTY_NODE(&pt->node)) | ||
706 | continue; | ||
707 | |||
708 | engine = pt_lock_engine(pt, engine); | ||
709 | |||
710 | /* If it is not already in the rbtree, we can update the | ||
711 | * priority inplace and skip over it (and its dependencies) | ||
712 | * if it is referenced *again* as we descend the dfs. | ||
713 | */ | ||
714 | if (prio > pt->priority && RB_EMPTY_NODE(&pt->node)) { | ||
715 | pt->priority = prio; | ||
716 | list_del_init(&dep->dfs_link); | ||
717 | } | ||
718 | } | 710 | } |
719 | 711 | ||
712 | engine = request->engine; | ||
713 | spin_lock_irq(&engine->timeline->lock); | ||
714 | |||
720 | /* Fifo and depth-first replacement ensure our deps execute before us */ | 715 | /* Fifo and depth-first replacement ensure our deps execute before us */ |
721 | list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) { | 716 | list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) { |
722 | struct i915_priotree *pt = dep->signaler; | 717 | struct i915_priotree *pt = dep->signaler; |
@@ -728,16 +723,15 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) | |||
728 | if (prio <= pt->priority) | 723 | if (prio <= pt->priority) |
729 | continue; | 724 | continue; |
730 | 725 | ||
731 | GEM_BUG_ON(RB_EMPTY_NODE(&pt->node)); | ||
732 | |||
733 | pt->priority = prio; | 726 | pt->priority = prio; |
734 | rb_erase(&pt->node, &engine->execlist_queue); | 727 | if (!RB_EMPTY_NODE(&pt->node)) { |
735 | if (insert_request(pt, &engine->execlist_queue)) | 728 | rb_erase(&pt->node, &engine->execlist_queue); |
736 | engine->execlist_first = &pt->node; | 729 | if (insert_request(pt, &engine->execlist_queue)) |
730 | engine->execlist_first = &pt->node; | ||
731 | } | ||
737 | } | 732 | } |
738 | 733 | ||
739 | if (engine) | 734 | spin_unlock_irq(&engine->timeline->lock); |
740 | spin_unlock_irq(&engine->timeline->lock); | ||
741 | 735 | ||
742 | /* XXX Do we need to preempt to make room for us and our deps? */ | 736 | /* XXX Do we need to preempt to make room for us and our deps? */ |
743 | } | 737 | } |
@@ -1255,7 +1249,6 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1255 | ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; | 1249 | ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; |
1256 | 1250 | ||
1257 | request->ring->head = request->postfix; | 1251 | request->ring->head = request->postfix; |
1258 | request->ring->last_retired_head = -1; | ||
1259 | intel_ring_update_space(request->ring); | 1252 | intel_ring_update_space(request->ring); |
1260 | 1253 | ||
1261 | /* Catch up with any missed context-switch interrupts */ | 1254 | /* Catch up with any missed context-switch interrupts */ |
@@ -1268,8 +1261,10 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1268 | GEM_BUG_ON(request->ctx != port[0].request->ctx); | 1261 | GEM_BUG_ON(request->ctx != port[0].request->ctx); |
1269 | 1262 | ||
1270 | /* Reset WaIdleLiteRestore:bdw,skl as well */ | 1263 | /* Reset WaIdleLiteRestore:bdw,skl as well */ |
1271 | request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); | 1264 | request->tail = |
1272 | GEM_BUG_ON(!IS_ALIGNED(request->tail, 8)); | 1265 | intel_ring_wrap(request->ring, |
1266 | request->wa_tail - WA_TAIL_DWORDS*sizeof(u32)); | ||
1267 | assert_ring_tail_valid(request->ring, request->tail); | ||
1273 | } | 1268 | } |
1274 | 1269 | ||
1275 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) | 1270 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) |
@@ -1480,7 +1475,7 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs) | |||
1480 | *cs++ = MI_USER_INTERRUPT; | 1475 | *cs++ = MI_USER_INTERRUPT; |
1481 | *cs++ = MI_NOOP; | 1476 | *cs++ = MI_NOOP; |
1482 | request->tail = intel_ring_offset(request, cs); | 1477 | request->tail = intel_ring_offset(request, cs); |
1483 | GEM_BUG_ON(!IS_ALIGNED(request->tail, 8)); | 1478 | assert_ring_tail_valid(request->ring, request->tail); |
1484 | 1479 | ||
1485 | gen8_emit_wa_tail(request, cs); | 1480 | gen8_emit_wa_tail(request, cs); |
1486 | } | 1481 | } |
@@ -1508,7 +1503,7 @@ static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, | |||
1508 | *cs++ = MI_USER_INTERRUPT; | 1503 | *cs++ = MI_USER_INTERRUPT; |
1509 | *cs++ = MI_NOOP; | 1504 | *cs++ = MI_NOOP; |
1510 | request->tail = intel_ring_offset(request, cs); | 1505 | request->tail = intel_ring_offset(request, cs); |
1511 | GEM_BUG_ON(!IS_ALIGNED(request->tail, 8)); | 1506 | assert_ring_tail_valid(request->ring, request->tail); |
1512 | 1507 | ||
1513 | gen8_emit_wa_tail(request, cs); | 1508 | gen8_emit_wa_tail(request, cs); |
1514 | } | 1509 | } |
@@ -1575,6 +1570,7 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) | |||
1575 | { | 1570 | { |
1576 | engine->submit_request = execlists_submit_request; | 1571 | engine->submit_request = execlists_submit_request; |
1577 | engine->schedule = execlists_schedule; | 1572 | engine->schedule = execlists_schedule; |
1573 | engine->irq_tasklet.func = intel_lrc_irq_handler; | ||
1578 | } | 1574 | } |
1579 | 1575 | ||
1580 | static void | 1576 | static void |
@@ -2041,7 +2037,6 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) | |||
2041 | i915_gem_object_unpin_map(ce->state->obj); | 2037 | i915_gem_object_unpin_map(ce->state->obj); |
2042 | 2038 | ||
2043 | ce->ring->head = ce->ring->tail = 0; | 2039 | ce->ring->head = ce->ring->tail = 0; |
2044 | ce->ring->last_retired_head = -1; | ||
2045 | intel_ring_update_space(ce->ring); | 2040 | intel_ring_update_space(ce->ring); |
2046 | } | 2041 | } |
2047 | } | 2042 | } |
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 441c01466384..d44465190dc1 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -920,6 +920,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) | |||
920 | char buf[sizeof(OPREGION_SIGNATURE)]; | 920 | char buf[sizeof(OPREGION_SIGNATURE)]; |
921 | int err = 0; | 921 | int err = 0; |
922 | void *base; | 922 | void *base; |
923 | const void *vbt; | ||
924 | u32 vbt_size; | ||
923 | 925 | ||
924 | BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100); | 926 | BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100); |
925 | BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100); | 927 | BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100); |
@@ -972,45 +974,46 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) | |||
972 | if (mboxes & MBOX_ASLE_EXT) | 974 | if (mboxes & MBOX_ASLE_EXT) |
973 | DRM_DEBUG_DRIVER("ASLE extension supported\n"); | 975 | DRM_DEBUG_DRIVER("ASLE extension supported\n"); |
974 | 976 | ||
975 | if (!dmi_check_system(intel_no_opregion_vbt)) { | 977 | if (dmi_check_system(intel_no_opregion_vbt)) |
976 | const void *vbt = NULL; | 978 | goto out; |
977 | u32 vbt_size = 0; | ||
978 | |||
979 | if (opregion->header->opregion_ver >= 2 && opregion->asle && | ||
980 | opregion->asle->rvda && opregion->asle->rvds) { | ||
981 | opregion->rvda = memremap(opregion->asle->rvda, | ||
982 | opregion->asle->rvds, | ||
983 | MEMREMAP_WB); | ||
984 | vbt = opregion->rvda; | ||
985 | vbt_size = opregion->asle->rvds; | ||
986 | } | ||
987 | 979 | ||
980 | if (opregion->header->opregion_ver >= 2 && opregion->asle && | ||
981 | opregion->asle->rvda && opregion->asle->rvds) { | ||
982 | opregion->rvda = memremap(opregion->asle->rvda, | ||
983 | opregion->asle->rvds, | ||
984 | MEMREMAP_WB); | ||
985 | vbt = opregion->rvda; | ||
986 | vbt_size = opregion->asle->rvds; | ||
988 | if (intel_bios_is_valid_vbt(vbt, vbt_size)) { | 987 | if (intel_bios_is_valid_vbt(vbt, vbt_size)) { |
989 | DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n"); | 988 | DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n"); |
990 | opregion->vbt = vbt; | 989 | opregion->vbt = vbt; |
991 | opregion->vbt_size = vbt_size; | 990 | opregion->vbt_size = vbt_size; |
991 | goto out; | ||
992 | } else { | 992 | } else { |
993 | vbt = base + OPREGION_VBT_OFFSET; | 993 | DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n"); |
994 | /* | ||
995 | * The VBT specification says that if the ASLE ext | ||
996 | * mailbox is not used its area is reserved, but | ||
997 | * on some CHT boards the VBT extends into the | ||
998 | * ASLE ext area. Allow this even though it is | ||
999 | * against the spec, so we do not end up rejecting | ||
1000 | * the VBT on those boards (and end up not finding the | ||
1001 | * LCD panel because of this). | ||
1002 | */ | ||
1003 | vbt_size = (mboxes & MBOX_ASLE_EXT) ? | ||
1004 | OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE; | ||
1005 | vbt_size -= OPREGION_VBT_OFFSET; | ||
1006 | if (intel_bios_is_valid_vbt(vbt, vbt_size)) { | ||
1007 | DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n"); | ||
1008 | opregion->vbt = vbt; | ||
1009 | opregion->vbt_size = vbt_size; | ||
1010 | } | ||
1011 | } | 994 | } |
1012 | } | 995 | } |
1013 | 996 | ||
997 | vbt = base + OPREGION_VBT_OFFSET; | ||
998 | /* | ||
999 | * The VBT specification says that if the ASLE ext mailbox is not used | ||
1000 | * its area is reserved, but on some CHT boards the VBT extends into the | ||
1001 | * ASLE ext area. Allow this even though it is against the spec, so we | ||
1002 | * do not end up rejecting the VBT on those boards (and end up not | ||
1003 | * finding the LCD panel because of this). | ||
1004 | */ | ||
1005 | vbt_size = (mboxes & MBOX_ASLE_EXT) ? | ||
1006 | OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE; | ||
1007 | vbt_size -= OPREGION_VBT_OFFSET; | ||
1008 | if (intel_bios_is_valid_vbt(vbt, vbt_size)) { | ||
1009 | DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n"); | ||
1010 | opregion->vbt = vbt; | ||
1011 | opregion->vbt_size = vbt_size; | ||
1012 | } else { | ||
1013 | DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (Mailbox #4)\n"); | ||
1014 | } | ||
1015 | |||
1016 | out: | ||
1014 | return 0; | 1017 | return 0; |
1015 | 1018 | ||
1016 | err_out: | 1019 | err_out: |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aece0ff88a5d..570bd603f401 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -655,6 +655,29 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | |||
655 | return wm_size; | 655 | return wm_size; |
656 | } | 656 | } |
657 | 657 | ||
658 | static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, | ||
659 | const struct intel_plane_state *plane_state) | ||
660 | { | ||
661 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
662 | |||
663 | /* FIXME check the 'enable' instead */ | ||
664 | if (!crtc_state->base.active) | ||
665 | return false; | ||
666 | |||
667 | /* | ||
668 | * Treat cursor with fb as always visible since cursor updates | ||
669 | * can happen faster than the vrefresh rate, and the current | ||
670 | * watermark code doesn't handle that correctly. Cursor updates | ||
671 | * which set/clear the fb or change the cursor size are going | ||
672 | * to get throttled by intel_legacy_cursor_update() to work | ||
673 | * around this problem with the watermark code. | ||
674 | */ | ||
675 | if (plane->id == PLANE_CURSOR) | ||
676 | return plane_state->base.fb != NULL; | ||
677 | else | ||
678 | return plane_state->base.visible; | ||
679 | } | ||
680 | |||
658 | static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv) | 681 | static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv) |
659 | { | 682 | { |
660 | struct intel_crtc *crtc, *enabled = NULL; | 683 | struct intel_crtc *crtc, *enabled = NULL; |
@@ -1961,7 +1984,7 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, | |||
1961 | uint32_t method1, method2; | 1984 | uint32_t method1, method2; |
1962 | int cpp; | 1985 | int cpp; |
1963 | 1986 | ||
1964 | if (!cstate->base.active || !pstate->base.visible) | 1987 | if (!intel_wm_plane_visible(cstate, pstate)) |
1965 | return 0; | 1988 | return 0; |
1966 | 1989 | ||
1967 | cpp = pstate->base.fb->format->cpp[0]; | 1990 | cpp = pstate->base.fb->format->cpp[0]; |
@@ -1990,7 +2013,7 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate, | |||
1990 | uint32_t method1, method2; | 2013 | uint32_t method1, method2; |
1991 | int cpp; | 2014 | int cpp; |
1992 | 2015 | ||
1993 | if (!cstate->base.active || !pstate->base.visible) | 2016 | if (!intel_wm_plane_visible(cstate, pstate)) |
1994 | return 0; | 2017 | return 0; |
1995 | 2018 | ||
1996 | cpp = pstate->base.fb->format->cpp[0]; | 2019 | cpp = pstate->base.fb->format->cpp[0]; |
@@ -2013,15 +2036,7 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, | |||
2013 | { | 2036 | { |
2014 | int cpp; | 2037 | int cpp; |
2015 | 2038 | ||
2016 | /* | 2039 | if (!intel_wm_plane_visible(cstate, pstate)) |
2017 | * Treat cursor with fb as always visible since cursor updates | ||
2018 | * can happen faster than the vrefresh rate, and the current | ||
2019 | * watermark code doesn't handle that correctly. Cursor updates | ||
2020 | * which set/clear the fb or change the cursor size are going | ||
2021 | * to get throttled by intel_legacy_cursor_update() to work | ||
2022 | * around this problem with the watermark code. | ||
2023 | */ | ||
2024 | if (!cstate->base.active || !pstate->base.fb) | ||
2025 | return 0; | 2040 | return 0; |
2026 | 2041 | ||
2027 | cpp = pstate->base.fb->format->cpp[0]; | 2042 | cpp = pstate->base.fb->format->cpp[0]; |
@@ -2038,7 +2053,7 @@ static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate, | |||
2038 | { | 2053 | { |
2039 | int cpp; | 2054 | int cpp; |
2040 | 2055 | ||
2041 | if (!cstate->base.active || !pstate->base.visible) | 2056 | if (!intel_wm_plane_visible(cstate, pstate)) |
2042 | return 0; | 2057 | return 0; |
2043 | 2058 | ||
2044 | cpp = pstate->base.fb->format->cpp[0]; | 2059 | cpp = pstate->base.fb->format->cpp[0]; |
@@ -3346,19 +3361,29 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | |||
3346 | * Caller should take care of dividing & rounding off the value. | 3361 | * Caller should take care of dividing & rounding off the value. |
3347 | */ | 3362 | */ |
3348 | static uint32_t | 3363 | static uint32_t |
3349 | skl_plane_downscale_amount(const struct intel_plane_state *pstate) | 3364 | skl_plane_downscale_amount(const struct intel_crtc_state *cstate, |
3365 | const struct intel_plane_state *pstate) | ||
3350 | { | 3366 | { |
3367 | struct intel_plane *plane = to_intel_plane(pstate->base.plane); | ||
3351 | uint32_t downscale_h, downscale_w; | 3368 | uint32_t downscale_h, downscale_w; |
3352 | uint32_t src_w, src_h, dst_w, dst_h; | 3369 | uint32_t src_w, src_h, dst_w, dst_h; |
3353 | 3370 | ||
3354 | if (WARN_ON(!pstate->base.visible)) | 3371 | if (WARN_ON(!intel_wm_plane_visible(cstate, pstate))) |
3355 | return DRM_PLANE_HELPER_NO_SCALING; | 3372 | return DRM_PLANE_HELPER_NO_SCALING; |
3356 | 3373 | ||
3357 | /* n.b., src is 16.16 fixed point, dst is whole integer */ | 3374 | /* n.b., src is 16.16 fixed point, dst is whole integer */ |
3358 | src_w = drm_rect_width(&pstate->base.src); | 3375 | if (plane->id == PLANE_CURSOR) { |
3359 | src_h = drm_rect_height(&pstate->base.src); | 3376 | src_w = pstate->base.src_w; |
3360 | dst_w = drm_rect_width(&pstate->base.dst); | 3377 | src_h = pstate->base.src_h; |
3361 | dst_h = drm_rect_height(&pstate->base.dst); | 3378 | dst_w = pstate->base.crtc_w; |
3379 | dst_h = pstate->base.crtc_h; | ||
3380 | } else { | ||
3381 | src_w = drm_rect_width(&pstate->base.src); | ||
3382 | src_h = drm_rect_height(&pstate->base.src); | ||
3383 | dst_w = drm_rect_width(&pstate->base.dst); | ||
3384 | dst_h = drm_rect_height(&pstate->base.dst); | ||
3385 | } | ||
3386 | |||
3362 | if (drm_rotation_90_or_270(pstate->base.rotation)) | 3387 | if (drm_rotation_90_or_270(pstate->base.rotation)) |
3363 | swap(dst_w, dst_h); | 3388 | swap(dst_w, dst_h); |
3364 | 3389 | ||
@@ -3374,6 +3399,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
3374 | const struct drm_plane_state *pstate, | 3399 | const struct drm_plane_state *pstate, |
3375 | int y) | 3400 | int y) |
3376 | { | 3401 | { |
3402 | struct intel_plane *plane = to_intel_plane(pstate->plane); | ||
3377 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); | 3403 | struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); |
3378 | uint32_t down_scale_amount, data_rate; | 3404 | uint32_t down_scale_amount, data_rate; |
3379 | uint32_t width = 0, height = 0; | 3405 | uint32_t width = 0, height = 0; |
@@ -3386,7 +3412,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
3386 | fb = pstate->fb; | 3412 | fb = pstate->fb; |
3387 | format = fb->format->format; | 3413 | format = fb->format->format; |
3388 | 3414 | ||
3389 | if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR) | 3415 | if (plane->id == PLANE_CURSOR) |
3390 | return 0; | 3416 | return 0; |
3391 | if (y && format != DRM_FORMAT_NV12) | 3417 | if (y && format != DRM_FORMAT_NV12) |
3392 | return 0; | 3418 | return 0; |
@@ -3410,7 +3436,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
3410 | data_rate = width * height * fb->format->cpp[0]; | 3436 | data_rate = width * height * fb->format->cpp[0]; |
3411 | } | 3437 | } |
3412 | 3438 | ||
3413 | down_scale_amount = skl_plane_downscale_amount(intel_pstate); | 3439 | down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate); |
3414 | 3440 | ||
3415 | return (uint64_t)data_rate * down_scale_amount >> 16; | 3441 | return (uint64_t)data_rate * down_scale_amount >> 16; |
3416 | } | 3442 | } |
@@ -3702,7 +3728,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst | |||
3702 | uint64_t pixel_rate; | 3728 | uint64_t pixel_rate; |
3703 | 3729 | ||
3704 | /* Shouldn't reach here on disabled planes... */ | 3730 | /* Shouldn't reach here on disabled planes... */ |
3705 | if (WARN_ON(!pstate->base.visible)) | 3731 | if (WARN_ON(!intel_wm_plane_visible(cstate, pstate))) |
3706 | return 0; | 3732 | return 0; |
3707 | 3733 | ||
3708 | /* | 3734 | /* |
@@ -3710,7 +3736,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst | |||
3710 | * with additional adjustments for plane-specific scaling. | 3736 | * with additional adjustments for plane-specific scaling. |
3711 | */ | 3737 | */ |
3712 | adjusted_pixel_rate = cstate->pixel_rate; | 3738 | adjusted_pixel_rate = cstate->pixel_rate; |
3713 | downscale_amount = skl_plane_downscale_amount(pstate); | 3739 | downscale_amount = skl_plane_downscale_amount(cstate, pstate); |
3714 | 3740 | ||
3715 | pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; | 3741 | pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; |
3716 | WARN_ON(pixel_rate != clamp_t(uint32_t, pixel_rate, 0, ~0)); | 3742 | WARN_ON(pixel_rate != clamp_t(uint32_t, pixel_rate, 0, ~0)); |
@@ -3727,6 +3753,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
3727 | uint8_t *out_lines, /* out */ | 3753 | uint8_t *out_lines, /* out */ |
3728 | bool *enabled /* out */) | 3754 | bool *enabled /* out */) |
3729 | { | 3755 | { |
3756 | struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); | ||
3730 | struct drm_plane_state *pstate = &intel_pstate->base; | 3757 | struct drm_plane_state *pstate = &intel_pstate->base; |
3731 | struct drm_framebuffer *fb = pstate->fb; | 3758 | struct drm_framebuffer *fb = pstate->fb; |
3732 | uint32_t latency = dev_priv->wm.skl_latency[level]; | 3759 | uint32_t latency = dev_priv->wm.skl_latency[level]; |
@@ -3746,7 +3773,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
3746 | bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); | 3773 | bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); |
3747 | bool y_tiled, x_tiled; | 3774 | bool y_tiled, x_tiled; |
3748 | 3775 | ||
3749 | if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { | 3776 | if (latency == 0 || |
3777 | !intel_wm_plane_visible(cstate, intel_pstate)) { | ||
3750 | *enabled = false; | 3778 | *enabled = false; |
3751 | return 0; | 3779 | return 0; |
3752 | } | 3780 | } |
@@ -3762,8 +3790,13 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
3762 | if (apply_memory_bw_wa && x_tiled) | 3790 | if (apply_memory_bw_wa && x_tiled) |
3763 | latency += 15; | 3791 | latency += 15; |
3764 | 3792 | ||
3765 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | 3793 | if (plane->id == PLANE_CURSOR) { |
3766 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | 3794 | width = intel_pstate->base.crtc_w; |
3795 | height = intel_pstate->base.crtc_h; | ||
3796 | } else { | ||
3797 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | ||
3798 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | ||
3799 | } | ||
3767 | 3800 | ||
3768 | if (drm_rotation_90_or_270(pstate->rotation)) | 3801 | if (drm_rotation_90_or_270(pstate->rotation)) |
3769 | swap(width, height); | 3802 | swap(width, height); |
@@ -8055,7 +8088,7 @@ static inline int gen6_check_mailbox_status(struct drm_i915_private *dev_priv) | |||
8055 | case GEN6_PCODE_TIMEOUT: | 8088 | case GEN6_PCODE_TIMEOUT: |
8056 | return -ETIMEDOUT; | 8089 | return -ETIMEDOUT; |
8057 | default: | 8090 | default: |
8058 | MISSING_CASE(flags) | 8091 | MISSING_CASE(flags); |
8059 | return 0; | 8092 | return 0; |
8060 | } | 8093 | } |
8061 | } | 8094 | } |
@@ -8355,6 +8388,7 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, | |||
8355 | const i915_reg_t reg) | 8388 | const i915_reg_t reg) |
8356 | { | 8389 | { |
8357 | u32 lower, upper, tmp; | 8390 | u32 lower, upper, tmp; |
8391 | int loop = 2; | ||
8358 | 8392 | ||
8359 | /* The register accessed do not need forcewake. We borrow | 8393 | /* The register accessed do not need forcewake. We borrow |
8360 | * uncore lock to prevent concurrent access to range reg. | 8394 | * uncore lock to prevent concurrent access to range reg. |
@@ -8383,7 +8417,7 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, | |||
8383 | I915_WRITE_FW(VLV_COUNTER_CONTROL, | 8417 | I915_WRITE_FW(VLV_COUNTER_CONTROL, |
8384 | _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH)); | 8418 | _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH)); |
8385 | upper = I915_READ_FW(reg); | 8419 | upper = I915_READ_FW(reg); |
8386 | } while (upper != tmp); | 8420 | } while (upper != tmp && --loop); |
8387 | 8421 | ||
8388 | /* Everywhere else we always use VLV_COUNTER_CONTROL with the | 8422 | /* Everywhere else we always use VLV_COUNTER_CONTROL with the |
8389 | * VLV_COUNT_RANGE_HIGH bit set - so it is safe to leave it set | 8423 | * VLV_COUNT_RANGE_HIGH bit set - so it is safe to leave it set |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d9b8d17c3fc6..66a2b8b83972 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -49,13 +49,7 @@ static int __intel_ring_space(int head, int tail, int size) | |||
49 | 49 | ||
50 | void intel_ring_update_space(struct intel_ring *ring) | 50 | void intel_ring_update_space(struct intel_ring *ring) |
51 | { | 51 | { |
52 | if (ring->last_retired_head != -1) { | 52 | ring->space = __intel_ring_space(ring->head, ring->tail, ring->size); |
53 | ring->head = ring->last_retired_head; | ||
54 | ring->last_retired_head = -1; | ||
55 | } | ||
56 | |||
57 | ring->space = __intel_ring_space(ring->head & HEAD_ADDR, | ||
58 | ring->tail, ring->size); | ||
59 | } | 53 | } |
60 | 54 | ||
61 | static int | 55 | static int |
@@ -618,12 +612,8 @@ static void reset_ring_common(struct intel_engine_cs *engine, | |||
618 | } | 612 | } |
619 | 613 | ||
620 | /* If the rq hung, jump to its breadcrumb and skip the batch */ | 614 | /* If the rq hung, jump to its breadcrumb and skip the batch */ |
621 | if (request->fence.error == -EIO) { | 615 | if (request->fence.error == -EIO) |
622 | struct intel_ring *ring = request->ring; | 616 | request->ring->head = request->postfix; |
623 | |||
624 | ring->head = request->postfix; | ||
625 | ring->last_retired_head = -1; | ||
626 | } | ||
627 | } else { | 617 | } else { |
628 | engine->legacy_active_context = NULL; | 618 | engine->legacy_active_context = NULL; |
629 | } | 619 | } |
@@ -784,7 +774,7 @@ static void i9xx_submit_request(struct drm_i915_gem_request *request) | |||
784 | 774 | ||
785 | i915_gem_request_submit(request); | 775 | i915_gem_request_submit(request); |
786 | 776 | ||
787 | GEM_BUG_ON(!IS_ALIGNED(request->tail, 8)); | 777 | assert_ring_tail_valid(request->ring, request->tail); |
788 | I915_WRITE_TAIL(request->engine, request->tail); | 778 | I915_WRITE_TAIL(request->engine, request->tail); |
789 | } | 779 | } |
790 | 780 | ||
@@ -796,7 +786,7 @@ static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) | |||
796 | *cs++ = MI_USER_INTERRUPT; | 786 | *cs++ = MI_USER_INTERRUPT; |
797 | 787 | ||
798 | req->tail = intel_ring_offset(req, cs); | 788 | req->tail = intel_ring_offset(req, cs); |
799 | GEM_BUG_ON(!IS_ALIGNED(req->tail, 8)); | 789 | assert_ring_tail_valid(req->ring, req->tail); |
800 | } | 790 | } |
801 | 791 | ||
802 | static const int i9xx_emit_breadcrumb_sz = 4; | 792 | static const int i9xx_emit_breadcrumb_sz = 4; |
@@ -835,7 +825,7 @@ static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req, | |||
835 | *cs++ = MI_NOOP; | 825 | *cs++ = MI_NOOP; |
836 | 826 | ||
837 | req->tail = intel_ring_offset(req, cs); | 827 | req->tail = intel_ring_offset(req, cs); |
838 | GEM_BUG_ON(!IS_ALIGNED(req->tail, 8)); | 828 | assert_ring_tail_valid(req->ring, req->tail); |
839 | } | 829 | } |
840 | 830 | ||
841 | static const int gen8_render_emit_breadcrumb_sz = 8; | 831 | static const int gen8_render_emit_breadcrumb_sz = 8; |
@@ -1392,7 +1382,6 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) | |||
1392 | if (IS_I830(engine->i915) || IS_I845G(engine->i915)) | 1382 | if (IS_I830(engine->i915) || IS_I845G(engine->i915)) |
1393 | ring->effective_size -= 2 * CACHELINE_BYTES; | 1383 | ring->effective_size -= 2 * CACHELINE_BYTES; |
1394 | 1384 | ||
1395 | ring->last_retired_head = -1; | ||
1396 | intel_ring_update_space(ring); | 1385 | intel_ring_update_space(ring); |
1397 | 1386 | ||
1398 | vma = intel_ring_create_vma(engine->i915, size); | 1387 | vma = intel_ring_create_vma(engine->i915, size); |
@@ -1451,6 +1440,8 @@ static int intel_ring_context_pin(struct intel_engine_cs *engine, | |||
1451 | ret = context_pin(ctx); | 1440 | ret = context_pin(ctx); |
1452 | if (ret) | 1441 | if (ret) |
1453 | goto error; | 1442 | goto error; |
1443 | |||
1444 | ce->state->obj->mm.dirty = true; | ||
1454 | } | 1445 | } |
1455 | 1446 | ||
1456 | /* The kernel context is only used as a placeholder for flushing the | 1447 | /* The kernel context is only used as a placeholder for flushing the |
@@ -1571,10 +1562,8 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) | |||
1571 | struct intel_engine_cs *engine; | 1562 | struct intel_engine_cs *engine; |
1572 | enum intel_engine_id id; | 1563 | enum intel_engine_id id; |
1573 | 1564 | ||
1574 | for_each_engine(engine, dev_priv, id) { | 1565 | for_each_engine(engine, dev_priv, id) |
1575 | engine->buffer->head = engine->buffer->tail; | 1566 | engine->buffer->head = engine->buffer->tail; |
1576 | engine->buffer->last_retired_head = -1; | ||
1577 | } | ||
1578 | } | 1567 | } |
1579 | 1568 | ||
1580 | static int ring_request_alloc(struct drm_i915_gem_request *request) | 1569 | static int ring_request_alloc(struct drm_i915_gem_request *request) |
@@ -2128,7 +2117,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) | |||
2128 | 2117 | ||
2129 | num_rings = | 2118 | num_rings = |
2130 | hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; | 2119 | hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; |
2131 | engine->emit_breadcrumb_sz += num_rings * 6; | 2120 | engine->emit_breadcrumb_sz += num_rings * 8; |
2132 | } | 2121 | } |
2133 | } else if (INTEL_GEN(dev_priv) >= 6) { | 2122 | } else if (INTEL_GEN(dev_priv) >= 6) { |
2134 | engine->init_context = intel_rcs_ctx_init; | 2123 | engine->init_context = intel_rcs_ctx_init; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 847aea554464..a82a0807f64d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -149,16 +149,6 @@ struct intel_ring { | |||
149 | int space; | 149 | int space; |
150 | int size; | 150 | int size; |
151 | int effective_size; | 151 | int effective_size; |
152 | |||
153 | /** We track the position of the requests in the ring buffer, and | ||
154 | * when each is retired we increment last_retired_head as the GPU | ||
155 | * must have finished processing the request and so we know we | ||
156 | * can advance the ringbuffer up to that position. | ||
157 | * | ||
158 | * last_retired_head is set to -1 after the value is consumed so | ||
159 | * we can detect new retirements. | ||
160 | */ | ||
161 | u32 last_retired_head; | ||
162 | }; | 152 | }; |
163 | 153 | ||
164 | struct i915_gem_context; | 154 | struct i915_gem_context; |
@@ -442,18 +432,10 @@ struct intel_engine_cs { | |||
442 | u32 (*get_cmd_length_mask)(u32 cmd_header); | 432 | u32 (*get_cmd_length_mask)(u32 cmd_header); |
443 | }; | 433 | }; |
444 | 434 | ||
445 | static inline unsigned | 435 | static inline unsigned int |
446 | intel_engine_flag(const struct intel_engine_cs *engine) | 436 | intel_engine_flag(const struct intel_engine_cs *engine) |
447 | { | 437 | { |
448 | return 1 << engine->id; | 438 | return BIT(engine->id); |
449 | } | ||
450 | |||
451 | static inline void | ||
452 | intel_flush_status_page(struct intel_engine_cs *engine, int reg) | ||
453 | { | ||
454 | mb(); | ||
455 | clflush(&engine->status_page.page_addr[reg]); | ||
456 | mb(); | ||
457 | } | 439 | } |
458 | 440 | ||
459 | static inline u32 | 441 | static inline u32 |
@@ -464,14 +446,22 @@ intel_read_status_page(struct intel_engine_cs *engine, int reg) | |||
464 | } | 446 | } |
465 | 447 | ||
466 | static inline void | 448 | static inline void |
467 | intel_write_status_page(struct intel_engine_cs *engine, | 449 | intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) |
468 | int reg, u32 value) | ||
469 | { | 450 | { |
470 | mb(); | 451 | /* Writing into the status page should be done sparingly. Since |
471 | clflush(&engine->status_page.page_addr[reg]); | 452 | * we do when we are uncertain of the device state, we take a bit |
472 | engine->status_page.page_addr[reg] = value; | 453 | * of extra paranoia to try and ensure that the HWS takes the value |
473 | clflush(&engine->status_page.page_addr[reg]); | 454 | * we give and that it doesn't end up trapped inside the CPU! |
474 | mb(); | 455 | */ |
456 | if (static_cpu_has(X86_FEATURE_CLFLUSH)) { | ||
457 | mb(); | ||
458 | clflush(&engine->status_page.page_addr[reg]); | ||
459 | engine->status_page.page_addr[reg] = value; | ||
460 | clflush(&engine->status_page.page_addr[reg]); | ||
461 | mb(); | ||
462 | } else { | ||
463 | WRITE_ONCE(engine->status_page.page_addr[reg], value); | ||
464 | } | ||
475 | } | 465 | } |
476 | 466 | ||
477 | /* | 467 | /* |
@@ -525,12 +515,29 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs) | |||
525 | } | 515 | } |
526 | 516 | ||
527 | static inline u32 | 517 | static inline u32 |
528 | intel_ring_offset(struct drm_i915_gem_request *req, void *addr) | 518 | intel_ring_wrap(const struct intel_ring *ring, u32 pos) |
519 | { | ||
520 | return pos & (ring->size - 1); | ||
521 | } | ||
522 | |||
523 | static inline u32 | ||
524 | intel_ring_offset(const struct drm_i915_gem_request *req, void *addr) | ||
529 | { | 525 | { |
530 | /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ | 526 | /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ |
531 | u32 offset = addr - req->ring->vaddr; | 527 | u32 offset = addr - req->ring->vaddr; |
532 | GEM_BUG_ON(offset > req->ring->size); | 528 | GEM_BUG_ON(offset > req->ring->size); |
533 | return offset & (req->ring->size - 1); | 529 | return intel_ring_wrap(req->ring, offset); |
530 | } | ||
531 | |||
532 | static inline void | ||
533 | assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail) | ||
534 | { | ||
535 | /* We could combine these into a single tail operation, but keeping | ||
536 | * them as seperate tests will help identify the cause should one | ||
537 | * ever fire. | ||
538 | */ | ||
539 | GEM_BUG_ON(!IS_ALIGNED(tail, 8)); | ||
540 | GEM_BUG_ON(tail >= ring->size); | ||
534 | } | 541 | } |
535 | 542 | ||
536 | void intel_ring_update_space(struct intel_ring *ring); | 543 | void intel_ring_update_space(struct intel_ring *ring); |
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 012bc358a33a..f8a375f8dde6 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
@@ -2840,8 +2840,10 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) | |||
2840 | { | 2840 | { |
2841 | struct pci_dev *pdev = dev_priv->drm.pdev; | 2841 | struct pci_dev *pdev = dev_priv->drm.pdev; |
2842 | struct device *kdev = &pdev->dev; | 2842 | struct device *kdev = &pdev->dev; |
2843 | int ret; | ||
2843 | 2844 | ||
2844 | pm_runtime_get_sync(kdev); | 2845 | ret = pm_runtime_get_sync(kdev); |
2846 | WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret); | ||
2845 | 2847 | ||
2846 | atomic_inc(&dev_priv->pm.wakeref_count); | 2848 | atomic_inc(&dev_priv->pm.wakeref_count); |
2847 | assert_rpm_wakelock_held(dev_priv); | 2849 | assert_rpm_wakelock_held(dev_priv); |
@@ -2871,7 +2873,8 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) | |||
2871 | * function, since the power state is undefined. This applies | 2873 | * function, since the power state is undefined. This applies |
2872 | * atm to the late/early system suspend/resume handlers. | 2874 | * atm to the late/early system suspend/resume handlers. |
2873 | */ | 2875 | */ |
2874 | WARN_ON_ONCE(ret < 0); | 2876 | WARN_ONCE(ret < 0, |
2877 | "pm_runtime_get_if_in_use() failed: %d\n", ret); | ||
2875 | if (ret <= 0) | 2878 | if (ret <= 0) |
2876 | return false; | 2879 | return false; |
2877 | } | 2880 | } |
@@ -2955,8 +2958,11 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) | |||
2955 | * platforms without RPM support. | 2958 | * platforms without RPM support. |
2956 | */ | 2959 | */ |
2957 | if (!HAS_RUNTIME_PM(dev_priv)) { | 2960 | if (!HAS_RUNTIME_PM(dev_priv)) { |
2961 | int ret; | ||
2962 | |||
2958 | pm_runtime_dont_use_autosuspend(kdev); | 2963 | pm_runtime_dont_use_autosuspend(kdev); |
2959 | pm_runtime_get_sync(kdev); | 2964 | ret = pm_runtime_get_sync(kdev); |
2965 | WARN(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret); | ||
2960 | } else { | 2966 | } else { |
2961 | pm_runtime_use_autosuspend(kdev); | 2967 | pm_runtime_use_autosuspend(kdev); |
2962 | } | 2968 | } |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b931d0bd7a64..f7d431427115 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -217,7 +217,7 @@ skl_update_plane(struct drm_plane *drm_plane, | |||
217 | struct drm_framebuffer *fb = plane_state->base.fb; | 217 | struct drm_framebuffer *fb = plane_state->base.fb; |
218 | enum plane_id plane_id = intel_plane->id; | 218 | enum plane_id plane_id = intel_plane->id; |
219 | enum pipe pipe = intel_plane->pipe; | 219 | enum pipe pipe = intel_plane->pipe; |
220 | u32 plane_ctl; | 220 | u32 plane_ctl = plane_state->ctl; |
221 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 221 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
222 | u32 surf_addr = plane_state->main.offset; | 222 | u32 surf_addr = plane_state->main.offset; |
223 | unsigned int rotation = plane_state->base.rotation; | 223 | unsigned int rotation = plane_state->base.rotation; |
@@ -232,24 +232,6 @@ skl_update_plane(struct drm_plane *drm_plane, | |||
232 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | 232 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; |
233 | unsigned long irqflags; | 233 | unsigned long irqflags; |
234 | 234 | ||
235 | plane_ctl = PLANE_CTL_ENABLE; | ||
236 | |||
237 | if (!IS_GEMINILAKE(dev_priv)) { | ||
238 | plane_ctl |= | ||
239 | PLANE_CTL_PIPE_GAMMA_ENABLE | | ||
240 | PLANE_CTL_PIPE_CSC_ENABLE | | ||
241 | PLANE_CTL_PLANE_GAMMA_DISABLE; | ||
242 | } | ||
243 | |||
244 | plane_ctl |= skl_plane_ctl_format(fb->format->format); | ||
245 | plane_ctl |= skl_plane_ctl_tiling(fb->modifier); | ||
246 | plane_ctl |= skl_plane_ctl_rotation(rotation); | ||
247 | |||
248 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | ||
249 | plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; | ||
250 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | ||
251 | plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; | ||
252 | |||
253 | /* Sizes are 0 based */ | 235 | /* Sizes are 0 based */ |
254 | src_w--; | 236 | src_w--; |
255 | src_h--; | 237 | src_h--; |
@@ -361,32 +343,15 @@ chv_update_csc(struct intel_plane *intel_plane, uint32_t format) | |||
361 | I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | 343 | I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
362 | } | 344 | } |
363 | 345 | ||
364 | static void | 346 | static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, |
365 | vlv_update_plane(struct drm_plane *dplane, | 347 | const struct intel_plane_state *plane_state) |
366 | const struct intel_crtc_state *crtc_state, | ||
367 | const struct intel_plane_state *plane_state) | ||
368 | { | 348 | { |
369 | struct drm_device *dev = dplane->dev; | 349 | const struct drm_framebuffer *fb = plane_state->base.fb; |
370 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
371 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
372 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
373 | enum pipe pipe = intel_plane->pipe; | ||
374 | enum plane_id plane_id = intel_plane->id; | ||
375 | u32 sprctl; | ||
376 | u32 sprsurf_offset, linear_offset; | ||
377 | unsigned int rotation = plane_state->base.rotation; | 350 | unsigned int rotation = plane_state->base.rotation; |
378 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 351 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
379 | int crtc_x = plane_state->base.dst.x1; | 352 | u32 sprctl; |
380 | int crtc_y = plane_state->base.dst.y1; | ||
381 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
382 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
383 | uint32_t x = plane_state->base.src.x1 >> 16; | ||
384 | uint32_t y = plane_state->base.src.y1 >> 16; | ||
385 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
386 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
387 | unsigned long irqflags; | ||
388 | 353 | ||
389 | sprctl = SP_ENABLE; | 354 | sprctl = SP_ENABLE | SP_GAMMA_ENABLE; |
390 | 355 | ||
391 | switch (fb->format->format) { | 356 | switch (fb->format->format) { |
392 | case DRM_FORMAT_YUYV: | 357 | case DRM_FORMAT_YUYV: |
@@ -423,20 +388,10 @@ vlv_update_plane(struct drm_plane *dplane, | |||
423 | sprctl |= SP_FORMAT_RGBA8888; | 388 | sprctl |= SP_FORMAT_RGBA8888; |
424 | break; | 389 | break; |
425 | default: | 390 | default: |
426 | /* | 391 | MISSING_CASE(fb->format->format); |
427 | * If we get here one of the upper layers failed to filter | 392 | return 0; |
428 | * out the unsupported plane formats | ||
429 | */ | ||
430 | BUG(); | ||
431 | break; | ||
432 | } | 393 | } |
433 | 394 | ||
434 | /* | ||
435 | * Enable gamma to match primary/cursor plane behaviour. | ||
436 | * FIXME should be user controllable via propertiesa. | ||
437 | */ | ||
438 | sprctl |= SP_GAMMA_ENABLE; | ||
439 | |||
440 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 395 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
441 | sprctl |= SP_TILED; | 396 | sprctl |= SP_TILED; |
442 | 397 | ||
@@ -449,22 +404,36 @@ vlv_update_plane(struct drm_plane *dplane, | |||
449 | if (key->flags & I915_SET_COLORKEY_SOURCE) | 404 | if (key->flags & I915_SET_COLORKEY_SOURCE) |
450 | sprctl |= SP_SOURCE_KEY; | 405 | sprctl |= SP_SOURCE_KEY; |
451 | 406 | ||
407 | return sprctl; | ||
408 | } | ||
409 | |||
410 | static void | ||
411 | vlv_update_plane(struct drm_plane *dplane, | ||
412 | const struct intel_crtc_state *crtc_state, | ||
413 | const struct intel_plane_state *plane_state) | ||
414 | { | ||
415 | struct drm_device *dev = dplane->dev; | ||
416 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
417 | struct intel_plane *intel_plane = to_intel_plane(dplane); | ||
418 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
419 | enum pipe pipe = intel_plane->pipe; | ||
420 | enum plane_id plane_id = intel_plane->id; | ||
421 | u32 sprctl = plane_state->ctl; | ||
422 | u32 sprsurf_offset = plane_state->main.offset; | ||
423 | u32 linear_offset; | ||
424 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | ||
425 | int crtc_x = plane_state->base.dst.x1; | ||
426 | int crtc_y = plane_state->base.dst.y1; | ||
427 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
428 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
429 | uint32_t x = plane_state->main.x; | ||
430 | uint32_t y = plane_state->main.y; | ||
431 | unsigned long irqflags; | ||
432 | |||
452 | /* Sizes are 0 based */ | 433 | /* Sizes are 0 based */ |
453 | src_w--; | ||
454 | src_h--; | ||
455 | crtc_w--; | 434 | crtc_w--; |
456 | crtc_h--; | 435 | crtc_h--; |
457 | 436 | ||
458 | intel_add_fb_offsets(&x, &y, plane_state, 0); | ||
459 | sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0); | ||
460 | |||
461 | if (rotation & DRM_ROTATE_180) { | ||
462 | x += src_w; | ||
463 | y += src_h; | ||
464 | } else if (rotation & DRM_REFLECT_X) { | ||
465 | x += src_w; | ||
466 | } | ||
467 | |||
468 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); | 437 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); |
469 | 438 | ||
470 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 439 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
@@ -516,31 +485,23 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | |||
516 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 485 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
517 | } | 486 | } |
518 | 487 | ||
519 | static void | 488 | static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, |
520 | ivb_update_plane(struct drm_plane *plane, | 489 | const struct intel_plane_state *plane_state) |
521 | const struct intel_crtc_state *crtc_state, | ||
522 | const struct intel_plane_state *plane_state) | ||
523 | { | 490 | { |
524 | struct drm_device *dev = plane->dev; | 491 | struct drm_i915_private *dev_priv = |
525 | struct drm_i915_private *dev_priv = to_i915(dev); | 492 | to_i915(plane_state->base.plane->dev); |
526 | struct intel_plane *intel_plane = to_intel_plane(plane); | 493 | const struct drm_framebuffer *fb = plane_state->base.fb; |
527 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
528 | enum pipe pipe = intel_plane->pipe; | ||
529 | u32 sprctl, sprscale = 0; | ||
530 | u32 sprsurf_offset, linear_offset; | ||
531 | unsigned int rotation = plane_state->base.rotation; | 494 | unsigned int rotation = plane_state->base.rotation; |
532 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 495 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
533 | int crtc_x = plane_state->base.dst.x1; | 496 | u32 sprctl; |
534 | int crtc_y = plane_state->base.dst.y1; | 497 | |
535 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 498 | sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE; |
536 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 499 | |
537 | uint32_t x = plane_state->base.src.x1 >> 16; | 500 | if (IS_IVYBRIDGE(dev_priv)) |
538 | uint32_t y = plane_state->base.src.y1 >> 16; | 501 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
539 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
540 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
541 | unsigned long irqflags; | ||
542 | 502 | ||
543 | sprctl = SPRITE_ENABLE; | 503 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
504 | sprctl |= SPRITE_PIPE_CSC_ENABLE; | ||
544 | 505 | ||
545 | switch (fb->format->format) { | 506 | switch (fb->format->format) { |
546 | case DRM_FORMAT_XBGR8888: | 507 | case DRM_FORMAT_XBGR8888: |
@@ -562,34 +523,48 @@ ivb_update_plane(struct drm_plane *plane, | |||
562 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; | 523 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; |
563 | break; | 524 | break; |
564 | default: | 525 | default: |
565 | BUG(); | 526 | MISSING_CASE(fb->format->format); |
527 | return 0; | ||
566 | } | 528 | } |
567 | 529 | ||
568 | /* | ||
569 | * Enable gamma to match primary/cursor plane behaviour. | ||
570 | * FIXME should be user controllable via propertiesa. | ||
571 | */ | ||
572 | sprctl |= SPRITE_GAMMA_ENABLE; | ||
573 | |||
574 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 530 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
575 | sprctl |= SPRITE_TILED; | 531 | sprctl |= SPRITE_TILED; |
576 | 532 | ||
577 | if (rotation & DRM_ROTATE_180) | 533 | if (rotation & DRM_ROTATE_180) |
578 | sprctl |= SPRITE_ROTATE_180; | 534 | sprctl |= SPRITE_ROTATE_180; |
579 | 535 | ||
580 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||
581 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; | ||
582 | else | ||
583 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | ||
584 | |||
585 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||
586 | sprctl |= SPRITE_PIPE_CSC_ENABLE; | ||
587 | |||
588 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | 536 | if (key->flags & I915_SET_COLORKEY_DESTINATION) |
589 | sprctl |= SPRITE_DEST_KEY; | 537 | sprctl |= SPRITE_DEST_KEY; |
590 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | 538 | else if (key->flags & I915_SET_COLORKEY_SOURCE) |
591 | sprctl |= SPRITE_SOURCE_KEY; | 539 | sprctl |= SPRITE_SOURCE_KEY; |
592 | 540 | ||
541 | return sprctl; | ||
542 | } | ||
543 | |||
544 | static void | ||
545 | ivb_update_plane(struct drm_plane *plane, | ||
546 | const struct intel_crtc_state *crtc_state, | ||
547 | const struct intel_plane_state *plane_state) | ||
548 | { | ||
549 | struct drm_device *dev = plane->dev; | ||
550 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
551 | struct intel_plane *intel_plane = to_intel_plane(plane); | ||
552 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
553 | enum pipe pipe = intel_plane->pipe; | ||
554 | u32 sprctl = plane_state->ctl, sprscale = 0; | ||
555 | u32 sprsurf_offset = plane_state->main.offset; | ||
556 | u32 linear_offset; | ||
557 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | ||
558 | int crtc_x = plane_state->base.dst.x1; | ||
559 | int crtc_y = plane_state->base.dst.y1; | ||
560 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
561 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
562 | uint32_t x = plane_state->main.x; | ||
563 | uint32_t y = plane_state->main.y; | ||
564 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
565 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
566 | unsigned long irqflags; | ||
567 | |||
593 | /* Sizes are 0 based */ | 568 | /* Sizes are 0 based */ |
594 | src_w--; | 569 | src_w--; |
595 | src_h--; | 570 | src_h--; |
@@ -599,16 +574,6 @@ ivb_update_plane(struct drm_plane *plane, | |||
599 | if (crtc_w != src_w || crtc_h != src_h) | 574 | if (crtc_w != src_w || crtc_h != src_h) |
600 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; | 575 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; |
601 | 576 | ||
602 | intel_add_fb_offsets(&x, &y, plane_state, 0); | ||
603 | sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0); | ||
604 | |||
605 | /* HSW+ does this automagically in hardware */ | ||
606 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) && | ||
607 | rotation & DRM_ROTATE_180) { | ||
608 | x += src_w; | ||
609 | y += src_h; | ||
610 | } | ||
611 | |||
612 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); | 577 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); |
613 | 578 | ||
614 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 579 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
@@ -664,31 +629,20 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | |||
664 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 629 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
665 | } | 630 | } |
666 | 631 | ||
667 | static void | 632 | static u32 ilk_sprite_ctl(const struct intel_crtc_state *crtc_state, |
668 | ilk_update_plane(struct drm_plane *plane, | 633 | const struct intel_plane_state *plane_state) |
669 | const struct intel_crtc_state *crtc_state, | ||
670 | const struct intel_plane_state *plane_state) | ||
671 | { | 634 | { |
672 | struct drm_device *dev = plane->dev; | 635 | struct drm_i915_private *dev_priv = |
673 | struct drm_i915_private *dev_priv = to_i915(dev); | 636 | to_i915(plane_state->base.plane->dev); |
674 | struct intel_plane *intel_plane = to_intel_plane(plane); | 637 | const struct drm_framebuffer *fb = plane_state->base.fb; |
675 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
676 | int pipe = intel_plane->pipe; | ||
677 | u32 dvscntr, dvsscale; | ||
678 | u32 dvssurf_offset, linear_offset; | ||
679 | unsigned int rotation = plane_state->base.rotation; | 638 | unsigned int rotation = plane_state->base.rotation; |
680 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 639 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
681 | int crtc_x = plane_state->base.dst.x1; | 640 | u32 dvscntr; |
682 | int crtc_y = plane_state->base.dst.y1; | ||
683 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
684 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
685 | uint32_t x = plane_state->base.src.x1 >> 16; | ||
686 | uint32_t y = plane_state->base.src.y1 >> 16; | ||
687 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
688 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
689 | unsigned long irqflags; | ||
690 | 641 | ||
691 | dvscntr = DVS_ENABLE; | 642 | dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE; |
643 | |||
644 | if (IS_GEN6(dev_priv)) | ||
645 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; | ||
692 | 646 | ||
693 | switch (fb->format->format) { | 647 | switch (fb->format->format) { |
694 | case DRM_FORMAT_XBGR8888: | 648 | case DRM_FORMAT_XBGR8888: |
@@ -710,47 +664,57 @@ ilk_update_plane(struct drm_plane *plane, | |||
710 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; | 664 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; |
711 | break; | 665 | break; |
712 | default: | 666 | default: |
713 | BUG(); | 667 | MISSING_CASE(fb->format->format); |
668 | return 0; | ||
714 | } | 669 | } |
715 | 670 | ||
716 | /* | ||
717 | * Enable gamma to match primary/cursor plane behaviour. | ||
718 | * FIXME should be user controllable via propertiesa. | ||
719 | */ | ||
720 | dvscntr |= DVS_GAMMA_ENABLE; | ||
721 | |||
722 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 671 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) |
723 | dvscntr |= DVS_TILED; | 672 | dvscntr |= DVS_TILED; |
724 | 673 | ||
725 | if (rotation & DRM_ROTATE_180) | 674 | if (rotation & DRM_ROTATE_180) |
726 | dvscntr |= DVS_ROTATE_180; | 675 | dvscntr |= DVS_ROTATE_180; |
727 | 676 | ||
728 | if (IS_GEN6(dev_priv)) | ||
729 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ | ||
730 | |||
731 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | 677 | if (key->flags & I915_SET_COLORKEY_DESTINATION) |
732 | dvscntr |= DVS_DEST_KEY; | 678 | dvscntr |= DVS_DEST_KEY; |
733 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | 679 | else if (key->flags & I915_SET_COLORKEY_SOURCE) |
734 | dvscntr |= DVS_SOURCE_KEY; | 680 | dvscntr |= DVS_SOURCE_KEY; |
735 | 681 | ||
682 | return dvscntr; | ||
683 | } | ||
684 | |||
685 | static void | ||
686 | ilk_update_plane(struct drm_plane *plane, | ||
687 | const struct intel_crtc_state *crtc_state, | ||
688 | const struct intel_plane_state *plane_state) | ||
689 | { | ||
690 | struct drm_device *dev = plane->dev; | ||
691 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
692 | struct intel_plane *intel_plane = to_intel_plane(plane); | ||
693 | struct drm_framebuffer *fb = plane_state->base.fb; | ||
694 | int pipe = intel_plane->pipe; | ||
695 | u32 dvscntr = plane_state->ctl, dvsscale = 0; | ||
696 | u32 dvssurf_offset = plane_state->main.offset; | ||
697 | u32 linear_offset; | ||
698 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | ||
699 | int crtc_x = plane_state->base.dst.x1; | ||
700 | int crtc_y = plane_state->base.dst.y1; | ||
701 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
702 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
703 | uint32_t x = plane_state->main.x; | ||
704 | uint32_t y = plane_state->main.y; | ||
705 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
706 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | ||
707 | unsigned long irqflags; | ||
708 | |||
736 | /* Sizes are 0 based */ | 709 | /* Sizes are 0 based */ |
737 | src_w--; | 710 | src_w--; |
738 | src_h--; | 711 | src_h--; |
739 | crtc_w--; | 712 | crtc_w--; |
740 | crtc_h--; | 713 | crtc_h--; |
741 | 714 | ||
742 | dvsscale = 0; | ||
743 | if (crtc_w != src_w || crtc_h != src_h) | 715 | if (crtc_w != src_w || crtc_h != src_h) |
744 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; | 716 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; |
745 | 717 | ||
746 | intel_add_fb_offsets(&x, &y, plane_state, 0); | ||
747 | dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0); | ||
748 | |||
749 | if (rotation & DRM_ROTATE_180) { | ||
750 | x += src_w; | ||
751 | y += src_h; | ||
752 | } | ||
753 | |||
754 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); | 718 | linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); |
755 | 719 | ||
756 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 720 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
@@ -981,6 +945,26 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
981 | ret = skl_check_plane_surface(state); | 945 | ret = skl_check_plane_surface(state); |
982 | if (ret) | 946 | if (ret) |
983 | return ret; | 947 | return ret; |
948 | |||
949 | state->ctl = skl_plane_ctl(crtc_state, state); | ||
950 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
951 | ret = i9xx_check_plane_surface(state); | ||
952 | if (ret) | ||
953 | return ret; | ||
954 | |||
955 | state->ctl = vlv_sprite_ctl(crtc_state, state); | ||
956 | } else if (INTEL_GEN(dev_priv) >= 7) { | ||
957 | ret = i9xx_check_plane_surface(state); | ||
958 | if (ret) | ||
959 | return ret; | ||
960 | |||
961 | state->ctl = ivb_sprite_ctl(crtc_state, state); | ||
962 | } else { | ||
963 | ret = i9xx_check_plane_surface(state); | ||
964 | if (ret) | ||
965 | return ret; | ||
966 | |||
967 | state->ctl = ilk_sprite_ctl(crtc_state, state); | ||
984 | } | 968 | } |
985 | 969 | ||
986 | return 0; | 970 | return 0; |
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index d15a7d9d4eb0..c117424f1f50 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c | |||
@@ -26,6 +26,19 @@ | |||
26 | #include "intel_uc.h" | 26 | #include "intel_uc.h" |
27 | #include <linux/firmware.h> | 27 | #include <linux/firmware.h> |
28 | 28 | ||
29 | /* Cleans up uC firmware by releasing the firmware GEM obj. | ||
30 | */ | ||
31 | static void __intel_uc_fw_fini(struct intel_uc_fw *uc_fw) | ||
32 | { | ||
33 | struct drm_i915_gem_object *obj; | ||
34 | |||
35 | obj = fetch_and_zero(&uc_fw->obj); | ||
36 | if (obj) | ||
37 | i915_gem_object_put(obj); | ||
38 | |||
39 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; | ||
40 | } | ||
41 | |||
29 | /* Reset GuC providing us with fresh state for both GuC and HuC. | 42 | /* Reset GuC providing us with fresh state for both GuC and HuC. |
30 | */ | 43 | */ |
31 | static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv) | 44 | static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv) |
@@ -83,23 +96,166 @@ void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) | |||
83 | 96 | ||
84 | void intel_uc_init_early(struct drm_i915_private *dev_priv) | 97 | void intel_uc_init_early(struct drm_i915_private *dev_priv) |
85 | { | 98 | { |
86 | mutex_init(&dev_priv->guc.send_mutex); | 99 | struct intel_guc *guc = &dev_priv->guc; |
100 | |||
101 | mutex_init(&guc->send_mutex); | ||
102 | guc->send = intel_guc_send_mmio; | ||
103 | } | ||
104 | |||
105 | static void fetch_uc_fw(struct drm_i915_private *dev_priv, | ||
106 | struct intel_uc_fw *uc_fw) | ||
107 | { | ||
108 | struct pci_dev *pdev = dev_priv->drm.pdev; | ||
109 | struct drm_i915_gem_object *obj; | ||
110 | const struct firmware *fw = NULL; | ||
111 | struct uc_css_header *css; | ||
112 | size_t size; | ||
113 | int err; | ||
114 | |||
115 | if (!uc_fw->path) | ||
116 | return; | ||
117 | |||
118 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING; | ||
119 | |||
120 | DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n", | ||
121 | intel_uc_fw_status_repr(uc_fw->fetch_status)); | ||
122 | |||
123 | err = request_firmware(&fw, uc_fw->path, &pdev->dev); | ||
124 | if (err) | ||
125 | goto fail; | ||
126 | if (!fw) | ||
127 | goto fail; | ||
128 | |||
129 | DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n", | ||
130 | uc_fw->path, fw); | ||
131 | |||
132 | /* Check the size of the blob before examining buffer contents */ | ||
133 | if (fw->size < sizeof(struct uc_css_header)) { | ||
134 | DRM_NOTE("Firmware header is missing\n"); | ||
135 | goto fail; | ||
136 | } | ||
137 | |||
138 | css = (struct uc_css_header *)fw->data; | ||
139 | |||
140 | /* Firmware bits always start from header */ | ||
141 | uc_fw->header_offset = 0; | ||
142 | uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw - | ||
143 | css->key_size_dw - css->exponent_size_dw) * sizeof(u32); | ||
144 | |||
145 | if (uc_fw->header_size != sizeof(struct uc_css_header)) { | ||
146 | DRM_NOTE("CSS header definition mismatch\n"); | ||
147 | goto fail; | ||
148 | } | ||
149 | |||
150 | /* then, uCode */ | ||
151 | uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; | ||
152 | uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); | ||
153 | |||
154 | /* now RSA */ | ||
155 | if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { | ||
156 | DRM_NOTE("RSA key size is bad\n"); | ||
157 | goto fail; | ||
158 | } | ||
159 | uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size; | ||
160 | uc_fw->rsa_size = css->key_size_dw * sizeof(u32); | ||
161 | |||
162 | /* At least, it should have header, uCode and RSA. Size of all three. */ | ||
163 | size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size; | ||
164 | if (fw->size < size) { | ||
165 | DRM_NOTE("Missing firmware components\n"); | ||
166 | goto fail; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * The GuC firmware image has the version number embedded at a | ||
171 | * well-known offset within the firmware blob; note that major / minor | ||
172 | * version are TWO bytes each (i.e. u16), although all pointers and | ||
173 | * offsets are defined in terms of bytes (u8). | ||
174 | */ | ||
175 | switch (uc_fw->type) { | ||
176 | case INTEL_UC_FW_TYPE_GUC: | ||
177 | /* Header and uCode will be loaded to WOPCM. Size of the two. */ | ||
178 | size = uc_fw->header_size + uc_fw->ucode_size; | ||
179 | |||
180 | /* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */ | ||
181 | if (size > intel_guc_wopcm_size(dev_priv)) { | ||
182 | DRM_ERROR("Firmware is too large to fit in WOPCM\n"); | ||
183 | goto fail; | ||
184 | } | ||
185 | uc_fw->major_ver_found = css->guc.sw_version >> 16; | ||
186 | uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF; | ||
187 | break; | ||
188 | |||
189 | case INTEL_UC_FW_TYPE_HUC: | ||
190 | uc_fw->major_ver_found = css->huc.sw_version >> 16; | ||
191 | uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF; | ||
192 | break; | ||
193 | |||
194 | default: | ||
195 | DRM_ERROR("Unknown firmware type %d\n", uc_fw->type); | ||
196 | err = -ENOEXEC; | ||
197 | goto fail; | ||
198 | } | ||
199 | |||
200 | if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) { | ||
201 | DRM_NOTE("Skipping %s firmware version check\n", | ||
202 | intel_uc_fw_type_repr(uc_fw->type)); | ||
203 | } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted || | ||
204 | uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) { | ||
205 | DRM_NOTE("%s firmware version %d.%d, required %d.%d\n", | ||
206 | intel_uc_fw_type_repr(uc_fw->type), | ||
207 | uc_fw->major_ver_found, uc_fw->minor_ver_found, | ||
208 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); | ||
209 | err = -ENOEXEC; | ||
210 | goto fail; | ||
211 | } | ||
212 | |||
213 | DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n", | ||
214 | uc_fw->major_ver_found, uc_fw->minor_ver_found, | ||
215 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); | ||
216 | |||
217 | obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size); | ||
218 | if (IS_ERR(obj)) { | ||
219 | err = PTR_ERR(obj); | ||
220 | goto fail; | ||
221 | } | ||
222 | |||
223 | uc_fw->obj = obj; | ||
224 | uc_fw->size = fw->size; | ||
225 | |||
226 | DRM_DEBUG_DRIVER("uC fw fetch status SUCCESS, obj %p\n", | ||
227 | uc_fw->obj); | ||
228 | |||
229 | release_firmware(fw); | ||
230 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS; | ||
231 | return; | ||
232 | |||
233 | fail: | ||
234 | DRM_WARN("Failed to fetch valid uC firmware from %s (error %d)\n", | ||
235 | uc_fw->path, err); | ||
236 | DRM_DEBUG_DRIVER("uC fw fetch status FAIL; err %d, fw %p, obj %p\n", | ||
237 | err, fw, uc_fw->obj); | ||
238 | |||
239 | release_firmware(fw); /* OK even if fw is NULL */ | ||
240 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL; | ||
87 | } | 241 | } |
88 | 242 | ||
89 | void intel_uc_init_fw(struct drm_i915_private *dev_priv) | 243 | void intel_uc_init_fw(struct drm_i915_private *dev_priv) |
90 | { | 244 | { |
91 | if (dev_priv->huc.fw.path) | 245 | fetch_uc_fw(dev_priv, &dev_priv->huc.fw); |
92 | intel_uc_prepare_fw(dev_priv, &dev_priv->huc.fw); | 246 | fetch_uc_fw(dev_priv, &dev_priv->guc.fw); |
247 | } | ||
93 | 248 | ||
94 | if (dev_priv->guc.fw.path) | 249 | void intel_uc_fini_fw(struct drm_i915_private *dev_priv) |
95 | intel_uc_prepare_fw(dev_priv, &dev_priv->guc.fw); | 250 | { |
251 | __intel_uc_fw_fini(&dev_priv->guc.fw); | ||
252 | __intel_uc_fw_fini(&dev_priv->huc.fw); | ||
96 | } | 253 | } |
97 | 254 | ||
98 | int intel_uc_init_hw(struct drm_i915_private *dev_priv) | 255 | int intel_uc_init_hw(struct drm_i915_private *dev_priv) |
99 | { | 256 | { |
100 | int ret, attempts; | 257 | int ret, attempts; |
101 | 258 | ||
102 | /* GuC not enabled, nothing to do */ | ||
103 | if (!i915.enable_guc_loading) | 259 | if (!i915.enable_guc_loading) |
104 | return 0; | 260 | return 0; |
105 | 261 | ||
@@ -109,9 +265,13 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
109 | i915_ggtt_enable_guc(dev_priv); | 265 | i915_ggtt_enable_guc(dev_priv); |
110 | 266 | ||
111 | if (i915.enable_guc_submission) { | 267 | if (i915.enable_guc_submission) { |
268 | /* | ||
269 | * This is stuff we need to have available at fw load time | ||
270 | * if we are planning to enable submission later | ||
271 | */ | ||
112 | ret = i915_guc_submission_init(dev_priv); | 272 | ret = i915_guc_submission_init(dev_priv); |
113 | if (ret) | 273 | if (ret) |
114 | goto err; | 274 | goto err_guc; |
115 | } | 275 | } |
116 | 276 | ||
117 | /* WaEnableuKernelHeaderValidFix:skl */ | 277 | /* WaEnableuKernelHeaderValidFix:skl */ |
@@ -150,7 +310,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
150 | 310 | ||
151 | ret = i915_guc_submission_enable(dev_priv); | 311 | ret = i915_guc_submission_enable(dev_priv); |
152 | if (ret) | 312 | if (ret) |
153 | goto err_submission; | 313 | goto err_interrupts; |
154 | } | 314 | } |
155 | 315 | ||
156 | return 0; | 316 | return 0; |
@@ -164,11 +324,12 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) | |||
164 | * nonfatal error (i.e. it doesn't prevent driver load, but | 324 | * nonfatal error (i.e. it doesn't prevent driver load, but |
165 | * marks the GPU as wedged until reset). | 325 | * marks the GPU as wedged until reset). |
166 | */ | 326 | */ |
327 | err_interrupts: | ||
328 | gen9_disable_guc_interrupts(dev_priv); | ||
167 | err_submission: | 329 | err_submission: |
168 | if (i915.enable_guc_submission) | 330 | if (i915.enable_guc_submission) |
169 | i915_guc_submission_fini(dev_priv); | 331 | i915_guc_submission_fini(dev_priv); |
170 | 332 | err_guc: | |
171 | err: | ||
172 | i915_ggtt_disable_guc(dev_priv); | 333 | i915_ggtt_disable_guc(dev_priv); |
173 | 334 | ||
174 | DRM_ERROR("GuC init failed\n"); | 335 | DRM_ERROR("GuC init failed\n"); |
@@ -185,11 +346,24 @@ err: | |||
185 | return ret; | 346 | return ret; |
186 | } | 347 | } |
187 | 348 | ||
349 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv) | ||
350 | { | ||
351 | if (!i915.enable_guc_loading) | ||
352 | return; | ||
353 | |||
354 | if (i915.enable_guc_submission) { | ||
355 | i915_guc_submission_disable(dev_priv); | ||
356 | gen9_disable_guc_interrupts(dev_priv); | ||
357 | i915_guc_submission_fini(dev_priv); | ||
358 | } | ||
359 | i915_ggtt_disable_guc(dev_priv); | ||
360 | } | ||
361 | |||
188 | /* | 362 | /* |
189 | * Read GuC command/status register (SOFT_SCRATCH_0) | 363 | * Read GuC command/status register (SOFT_SCRATCH_0) |
190 | * Return true if it contains a response rather than a command | 364 | * Return true if it contains a response rather than a command |
191 | */ | 365 | */ |
192 | static bool intel_guc_recv(struct intel_guc *guc, u32 *status) | 366 | static bool guc_recv(struct intel_guc *guc, u32 *status) |
193 | { | 367 | { |
194 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 368 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
195 | 369 | ||
@@ -198,7 +372,10 @@ static bool intel_guc_recv(struct intel_guc *guc, u32 *status) | |||
198 | return INTEL_GUC_RECV_IS_RESPONSE(val); | 372 | return INTEL_GUC_RECV_IS_RESPONSE(val); |
199 | } | 373 | } |
200 | 374 | ||
201 | int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | 375 | /* |
376 | * This function implements the MMIO based host to GuC interface. | ||
377 | */ | ||
378 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) | ||
202 | { | 379 | { |
203 | struct drm_i915_private *dev_priv = guc_to_i915(guc); | 380 | struct drm_i915_private *dev_priv = guc_to_i915(guc); |
204 | u32 status; | 381 | u32 status; |
@@ -209,7 +386,7 @@ int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | |||
209 | return -EINVAL; | 386 | return -EINVAL; |
210 | 387 | ||
211 | mutex_lock(&guc->send_mutex); | 388 | mutex_lock(&guc->send_mutex); |
212 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 389 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_BLITTER); |
213 | 390 | ||
214 | dev_priv->guc.action_count += 1; | 391 | dev_priv->guc.action_count += 1; |
215 | dev_priv->guc.action_cmd = action[0]; | 392 | dev_priv->guc.action_cmd = action[0]; |
@@ -226,9 +403,9 @@ int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | |||
226 | * up to that length of time, then switch to a slower sleep-wait loop. | 403 | * up to that length of time, then switch to a slower sleep-wait loop. |
227 | * No inte_guc_send command should ever take longer than 10ms. | 404 | * No inte_guc_send command should ever take longer than 10ms. |
228 | */ | 405 | */ |
229 | ret = wait_for_us(intel_guc_recv(guc, &status), 10); | 406 | ret = wait_for_us(guc_recv(guc, &status), 10); |
230 | if (ret) | 407 | if (ret) |
231 | ret = wait_for(intel_guc_recv(guc, &status), 10); | 408 | ret = wait_for(guc_recv(guc, &status), 10); |
232 | if (status != INTEL_GUC_STATUS_SUCCESS) { | 409 | if (status != INTEL_GUC_STATUS_SUCCESS) { |
233 | /* | 410 | /* |
234 | * Either the GuC explicitly returned an error (which | 411 | * Either the GuC explicitly returned an error (which |
@@ -247,7 +424,7 @@ int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | |||
247 | } | 424 | } |
248 | dev_priv->guc.action_status = status; | 425 | dev_priv->guc.action_status = status; |
249 | 426 | ||
250 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); | 427 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_BLITTER); |
251 | mutex_unlock(&guc->send_mutex); | 428 | mutex_unlock(&guc->send_mutex); |
252 | 429 | ||
253 | return ret; | 430 | return ret; |
@@ -268,136 +445,3 @@ int intel_guc_sample_forcewake(struct intel_guc *guc) | |||
268 | 445 | ||
269 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); | 446 | return intel_guc_send(guc, action, ARRAY_SIZE(action)); |
270 | } | 447 | } |
271 | |||
272 | void intel_uc_prepare_fw(struct drm_i915_private *dev_priv, | ||
273 | struct intel_uc_fw *uc_fw) | ||
274 | { | ||
275 | struct pci_dev *pdev = dev_priv->drm.pdev; | ||
276 | struct drm_i915_gem_object *obj; | ||
277 | const struct firmware *fw = NULL; | ||
278 | struct uc_css_header *css; | ||
279 | size_t size; | ||
280 | int err; | ||
281 | |||
282 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING; | ||
283 | |||
284 | DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n", | ||
285 | intel_uc_fw_status_repr(uc_fw->fetch_status)); | ||
286 | |||
287 | err = request_firmware(&fw, uc_fw->path, &pdev->dev); | ||
288 | if (err) | ||
289 | goto fail; | ||
290 | if (!fw) | ||
291 | goto fail; | ||
292 | |||
293 | DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n", | ||
294 | uc_fw->path, fw); | ||
295 | |||
296 | /* Check the size of the blob before examining buffer contents */ | ||
297 | if (fw->size < sizeof(struct uc_css_header)) { | ||
298 | DRM_NOTE("Firmware header is missing\n"); | ||
299 | goto fail; | ||
300 | } | ||
301 | |||
302 | css = (struct uc_css_header *)fw->data; | ||
303 | |||
304 | /* Firmware bits always start from header */ | ||
305 | uc_fw->header_offset = 0; | ||
306 | uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw - | ||
307 | css->key_size_dw - css->exponent_size_dw) * sizeof(u32); | ||
308 | |||
309 | if (uc_fw->header_size != sizeof(struct uc_css_header)) { | ||
310 | DRM_NOTE("CSS header definition mismatch\n"); | ||
311 | goto fail; | ||
312 | } | ||
313 | |||
314 | /* then, uCode */ | ||
315 | uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; | ||
316 | uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); | ||
317 | |||
318 | /* now RSA */ | ||
319 | if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { | ||
320 | DRM_NOTE("RSA key size is bad\n"); | ||
321 | goto fail; | ||
322 | } | ||
323 | uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size; | ||
324 | uc_fw->rsa_size = css->key_size_dw * sizeof(u32); | ||
325 | |||
326 | /* At least, it should have header, uCode and RSA. Size of all three. */ | ||
327 | size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size; | ||
328 | if (fw->size < size) { | ||
329 | DRM_NOTE("Missing firmware components\n"); | ||
330 | goto fail; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * The GuC firmware image has the version number embedded at a | ||
335 | * well-known offset within the firmware blob; note that major / minor | ||
336 | * version are TWO bytes each (i.e. u16), although all pointers and | ||
337 | * offsets are defined in terms of bytes (u8). | ||
338 | */ | ||
339 | switch (uc_fw->type) { | ||
340 | case INTEL_UC_FW_TYPE_GUC: | ||
341 | /* Header and uCode will be loaded to WOPCM. Size of the two. */ | ||
342 | size = uc_fw->header_size + uc_fw->ucode_size; | ||
343 | |||
344 | /* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */ | ||
345 | if (size > intel_guc_wopcm_size(dev_priv)) { | ||
346 | DRM_ERROR("Firmware is too large to fit in WOPCM\n"); | ||
347 | goto fail; | ||
348 | } | ||
349 | uc_fw->major_ver_found = css->guc.sw_version >> 16; | ||
350 | uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF; | ||
351 | break; | ||
352 | |||
353 | case INTEL_UC_FW_TYPE_HUC: | ||
354 | uc_fw->major_ver_found = css->huc.sw_version >> 16; | ||
355 | uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF; | ||
356 | break; | ||
357 | |||
358 | default: | ||
359 | DRM_ERROR("Unknown firmware type %d\n", uc_fw->type); | ||
360 | err = -ENOEXEC; | ||
361 | goto fail; | ||
362 | } | ||
363 | |||
364 | if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) { | ||
365 | DRM_NOTE("Skipping uC firmware version check\n"); | ||
366 | } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted || | ||
367 | uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) { | ||
368 | DRM_NOTE("uC firmware version %d.%d, required %d.%d\n", | ||
369 | uc_fw->major_ver_found, uc_fw->minor_ver_found, | ||
370 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); | ||
371 | err = -ENOEXEC; | ||
372 | goto fail; | ||
373 | } | ||
374 | |||
375 | DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n", | ||
376 | uc_fw->major_ver_found, uc_fw->minor_ver_found, | ||
377 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); | ||
378 | |||
379 | obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size); | ||
380 | if (IS_ERR(obj)) { | ||
381 | err = PTR_ERR(obj); | ||
382 | goto fail; | ||
383 | } | ||
384 | |||
385 | uc_fw->obj = obj; | ||
386 | uc_fw->size = fw->size; | ||
387 | |||
388 | DRM_DEBUG_DRIVER("uC fw fetch status SUCCESS, obj %p\n", | ||
389 | uc_fw->obj); | ||
390 | |||
391 | release_firmware(fw); | ||
392 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS; | ||
393 | return; | ||
394 | |||
395 | fail: | ||
396 | DRM_WARN("Failed to fetch valid uC firmware from %s (error %d)\n", | ||
397 | uc_fw->path, err); | ||
398 | DRM_DEBUG_DRIVER("uC fw fetch status FAIL; err %d, fw %p, obj %p\n", | ||
399 | err, fw, uc_fw->obj); | ||
400 | |||
401 | release_firmware(fw); /* OK even if fw is NULL */ | ||
402 | uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL; | ||
403 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index a35ededfaa40..4b7f73aeddac 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h | |||
@@ -34,7 +34,9 @@ struct drm_i915_gem_request; | |||
34 | 34 | ||
35 | /* | 35 | /* |
36 | * This structure primarily describes the GEM object shared with the GuC. | 36 | * This structure primarily describes the GEM object shared with the GuC. |
37 | * The GEM object is held for the entire lifetime of our interaction with | 37 | * The specs sometimes refer to this object as a "GuC context", but we use |
38 | * the term "client" to avoid confusion with hardware contexts. This | ||
39 | * GEM object is held for the entire lifetime of our interaction with | ||
38 | * the GuC, being allocated before the GuC is loaded with its firmware. | 40 | * the GuC, being allocated before the GuC is loaded with its firmware. |
39 | * Because there's no way to update the address used by the GuC after | 41 | * Because there's no way to update the address used by the GuC after |
40 | * initialisation, the shared object must stay pinned into the GGTT as | 42 | * initialisation, the shared object must stay pinned into the GGTT as |
@@ -44,7 +46,7 @@ struct drm_i915_gem_request; | |||
44 | * | 46 | * |
45 | * The single GEM object described here is actually made up of several | 47 | * The single GEM object described here is actually made up of several |
46 | * separate areas, as far as the GuC is concerned. The first page (kept | 48 | * separate areas, as far as the GuC is concerned. The first page (kept |
47 | * kmap'd) includes the "process decriptor" which holds sequence data for | 49 | * kmap'd) includes the "process descriptor" which holds sequence data for |
48 | * the doorbell, and one cacheline which actually *is* the doorbell; a | 50 | * the doorbell, and one cacheline which actually *is* the doorbell; a |
49 | * write to this will "ring the doorbell" (i.e. send an interrupt to the | 51 | * write to this will "ring the doorbell" (i.e. send an interrupt to the |
50 | * GuC). The subsequent pages of the client object constitute the work | 52 | * GuC). The subsequent pages of the client object constitute the work |
@@ -72,13 +74,12 @@ struct i915_guc_client { | |||
72 | 74 | ||
73 | uint32_t engines; /* bitmap of (host) engine ids */ | 75 | uint32_t engines; /* bitmap of (host) engine ids */ |
74 | uint32_t priority; | 76 | uint32_t priority; |
75 | uint32_t ctx_index; | 77 | u32 stage_id; |
76 | uint32_t proc_desc_offset; | 78 | uint32_t proc_desc_offset; |
77 | 79 | ||
78 | uint32_t doorbell_offset; | 80 | u16 doorbell_id; |
79 | uint32_t doorbell_cookie; | 81 | unsigned long doorbell_offset; |
80 | uint16_t doorbell_id; | 82 | u32 doorbell_cookie; |
81 | uint16_t padding[3]; /* Maintain alignment */ | ||
82 | 83 | ||
83 | spinlock_t wq_lock; | 84 | spinlock_t wq_lock; |
84 | uint32_t wq_offset; | 85 | uint32_t wq_offset; |
@@ -100,11 +101,40 @@ enum intel_uc_fw_status { | |||
100 | INTEL_UC_FIRMWARE_SUCCESS | 101 | INTEL_UC_FIRMWARE_SUCCESS |
101 | }; | 102 | }; |
102 | 103 | ||
104 | /* User-friendly representation of an enum */ | ||
105 | static inline | ||
106 | const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) | ||
107 | { | ||
108 | switch (status) { | ||
109 | case INTEL_UC_FIRMWARE_FAIL: | ||
110 | return "FAIL"; | ||
111 | case INTEL_UC_FIRMWARE_NONE: | ||
112 | return "NONE"; | ||
113 | case INTEL_UC_FIRMWARE_PENDING: | ||
114 | return "PENDING"; | ||
115 | case INTEL_UC_FIRMWARE_SUCCESS: | ||
116 | return "SUCCESS"; | ||
117 | } | ||
118 | return "<invalid>"; | ||
119 | } | ||
120 | |||
103 | enum intel_uc_fw_type { | 121 | enum intel_uc_fw_type { |
104 | INTEL_UC_FW_TYPE_GUC, | 122 | INTEL_UC_FW_TYPE_GUC, |
105 | INTEL_UC_FW_TYPE_HUC | 123 | INTEL_UC_FW_TYPE_HUC |
106 | }; | 124 | }; |
107 | 125 | ||
126 | /* User-friendly representation of an enum */ | ||
127 | static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type) | ||
128 | { | ||
129 | switch (type) { | ||
130 | case INTEL_UC_FW_TYPE_GUC: | ||
131 | return "GuC"; | ||
132 | case INTEL_UC_FW_TYPE_HUC: | ||
133 | return "HuC"; | ||
134 | } | ||
135 | return "uC"; | ||
136 | } | ||
137 | |||
108 | /* | 138 | /* |
109 | * This structure encapsulates all the data needed during the process | 139 | * This structure encapsulates all the data needed during the process |
110 | * of fetching, caching, and loading the firmware image into the GuC. | 140 | * of fetching, caching, and loading the firmware image into the GuC. |
@@ -133,11 +163,13 @@ struct intel_uc_fw { | |||
133 | struct intel_guc_log { | 163 | struct intel_guc_log { |
134 | uint32_t flags; | 164 | uint32_t flags; |
135 | struct i915_vma *vma; | 165 | struct i915_vma *vma; |
136 | void *buf_addr; | 166 | /* The runtime stuff gets created only when GuC logging gets enabled */ |
137 | struct workqueue_struct *flush_wq; | 167 | struct { |
138 | struct work_struct flush_work; | 168 | void *buf_addr; |
139 | struct rchan *relay_chan; | 169 | struct workqueue_struct *flush_wq; |
140 | 170 | struct work_struct flush_work; | |
171 | struct rchan *relay_chan; | ||
172 | } runtime; | ||
141 | /* logging related stats */ | 173 | /* logging related stats */ |
142 | u32 capture_miss_count; | 174 | u32 capture_miss_count; |
143 | u32 flush_interrupt_count; | 175 | u32 flush_interrupt_count; |
@@ -154,12 +186,13 @@ struct intel_guc { | |||
154 | bool interrupts_enabled; | 186 | bool interrupts_enabled; |
155 | 187 | ||
156 | struct i915_vma *ads_vma; | 188 | struct i915_vma *ads_vma; |
157 | struct i915_vma *ctx_pool_vma; | 189 | struct i915_vma *stage_desc_pool; |
158 | struct ida ctx_ids; | 190 | void *stage_desc_pool_vaddr; |
191 | struct ida stage_ids; | ||
159 | 192 | ||
160 | struct i915_guc_client *execbuf_client; | 193 | struct i915_guc_client *execbuf_client; |
161 | 194 | ||
162 | DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS); | 195 | DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS); |
163 | uint32_t db_cacheline; /* Cyclic counter mod pagesize */ | 196 | uint32_t db_cacheline; /* Cyclic counter mod pagesize */ |
164 | 197 | ||
165 | /* Action status & statistics */ | 198 | /* Action status & statistics */ |
@@ -174,6 +207,9 @@ struct intel_guc { | |||
174 | 207 | ||
175 | /* To serialize the intel_guc_send actions */ | 208 | /* To serialize the intel_guc_send actions */ |
176 | struct mutex send_mutex; | 209 | struct mutex send_mutex; |
210 | |||
211 | /* GuC's FW specific send function */ | ||
212 | int (*send)(struct intel_guc *guc, const u32 *data, u32 len); | ||
177 | }; | 213 | }; |
178 | 214 | ||
179 | struct intel_huc { | 215 | struct intel_huc { |
@@ -187,17 +223,19 @@ struct intel_huc { | |||
187 | void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); | 223 | void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); |
188 | void intel_uc_init_early(struct drm_i915_private *dev_priv); | 224 | void intel_uc_init_early(struct drm_i915_private *dev_priv); |
189 | void intel_uc_init_fw(struct drm_i915_private *dev_priv); | 225 | void intel_uc_init_fw(struct drm_i915_private *dev_priv); |
226 | void intel_uc_fini_fw(struct drm_i915_private *dev_priv); | ||
190 | int intel_uc_init_hw(struct drm_i915_private *dev_priv); | 227 | int intel_uc_init_hw(struct drm_i915_private *dev_priv); |
191 | void intel_uc_prepare_fw(struct drm_i915_private *dev_priv, | 228 | void intel_uc_fini_hw(struct drm_i915_private *dev_priv); |
192 | struct intel_uc_fw *uc_fw); | ||
193 | int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len); | ||
194 | int intel_guc_sample_forcewake(struct intel_guc *guc); | 229 | int intel_guc_sample_forcewake(struct intel_guc *guc); |
230 | int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); | ||
231 | static inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) | ||
232 | { | ||
233 | return guc->send(guc, action, len); | ||
234 | } | ||
195 | 235 | ||
196 | /* intel_guc_loader.c */ | 236 | /* intel_guc_loader.c */ |
197 | int intel_guc_select_fw(struct intel_guc *guc); | 237 | int intel_guc_select_fw(struct intel_guc *guc); |
198 | int intel_guc_init_hw(struct intel_guc *guc); | 238 | int intel_guc_init_hw(struct intel_guc *guc); |
199 | void intel_guc_fini(struct drm_i915_private *dev_priv); | ||
200 | const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status); | ||
201 | int intel_guc_suspend(struct drm_i915_private *dev_priv); | 239 | int intel_guc_suspend(struct drm_i915_private *dev_priv); |
202 | int intel_guc_resume(struct drm_i915_private *dev_priv); | 240 | int intel_guc_resume(struct drm_i915_private *dev_priv); |
203 | u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); | 241 | u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); |
@@ -212,10 +250,11 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv); | |||
212 | struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); | 250 | struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); |
213 | 251 | ||
214 | /* intel_guc_log.c */ | 252 | /* intel_guc_log.c */ |
215 | void intel_guc_log_create(struct intel_guc *guc); | 253 | int intel_guc_log_create(struct intel_guc *guc); |
254 | void intel_guc_log_destroy(struct intel_guc *guc); | ||
255 | int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val); | ||
216 | void i915_guc_log_register(struct drm_i915_private *dev_priv); | 256 | void i915_guc_log_register(struct drm_i915_private *dev_priv); |
217 | void i915_guc_log_unregister(struct drm_i915_private *dev_priv); | 257 | void i915_guc_log_unregister(struct drm_i915_private *dev_priv); |
218 | int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val); | ||
219 | 258 | ||
220 | static inline u32 guc_ggtt_offset(struct i915_vma *vma) | 259 | static inline u32 guc_ggtt_offset(struct i915_vma *vma) |
221 | { | 260 | { |
@@ -227,7 +266,6 @@ static inline u32 guc_ggtt_offset(struct i915_vma *vma) | |||
227 | 266 | ||
228 | /* intel_huc.c */ | 267 | /* intel_huc.c */ |
229 | void intel_huc_select_fw(struct intel_huc *huc); | 268 | void intel_huc_select_fw(struct intel_huc *huc); |
230 | void intel_huc_fini(struct drm_i915_private *dev_priv); | ||
231 | int intel_huc_init_hw(struct intel_huc *huc); | 269 | int intel_huc_init_hw(struct intel_huc *huc); |
232 | void intel_guc_auth_huc(struct drm_i915_private *dev_priv); | 270 | void intel_guc_auth_huc(struct drm_i915_private *dev_priv); |
233 | 271 | ||
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 09f5f02d7901..6d1ea26b2493 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c | |||
@@ -52,10 +52,10 @@ intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id) | |||
52 | } | 52 | } |
53 | 53 | ||
54 | static inline void | 54 | static inline void |
55 | fw_domain_reset(const struct intel_uncore_forcewake_domain *d) | 55 | fw_domain_reset(struct drm_i915_private *i915, |
56 | const struct intel_uncore_forcewake_domain *d) | ||
56 | { | 57 | { |
57 | WARN_ON(!i915_mmio_reg_valid(d->reg_set)); | 58 | __raw_i915_write32(i915, d->reg_set, i915->uncore.fw_reset); |
58 | __raw_i915_write32(d->i915, d->reg_set, d->val_reset); | ||
59 | } | 59 | } |
60 | 60 | ||
61 | static inline void | 61 | static inline void |
@@ -69,9 +69,10 @@ fw_domain_arm_timer(struct intel_uncore_forcewake_domain *d) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | static inline void | 71 | static inline void |
72 | fw_domain_wait_ack_clear(const struct intel_uncore_forcewake_domain *d) | 72 | fw_domain_wait_ack_clear(const struct drm_i915_private *i915, |
73 | const struct intel_uncore_forcewake_domain *d) | ||
73 | { | 74 | { |
74 | if (wait_for_atomic((__raw_i915_read32(d->i915, d->reg_ack) & | 75 | if (wait_for_atomic((__raw_i915_read32(i915, d->reg_ack) & |
75 | FORCEWAKE_KERNEL) == 0, | 76 | FORCEWAKE_KERNEL) == 0, |
76 | FORCEWAKE_ACK_TIMEOUT_MS)) | 77 | FORCEWAKE_ACK_TIMEOUT_MS)) |
77 | DRM_ERROR("%s: timed out waiting for forcewake ack to clear.\n", | 78 | DRM_ERROR("%s: timed out waiting for forcewake ack to clear.\n", |
@@ -79,15 +80,17 @@ fw_domain_wait_ack_clear(const struct intel_uncore_forcewake_domain *d) | |||
79 | } | 80 | } |
80 | 81 | ||
81 | static inline void | 82 | static inline void |
82 | fw_domain_get(const struct intel_uncore_forcewake_domain *d) | 83 | fw_domain_get(struct drm_i915_private *i915, |
84 | const struct intel_uncore_forcewake_domain *d) | ||
83 | { | 85 | { |
84 | __raw_i915_write32(d->i915, d->reg_set, d->val_set); | 86 | __raw_i915_write32(i915, d->reg_set, i915->uncore.fw_set); |
85 | } | 87 | } |
86 | 88 | ||
87 | static inline void | 89 | static inline void |
88 | fw_domain_wait_ack(const struct intel_uncore_forcewake_domain *d) | 90 | fw_domain_wait_ack(const struct drm_i915_private *i915, |
91 | const struct intel_uncore_forcewake_domain *d) | ||
89 | { | 92 | { |
90 | if (wait_for_atomic((__raw_i915_read32(d->i915, d->reg_ack) & | 93 | if (wait_for_atomic((__raw_i915_read32(i915, d->reg_ack) & |
91 | FORCEWAKE_KERNEL), | 94 | FORCEWAKE_KERNEL), |
92 | FORCEWAKE_ACK_TIMEOUT_MS)) | 95 | FORCEWAKE_ACK_TIMEOUT_MS)) |
93 | DRM_ERROR("%s: timed out waiting for forcewake ack request.\n", | 96 | DRM_ERROR("%s: timed out waiting for forcewake ack request.\n", |
@@ -95,72 +98,59 @@ fw_domain_wait_ack(const struct intel_uncore_forcewake_domain *d) | |||
95 | } | 98 | } |
96 | 99 | ||
97 | static inline void | 100 | static inline void |
98 | fw_domain_put(const struct intel_uncore_forcewake_domain *d) | 101 | fw_domain_put(const struct drm_i915_private *i915, |
102 | const struct intel_uncore_forcewake_domain *d) | ||
99 | { | 103 | { |
100 | __raw_i915_write32(d->i915, d->reg_set, d->val_clear); | 104 | __raw_i915_write32(i915, d->reg_set, i915->uncore.fw_clear); |
101 | } | ||
102 | |||
103 | static inline void | ||
104 | fw_domain_posting_read(const struct intel_uncore_forcewake_domain *d) | ||
105 | { | ||
106 | /* something from same cacheline, but not from the set register */ | ||
107 | if (i915_mmio_reg_valid(d->reg_post)) | ||
108 | __raw_posting_read(d->i915, d->reg_post); | ||
109 | } | 105 | } |
110 | 106 | ||
111 | static void | 107 | static void |
112 | fw_domains_get(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains) | 108 | fw_domains_get(struct drm_i915_private *i915, enum forcewake_domains fw_domains) |
113 | { | 109 | { |
114 | struct intel_uncore_forcewake_domain *d; | 110 | struct intel_uncore_forcewake_domain *d; |
111 | unsigned int tmp; | ||
115 | 112 | ||
116 | for_each_fw_domain_masked(d, fw_domains, dev_priv) { | 113 | GEM_BUG_ON(fw_domains & ~i915->uncore.fw_domains); |
117 | fw_domain_wait_ack_clear(d); | 114 | |
118 | fw_domain_get(d); | 115 | for_each_fw_domain_masked(d, fw_domains, i915, tmp) { |
116 | fw_domain_wait_ack_clear(i915, d); | ||
117 | fw_domain_get(i915, d); | ||
119 | } | 118 | } |
120 | 119 | ||
121 | for_each_fw_domain_masked(d, fw_domains, dev_priv) | 120 | for_each_fw_domain_masked(d, fw_domains, i915, tmp) |
122 | fw_domain_wait_ack(d); | 121 | fw_domain_wait_ack(i915, d); |
123 | 122 | ||
124 | dev_priv->uncore.fw_domains_active |= fw_domains; | 123 | i915->uncore.fw_domains_active |= fw_domains; |
125 | } | 124 | } |
126 | 125 | ||
127 | static void | 126 | static void |
128 | fw_domains_put(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains) | 127 | fw_domains_put(struct drm_i915_private *i915, enum forcewake_domains fw_domains) |
129 | { | 128 | { |
130 | struct intel_uncore_forcewake_domain *d; | 129 | struct intel_uncore_forcewake_domain *d; |
130 | unsigned int tmp; | ||
131 | 131 | ||
132 | for_each_fw_domain_masked(d, fw_domains, dev_priv) { | 132 | GEM_BUG_ON(fw_domains & ~i915->uncore.fw_domains); |
133 | fw_domain_put(d); | ||
134 | fw_domain_posting_read(d); | ||
135 | } | ||
136 | |||
137 | dev_priv->uncore.fw_domains_active &= ~fw_domains; | ||
138 | } | ||
139 | 133 | ||
140 | static void | 134 | for_each_fw_domain_masked(d, fw_domains, i915, tmp) |
141 | fw_domains_posting_read(struct drm_i915_private *dev_priv) | 135 | fw_domain_put(i915, d); |
142 | { | ||
143 | struct intel_uncore_forcewake_domain *d; | ||
144 | 136 | ||
145 | /* No need to do for all, just do for first found */ | 137 | i915->uncore.fw_domains_active &= ~fw_domains; |
146 | for_each_fw_domain(d, dev_priv) { | ||
147 | fw_domain_posting_read(d); | ||
148 | break; | ||
149 | } | ||
150 | } | 138 | } |
151 | 139 | ||
152 | static void | 140 | static void |
153 | fw_domains_reset(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains) | 141 | fw_domains_reset(struct drm_i915_private *i915, |
142 | enum forcewake_domains fw_domains) | ||
154 | { | 143 | { |
155 | struct intel_uncore_forcewake_domain *d; | 144 | struct intel_uncore_forcewake_domain *d; |
145 | unsigned int tmp; | ||
156 | 146 | ||
157 | if (dev_priv->uncore.fw_domains == 0) | 147 | if (!fw_domains) |
158 | return; | 148 | return; |
159 | 149 | ||
160 | for_each_fw_domain_masked(d, fw_domains, dev_priv) | 150 | GEM_BUG_ON(fw_domains & ~i915->uncore.fw_domains); |
161 | fw_domain_reset(d); | ||
162 | 151 | ||
163 | fw_domains_posting_read(dev_priv); | 152 | for_each_fw_domain_masked(d, fw_domains, i915, tmp) |
153 | fw_domain_reset(i915, d); | ||
164 | } | 154 | } |
165 | 155 | ||
166 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) | 156 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) |
@@ -236,7 +226,8 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) | |||
236 | { | 226 | { |
237 | struct intel_uncore_forcewake_domain *domain = | 227 | struct intel_uncore_forcewake_domain *domain = |
238 | container_of(timer, struct intel_uncore_forcewake_domain, timer); | 228 | container_of(timer, struct intel_uncore_forcewake_domain, timer); |
239 | struct drm_i915_private *dev_priv = domain->i915; | 229 | struct drm_i915_private *dev_priv = |
230 | container_of(domain, struct drm_i915_private, uncore.fw_domain[domain->id]); | ||
240 | unsigned long irqflags; | 231 | unsigned long irqflags; |
241 | 232 | ||
242 | assert_rpm_device_not_suspended(dev_priv); | 233 | assert_rpm_device_not_suspended(dev_priv); |
@@ -266,9 +257,11 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, | |||
266 | * timers are run before holding. | 257 | * timers are run before holding. |
267 | */ | 258 | */ |
268 | while (1) { | 259 | while (1) { |
260 | unsigned int tmp; | ||
261 | |||
269 | active_domains = 0; | 262 | active_domains = 0; |
270 | 263 | ||
271 | for_each_fw_domain(domain, dev_priv) { | 264 | for_each_fw_domain(domain, dev_priv, tmp) { |
272 | if (hrtimer_cancel(&domain->timer) == 0) | 265 | if (hrtimer_cancel(&domain->timer) == 0) |
273 | continue; | 266 | continue; |
274 | 267 | ||
@@ -277,7 +270,7 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, | |||
277 | 270 | ||
278 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 271 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
279 | 272 | ||
280 | for_each_fw_domain(domain, dev_priv) { | 273 | for_each_fw_domain(domain, dev_priv, tmp) { |
281 | if (hrtimer_active(&domain->timer)) | 274 | if (hrtimer_active(&domain->timer)) |
282 | active_domains |= domain->mask; | 275 | active_domains |= domain->mask; |
283 | } | 276 | } |
@@ -300,7 +293,7 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, | |||
300 | if (fw) | 293 | if (fw) |
301 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); | 294 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); |
302 | 295 | ||
303 | fw_domains_reset(dev_priv, FORCEWAKE_ALL); | 296 | fw_domains_reset(dev_priv, dev_priv->uncore.fw_domains); |
304 | 297 | ||
305 | if (restore) { /* If reset with a user forcewake, try to restore */ | 298 | if (restore) { /* If reset with a user forcewake, try to restore */ |
306 | if (fw) | 299 | if (fw) |
@@ -457,13 +450,13 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, | |||
457 | enum forcewake_domains fw_domains) | 450 | enum forcewake_domains fw_domains) |
458 | { | 451 | { |
459 | struct intel_uncore_forcewake_domain *domain; | 452 | struct intel_uncore_forcewake_domain *domain; |
453 | unsigned int tmp; | ||
460 | 454 | ||
461 | fw_domains &= dev_priv->uncore.fw_domains; | 455 | fw_domains &= dev_priv->uncore.fw_domains; |
462 | 456 | ||
463 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { | 457 | for_each_fw_domain_masked(domain, fw_domains, dev_priv, tmp) |
464 | if (domain->wake_count++) | 458 | if (domain->wake_count++) |
465 | fw_domains &= ~domain->mask; | 459 | fw_domains &= ~domain->mask; |
466 | } | ||
467 | 460 | ||
468 | if (fw_domains) | 461 | if (fw_domains) |
469 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | 462 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); |
@@ -520,10 +513,11 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, | |||
520 | enum forcewake_domains fw_domains) | 513 | enum forcewake_domains fw_domains) |
521 | { | 514 | { |
522 | struct intel_uncore_forcewake_domain *domain; | 515 | struct intel_uncore_forcewake_domain *domain; |
516 | unsigned int tmp; | ||
523 | 517 | ||
524 | fw_domains &= dev_priv->uncore.fw_domains; | 518 | fw_domains &= dev_priv->uncore.fw_domains; |
525 | 519 | ||
526 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { | 520 | for_each_fw_domain_masked(domain, fw_domains, dev_priv, tmp) { |
527 | if (WARN_ON(domain->wake_count == 0)) | 521 | if (WARN_ON(domain->wake_count == 0)) |
528 | continue; | 522 | continue; |
529 | 523 | ||
@@ -928,8 +922,11 @@ static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv, | |||
928 | enum forcewake_domains fw_domains) | 922 | enum forcewake_domains fw_domains) |
929 | { | 923 | { |
930 | struct intel_uncore_forcewake_domain *domain; | 924 | struct intel_uncore_forcewake_domain *domain; |
925 | unsigned int tmp; | ||
926 | |||
927 | GEM_BUG_ON(fw_domains & ~dev_priv->uncore.fw_domains); | ||
931 | 928 | ||
932 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) | 929 | for_each_fw_domain_masked(domain, fw_domains, dev_priv, tmp) |
933 | fw_domain_arm_timer(domain); | 930 | fw_domain_arm_timer(domain); |
934 | 931 | ||
935 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | 932 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); |
@@ -1141,41 +1138,27 @@ static void fw_domain_init(struct drm_i915_private *dev_priv, | |||
1141 | 1138 | ||
1142 | WARN_ON(d->wake_count); | 1139 | WARN_ON(d->wake_count); |
1143 | 1140 | ||
1141 | WARN_ON(!i915_mmio_reg_valid(reg_set)); | ||
1142 | WARN_ON(!i915_mmio_reg_valid(reg_ack)); | ||
1143 | |||
1144 | d->wake_count = 0; | 1144 | d->wake_count = 0; |
1145 | d->reg_set = reg_set; | 1145 | d->reg_set = reg_set; |
1146 | d->reg_ack = reg_ack; | 1146 | d->reg_ack = reg_ack; |
1147 | 1147 | ||
1148 | if (IS_GEN6(dev_priv)) { | ||
1149 | d->val_reset = 0; | ||
1150 | d->val_set = FORCEWAKE_KERNEL; | ||
1151 | d->val_clear = 0; | ||
1152 | } else { | ||
1153 | /* WaRsClearFWBitsAtReset:bdw,skl */ | ||
1154 | d->val_reset = _MASKED_BIT_DISABLE(0xffff); | ||
1155 | d->val_set = _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL); | ||
1156 | d->val_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL); | ||
1157 | } | ||
1158 | |||
1159 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) | ||
1160 | d->reg_post = FORCEWAKE_ACK_VLV; | ||
1161 | else if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) | ||
1162 | d->reg_post = ECOBUS; | ||
1163 | |||
1164 | d->i915 = dev_priv; | ||
1165 | d->id = domain_id; | 1148 | d->id = domain_id; |
1166 | 1149 | ||
1167 | BUILD_BUG_ON(FORCEWAKE_RENDER != (1 << FW_DOMAIN_ID_RENDER)); | 1150 | BUILD_BUG_ON(FORCEWAKE_RENDER != (1 << FW_DOMAIN_ID_RENDER)); |
1168 | BUILD_BUG_ON(FORCEWAKE_BLITTER != (1 << FW_DOMAIN_ID_BLITTER)); | 1151 | BUILD_BUG_ON(FORCEWAKE_BLITTER != (1 << FW_DOMAIN_ID_BLITTER)); |
1169 | BUILD_BUG_ON(FORCEWAKE_MEDIA != (1 << FW_DOMAIN_ID_MEDIA)); | 1152 | BUILD_BUG_ON(FORCEWAKE_MEDIA != (1 << FW_DOMAIN_ID_MEDIA)); |
1170 | 1153 | ||
1171 | d->mask = 1 << domain_id; | 1154 | d->mask = BIT(domain_id); |
1172 | 1155 | ||
1173 | hrtimer_init(&d->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 1156 | hrtimer_init(&d->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
1174 | d->timer.function = intel_uncore_fw_release_timer; | 1157 | d->timer.function = intel_uncore_fw_release_timer; |
1175 | 1158 | ||
1176 | dev_priv->uncore.fw_domains |= (1 << domain_id); | 1159 | dev_priv->uncore.fw_domains |= BIT(domain_id); |
1177 | 1160 | ||
1178 | fw_domain_reset(d); | 1161 | fw_domain_reset(dev_priv, d); |
1179 | } | 1162 | } |
1180 | 1163 | ||
1181 | static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | 1164 | static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) |
@@ -1183,6 +1166,17 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | |||
1183 | if (INTEL_GEN(dev_priv) <= 5 || intel_vgpu_active(dev_priv)) | 1166 | if (INTEL_GEN(dev_priv) <= 5 || intel_vgpu_active(dev_priv)) |
1184 | return; | 1167 | return; |
1185 | 1168 | ||
1169 | if (IS_GEN6(dev_priv)) { | ||
1170 | dev_priv->uncore.fw_reset = 0; | ||
1171 | dev_priv->uncore.fw_set = FORCEWAKE_KERNEL; | ||
1172 | dev_priv->uncore.fw_clear = 0; | ||
1173 | } else { | ||
1174 | /* WaRsClearFWBitsAtReset:bdw,skl */ | ||
1175 | dev_priv->uncore.fw_reset = _MASKED_BIT_DISABLE(0xffff); | ||
1176 | dev_priv->uncore.fw_set = _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL); | ||
1177 | dev_priv->uncore.fw_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL); | ||
1178 | } | ||
1179 | |||
1186 | if (IS_GEN9(dev_priv)) { | 1180 | if (IS_GEN9(dev_priv)) { |
1187 | dev_priv->uncore.funcs.force_wake_get = fw_domains_get; | 1181 | dev_priv->uncore.funcs.force_wake_get = fw_domains_get; |
1188 | dev_priv->uncore.funcs.force_wake_put = fw_domains_put; | 1182 | dev_priv->uncore.funcs.force_wake_put = fw_domains_put; |
@@ -1246,9 +1240,9 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | |||
1246 | FORCEWAKE_MT, FORCEWAKE_MT_ACK); | 1240 | FORCEWAKE_MT, FORCEWAKE_MT_ACK); |
1247 | 1241 | ||
1248 | spin_lock_irq(&dev_priv->uncore.lock); | 1242 | spin_lock_irq(&dev_priv->uncore.lock); |
1249 | fw_domains_get_with_thread_status(dev_priv, FORCEWAKE_ALL); | 1243 | fw_domains_get_with_thread_status(dev_priv, FORCEWAKE_RENDER); |
1250 | ecobus = __raw_i915_read32(dev_priv, ECOBUS); | 1244 | ecobus = __raw_i915_read32(dev_priv, ECOBUS); |
1251 | fw_domains_put_with_fifo(dev_priv, FORCEWAKE_ALL); | 1245 | fw_domains_put_with_fifo(dev_priv, FORCEWAKE_RENDER); |
1252 | spin_unlock_irq(&dev_priv->uncore.lock); | 1246 | spin_unlock_irq(&dev_priv->uncore.lock); |
1253 | 1247 | ||
1254 | if (!(ecobus & FORCEWAKE_MT_ENABLE)) { | 1248 | if (!(ecobus & FORCEWAKE_MT_ENABLE)) { |
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 926b24c117d6..98b7aac41eec 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c | |||
@@ -291,8 +291,6 @@ static int begin_live_test(struct live_test *t, | |||
291 | return err; | 291 | return err; |
292 | } | 292 | } |
293 | 293 | ||
294 | i915_gem_retire_requests(i915); | ||
295 | |||
296 | i915->gpu_error.missed_irq_rings = 0; | 294 | i915->gpu_error.missed_irq_rings = 0; |
297 | t->reset_count = i915_reset_count(&i915->gpu_error); | 295 | t->reset_count = i915_reset_count(&i915->gpu_error); |
298 | 296 | ||
@@ -303,7 +301,9 @@ static int end_live_test(struct live_test *t) | |||
303 | { | 301 | { |
304 | struct drm_i915_private *i915 = t->i915; | 302 | struct drm_i915_private *i915 = t->i915; |
305 | 303 | ||
306 | if (wait_for(intel_engines_are_idle(i915), 1)) { | 304 | i915_gem_retire_requests(i915); |
305 | |||
306 | if (wait_for(intel_engines_are_idle(i915), 10)) { | ||
307 | pr_err("%s(%s): GPU not idle\n", t->func, t->name); | 307 | pr_err("%s(%s): GPU not idle\n", t->func, t->name); |
308 | return -EIO; | 308 | return -EIO; |
309 | } | 309 | } |
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 6ec7c731a267..aa31d6c0cdfb 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c | |||
@@ -235,7 +235,6 @@ static void hang_fini(struct hang *h) | |||
235 | i915_gem_object_put(h->hws); | 235 | i915_gem_object_put(h->hws); |
236 | 236 | ||
237 | i915_gem_wait_for_idle(h->i915, I915_WAIT_LOCKED); | 237 | i915_gem_wait_for_idle(h->i915, I915_WAIT_LOCKED); |
238 | i915_gem_retire_requests(h->i915); | ||
239 | } | 238 | } |
240 | 239 | ||
241 | static int igt_hang_sanitycheck(void *arg) | 240 | static int igt_hang_sanitycheck(void *arg) |
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c index 8d5ba037064c..0ad624a1db90 100644 --- a/drivers/gpu/drm/i915/selftests/mock_engine.c +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c | |||
@@ -118,7 +118,6 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine) | |||
118 | ring->vaddr = (void *)(ring + 1); | 118 | ring->vaddr = (void *)(ring + 1); |
119 | 119 | ||
120 | INIT_LIST_HEAD(&ring->request_list); | 120 | INIT_LIST_HEAD(&ring->request_list); |
121 | ring->last_retired_head = -1; | ||
122 | intel_ring_update_space(ring); | 121 | intel_ring_update_space(ring); |
123 | 122 | ||
124 | return ring; | 123 | return ring; |
diff --git a/drivers/gpu/drm/i915/selftests/scatterlist.c b/drivers/gpu/drm/i915/selftests/scatterlist.c index eb2cda8e2b9f..1cc5d2931753 100644 --- a/drivers/gpu/drm/i915/selftests/scatterlist.c +++ b/drivers/gpu/drm/i915/selftests/scatterlist.c | |||
@@ -189,6 +189,13 @@ static unsigned int random(unsigned long n, | |||
189 | return 1 + (prandom_u32_state(rnd) % 1024); | 189 | return 1 + (prandom_u32_state(rnd) % 1024); |
190 | } | 190 | } |
191 | 191 | ||
192 | static inline bool page_contiguous(struct page *first, | ||
193 | struct page *last, | ||
194 | unsigned long npages) | ||
195 | { | ||
196 | return first + npages == last; | ||
197 | } | ||
198 | |||
192 | static int alloc_table(struct pfn_table *pt, | 199 | static int alloc_table(struct pfn_table *pt, |
193 | unsigned long count, unsigned long max, | 200 | unsigned long count, unsigned long max, |
194 | npages_fn_t npages_fn, | 201 | npages_fn_t npages_fn, |
@@ -216,7 +223,9 @@ static int alloc_table(struct pfn_table *pt, | |||
216 | unsigned long npages = npages_fn(n, count, rnd); | 223 | unsigned long npages = npages_fn(n, count, rnd); |
217 | 224 | ||
218 | /* Nobody expects the Sparse Memmap! */ | 225 | /* Nobody expects the Sparse Memmap! */ |
219 | if (pfn_to_page(pfn + npages) != pfn_to_page(pfn) + npages) { | 226 | if (!page_contiguous(pfn_to_page(pfn), |
227 | pfn_to_page(pfn + npages), | ||
228 | npages)) { | ||
220 | sg_free_table(&pt->st); | 229 | sg_free_table(&pt->st); |
221 | return -ENOSPC; | 230 | return -ENOSPC; |
222 | } | 231 | } |
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index c70310206ac5..a14d7d64d7b1 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c | |||
@@ -35,18 +35,28 @@ | |||
35 | #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) | 35 | #define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n)) |
36 | #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) | 36 | #define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n)) |
37 | #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) | 37 | #define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n)) |
38 | #define DISP_REG_OVL_ADDR(n) (0x0f40 + 0x20 * (n)) | 38 | #define DISP_REG_OVL_ADDR_MT2701 0x0040 |
39 | #define DISP_REG_OVL_ADDR_MT8173 0x0f40 | ||
40 | #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) | ||
39 | 41 | ||
40 | #define OVL_RDMA_MEM_GMC 0x40402020 | 42 | #define OVL_RDMA_MEM_GMC 0x40402020 |
41 | 43 | ||
42 | #define OVL_CON_BYTE_SWAP BIT(24) | 44 | #define OVL_CON_BYTE_SWAP BIT(24) |
43 | #define OVL_CON_CLRFMT_RGB565 (0 << 12) | 45 | #define OVL_CON_CLRFMT_RGB (1 << 12) |
44 | #define OVL_CON_CLRFMT_RGB888 (1 << 12) | ||
45 | #define OVL_CON_CLRFMT_RGBA8888 (2 << 12) | 46 | #define OVL_CON_CLRFMT_RGBA8888 (2 << 12) |
46 | #define OVL_CON_CLRFMT_ARGB8888 (3 << 12) | 47 | #define OVL_CON_CLRFMT_ARGB8888 (3 << 12) |
48 | #define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ | ||
49 | 0 : OVL_CON_CLRFMT_RGB) | ||
50 | #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ | ||
51 | OVL_CON_CLRFMT_RGB : 0) | ||
47 | #define OVL_CON_AEN BIT(8) | 52 | #define OVL_CON_AEN BIT(8) |
48 | #define OVL_CON_ALPHA 0xff | 53 | #define OVL_CON_ALPHA 0xff |
49 | 54 | ||
55 | struct mtk_disp_ovl_data { | ||
56 | unsigned int addr; | ||
57 | bool fmt_rgb565_is_0; | ||
58 | }; | ||
59 | |||
50 | /** | 60 | /** |
51 | * struct mtk_disp_ovl - DISP_OVL driver structure | 61 | * struct mtk_disp_ovl - DISP_OVL driver structure |
52 | * @ddp_comp - structure containing type enum and hardware resources | 62 | * @ddp_comp - structure containing type enum and hardware resources |
@@ -55,8 +65,14 @@ | |||
55 | struct mtk_disp_ovl { | 65 | struct mtk_disp_ovl { |
56 | struct mtk_ddp_comp ddp_comp; | 66 | struct mtk_ddp_comp ddp_comp; |
57 | struct drm_crtc *crtc; | 67 | struct drm_crtc *crtc; |
68 | const struct mtk_disp_ovl_data *data; | ||
58 | }; | 69 | }; |
59 | 70 | ||
71 | static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp) | ||
72 | { | ||
73 | return container_of(comp, struct mtk_disp_ovl, ddp_comp); | ||
74 | } | ||
75 | |||
60 | static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) | 76 | static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) |
61 | { | 77 | { |
62 | struct mtk_disp_ovl *priv = dev_id; | 78 | struct mtk_disp_ovl *priv = dev_id; |
@@ -76,20 +92,18 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id) | |||
76 | static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, | 92 | static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, |
77 | struct drm_crtc *crtc) | 93 | struct drm_crtc *crtc) |
78 | { | 94 | { |
79 | struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, | 95 | struct mtk_disp_ovl *ovl = comp_to_ovl(comp); |
80 | ddp_comp); | ||
81 | 96 | ||
82 | priv->crtc = crtc; | 97 | ovl->crtc = crtc; |
83 | writel(0x0, comp->regs + DISP_REG_OVL_INTSTA); | 98 | writel(0x0, comp->regs + DISP_REG_OVL_INTSTA); |
84 | writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); | 99 | writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); |
85 | } | 100 | } |
86 | 101 | ||
87 | static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp) | 102 | static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp) |
88 | { | 103 | { |
89 | struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl, | 104 | struct mtk_disp_ovl *ovl = comp_to_ovl(comp); |
90 | ddp_comp); | ||
91 | 105 | ||
92 | priv->crtc = NULL; | 106 | ovl->crtc = NULL; |
93 | writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN); | 107 | writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN); |
94 | } | 108 | } |
95 | 109 | ||
@@ -138,18 +152,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx) | |||
138 | writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx)); | 152 | writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx)); |
139 | } | 153 | } |
140 | 154 | ||
141 | static unsigned int ovl_fmt_convert(unsigned int fmt) | 155 | static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) |
142 | { | 156 | { |
143 | switch (fmt) { | 157 | switch (fmt) { |
144 | default: | 158 | default: |
145 | case DRM_FORMAT_RGB565: | 159 | case DRM_FORMAT_RGB565: |
146 | return OVL_CON_CLRFMT_RGB565; | 160 | return OVL_CON_CLRFMT_RGB565(ovl); |
147 | case DRM_FORMAT_BGR565: | 161 | case DRM_FORMAT_BGR565: |
148 | return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP; | 162 | return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP; |
149 | case DRM_FORMAT_RGB888: | 163 | case DRM_FORMAT_RGB888: |
150 | return OVL_CON_CLRFMT_RGB888; | 164 | return OVL_CON_CLRFMT_RGB888(ovl); |
151 | case DRM_FORMAT_BGR888: | 165 | case DRM_FORMAT_BGR888: |
152 | return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP; | 166 | return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP; |
153 | case DRM_FORMAT_RGBX8888: | 167 | case DRM_FORMAT_RGBX8888: |
154 | case DRM_FORMAT_RGBA8888: | 168 | case DRM_FORMAT_RGBA8888: |
155 | return OVL_CON_CLRFMT_ARGB8888; | 169 | return OVL_CON_CLRFMT_ARGB8888; |
@@ -168,6 +182,7 @@ static unsigned int ovl_fmt_convert(unsigned int fmt) | |||
168 | static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, | 182 | static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, |
169 | struct mtk_plane_state *state) | 183 | struct mtk_plane_state *state) |
170 | { | 184 | { |
185 | struct mtk_disp_ovl *ovl = comp_to_ovl(comp); | ||
171 | struct mtk_plane_pending_state *pending = &state->pending; | 186 | struct mtk_plane_pending_state *pending = &state->pending; |
172 | unsigned int addr = pending->addr; | 187 | unsigned int addr = pending->addr; |
173 | unsigned int pitch = pending->pitch & 0xffff; | 188 | unsigned int pitch = pending->pitch & 0xffff; |
@@ -179,7 +194,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, | |||
179 | if (!pending->enable) | 194 | if (!pending->enable) |
180 | mtk_ovl_layer_off(comp, idx); | 195 | mtk_ovl_layer_off(comp, idx); |
181 | 196 | ||
182 | con = ovl_fmt_convert(fmt); | 197 | con = ovl_fmt_convert(ovl, fmt); |
183 | if (idx != 0) | 198 | if (idx != 0) |
184 | con |= OVL_CON_AEN | OVL_CON_ALPHA; | 199 | con |= OVL_CON_AEN | OVL_CON_ALPHA; |
185 | 200 | ||
@@ -187,7 +202,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, | |||
187 | writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx)); | 202 | writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx)); |
188 | writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx)); | 203 | writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx)); |
189 | writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx)); | 204 | writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx)); |
190 | writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx)); | 205 | writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx)); |
191 | 206 | ||
192 | if (pending->enable) | 207 | if (pending->enable) |
193 | mtk_ovl_layer_on(comp, idx); | 208 | mtk_ovl_layer_on(comp, idx); |
@@ -264,6 +279,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) | |||
264 | return ret; | 279 | return ret; |
265 | } | 280 | } |
266 | 281 | ||
282 | priv->data = of_device_get_match_data(dev); | ||
283 | |||
267 | platform_set_drvdata(pdev, priv); | 284 | platform_set_drvdata(pdev, priv); |
268 | 285 | ||
269 | ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler, | 286 | ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler, |
@@ -287,8 +304,21 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev) | |||
287 | return 0; | 304 | return 0; |
288 | } | 305 | } |
289 | 306 | ||
307 | static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { | ||
308 | .addr = DISP_REG_OVL_ADDR_MT2701, | ||
309 | .fmt_rgb565_is_0 = false, | ||
310 | }; | ||
311 | |||
312 | static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = { | ||
313 | .addr = DISP_REG_OVL_ADDR_MT8173, | ||
314 | .fmt_rgb565_is_0 = true, | ||
315 | }; | ||
316 | |||
290 | static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = { | 317 | static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = { |
291 | { .compatible = "mediatek,mt8173-disp-ovl", }, | 318 | { .compatible = "mediatek,mt2701-disp-ovl", |
319 | .data = &mt2701_ovl_driver_data}, | ||
320 | { .compatible = "mediatek,mt8173-disp-ovl", | ||
321 | .data = &mt8173_ovl_driver_data}, | ||
292 | {}, | 322 | {}, |
293 | }; | 323 | }; |
294 | MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match); | 324 | MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match); |
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 0df05f95b916..b68a51376f83 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c | |||
@@ -38,6 +38,11 @@ | |||
38 | #define RDMA_FIFO_UNDERFLOW_EN BIT(31) | 38 | #define RDMA_FIFO_UNDERFLOW_EN BIT(31) |
39 | #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16) | 39 | #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16) |
40 | #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16) | 40 | #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16) |
41 | #define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size) | ||
42 | |||
43 | struct mtk_disp_rdma_data { | ||
44 | unsigned int fifo_size; | ||
45 | }; | ||
41 | 46 | ||
42 | /** | 47 | /** |
43 | * struct mtk_disp_rdma - DISP_RDMA driver structure | 48 | * struct mtk_disp_rdma - DISP_RDMA driver structure |
@@ -47,8 +52,14 @@ | |||
47 | struct mtk_disp_rdma { | 52 | struct mtk_disp_rdma { |
48 | struct mtk_ddp_comp ddp_comp; | 53 | struct mtk_ddp_comp ddp_comp; |
49 | struct drm_crtc *crtc; | 54 | struct drm_crtc *crtc; |
55 | const struct mtk_disp_rdma_data *data; | ||
50 | }; | 56 | }; |
51 | 57 | ||
58 | static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp) | ||
59 | { | ||
60 | return container_of(comp, struct mtk_disp_rdma, ddp_comp); | ||
61 | } | ||
62 | |||
52 | static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id) | 63 | static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id) |
53 | { | 64 | { |
54 | struct mtk_disp_rdma *priv = dev_id; | 65 | struct mtk_disp_rdma *priv = dev_id; |
@@ -77,20 +88,18 @@ static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg, | |||
77 | static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp, | 88 | static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp, |
78 | struct drm_crtc *crtc) | 89 | struct drm_crtc *crtc) |
79 | { | 90 | { |
80 | struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, | 91 | struct mtk_disp_rdma *rdma = comp_to_rdma(comp); |
81 | ddp_comp); | ||
82 | 92 | ||
83 | priv->crtc = crtc; | 93 | rdma->crtc = crtc; |
84 | rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, | 94 | rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, |
85 | RDMA_FRAME_END_INT); | 95 | RDMA_FRAME_END_INT); |
86 | } | 96 | } |
87 | 97 | ||
88 | static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp) | 98 | static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp) |
89 | { | 99 | { |
90 | struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma, | 100 | struct mtk_disp_rdma *rdma = comp_to_rdma(comp); |
91 | ddp_comp); | ||
92 | 101 | ||
93 | priv->crtc = NULL; | 102 | rdma->crtc = NULL; |
94 | rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); | 103 | rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); |
95 | } | 104 | } |
96 | 105 | ||
@@ -111,6 +120,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, | |||
111 | { | 120 | { |
112 | unsigned int threshold; | 121 | unsigned int threshold; |
113 | unsigned int reg; | 122 | unsigned int reg; |
123 | struct mtk_disp_rdma *rdma = comp_to_rdma(comp); | ||
114 | 124 | ||
115 | rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width); | 125 | rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width); |
116 | rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height); | 126 | rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height); |
@@ -123,7 +133,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, | |||
123 | */ | 133 | */ |
124 | threshold = width * height * vrefresh * 4 * 7 / 1000000; | 134 | threshold = width * height * vrefresh * 4 * 7 / 1000000; |
125 | reg = RDMA_FIFO_UNDERFLOW_EN | | 135 | reg = RDMA_FIFO_UNDERFLOW_EN | |
126 | RDMA_FIFO_PSEUDO_SIZE(SZ_8K) | | 136 | RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma)) | |
127 | RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold); | 137 | RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold); |
128 | writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); | 138 | writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); |
129 | } | 139 | } |
@@ -208,6 +218,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev) | |||
208 | return ret; | 218 | return ret; |
209 | } | 219 | } |
210 | 220 | ||
221 | priv->data = of_device_get_match_data(dev); | ||
222 | |||
211 | platform_set_drvdata(pdev, priv); | 223 | platform_set_drvdata(pdev, priv); |
212 | 224 | ||
213 | ret = component_add(dev, &mtk_disp_rdma_component_ops); | 225 | ret = component_add(dev, &mtk_disp_rdma_component_ops); |
@@ -224,8 +236,19 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) | |||
224 | return 0; | 236 | return 0; |
225 | } | 237 | } |
226 | 238 | ||
239 | static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = { | ||
240 | .fifo_size = SZ_4K, | ||
241 | }; | ||
242 | |||
243 | static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = { | ||
244 | .fifo_size = SZ_8K, | ||
245 | }; | ||
246 | |||
227 | static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = { | 247 | static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = { |
228 | { .compatible = "mediatek,mt8173-disp-rdma", }, | 248 | { .compatible = "mediatek,mt2701-disp-rdma", |
249 | .data = &mt2701_rdma_driver_data}, | ||
250 | { .compatible = "mediatek,mt8173-disp-rdma", | ||
251 | .data = &mt8173_rdma_driver_data}, | ||
229 | {}, | 252 | {}, |
230 | }; | 253 | }; |
231 | MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match); | 254 | MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match); |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 69982f5a6198..6b08774e5501 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c | |||
@@ -327,6 +327,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) | |||
327 | pm_runtime_put(drm->dev); | 327 | pm_runtime_put(drm->dev); |
328 | } | 328 | } |
329 | 329 | ||
330 | static void mtk_crtc_ddp_config(struct drm_crtc *crtc) | ||
331 | { | ||
332 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); | ||
333 | struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); | ||
334 | struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; | ||
335 | unsigned int i; | ||
336 | |||
337 | /* | ||
338 | * TODO: instead of updating the registers here, we should prepare | ||
339 | * working registers in atomic_commit and let the hardware command | ||
340 | * queue update module registers on vblank. | ||
341 | */ | ||
342 | if (state->pending_config) { | ||
343 | mtk_ddp_comp_config(ovl, state->pending_width, | ||
344 | state->pending_height, | ||
345 | state->pending_vrefresh, 0); | ||
346 | |||
347 | state->pending_config = false; | ||
348 | } | ||
349 | |||
350 | if (mtk_crtc->pending_planes) { | ||
351 | for (i = 0; i < OVL_LAYER_NR; i++) { | ||
352 | struct drm_plane *plane = &mtk_crtc->planes[i]; | ||
353 | struct mtk_plane_state *plane_state; | ||
354 | |||
355 | plane_state = to_mtk_plane_state(plane->state); | ||
356 | |||
357 | if (plane_state->pending.config) { | ||
358 | mtk_ddp_comp_layer_config(ovl, i, plane_state); | ||
359 | plane_state->pending.config = false; | ||
360 | } | ||
361 | } | ||
362 | mtk_crtc->pending_planes = false; | ||
363 | } | ||
364 | } | ||
365 | |||
330 | static void mtk_drm_crtc_enable(struct drm_crtc *crtc) | 366 | static void mtk_drm_crtc_enable(struct drm_crtc *crtc) |
331 | { | 367 | { |
332 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); | 368 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); |
@@ -403,6 +439,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, | |||
403 | struct drm_crtc_state *old_crtc_state) | 439 | struct drm_crtc_state *old_crtc_state) |
404 | { | 440 | { |
405 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); | 441 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); |
442 | struct mtk_drm_private *priv = crtc->dev->dev_private; | ||
406 | unsigned int pending_planes = 0; | 443 | unsigned int pending_planes = 0; |
407 | int i; | 444 | int i; |
408 | 445 | ||
@@ -424,6 +461,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, | |||
424 | if (crtc->state->color_mgmt_changed) | 461 | if (crtc->state->color_mgmt_changed) |
425 | for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) | 462 | for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) |
426 | mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); | 463 | mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); |
464 | |||
465 | if (priv->data->shadow_register) { | ||
466 | mtk_disp_mutex_acquire(mtk_crtc->mutex); | ||
467 | mtk_crtc_ddp_config(crtc); | ||
468 | mtk_disp_mutex_release(mtk_crtc->mutex); | ||
469 | } | ||
427 | } | 470 | } |
428 | 471 | ||
429 | static const struct drm_crtc_funcs mtk_crtc_funcs = { | 472 | static const struct drm_crtc_funcs mtk_crtc_funcs = { |
@@ -471,36 +514,10 @@ err_cleanup_crtc: | |||
471 | void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl) | 514 | void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl) |
472 | { | 515 | { |
473 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); | 516 | struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); |
474 | struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); | 517 | struct mtk_drm_private *priv = crtc->dev->dev_private; |
475 | unsigned int i; | ||
476 | 518 | ||
477 | /* | 519 | if (!priv->data->shadow_register) |
478 | * TODO: instead of updating the registers here, we should prepare | 520 | mtk_crtc_ddp_config(crtc); |
479 | * working registers in atomic_commit and let the hardware command | ||
480 | * queue update module registers on vblank. | ||
481 | */ | ||
482 | if (state->pending_config) { | ||
483 | mtk_ddp_comp_config(ovl, state->pending_width, | ||
484 | state->pending_height, | ||
485 | state->pending_vrefresh, 0); | ||
486 | |||
487 | state->pending_config = false; | ||
488 | } | ||
489 | |||
490 | if (mtk_crtc->pending_planes) { | ||
491 | for (i = 0; i < OVL_LAYER_NR; i++) { | ||
492 | struct drm_plane *plane = &mtk_crtc->planes[i]; | ||
493 | struct mtk_plane_state *plane_state; | ||
494 | |||
495 | plane_state = to_mtk_plane_state(plane->state); | ||
496 | |||
497 | if (plane_state->pending.config) { | ||
498 | mtk_ddp_comp_layer_config(ovl, i, plane_state); | ||
499 | plane_state->pending.config = false; | ||
500 | } | ||
501 | } | ||
502 | mtk_crtc->pending_planes = false; | ||
503 | } | ||
504 | 521 | ||
505 | mtk_drm_finish_page_flip(mtk_crtc); | 522 | mtk_drm_finish_page_flip(mtk_crtc); |
506 | } | 523 | } |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 17ba9355a49c..8130f3dab661 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/iopoll.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
@@ -31,26 +32,40 @@ | |||
31 | #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8 | 32 | #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN 0x0c8 |
32 | #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 | 33 | #define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 |
33 | 34 | ||
35 | #define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 | ||
36 | #define DISP_REG_CONFIG_OUT_SEL 0x04c | ||
37 | #define DISP_REG_CONFIG_DSI_SEL 0x050 | ||
38 | |||
34 | #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) | 39 | #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) |
40 | #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) | ||
35 | #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n)) | 41 | #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n)) |
36 | #define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n)) | 42 | #define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n)) |
37 | #define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n)) | 43 | #define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n)) |
38 | 44 | ||
39 | #define MUTEX_MOD_DISP_OVL0 BIT(11) | 45 | #define INT_MUTEX BIT(1) |
40 | #define MUTEX_MOD_DISP_OVL1 BIT(12) | 46 | |
41 | #define MUTEX_MOD_DISP_RDMA0 BIT(13) | 47 | #define MT8173_MUTEX_MOD_DISP_OVL0 BIT(11) |
42 | #define MUTEX_MOD_DISP_RDMA1 BIT(14) | 48 | #define MT8173_MUTEX_MOD_DISP_OVL1 BIT(12) |
43 | #define MUTEX_MOD_DISP_RDMA2 BIT(15) | 49 | #define MT8173_MUTEX_MOD_DISP_RDMA0 BIT(13) |
44 | #define MUTEX_MOD_DISP_WDMA0 BIT(16) | 50 | #define MT8173_MUTEX_MOD_DISP_RDMA1 BIT(14) |
45 | #define MUTEX_MOD_DISP_WDMA1 BIT(17) | 51 | #define MT8173_MUTEX_MOD_DISP_RDMA2 BIT(15) |
46 | #define MUTEX_MOD_DISP_COLOR0 BIT(18) | 52 | #define MT8173_MUTEX_MOD_DISP_WDMA0 BIT(16) |
47 | #define MUTEX_MOD_DISP_COLOR1 BIT(19) | 53 | #define MT8173_MUTEX_MOD_DISP_WDMA1 BIT(17) |
48 | #define MUTEX_MOD_DISP_AAL BIT(20) | 54 | #define MT8173_MUTEX_MOD_DISP_COLOR0 BIT(18) |
49 | #define MUTEX_MOD_DISP_GAMMA BIT(21) | 55 | #define MT8173_MUTEX_MOD_DISP_COLOR1 BIT(19) |
50 | #define MUTEX_MOD_DISP_UFOE BIT(22) | 56 | #define MT8173_MUTEX_MOD_DISP_AAL BIT(20) |
51 | #define MUTEX_MOD_DISP_PWM0 BIT(23) | 57 | #define MT8173_MUTEX_MOD_DISP_GAMMA BIT(21) |
52 | #define MUTEX_MOD_DISP_PWM1 BIT(24) | 58 | #define MT8173_MUTEX_MOD_DISP_UFOE BIT(22) |
53 | #define MUTEX_MOD_DISP_OD BIT(25) | 59 | #define MT8173_MUTEX_MOD_DISP_PWM0 BIT(23) |
60 | #define MT8173_MUTEX_MOD_DISP_PWM1 BIT(24) | ||
61 | #define MT8173_MUTEX_MOD_DISP_OD BIT(25) | ||
62 | |||
63 | #define MT2701_MUTEX_MOD_DISP_OVL BIT(3) | ||
64 | #define MT2701_MUTEX_MOD_DISP_WDMA BIT(6) | ||
65 | #define MT2701_MUTEX_MOD_DISP_COLOR BIT(7) | ||
66 | #define MT2701_MUTEX_MOD_DISP_BLS BIT(9) | ||
67 | #define MT2701_MUTEX_MOD_DISP_RDMA0 BIT(10) | ||
68 | #define MT2701_MUTEX_MOD_DISP_RDMA1 BIT(12) | ||
54 | 69 | ||
55 | #define MUTEX_SOF_SINGLE_MODE 0 | 70 | #define MUTEX_SOF_SINGLE_MODE 0 |
56 | #define MUTEX_SOF_DSI0 1 | 71 | #define MUTEX_SOF_DSI0 1 |
@@ -67,6 +82,10 @@ | |||
67 | #define DPI0_SEL_IN_RDMA1 0x1 | 82 | #define DPI0_SEL_IN_RDMA1 0x1 |
68 | #define COLOR1_SEL_IN_OVL1 0x1 | 83 | #define COLOR1_SEL_IN_OVL1 0x1 |
69 | 84 | ||
85 | #define OVL_MOUT_EN_RDMA 0x1 | ||
86 | #define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 | ||
87 | #define DSI_SEL_IN_BLS 0x0 | ||
88 | |||
70 | struct mtk_disp_mutex { | 89 | struct mtk_disp_mutex { |
71 | int id; | 90 | int id; |
72 | bool claimed; | 91 | bool claimed; |
@@ -77,24 +96,34 @@ struct mtk_ddp { | |||
77 | struct clk *clk; | 96 | struct clk *clk; |
78 | void __iomem *regs; | 97 | void __iomem *regs; |
79 | struct mtk_disp_mutex mutex[10]; | 98 | struct mtk_disp_mutex mutex[10]; |
99 | const unsigned int *mutex_mod; | ||
100 | }; | ||
101 | |||
102 | static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = { | ||
103 | [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS, | ||
104 | [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR, | ||
105 | [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL, | ||
106 | [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0, | ||
107 | [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1, | ||
108 | [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA, | ||
80 | }; | 109 | }; |
81 | 110 | ||
82 | static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = { | 111 | static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = { |
83 | [DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL, | 112 | [DDP_COMPONENT_AAL] = MT8173_MUTEX_MOD_DISP_AAL, |
84 | [DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0, | 113 | [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0, |
85 | [DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1, | 114 | [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1, |
86 | [DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA, | 115 | [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA, |
87 | [DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD, | 116 | [DDP_COMPONENT_OD] = MT8173_MUTEX_MOD_DISP_OD, |
88 | [DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0, | 117 | [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0, |
89 | [DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1, | 118 | [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1, |
90 | [DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0, | 119 | [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0, |
91 | [DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1, | 120 | [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1, |
92 | [DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0, | 121 | [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0, |
93 | [DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1, | 122 | [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1, |
94 | [DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2, | 123 | [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2, |
95 | [DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE, | 124 | [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE, |
96 | [DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0, | 125 | [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0, |
97 | [DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1, | 126 | [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, |
98 | }; | 127 | }; |
99 | 128 | ||
100 | static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, | 129 | static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, |
@@ -106,6 +135,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, | |||
106 | if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { | 135 | if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { |
107 | *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; | 136 | *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; |
108 | value = OVL0_MOUT_EN_COLOR0; | 137 | value = OVL0_MOUT_EN_COLOR0; |
138 | } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) { | ||
139 | *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN; | ||
140 | value = OVL_MOUT_EN_RDMA; | ||
109 | } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) { | 141 | } else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) { |
110 | *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; | 142 | *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; |
111 | value = OD_MOUT_EN_RDMA0; | 143 | value = OD_MOUT_EN_RDMA0; |
@@ -143,6 +175,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, | |||
143 | } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { | 175 | } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { |
144 | *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; | 176 | *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; |
145 | value = COLOR1_SEL_IN_OVL1; | 177 | value = COLOR1_SEL_IN_OVL1; |
178 | } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { | ||
179 | *addr = DISP_REG_CONFIG_DSI_SEL; | ||
180 | value = DSI_SEL_IN_BLS; | ||
146 | } else { | 181 | } else { |
147 | value = 0; | 182 | value = 0; |
148 | } | 183 | } |
@@ -150,6 +185,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, | |||
150 | return value; | 185 | return value; |
151 | } | 186 | } |
152 | 187 | ||
188 | static void mtk_ddp_sout_sel(void __iomem *config_regs, | ||
189 | enum mtk_ddp_comp_id cur, | ||
190 | enum mtk_ddp_comp_id next) | ||
191 | { | ||
192 | if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) | ||
193 | writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, | ||
194 | config_regs + DISP_REG_CONFIG_OUT_SEL); | ||
195 | } | ||
196 | |||
153 | void mtk_ddp_add_comp_to_path(void __iomem *config_regs, | 197 | void mtk_ddp_add_comp_to_path(void __iomem *config_regs, |
154 | enum mtk_ddp_comp_id cur, | 198 | enum mtk_ddp_comp_id cur, |
155 | enum mtk_ddp_comp_id next) | 199 | enum mtk_ddp_comp_id next) |
@@ -162,6 +206,8 @@ void mtk_ddp_add_comp_to_path(void __iomem *config_regs, | |||
162 | writel_relaxed(reg, config_regs + addr); | 206 | writel_relaxed(reg, config_regs + addr); |
163 | } | 207 | } |
164 | 208 | ||
209 | mtk_ddp_sout_sel(config_regs, cur, next); | ||
210 | |||
165 | value = mtk_ddp_sel_in(cur, next, &addr); | 211 | value = mtk_ddp_sel_in(cur, next, &addr); |
166 | if (value) { | 212 | if (value) { |
167 | reg = readl_relaxed(config_regs + addr) | value; | 213 | reg = readl_relaxed(config_regs + addr) | value; |
@@ -247,7 +293,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex, | |||
247 | break; | 293 | break; |
248 | default: | 294 | default: |
249 | reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); | 295 | reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); |
250 | reg |= mutex_mod[id]; | 296 | reg |= ddp->mutex_mod[id]; |
251 | writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); | 297 | writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); |
252 | return; | 298 | return; |
253 | } | 299 | } |
@@ -273,7 +319,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex, | |||
273 | break; | 319 | break; |
274 | default: | 320 | default: |
275 | reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); | 321 | reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); |
276 | reg &= ~mutex_mod[id]; | 322 | reg &= ~(ddp->mutex_mod[id]); |
277 | writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); | 323 | writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id)); |
278 | break; | 324 | break; |
279 | } | 325 | } |
@@ -299,6 +345,27 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex) | |||
299 | writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); | 345 | writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); |
300 | } | 346 | } |
301 | 347 | ||
348 | void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex) | ||
349 | { | ||
350 | struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, | ||
351 | mutex[mutex->id]); | ||
352 | u32 tmp; | ||
353 | |||
354 | writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id)); | ||
355 | writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id)); | ||
356 | if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id), | ||
357 | tmp, tmp & INT_MUTEX, 1, 10000)) | ||
358 | pr_err("could not acquire mutex %d\n", mutex->id); | ||
359 | } | ||
360 | |||
361 | void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex) | ||
362 | { | ||
363 | struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp, | ||
364 | mutex[mutex->id]); | ||
365 | |||
366 | writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id)); | ||
367 | } | ||
368 | |||
302 | static int mtk_ddp_probe(struct platform_device *pdev) | 369 | static int mtk_ddp_probe(struct platform_device *pdev) |
303 | { | 370 | { |
304 | struct device *dev = &pdev->dev; | 371 | struct device *dev = &pdev->dev; |
@@ -326,6 +393,8 @@ static int mtk_ddp_probe(struct platform_device *pdev) | |||
326 | return PTR_ERR(ddp->regs); | 393 | return PTR_ERR(ddp->regs); |
327 | } | 394 | } |
328 | 395 | ||
396 | ddp->mutex_mod = of_device_get_match_data(dev); | ||
397 | |||
329 | platform_set_drvdata(pdev, ddp); | 398 | platform_set_drvdata(pdev, ddp); |
330 | 399 | ||
331 | return 0; | 400 | return 0; |
@@ -337,7 +406,8 @@ static int mtk_ddp_remove(struct platform_device *pdev) | |||
337 | } | 406 | } |
338 | 407 | ||
339 | static const struct of_device_id ddp_driver_dt_match[] = { | 408 | static const struct of_device_id ddp_driver_dt_match[] = { |
340 | { .compatible = "mediatek,mt8173-disp-mutex" }, | 409 | { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod}, |
410 | { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod}, | ||
341 | {}, | 411 | {}, |
342 | }; | 412 | }; |
343 | MODULE_DEVICE_TABLE(of, ddp_driver_dt_match); | 413 | MODULE_DEVICE_TABLE(of, ddp_driver_dt_match); |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h index 92c11752ff65..f9a799168077 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h | |||
@@ -37,5 +37,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex, | |||
37 | enum mtk_ddp_comp_id id); | 37 | enum mtk_ddp_comp_id id); |
38 | void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex); | 38 | void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex); |
39 | void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex); | 39 | void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex); |
40 | void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex); | ||
41 | void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex); | ||
40 | 42 | ||
41 | #endif /* MTK_DRM_DDP_H */ | 43 | #endif /* MTK_DRM_DDP_H */ |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 48cc01fd20c7..8b52416b6e41 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | |||
@@ -39,9 +39,11 @@ | |||
39 | #define DISP_REG_UFO_START 0x0000 | 39 | #define DISP_REG_UFO_START 0x0000 |
40 | 40 | ||
41 | #define DISP_COLOR_CFG_MAIN 0x0400 | 41 | #define DISP_COLOR_CFG_MAIN 0x0400 |
42 | #define DISP_COLOR_START 0x0c00 | 42 | #define DISP_COLOR_START_MT2701 0x0f00 |
43 | #define DISP_COLOR_WIDTH 0x0c50 | 43 | #define DISP_COLOR_START_MT8173 0x0c00 |
44 | #define DISP_COLOR_HEIGHT 0x0c54 | 44 | #define DISP_COLOR_START(comp) ((comp)->data->color_offset) |
45 | #define DISP_COLOR_WIDTH(comp) (DISP_COLOR_START(comp) + 0x50) | ||
46 | #define DISP_COLOR_HEIGHT(comp) (DISP_COLOR_START(comp) + 0x54) | ||
45 | 47 | ||
46 | #define DISP_AAL_EN 0x0000 | 48 | #define DISP_AAL_EN 0x0000 |
47 | #define DISP_AAL_SIZE 0x0030 | 49 | #define DISP_AAL_SIZE 0x0030 |
@@ -80,6 +82,20 @@ | |||
80 | #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) | 82 | #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) |
81 | #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0) | 83 | #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0) |
82 | 84 | ||
85 | struct mtk_disp_color_data { | ||
86 | unsigned int color_offset; | ||
87 | }; | ||
88 | |||
89 | struct mtk_disp_color { | ||
90 | struct mtk_ddp_comp ddp_comp; | ||
91 | const struct mtk_disp_color_data *data; | ||
92 | }; | ||
93 | |||
94 | static inline struct mtk_disp_color *comp_to_color(struct mtk_ddp_comp *comp) | ||
95 | { | ||
96 | return container_of(comp, struct mtk_disp_color, ddp_comp); | ||
97 | } | ||
98 | |||
83 | void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, | 99 | void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, |
84 | unsigned int CFG) | 100 | unsigned int CFG) |
85 | { | 101 | { |
@@ -107,15 +123,19 @@ static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w, | |||
107 | unsigned int h, unsigned int vrefresh, | 123 | unsigned int h, unsigned int vrefresh, |
108 | unsigned int bpc) | 124 | unsigned int bpc) |
109 | { | 125 | { |
110 | writel(w, comp->regs + DISP_COLOR_WIDTH); | 126 | struct mtk_disp_color *color = comp_to_color(comp); |
111 | writel(h, comp->regs + DISP_COLOR_HEIGHT); | 127 | |
128 | writel(w, comp->regs + DISP_COLOR_WIDTH(color)); | ||
129 | writel(h, comp->regs + DISP_COLOR_HEIGHT(color)); | ||
112 | } | 130 | } |
113 | 131 | ||
114 | static void mtk_color_start(struct mtk_ddp_comp *comp) | 132 | static void mtk_color_start(struct mtk_ddp_comp *comp) |
115 | { | 133 | { |
134 | struct mtk_disp_color *color = comp_to_color(comp); | ||
135 | |||
116 | writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL, | 136 | writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL, |
117 | comp->regs + DISP_COLOR_CFG_MAIN); | 137 | comp->regs + DISP_COLOR_CFG_MAIN); |
118 | writel(0x1, comp->regs + DISP_COLOR_START); | 138 | writel(0x1, comp->regs + DISP_COLOR_START(color)); |
119 | } | 139 | } |
120 | 140 | ||
121 | static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, | 141 | static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, |
@@ -236,6 +256,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { | |||
236 | [MTK_DISP_PWM] = "pwm", | 256 | [MTK_DISP_PWM] = "pwm", |
237 | [MTK_DISP_MUTEX] = "mutex", | 257 | [MTK_DISP_MUTEX] = "mutex", |
238 | [MTK_DISP_OD] = "od", | 258 | [MTK_DISP_OD] = "od", |
259 | [MTK_DISP_BLS] = "bls", | ||
239 | }; | 260 | }; |
240 | 261 | ||
241 | struct mtk_ddp_comp_match { | 262 | struct mtk_ddp_comp_match { |
@@ -246,6 +267,7 @@ struct mtk_ddp_comp_match { | |||
246 | 267 | ||
247 | static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { | 268 | static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { |
248 | [DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, &ddp_aal }, | 269 | [DDP_COMPONENT_AAL] = { MTK_DISP_AAL, 0, &ddp_aal }, |
270 | [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL }, | ||
249 | [DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color }, | 271 | [DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color }, |
250 | [DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color }, | 272 | [DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color }, |
251 | [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL }, | 273 | [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL }, |
@@ -264,6 +286,22 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { | |||
264 | [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, | 286 | [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, |
265 | }; | 287 | }; |
266 | 288 | ||
289 | static const struct mtk_disp_color_data mt2701_color_driver_data = { | ||
290 | .color_offset = DISP_COLOR_START_MT2701, | ||
291 | }; | ||
292 | |||
293 | static const struct mtk_disp_color_data mt8173_color_driver_data = { | ||
294 | .color_offset = DISP_COLOR_START_MT8173, | ||
295 | }; | ||
296 | |||
297 | static const struct of_device_id mtk_disp_color_driver_dt_match[] = { | ||
298 | { .compatible = "mediatek,mt2701-disp-color", | ||
299 | .data = &mt2701_color_driver_data}, | ||
300 | { .compatible = "mediatek,mt8173-disp-color", | ||
301 | .data = &mt8173_color_driver_data}, | ||
302 | {}, | ||
303 | }; | ||
304 | |||
267 | int mtk_ddp_comp_get_id(struct device_node *node, | 305 | int mtk_ddp_comp_get_id(struct device_node *node, |
268 | enum mtk_ddp_comp_type comp_type) | 306 | enum mtk_ddp_comp_type comp_type) |
269 | { | 307 | { |
@@ -286,14 +324,29 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, | |||
286 | enum mtk_ddp_comp_type type; | 324 | enum mtk_ddp_comp_type type; |
287 | struct device_node *larb_node; | 325 | struct device_node *larb_node; |
288 | struct platform_device *larb_pdev; | 326 | struct platform_device *larb_pdev; |
327 | const struct of_device_id *match; | ||
328 | struct mtk_disp_color *color; | ||
289 | 329 | ||
290 | if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) | 330 | if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) |
291 | return -EINVAL; | 331 | return -EINVAL; |
292 | 332 | ||
333 | type = mtk_ddp_matches[comp_id].type; | ||
334 | if (type == MTK_DISP_COLOR) { | ||
335 | devm_kfree(dev, comp); | ||
336 | color = devm_kzalloc(dev, sizeof(*color), GFP_KERNEL); | ||
337 | if (!color) | ||
338 | return -ENOMEM; | ||
339 | |||
340 | match = of_match_node(mtk_disp_color_driver_dt_match, node); | ||
341 | color->data = match->data; | ||
342 | comp = &color->ddp_comp; | ||
343 | } | ||
344 | |||
293 | comp->id = comp_id; | 345 | comp->id = comp_id; |
294 | comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs; | 346 | comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs; |
295 | 347 | ||
296 | if (comp_id == DDP_COMPONENT_DPI0 || | 348 | if (comp_id == DDP_COMPONENT_BLS || |
349 | comp_id == DDP_COMPONENT_DPI0 || | ||
297 | comp_id == DDP_COMPONENT_DSI0 || | 350 | comp_id == DDP_COMPONENT_DSI0 || |
298 | comp_id == DDP_COMPONENT_PWM0) { | 351 | comp_id == DDP_COMPONENT_PWM0) { |
299 | comp->regs = NULL; | 352 | comp->regs = NULL; |
@@ -308,8 +361,6 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, | |||
308 | if (IS_ERR(comp->clk)) | 361 | if (IS_ERR(comp->clk)) |
309 | comp->clk = NULL; | 362 | comp->clk = NULL; |
310 | 363 | ||
311 | type = mtk_ddp_matches[comp_id].type; | ||
312 | |||
313 | /* Only DMA capable components need the LARB property */ | 364 | /* Only DMA capable components need the LARB property */ |
314 | comp->larb_dev = NULL; | 365 | comp->larb_dev = NULL; |
315 | if (type != MTK_DISP_OVL && | 366 | if (type != MTK_DISP_OVL && |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 22a33ee451c4..0828cf8bf85c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | |||
@@ -36,11 +36,13 @@ enum mtk_ddp_comp_type { | |||
36 | MTK_DISP_PWM, | 36 | MTK_DISP_PWM, |
37 | MTK_DISP_MUTEX, | 37 | MTK_DISP_MUTEX, |
38 | MTK_DISP_OD, | 38 | MTK_DISP_OD, |
39 | MTK_DISP_BLS, | ||
39 | MTK_DDP_COMP_TYPE_MAX, | 40 | MTK_DDP_COMP_TYPE_MAX, |
40 | }; | 41 | }; |
41 | 42 | ||
42 | enum mtk_ddp_comp_id { | 43 | enum mtk_ddp_comp_id { |
43 | DDP_COMPONENT_AAL, | 44 | DDP_COMPONENT_AAL, |
45 | DDP_COMPONENT_BLS, | ||
44 | DDP_COMPONENT_COLOR0, | 46 | DDP_COMPONENT_COLOR0, |
45 | DDP_COMPONENT_COLOR1, | 47 | DDP_COMPONENT_COLOR1, |
46 | DDP_COMPONENT_DPI0, | 48 | DDP_COMPONENT_DPI0, |
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index f5a1fd9b3ecc..f6c8ec4c7dbc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c | |||
@@ -128,7 +128,20 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { | |||
128 | .atomic_commit = mtk_atomic_commit, | 128 | .atomic_commit = mtk_atomic_commit, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static const enum mtk_ddp_comp_id mtk_ddp_main[] = { | 131 | static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { |
132 | DDP_COMPONENT_OVL0, | ||
133 | DDP_COMPONENT_RDMA0, | ||
134 | DDP_COMPONENT_COLOR0, | ||
135 | DDP_COMPONENT_BLS, | ||
136 | DDP_COMPONENT_DSI0, | ||
137 | }; | ||
138 | |||
139 | static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { | ||
140 | DDP_COMPONENT_RDMA1, | ||
141 | DDP_COMPONENT_DPI0, | ||
142 | }; | ||
143 | |||
144 | static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { | ||
132 | DDP_COMPONENT_OVL0, | 145 | DDP_COMPONENT_OVL0, |
133 | DDP_COMPONENT_COLOR0, | 146 | DDP_COMPONENT_COLOR0, |
134 | DDP_COMPONENT_AAL, | 147 | DDP_COMPONENT_AAL, |
@@ -139,7 +152,7 @@ static const enum mtk_ddp_comp_id mtk_ddp_main[] = { | |||
139 | DDP_COMPONENT_PWM0, | 152 | DDP_COMPONENT_PWM0, |
140 | }; | 153 | }; |
141 | 154 | ||
142 | static const enum mtk_ddp_comp_id mtk_ddp_ext[] = { | 155 | static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { |
143 | DDP_COMPONENT_OVL1, | 156 | DDP_COMPONENT_OVL1, |
144 | DDP_COMPONENT_COLOR1, | 157 | DDP_COMPONENT_COLOR1, |
145 | DDP_COMPONENT_GAMMA, | 158 | DDP_COMPONENT_GAMMA, |
@@ -147,6 +160,21 @@ static const enum mtk_ddp_comp_id mtk_ddp_ext[] = { | |||
147 | DDP_COMPONENT_DPI0, | 160 | DDP_COMPONENT_DPI0, |
148 | }; | 161 | }; |
149 | 162 | ||
163 | static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { | ||
164 | .main_path = mt2701_mtk_ddp_main, | ||
165 | .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main), | ||
166 | .ext_path = mt2701_mtk_ddp_ext, | ||
167 | .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext), | ||
168 | .shadow_register = true, | ||
169 | }; | ||
170 | |||
171 | static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { | ||
172 | .main_path = mt8173_mtk_ddp_main, | ||
173 | .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main), | ||
174 | .ext_path = mt8173_mtk_ddp_ext, | ||
175 | .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext), | ||
176 | }; | ||
177 | |||
150 | static int mtk_drm_kms_init(struct drm_device *drm) | 178 | static int mtk_drm_kms_init(struct drm_device *drm) |
151 | { | 179 | { |
152 | struct mtk_drm_private *private = drm->dev_private; | 180 | struct mtk_drm_private *private = drm->dev_private; |
@@ -189,17 +217,19 @@ static int mtk_drm_kms_init(struct drm_device *drm) | |||
189 | * and each statically assigned to a crtc: | 217 | * and each statically assigned to a crtc: |
190 | * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ... | 218 | * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ... |
191 | */ | 219 | */ |
192 | ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main)); | 220 | ret = mtk_drm_crtc_create(drm, private->data->main_path, |
221 | private->data->main_len); | ||
193 | if (ret < 0) | 222 | if (ret < 0) |
194 | goto err_component_unbind; | 223 | goto err_component_unbind; |
195 | /* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */ | 224 | /* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */ |
196 | ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext)); | 225 | ret = mtk_drm_crtc_create(drm, private->data->ext_path, |
226 | private->data->ext_len); | ||
197 | if (ret < 0) | 227 | if (ret < 0) |
198 | goto err_component_unbind; | 228 | goto err_component_unbind; |
199 | 229 | ||
200 | /* Use OVL device for all DMA memory allocations */ | 230 | /* Use OVL device for all DMA memory allocations */ |
201 | np = private->comp_node[mtk_ddp_main[0]] ?: | 231 | np = private->comp_node[private->data->main_path[0]] ?: |
202 | private->comp_node[mtk_ddp_ext[0]]; | 232 | private->comp_node[private->data->ext_path[0]]; |
203 | pdev = of_find_device_by_node(np); | 233 | pdev = of_find_device_by_node(np); |
204 | if (!pdev) { | 234 | if (!pdev) { |
205 | ret = -ENODEV; | 235 | ret = -ENODEV; |
@@ -328,16 +358,22 @@ static const struct component_master_ops mtk_drm_ops = { | |||
328 | }; | 358 | }; |
329 | 359 | ||
330 | static const struct of_device_id mtk_ddp_comp_dt_ids[] = { | 360 | static const struct of_device_id mtk_ddp_comp_dt_ids[] = { |
361 | { .compatible = "mediatek,mt2701-disp-ovl", .data = (void *)MTK_DISP_OVL }, | ||
331 | { .compatible = "mediatek,mt8173-disp-ovl", .data = (void *)MTK_DISP_OVL }, | 362 | { .compatible = "mediatek,mt8173-disp-ovl", .data = (void *)MTK_DISP_OVL }, |
363 | { .compatible = "mediatek,mt2701-disp-rdma", .data = (void *)MTK_DISP_RDMA }, | ||
332 | { .compatible = "mediatek,mt8173-disp-rdma", .data = (void *)MTK_DISP_RDMA }, | 364 | { .compatible = "mediatek,mt8173-disp-rdma", .data = (void *)MTK_DISP_RDMA }, |
333 | { .compatible = "mediatek,mt8173-disp-wdma", .data = (void *)MTK_DISP_WDMA }, | 365 | { .compatible = "mediatek,mt8173-disp-wdma", .data = (void *)MTK_DISP_WDMA }, |
366 | { .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR }, | ||
334 | { .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR }, | 367 | { .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR }, |
335 | { .compatible = "mediatek,mt8173-disp-aal", .data = (void *)MTK_DISP_AAL}, | 368 | { .compatible = "mediatek,mt8173-disp-aal", .data = (void *)MTK_DISP_AAL}, |
336 | { .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, | 369 | { .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, |
337 | { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE }, | 370 | { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE }, |
371 | { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI }, | ||
338 | { .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI }, | 372 | { .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI }, |
339 | { .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI }, | 373 | { .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI }, |
374 | { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, | ||
340 | { .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, | 375 | { .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, |
376 | { .compatible = "mediatek,mt2701-disp-pwm", .data = (void *)MTK_DISP_BLS }, | ||
341 | { .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM }, | 377 | { .compatible = "mediatek,mt8173-disp-pwm", .data = (void *)MTK_DISP_PWM }, |
342 | { .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD }, | 378 | { .compatible = "mediatek,mt8173-disp-od", .data = (void *)MTK_DISP_OD }, |
343 | { } | 379 | { } |
@@ -359,6 +395,7 @@ static int mtk_drm_probe(struct platform_device *pdev) | |||
359 | 395 | ||
360 | mutex_init(&private->commit.lock); | 396 | mutex_init(&private->commit.lock); |
361 | INIT_WORK(&private->commit.work, mtk_atomic_work); | 397 | INIT_WORK(&private->commit.work, mtk_atomic_work); |
398 | private->data = of_device_get_match_data(dev); | ||
362 | 399 | ||
363 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 400 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
364 | private->config_regs = devm_ioremap_resource(dev, mem); | 401 | private->config_regs = devm_ioremap_resource(dev, mem); |
@@ -510,7 +547,10 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend, | |||
510 | mtk_drm_sys_resume); | 547 | mtk_drm_sys_resume); |
511 | 548 | ||
512 | static const struct of_device_id mtk_drm_of_ids[] = { | 549 | static const struct of_device_id mtk_drm_of_ids[] = { |
513 | { .compatible = "mediatek,mt8173-mmsys", }, | 550 | { .compatible = "mediatek,mt2701-mmsys", |
551 | .data = &mt2701_mmsys_driver_data}, | ||
552 | { .compatible = "mediatek,mt8173-mmsys", | ||
553 | .data = &mt8173_mmsys_driver_data}, | ||
514 | { } | 554 | { } |
515 | }; | 555 | }; |
516 | 556 | ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index df322a7a5fcb..aef8747d810b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h | |||
@@ -28,6 +28,14 @@ struct drm_fb_helper; | |||
28 | struct drm_property; | 28 | struct drm_property; |
29 | struct regmap; | 29 | struct regmap; |
30 | 30 | ||
31 | struct mtk_mmsys_driver_data { | ||
32 | const enum mtk_ddp_comp_id *main_path; | ||
33 | unsigned int main_len; | ||
34 | const enum mtk_ddp_comp_id *ext_path; | ||
35 | unsigned int ext_len; | ||
36 | bool shadow_register; | ||
37 | }; | ||
38 | |||
31 | struct mtk_drm_private { | 39 | struct mtk_drm_private { |
32 | struct drm_device *drm; | 40 | struct drm_device *drm; |
33 | struct device *dma_dev; | 41 | struct device *dma_dev; |
@@ -39,6 +47,7 @@ struct mtk_drm_private { | |||
39 | void __iomem *config_regs; | 47 | void __iomem *config_regs; |
40 | struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; | 48 | struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; |
41 | struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX]; | 49 | struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX]; |
50 | const struct mtk_mmsys_driver_data *data; | ||
42 | 51 | ||
43 | struct { | 52 | struct { |
44 | struct drm_atomic_state *state; | 53 | struct drm_atomic_state *state; |
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index dd71cbb1a622..1a5b0f7795b8 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c | |||
@@ -18,20 +18,29 @@ | |||
18 | #include <drm/drm_panel.h> | 18 | #include <drm/drm_panel.h> |
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/component.h> | 20 | #include <linux/component.h> |
21 | #include <linux/irq.h> | ||
21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
22 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
23 | #include <linux/of_graph.h> | 24 | #include <linux/of_graph.h> |
24 | #include <linux/phy/phy.h> | 25 | #include <linux/phy/phy.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <video/mipi_display.h> | ||
26 | #include <video/videomode.h> | 28 | #include <video/videomode.h> |
27 | 29 | ||
28 | #include "mtk_drm_ddp_comp.h" | 30 | #include "mtk_drm_ddp_comp.h" |
29 | 31 | ||
30 | #define DSI_VIDEO_FIFO_DEPTH (1920 / 4) | ||
31 | #define DSI_HOST_FIFO_DEPTH 64 | ||
32 | |||
33 | #define DSI_START 0x00 | 32 | #define DSI_START 0x00 |
34 | 33 | ||
34 | #define DSI_INTEN 0x08 | ||
35 | |||
36 | #define DSI_INTSTA 0x0c | ||
37 | #define LPRX_RD_RDY_INT_FLAG BIT(0) | ||
38 | #define CMD_DONE_INT_FLAG BIT(1) | ||
39 | #define TE_RDY_INT_FLAG BIT(2) | ||
40 | #define VM_DONE_INT_FLAG BIT(3) | ||
41 | #define EXT_TE_RDY_INT_FLAG BIT(4) | ||
42 | #define DSI_BUSY BIT(31) | ||
43 | |||
35 | #define DSI_CON_CTRL 0x10 | 44 | #define DSI_CON_CTRL 0x10 |
36 | #define DSI_RESET BIT(0) | 45 | #define DSI_RESET BIT(0) |
37 | #define DSI_EN BIT(1) | 46 | #define DSI_EN BIT(1) |
@@ -46,7 +55,7 @@ | |||
46 | #define MIX_MODE BIT(17) | 55 | #define MIX_MODE BIT(17) |
47 | 56 | ||
48 | #define DSI_TXRX_CTRL 0x18 | 57 | #define DSI_TXRX_CTRL 0x18 |
49 | #define VC_NUM (2 << 0) | 58 | #define VC_NUM BIT(1) |
50 | #define LANE_NUM (0xf << 2) | 59 | #define LANE_NUM (0xf << 2) |
51 | #define DIS_EOT BIT(6) | 60 | #define DIS_EOT BIT(6) |
52 | #define NULL_EN BIT(7) | 61 | #define NULL_EN BIT(7) |
@@ -72,8 +81,19 @@ | |||
72 | #define DSI_HBP_WC 0x54 | 81 | #define DSI_HBP_WC 0x54 |
73 | #define DSI_HFP_WC 0x58 | 82 | #define DSI_HFP_WC 0x58 |
74 | 83 | ||
84 | #define DSI_CMDQ_SIZE 0x60 | ||
85 | #define CMDQ_SIZE 0x3f | ||
86 | |||
75 | #define DSI_HSTX_CKL_WC 0x64 | 87 | #define DSI_HSTX_CKL_WC 0x64 |
76 | 88 | ||
89 | #define DSI_RX_DATA0 0x74 | ||
90 | #define DSI_RX_DATA1 0x78 | ||
91 | #define DSI_RX_DATA2 0x7c | ||
92 | #define DSI_RX_DATA3 0x80 | ||
93 | |||
94 | #define DSI_RACK 0x84 | ||
95 | #define RACK BIT(0) | ||
96 | |||
77 | #define DSI_PHY_LCCON 0x104 | 97 | #define DSI_PHY_LCCON 0x104 |
78 | #define LC_HS_TX_EN BIT(0) | 98 | #define LC_HS_TX_EN BIT(0) |
79 | #define LC_ULPM_EN BIT(1) | 99 | #define LC_ULPM_EN BIT(1) |
@@ -106,6 +126,19 @@ | |||
106 | #define CLK_HS_POST (0xff << 8) | 126 | #define CLK_HS_POST (0xff << 8) |
107 | #define CLK_HS_EXIT (0xff << 16) | 127 | #define CLK_HS_EXIT (0xff << 16) |
108 | 128 | ||
129 | #define DSI_VM_CMD_CON 0x130 | ||
130 | #define VM_CMD_EN BIT(0) | ||
131 | #define TS_VFP_EN BIT(5) | ||
132 | |||
133 | #define DSI_CMDQ0 0x180 | ||
134 | #define CONFIG (0xff << 0) | ||
135 | #define SHORT_PACKET 0 | ||
136 | #define LONG_PACKET 2 | ||
137 | #define BTA BIT(2) | ||
138 | #define DATA_ID (0xff << 8) | ||
139 | #define DATA_0 (0xff << 16) | ||
140 | #define DATA_1 (0xff << 24) | ||
141 | |||
109 | #define T_LPX 5 | 142 | #define T_LPX 5 |
110 | #define T_HS_PREP 6 | 143 | #define T_HS_PREP 6 |
111 | #define T_HS_TRAIL 8 | 144 | #define T_HS_TRAIL 8 |
@@ -114,6 +147,12 @@ | |||
114 | 147 | ||
115 | #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) | 148 | #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) |
116 | 149 | ||
150 | #define MTK_DSI_HOST_IS_READ(type) \ | ||
151 | ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \ | ||
152 | (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \ | ||
153 | (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ | ||
154 | (type == MIPI_DSI_DCS_READ)) | ||
155 | |||
117 | struct phy; | 156 | struct phy; |
118 | 157 | ||
119 | struct mtk_dsi { | 158 | struct mtk_dsi { |
@@ -140,6 +179,8 @@ struct mtk_dsi { | |||
140 | struct videomode vm; | 179 | struct videomode vm; |
141 | int refcount; | 180 | int refcount; |
142 | bool enabled; | 181 | bool enabled; |
182 | u32 irq_data; | ||
183 | wait_queue_head_t irq_wait_queue; | ||
143 | }; | 184 | }; |
144 | 185 | ||
145 | static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) | 186 | static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) |
@@ -164,7 +205,7 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data) | |||
164 | writel((temp & ~mask) | (data & mask), dsi->regs + offset); | 205 | writel((temp & ~mask) | (data & mask), dsi->regs + offset); |
165 | } | 206 | } |
166 | 207 | ||
167 | static void dsi_phy_timconfig(struct mtk_dsi *dsi) | 208 | static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) |
168 | { | 209 | { |
169 | u32 timcon0, timcon1, timcon2, timcon3; | 210 | u32 timcon0, timcon1, timcon2, timcon3; |
170 | u32 ui, cycle_time; | 211 | u32 ui, cycle_time; |
@@ -196,118 +237,39 @@ static void mtk_dsi_disable(struct mtk_dsi *dsi) | |||
196 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0); | 237 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0); |
197 | } | 238 | } |
198 | 239 | ||
199 | static void mtk_dsi_reset(struct mtk_dsi *dsi) | 240 | static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) |
200 | { | 241 | { |
201 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); | 242 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); |
202 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0); | 243 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0); |
203 | } | 244 | } |
204 | 245 | ||
205 | static int mtk_dsi_poweron(struct mtk_dsi *dsi) | 246 | static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) |
206 | { | ||
207 | struct device *dev = dsi->dev; | ||
208 | int ret; | ||
209 | u64 pixel_clock, total_bits; | ||
210 | u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; | ||
211 | |||
212 | if (++dsi->refcount != 1) | ||
213 | return 0; | ||
214 | |||
215 | switch (dsi->format) { | ||
216 | case MIPI_DSI_FMT_RGB565: | ||
217 | bit_per_pixel = 16; | ||
218 | break; | ||
219 | case MIPI_DSI_FMT_RGB666_PACKED: | ||
220 | bit_per_pixel = 18; | ||
221 | break; | ||
222 | case MIPI_DSI_FMT_RGB666: | ||
223 | case MIPI_DSI_FMT_RGB888: | ||
224 | default: | ||
225 | bit_per_pixel = 24; | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000 | ||
231 | * htotal_time = htotal * byte_per_pixel / num_lanes | ||
232 | * overhead_time = lpx + hs_prepare + hs_zero + hs_trail + hs_exit | ||
233 | * mipi_ratio = (htotal_time + overhead_time) / htotal_time | ||
234 | * data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes; | ||
235 | */ | ||
236 | pixel_clock = dsi->vm.pixelclock * 1000; | ||
237 | htotal = dsi->vm.hactive + dsi->vm.hback_porch + dsi->vm.hfront_porch + | ||
238 | dsi->vm.hsync_len; | ||
239 | htotal_bits = htotal * bit_per_pixel; | ||
240 | |||
241 | overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL + | ||
242 | T_HS_EXIT; | ||
243 | overhead_bits = overhead_cycles * dsi->lanes * 8; | ||
244 | total_bits = htotal_bits + overhead_bits; | ||
245 | |||
246 | dsi->data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits, | ||
247 | htotal * dsi->lanes); | ||
248 | |||
249 | ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); | ||
250 | if (ret < 0) { | ||
251 | dev_err(dev, "Failed to set data rate: %d\n", ret); | ||
252 | goto err_refcount; | ||
253 | } | ||
254 | |||
255 | phy_power_on(dsi->phy); | ||
256 | |||
257 | ret = clk_prepare_enable(dsi->engine_clk); | ||
258 | if (ret < 0) { | ||
259 | dev_err(dev, "Failed to enable engine clock: %d\n", ret); | ||
260 | goto err_phy_power_off; | ||
261 | } | ||
262 | |||
263 | ret = clk_prepare_enable(dsi->digital_clk); | ||
264 | if (ret < 0) { | ||
265 | dev_err(dev, "Failed to enable digital clock: %d\n", ret); | ||
266 | goto err_disable_engine_clk; | ||
267 | } | ||
268 | |||
269 | mtk_dsi_enable(dsi); | ||
270 | mtk_dsi_reset(dsi); | ||
271 | dsi_phy_timconfig(dsi); | ||
272 | |||
273 | return 0; | ||
274 | |||
275 | err_disable_engine_clk: | ||
276 | clk_disable_unprepare(dsi->engine_clk); | ||
277 | err_phy_power_off: | ||
278 | phy_power_off(dsi->phy); | ||
279 | err_refcount: | ||
280 | dsi->refcount--; | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static void dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) | ||
285 | { | 247 | { |
286 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); | 248 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); |
287 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); | 249 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); |
288 | } | 250 | } |
289 | 251 | ||
290 | static void dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) | 252 | static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) |
291 | { | 253 | { |
292 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); | 254 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0); |
293 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); | 255 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); |
294 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0); | 256 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0); |
295 | } | 257 | } |
296 | 258 | ||
297 | static void dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi) | 259 | static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi) |
298 | { | 260 | { |
299 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0); | 261 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0); |
300 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); | 262 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); |
301 | } | 263 | } |
302 | 264 | ||
303 | static void dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) | 265 | static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) |
304 | { | 266 | { |
305 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); | 267 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0); |
306 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); | 268 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); |
307 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0); | 269 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0); |
308 | } | 270 | } |
309 | 271 | ||
310 | static bool dsi_clk_hs_state(struct mtk_dsi *dsi) | 272 | static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi) |
311 | { | 273 | { |
312 | u32 tmp_reg1; | 274 | u32 tmp_reg1; |
313 | 275 | ||
@@ -315,30 +277,37 @@ static bool dsi_clk_hs_state(struct mtk_dsi *dsi) | |||
315 | return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false; | 277 | return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false; |
316 | } | 278 | } |
317 | 279 | ||
318 | static void dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) | 280 | static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) |
319 | { | 281 | { |
320 | if (enter && !dsi_clk_hs_state(dsi)) | 282 | if (enter && !mtk_dsi_clk_hs_state(dsi)) |
321 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); | 283 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); |
322 | else if (!enter && dsi_clk_hs_state(dsi)) | 284 | else if (!enter && mtk_dsi_clk_hs_state(dsi)) |
323 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); | 285 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0); |
324 | } | 286 | } |
325 | 287 | ||
326 | static void dsi_set_mode(struct mtk_dsi *dsi) | 288 | static void mtk_dsi_set_mode(struct mtk_dsi *dsi) |
327 | { | 289 | { |
328 | u32 vid_mode = CMD_MODE; | 290 | u32 vid_mode = CMD_MODE; |
329 | 291 | ||
330 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { | 292 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { |
331 | vid_mode = SYNC_PULSE_MODE; | 293 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) |
332 | |||
333 | if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) && | ||
334 | !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) | ||
335 | vid_mode = BURST_MODE; | 294 | vid_mode = BURST_MODE; |
295 | else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) | ||
296 | vid_mode = SYNC_PULSE_MODE; | ||
297 | else | ||
298 | vid_mode = SYNC_EVENT_MODE; | ||
336 | } | 299 | } |
337 | 300 | ||
338 | writel(vid_mode, dsi->regs + DSI_MODE_CTRL); | 301 | writel(vid_mode, dsi->regs + DSI_MODE_CTRL); |
339 | } | 302 | } |
340 | 303 | ||
341 | static void dsi_ps_control_vact(struct mtk_dsi *dsi) | 304 | static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi) |
305 | { | ||
306 | mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN); | ||
307 | mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN); | ||
308 | } | ||
309 | |||
310 | static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi) | ||
342 | { | 311 | { |
343 | struct videomode *vm = &dsi->vm; | 312 | struct videomode *vm = &dsi->vm; |
344 | u32 dsi_buf_bpp, ps_wc; | 313 | u32 dsi_buf_bpp, ps_wc; |
@@ -372,7 +341,7 @@ static void dsi_ps_control_vact(struct mtk_dsi *dsi) | |||
372 | writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); | 341 | writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC); |
373 | } | 342 | } |
374 | 343 | ||
375 | static void dsi_rxtx_control(struct mtk_dsi *dsi) | 344 | static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) |
376 | { | 345 | { |
377 | u32 tmp_reg; | 346 | u32 tmp_reg; |
378 | 347 | ||
@@ -394,12 +363,15 @@ static void dsi_rxtx_control(struct mtk_dsi *dsi) | |||
394 | break; | 363 | break; |
395 | } | 364 | } |
396 | 365 | ||
366 | tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6; | ||
367 | tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3; | ||
368 | |||
397 | writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); | 369 | writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL); |
398 | } | 370 | } |
399 | 371 | ||
400 | static void dsi_ps_control(struct mtk_dsi *dsi) | 372 | static void mtk_dsi_ps_control(struct mtk_dsi *dsi) |
401 | { | 373 | { |
402 | unsigned int dsi_tmp_buf_bpp; | 374 | u32 dsi_tmp_buf_bpp; |
403 | u32 tmp_reg; | 375 | u32 tmp_reg; |
404 | 376 | ||
405 | switch (dsi->format) { | 377 | switch (dsi->format) { |
@@ -429,12 +401,12 @@ static void dsi_ps_control(struct mtk_dsi *dsi) | |||
429 | writel(tmp_reg, dsi->regs + DSI_PSCTRL); | 401 | writel(tmp_reg, dsi->regs + DSI_PSCTRL); |
430 | } | 402 | } |
431 | 403 | ||
432 | static void dsi_config_vdo_timing(struct mtk_dsi *dsi) | 404 | static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) |
433 | { | 405 | { |
434 | unsigned int horizontal_sync_active_byte; | 406 | u32 horizontal_sync_active_byte; |
435 | unsigned int horizontal_backporch_byte; | 407 | u32 horizontal_backporch_byte; |
436 | unsigned int horizontal_frontporch_byte; | 408 | u32 horizontal_frontporch_byte; |
437 | unsigned int dsi_tmp_buf_bpp; | 409 | u32 dsi_tmp_buf_bpp; |
438 | 410 | ||
439 | struct videomode *vm = &dsi->vm; | 411 | struct videomode *vm = &dsi->vm; |
440 | 412 | ||
@@ -463,7 +435,7 @@ static void dsi_config_vdo_timing(struct mtk_dsi *dsi) | |||
463 | writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); | 435 | writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); |
464 | writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); | 436 | writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); |
465 | 437 | ||
466 | dsi_ps_control(dsi); | 438 | mtk_dsi_ps_control(dsi); |
467 | } | 439 | } |
468 | 440 | ||
469 | static void mtk_dsi_start(struct mtk_dsi *dsi) | 441 | static void mtk_dsi_start(struct mtk_dsi *dsi) |
@@ -472,6 +444,184 @@ static void mtk_dsi_start(struct mtk_dsi *dsi) | |||
472 | writel(1, dsi->regs + DSI_START); | 444 | writel(1, dsi->regs + DSI_START); |
473 | } | 445 | } |
474 | 446 | ||
447 | static void mtk_dsi_stop(struct mtk_dsi *dsi) | ||
448 | { | ||
449 | writel(0, dsi->regs + DSI_START); | ||
450 | } | ||
451 | |||
452 | static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi) | ||
453 | { | ||
454 | writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL); | ||
455 | } | ||
456 | |||
457 | static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi) | ||
458 | { | ||
459 | u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; | ||
460 | |||
461 | writel(inten, dsi->regs + DSI_INTEN); | ||
462 | } | ||
463 | |||
464 | static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit) | ||
465 | { | ||
466 | dsi->irq_data |= irq_bit; | ||
467 | } | ||
468 | |||
469 | static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) | ||
470 | { | ||
471 | dsi->irq_data &= ~irq_bit; | ||
472 | } | ||
473 | |||
474 | static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, | ||
475 | unsigned int timeout) | ||
476 | { | ||
477 | s32 ret = 0; | ||
478 | unsigned long jiffies = msecs_to_jiffies(timeout); | ||
479 | |||
480 | ret = wait_event_interruptible_timeout(dsi->irq_wait_queue, | ||
481 | dsi->irq_data & irq_flag, | ||
482 | jiffies); | ||
483 | if (ret == 0) { | ||
484 | DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag); | ||
485 | |||
486 | mtk_dsi_enable(dsi); | ||
487 | mtk_dsi_reset_engine(dsi); | ||
488 | } | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | static irqreturn_t mtk_dsi_irq(int irq, void *dev_id) | ||
494 | { | ||
495 | struct mtk_dsi *dsi = dev_id; | ||
496 | u32 status, tmp; | ||
497 | u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; | ||
498 | |||
499 | status = readl(dsi->regs + DSI_INTSTA) & flag; | ||
500 | |||
501 | if (status) { | ||
502 | do { | ||
503 | mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK); | ||
504 | tmp = readl(dsi->regs + DSI_INTSTA); | ||
505 | } while (tmp & DSI_BUSY); | ||
506 | |||
507 | mtk_dsi_mask(dsi, DSI_INTSTA, status, 0); | ||
508 | mtk_dsi_irq_data_set(dsi, status); | ||
509 | wake_up_interruptible(&dsi->irq_wait_queue); | ||
510 | } | ||
511 | |||
512 | return IRQ_HANDLED; | ||
513 | } | ||
514 | |||
515 | static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t) | ||
516 | { | ||
517 | mtk_dsi_irq_data_clear(dsi, irq_flag); | ||
518 | mtk_dsi_set_cmd_mode(dsi); | ||
519 | |||
520 | if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t)) { | ||
521 | DRM_ERROR("failed to switch cmd mode\n"); | ||
522 | return -ETIME; | ||
523 | } else { | ||
524 | return 0; | ||
525 | } | ||
526 | } | ||
527 | |||
528 | static int mtk_dsi_poweron(struct mtk_dsi *dsi) | ||
529 | { | ||
530 | struct device *dev = dsi->dev; | ||
531 | int ret; | ||
532 | u64 pixel_clock, total_bits; | ||
533 | u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; | ||
534 | |||
535 | if (++dsi->refcount != 1) | ||
536 | return 0; | ||
537 | |||
538 | switch (dsi->format) { | ||
539 | case MIPI_DSI_FMT_RGB565: | ||
540 | bit_per_pixel = 16; | ||
541 | break; | ||
542 | case MIPI_DSI_FMT_RGB666_PACKED: | ||
543 | bit_per_pixel = 18; | ||
544 | break; | ||
545 | case MIPI_DSI_FMT_RGB666: | ||
546 | case MIPI_DSI_FMT_RGB888: | ||
547 | default: | ||
548 | bit_per_pixel = 24; | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000 | ||
554 | * htotal_time = htotal * byte_per_pixel / num_lanes | ||
555 | * overhead_time = lpx + hs_prepare + hs_zero + hs_trail + hs_exit | ||
556 | * mipi_ratio = (htotal_time + overhead_time) / htotal_time | ||
557 | * data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes; | ||
558 | */ | ||
559 | pixel_clock = dsi->vm.pixelclock * 1000; | ||
560 | htotal = dsi->vm.hactive + dsi->vm.hback_porch + dsi->vm.hfront_porch + | ||
561 | dsi->vm.hsync_len; | ||
562 | htotal_bits = htotal * bit_per_pixel; | ||
563 | |||
564 | overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL + | ||
565 | T_HS_EXIT; | ||
566 | overhead_bits = overhead_cycles * dsi->lanes * 8; | ||
567 | total_bits = htotal_bits + overhead_bits; | ||
568 | |||
569 | dsi->data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits, | ||
570 | htotal * dsi->lanes); | ||
571 | |||
572 | ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); | ||
573 | if (ret < 0) { | ||
574 | dev_err(dev, "Failed to set data rate: %d\n", ret); | ||
575 | goto err_refcount; | ||
576 | } | ||
577 | |||
578 | phy_power_on(dsi->phy); | ||
579 | |||
580 | ret = clk_prepare_enable(dsi->engine_clk); | ||
581 | if (ret < 0) { | ||
582 | dev_err(dev, "Failed to enable engine clock: %d\n", ret); | ||
583 | goto err_phy_power_off; | ||
584 | } | ||
585 | |||
586 | ret = clk_prepare_enable(dsi->digital_clk); | ||
587 | if (ret < 0) { | ||
588 | dev_err(dev, "Failed to enable digital clock: %d\n", ret); | ||
589 | goto err_disable_engine_clk; | ||
590 | } | ||
591 | |||
592 | mtk_dsi_enable(dsi); | ||
593 | mtk_dsi_reset_engine(dsi); | ||
594 | mtk_dsi_phy_timconfig(dsi); | ||
595 | |||
596 | mtk_dsi_rxtx_control(dsi); | ||
597 | mtk_dsi_ps_control_vact(dsi); | ||
598 | mtk_dsi_set_vm_cmd(dsi); | ||
599 | mtk_dsi_config_vdo_timing(dsi); | ||
600 | mtk_dsi_set_interrupt_enable(dsi); | ||
601 | |||
602 | mtk_dsi_clk_ulp_mode_leave(dsi); | ||
603 | mtk_dsi_lane0_ulp_mode_leave(dsi); | ||
604 | mtk_dsi_clk_hs_mode(dsi, 0); | ||
605 | |||
606 | if (dsi->panel) { | ||
607 | if (drm_panel_prepare(dsi->panel)) { | ||
608 | DRM_ERROR("failed to prepare the panel\n"); | ||
609 | goto err_disable_digital_clk; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | return 0; | ||
614 | err_disable_digital_clk: | ||
615 | clk_disable_unprepare(dsi->digital_clk); | ||
616 | err_disable_engine_clk: | ||
617 | clk_disable_unprepare(dsi->engine_clk); | ||
618 | err_phy_power_off: | ||
619 | phy_power_off(dsi->phy); | ||
620 | err_refcount: | ||
621 | dsi->refcount--; | ||
622 | return ret; | ||
623 | } | ||
624 | |||
475 | static void mtk_dsi_poweroff(struct mtk_dsi *dsi) | 625 | static void mtk_dsi_poweroff(struct mtk_dsi *dsi) |
476 | { | 626 | { |
477 | if (WARN_ON(dsi->refcount == 0)) | 627 | if (WARN_ON(dsi->refcount == 0)) |
@@ -480,8 +630,18 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) | |||
480 | if (--dsi->refcount != 0) | 630 | if (--dsi->refcount != 0) |
481 | return; | 631 | return; |
482 | 632 | ||
483 | dsi_lane0_ulp_mode_enter(dsi); | 633 | if (!mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500)) { |
484 | dsi_clk_ulp_mode_enter(dsi); | 634 | if (dsi->panel) { |
635 | if (drm_panel_unprepare(dsi->panel)) { | ||
636 | DRM_ERROR("failed to unprepare the panel\n"); | ||
637 | return; | ||
638 | } | ||
639 | } | ||
640 | } | ||
641 | |||
642 | mtk_dsi_reset_engine(dsi); | ||
643 | mtk_dsi_lane0_ulp_mode_enter(dsi); | ||
644 | mtk_dsi_clk_ulp_mode_enter(dsi); | ||
485 | 645 | ||
486 | mtk_dsi_disable(dsi); | 646 | mtk_dsi_disable(dsi); |
487 | 647 | ||
@@ -498,35 +658,30 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi) | |||
498 | if (dsi->enabled) | 658 | if (dsi->enabled) |
499 | return; | 659 | return; |
500 | 660 | ||
501 | if (dsi->panel) { | ||
502 | if (drm_panel_prepare(dsi->panel)) { | ||
503 | DRM_ERROR("failed to setup the panel\n"); | ||
504 | return; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | ret = mtk_dsi_poweron(dsi); | 661 | ret = mtk_dsi_poweron(dsi); |
509 | if (ret < 0) { | 662 | if (ret < 0) { |
510 | DRM_ERROR("failed to power on dsi\n"); | 663 | DRM_ERROR("failed to power on dsi\n"); |
511 | return; | 664 | return; |
512 | } | 665 | } |
513 | 666 | ||
514 | dsi_rxtx_control(dsi); | 667 | mtk_dsi_set_mode(dsi); |
515 | 668 | mtk_dsi_clk_hs_mode(dsi, 1); | |
516 | dsi_clk_ulp_mode_leave(dsi); | ||
517 | dsi_lane0_ulp_mode_leave(dsi); | ||
518 | dsi_clk_hs_mode(dsi, 0); | ||
519 | dsi_set_mode(dsi); | ||
520 | |||
521 | dsi_ps_control_vact(dsi); | ||
522 | dsi_config_vdo_timing(dsi); | ||
523 | |||
524 | dsi_set_mode(dsi); | ||
525 | dsi_clk_hs_mode(dsi, 1); | ||
526 | 669 | ||
527 | mtk_dsi_start(dsi); | 670 | mtk_dsi_start(dsi); |
528 | 671 | ||
672 | if (dsi->panel) { | ||
673 | if (drm_panel_enable(dsi->panel)) { | ||
674 | DRM_ERROR("failed to enable the panel\n"); | ||
675 | goto err_dsi_power_off; | ||
676 | } | ||
677 | } | ||
678 | |||
529 | dsi->enabled = true; | 679 | dsi->enabled = true; |
680 | |||
681 | return; | ||
682 | err_dsi_power_off: | ||
683 | mtk_dsi_stop(dsi); | ||
684 | mtk_dsi_poweroff(dsi); | ||
530 | } | 685 | } |
531 | 686 | ||
532 | static void mtk_output_dsi_disable(struct mtk_dsi *dsi) | 687 | static void mtk_output_dsi_disable(struct mtk_dsi *dsi) |
@@ -541,6 +696,7 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) | |||
541 | } | 696 | } |
542 | } | 697 | } |
543 | 698 | ||
699 | mtk_dsi_stop(dsi); | ||
544 | mtk_dsi_poweroff(dsi); | 700 | mtk_dsi_poweroff(dsi); |
545 | 701 | ||
546 | dsi->enabled = false; | 702 | dsi->enabled = false; |
@@ -742,9 +898,149 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host, | |||
742 | return 0; | 898 | return 0; |
743 | } | 899 | } |
744 | 900 | ||
901 | static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi) | ||
902 | { | ||
903 | u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */ | ||
904 | |||
905 | while (timeout_ms--) { | ||
906 | if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY)) | ||
907 | break; | ||
908 | |||
909 | usleep_range(2, 4); | ||
910 | } | ||
911 | |||
912 | if (timeout_ms == 0) { | ||
913 | DRM_WARN("polling dsi wait not busy timeout!\n"); | ||
914 | |||
915 | mtk_dsi_enable(dsi); | ||
916 | mtk_dsi_reset_engine(dsi); | ||
917 | } | ||
918 | } | ||
919 | |||
920 | static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data) | ||
921 | { | ||
922 | switch (type) { | ||
923 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: | ||
924 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: | ||
925 | return 1; | ||
926 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: | ||
927 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: | ||
928 | return 2; | ||
929 | case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: | ||
930 | case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: | ||
931 | return read_data[1] + read_data[2] * 16; | ||
932 | case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: | ||
933 | DRM_INFO("type is 0x02, try again\n"); | ||
934 | break; | ||
935 | default: | ||
936 | DRM_INFO("type(0x%x) cannot be non-recognite\n", type); | ||
937 | break; | ||
938 | } | ||
939 | |||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg) | ||
944 | { | ||
945 | const char *tx_buf = msg->tx_buf; | ||
946 | u8 config, cmdq_size, cmdq_off, type = msg->type; | ||
947 | u32 reg_val, cmdq_mask, i; | ||
948 | |||
949 | if (MTK_DSI_HOST_IS_READ(type)) | ||
950 | config = BTA; | ||
951 | else | ||
952 | config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET; | ||
953 | |||
954 | if (msg->tx_len > 2) { | ||
955 | cmdq_size = 1 + (msg->tx_len + 3) / 4; | ||
956 | cmdq_off = 4; | ||
957 | cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1; | ||
958 | reg_val = (msg->tx_len << 16) | (type << 8) | config; | ||
959 | } else { | ||
960 | cmdq_size = 1; | ||
961 | cmdq_off = 2; | ||
962 | cmdq_mask = CONFIG | DATA_ID; | ||
963 | reg_val = (type << 8) | config; | ||
964 | } | ||
965 | |||
966 | for (i = 0; i < msg->tx_len; i++) | ||
967 | writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i); | ||
968 | |||
969 | mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val); | ||
970 | mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size); | ||
971 | } | ||
972 | |||
973 | static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi, | ||
974 | const struct mipi_dsi_msg *msg, u8 flag) | ||
975 | { | ||
976 | mtk_dsi_wait_for_idle(dsi); | ||
977 | mtk_dsi_irq_data_clear(dsi, flag); | ||
978 | mtk_dsi_cmdq(dsi, msg); | ||
979 | mtk_dsi_start(dsi); | ||
980 | |||
981 | if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000)) | ||
982 | return -ETIME; | ||
983 | else | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, | ||
988 | const struct mipi_dsi_msg *msg) | ||
989 | { | ||
990 | struct mtk_dsi *dsi = host_to_dsi(host); | ||
991 | u32 recv_cnt, i; | ||
992 | u8 read_data[16]; | ||
993 | void *src_addr; | ||
994 | u8 irq_flag = CMD_DONE_INT_FLAG; | ||
995 | |||
996 | if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) { | ||
997 | DRM_ERROR("dsi engine is not command mode\n"); | ||
998 | return -EINVAL; | ||
999 | } | ||
1000 | |||
1001 | if (MTK_DSI_HOST_IS_READ(msg->type)) | ||
1002 | irq_flag |= LPRX_RD_RDY_INT_FLAG; | ||
1003 | |||
1004 | if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0) | ||
1005 | return -ETIME; | ||
1006 | |||
1007 | if (!MTK_DSI_HOST_IS_READ(msg->type)) | ||
1008 | return 0; | ||
1009 | |||
1010 | if (!msg->rx_buf) { | ||
1011 | DRM_ERROR("dsi receive buffer size may be NULL\n"); | ||
1012 | return -EINVAL; | ||
1013 | } | ||
1014 | |||
1015 | for (i = 0; i < 16; i++) | ||
1016 | *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i); | ||
1017 | |||
1018 | recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data); | ||
1019 | |||
1020 | if (recv_cnt > 2) | ||
1021 | src_addr = &read_data[4]; | ||
1022 | else | ||
1023 | src_addr = &read_data[1]; | ||
1024 | |||
1025 | if (recv_cnt > 10) | ||
1026 | recv_cnt = 10; | ||
1027 | |||
1028 | if (recv_cnt > msg->rx_len) | ||
1029 | recv_cnt = msg->rx_len; | ||
1030 | |||
1031 | if (recv_cnt) | ||
1032 | memcpy(msg->rx_buf, src_addr, recv_cnt); | ||
1033 | |||
1034 | DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n", | ||
1035 | recv_cnt, *((u8 *)(msg->tx_buf))); | ||
1036 | |||
1037 | return recv_cnt; | ||
1038 | } | ||
1039 | |||
745 | static const struct mipi_dsi_host_ops mtk_dsi_ops = { | 1040 | static const struct mipi_dsi_host_ops mtk_dsi_ops = { |
746 | .attach = mtk_dsi_host_attach, | 1041 | .attach = mtk_dsi_host_attach, |
747 | .detach = mtk_dsi_host_detach, | 1042 | .detach = mtk_dsi_host_detach, |
1043 | .transfer = mtk_dsi_host_transfer, | ||
748 | }; | 1044 | }; |
749 | 1045 | ||
750 | static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) | 1046 | static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) |
@@ -803,6 +1099,7 @@ static int mtk_dsi_probe(struct platform_device *pdev) | |||
803 | struct device *dev = &pdev->dev; | 1099 | struct device *dev = &pdev->dev; |
804 | struct device_node *remote_node, *endpoint; | 1100 | struct device_node *remote_node, *endpoint; |
805 | struct resource *regs; | 1101 | struct resource *regs; |
1102 | int irq_num; | ||
806 | int comp_id; | 1103 | int comp_id; |
807 | int ret; | 1104 | int ret; |
808 | 1105 | ||
@@ -879,6 +1176,22 @@ static int mtk_dsi_probe(struct platform_device *pdev) | |||
879 | return ret; | 1176 | return ret; |
880 | } | 1177 | } |
881 | 1178 | ||
1179 | irq_num = platform_get_irq(pdev, 0); | ||
1180 | if (irq_num < 0) { | ||
1181 | dev_err(&pdev->dev, "failed to request dsi irq resource\n"); | ||
1182 | return -EPROBE_DEFER; | ||
1183 | } | ||
1184 | |||
1185 | irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW); | ||
1186 | ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq, | ||
1187 | IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi); | ||
1188 | if (ret) { | ||
1189 | dev_err(&pdev->dev, "failed to request mediatek dsi irq\n"); | ||
1190 | return -EPROBE_DEFER; | ||
1191 | } | ||
1192 | |||
1193 | init_waitqueue_head(&dsi->irq_wait_queue); | ||
1194 | |||
882 | platform_set_drvdata(pdev, dsi); | 1195 | platform_set_drvdata(pdev, dsi); |
883 | 1196 | ||
884 | return component_add(&pdev->dev, &mtk_dsi_component_ops); | 1197 | return component_add(&pdev->dev, &mtk_dsi_component_ops); |
@@ -895,6 +1208,7 @@ static int mtk_dsi_remove(struct platform_device *pdev) | |||
895 | } | 1208 | } |
896 | 1209 | ||
897 | static const struct of_device_id mtk_dsi_of_match[] = { | 1210 | static const struct of_device_id mtk_dsi_of_match[] = { |
1211 | { .compatible = "mediatek,mt2701-dsi" }, | ||
898 | { .compatible = "mediatek,mt8173-dsi" }, | 1212 | { .compatible = "mediatek,mt8173-dsi" }, |
899 | { }, | 1213 | { }, |
900 | }; | 1214 | }; |
diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c index 1c366f8cb2d0..90e913108950 100644 --- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c +++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/of_device.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
21 | 22 | ||
@@ -87,6 +88,9 @@ | |||
87 | 88 | ||
88 | #define MIPITX_DSI_PLL_CON2 0x58 | 89 | #define MIPITX_DSI_PLL_CON2 0x58 |
89 | 90 | ||
91 | #define MIPITX_DSI_PLL_TOP 0x64 | ||
92 | #define RG_DSI_MPPLL_PRESERVE (0xff << 8) | ||
93 | |||
90 | #define MIPITX_DSI_PLL_PWR 0x68 | 94 | #define MIPITX_DSI_PLL_PWR 0x68 |
91 | #define RG_DSI_MPPLL_SDM_PWR_ON BIT(0) | 95 | #define RG_DSI_MPPLL_SDM_PWR_ON BIT(0) |
92 | #define RG_DSI_MPPLL_SDM_ISO_EN BIT(1) | 96 | #define RG_DSI_MPPLL_SDM_ISO_EN BIT(1) |
@@ -123,10 +127,15 @@ | |||
123 | #define SW_LNT2_HSTX_PRE_OE BIT(24) | 127 | #define SW_LNT2_HSTX_PRE_OE BIT(24) |
124 | #define SW_LNT2_HSTX_OE BIT(25) | 128 | #define SW_LNT2_HSTX_OE BIT(25) |
125 | 129 | ||
130 | struct mtk_mipitx_data { | ||
131 | const u32 mppll_preserve; | ||
132 | }; | ||
133 | |||
126 | struct mtk_mipi_tx { | 134 | struct mtk_mipi_tx { |
127 | struct device *dev; | 135 | struct device *dev; |
128 | void __iomem *regs; | 136 | void __iomem *regs; |
129 | unsigned int data_rate; | 137 | u32 data_rate; |
138 | const struct mtk_mipitx_data *driver_data; | ||
130 | struct clk_hw pll_hw; | 139 | struct clk_hw pll_hw; |
131 | struct clk *pll; | 140 | struct clk *pll; |
132 | }; | 141 | }; |
@@ -163,7 +172,7 @@ static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, | |||
163 | static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) | 172 | static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) |
164 | { | 173 | { |
165 | struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); | 174 | struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); |
166 | unsigned int txdiv, txdiv0, txdiv1; | 175 | u8 txdiv, txdiv0, txdiv1; |
167 | u64 pcw; | 176 | u64 pcw; |
168 | 177 | ||
169 | dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); | 178 | dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); |
@@ -243,6 +252,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) | |||
243 | mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1, | 252 | mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1, |
244 | RG_DSI_MPPLL_SDM_SSC_EN); | 253 | RG_DSI_MPPLL_SDM_SSC_EN); |
245 | 254 | ||
255 | mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, | ||
256 | RG_DSI_MPPLL_PRESERVE, | ||
257 | mipi_tx->driver_data->mppll_preserve); | ||
258 | |||
246 | return 0; | 259 | return 0; |
247 | } | 260 | } |
248 | 261 | ||
@@ -255,6 +268,9 @@ static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw) | |||
255 | mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, | 268 | mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, |
256 | RG_DSI_MPPLL_PLL_EN); | 269 | RG_DSI_MPPLL_PLL_EN); |
257 | 270 | ||
271 | mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, | ||
272 | RG_DSI_MPPLL_PRESERVE, 0); | ||
273 | |||
258 | mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, | 274 | mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, |
259 | RG_DSI_MPPLL_SDM_ISO_EN | | 275 | RG_DSI_MPPLL_SDM_ISO_EN | |
260 | RG_DSI_MPPLL_SDM_PWR_ON, | 276 | RG_DSI_MPPLL_SDM_PWR_ON, |
@@ -310,7 +326,7 @@ static const struct clk_ops mtk_mipi_tx_pll_ops = { | |||
310 | static int mtk_mipi_tx_power_on_signal(struct phy *phy) | 326 | static int mtk_mipi_tx_power_on_signal(struct phy *phy) |
311 | { | 327 | { |
312 | struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); | 328 | struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
313 | unsigned int reg; | 329 | u32 reg; |
314 | 330 | ||
315 | for (reg = MIPITX_DSI_CLOCK_LANE; | 331 | for (reg = MIPITX_DSI_CLOCK_LANE; |
316 | reg <= MIPITX_DSI_DATA_LANE3; reg += 4) | 332 | reg <= MIPITX_DSI_DATA_LANE3; reg += 4) |
@@ -341,7 +357,7 @@ static int mtk_mipi_tx_power_on(struct phy *phy) | |||
341 | static void mtk_mipi_tx_power_off_signal(struct phy *phy) | 357 | static void mtk_mipi_tx_power_off_signal(struct phy *phy) |
342 | { | 358 | { |
343 | struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); | 359 | struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
344 | unsigned int reg; | 360 | u32 reg; |
345 | 361 | ||
346 | mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, | 362 | mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, |
347 | RG_DSI_PAD_TIE_LOW_EN); | 363 | RG_DSI_PAD_TIE_LOW_EN); |
@@ -391,6 +407,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) | |||
391 | if (!mipi_tx) | 407 | if (!mipi_tx) |
392 | return -ENOMEM; | 408 | return -ENOMEM; |
393 | 409 | ||
410 | mipi_tx->driver_data = of_device_get_match_data(dev); | ||
394 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 411 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
395 | mipi_tx->regs = devm_ioremap_resource(dev, mem); | 412 | mipi_tx->regs = devm_ioremap_resource(dev, mem); |
396 | if (IS_ERR(mipi_tx->regs)) { | 413 | if (IS_ERR(mipi_tx->regs)) { |
@@ -448,8 +465,19 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev) | |||
448 | return 0; | 465 | return 0; |
449 | } | 466 | } |
450 | 467 | ||
468 | static const struct mtk_mipitx_data mt2701_mipitx_data = { | ||
469 | .mppll_preserve = (3 << 8) | ||
470 | }; | ||
471 | |||
472 | static const struct mtk_mipitx_data mt8173_mipitx_data = { | ||
473 | .mppll_preserve = (0 << 8) | ||
474 | }; | ||
475 | |||
451 | static const struct of_device_id mtk_mipi_tx_match[] = { | 476 | static const struct of_device_id mtk_mipi_tx_match[] = { |
452 | { .compatible = "mediatek,mt8173-mipi-tx", }, | 477 | { .compatible = "mediatek,mt2701-mipi-tx", |
478 | .data = &mt2701_mipitx_data }, | ||
479 | { .compatible = "mediatek,mt8173-mipi-tx", | ||
480 | .data = &mt8173_mipitx_data }, | ||
453 | {}, | 481 | {}, |
454 | }; | 482 | }; |
455 | 483 | ||