diff options
Diffstat (limited to 'drivers/gpu')
69 files changed, 551 insertions, 438 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 3e5d550c5bd0..0148dd32e561 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -788,7 +788,6 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, - .set_busid = drm_pci_set_busid, .unload = amdgpu_driver_unload_kms, .get_vblank_counter = amdgpu_get_vblank_counter_kms, .enable_vblank = amdgpu_enable_vblank_kms, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 62da6c5c6095..2480273c1dca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -263,7 +263,6 @@ void amdgpu_irq_fini(struct amdgpu_device *adev) { unsigned i, j; - drm_vblank_cleanup(adev->ddev); if (adev->irq.installed) { drm_irq_uninstall(adev->ddev); adev->irq.installed = false; diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index ad9a95916f1f..611af74a31c0 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -64,6 +64,19 @@ static const struct drm_crtc_funcs arc_pgu_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; +static enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); + long rate, clk_rate = mode->clock * 1000; + + rate = clk_round_rate(arcpgu->clk, clk_rate); + if (rate != clk_rate) + return MODE_NOCLOCK; + + return MODE_OK; +} + static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); @@ -129,20 +142,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc) ~ARCPGU_CTRL_ENABLE_MASK); } -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); - struct drm_display_mode *mode = &state->adjusted_mode; - long rate, clk_rate = mode->clock * 1000; - - rate = clk_round_rate(arcpgu->clk, clk_rate); - if (rate != clk_rate) - return -EINVAL; - - return 0; -} - static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -158,6 +157,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { + .mode_valid = arc_pgu_crtc_mode_valid, .mode_set = drm_helper_crtc_mode_set, .mode_set_base = drm_helper_crtc_mode_set_base, .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, @@ -165,7 +165,6 @@ static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { .disable = arc_pgu_crtc_disable, .prepare = arc_pgu_crtc_disable, .commit = arc_pgu_crtc_enable, - .atomic_check = arc_pgu_crtc_atomic_check, .atomic_begin = arc_pgu_crtc_atomic_begin, }; diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 4fe19fde84f9..94b76bdd7553 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1364,7 +1364,7 @@ static int armada_lcd_remove(struct platform_device *pdev) return 0; } -static struct of_device_id armada_lcd_of_match[] = { +static const struct of_device_id armada_lcd_of_match[] = { { .compatible = "marvell,dove-lcd", .data = &armada510_ops, diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index fd7c9eec92e4..3022b39c00f3 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -197,7 +197,6 @@ static struct drm_driver driver = { .load = ast_driver_load, .unload = ast_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &ast_fops, .name = DRIVER_NAME, @@ -221,11 +220,11 @@ static int __init ast_init(void) if (ast_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &ast_pci_driver); + return pci_register_driver(&ast_pci_driver); } static void __exit ast_exit(void) { - drm_pci_exit(&driver, &ast_pci_driver); + pci_unregister_driver(&ast_pci_driver); } module_init(ast_init); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 53489859997b..f6b8c5908a20 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -429,6 +429,8 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, .enable_vblank = atmel_hlcdc_crtc_enable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank, + .set_property = drm_atomic_helper_crtc_set_property, + .gamma_set = drm_atomic_helper_legacy_gamma_set, }; int atmel_hlcdc_crtc_create(struct drm_device *dev) @@ -484,6 +486,10 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); drm_crtc_vblank_reset(&crtc->base); + drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); + drm_crtc_enable_color_mgmt(&crtc->base, 0, false, + ATMEL_HLCDC_CLUT_SIZE); + dc->crtc = &crtc->base; return 0; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 30dbffdb45a3..516d9547d331 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = { .default_color = 3, .general_config = 4, }, + .clut_offset = 0x400, }, }; @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x400, }, { .name = "overlay1", @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x800, }, { .name = "high-end-overlay", @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .scaler_config = 13, .csc = 14, }, + .clut_offset = 0x1000, }, { .name = "cursor", @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0x1400, }, }; @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, { .name = "cursor", @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { .general_config = 9, .scaler_config = 13, }, + .clut_offset = 0x1600, }, }; @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .disc_pos = 5, .disc_size = 6, }, + .clut_offset = 0x600, }, { .name = "overlay1", @@ -293,6 +304,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xa00, }, { .name = "overlay2", @@ -311,6 +323,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { .chroma_key_mask = 8, .general_config = 9, }, + .clut_offset = 0xe00, }, { .name = "high-end-overlay", @@ -336,6 +349,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { }, .csc = 14, }, + .clut_offset = 0x1200, }, }; @@ -451,8 +465,7 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev) { struct atmel_hlcdc_dc *dc = dev->dev_private; - if (dc->fbdev) - drm_fbdev_cma_hotplug_event(dc->fbdev); + drm_fbdev_cma_hotplug_event(dc->fbdev); } struct atmel_hlcdc_dc_commit { diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index b0596a84c1b8..4237b0446721 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -88,6 +88,11 @@ #define ATMEL_HLCDC_YUV422SWP BIT(17) #define ATMEL_HLCDC_DSCALEOPT BIT(20) +#define ATMEL_HLCDC_C1_MODE ATMEL_HLCDC_CLUT_MODE(0) +#define ATMEL_HLCDC_C2_MODE ATMEL_HLCDC_CLUT_MODE(1) +#define ATMEL_HLCDC_C4_MODE ATMEL_HLCDC_CLUT_MODE(2) +#define ATMEL_HLCDC_C8_MODE ATMEL_HLCDC_CLUT_MODE(3) + #define ATMEL_HLCDC_XRGB4444_MODE ATMEL_HLCDC_RGB_MODE(0) #define ATMEL_HLCDC_ARGB4444_MODE ATMEL_HLCDC_RGB_MODE(1) #define ATMEL_HLCDC_RGBA4444_MODE ATMEL_HLCDC_RGB_MODE(2) @@ -142,6 +147,8 @@ #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE BIT(2) #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN BIT(3) +#define ATMEL_HLCDC_CLUT_SIZE 256 + #define ATMEL_HLCDC_MAX_LAYERS 6 /** @@ -259,6 +266,7 @@ struct atmel_hlcdc_layer_desc { int id; int regs_offset; int cfgs_offset; + int clut_offset; struct atmel_hlcdc_formats *formats; struct atmel_hlcdc_layer_cfg_layout layout; int max_width; @@ -414,6 +422,14 @@ static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer, (cfgid * sizeof(u32))); } +static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer, + unsigned int c, u32 val) +{ + regmap_write(layer->regmap, + layer->desc->clut_offset + c * sizeof(u32), + val); +} + static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer, const struct atmel_hlcdc_layer_desc *desc, struct regmap *regmap) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 1124200bb280..b5bd9b005225 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -83,6 +83,7 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s) #define SUBPIXEL_MASK 0xffff static uint32_t rgb_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_XRGB4444, DRM_FORMAT_ARGB4444, DRM_FORMAT_RGBA4444, @@ -100,6 +101,7 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = { }; static uint32_t rgb_and_yuv_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_XRGB4444, DRM_FORMAT_ARGB4444, DRM_FORMAT_RGBA4444, @@ -128,6 +130,9 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = { static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode) { switch (format) { + case DRM_FORMAT_C8: + *mode = ATMEL_HLCDC_C8_MODE; + break; case DRM_FORMAT_XRGB4444: *mode = ATMEL_HLCDC_XRGB4444_MODE; break; @@ -424,6 +429,29 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg); } +static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane) +{ + struct drm_crtc *crtc = plane->base.crtc; + struct drm_color_lut *lut; + int idx; + + if (!crtc || !crtc->state) + return; + + if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut) + return; + + lut = (struct drm_color_lut *)crtc->state->gamma_lut->data; + + for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) { + u32 val = ((lut->red << 8) & 0xff0000) | + (lut->green & 0xff00) | + (lut->blue >> 8); + + atmel_hlcdc_layer_write_clut(&plane->layer, idx, val); + } +} + static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { @@ -768,6 +796,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, atmel_hlcdc_plane_update_pos_and_size(plane, state); atmel_hlcdc_plane_update_general_settings(plane, state); atmel_hlcdc_plane_update_format(plane, state); + atmel_hlcdc_plane_update_clut(plane); atmel_hlcdc_plane_update_buffers(plane, state); atmel_hlcdc_plane_update_disc_area(plane, state); diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index aa342515ddf4..a1d28845da5f 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -84,7 +84,6 @@ static struct drm_driver bochs_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET, .load = bochs_load, .unload = bochs_unload, - .set_busid = drm_pci_set_busid, .fops = &bochs_fops, .name = "bochs-drm", .desc = "bochs dispi vga interface (qemu stdvga)", @@ -224,12 +223,12 @@ static int __init bochs_init(void) if (bochs_modeset == 0) return -EINVAL; - return drm_pci_init(&bochs_driver, &bochs_pci_driver); + return pci_register_driver(&bochs_pci_driver); } static void __exit bochs_exit(void) { - drm_pci_exit(&bochs_driver, &bochs_pci_driver); + pci_unregister_driver(&bochs_pci_driver); } module_init(bochs_init); diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index d893ea21a359..910c300f5c37 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -132,7 +132,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM, .load = cirrus_driver_load, .unload = cirrus_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &cirrus_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, @@ -166,12 +165,12 @@ static int __init cirrus_init(void) if (cirrus_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &cirrus_pci_driver); + return pci_register_driver(&cirrus_pci_driver); } static void __exit cirrus_exit(void) { - drm_pci_exit(&driver, &cirrus_pci_driver); + pci_unregister_driver(&cirrus_pci_driver); } module_init(cirrus_init); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 86d3093c6c9b..2f269e4267da 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1191,9 +1191,13 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); * * Helper to, after atomic commit, wait for vblanks on all effected * crtcs (ie. before cleaning up old framebuffers using - * drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the + * drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the * framebuffers have actually changed to optimize for the legacy cursor and * plane update use-case. + * + * Drivers using the nonblocking commit tracking support initialized by calling + * drm_atomic_helper_setup_commit() should look at + * drm_atomic_helper_wait_for_flip_done() as an alternative. */ void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, @@ -1241,6 +1245,43 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); /** + * drm_atomic_helper_wait_for_flip_done - wait for all page flips to be done + * @dev: DRM device + * @old_state: atomic state object with old state structures + * + * Helper to, after atomic commit, wait for page flips on all effected + * crtcs (ie. before cleaning up old framebuffers using + * drm_atomic_helper_cleanup_planes()). Compared to + * drm_atomic_helper_wait_for_vblanks() this waits for the completion of on all + * CRTCs, assuming that cursors-only updates are signalling their completion + * immediately (or using a different path). + * + * This requires that drivers use the nonblocking commit tracking support + * initialized using drm_atomic_helper_setup_commit(). + */ +void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, + struct drm_atomic_state *old_state) +{ + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + int i; + + for_each_crtc_in_state(old_state, crtc, crtc_state, i) { + struct drm_crtc_commit *commit = old_state->crtcs[i].commit; + int ret; + + if (!commit) + continue; + + ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ); + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", + crtc->base.id, crtc->name); + } +} +EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); + +/** * drm_atomic_helper_commit_tail - commit atomic update to hardware * @old_state: atomic state object with old state structures * @@ -1680,9 +1721,7 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) /* backend must have consumed any event by now */ WARN_ON(new_crtc_state->event); - spin_lock(&crtc->commit_lock); complete_all(&commit->hw_done); - spin_unlock(&crtc->commit_lock); } } EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); @@ -1711,7 +1750,6 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) if (WARN_ON(!commit)) continue; - spin_lock(&crtc->commit_lock); complete_all(&commit->cleanup_done); WARN_ON(!try_wait_for_completion(&commit->hw_done)); @@ -1721,8 +1759,6 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) if (try_wait_for_completion(&commit->flip_done)) goto del_commit; - spin_unlock(&crtc->commit_lock); - /* We must wait for the vblank event to signal our completion * before releasing our reference, since the vblank work does * not hold a reference of its own. */ @@ -1732,8 +1768,8 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", crtc->base.id, crtc->name); - spin_lock(&crtc->commit_lock); del_commit: + spin_lock(&crtc->commit_lock); list_del(&commit->commit_entry); spin_unlock(&crtc->commit_lock); } diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 3eda500fc005..fe0982708e95 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -128,6 +128,9 @@ EXPORT_SYMBOL(drm_color_lut_extract); * optional. The gamma and degamma properties are only attached if * their size is not 0 and ctm_property is only attached if has_ctm is * true. + * + * Drivers should use drm_atomic_helper_legacy_gamma_set() to implement the + * legacy &drm_crtc_funcs.gamma_set callback. */ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 53f9bdf470d7..ade319d10e70 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -640,7 +640,7 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); * Calls drm_fb_helper_set_suspend, which is a wrapper around * fb_set_suspend implemented by fbdev core. */ -void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state) +void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, bool state) { if (fbdev_cma) drm_fb_helper_set_suspend(&fbdev_cma->fb_helper, state); @@ -657,7 +657,7 @@ EXPORT_SYMBOL(drm_fbdev_cma_set_suspend); * fb_set_suspend implemented by fbdev core. */ void drm_fbdev_cma_set_suspend_unlocked(struct drm_fbdev_cma *fbdev_cma, - int state) + bool state) { if (fbdev_cma) drm_fb_helper_set_suspend_unlocked(&fbdev_cma->fb_helper, diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 84f3a242cc39..59b75a974357 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -75,7 +75,7 @@ DEFINE_MUTEX(drm_global_mutex); * for drivers which use the CMA GEM helpers it's drm_gem_cma_mmap(). * * No other file operations are supported by the DRM userspace API. Overall the - * following is an example #file_operations structure:: + * following is an example &file_operations structure:: * * static const example_drm_fops = { * .owner = THIS_MODULE, @@ -92,6 +92,11 @@ DEFINE_MUTEX(drm_global_mutex); * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this * simpler. + * + * The driver's &file_operations must be stored in &drm_driver.fops. + * + * For driver-private IOCTL handling see the more detailed discussion in + * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`. */ static int drm_open_helper(struct file *filp, struct drm_minor *minor); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 5cecc974d2f9..f89371e920e6 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -32,6 +32,7 @@ void drm_lastclose(struct drm_device *dev); int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv); void drm_pci_agp_destroy(struct drm_device *dev); +int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); /* drm_prime.c */ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, @@ -58,12 +59,16 @@ extern unsigned int drm_timestamp_monotonic; void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); /* IOCTLS */ -int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *filp); +int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/* drm_irq.c */ + +/* IOCTLS */ int drm_legacy_irq_control(struct drm_device *dev, void *data, struct drm_file *file_priv); -int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); /* drm_auth.c */ int drm_getmagic(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f1e568176da9..f7f150e4a0c0 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -143,8 +143,8 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) if (master->unique != NULL) drm_unset_busid(dev, master); - if (dev->driver->set_busid) { - ret = dev->driver->set_busid(dev, master); + if (dev->dev && dev_is_pci(dev->dev)) { + ret = drm_pci_set_busid(dev, master); if (ret) { drm_unset_busid(dev, master); return ret; @@ -603,9 +603,9 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -695,7 +695,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { * * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire - * up the handlers and set the access rights: + * up the handlers and set the access rights:: * * static const struct drm_ioctl_desc my_driver_ioctls[] = { * DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation, @@ -704,6 +704,9 @@ static const struct drm_ioctl_desc drm_ioctls[] = { * * And then assign this to the &drm_driver.ioctls field in your driver * structure. + * + * See the separate chapter on :ref:`file operations<drm_driver_fops>` for how + * the driver-specific IOCTLs are wired up. */ /** diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 1eb4fc3eee20..1235c9877d6f 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -149,7 +149,6 @@ int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) master->unique_len = strlen(master->unique); return 0; } -EXPORT_SYMBOL(drm_pci_set_busid); static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) { @@ -281,20 +280,15 @@ err_free: EXPORT_SYMBOL(drm_get_pci_dev); /** - * drm_pci_init - Register matching PCI devices with the DRM subsystem + * drm_legacy_pci_init - shadow-attach a legacy DRM PCI driver * @driver: DRM device driver * @pdriver: PCI device driver * - * Initializes a drm_device structures, registering the stubs and initializing - * the AGP device. - * - * NOTE: This function is deprecated. Modern modesetting drm drivers should use - * pci_register_driver() directly, this function only provides shadow-binding - * support for old legacy drivers on top of that core pci function. + * This is only used by legacy dri1 drivers and deprecated. * * Return: 0 on success or a negative error code on failure. */ -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) +int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) { struct pci_dev *pdev = NULL; const struct pci_device_id *pid; @@ -302,8 +296,8 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) DRM_DEBUG("\n"); - if (!(driver->driver_features & DRIVER_LEGACY)) - return pci_register_driver(pdriver); + if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY))) + return -EINVAL; /* If not using KMS, fall back to stealth mode manual scanning. */ INIT_LIST_HEAD(&driver->legacy_dev_list); @@ -330,6 +324,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) } return 0; } +EXPORT_SYMBOL(drm_legacy_pci_init); int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) { @@ -391,11 +386,6 @@ EXPORT_SYMBOL(drm_pcie_get_max_link_width); #else -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) -{ - return -1; -} - void drm_pci_agp_destroy(struct drm_device *dev) {} int drm_irq_by_busid(struct drm_device *dev, void *data, @@ -405,27 +395,21 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, } #endif -EXPORT_SYMBOL(drm_pci_init); - /** - * drm_pci_exit - Unregister matching PCI devices from the DRM subsystem + * drm_legacy_pci_exit - unregister shadow-attach legacy DRM driver * @driver: DRM device driver * @pdriver: PCI device driver * - * Unregisters one or more devices matched by a PCI driver from the DRM - * subsystem. - * - * NOTE: This function is deprecated. Modern modesetting drm drivers should use - * pci_unregister_driver() directly, this function only provides shadow-binding - * support for old legacy drivers on top of that core pci function. + * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). This + * is deprecated and only used by dri1 drivers. */ -void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) +void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) { struct drm_device *dev, *tmp; DRM_DEBUG("\n"); if (!(driver->driver_features & DRIVER_LEGACY)) { - pci_unregister_driver(pdriver); + WARN_ON(1); } else { list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list, legacy_dev_list) { @@ -435,4 +419,4 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) } DRM_INFO("Module unloaded\n"); } -EXPORT_SYMBOL(drm_pci_exit); +EXPORT_SYMBOL(drm_legacy_pci_exit); diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 463e4d81fb0d..7e3f59182571 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -31,6 +31,41 @@ #include "drm_trace.h" #include "drm_internal.h" +/** + * DOC: vblank handling + * + * Vertical blanking plays a major role in graphics rendering. To achieve + * tear-free display, users must synchronize page flips and/or rendering to + * vertical blanking. The DRM API offers ioctls to perform page flips + * synchronized to vertical blanking and wait for vertical blanking. + * + * The DRM core handles most of the vertical blanking management logic, which + * involves filtering out spurious interrupts, keeping race-free blanking + * counters, coping with counter wrap-around and resets and keeping use counts. + * It relies on the driver to generate vertical blanking interrupts and + * optionally provide a hardware vertical blanking counter. + * + * Drivers must initialize the vertical blanking handling core with a call to + * drm_vblank_init(). Minimally, a driver needs to implement + * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call + * drm_crtc_handle_vblank() in it's vblank interrupt handler for working vblank + * support. + * + * Vertical blanking interrupts can be enabled by the DRM core or by drivers + * themselves (for instance to handle page flipping operations). The DRM core + * maintains a vertical blanking use count to ensure that the interrupts are not + * disabled while a user still needs them. To increment the use count, drivers + * call drm_crtc_vblank_get() and release the vblank reference again with + * drm_crtc_vblank_put(). In between these two calls vblank interrupts are + * guaranteed to be enabled. + * + * On many hardware disabling the vblank interrupt cannot be done in a race-free + * manner, see &drm_driver.vblank_disable_immediate and + * &drm_driver.max_vblank_count. In that case the vblank core only disables the + * vblanks after a timer has expired, which can be configured through the + * ``vblankoffdelay`` module parameter. + */ + /* Retry timestamp calculation up to 3 times to satisfy * drm_timestamp_precision before giving up. */ @@ -259,16 +294,17 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) } /** - * drm_accurate_vblank_count - retrieve the master vblank counter + * drm_crtc_accurate_vblank_count - retrieve the master vblank counter * @crtc: which counter to retrieve * - * This function is similar to @drm_crtc_vblank_count but this - * function interpolates to handle a race with vblank irq's. + * This function is similar to drm_crtc_vblank_count() but this function + * interpolates to handle a race with vblank interrupts using the high precision + * timestamping support. * - * This is mostly useful for hardware that can obtain the scanout - * position, but doesn't have a frame counter. + * This is mostly useful for hardware that can obtain the scanout position, but + * doesn't have a hardware frame counter. */ -u32 drm_accurate_vblank_count(struct drm_crtc *crtc) +u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); @@ -287,7 +323,7 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc) return vblank; } -EXPORT_SYMBOL(drm_accurate_vblank_count); +EXPORT_SYMBOL(drm_crtc_accurate_vblank_count); static void __disable_vblank(struct drm_device *dev, unsigned int pipe) { @@ -362,10 +398,14 @@ static void vblank_disable_fn(unsigned long arg) * drm_vblank_cleanup - cleanup vblank support * @dev: DRM device * - * This function cleans up any resources allocated in drm_vblank_init. + * This function cleans up any resources allocated in drm_vblank_init(). It is + * called by the DRM core when @dev is finalized. + * + * Drivers can call drm_vblank_cleanup() if they need to quiescent the vblank + * interrupt in their unload code. But in general this should be handled by + * disabling all active &drm_crtc through e.g. drm_atomic_helper_shutdown, which + * should end up calling drm_crtc_vblank_off(). * - * Drivers which don't use drm_irq_install() need to set &drm_device.irq_enabled - * themselves, to signal to the DRM core that vblank interrupts are enabled. */ void drm_vblank_cleanup(struct drm_device *dev) { @@ -396,6 +436,9 @@ EXPORT_SYMBOL(drm_vblank_cleanup); * @num_crtcs: number of CRTCs supported by @dev * * This function initializes vblank support for @num_crtcs display pipelines. + * Drivers do not need to call drm_vblank_cleanup(), cleanup is already handled + * by the DRM core, or through calling drm_dev_fini() for drivers with a + * &drm_driver.release callback. * * Returns: * Zero on success or a negative error code on failure. @@ -468,11 +511,11 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue); * @crtc: drm_crtc whose timestamp constants should be updated. * @mode: display mode containing the scanout timings * - * Calculate and store various constants which are later - * needed by vblank and swap-completion timestamping, e.g, - * by drm_calc_vbltimestamp_from_scanoutpos(). They are - * derived from CRTC's true scanout timing, so they take - * things like panel scaling or other adjustments into account. + * Calculate and store various constants which are later needed by vblank and + * swap-completion timestamping, e.g, by + * drm_calc_vbltimestamp_from_scanoutpos(). They are derived from CRTC's true + * scanout timing, so they take things like panel scaling or other adjustments + * into account. */ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) @@ -535,25 +578,14 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * if flag is set. * * Implements calculation of exact vblank timestamps from given drm_display_mode - * timings and current video scanout position of a CRTC. This can be called from - * within get_vblank_timestamp() implementation of a kms driver to implement the - * actual timestamping. - * - * Should return timestamps conforming to the OML_sync_control OpenML - * extension specification. The timestamp corresponds to the end of - * the vblank interval, aka start of scanout of topmost-leftmost display - * pixel in the following video frame. + * timings and current video scanout position of a CRTC. This can be directly + * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver + * if &drm_driver.get_scanout_position is implemented. * - * Requires support for optional dev->driver->get_scanout_position() - * in kms driver, plus a bit of setup code to provide a drm_display_mode - * that corresponds to the true scanout timing. - * - * The current implementation only handles standard video modes. It - * returns as no operation if a doublescan or interlaced video mode is - * active. Higher level code is expected to handle this. - * - * This function can be used to implement the &drm_driver.get_vblank_timestamp - * directly, if the driver implements the &drm_driver.get_scanout_position hook. + * The current implementation only handles standard video modes. For double scan + * and interlaced modes the driver is supposed to adjust the hardware mode + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to + * match the scanout position reported. * * Note that atomic drivers must call drm_calc_timestamping_constants() before * enabling a CRTC. The atomic helpers already take care of that in @@ -738,7 +770,9 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, * * Fetches the "cooked" vblank count value that represents the number of * vblank events since the system was booted, including lost events due to - * modesetting activity. + * modesetting activity. Note that this timer isn't correct against a racing + * vblank interrupt (since it only reports the software vblank counter), see + * drm_crtc_accurate_vblank_count() for such use-cases. * * Returns: * The software vblank counter. @@ -749,20 +783,6 @@ u32 drm_crtc_vblank_count(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_count); -/** - * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the - * system timestamp corresponding to that vblank counter value. - * @dev: DRM device - * @pipe: index of CRTC whose counter to retrieve - * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. - * - * Fetches the "cooked" vblank count value that represents the number of - * vblank events since the system was booted, including lost events due to - * modesetting activity. Returns corresponding system timestamp of the time - * of the vblank interval that corresponds to the current vblank counter value. - * - * This is the legacy version of drm_crtc_vblank_count_and_time(). - */ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime) { @@ -852,8 +872,8 @@ static void send_vblank_event(struct drm_device *dev, * handler by calling drm_crtc_send_vblank_event() and make sure that there's no * possible race with the hardware committing the atomic update. * - * Caller must hold event lock. Caller must also hold a vblank reference for - * the event @e, which will be dropped when the next vblank arrives. + * Caller must hold a vblank reference for the event @e, which will be dropped + * when the next vblank arrives. */ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e) @@ -913,14 +933,6 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe) return dev->driver->enable_vblank(dev, pipe); } -/** - * drm_vblank_enable - enable the vblank interrupt on a CRTC - * @dev: DRM device - * @pipe: CRTC index - * - * Returns: - * Zero on success or a negative error code on failure. - */ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -958,19 +970,6 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) return ret; } -/** - * drm_vblank_get - get a reference count on vblank events - * @dev: DRM device - * @pipe: index of CRTC to own - * - * Acquire a reference count on vblank events to avoid having them disabled - * while in use. - * - * This is the legacy version of drm_crtc_vblank_get(). - * - * Returns: - * Zero on success or a negative error code on failure. - */ static int drm_vblank_get(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -1014,16 +1013,6 @@ int drm_crtc_vblank_get(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_get); -/** - * drm_vblank_put - release ownership of vblank events - * @dev: DRM device - * @pipe: index of CRTC to release - * - * Release ownership of a given vblank counter, turning off interrupts - * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. - * - * This is the legacy version of drm_crtc_vblank_put(). - */ static void drm_vblank_put(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -1067,6 +1056,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); * This waits for one vblank to pass on @pipe, using the irq driver interfaces. * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. * due to lack of driver support or because the crtc is off. + * + * This is the legacy version of drm_crtc_wait_one_vblank(). */ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { @@ -1116,7 +1107,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank); * stored so that drm_vblank_on can restore it again. * * Drivers must use this function when the hardware vblank counter can get - * reset, e.g. when suspending. + * reset, e.g. when suspending or disabling the @crtc in general. */ void drm_crtc_vblank_off(struct drm_crtc *crtc) { @@ -1184,6 +1175,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); * drm_crtc_vblank_on() functions. The difference compared to * drm_crtc_vblank_off() is that this function doesn't save the vblank counter * and hence doesn't need to call any driver hooks. + * + * This is useful for recovering driver state e.g. on driver load, or on resume. */ void drm_crtc_vblank_reset(struct drm_crtc *crtc) { @@ -1212,9 +1205,10 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset); * @crtc: CRTC in question * * This functions restores the vblank interrupt state captured with - * drm_crtc_vblank_off() again. Note that calls to drm_crtc_vblank_on() and - * drm_crtc_vblank_off() can be unbalanced and so can also be unconditionally called - * in driver load code to reflect the current hardware state of the crtc. + * drm_crtc_vblank_off() again and is generally called when enabling @crtc. Note + * that calls to drm_crtc_vblank_on() and drm_crtc_vblank_off() can be + * unbalanced and so can also be unconditionally called in driver load code to + * reflect the current hardware state of the crtc. */ void drm_crtc_vblank_on(struct drm_crtc *crtc) { @@ -1299,8 +1293,8 @@ static void drm_legacy_vblank_post_modeset(struct drm_device *dev, } } -int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; unsigned int pipe; @@ -1419,22 +1413,8 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait) _DRM_VBLANK_NEXTONMISS)); } -/* - * Wait for VBLANK. - * - * \param inode device inode. - * \param file_priv DRM file private. - * \param cmd command. - * \param data user argument, pointing to a drm_wait_vblank structure. - * \return zero on success or a negative number on failure. - * - * This function enables the vblank interrupt on the pipe requested, then - * sleeps waiting for the requested sequence number to occur, and drops - * the vblank interrupt refcount afterwards. (vblank IRQ disable follows that - * after a timeout with no further vblank waits scheduled). - */ -int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_vblank_crtc *vblank; union drm_wait_vblank *vblwait = data; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 1f9b35afefee..747c06b227c5 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -480,7 +480,6 @@ static struct drm_driver driver = { .load = psb_driver_load, .unload = psb_driver_unload, .lastclose = psb_driver_lastclose, - .set_busid = drm_pci_set_busid, .num_ioctls = ARRAY_SIZE(psb_ioctls), .irq_preinstall = psb_irq_preinstall, @@ -517,12 +516,12 @@ static struct pci_driver psb_pci_driver = { static int __init psb_init(void) { - return drm_pci_init(&driver, &psb_pci_driver); + return pci_register_driver(&psb_pci_driver); } static void __exit psb_exit(void) { - drm_pci_exit(&driver, &psb_pci_driver); + pci_unregister_driver(&psb_pci_driver); } late_initcall(psb_init); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 2ffdbf9801bd..4d018ca98581 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -276,11 +276,12 @@ static int hibmc_unload(struct drm_device *dev) hibmc_fbdev_fini(priv); + drm_atomic_helper_shutdown(dev); + if (dev->irq_enabled) drm_irq_uninstall(dev); if (priv->msi_enabled) pci_disable_msi(dev->pdev); - drm_vblank_cleanup(dev); hibmc_kms_fini(priv); hibmc_mm_fini(priv); diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 9c903672f582..8065d6cb1d7f 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -41,7 +41,6 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) } #endif drm_kms_helper_poll_fini(dev); - drm_vblank_cleanup(dev); dc_ops->cleanup(to_platform_device(dev->dev)); drm_mode_config_cleanup(dev); devm_kfree(dev->dev, priv); diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 37fd0906f807..c69d5c487f51 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -59,7 +59,6 @@ static struct drm_driver driver = { .load = i810_driver_load, .lastclose = i810_driver_lastclose, .preclose = i810_driver_preclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = i810_driver_dma_quiescent, .ioctls = i810_ioctls, .fops = &i810_driver_fops, @@ -83,12 +82,12 @@ static int __init i810_init(void) return -EINVAL; } driver.num_ioctls = i810_max_ioctl; - return drm_pci_init(&driver, &i810_pci_driver); + return drm_legacy_pci_init(&driver, &i810_pci_driver); } static void __exit i810_exit(void) { - drm_pci_exit(&driver, &i810_pci_driver); + drm_legacy_pci_exit(&driver, &i810_pci_driver); } module_init(i810_init); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ee2325b180e7..04d9bd84ee43 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1317,7 +1317,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) ret = i915_load_modeset_init(&dev_priv->drm); if (ret < 0) - goto out_cleanup_vblank; + goto out_cleanup_hw; i915_driver_register(dev_priv); @@ -1334,8 +1334,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; -out_cleanup_vblank: - drm_vblank_cleanup(&dev_priv->drm); out_cleanup_hw: i915_driver_cleanup_hw(dev_priv); out_cleanup_mmio: @@ -1371,8 +1369,6 @@ void i915_driver_unload(struct drm_device *dev) i915_driver_unregister(dev_priv); - drm_vblank_cleanup(dev); - intel_modeset_cleanup(dev); /* @@ -2668,7 +2664,6 @@ static struct drm_driver driver = { .open = i915_driver_open, .lastclose = i915_driver_lastclose, .postclose = i915_driver_postclose, - .set_busid = drm_pci_set_busid, .gem_close_object = i915_gem_close_object, .gem_free_object_unlocked = i915_gem_free_object, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4cd9ee1ba332..bce2d1feceb1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1603,7 +1603,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, crcs[3] = crc3; crcs[4] = crc4; drm_crtc_add_crc_entry(&crtc->base, true, - drm_accurate_vblank_count(&crtc->base), + drm_crtc_accurate_vblank_count(&crtc->base), crcs); } } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dec9e58545a1..4e03ca6c946f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12803,7 +12803,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; if (!dev->max_vblank_count) - return drm_accurate_vblank_count(&crtc->base); + return drm_crtc_accurate_vblank_count(&crtc->base); return dev->driver->get_vblank_counter(dev, crtc->pipe); } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index f6c8ec4c7dbc..56f802d0a51c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -266,7 +266,6 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) { drm_kms_helper_poll_fini(drm); - drm_vblank_cleanup(drm); component_unbind_all(drm->dev, drm); drm_mode_config_cleanup(drm); } diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 63ba0699d107..1aad27813c23 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -62,7 +62,6 @@ static struct drm_driver driver = { .load = mga_driver_load, .unload = mga_driver_unload, .lastclose = mga_driver_lastclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = mga_driver_dma_quiescent, .get_vblank_counter = mga_get_vblank_counter, .enable_vblank = mga_enable_vblank, @@ -90,12 +89,12 @@ static struct pci_driver mga_pci_driver = { static int __init mga_init(void) { driver.num_ioctls = mga_max_ioctl; - return drm_pci_init(&driver, &mga_pci_driver); + return drm_legacy_pci_init(&driver, &mga_pci_driver); } static void __exit mga_exit(void) { - drm_pci_exit(&driver, &mga_pci_driver); + drm_legacy_pci_exit(&driver, &mga_pci_driver); } module_init(mga_init); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 9ac007880328..4189160af726 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -91,7 +91,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET, .load = mgag200_driver_load, .unload = mgag200_driver_unload, - .set_busid = drm_pci_set_busid, .fops = &mgag200_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, @@ -120,12 +119,13 @@ static int __init mgag200_init(void) if (mgag200_modeset == 0) return -EINVAL; - return drm_pci_init(&driver, &mgag200_pci_driver); + + return pci_register_driver(&mgag200_pci_driver); } static void __exit mgag200_exit(void) { - drm_pci_exit(&driver, &mgag200_pci_driver); + pci_unregister_driver(&mgag200_pci_driver); } module_init(mgag200_init); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index d1b9c34c7c00..1853557fef46 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -256,7 +256,6 @@ static void mxsfb_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); pm_runtime_get_sync(drm->dev); drm_irq_uninstall(drm); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 8d1df5678eaa..b9a109be989c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -159,8 +159,6 @@ nouveau_display_vblank_fini(struct drm_device *dev) { struct drm_crtc *crtc; - drm_vblank_cleanup(dev); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); nvif_notify_fini(&nv_crtc->vblank); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 90757af9bc73..2600b3b9f2e7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1098,7 +1098,6 @@ static int __init nouveau_drm_init(void) { driver_pci = driver_stub; - driver_pci.set_busid = drm_pci_set_busid; driver_platform = driver_stub; nouveau_display_options(); @@ -1117,7 +1116,12 @@ nouveau_drm_init(void) nouveau_register_dsm_handler(); nouveau_backlight_ctor(); - return drm_pci_init(&driver_pci, &nouveau_drm_pci_driver); + +#ifdef CONFIG_PCI + return pci_register_driver(&nouveau_drm_pci_driver); +#else + return 0; +#endif } static void __exit @@ -1126,7 +1130,9 @@ nouveau_drm_exit(void) if (!nouveau_modeset) return; - drm_pci_exit(&driver_pci, &nouveau_drm_pci_driver); +#ifdef CONFIG_PCI + pci_unregister_driver(&nouveau_drm_pci_driver); +#endif nouveau_backlight_dtor(); nouveau_unregister_dsm_handler(); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index e3132a2ce34d..42a85c14aea0 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -4067,7 +4067,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) if (crtc->state->event) { unsigned long flags; /* Get correct count/ts if racing with vblank irq */ - drm_accurate_vblank_count(crtc); + drm_crtc_accurate_vblank_count(crtc); spin_lock_irqsave(&crtc->dev->event_lock, flags); drm_crtc_send_vblank_event(crtc, crtc->state->event); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 03fe182203ce..72dcaab84bba 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -437,7 +437,7 @@ static void qxl_monitors_config_set(struct qxl_device *qdev, } -void qxl_mode_set_nofb(struct drm_crtc *crtc) +static void qxl_mode_set_nofb(struct drm_crtc *crtc) { struct qxl_device *qdev = crtc->dev->dev_private; struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); @@ -475,8 +475,8 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { .atomic_flush = qxl_crtc_atomic_flush, }; -int qxl_primary_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int qxl_primary_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { struct qxl_device *qdev = plane->dev->dev_private; struct qxl_framebuffer *qfb; @@ -547,8 +547,8 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane, } } -int qxl_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int qxl_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { return 0; } @@ -647,8 +647,8 @@ out_free_release: } -void qxl_cursor_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) +static void qxl_cursor_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) { struct qxl_device *qdev = plane->dev->dev_private; struct qxl_release *release; @@ -675,8 +675,8 @@ void qxl_cursor_atomic_disable(struct drm_plane *plane, qxl_release_fence_buffer_objects(release); } -int qxl_plane_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *new_state) +static int qxl_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) { struct drm_gem_object *obj; struct qxl_bo *user_bo; diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index c2fc201d9e1b..403e135895bf 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -37,7 +37,6 @@ #include "qxl_drv.h" #include "qxl_object.h" -extern int qxl_max_ioctls; static const struct pci_device_id pciidlist[] = { { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0 }, @@ -262,8 +261,6 @@ static struct drm_driver qxl_driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_ATOMIC, - .set_busid = drm_pci_set_busid, - .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, @@ -303,12 +300,12 @@ static int __init qxl_init(void) if (qxl_modeset == 0) return -EINVAL; qxl_driver.num_ioctls = qxl_max_ioctls; - return drm_pci_init(&qxl_driver, &qxl_pci_driver); + return pci_register_driver(&qxl_pci_driver); } static void __exit qxl_exit(void) { - drm_pci_exit(&qxl_driver, &qxl_pci_driver); + pci_unregister_driver(&qxl_pci_driver); } module_init(qxl_init); diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 3591d2330a09..3397a1907336 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -64,6 +64,7 @@ extern int qxl_log_level; extern int qxl_num_crtc; +extern int qxl_max_ioctls; enum { QXL_INFO_LEVEL = 1, diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 0b82a87916ae..31effed4a3c8 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -163,7 +163,7 @@ static int qxl_process_single_command(struct qxl_device *qdev, return -EINVAL; if (!access_ok(VERIFY_READ, - (void *)(unsigned long)cmd->command, + u64_to_user_ptr(cmd->command), cmd->command_size)) return -EFAULT; @@ -183,7 +183,9 @@ static int qxl_process_single_command(struct qxl_device *qdev, /* TODO copy slow path code from i915 */ fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_SIZE)); - unwritten = __copy_from_user_inatomic_nocache(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (void *)(unsigned long)cmd->command, cmd->command_size); + unwritten = __copy_from_user_inatomic_nocache + (fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), + u64_to_user_ptr(cmd->command), cmd->command_size); { struct qxl_drawable *draw = fb_cmd; @@ -201,10 +203,9 @@ static int qxl_process_single_command(struct qxl_device *qdev, num_relocs = 0; for (i = 0; i < cmd->relocs_num; ++i) { struct drm_qxl_reloc reloc; + struct drm_qxl_reloc __user *u = u64_to_user_ptr(cmd->relocs); - if (copy_from_user(&reloc, - &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i], - sizeof(reloc))) { + if (copy_from_user(&reloc, u + i, sizeof(reloc))) { ret = -EFAULT; goto out_free_bos; } @@ -282,10 +283,10 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, for (cmd_num = 0; cmd_num < execbuffer->commands_num; ++cmd_num) { - struct drm_qxl_command *commands = - (struct drm_qxl_command *)(uintptr_t)execbuffer->commands; + struct drm_qxl_command __user *commands = + u64_to_user_ptr(execbuffer->commands); - if (copy_from_user(&user_cmd, &commands[cmd_num], + if (copy_from_user(&user_cmd, commands + cmd_num, sizeof(user_cmd))) return -EFAULT; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 9a7eef7dd604..0a67ddf19c3d 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -221,7 +221,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) return bo; } -int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +static int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) { struct drm_device *ddev = bo->gem_base.dev; int r; @@ -244,7 +244,7 @@ int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) return r; } -int __qxl_bo_unpin(struct qxl_bo *bo) +static int __qxl_bo_unpin(struct qxl_bo *bo) { struct drm_device *ddev = bo->gem_base.dev; int r, i; diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index a982be57d1ef..0d2b7e42b3a7 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -62,7 +62,6 @@ static struct drm_driver driver = { .load = r128_driver_load, .preclose = r128_driver_preclose, .lastclose = r128_driver_lastclose, - .set_busid = drm_pci_set_busid, .get_vblank_counter = r128_get_vblank_counter, .enable_vblank = r128_enable_vblank, .disable_vblank = r128_disable_vblank, @@ -96,12 +95,12 @@ static int __init r128_init(void) { driver.num_ioctls = r128_max_ioctl; - return drm_pci_init(&driver, &r128_pci_driver); + return drm_legacy_pci_init(&driver, &r128_pci_driver); } static void __exit r128_exit(void) { - drm_pci_exit(&driver, &r128_pci_driver); + drm_legacy_pci_exit(&driver, &r128_pci_driver); } module_init(r128_init); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index b23c771f4216..ff2641cbf172 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -553,7 +553,6 @@ static struct drm_driver kms_driver = { .open = radeon_driver_open_kms, .postclose = radeon_driver_postclose_kms, .lastclose = radeon_driver_lastclose_kms, - .set_busid = drm_pci_set_busid, .unload = radeon_driver_unload_kms, .get_vblank_counter = radeon_get_vblank_counter_kms, .enable_vblank = radeon_enable_vblank_kms, @@ -628,14 +627,13 @@ static int __init radeon_init(void) return -EINVAL; } - /* let modprobe override vga console setting */ - return drm_pci_init(driver, pdriver); + return pci_register_driver(pdriver); } static void __exit radeon_exit(void) { radeon_kfd_fini(); - drm_pci_exit(driver, pdriver); + pci_unregister_driver(pdriver); radeon_unregister_atpx_handler(); } diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 7aacb44df201..fff0d11b0600 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -324,7 +324,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev) */ void radeon_irq_kms_fini(struct radeon_device *rdev) { - drm_vblank_cleanup(rdev->ddev); if (rdev->irq.installed) { drm_irq_uninstall(rdev->ddev); rdev->irq.installed = false; diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index f8208489724e..ccd5d595ada7 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -7,10 +7,12 @@ * (at your option) any later version. */ +#include <linux/clk.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/mfd/syscon.h> #include <linux/regmap.h> + #include <drm/drm_of.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> @@ -20,13 +22,32 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" -#define GRF_SOC_CON6 0x025c -#define HDMI_SEL_VOP_LIT (1 << 4) +#define RK3288_GRF_SOC_CON6 0x025C +#define RK3288_HDMI_LCDC_SEL BIT(4) +#define RK3399_GRF_SOC_CON20 0x6250 +#define RK3399_HDMI_LCDC_SEL BIT(6) + +#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) + +/** + * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips + * @lcdsel_grf_reg: grf register offset of lcdc select + * @lcdsel_big: reg value of selecting vop big for HDMI + * @lcdsel_lit: reg value of selecting vop little for HDMI + */ +struct rockchip_hdmi_chip_data { + u32 lcdsel_grf_reg; + u32 lcdsel_big; + u32 lcdsel_lit; +}; struct rockchip_hdmi { struct device *dev; struct regmap *regmap; struct drm_encoder encoder; + const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; + struct clk *grf_clk; }; #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) @@ -143,6 +164,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) { struct device_node *np = hdmi->dev->of_node; + int ret; hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { @@ -150,6 +172,32 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->regmap); } + hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll"); + if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) { + hdmi->vpll_clk = NULL; + } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->vpll_clk)) { + dev_err(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->vpll_clk); + } + + hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); + if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { + hdmi->grf_clk = NULL; + } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->grf_clk)) { + dev_err(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->grf_clk); + } + + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + return 0; } @@ -192,23 +240,36 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + + clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); } static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); u32 val; - int mux; + int ret; - mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); - if (mux) - val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); + ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); + if (ret) + val = hdmi->chip_data->lcdsel_lit; else - val = HDMI_SEL_VOP_LIT << 16; + val = hdmi->chip_data->lcdsel_big; - regmap_write(hdmi->regmap, GRF_SOC_CON6, val); + ret = clk_prepare_enable(hdmi->grf_clk); + if (ret < 0) { + dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret); + return; + } + + ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); + if (ret != 0) + dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret); + + clk_disable_unprepare(hdmi->grf_clk); dev_dbg(hdmi->dev, "vop %s output to hdmi\n", - (mux) ? "LIT" : "BIG"); + ret ? "LIT" : "BIG"); } static int @@ -232,16 +293,40 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, }; -static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { +static struct rockchip_hdmi_chip_data rk3288_chip_data = { + .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, + .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, .mpll_cfg = rockchip_mpll_cfg, .cur_ctr = rockchip_cur_ctr, .phy_config = rockchip_phy_config, + .phy_data = &rk3288_chip_data, +}; + +static struct rockchip_hdmi_chip_data rk3399_chip_data = { + .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, + .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, }; static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { { .compatible = "rockchip,rk3288-dw-hdmi", - .data = &rockchip_hdmi_drv_data + .data = &rk3288_hdmi_drv_data + }, + { .compatible = "rockchip,rk3399-dw-hdmi", + .data = &rk3399_hdmi_drv_data }, {}, }; @@ -268,6 +353,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); plat_data = match->data; hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; encoder = &hdmi->encoder; encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index c6b1b7f3a2a3..b9fbf4b1e8f0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -177,7 +177,6 @@ err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); - drm_vblank_cleanup(drm_dev); err_unbind_all: component_unbind_all(dev, drm_dev); err_mode_config_cleanup: @@ -200,7 +199,6 @@ static void rockchip_drm_unbind(struct device *dev) drm_kms_helper_poll_fini(drm_dev); drm_atomic_helper_shutdown(drm_dev); - drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); rockchip_iommu_cleanup(drm_dev); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 81f9548672b0..df6bceabeca8 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -168,10 +168,8 @@ err_gem_object_unreference: static void rockchip_drm_output_poll_changed(struct drm_device *dev) { struct rockchip_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper = &private->fbdev_helper; - if (fb_helper) - drm_fb_helper_hotplug_event(fb_helper); + drm_fb_helper_hotplug_event(&private->fbdev_helper); } static void diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 78c6d8e9b42c..2bddeb8bf457 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -55,7 +55,6 @@ static struct drm_driver driver = { .preclose = savage_reclaim_buffers, .lastclose = savage_driver_lastclose, .unload = savage_driver_unload, - .set_busid = drm_pci_set_busid, .ioctls = savage_ioctls, .dma_ioctl = savage_bci_buffers, .fops = &savage_driver_fops, @@ -75,12 +74,12 @@ static struct pci_driver savage_pci_driver = { static int __init savage_init(void) { driver.num_ioctls = savage_max_ioctl; - return drm_pci_init(&driver, &savage_pci_driver); + return drm_legacy_pci_init(&driver, &savage_pci_driver); } static void __exit savage_exit(void) { - drm_pci_exit(&driver, &savage_pci_driver); + drm_legacy_pci_exit(&driver, &savage_pci_driver); } module_init(savage_init); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 800d1d2c435d..c2ca07357aac 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -277,7 +277,7 @@ static int shmob_drm_probe(struct platform_device *pdev) ret = drm_irq_install(ddev, platform_get_irq(pdev, 0)); if (ret < 0) { dev_err(&pdev->dev, "failed to install IRQ handler\n"); - goto err_vblank_cleanup; + goto err_modeset_cleanup; } /* @@ -292,8 +292,6 @@ static int shmob_drm_probe(struct platform_device *pdev) err_irq_uninstall: drm_irq_uninstall(ddev); -err_vblank_cleanup: - drm_vblank_cleanup(ddev); err_modeset_cleanup: drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f05da13ea5e..e04a92658cd7 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -104,7 +104,6 @@ static struct drm_driver driver = { .open = sis_driver_open, .preclose = sis_reclaim_buffers_locked, .postclose = sis_driver_postclose, - .set_busid = drm_pci_set_busid, .dma_quiescent = sis_idle, .lastclose = sis_lastclose, .ioctls = sis_ioctls, @@ -125,12 +124,12 @@ static struct pci_driver sis_pci_driver = { static int __init sis_init(void) { driver.num_ioctls = sis_max_ioctl; - return drm_pci_init(&driver, &sis_pci_driver); + return drm_legacy_pci_init(&driver, &sis_pci_driver); } static void __exit sis_exit(void) { - drm_pci_exit(&driver, &sis_pci_driver); + drm_legacy_pci_exit(&driver, &sis_pci_driver); } module_init(sis_init); diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index a4b574283269..06ef1e3886cf 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -237,7 +237,6 @@ static void sti_cleanup(struct drm_device *ddev) } drm_kms_helper_poll_fini(ddev); - drm_vblank_cleanup(ddev); component_unbind_all(ddev->dev, ddev); kfree(private); ddev->dev_private = NULL; diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 24ebc6b2f34d..a51cd9f754db 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -582,7 +582,7 @@ static int sti_dvo_remove(struct platform_device *pdev) return 0; } -static struct of_device_id dvo_of_match[] = { +static const struct of_device_id dvo_of_match[] = { { .compatible = "st,stih407-dvo", }, { /* end node */ } }; diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index a1c161f77804..53a46dda8bd5 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -958,6 +958,7 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) } if (i == POLL_MAX_ATTEMPT) { DRM_ERROR("Could not reset\n"); + clk_disable_unprepare(hqvdp->clk); goto out; } @@ -994,6 +995,7 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp) } if (i == POLL_MAX_ATTEMPT) { DRM_ERROR("Could not boot\n"); + clk_disable_unprepare(hqvdp->clk); goto out; } @@ -1081,6 +1083,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, &hqvdp->vtg_nb, crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); + clk_disable_unprepare(hqvdp->clk_pix_main); return -EINVAL; } hqvdp->vtg_registered = true; @@ -1395,7 +1398,7 @@ static int sti_hqvdp_remove(struct platform_device *pdev) return 0; } -static struct of_device_id hqvdp_of_match[] = { +static const struct of_device_id hqvdp_of_match[] = { { .compatible = "st,stih407-hqvdp", }, { /* end node */ } }; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index c54138c3a376..3a1476818c65 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -55,7 +55,6 @@ static const struct file_operations tdfx_driver_fops = { static struct drm_driver driver = { .driver_features = DRIVER_LEGACY, - .set_busid = drm_pci_set_busid, .fops = &tdfx_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, @@ -72,12 +71,12 @@ static struct pci_driver tdfx_pci_driver = { static int __init tdfx_init(void) { - return drm_pci_init(&driver, &tdfx_pci_driver); + return drm_legacy_pci_init(&driver, &tdfx_pci_driver); } static void __exit tdfx_exit(void) { - drm_pci_exit(&driver, &tdfx_pci_driver); + drm_legacy_pci_exit(&driver, &tdfx_pci_driver); } module_init(tdfx_init); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 518f4b69ea53..ad3d124a972d 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -214,12 +214,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) err = tegra_drm_fb_init(drm); if (err < 0) - goto vblank; + goto device; return 0; -vblank: - drm_vblank_cleanup(drm); device: host1x_device_exit(device); fbdev: @@ -248,7 +246,6 @@ static void tegra_drm_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); tegra_drm_fb_exit(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); err = host1x_device_exit(device); if (err < 0) diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index cd8b01727734..0f02e1acf0ba 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -11,11 +11,6 @@ #include <drm/drm_crtc_helper.h> #include "udl_drv.h" -static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m) -{ - return 0; -} - static int udl_usb_suspend(struct usb_interface *interface, pm_message_t message) { @@ -52,7 +47,6 @@ static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, .load = udl_driver_load, .unload = udl_driver_unload, - .set_busid = udl_driver_set_busid, /* gem hooks */ .gem_free_object = udl_gem_free_object, diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index a9d93b871a15..0328b2c7b210 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -371,8 +371,6 @@ void udl_driver_unload(struct drm_device *dev) { struct udl_device *udl = dev->dev_private; - drm_vblank_cleanup(dev); - if (udl->urbs.count) udl_free_urb_list(dev); diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 403bbd5f99a9..f20c01759c0d 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -518,6 +518,19 @@ static void vc4_crtc_disable(struct drm_crtc *crtc) WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); + + /* + * Make sure we issue a vblank event after disabling the CRTC if + * someone was waiting it. + */ + if (crtc->state->event) { + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + } } static void vc4_crtc_enable(struct drm_crtc *crtc) @@ -546,18 +559,17 @@ static void vc4_crtc_enable(struct drm_crtc *crtc) drm_crtc_vblank_on(crtc); } -static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { /* Do not allow doublescan modes from user space */ - if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n", crtc->base.id); - return false; + return MODE_NO_DBLESCAN; } - return true; + return MODE_OK; } static int vc4_crtc_atomic_check(struct drm_crtc *crtc, @@ -662,14 +674,6 @@ static void vc4_disable_vblank(struct drm_crtc *crtc) CRTC_WRITE(PV_INTEN, 0); } -/* Must be called with the event lock held */ -bool vc4_event_pending(struct drm_crtc *crtc) -{ - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - - return !!vc4_crtc->event; -} - static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) { struct drm_crtc *crtc = &vc4_crtc->base; @@ -867,7 +871,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .mode_set_nofb = vc4_crtc_mode_set_nofb, .disable = vc4_crtc_disable, .enable = vc4_crtc_enable, - .mode_fixup = vc4_crtc_mode_fixup, + .mode_valid = vc4_crtc_mode_valid, .atomic_check = vc4_crtc_atomic_check, .atomic_flush = vc4_crtc_atomic_flush, }; diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 2e0fe46aeb2e..519cefef800d 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -224,20 +224,19 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) DRM_ERROR("Failed to set clock rate: %d\n", ret); } -static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static enum drm_mode_status vc4_dpi_encoder_mode_valid(struct drm_encoder *encoder, + const struct drm_display_mode *mode) { - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) - return false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; - return true; + return MODE_OK; } static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { .disable = vc4_dpi_encoder_disable, .enable = vc4_dpi_encoder_enable, - .mode_fixup = vc4_dpi_encoder_mode_fixup, + .mode_valid = vc4_dpi_encoder_mode_valid, }; static const struct of_device_id vc4_dpi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index df22698d62ee..1047953216a8 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -491,7 +491,6 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; -bool vc4_event_pending(struct drm_crtc *crtc); int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, bool in_vblank_irq, int *vpos, int *hpos, diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index bc6ecdc6f104..27edae427025 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -29,16 +29,9 @@ static void vc4_output_poll_changed(struct drm_device *dev) drm_fbdev_cma_hotplug_event(vc4->fbdev); } -struct vc4_commit { - struct drm_device *dev; - struct drm_atomic_state *state; - struct vc4_seqno_cb cb; -}; - static void -vc4_atomic_complete_commit(struct vc4_commit *c) +vc4_atomic_complete_commit(struct drm_atomic_state *state) { - struct drm_atomic_state *state = c->state; struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -72,28 +65,14 @@ vc4_atomic_complete_commit(struct vc4_commit *c) drm_atomic_state_put(state); up(&vc4->async_modeset); - - kfree(c); } -static void -vc4_atomic_complete_commit_seqno_cb(struct vc4_seqno_cb *cb) +static void commit_work(struct work_struct *work) { - struct vc4_commit *c = container_of(cb, struct vc4_commit, cb); - - vc4_atomic_complete_commit(c); -} - -static struct vc4_commit *commit_init(struct drm_atomic_state *state) -{ - struct vc4_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); - - if (!c) - return NULL; - c->dev = state->dev; - c->state = state; - - return c; + struct drm_atomic_state *state = container_of(work, + struct drm_atomic_state, + commit_work); + vc4_atomic_complete_commit(state); } /** @@ -115,40 +94,29 @@ static int vc4_atomic_commit(struct drm_device *dev, { struct vc4_dev *vc4 = to_vc4_dev(dev); int ret; - int i; - uint64_t wait_seqno = 0; - struct vc4_commit *c; - struct drm_plane *plane; - struct drm_plane_state *new_state; - - c = commit_init(state); - if (!c) - return -ENOMEM; ret = drm_atomic_helper_setup_commit(state, nonblock); if (ret) return ret; + INIT_WORK(&state->commit_work, commit_work); + ret = down_interruptible(&vc4->async_modeset); - if (ret) { - kfree(c); + if (ret) return ret; - } ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) { - kfree(c); up(&vc4->async_modeset); return ret; } - for_each_plane_in_state(state, plane, new_state, i) { - if ((plane->state->fb != new_state->fb) && new_state->fb) { - struct drm_gem_cma_object *cma_bo = - drm_fb_cma_get_gem_obj(new_state->fb, 0); - struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); - - wait_seqno = max(bo->seqno, wait_seqno); + if (!nonblock) { + ret = drm_atomic_helper_wait_for_fences(dev, state, true); + if (ret) { + drm_atomic_helper_cleanup_planes(dev, state); + up(&vc4->async_modeset); + return ret; } } @@ -177,13 +145,10 @@ static int vc4_atomic_commit(struct drm_device *dev, */ drm_atomic_state_get(state); - if (nonblock) { - vc4_queue_seqno_cb(dev, &c->cb, wait_seqno, - vc4_atomic_complete_commit_seqno_cb); - } else { - vc4_wait_for_seqno(dev, wait_seqno, ~0ull, false); - vc4_atomic_complete_commit(c); - } + if (nonblock) + queue_work(system_unbound_wq, &state->commit_work); + else + vc4_atomic_complete_commit(state); return 0; } @@ -241,6 +206,9 @@ int vc4_kms_load(struct drm_device *dev) sema_init(&vc4->async_modeset, 1); + /* Set support for vblank irq fast disable, before drm_vblank_init() */ + dev->vblank_disable_immediate = true; + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret < 0) { dev_err(dev->dev, "failed to initialize vblank\n"); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index fa6809d8b0fe..8853e9a4f005 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -759,9 +759,26 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) vc4_state->dlist[vc4_state->ptr0_offset] = addr; } +static int vc4_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct vc4_bo *bo; + struct dma_fence *fence; + + if ((plane->state->fb == state->fb) || !state->fb) + return 0; + + bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + fence = reservation_object_get_excl_rcu(bo->resv); + drm_atomic_set_fence_for_plane(state, fence); + + return 0; +} + static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { .atomic_check = vc4_plane_atomic_check, .atomic_update = vc4_plane_atomic_update, + .prepare_fb = vc4_prepare_fb, }; static void vc4_plane_destroy(struct drm_plane *plane) diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 18f401b442c2..c938af8c40cf 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -52,6 +52,7 @@ static void vgem_gem_free_object(struct drm_gem_object *obj) struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj); kvfree(vgem_obj->pages); + mutex_destroy(&vgem_obj->pages_lock); if (obj->import_attach) drm_prime_gem_destroy(obj, vgem_obj->table); @@ -76,11 +77,15 @@ static int vgem_gem_fault(struct vm_fault *vmf) if (page_offset > num_pages) return VM_FAULT_SIGBUS; + ret = -ENOENT; + mutex_lock(&obj->pages_lock); if (obj->pages) { get_page(obj->pages[page_offset]); vmf->page = obj->pages[page_offset]; ret = 0; - } else { + } + mutex_unlock(&obj->pages_lock); + if (ret) { struct page *page; page = shmem_read_mapping_page( @@ -161,6 +166,8 @@ static struct drm_vgem_gem_object *__vgem_gem_create(struct drm_device *dev, return ERR_PTR(ret); } + mutex_init(&obj->pages_lock); + return obj; } @@ -274,37 +281,66 @@ static const struct file_operations vgem_driver_fops = { .release = drm_release, }; +static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo) +{ + mutex_lock(&bo->pages_lock); + if (bo->pages_pin_count++ == 0) { + struct page **pages; + + pages = drm_gem_get_pages(&bo->base); + if (IS_ERR(pages)) { + bo->pages_pin_count--; + mutex_unlock(&bo->pages_lock); + return pages; + } + + bo->pages = pages; + } + mutex_unlock(&bo->pages_lock); + + return bo->pages; +} + +static void vgem_unpin_pages(struct drm_vgem_gem_object *bo) +{ + mutex_lock(&bo->pages_lock); + if (--bo->pages_pin_count == 0) { + drm_gem_put_pages(&bo->base, bo->pages, true, true); + bo->pages = NULL; + } + mutex_unlock(&bo->pages_lock); +} + static int vgem_prime_pin(struct drm_gem_object *obj) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); long n_pages = obj->size >> PAGE_SHIFT; struct page **pages; - /* Flush the object from the CPU cache so that importers can rely - * on coherent indirect access via the exported dma-address. - */ - pages = drm_gem_get_pages(obj); + pages = vgem_pin_pages(bo); if (IS_ERR(pages)) return PTR_ERR(pages); + /* Flush the object from the CPU cache so that importers can rely + * on coherent indirect access via the exported dma-address. + */ drm_clflush_pages(pages, n_pages); - drm_gem_put_pages(obj, pages, true, false); return 0; } -static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj) +static void vgem_prime_unpin(struct drm_gem_object *obj) { - struct sg_table *st; - struct page **pages; + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); - pages = drm_gem_get_pages(obj); - if (IS_ERR(pages)) - return ERR_CAST(pages); + vgem_unpin_pages(bo); +} - st = drm_prime_pages_to_sg(pages, obj->size >> PAGE_SHIFT); - drm_gem_put_pages(obj, pages, false, false); +static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj) +{ + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); - return st; + return drm_prime_pages_to_sg(bo->pages, bo->base.size >> PAGE_SHIFT); } static struct drm_gem_object* vgem_prime_import(struct drm_device *dev, @@ -333,6 +369,8 @@ static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev, __vgem_gem_destroy(obj); return ERR_PTR(-ENOMEM); } + + obj->pages_pin_count++; /* perma-pinned */ drm_prime_sg_to_page_addr_arrays(obj->table, obj->pages, NULL, npages); return &obj->base; @@ -340,23 +378,23 @@ static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev, static void *vgem_prime_vmap(struct drm_gem_object *obj) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); long n_pages = obj->size >> PAGE_SHIFT; struct page **pages; - void *addr; - pages = drm_gem_get_pages(obj); + pages = vgem_pin_pages(bo); if (IS_ERR(pages)) return NULL; - addr = vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL)); - drm_gem_put_pages(obj, pages, false, false); - - return addr; + return vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL)); } static void vgem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) { + struct drm_vgem_gem_object *bo = to_vgem_bo(obj); + vunmap(vaddr); + vgem_unpin_pages(bo); } static int vgem_prime_mmap(struct drm_gem_object *obj, @@ -409,6 +447,7 @@ static struct drm_driver vgem_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_pin = vgem_prime_pin, + .gem_prime_unpin = vgem_prime_unpin, .gem_prime_import = vgem_prime_import, .gem_prime_export = drm_gem_prime_export, .gem_prime_import_sg_table = vgem_prime_import_sg_table, diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h index 1aae01419112..5c8f6d619ff3 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.h +++ b/drivers/gpu/drm/vgem/vgem_drv.h @@ -43,7 +43,11 @@ struct vgem_file { #define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base) struct drm_vgem_gem_object { struct drm_gem_object base; + struct page **pages; + unsigned int pages_pin_count; + struct mutex pages_lock; + struct sg_table *table; }; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 9e0e5392b6ec..aaf766f7cca2 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -77,7 +77,6 @@ static struct drm_driver driver = { .open = via_driver_open, .preclose = via_reclaim_buffers_locked, .postclose = via_driver_postclose, - .set_busid = drm_pci_set_busid, .context_dtor = via_final_context, .get_vblank_counter = via_get_vblank_counter, .enable_vblank = via_enable_vblank, @@ -107,12 +106,12 @@ static int __init via_init(void) { driver.num_ioctls = via_max_ioctl; via_init_command_verifier(); - return drm_pci_init(&driver, &via_pci_driver); + return drm_legacy_pci_init(&driver, &via_pci_driver); } static void __exit via_exit(void) { - drm_pci_exit(&driver, &via_pci_driver); + drm_legacy_pci_exit(&driver, &via_pci_driver); } module_init(via_init); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4a641555b960..204bf181b69e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1531,7 +1531,6 @@ static struct drm_driver driver = { .master_drop = vmw_master_drop, .open = vmw_driver_open, .postclose = vmw_postclose, - .set_busid = drm_pci_set_busid, .dumb_create = vmw_dumb_create, .dumb_map_offset = vmw_dumb_map_offset, @@ -1571,7 +1570,7 @@ static int __init vmwgfx_init(void) if (vgacon_text_force()) return -EINVAL; - ret = drm_pci_init(&driver, &vmw_pci_driver); + ret = pci_register_driver(&vmw_pci_driver); if (ret) DRM_ERROR("Failed initializing DRM.\n"); return ret; @@ -1579,7 +1578,7 @@ static int __init vmwgfx_init(void) static void __exit vmwgfx_exit(void) { - drm_pci_exit(&driver, &vmw_pci_driver); + pci_unregister_driver(&vmw_pci_driver); } module_init(vmwgfx_init); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 3d94ea67a825..1cd67b10a0d9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1658,7 +1658,7 @@ int vmw_kms_init(struct vmw_private *dev_priv) int vmw_kms_close(struct vmw_private *dev_priv) { - int ret; + int ret = 0; /* * Docs says we should take the lock before calling this function @@ -1666,11 +1666,7 @@ int vmw_kms_close(struct vmw_private *dev_priv) * drm_encoder_cleanup which takes the lock we deadlock. */ drm_mode_config_cleanup(dev_priv->dev); - if (dev_priv->active_display_unit == vmw_du_screen_object) - ret = vmw_kms_sou_close_display(dev_priv); - else if (dev_priv->active_display_unit == vmw_du_screen_target) - ret = vmw_kms_stdu_close_display(dev_priv); - else + if (dev_priv->active_display_unit == vmw_du_legacy) ret = vmw_kms_ldu_close_display(dev_priv); return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 5f8d678ae675..ff9c8389ff21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -390,7 +390,6 @@ int vmw_kms_update_proxy(struct vmw_resource *res, * Screen Objects display functions - vmwgfx_scrn.c */ int vmw_kms_sou_init_display(struct vmw_private *dev_priv); -int vmw_kms_sou_close_display(struct vmw_private *dev_priv); int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, @@ -418,7 +417,6 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, * Screen Target Display Unit functions - vmwgfx_stdu.c */ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv); -int vmw_kms_stdu_close_display(struct vmw_private *dev_priv); int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index d3987bcf53f8..449ed4fba0f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -582,13 +582,9 @@ err_free: int vmw_kms_ldu_close_display(struct vmw_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; - if (!dev_priv->ldu_priv) return -ENOSYS; - drm_vblank_cleanup(dev); - BUG_ON(!list_empty(&dev_priv->ldu_priv->active)); kfree(dev_priv->ldu_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 8d7dc9def7c2..3b917c9b0c21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -746,15 +746,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) return 0; } -int vmw_kms_sou_close_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - drm_vblank_cleanup(dev); - - return 0; -} - static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 50be1f034f9e..6aecba6cd5e2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1651,36 +1651,11 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) if (unlikely(ret != 0)) { DRM_ERROR("Failed to initialize STDU %d", i); - goto err_vblank_cleanup; + return ret; } } DRM_INFO("Screen Target Display device initialized\n"); return 0; - -err_vblank_cleanup: - drm_vblank_cleanup(dev); - return ret; -} - - - -/** - * vmw_kms_stdu_close_display - Cleans up after vmw_kms_stdu_init_display - * - * @dev_priv: VMW DRM device - * - * Frees up any resources allocated by vmw_kms_stdu_init_display - * - * RETURNS: - * 0 on success - */ -int vmw_kms_stdu_close_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - drm_vblank_cleanup(dev); - - return 0; } diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index f46c855d274b..fe1aa5315e19 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -149,7 +149,6 @@ out_fbdev_fini: out_poll_fini: drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); out_unbind: component_unbind_all(dev, drm); out_unregister: @@ -171,7 +170,6 @@ static void zx_drm_unbind(struct device *dev) } drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); component_unbind_all(dev, drm); dev_set_drvdata(dev, NULL); drm->dev_private = NULL; |