diff options
author | Dave Airlie <airlied@redhat.com> | 2018-07-29 20:39:22 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-07-29 20:39:22 -0400 |
commit | 3fce4618279373efc59a91adb16c11da46cd69e5 (patch) | |
tree | 086fad6c9f260a0bcc9b6a3532c6cddc387dd907 /drivers/gpu | |
parent | ecd7963f7cf967009882fd56eaee1e87a229bea2 (diff) | |
parent | acb1872577b346bd15ab3a3f8dff780d6cca4b70 (diff) |
BackMerge v4.18-rc7 into drm-next
rmk requested this for armada and I think we've had a few
conflicts build up.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
43 files changed, 458 insertions, 140 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index f4c474a95875..71efcf38f11b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | |||
@@ -57,6 +57,10 @@ | |||
57 | #define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8 | 57 | #define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8 |
58 | #define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c | 58 | #define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c |
59 | #define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68 | 59 | #define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68 |
60 | #define ACP_BT_PLAY_REGS_START 0x14970 | ||
61 | #define ACP_BT_PLAY_REGS_END 0x14a24 | ||
62 | #define ACP_BT_COMP1_REG_OFFSET 0xac | ||
63 | #define ACP_BT_COMP2_REG_OFFSET 0xa8 | ||
60 | 64 | ||
61 | #define mmACP_PGFSM_RETAIN_REG 0x51c9 | 65 | #define mmACP_PGFSM_RETAIN_REG 0x51c9 |
62 | #define mmACP_PGFSM_CONFIG_REG 0x51ca | 66 | #define mmACP_PGFSM_CONFIG_REG 0x51ca |
@@ -77,7 +81,7 @@ | |||
77 | #define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF | 81 | #define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF |
78 | 82 | ||
79 | #define ACP_TIMEOUT_LOOP 0x000000FF | 83 | #define ACP_TIMEOUT_LOOP 0x000000FF |
80 | #define ACP_DEVS 3 | 84 | #define ACP_DEVS 4 |
81 | #define ACP_SRC_ID 162 | 85 | #define ACP_SRC_ID 162 |
82 | 86 | ||
83 | enum { | 87 | enum { |
@@ -316,14 +320,13 @@ static int acp_hw_init(void *handle) | |||
316 | if (adev->acp.acp_cell == NULL) | 320 | if (adev->acp.acp_cell == NULL) |
317 | return -ENOMEM; | 321 | return -ENOMEM; |
318 | 322 | ||
319 | adev->acp.acp_res = kcalloc(4, sizeof(struct resource), GFP_KERNEL); | 323 | adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL); |
320 | |||
321 | if (adev->acp.acp_res == NULL) { | 324 | if (adev->acp.acp_res == NULL) { |
322 | kfree(adev->acp.acp_cell); | 325 | kfree(adev->acp.acp_cell); |
323 | return -ENOMEM; | 326 | return -ENOMEM; |
324 | } | 327 | } |
325 | 328 | ||
326 | i2s_pdata = kcalloc(2, sizeof(struct i2s_platform_data), GFP_KERNEL); | 329 | i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL); |
327 | if (i2s_pdata == NULL) { | 330 | if (i2s_pdata == NULL) { |
328 | kfree(adev->acp.acp_res); | 331 | kfree(adev->acp.acp_res); |
329 | kfree(adev->acp.acp_cell); | 332 | kfree(adev->acp.acp_cell); |
@@ -358,6 +361,20 @@ static int acp_hw_init(void *handle) | |||
358 | i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET; | 361 | i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET; |
359 | i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET; | 362 | i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET; |
360 | 363 | ||
364 | i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; | ||
365 | switch (adev->asic_type) { | ||
366 | case CHIP_STONEY: | ||
367 | i2s_pdata[2].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; | ||
368 | break; | ||
369 | default: | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD; | ||
374 | i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000; | ||
375 | i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; | ||
376 | i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; | ||
377 | |||
361 | adev->acp.acp_res[0].name = "acp2x_dma"; | 378 | adev->acp.acp_res[0].name = "acp2x_dma"; |
362 | adev->acp.acp_res[0].flags = IORESOURCE_MEM; | 379 | adev->acp.acp_res[0].flags = IORESOURCE_MEM; |
363 | adev->acp.acp_res[0].start = acp_base; | 380 | adev->acp.acp_res[0].start = acp_base; |
@@ -373,13 +390,18 @@ static int acp_hw_init(void *handle) | |||
373 | adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START; | 390 | adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START; |
374 | adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END; | 391 | adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END; |
375 | 392 | ||
376 | adev->acp.acp_res[3].name = "acp2x_dma_irq"; | 393 | adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap"; |
377 | adev->acp.acp_res[3].flags = IORESOURCE_IRQ; | 394 | adev->acp.acp_res[3].flags = IORESOURCE_MEM; |
378 | adev->acp.acp_res[3].start = amdgpu_irq_create_mapping(adev, 162); | 395 | adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_START; |
379 | adev->acp.acp_res[3].end = adev->acp.acp_res[3].start; | 396 | adev->acp.acp_res[3].end = acp_base + ACP_BT_PLAY_REGS_END; |
397 | |||
398 | adev->acp.acp_res[4].name = "acp2x_dma_irq"; | ||
399 | adev->acp.acp_res[4].flags = IORESOURCE_IRQ; | ||
400 | adev->acp.acp_res[4].start = amdgpu_irq_create_mapping(adev, 162); | ||
401 | adev->acp.acp_res[4].end = adev->acp.acp_res[4].start; | ||
380 | 402 | ||
381 | adev->acp.acp_cell[0].name = "acp_audio_dma"; | 403 | adev->acp.acp_cell[0].name = "acp_audio_dma"; |
382 | adev->acp.acp_cell[0].num_resources = 4; | 404 | adev->acp.acp_cell[0].num_resources = 5; |
383 | adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0]; | 405 | adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0]; |
384 | adev->acp.acp_cell[0].platform_data = &adev->asic_type; | 406 | adev->acp.acp_cell[0].platform_data = &adev->asic_type; |
385 | adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type); | 407 | adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type); |
@@ -396,6 +418,12 @@ static int acp_hw_init(void *handle) | |||
396 | adev->acp.acp_cell[2].platform_data = &i2s_pdata[1]; | 418 | adev->acp.acp_cell[2].platform_data = &i2s_pdata[1]; |
397 | adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data); | 419 | adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data); |
398 | 420 | ||
421 | adev->acp.acp_cell[3].name = "designware-i2s"; | ||
422 | adev->acp.acp_cell[3].num_resources = 1; | ||
423 | adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3]; | ||
424 | adev->acp.acp_cell[3].platform_data = &i2s_pdata[2]; | ||
425 | adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data); | ||
426 | |||
399 | r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, | 427 | r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, |
400 | ACP_DEVS); | 428 | ACP_DEVS); |
401 | if (r) | 429 | if (r) |
@@ -451,7 +479,6 @@ static int acp_hw_init(void *handle) | |||
451 | val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); | 479 | val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); |
452 | val &= ~ACP_SOFT_RESET__SoftResetAud_MASK; | 480 | val &= ~ACP_SOFT_RESET__SoftResetAud_MASK; |
453 | cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); | 481 | cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); |
454 | |||
455 | return 0; | 482 | return 0; |
456 | } | 483 | } |
457 | 484 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index b33f1680c9a3..a028661d9e20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | |||
@@ -575,6 +575,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = { | |||
575 | { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, | 575 | { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
576 | { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, | 576 | { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
577 | { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX }, | 577 | { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
578 | { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX }, | ||
578 | { 0, 0, 0, 0, 0 }, | 579 | { 0, 0, 0, 0, 0 }, |
579 | }; | 580 | }; |
580 | 581 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 13acef526c5b..e839470880d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -2843,6 +2843,9 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) | |||
2843 | if (r) | 2843 | if (r) |
2844 | return r; | 2844 | return r; |
2845 | 2845 | ||
2846 | /* Make sure IB tests flushed */ | ||
2847 | flush_delayed_work(&adev->late_init_work); | ||
2848 | |||
2846 | /* blat the mode back in */ | 2849 | /* blat the mode back in */ |
2847 | if (fbcon) { | 2850 | if (fbcon) { |
2848 | if (!amdgpu_device_has_dc_support(adev)) { | 2851 | if (!amdgpu_device_has_dc_support(adev)) { |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 9f0a217603ad..516795342dd2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | |||
@@ -74,4 +74,3 @@ bool dm_read_persistent_data(struct dc_context *ctx, | |||
74 | 74 | ||
75 | /**** power component interfaces ****/ | 75 | /**** power component interfaces ****/ |
76 | 76 | ||
77 | |||
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9d901ca70588..af9386ee5a93 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | |||
@@ -1781,12 +1781,10 @@ static void dp_test_send_link_training(struct dc_link *link) | |||
1781 | dp_retrain_link_dp_test(link, &link_settings, false); | 1781 | dp_retrain_link_dp_test(link, &link_settings, false); |
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | /* TODO hbr2 compliance eye output is unstable | 1784 | /* TODO Raven hbr2 compliance eye output is unstable |
1785 | * (toggling on and off) with debugger break | 1785 | * (toggling on and off) with debugger break |
1786 | * This caueses intermittent PHY automation failure | 1786 | * This caueses intermittent PHY automation failure |
1787 | * Need to look into the root cause */ | 1787 | * Need to look into the root cause */ |
1788 | static uint8_t force_tps4_for_cp2520 = 1; | ||
1789 | |||
1790 | static void dp_test_send_phy_test_pattern(struct dc_link *link) | 1788 | static void dp_test_send_phy_test_pattern(struct dc_link *link) |
1791 | { | 1789 | { |
1792 | union phy_test_pattern dpcd_test_pattern; | 1790 | union phy_test_pattern dpcd_test_pattern; |
@@ -1846,13 +1844,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) | |||
1846 | break; | 1844 | break; |
1847 | case PHY_TEST_PATTERN_CP2520_1: | 1845 | case PHY_TEST_PATTERN_CP2520_1: |
1848 | /* CP2520 pattern is unstable, temporarily use TPS4 instead */ | 1846 | /* CP2520 pattern is unstable, temporarily use TPS4 instead */ |
1849 | test_pattern = (force_tps4_for_cp2520 == 1) ? | 1847 | test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? |
1850 | DP_TEST_PATTERN_TRAINING_PATTERN4 : | 1848 | DP_TEST_PATTERN_TRAINING_PATTERN4 : |
1851 | DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; | 1849 | DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; |
1852 | break; | 1850 | break; |
1853 | case PHY_TEST_PATTERN_CP2520_2: | 1851 | case PHY_TEST_PATTERN_CP2520_2: |
1854 | /* CP2520 pattern is unstable, temporarily use TPS4 instead */ | 1852 | /* CP2520 pattern is unstable, temporarily use TPS4 instead */ |
1855 | test_pattern = (force_tps4_for_cp2520 == 1) ? | 1853 | test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ? |
1856 | DP_TEST_PATTERN_TRAINING_PATTERN4 : | 1854 | DP_TEST_PATTERN_TRAINING_PATTERN4 : |
1857 | DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; | 1855 | DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; |
1858 | break; | 1856 | break; |
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7515c0dcbdd2..b91f14989aef 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h | |||
@@ -77,6 +77,7 @@ struct dc_caps { | |||
77 | bool is_apu; | 77 | bool is_apu; |
78 | bool dual_link_dvi; | 78 | bool dual_link_dvi; |
79 | bool post_blend_color_processing; | 79 | bool post_blend_color_processing; |
80 | bool force_dp_tps4_for_cp2520; | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | struct dc_dcc_surface_param { | 83 | struct dc_dcc_surface_param { |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index cd8c22839227..c39934f8677f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | |||
@@ -1127,6 +1127,8 @@ static bool construct( | |||
1127 | dc->caps.max_slave_planes = 1; | 1127 | dc->caps.max_slave_planes = 1; |
1128 | dc->caps.is_apu = true; | 1128 | dc->caps.is_apu = true; |
1129 | dc->caps.post_blend_color_processing = false; | 1129 | dc->caps.post_blend_color_processing = false; |
1130 | /* Raven DP PHY HBR2 eye diagram pattern is not stable. Use TP4 */ | ||
1131 | dc->caps.force_dp_tps4_for_cp2520 = true; | ||
1130 | 1132 | ||
1131 | if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) | 1133 | if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) |
1132 | dc->debug = debug_defaults_drv; | 1134 | dc->debug = debug_defaults_drv; |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c index f4f366b26fd1..cb3a5b1737c8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c | |||
@@ -226,6 +226,8 @@ static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable | |||
226 | 226 | ||
227 | ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; | 227 | ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; |
228 | 228 | ||
229 | ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; | ||
230 | |||
229 | return 0; | 231 | return 0; |
230 | } | 232 | } |
231 | 233 | ||
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 03eeee11dd5b..42a40daff132 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -519,8 +519,9 @@ static irqreturn_t armada_drm_irq(int irq, void *arg) | |||
519 | u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR); | 519 | u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR); |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * This is rediculous - rather than writing bits to clear, we | 522 | * Reading the ISR appears to clear bits provided CLEAN_SPU_IRQ_ISR |
523 | * have to set the actual status register value. This is racy. | 523 | * is set. Writing has some other effect to acknowledge the IRQ - |
524 | * without this, we only get a single IRQ. | ||
524 | */ | 525 | */ |
525 | writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); | 526 | writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); |
526 | 527 | ||
@@ -1116,16 +1117,22 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, | |||
1116 | static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc) | 1117 | static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc) |
1117 | { | 1118 | { |
1118 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 1119 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
1120 | unsigned long flags; | ||
1119 | 1121 | ||
1122 | spin_lock_irqsave(&dcrtc->irq_lock, flags); | ||
1120 | armada_drm_crtc_enable_irq(dcrtc, VSYNC_IRQ_ENA); | 1123 | armada_drm_crtc_enable_irq(dcrtc, VSYNC_IRQ_ENA); |
1124 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); | ||
1121 | return 0; | 1125 | return 0; |
1122 | } | 1126 | } |
1123 | 1127 | ||
1124 | static void armada_drm_crtc_disable_vblank(struct drm_crtc *crtc) | 1128 | static void armada_drm_crtc_disable_vblank(struct drm_crtc *crtc) |
1125 | { | 1129 | { |
1126 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 1130 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
1131 | unsigned long flags; | ||
1127 | 1132 | ||
1133 | spin_lock_irqsave(&dcrtc->irq_lock, flags); | ||
1128 | armada_drm_crtc_disable_irq(dcrtc, VSYNC_IRQ_ENA); | 1134 | armada_drm_crtc_disable_irq(dcrtc, VSYNC_IRQ_ENA); |
1135 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); | ||
1129 | } | 1136 | } |
1130 | 1137 | ||
1131 | static const struct drm_crtc_funcs armada_crtc_funcs = { | 1138 | static const struct drm_crtc_funcs armada_crtc_funcs = { |
@@ -1415,6 +1422,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, | |||
1415 | CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); | 1422 | CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); |
1416 | writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); | 1423 | writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); |
1417 | writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA); | 1424 | writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA); |
1425 | readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR); | ||
1418 | writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); | 1426 | writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR); |
1419 | 1427 | ||
1420 | ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc", | 1428 | ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc", |
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h index 27319a8335e2..345dc4d0851e 100644 --- a/drivers/gpu/drm/armada/armada_hw.h +++ b/drivers/gpu/drm/armada/armada_hw.h | |||
@@ -160,6 +160,7 @@ enum { | |||
160 | CFG_ALPHAM_GRA = 0x1 << 16, | 160 | CFG_ALPHAM_GRA = 0x1 << 16, |
161 | CFG_ALPHAM_CFG = 0x2 << 16, | 161 | CFG_ALPHAM_CFG = 0x2 << 16, |
162 | CFG_ALPHA_MASK = 0xff << 8, | 162 | CFG_ALPHA_MASK = 0xff << 8, |
163 | #define CFG_ALPHA(x) ((x) << 8) | ||
163 | CFG_PIXCMD_MASK = 0xff, | 164 | CFG_PIXCMD_MASK = 0xff, |
164 | }; | 165 | }; |
165 | 166 | ||
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index c391955009d6..afa7ded3ae31 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -28,6 +28,7 @@ struct armada_ovl_plane_properties { | |||
28 | uint16_t contrast; | 28 | uint16_t contrast; |
29 | uint16_t saturation; | 29 | uint16_t saturation; |
30 | uint32_t colorkey_mode; | 30 | uint32_t colorkey_mode; |
31 | uint32_t colorkey_enable; | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | struct armada_ovl_plane { | 34 | struct armada_ovl_plane { |
@@ -54,11 +55,13 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, | |||
54 | writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); | 55 | writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); |
55 | 56 | ||
56 | spin_lock_irq(&dcrtc->irq_lock); | 57 | spin_lock_irq(&dcrtc->irq_lock); |
57 | armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, | 58 | armada_updatel(prop->colorkey_mode, |
58 | CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, | 59 | CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, |
59 | dcrtc->base + LCD_SPU_DMA_CTRL1); | 60 | dcrtc->base + LCD_SPU_DMA_CTRL1); |
60 | 61 | if (dcrtc->variant->has_spu_adv_reg) | |
61 | armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); | 62 | armada_updatel(prop->colorkey_enable, |
63 | ADV_GRACOLORKEY | ADV_VIDCOLORKEY, | ||
64 | dcrtc->base + LCD_SPU_ADV_REG); | ||
62 | spin_unlock_irq(&dcrtc->irq_lock); | 65 | spin_unlock_irq(&dcrtc->irq_lock); |
63 | } | 66 | } |
64 | 67 | ||
@@ -321,8 +324,17 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, | |||
321 | dplane->prop.colorkey_vb |= K2B(val); | 324 | dplane->prop.colorkey_vb |= K2B(val); |
322 | update_attr = true; | 325 | update_attr = true; |
323 | } else if (property == priv->colorkey_mode_prop) { | 326 | } else if (property == priv->colorkey_mode_prop) { |
324 | dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; | 327 | if (val == CKMODE_DISABLE) { |
325 | dplane->prop.colorkey_mode |= CFG_CKMODE(val); | 328 | dplane->prop.colorkey_mode = |
329 | CFG_CKMODE(CKMODE_DISABLE) | | ||
330 | CFG_ALPHAM_CFG | CFG_ALPHA(255); | ||
331 | dplane->prop.colorkey_enable = 0; | ||
332 | } else { | ||
333 | dplane->prop.colorkey_mode = | ||
334 | CFG_CKMODE(val) | | ||
335 | CFG_ALPHAM_GRA | CFG_ALPHA(0); | ||
336 | dplane->prop.colorkey_enable = ADV_GRACOLORKEY; | ||
337 | } | ||
326 | update_attr = true; | 338 | update_attr = true; |
327 | } else if (property == priv->brightness_prop) { | 339 | } else if (property == priv->brightness_prop) { |
328 | dplane->prop.brightness = val - 256; | 340 | dplane->prop.brightness = val - 256; |
@@ -453,7 +465,9 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) | |||
453 | dplane->prop.colorkey_yr = 0xfefefe00; | 465 | dplane->prop.colorkey_yr = 0xfefefe00; |
454 | dplane->prop.colorkey_ug = 0x01010100; | 466 | dplane->prop.colorkey_ug = 0x01010100; |
455 | dplane->prop.colorkey_vb = 0x01010100; | 467 | dplane->prop.colorkey_vb = 0x01010100; |
456 | dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); | 468 | dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) | |
469 | CFG_ALPHAM_GRA | CFG_ALPHA(0); | ||
470 | dplane->prop.colorkey_enable = ADV_GRACOLORKEY; | ||
457 | dplane->prop.brightness = 0; | 471 | dplane->prop.brightness = 0; |
458 | dplane->prop.contrast = 0x4000; | 472 | dplane->prop.contrast = 0x4000; |
459 | dplane->prop.saturation = 0x4000; | 473 | dplane->prop.saturation = 0x4000; |
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 250effa0e6b8..a6e8f4591e63 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <drm/bridge/mhl.h> | 14 | #include <drm/bridge/mhl.h> |
15 | #include <drm/drm_crtc.h> | 15 | #include <drm/drm_crtc.h> |
16 | #include <drm/drm_edid.h> | 16 | #include <drm/drm_edid.h> |
17 | #include <drm/drm_encoder.h> | ||
17 | 18 | ||
18 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
19 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
@@ -72,9 +73,7 @@ struct sii8620 { | |||
72 | struct regulator_bulk_data supplies[2]; | 73 | struct regulator_bulk_data supplies[2]; |
73 | struct mutex lock; /* context lock, protects fields below */ | 74 | struct mutex lock; /* context lock, protects fields below */ |
74 | int error; | 75 | int error; |
75 | int pixel_clock; | ||
76 | unsigned int use_packed_pixel:1; | 76 | unsigned int use_packed_pixel:1; |
77 | int video_code; | ||
78 | enum sii8620_mode mode; | 77 | enum sii8620_mode mode; |
79 | enum sii8620_sink_type sink_type; | 78 | enum sii8620_sink_type sink_type; |
80 | u8 cbus_status; | 79 | u8 cbus_status; |
@@ -82,7 +81,6 @@ struct sii8620 { | |||
82 | u8 xstat[MHL_XDS_SIZE]; | 81 | u8 xstat[MHL_XDS_SIZE]; |
83 | u8 devcap[MHL_DCAP_SIZE]; | 82 | u8 devcap[MHL_DCAP_SIZE]; |
84 | u8 xdevcap[MHL_XDC_SIZE]; | 83 | u8 xdevcap[MHL_XDC_SIZE]; |
85 | u8 avif[HDMI_INFOFRAME_SIZE(AVI)]; | ||
86 | bool feature_complete; | 84 | bool feature_complete; |
87 | bool devcap_read; | 85 | bool devcap_read; |
88 | bool sink_detected; | 86 | bool sink_detected; |
@@ -1017,21 +1015,36 @@ static void sii8620_stop_video(struct sii8620 *ctx) | |||
1017 | 1015 | ||
1018 | static void sii8620_set_format(struct sii8620 *ctx) | 1016 | static void sii8620_set_format(struct sii8620 *ctx) |
1019 | { | 1017 | { |
1018 | u8 out_fmt; | ||
1019 | |||
1020 | if (sii8620_is_mhl3(ctx)) { | 1020 | if (sii8620_is_mhl3(ctx)) { |
1021 | sii8620_setbits(ctx, REG_M3_P0CTRL, | 1021 | sii8620_setbits(ctx, REG_M3_P0CTRL, |
1022 | BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED, | 1022 | BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED, |
1023 | ctx->use_packed_pixel ? ~0 : 0); | 1023 | ctx->use_packed_pixel ? ~0 : 0); |
1024 | } else { | 1024 | } else { |
1025 | if (ctx->use_packed_pixel) { | ||
1026 | sii8620_write_seq_static(ctx, | ||
1027 | REG_VID_MODE, BIT_VID_MODE_M1080P, | ||
1028 | REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1, | ||
1029 | REG_MHLTX_CTL6, 0x60 | ||
1030 | ); | ||
1031 | } else { | ||
1025 | sii8620_write_seq_static(ctx, | 1032 | sii8620_write_seq_static(ctx, |
1026 | REG_VID_MODE, 0, | 1033 | REG_VID_MODE, 0, |
1027 | REG_MHL_TOP_CTL, 1, | 1034 | REG_MHL_TOP_CTL, 1, |
1028 | REG_MHLTX_CTL6, 0xa0 | 1035 | REG_MHLTX_CTL6, 0xa0 |
1029 | ); | 1036 | ); |
1037 | } | ||
1030 | } | 1038 | } |
1031 | 1039 | ||
1040 | if (ctx->use_packed_pixel) | ||
1041 | out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL); | ||
1042 | else | ||
1043 | out_fmt = VAL_TPI_FORMAT(RGB, FULL); | ||
1044 | |||
1032 | sii8620_write_seq(ctx, | 1045 | sii8620_write_seq(ctx, |
1033 | REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL), | 1046 | REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL), |
1034 | REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL), | 1047 | REG_TPI_OUTPUT, out_fmt, |
1035 | ); | 1048 | ); |
1036 | } | 1049 | } |
1037 | 1050 | ||
@@ -1082,18 +1095,28 @@ static ssize_t mhl3_infoframe_pack(struct mhl3_infoframe *frame, | |||
1082 | return frm_len; | 1095 | return frm_len; |
1083 | } | 1096 | } |
1084 | 1097 | ||
1085 | static void sii8620_set_infoframes(struct sii8620 *ctx) | 1098 | static void sii8620_set_infoframes(struct sii8620 *ctx, |
1099 | struct drm_display_mode *mode) | ||
1086 | { | 1100 | { |
1087 | struct mhl3_infoframe mhl_frm; | 1101 | struct mhl3_infoframe mhl_frm; |
1088 | union hdmi_infoframe frm; | 1102 | union hdmi_infoframe frm; |
1089 | u8 buf[31]; | 1103 | u8 buf[31]; |
1090 | int ret; | 1104 | int ret; |
1091 | 1105 | ||
1106 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, | ||
1107 | mode, | ||
1108 | true); | ||
1109 | if (ctx->use_packed_pixel) | ||
1110 | frm.avi.colorspace = HDMI_COLORSPACE_YUV422; | ||
1111 | |||
1112 | if (!ret) | ||
1113 | ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf)); | ||
1114 | if (ret > 0) | ||
1115 | sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3); | ||
1116 | |||
1092 | if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) { | 1117 | if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) { |
1093 | sii8620_write(ctx, REG_TPI_SC, | 1118 | sii8620_write(ctx, REG_TPI_SC, |
1094 | BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI); | 1119 | BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI); |
1095 | sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif + 3, | ||
1096 | ARRAY_SIZE(ctx->avif) - 3); | ||
1097 | sii8620_write(ctx, REG_PKT_FILTER_0, | 1120 | sii8620_write(ctx, REG_PKT_FILTER_0, |
1098 | BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | | 1121 | BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | |
1099 | BIT_PKT_FILTER_0_DROP_MPEG_PKT | | 1122 | BIT_PKT_FILTER_0_DROP_MPEG_PKT | |
@@ -1102,16 +1125,6 @@ static void sii8620_set_infoframes(struct sii8620 *ctx) | |||
1102 | return; | 1125 | return; |
1103 | } | 1126 | } |
1104 | 1127 | ||
1105 | ret = hdmi_avi_infoframe_init(&frm.avi); | ||
1106 | frm.avi.colorspace = HDMI_COLORSPACE_YUV422; | ||
1107 | frm.avi.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE; | ||
1108 | frm.avi.picture_aspect = HDMI_PICTURE_ASPECT_16_9; | ||
1109 | frm.avi.colorimetry = HDMI_COLORIMETRY_ITU_709; | ||
1110 | frm.avi.video_code = ctx->video_code; | ||
1111 | if (!ret) | ||
1112 | ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf)); | ||
1113 | if (ret > 0) | ||
1114 | sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3); | ||
1115 | sii8620_write(ctx, REG_PKT_FILTER_0, | 1128 | sii8620_write(ctx, REG_PKT_FILTER_0, |
1116 | BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | | 1129 | BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | |
1117 | BIT_PKT_FILTER_0_DROP_MPEG_PKT | | 1130 | BIT_PKT_FILTER_0_DROP_MPEG_PKT | |
@@ -1131,6 +1144,9 @@ static void sii8620_set_infoframes(struct sii8620 *ctx) | |||
1131 | 1144 | ||
1132 | static void sii8620_start_video(struct sii8620 *ctx) | 1145 | static void sii8620_start_video(struct sii8620 *ctx) |
1133 | { | 1146 | { |
1147 | struct drm_display_mode *mode = | ||
1148 | &ctx->bridge.encoder->crtc->state->adjusted_mode; | ||
1149 | |||
1134 | if (!sii8620_is_mhl3(ctx)) | 1150 | if (!sii8620_is_mhl3(ctx)) |
1135 | sii8620_stop_video(ctx); | 1151 | sii8620_stop_video(ctx); |
1136 | 1152 | ||
@@ -1149,8 +1165,14 @@ static void sii8620_start_video(struct sii8620 *ctx) | |||
1149 | sii8620_set_format(ctx); | 1165 | sii8620_set_format(ctx); |
1150 | 1166 | ||
1151 | if (!sii8620_is_mhl3(ctx)) { | 1167 | if (!sii8620_is_mhl3(ctx)) { |
1152 | sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), | 1168 | u8 link_mode = MHL_DST_LM_PATH_ENABLED; |
1153 | MHL_DST_LM_CLK_MODE_NORMAL | MHL_DST_LM_PATH_ENABLED); | 1169 | |
1170 | if (ctx->use_packed_pixel) | ||
1171 | link_mode |= MHL_DST_LM_CLK_MODE_PACKED_PIXEL; | ||
1172 | else | ||
1173 | link_mode |= MHL_DST_LM_CLK_MODE_NORMAL; | ||
1174 | |||
1175 | sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), link_mode); | ||
1154 | sii8620_set_auto_zone(ctx); | 1176 | sii8620_set_auto_zone(ctx); |
1155 | } else { | 1177 | } else { |
1156 | static const struct { | 1178 | static const struct { |
@@ -1167,7 +1189,7 @@ static void sii8620_start_video(struct sii8620 *ctx) | |||
1167 | MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 }, | 1189 | MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 }, |
1168 | }; | 1190 | }; |
1169 | u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN; | 1191 | u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN; |
1170 | int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3); | 1192 | int clk = mode->clock * (ctx->use_packed_pixel ? 2 : 3); |
1171 | int i; | 1193 | int i; |
1172 | 1194 | ||
1173 | for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i) | 1195 | for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i) |
@@ -1196,7 +1218,7 @@ static void sii8620_start_video(struct sii8620 *ctx) | |||
1196 | clk_spec[i].link_rate); | 1218 | clk_spec[i].link_rate); |
1197 | } | 1219 | } |
1198 | 1220 | ||
1199 | sii8620_set_infoframes(ctx); | 1221 | sii8620_set_infoframes(ctx, mode); |
1200 | } | 1222 | } |
1201 | 1223 | ||
1202 | static void sii8620_disable_hpd(struct sii8620 *ctx) | 1224 | static void sii8620_disable_hpd(struct sii8620 *ctx) |
@@ -1661,14 +1683,18 @@ static void sii8620_status_dcap_ready(struct sii8620 *ctx) | |||
1661 | 1683 | ||
1662 | static void sii8620_status_changed_path(struct sii8620 *ctx) | 1684 | static void sii8620_status_changed_path(struct sii8620 *ctx) |
1663 | { | 1685 | { |
1664 | if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) { | 1686 | u8 link_mode; |
1665 | sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), | 1687 | |
1666 | MHL_DST_LM_CLK_MODE_NORMAL | 1688 | if (ctx->use_packed_pixel) |
1667 | | MHL_DST_LM_PATH_ENABLED); | 1689 | link_mode = MHL_DST_LM_CLK_MODE_PACKED_PIXEL; |
1668 | } else { | 1690 | else |
1669 | sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), | 1691 | link_mode = MHL_DST_LM_CLK_MODE_NORMAL; |
1670 | MHL_DST_LM_CLK_MODE_NORMAL); | 1692 | |
1671 | } | 1693 | if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) |
1694 | link_mode |= MHL_DST_LM_PATH_ENABLED; | ||
1695 | |||
1696 | sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), | ||
1697 | link_mode); | ||
1672 | } | 1698 | } |
1673 | 1699 | ||
1674 | static void sii8620_msc_mr_write_stat(struct sii8620 *ctx) | 1700 | static void sii8620_msc_mr_write_stat(struct sii8620 *ctx) |
@@ -2242,8 +2268,6 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge, | |||
2242 | mutex_lock(&ctx->lock); | 2268 | mutex_lock(&ctx->lock); |
2243 | 2269 | ||
2244 | ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode); | 2270 | ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode); |
2245 | ctx->video_code = drm_match_cea_mode(adjusted_mode); | ||
2246 | ctx->pixel_clock = adjusted_mode->clock; | ||
2247 | 2271 | ||
2248 | mutex_unlock(&ctx->lock); | 2272 | mutex_unlock(&ctx->lock); |
2249 | 2273 | ||
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 50c73c0a20b9..d638c0fb3418 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c | |||
@@ -553,24 +553,13 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, | |||
553 | 553 | ||
554 | /* Clone the lessor file to create a new file for us */ | 554 | /* Clone the lessor file to create a new file for us */ |
555 | DRM_DEBUG_LEASE("Allocating lease file\n"); | 555 | DRM_DEBUG_LEASE("Allocating lease file\n"); |
556 | path_get(&lessor_file->f_path); | 556 | lessee_file = filp_clone_open(lessor_file); |
557 | lessee_file = alloc_file(&lessor_file->f_path, | ||
558 | lessor_file->f_mode, | ||
559 | fops_get(lessor_file->f_inode->i_fop)); | ||
560 | |||
561 | if (IS_ERR(lessee_file)) { | 557 | if (IS_ERR(lessee_file)) { |
562 | ret = PTR_ERR(lessee_file); | 558 | ret = PTR_ERR(lessee_file); |
563 | goto out_lessee; | 559 | goto out_lessee; |
564 | } | 560 | } |
565 | 561 | ||
566 | /* Initialize the new file for DRM */ | ||
567 | DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open); | ||
568 | ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file); | ||
569 | if (ret) | ||
570 | goto out_lessee_file; | ||
571 | |||
572 | lessee_priv = lessee_file->private_data; | 562 | lessee_priv = lessee_file->private_data; |
573 | |||
574 | /* Change the file to a master one */ | 563 | /* Change the file to a master one */ |
575 | drm_master_put(&lessee_priv->master); | 564 | drm_master_put(&lessee_priv->master); |
576 | lessee_priv->master = lessee; | 565 | lessee_priv->master = lessee; |
@@ -588,9 +577,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, | |||
588 | DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); | 577 | DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); |
589 | return 0; | 578 | return 0; |
590 | 579 | ||
591 | out_lessee_file: | ||
592 | fput(lessee_file); | ||
593 | |||
594 | out_lessee: | 580 | out_lessee: |
595 | drm_master_put(&lessee); | 581 | drm_master_put(&lessee); |
596 | 582 | ||
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 1f8031e30f53..cdb10f885a4f 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c | |||
@@ -532,7 +532,7 @@ static void drm_property_free_blob(struct kref *kref) | |||
532 | 532 | ||
533 | drm_mode_object_unregister(blob->dev, &blob->base); | 533 | drm_mode_object_unregister(blob->dev, &blob->base); |
534 | 534 | ||
535 | kfree(blob); | 535 | kvfree(blob); |
536 | } | 536 | } |
537 | 537 | ||
538 | /** | 538 | /** |
@@ -559,7 +559,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length, | |||
559 | if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob)) | 559 | if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob)) |
560 | return ERR_PTR(-EINVAL); | 560 | return ERR_PTR(-EINVAL); |
561 | 561 | ||
562 | blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); | 562 | blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); |
563 | if (!blob) | 563 | if (!blob) |
564 | return ERR_PTR(-ENOMEM); | 564 | return ERR_PTR(-ENOMEM); |
565 | 565 | ||
@@ -576,7 +576,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length, | |||
576 | ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB, | 576 | ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB, |
577 | true, drm_property_free_blob); | 577 | true, drm_property_free_blob); |
578 | if (ret) { | 578 | if (ret) { |
579 | kfree(blob); | 579 | kvfree(blob); |
580 | return ERR_PTR(-EINVAL); | 580 | return ERR_PTR(-EINVAL); |
581 | } | 581 | } |
582 | 582 | ||
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 207532c05eb8..9b2720b41571 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c | |||
@@ -630,8 +630,11 @@ static struct platform_driver etnaviv_platform_driver = { | |||
630 | }, | 630 | }, |
631 | }; | 631 | }; |
632 | 632 | ||
633 | static struct platform_device *etnaviv_drm; | ||
634 | |||
633 | static int __init etnaviv_init(void) | 635 | static int __init etnaviv_init(void) |
634 | { | 636 | { |
637 | struct platform_device *pdev; | ||
635 | int ret; | 638 | int ret; |
636 | struct device_node *np; | 639 | struct device_node *np; |
637 | 640 | ||
@@ -643,7 +646,7 @@ static int __init etnaviv_init(void) | |||
643 | 646 | ||
644 | ret = platform_driver_register(&etnaviv_platform_driver); | 647 | ret = platform_driver_register(&etnaviv_platform_driver); |
645 | if (ret != 0) | 648 | if (ret != 0) |
646 | platform_driver_unregister(&etnaviv_gpu_driver); | 649 | goto unregister_gpu_driver; |
647 | 650 | ||
648 | /* | 651 | /* |
649 | * If the DT contains at least one available GPU device, instantiate | 652 | * If the DT contains at least one available GPU device, instantiate |
@@ -652,20 +655,33 @@ static int __init etnaviv_init(void) | |||
652 | for_each_compatible_node(np, NULL, "vivante,gc") { | 655 | for_each_compatible_node(np, NULL, "vivante,gc") { |
653 | if (!of_device_is_available(np)) | 656 | if (!of_device_is_available(np)) |
654 | continue; | 657 | continue; |
655 | 658 | pdev = platform_device_register_simple("etnaviv", -1, | |
656 | platform_device_register_simple("etnaviv", -1, NULL, 0); | 659 | NULL, 0); |
660 | if (IS_ERR(pdev)) { | ||
661 | ret = PTR_ERR(pdev); | ||
662 | of_node_put(np); | ||
663 | goto unregister_platform_driver; | ||
664 | } | ||
665 | etnaviv_drm = pdev; | ||
657 | of_node_put(np); | 666 | of_node_put(np); |
658 | break; | 667 | break; |
659 | } | 668 | } |
660 | 669 | ||
670 | return 0; | ||
671 | |||
672 | unregister_platform_driver: | ||
673 | platform_driver_unregister(&etnaviv_platform_driver); | ||
674 | unregister_gpu_driver: | ||
675 | platform_driver_unregister(&etnaviv_gpu_driver); | ||
661 | return ret; | 676 | return ret; |
662 | } | 677 | } |
663 | module_init(etnaviv_init); | 678 | module_init(etnaviv_init); |
664 | 679 | ||
665 | static void __exit etnaviv_exit(void) | 680 | static void __exit etnaviv_exit(void) |
666 | { | 681 | { |
667 | platform_driver_unregister(&etnaviv_gpu_driver); | 682 | platform_device_unregister(etnaviv_drm); |
668 | platform_driver_unregister(&etnaviv_platform_driver); | 683 | platform_driver_unregister(&etnaviv_platform_driver); |
684 | platform_driver_unregister(&etnaviv_gpu_driver); | ||
669 | } | 685 | } |
670 | module_exit(etnaviv_exit); | 686 | module_exit(etnaviv_exit); |
671 | 687 | ||
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index dd430f0f8ff5..90f17ff7888e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h | |||
@@ -131,6 +131,9 @@ struct etnaviv_gpu { | |||
131 | struct work_struct sync_point_work; | 131 | struct work_struct sync_point_work; |
132 | int sync_point_event; | 132 | int sync_point_event; |
133 | 133 | ||
134 | /* hang detection */ | ||
135 | u32 hangcheck_dma_addr; | ||
136 | |||
134 | void __iomem *mmio; | 137 | void __iomem *mmio; |
135 | int irq; | 138 | int irq; |
136 | 139 | ||
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 590e44b0d963..3949f18afb35 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "etnaviv_gem.h" | 10 | #include "etnaviv_gem.h" |
11 | #include "etnaviv_gpu.h" | 11 | #include "etnaviv_gpu.h" |
12 | #include "etnaviv_sched.h" | 12 | #include "etnaviv_sched.h" |
13 | #include "state.xml.h" | ||
13 | 14 | ||
14 | static int etnaviv_job_hang_limit = 0; | 15 | static int etnaviv_job_hang_limit = 0; |
15 | module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444); | 16 | module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444); |
@@ -85,6 +86,29 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) | |||
85 | { | 86 | { |
86 | struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); | 87 | struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); |
87 | struct etnaviv_gpu *gpu = submit->gpu; | 88 | struct etnaviv_gpu *gpu = submit->gpu; |
89 | u32 dma_addr; | ||
90 | int change; | ||
91 | |||
92 | /* | ||
93 | * If the GPU managed to complete this jobs fence, the timout is | ||
94 | * spurious. Bail out. | ||
95 | */ | ||
96 | if (fence_completed(gpu, submit->out_fence->seqno)) | ||
97 | return; | ||
98 | |||
99 | /* | ||
100 | * If the GPU is still making forward progress on the front-end (which | ||
101 | * should never loop) we shift out the timeout to give it a chance to | ||
102 | * finish the job. | ||
103 | */ | ||
104 | dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS); | ||
105 | change = dma_addr - gpu->hangcheck_dma_addr; | ||
106 | if (change < 0 || change > 16) { | ||
107 | gpu->hangcheck_dma_addr = dma_addr; | ||
108 | schedule_delayed_work(&sched_job->work_tdr, | ||
109 | sched_job->sched->timeout); | ||
110 | return; | ||
111 | } | ||
88 | 112 | ||
89 | /* block scheduler */ | 113 | /* block scheduler */ |
90 | kthread_park(gpu->sched.thread); | 114 | kthread_park(gpu->sched.thread); |
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0651e63b25fb..45e89b1e0481 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | |||
@@ -863,6 +863,7 @@ static int cmd_reg_handler(struct parser_exec_state *s, | |||
863 | { | 863 | { |
864 | struct intel_vgpu *vgpu = s->vgpu; | 864 | struct intel_vgpu *vgpu = s->vgpu; |
865 | struct intel_gvt *gvt = vgpu->gvt; | 865 | struct intel_gvt *gvt = vgpu->gvt; |
866 | u32 ctx_sr_ctl; | ||
866 | 867 | ||
867 | if (offset + 4 > gvt->device_info.mmio_size) { | 868 | if (offset + 4 > gvt->device_info.mmio_size) { |
868 | gvt_vgpu_err("%s access to (%x) outside of MMIO range\n", | 869 | gvt_vgpu_err("%s access to (%x) outside of MMIO range\n", |
@@ -895,6 +896,28 @@ static int cmd_reg_handler(struct parser_exec_state *s, | |||
895 | patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE); | 896 | patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE); |
896 | } | 897 | } |
897 | 898 | ||
899 | /* TODO | ||
900 | * Right now only scan LRI command on KBL and in inhibit context. | ||
901 | * It's good enough to support initializing mmio by lri command in | ||
902 | * vgpu inhibit context on KBL. | ||
903 | */ | ||
904 | if (IS_KABYLAKE(s->vgpu->gvt->dev_priv) && | ||
905 | intel_gvt_mmio_is_in_ctx(gvt, offset) && | ||
906 | !strncmp(cmd, "lri", 3)) { | ||
907 | intel_gvt_hypervisor_read_gpa(s->vgpu, | ||
908 | s->workload->ring_context_gpa + 12, &ctx_sr_ctl, 4); | ||
909 | /* check inhibit context */ | ||
910 | if (ctx_sr_ctl & 1) { | ||
911 | u32 data = cmd_val(s, index + 1); | ||
912 | |||
913 | if (intel_gvt_mmio_has_mode_mask(s->vgpu->gvt, offset)) | ||
914 | intel_vgpu_mask_mmio_write(vgpu, | ||
915 | offset, &data, 4); | ||
916 | else | ||
917 | vgpu_vreg(vgpu, offset) = data; | ||
918 | } | ||
919 | } | ||
920 | |||
898 | /* TODO: Update the global mask if this MMIO is a masked-MMIO */ | 921 | /* TODO: Update the global mask if this MMIO is a masked-MMIO */ |
899 | intel_gvt_mmio_set_cmd_accessed(gvt, offset); | 922 | intel_gvt_mmio_set_cmd_accessed(gvt, offset); |
900 | return 0; | 923 | return 0; |
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 6ee50cb328f8..3019dbc39aef 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c | |||
@@ -219,7 +219,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | |||
219 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | | 219 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | |
220 | TRANS_DDI_PORT_MASK); | 220 | TRANS_DDI_PORT_MASK); |
221 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= | 221 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= |
222 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | | 222 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI | |
223 | (PORT_B << TRANS_DDI_PORT_SHIFT) | | 223 | (PORT_B << TRANS_DDI_PORT_SHIFT) | |
224 | TRANS_DDI_FUNC_ENABLE); | 224 | TRANS_DDI_FUNC_ENABLE); |
225 | if (IS_BROADWELL(dev_priv)) { | 225 | if (IS_BROADWELL(dev_priv)) { |
@@ -239,7 +239,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | |||
239 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | | 239 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | |
240 | TRANS_DDI_PORT_MASK); | 240 | TRANS_DDI_PORT_MASK); |
241 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= | 241 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= |
242 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | | 242 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI | |
243 | (PORT_C << TRANS_DDI_PORT_SHIFT) | | 243 | (PORT_C << TRANS_DDI_PORT_SHIFT) | |
244 | TRANS_DDI_FUNC_ENABLE); | 244 | TRANS_DDI_FUNC_ENABLE); |
245 | if (IS_BROADWELL(dev_priv)) { | 245 | if (IS_BROADWELL(dev_priv)) { |
@@ -259,7 +259,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | |||
259 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | | 259 | ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | |
260 | TRANS_DDI_PORT_MASK); | 260 | TRANS_DDI_PORT_MASK); |
261 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= | 261 | vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= |
262 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | | 262 | (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI | |
263 | (PORT_D << TRANS_DDI_PORT_SHIFT) | | 263 | (PORT_D << TRANS_DDI_PORT_SHIFT) | |
264 | TRANS_DDI_FUNC_ENABLE); | 264 | TRANS_DDI_FUNC_ENABLE); |
265 | if (IS_BROADWELL(dev_priv)) { | 265 | if (IS_BROADWELL(dev_priv)) { |
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 39980dfbbebd..00aad8164dec 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c | |||
@@ -1901,6 +1901,7 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu) | |||
1901 | vgpu_free_mm(mm); | 1901 | vgpu_free_mm(mm); |
1902 | return ERR_PTR(-ENOMEM); | 1902 | return ERR_PTR(-ENOMEM); |
1903 | } | 1903 | } |
1904 | mm->ggtt_mm.last_partial_off = -1UL; | ||
1904 | 1905 | ||
1905 | return mm; | 1906 | return mm; |
1906 | } | 1907 | } |
@@ -1925,6 +1926,7 @@ void _intel_vgpu_mm_release(struct kref *mm_ref) | |||
1925 | invalidate_ppgtt_mm(mm); | 1926 | invalidate_ppgtt_mm(mm); |
1926 | } else { | 1927 | } else { |
1927 | vfree(mm->ggtt_mm.virtual_ggtt); | 1928 | vfree(mm->ggtt_mm.virtual_ggtt); |
1929 | mm->ggtt_mm.last_partial_off = -1UL; | ||
1928 | } | 1930 | } |
1929 | 1931 | ||
1930 | vgpu_free_mm(mm); | 1932 | vgpu_free_mm(mm); |
@@ -2177,6 +2179,62 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, | |||
2177 | memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, | 2179 | memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, |
2178 | bytes); | 2180 | bytes); |
2179 | 2181 | ||
2182 | /* If ggtt entry size is 8 bytes, and it's split into two 4 bytes | ||
2183 | * write, we assume the two 4 bytes writes are consecutive. | ||
2184 | * Otherwise, we abort and report error | ||
2185 | */ | ||
2186 | if (bytes < info->gtt_entry_size) { | ||
2187 | if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) { | ||
2188 | /* the first partial part*/ | ||
2189 | ggtt_mm->ggtt_mm.last_partial_off = off; | ||
2190 | ggtt_mm->ggtt_mm.last_partial_data = e.val64; | ||
2191 | return 0; | ||
2192 | } else if ((g_gtt_index == | ||
2193 | (ggtt_mm->ggtt_mm.last_partial_off >> | ||
2194 | info->gtt_entry_size_shift)) && | ||
2195 | (off != ggtt_mm->ggtt_mm.last_partial_off)) { | ||
2196 | /* the second partial part */ | ||
2197 | |||
2198 | int last_off = ggtt_mm->ggtt_mm.last_partial_off & | ||
2199 | (info->gtt_entry_size - 1); | ||
2200 | |||
2201 | memcpy((void *)&e.val64 + last_off, | ||
2202 | (void *)&ggtt_mm->ggtt_mm.last_partial_data + | ||
2203 | last_off, bytes); | ||
2204 | |||
2205 | ggtt_mm->ggtt_mm.last_partial_off = -1UL; | ||
2206 | } else { | ||
2207 | int last_offset; | ||
2208 | |||
2209 | gvt_vgpu_err("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n", | ||
2210 | ggtt_mm->ggtt_mm.last_partial_off, off, | ||
2211 | bytes, info->gtt_entry_size); | ||
2212 | |||
2213 | /* set host ggtt entry to scratch page and clear | ||
2214 | * virtual ggtt entry as not present for last | ||
2215 | * partially write offset | ||
2216 | */ | ||
2217 | last_offset = ggtt_mm->ggtt_mm.last_partial_off & | ||
2218 | (~(info->gtt_entry_size - 1)); | ||
2219 | |||
2220 | ggtt_get_host_entry(ggtt_mm, &m, last_offset); | ||
2221 | ggtt_invalidate_pte(vgpu, &m); | ||
2222 | ops->set_pfn(&m, gvt->gtt.scratch_mfn); | ||
2223 | ops->clear_present(&m); | ||
2224 | ggtt_set_host_entry(ggtt_mm, &m, last_offset); | ||
2225 | ggtt_invalidate(gvt->dev_priv); | ||
2226 | |||
2227 | ggtt_get_guest_entry(ggtt_mm, &e, last_offset); | ||
2228 | ops->clear_present(&e); | ||
2229 | ggtt_set_guest_entry(ggtt_mm, &e, last_offset); | ||
2230 | |||
2231 | ggtt_mm->ggtt_mm.last_partial_off = off; | ||
2232 | ggtt_mm->ggtt_mm.last_partial_data = e.val64; | ||
2233 | |||
2234 | return 0; | ||
2235 | } | ||
2236 | } | ||
2237 | |||
2180 | if (ops->test_present(&e)) { | 2238 | if (ops->test_present(&e)) { |
2181 | gfn = ops->get_pfn(&e); | 2239 | gfn = ops->get_pfn(&e); |
2182 | m = e; | 2240 | m = e; |
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index b7bf68cc8418..7a9b36176efb 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h | |||
@@ -157,6 +157,8 @@ struct intel_vgpu_mm { | |||
157 | } ppgtt_mm; | 157 | } ppgtt_mm; |
158 | struct { | 158 | struct { |
159 | void *virtual_ggtt; | 159 | void *virtual_ggtt; |
160 | unsigned long last_partial_off; | ||
161 | u64 last_partial_data; | ||
160 | } ggtt_mm; | 162 | } ggtt_mm; |
161 | }; | 163 | }; |
162 | }; | 164 | }; |
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index de2a3a2580be..9a9671522774 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h | |||
@@ -274,6 +274,8 @@ struct intel_gvt_mmio { | |||
274 | #define F_CMD_ACCESSED (1 << 5) | 274 | #define F_CMD_ACCESSED (1 << 5) |
275 | /* This reg could be accessed by unaligned address */ | 275 | /* This reg could be accessed by unaligned address */ |
276 | #define F_UNALIGN (1 << 6) | 276 | #define F_UNALIGN (1 << 6) |
277 | /* This reg is saved/restored in context */ | ||
278 | #define F_IN_CTX (1 << 7) | ||
277 | 279 | ||
278 | struct gvt_mmio_block *mmio_block; | 280 | struct gvt_mmio_block *mmio_block; |
279 | unsigned int num_mmio_block; | 281 | unsigned int num_mmio_block; |
@@ -655,6 +657,33 @@ static inline bool intel_gvt_mmio_has_mode_mask( | |||
655 | return gvt->mmio.mmio_attribute[offset >> 2] & F_MODE_MASK; | 657 | return gvt->mmio.mmio_attribute[offset >> 2] & F_MODE_MASK; |
656 | } | 658 | } |
657 | 659 | ||
660 | /** | ||
661 | * intel_gvt_mmio_is_in_ctx - check if a MMIO has in-ctx mask | ||
662 | * @gvt: a GVT device | ||
663 | * @offset: register offset | ||
664 | * | ||
665 | * Returns: | ||
666 | * True if a MMIO has a in-context mask, false if it isn't. | ||
667 | * | ||
668 | */ | ||
669 | static inline bool intel_gvt_mmio_is_in_ctx( | ||
670 | struct intel_gvt *gvt, unsigned int offset) | ||
671 | { | ||
672 | return gvt->mmio.mmio_attribute[offset >> 2] & F_IN_CTX; | ||
673 | } | ||
674 | |||
675 | /** | ||
676 | * intel_gvt_mmio_set_in_ctx - mask a MMIO in logical context | ||
677 | * @gvt: a GVT device | ||
678 | * @offset: register offset | ||
679 | * | ||
680 | */ | ||
681 | static inline void intel_gvt_mmio_set_in_ctx( | ||
682 | struct intel_gvt *gvt, unsigned int offset) | ||
683 | { | ||
684 | gvt->mmio.mmio_attribute[offset >> 2] |= F_IN_CTX; | ||
685 | } | ||
686 | |||
658 | int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu); | 687 | int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu); |
659 | void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu); | 688 | void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu); |
660 | int intel_gvt_debugfs_init(struct intel_gvt *gvt); | 689 | int intel_gvt_debugfs_init(struct intel_gvt *gvt); |
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 6b50f850dc28..7a58ca555197 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c | |||
@@ -3388,6 +3388,30 @@ int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | |||
3388 | } | 3388 | } |
3389 | 3389 | ||
3390 | /** | 3390 | /** |
3391 | * intel_vgpu_mask_mmio_write - write mask register | ||
3392 | * @vgpu: a vGPU | ||
3393 | * @offset: access offset | ||
3394 | * @p_data: write data buffer | ||
3395 | * @bytes: access data length | ||
3396 | * | ||
3397 | * Returns: | ||
3398 | * Zero on success, negative error code if failed. | ||
3399 | */ | ||
3400 | int intel_vgpu_mask_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
3401 | void *p_data, unsigned int bytes) | ||
3402 | { | ||
3403 | u32 mask, old_vreg; | ||
3404 | |||
3405 | old_vreg = vgpu_vreg(vgpu, offset); | ||
3406 | write_vreg(vgpu, offset, p_data, bytes); | ||
3407 | mask = vgpu_vreg(vgpu, offset) >> 16; | ||
3408 | vgpu_vreg(vgpu, offset) = (old_vreg & ~mask) | | ||
3409 | (vgpu_vreg(vgpu, offset) & mask); | ||
3410 | |||
3411 | return 0; | ||
3412 | } | ||
3413 | |||
3414 | /** | ||
3391 | * intel_gvt_in_force_nonpriv_whitelist - if a mmio is in whitelist to be | 3415 | * intel_gvt_in_force_nonpriv_whitelist - if a mmio is in whitelist to be |
3392 | * force-nopriv register | 3416 | * force-nopriv register |
3393 | * | 3417 | * |
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index e474188b46d2..1ffc69eba30e 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h | |||
@@ -99,4 +99,6 @@ bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt, | |||
99 | int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset, | 99 | int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset, |
100 | void *pdata, unsigned int bytes, bool is_read); | 100 | void *pdata, unsigned int bytes, bool is_read); |
101 | 101 | ||
102 | int intel_vgpu_mask_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
103 | void *p_data, unsigned int bytes); | ||
102 | #endif | 104 | #endif |
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 20be9a92600f..42e1e6bdcc2c 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c | |||
@@ -587,7 +587,9 @@ void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt) | |||
587 | 587 | ||
588 | for (mmio = gvt->engine_mmio_list.mmio; | 588 | for (mmio = gvt->engine_mmio_list.mmio; |
589 | i915_mmio_reg_valid(mmio->reg); mmio++) { | 589 | i915_mmio_reg_valid(mmio->reg); mmio++) { |
590 | if (mmio->in_context) | 590 | if (mmio->in_context) { |
591 | gvt->engine_mmio_list.ctx_mmio_count[mmio->ring_id]++; | 591 | gvt->engine_mmio_list.ctx_mmio_count[mmio->ring_id]++; |
592 | intel_gvt_mmio_set_in_ctx(gvt, mmio->reg.reg); | ||
593 | } | ||
592 | } | 594 | } |
593 | } | 595 | } |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 501d2d290e9c..70dce544984e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c | |||
@@ -55,6 +55,9 @@ nv04_display_create(struct drm_device *dev) | |||
55 | nouveau_display(dev)->init = nv04_display_init; | 55 | nouveau_display(dev)->init = nv04_display_init; |
56 | nouveau_display(dev)->fini = nv04_display_fini; | 56 | nouveau_display(dev)->fini = nv04_display_fini; |
57 | 57 | ||
58 | /* Pre-nv50 doesn't support atomic, so don't expose the ioctls */ | ||
59 | dev->driver->driver_features &= ~DRIVER_ATOMIC; | ||
60 | |||
58 | nouveau_hw_save_vga_fonts(dev, 1); | 61 | nouveau_hw_save_vga_fonts(dev, 1); |
59 | 62 | ||
60 | nv04_crtc_create(dev, 0); | 63 | nv04_crtc_create(dev, 0); |
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 0190377b02a6..8412119bd940 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c | |||
@@ -1610,8 +1610,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) | |||
1610 | *****************************************************************************/ | 1610 | *****************************************************************************/ |
1611 | 1611 | ||
1612 | static void | 1612 | static void |
1613 | nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock) | 1613 | nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock) |
1614 | { | 1614 | { |
1615 | struct nouveau_drm *drm = nouveau_drm(state->dev); | ||
1615 | struct nv50_disp *disp = nv50_disp(drm->dev); | 1616 | struct nv50_disp *disp = nv50_disp(drm->dev); |
1616 | struct nv50_core *core = disp->core; | 1617 | struct nv50_core *core = disp->core; |
1617 | struct nv50_mstm *mstm; | 1618 | struct nv50_mstm *mstm; |
@@ -1643,6 +1644,22 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock) | |||
1643 | } | 1644 | } |
1644 | 1645 | ||
1645 | static void | 1646 | static void |
1647 | nv50_disp_atomic_commit_wndw(struct drm_atomic_state *state, u32 *interlock) | ||
1648 | { | ||
1649 | struct drm_plane_state *new_plane_state; | ||
1650 | struct drm_plane *plane; | ||
1651 | int i; | ||
1652 | |||
1653 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | ||
1654 | struct nv50_wndw *wndw = nv50_wndw(plane); | ||
1655 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
1656 | if (wndw->func->update) | ||
1657 | wndw->func->update(wndw, interlock); | ||
1658 | } | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | static void | ||
1646 | nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | 1663 | nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) |
1647 | { | 1664 | { |
1648 | struct drm_device *dev = state->dev; | 1665 | struct drm_device *dev = state->dev; |
@@ -1709,7 +1726,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
1709 | help->disable(encoder); | 1726 | help->disable(encoder); |
1710 | interlock[NV50_DISP_INTERLOCK_CORE] |= 1; | 1727 | interlock[NV50_DISP_INTERLOCK_CORE] |= 1; |
1711 | if (outp->flush_disable) { | 1728 | if (outp->flush_disable) { |
1712 | nv50_disp_atomic_commit_core(drm, interlock); | 1729 | nv50_disp_atomic_commit_wndw(state, interlock); |
1730 | nv50_disp_atomic_commit_core(state, interlock); | ||
1713 | memset(interlock, 0x00, sizeof(interlock)); | 1731 | memset(interlock, 0x00, sizeof(interlock)); |
1714 | } | 1732 | } |
1715 | } | 1733 | } |
@@ -1718,15 +1736,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
1718 | /* Flush disable. */ | 1736 | /* Flush disable. */ |
1719 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { | 1737 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { |
1720 | if (atom->flush_disable) { | 1738 | if (atom->flush_disable) { |
1721 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | 1739 | nv50_disp_atomic_commit_wndw(state, interlock); |
1722 | struct nv50_wndw *wndw = nv50_wndw(plane); | 1740 | nv50_disp_atomic_commit_core(state, interlock); |
1723 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
1724 | if (wndw->func->update) | ||
1725 | wndw->func->update(wndw, interlock); | ||
1726 | } | ||
1727 | } | ||
1728 | |||
1729 | nv50_disp_atomic_commit_core(drm, interlock); | ||
1730 | memset(interlock, 0x00, sizeof(interlock)); | 1741 | memset(interlock, 0x00, sizeof(interlock)); |
1731 | } | 1742 | } |
1732 | } | 1743 | } |
@@ -1787,18 +1798,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
1787 | } | 1798 | } |
1788 | 1799 | ||
1789 | /* Flush update. */ | 1800 | /* Flush update. */ |
1790 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | 1801 | nv50_disp_atomic_commit_wndw(state, interlock); |
1791 | struct nv50_wndw *wndw = nv50_wndw(plane); | ||
1792 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
1793 | if (wndw->func->update) | ||
1794 | wndw->func->update(wndw, interlock); | ||
1795 | } | ||
1796 | } | ||
1797 | 1802 | ||
1798 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { | 1803 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { |
1799 | if (interlock[NV50_DISP_INTERLOCK_BASE] || | 1804 | if (interlock[NV50_DISP_INTERLOCK_BASE] || |
1805 | interlock[NV50_DISP_INTERLOCK_OVLY] || | ||
1806 | interlock[NV50_DISP_INTERLOCK_WNDW] || | ||
1800 | !atom->state.legacy_cursor_update) | 1807 | !atom->state.legacy_cursor_update) |
1801 | nv50_disp_atomic_commit_core(drm, interlock); | 1808 | nv50_disp_atomic_commit_core(state, interlock); |
1802 | else | 1809 | else |
1803 | disp->core->func->update(disp->core, interlock, false); | 1810 | disp->core->func->update(disp->core, interlock, false); |
1804 | } | 1811 | } |
@@ -1896,7 +1903,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, | |||
1896 | nv50_disp_atomic_commit_tail(state); | 1903 | nv50_disp_atomic_commit_tail(state); |
1897 | 1904 | ||
1898 | drm_for_each_crtc(crtc, dev) { | 1905 | drm_for_each_crtc(crtc, dev) { |
1899 | if (crtc->state->enable) { | 1906 | if (crtc->state->active) { |
1900 | if (!drm->have_disp_power_ref) { | 1907 | if (!drm->have_disp_power_ref) { |
1901 | drm->have_disp_power_ref = true; | 1908 | drm->have_disp_power_ref = true; |
1902 | return 0; | 1909 | return 0; |
@@ -2144,10 +2151,6 @@ nv50_display_destroy(struct drm_device *dev) | |||
2144 | kfree(disp); | 2151 | kfree(disp); |
2145 | } | 2152 | } |
2146 | 2153 | ||
2147 | MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)"); | ||
2148 | static int nouveau_atomic = 0; | ||
2149 | module_param_named(atomic, nouveau_atomic, int, 0400); | ||
2150 | |||
2151 | int | 2154 | int |
2152 | nv50_display_create(struct drm_device *dev) | 2155 | nv50_display_create(struct drm_device *dev) |
2153 | { | 2156 | { |
@@ -2172,8 +2175,6 @@ nv50_display_create(struct drm_device *dev) | |||
2172 | disp->disp = &nouveau_display(dev)->disp; | 2175 | disp->disp = &nouveau_display(dev)->disp; |
2173 | dev->mode_config.funcs = &nv50_disp_func; | 2176 | dev->mode_config.funcs = &nv50_disp_func; |
2174 | dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP; | 2177 | dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP; |
2175 | if (nouveau_atomic) | ||
2176 | dev->driver->driver_features |= DRIVER_ATOMIC; | ||
2177 | 2178 | ||
2178 | /* small shared memory area we use for notifiers and semaphores */ | 2179 | /* small shared memory area we use for notifiers and semaphores */ |
2179 | ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, | 2180 | ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index debbbf0fd4bd..408b955e5c39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
@@ -267,6 +267,7 @@ nouveau_backlight_init(struct drm_device *dev) | |||
267 | struct nouveau_drm *drm = nouveau_drm(dev); | 267 | struct nouveau_drm *drm = nouveau_drm(dev); |
268 | struct nvif_device *device = &drm->client.device; | 268 | struct nvif_device *device = &drm->client.device; |
269 | struct drm_connector *connector; | 269 | struct drm_connector *connector; |
270 | struct drm_connector_list_iter conn_iter; | ||
270 | 271 | ||
271 | INIT_LIST_HEAD(&drm->bl_connectors); | 272 | INIT_LIST_HEAD(&drm->bl_connectors); |
272 | 273 | ||
@@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev) | |||
275 | return 0; | 276 | return 0; |
276 | } | 277 | } |
277 | 278 | ||
278 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 279 | drm_connector_list_iter_begin(dev, &conn_iter); |
280 | drm_for_each_connector_iter(connector, &conn_iter) { | ||
279 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && | 281 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && |
280 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) | 282 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) |
281 | continue; | 283 | continue; |
@@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev) | |||
292 | break; | 294 | break; |
293 | } | 295 | } |
294 | } | 296 | } |
295 | 297 | drm_connector_list_iter_end(&conn_iter); | |
296 | 298 | ||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 22a15478d23d..51932c72334e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -1193,14 +1193,19 @@ nouveau_connector_create(struct drm_device *dev, int index) | |||
1193 | struct nouveau_display *disp = nouveau_display(dev); | 1193 | struct nouveau_display *disp = nouveau_display(dev); |
1194 | struct nouveau_connector *nv_connector = NULL; | 1194 | struct nouveau_connector *nv_connector = NULL; |
1195 | struct drm_connector *connector; | 1195 | struct drm_connector *connector; |
1196 | struct drm_connector_list_iter conn_iter; | ||
1196 | int type, ret = 0; | 1197 | int type, ret = 0; |
1197 | bool dummy; | 1198 | bool dummy; |
1198 | 1199 | ||
1199 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 1200 | drm_connector_list_iter_begin(dev, &conn_iter); |
1201 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
1200 | nv_connector = nouveau_connector(connector); | 1202 | nv_connector = nouveau_connector(connector); |
1201 | if (nv_connector->index == index) | 1203 | if (nv_connector->index == index) { |
1204 | drm_connector_list_iter_end(&conn_iter); | ||
1202 | return connector; | 1205 | return connector; |
1206 | } | ||
1203 | } | 1207 | } |
1208 | drm_connector_list_iter_end(&conn_iter); | ||
1204 | 1209 | ||
1205 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); | 1210 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); |
1206 | if (!nv_connector) | 1211 | if (!nv_connector) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index a4d1a059bd3d..dc7454e7f19a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <drm/drm_encoder.h> | 33 | #include <drm/drm_encoder.h> |
34 | #include <drm/drm_dp_helper.h> | 34 | #include <drm/drm_dp_helper.h> |
35 | #include "nouveau_crtc.h" | 35 | #include "nouveau_crtc.h" |
36 | #include "nouveau_encoder.h" | ||
36 | 37 | ||
37 | struct nvkm_i2c_port; | 38 | struct nvkm_i2c_port; |
38 | 39 | ||
@@ -60,19 +61,46 @@ static inline struct nouveau_connector *nouveau_connector( | |||
60 | return container_of(con, struct nouveau_connector, base); | 61 | return container_of(con, struct nouveau_connector, base); |
61 | } | 62 | } |
62 | 63 | ||
64 | static inline bool | ||
65 | nouveau_connector_is_mst(struct drm_connector *connector) | ||
66 | { | ||
67 | const struct nouveau_encoder *nv_encoder; | ||
68 | const struct drm_encoder *encoder; | ||
69 | |||
70 | if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) | ||
71 | return false; | ||
72 | |||
73 | nv_encoder = find_encoder(connector, DCB_OUTPUT_ANY); | ||
74 | if (!nv_encoder) | ||
75 | return false; | ||
76 | |||
77 | encoder = &nv_encoder->base.base; | ||
78 | return encoder->encoder_type == DRM_MODE_ENCODER_DPMST; | ||
79 | } | ||
80 | |||
81 | #define nouveau_for_each_non_mst_connector_iter(connector, iter) \ | ||
82 | drm_for_each_connector_iter(connector, iter) \ | ||
83 | for_each_if(!nouveau_connector_is_mst(connector)) | ||
84 | |||
63 | static inline struct nouveau_connector * | 85 | static inline struct nouveau_connector * |
64 | nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) | 86 | nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) |
65 | { | 87 | { |
66 | struct drm_device *dev = nv_crtc->base.dev; | 88 | struct drm_device *dev = nv_crtc->base.dev; |
67 | struct drm_connector *connector; | 89 | struct drm_connector *connector; |
90 | struct drm_connector_list_iter conn_iter; | ||
91 | struct nouveau_connector *nv_connector = NULL; | ||
68 | struct drm_crtc *crtc = to_drm_crtc(nv_crtc); | 92 | struct drm_crtc *crtc = to_drm_crtc(nv_crtc); |
69 | 93 | ||
70 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 94 | drm_connector_list_iter_begin(dev, &conn_iter); |
71 | if (connector->encoder && connector->encoder->crtc == crtc) | 95 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { |
72 | return nouveau_connector(connector); | 96 | if (connector->encoder && connector->encoder->crtc == crtc) { |
97 | nv_connector = nouveau_connector(connector); | ||
98 | break; | ||
99 | } | ||
73 | } | 100 | } |
101 | drm_connector_list_iter_end(&conn_iter); | ||
74 | 102 | ||
75 | return NULL; | 103 | return nv_connector; |
76 | } | 104 | } |
77 | 105 | ||
78 | struct drm_connector * | 106 | struct drm_connector * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index dfa236370726..139368b31916 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev) | |||
404 | struct nouveau_display *disp = nouveau_display(dev); | 404 | struct nouveau_display *disp = nouveau_display(dev); |
405 | struct nouveau_drm *drm = nouveau_drm(dev); | 405 | struct nouveau_drm *drm = nouveau_drm(dev); |
406 | struct drm_connector *connector; | 406 | struct drm_connector *connector; |
407 | struct drm_connector_list_iter conn_iter; | ||
407 | int ret; | 408 | int ret; |
408 | 409 | ||
409 | ret = disp->init(dev); | 410 | ret = disp->init(dev); |
@@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev) | |||
411 | return ret; | 412 | return ret; |
412 | 413 | ||
413 | /* enable hotplug interrupts */ | 414 | /* enable hotplug interrupts */ |
414 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 415 | drm_connector_list_iter_begin(dev, &conn_iter); |
416 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
415 | struct nouveau_connector *conn = nouveau_connector(connector); | 417 | struct nouveau_connector *conn = nouveau_connector(connector); |
416 | nvif_notify_get(&conn->hpd); | 418 | nvif_notify_get(&conn->hpd); |
417 | } | 419 | } |
420 | drm_connector_list_iter_end(&conn_iter); | ||
418 | 421 | ||
419 | /* enable flip completion events */ | 422 | /* enable flip completion events */ |
420 | nvif_notify_get(&drm->flip); | 423 | nvif_notify_get(&drm->flip); |
@@ -427,6 +430,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) | |||
427 | struct nouveau_display *disp = nouveau_display(dev); | 430 | struct nouveau_display *disp = nouveau_display(dev); |
428 | struct nouveau_drm *drm = nouveau_drm(dev); | 431 | struct nouveau_drm *drm = nouveau_drm(dev); |
429 | struct drm_connector *connector; | 432 | struct drm_connector *connector; |
433 | struct drm_connector_list_iter conn_iter; | ||
430 | 434 | ||
431 | if (!suspend) { | 435 | if (!suspend) { |
432 | if (drm_drv_uses_atomic_modeset(dev)) | 436 | if (drm_drv_uses_atomic_modeset(dev)) |
@@ -439,10 +443,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) | |||
439 | nvif_notify_put(&drm->flip); | 443 | nvif_notify_put(&drm->flip); |
440 | 444 | ||
441 | /* disable hotplug interrupts */ | 445 | /* disable hotplug interrupts */ |
442 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 446 | drm_connector_list_iter_begin(dev, &conn_iter); |
447 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
443 | struct nouveau_connector *conn = nouveau_connector(connector); | 448 | struct nouveau_connector *conn = nouveau_connector(connector); |
444 | nvif_notify_put(&conn->hpd); | 449 | nvif_notify_put(&conn->hpd); |
445 | } | 450 | } |
451 | drm_connector_list_iter_end(&conn_iter); | ||
446 | 452 | ||
447 | drm_kms_helper_poll_disable(dev); | 453 | drm_kms_helper_poll_disable(dev); |
448 | disp->fini(dev); | 454 | disp->fini(dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index c779ee3c665b..c7ec86d6c3c9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -81,6 +81,10 @@ MODULE_PARM_DESC(modeset, "enable driver (default: auto, " | |||
81 | int nouveau_modeset = -1; | 81 | int nouveau_modeset = -1; |
82 | module_param_named(modeset, nouveau_modeset, int, 0400); | 82 | module_param_named(modeset, nouveau_modeset, int, 0400); |
83 | 83 | ||
84 | MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)"); | ||
85 | static int nouveau_atomic = 0; | ||
86 | module_param_named(atomic, nouveau_atomic, int, 0400); | ||
87 | |||
84 | MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); | 88 | MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); |
85 | static int nouveau_runtime_pm = -1; | 89 | static int nouveau_runtime_pm = -1; |
86 | module_param_named(runpm, nouveau_runtime_pm, int, 0400); | 90 | module_param_named(runpm, nouveau_runtime_pm, int, 0400); |
@@ -509,6 +513,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, | |||
509 | 513 | ||
510 | pci_set_master(pdev); | 514 | pci_set_master(pdev); |
511 | 515 | ||
516 | if (nouveau_atomic) | ||
517 | driver_pci.driver_features |= DRIVER_ATOMIC; | ||
518 | |||
512 | ret = drm_get_pci_dev(pdev, pent, &driver_pci); | 519 | ret = drm_get_pci_dev(pdev, pent, &driver_pci); |
513 | if (ret) { | 520 | if (ret) { |
514 | nvkm_device_del(&device); | 521 | nvkm_device_del(&device); |
@@ -874,22 +881,11 @@ nouveau_pmops_runtime_resume(struct device *dev) | |||
874 | static int | 881 | static int |
875 | nouveau_pmops_runtime_idle(struct device *dev) | 882 | nouveau_pmops_runtime_idle(struct device *dev) |
876 | { | 883 | { |
877 | struct pci_dev *pdev = to_pci_dev(dev); | ||
878 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
879 | struct nouveau_drm *drm = nouveau_drm(drm_dev); | ||
880 | struct drm_crtc *crtc; | ||
881 | |||
882 | if (!nouveau_pmops_runtime()) { | 884 | if (!nouveau_pmops_runtime()) { |
883 | pm_runtime_forbid(dev); | 885 | pm_runtime_forbid(dev); |
884 | return -EBUSY; | 886 | return -EBUSY; |
885 | } | 887 | } |
886 | 888 | ||
887 | list_for_each_entry(crtc, &drm->dev->mode_config.crtc_list, head) { | ||
888 | if (crtc->enabled) { | ||
889 | DRM_DEBUG_DRIVER("failing to power off - crtc active\n"); | ||
890 | return -EBUSY; | ||
891 | } | ||
892 | } | ||
893 | pm_runtime_mark_last_busy(dev); | 889 | pm_runtime_mark_last_busy(dev); |
894 | pm_runtime_autosuspend(dev); | 890 | pm_runtime_autosuspend(dev); |
895 | /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ | 891 | /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index df73bec354e8..b56524d343c3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -616,7 +616,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
616 | struct nouveau_bo *nvbo; | 616 | struct nouveau_bo *nvbo; |
617 | uint32_t data; | 617 | uint32_t data; |
618 | 618 | ||
619 | if (unlikely(r->bo_index > req->nr_buffers)) { | 619 | if (unlikely(r->bo_index >= req->nr_buffers)) { |
620 | NV_PRINTK(err, cli, "reloc bo index invalid\n"); | 620 | NV_PRINTK(err, cli, "reloc bo index invalid\n"); |
621 | ret = -EINVAL; | 621 | ret = -EINVAL; |
622 | break; | 622 | break; |
@@ -626,7 +626,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
626 | if (b->presumed.valid) | 626 | if (b->presumed.valid) |
627 | continue; | 627 | continue; |
628 | 628 | ||
629 | if (unlikely(r->reloc_bo_index > req->nr_buffers)) { | 629 | if (unlikely(r->reloc_bo_index >= req->nr_buffers)) { |
630 | NV_PRINTK(err, cli, "reloc container bo index invalid\n"); | 630 | NV_PRINTK(err, cli, "reloc container bo index invalid\n"); |
631 | ret = -EINVAL; | 631 | ret = -EINVAL; |
632 | break; | 632 | break; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 73b5d46104bd..434d2fc5bb1c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | |||
@@ -140,6 +140,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev) | |||
140 | if (fb->func->init) | 140 | if (fb->func->init) |
141 | fb->func->init(fb); | 141 | fb->func->init(fb); |
142 | 142 | ||
143 | if (fb->func->init_remapper) | ||
144 | fb->func->init_remapper(fb); | ||
145 | |||
143 | if (fb->func->init_page) { | 146 | if (fb->func->init_page) { |
144 | ret = fb->func->init_page(fb); | 147 | ret = fb->func->init_page(fb); |
145 | if (WARN_ON(ret)) | 148 | if (WARN_ON(ret)) |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c index dffe1f5e1071..8205ce436b3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c | |||
@@ -37,6 +37,14 @@ gp100_fb_init_unkn(struct nvkm_fb *base) | |||
37 | } | 37 | } |
38 | 38 | ||
39 | void | 39 | void |
40 | gp100_fb_init_remapper(struct nvkm_fb *fb) | ||
41 | { | ||
42 | struct nvkm_device *device = fb->subdev.device; | ||
43 | /* Disable address remapper. */ | ||
44 | nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000); | ||
45 | } | ||
46 | |||
47 | void | ||
40 | gp100_fb_init(struct nvkm_fb *base) | 48 | gp100_fb_init(struct nvkm_fb *base) |
41 | { | 49 | { |
42 | struct gf100_fb *fb = gf100_fb(base); | 50 | struct gf100_fb *fb = gf100_fb(base); |
@@ -56,6 +64,7 @@ gp100_fb = { | |||
56 | .dtor = gf100_fb_dtor, | 64 | .dtor = gf100_fb_dtor, |
57 | .oneinit = gf100_fb_oneinit, | 65 | .oneinit = gf100_fb_oneinit, |
58 | .init = gp100_fb_init, | 66 | .init = gp100_fb_init, |
67 | .init_remapper = gp100_fb_init_remapper, | ||
59 | .init_page = gm200_fb_init_page, | 68 | .init_page = gm200_fb_init_page, |
60 | .init_unkn = gp100_fb_init_unkn, | 69 | .init_unkn = gp100_fb_init_unkn, |
61 | .ram_new = gp100_ram_new, | 70 | .ram_new = gp100_ram_new, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index b84b9861ef26..b4d74e815674 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | |||
@@ -31,6 +31,7 @@ gp102_fb = { | |||
31 | .dtor = gf100_fb_dtor, | 31 | .dtor = gf100_fb_dtor, |
32 | .oneinit = gf100_fb_oneinit, | 32 | .oneinit = gf100_fb_oneinit, |
33 | .init = gp100_fb_init, | 33 | .init = gp100_fb_init, |
34 | .init_remapper = gp100_fb_init_remapper, | ||
34 | .init_page = gm200_fb_init_page, | 35 | .init_page = gm200_fb_init_page, |
35 | .ram_new = gp100_ram_new, | 36 | .ram_new = gp100_ram_new, |
36 | }; | 37 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 2857f31466bf..1e4ad61c19e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | |||
@@ -11,6 +11,7 @@ struct nvkm_fb_func { | |||
11 | u32 (*tags)(struct nvkm_fb *); | 11 | u32 (*tags)(struct nvkm_fb *); |
12 | int (*oneinit)(struct nvkm_fb *); | 12 | int (*oneinit)(struct nvkm_fb *); |
13 | void (*init)(struct nvkm_fb *); | 13 | void (*init)(struct nvkm_fb *); |
14 | void (*init_remapper)(struct nvkm_fb *); | ||
14 | int (*init_page)(struct nvkm_fb *); | 15 | int (*init_page)(struct nvkm_fb *); |
15 | void (*init_unkn)(struct nvkm_fb *); | 16 | void (*init_unkn)(struct nvkm_fb *); |
16 | void (*intr)(struct nvkm_fb *); | 17 | void (*intr)(struct nvkm_fb *); |
@@ -69,5 +70,6 @@ int gf100_fb_init_page(struct nvkm_fb *); | |||
69 | 70 | ||
70 | int gm200_fb_init_page(struct nvkm_fb *); | 71 | int gm200_fb_init_page(struct nvkm_fb *); |
71 | 72 | ||
73 | void gp100_fb_init_remapper(struct nvkm_fb *); | ||
72 | void gp100_fb_init_unkn(struct nvkm_fb *); | 74 | void gp100_fb_init_unkn(struct nvkm_fb *); |
73 | #endif | 75 | #endif |
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index b04ea0f3da75..0eb38ac8e86e 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile | |||
@@ -32,7 +32,10 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-tcon.o | |||
32 | obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o | 32 | obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o |
33 | obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o | 33 | obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o |
34 | 34 | ||
35 | obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o | 35 | obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o |
36 | ifdef CONFIG_DRM_SUN4I_BACKEND | ||
37 | obj-$(CONFIG_DRM_SUN4I) += sun4i-frontend.o | ||
38 | endif | ||
36 | obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o | 39 | obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o |
37 | obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i-dsi.o | 40 | obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i-dsi.o |
38 | obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o | 41 | obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 776c1513e582..a2bd5876c633 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -398,7 +398,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, | |||
398 | * unaligned offset is malformed and cause commands stream | 398 | * unaligned offset is malformed and cause commands stream |
399 | * corruption on the buffer address relocation. | 399 | * corruption on the buffer address relocation. |
400 | */ | 400 | */ |
401 | if (offset & 3 || offset >= obj->gem.size) { | 401 | if (offset & 3 || offset > obj->gem.size) { |
402 | err = -EINVAL; | 402 | err = -EINVAL; |
403 | goto fail; | 403 | goto fail; |
404 | } | 404 | } |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 2ebdc6d5a76e..d5583190f3e4 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
@@ -137,7 +137,10 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
137 | 137 | ||
138 | if (cmd > (char *) urb->transfer_buffer) { | 138 | if (cmd > (char *) urb->transfer_buffer) { |
139 | /* Send partial buffer remaining before exiting */ | 139 | /* Send partial buffer remaining before exiting */ |
140 | int len = cmd - (char *) urb->transfer_buffer; | 140 | int len; |
141 | if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length) | ||
142 | *cmd++ = 0xAF; | ||
143 | len = cmd - (char *) urb->transfer_buffer; | ||
141 | ret = udl_submit_urb(dev, urb, len); | 144 | ret = udl_submit_urb(dev, urb, len); |
142 | bytes_sent += len; | 145 | bytes_sent += len; |
143 | } else | 146 | } else |
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 0c87b1ac6b68..b992644c17e6 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c | |||
@@ -153,11 +153,11 @@ static void udl_compress_hline16( | |||
153 | raw_pixels_count_byte = cmd++; /* we'll know this later */ | 153 | raw_pixels_count_byte = cmd++; /* we'll know this later */ |
154 | raw_pixel_start = pixel; | 154 | raw_pixel_start = pixel; |
155 | 155 | ||
156 | cmd_pixel_end = pixel + (min(MAX_CMD_PIXELS + 1, | 156 | cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL, |
157 | min((int)(pixel_end - pixel) / bpp, | 157 | (unsigned long)(pixel_end - pixel) / bpp, |
158 | (int)(cmd_buffer_end - cmd) / 2))) * bpp; | 158 | (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) * bpp; |
159 | 159 | ||
160 | prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); | 160 | prefetch_range((void *) pixel, cmd_pixel_end - pixel); |
161 | pixel_val16 = get_pixel_val16(pixel, bpp); | 161 | pixel_val16 = get_pixel_val16(pixel, bpp); |
162 | 162 | ||
163 | while (pixel < cmd_pixel_end) { | 163 | while (pixel < cmd_pixel_end) { |
@@ -193,6 +193,9 @@ static void udl_compress_hline16( | |||
193 | if (pixel > raw_pixel_start) { | 193 | if (pixel > raw_pixel_start) { |
194 | /* finalize last RAW span */ | 194 | /* finalize last RAW span */ |
195 | *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; | 195 | *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; |
196 | } else { | ||
197 | /* undo unused byte */ | ||
198 | cmd--; | ||
196 | } | 199 | } |
197 | 200 | ||
198 | *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; | 201 | *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; |
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index f1d5f76e9c33..d88073e7d22d 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c | |||
@@ -218,6 +218,9 @@ static int host1x_probe(struct platform_device *pdev) | |||
218 | return err; | 218 | return err; |
219 | } | 219 | } |
220 | 220 | ||
221 | if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) | ||
222 | goto skip_iommu; | ||
223 | |||
221 | host->group = iommu_group_get(&pdev->dev); | 224 | host->group = iommu_group_get(&pdev->dev); |
222 | if (host->group) { | 225 | if (host->group) { |
223 | struct iommu_domain_geometry *geometry; | 226 | struct iommu_domain_geometry *geometry; |
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index e2f4a4d93d20..527a1cddb14f 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c | |||
@@ -569,7 +569,8 @@ void host1x_job_unpin(struct host1x_job *job) | |||
569 | for (i = 0; i < job->num_unpins; i++) { | 569 | for (i = 0; i < job->num_unpins; i++) { |
570 | struct host1x_job_unpin_data *unpin = &job->unpins[i]; | 570 | struct host1x_job_unpin_data *unpin = &job->unpins[i]; |
571 | 571 | ||
572 | if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { | 572 | if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && |
573 | unpin->size && host->domain) { | ||
573 | iommu_unmap(host->domain, job->addr_phys[i], | 574 | iommu_unmap(host->domain, job->addr_phys[i], |
574 | unpin->size); | 575 | unpin->size); |
575 | free_iova(&host->iova, | 576 | free_iova(&host->iova, |