diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 8df761a10251..c57a609db75b 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -227,8 +227,8 @@ static long udmabuf_create(struct miscdevice *device, if (!hpage) { hpage = find_get_page_flags(mapping, pgoff, FGP_ACCESSED); - if (IS_ERR(hpage)) { - ret = PTR_ERR(hpage); + if (!hpage) { + ret = -EINVAL; goto err; } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index febb7b08d19b..b6640291f980 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1786,7 +1786,6 @@ static const struct drm_driver amdgpu_kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, - .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms), .dumb_create = amdgpu_mode_dumb_create, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 7dfdabe1cdf9..3ac39b44a211 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -184,7 +183,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev) * Returns: * result of handling the IRQ, as defined by &irqreturn_t */ -irqreturn_t amdgpu_irq_handler(int irq, void *arg) +static irqreturn_t amdgpu_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct amdgpu_device *adev = drm_to_adev(dev); @@ -307,6 +306,7 @@ static void amdgpu_restore_msix(struct amdgpu_device *adev) int amdgpu_irq_init(struct amdgpu_device *adev) { int r = 0; + unsigned int irq; spin_lock_init(&adev->irq.lock); @@ -349,15 +349,22 @@ int amdgpu_irq_init(struct amdgpu_device *adev) INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); - adev->irq.installed = true; - /* Use vector 0 for MSI-X */ - r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0)); + /* Use vector 0 for MSI-X. */ + r = pci_irq_vector(adev->pdev, 0); + if (r < 0) + return r; + irq = r; + + /* PCI devices require shared interrupts. */ + r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name, + adev_to_drm(adev)); if (r) { - adev->irq.installed = false; if (!amdgpu_device_has_dc_support(adev)) flush_work(&adev->hotplug_work); return r; } + adev->irq.installed = true; + adev->irq.irq = irq; adev_to_drm(adev)->max_vblank_count = 0x00ffffff; DRM_DEBUG("amdgpu: irq initialized.\n"); @@ -368,7 +375,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev) void amdgpu_irq_fini_hw(struct amdgpu_device *adev) { if (adev->irq.installed) { - drm_irq_uninstall(&adev->ddev); + free_irq(adev->irq.irq, adev_to_drm(adev)); adev->irq.installed = false; if (adev->irq.msi_enabled) pci_free_irq_vectors(adev->pdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h index 78ad4784cc74..e9f2c11ea416 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h @@ -80,6 +80,7 @@ struct amdgpu_irq_src_funcs { struct amdgpu_irq { bool installed; + unsigned int irq; spinlock_t lock; /* interrupt sources */ struct amdgpu_irq_client client[AMDGPU_IRQ_CLIENTID_MAX]; @@ -100,7 +101,6 @@ struct amdgpu_irq { }; void amdgpu_irq_disable_all(struct amdgpu_device *adev); -irqreturn_t amdgpu_irq_handler(int irq, void *arg); int amdgpu_irq_init(struct amdgpu_device *adev); void amdgpu_irq_fini_sw(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 81ae92390736..479c2422a2e0 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -38,6 +37,94 @@ #include "hdlcd_drv.h" #include "hdlcd_regs.h" +static irqreturn_t hdlcd_irq(int irq, void *arg) +{ + struct drm_device *drm = arg; + struct hdlcd_drm_private *hdlcd = drm->dev_private; + unsigned long irq_status; + + irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS); + +#ifdef CONFIG_DEBUG_FS + if (irq_status & HDLCD_INTERRUPT_UNDERRUN) + atomic_inc(&hdlcd->buffer_underrun_count); + + if (irq_status & HDLCD_INTERRUPT_DMA_END) + atomic_inc(&hdlcd->dma_end_count); + + if (irq_status & HDLCD_INTERRUPT_BUS_ERROR) + atomic_inc(&hdlcd->bus_error_count); + + if (irq_status & HDLCD_INTERRUPT_VSYNC) + atomic_inc(&hdlcd->vsync_count); + +#endif + if (irq_status & HDLCD_INTERRUPT_VSYNC) + drm_crtc_handle_vblank(&hdlcd->crtc); + + /* acknowledge interrupt(s) */ + hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status); + + return IRQ_HANDLED; +} + +static void hdlcd_irq_preinstall(struct drm_device *drm) +{ + struct hdlcd_drm_private *hdlcd = drm->dev_private; + /* Ensure interrupts are disabled */ + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0); + hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0); +} + +static void hdlcd_irq_postinstall(struct drm_device *drm) +{ +#ifdef CONFIG_DEBUG_FS + struct hdlcd_drm_private *hdlcd = drm->dev_private; + unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); + + /* enable debug interrupts */ + irq_mask |= HDLCD_DEBUG_INT_MASK; + + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); +#endif +} + +static int hdlcd_irq_install(struct drm_device *drm, int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + hdlcd_irq_preinstall(drm); + + ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm); + if (ret) + return ret; + + hdlcd_irq_postinstall(drm); + + return 0; +} + +static void hdlcd_irq_uninstall(struct drm_device *drm) +{ + struct hdlcd_drm_private *hdlcd = drm->dev_private; + /* disable all the interrupts that we might have enabled */ + unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); + +#ifdef CONFIG_DEBUG_FS + /* disable debug interrupts */ + irq_mask &= ~HDLCD_DEBUG_INT_MASK; +#endif + + /* disable vsync interrupts */ + irq_mask &= ~HDLCD_INTERRUPT_VSYNC; + hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); + + free_irq(hdlcd->irq, drm); +} + static int hdlcd_load(struct drm_device *drm, unsigned long flags) { struct hdlcd_drm_private *hdlcd = drm->dev_private; @@ -90,7 +177,12 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags) goto setup_fail; } - ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto irq_fail; + hdlcd->irq = ret; + + ret = hdlcd_irq_install(drm, hdlcd->irq); if (ret < 0) { DRM_ERROR("failed to install IRQ handler\n"); goto irq_fail; @@ -122,76 +214,6 @@ static void hdlcd_setup_mode_config(struct drm_device *drm) drm->mode_config.funcs = &hdlcd_mode_config_funcs; } -static irqreturn_t hdlcd_irq(int irq, void *arg) -{ - struct drm_device *drm = arg; - struct hdlcd_drm_private *hdlcd = drm->dev_private; - unsigned long irq_status; - - irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS); - -#ifdef CONFIG_DEBUG_FS - if (irq_status & HDLCD_INTERRUPT_UNDERRUN) - atomic_inc(&hdlcd->buffer_underrun_count); - - if (irq_status & HDLCD_INTERRUPT_DMA_END) - atomic_inc(&hdlcd->dma_end_count); - - if (irq_status & HDLCD_INTERRUPT_BUS_ERROR) - atomic_inc(&hdlcd->bus_error_count); - - if (irq_status & HDLCD_INTERRUPT_VSYNC) - atomic_inc(&hdlcd->vsync_count); - -#endif - if (irq_status & HDLCD_INTERRUPT_VSYNC) - drm_crtc_handle_vblank(&hdlcd->crtc); - - /* acknowledge interrupt(s) */ - hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status); - - return IRQ_HANDLED; -} - -static void hdlcd_irq_preinstall(struct drm_device *drm) -{ - struct hdlcd_drm_private *hdlcd = drm->dev_private; - /* Ensure interrupts are disabled */ - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0); - hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0); -} - -static int hdlcd_irq_postinstall(struct drm_device *drm) -{ -#ifdef CONFIG_DEBUG_FS - struct hdlcd_drm_private *hdlcd = drm->dev_private; - unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); - - /* enable debug interrupts */ - irq_mask |= HDLCD_DEBUG_INT_MASK; - - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); -#endif - return 0; -} - -static void hdlcd_irq_uninstall(struct drm_device *drm) -{ - struct hdlcd_drm_private *hdlcd = drm->dev_private; - /* disable all the interrupts that we might have enabled */ - unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK); - -#ifdef CONFIG_DEBUG_FS - /* disable debug interrupts */ - irq_mask &= ~HDLCD_DEBUG_INT_MASK; -#endif - - /* disable vsync interrupts */ - irq_mask &= ~HDLCD_INTERRUPT_VSYNC; - - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask); -} - #ifdef CONFIG_DEBUG_FS static int hdlcd_show_underrun_count(struct seq_file *m, void *arg) { @@ -236,10 +258,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops); static const struct drm_driver hdlcd_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .irq_handler = hdlcd_irq, - .irq_preinstall = hdlcd_irq_preinstall, - .irq_postinstall = hdlcd_irq_postinstall, - .irq_uninstall = hdlcd_irq_uninstall, DRM_GEM_CMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = hdlcd_debugfs_init, @@ -316,7 +334,7 @@ err_pm_active: err_unload: of_node_put(hdlcd->crtc.port); hdlcd->crtc.port = NULL; - drm_irq_uninstall(drm); + hdlcd_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); err_free: drm_mode_config_cleanup(drm); @@ -338,7 +356,7 @@ static void hdlcd_drm_unbind(struct device *dev) hdlcd->crtc.port = NULL; pm_runtime_get_sync(dev); drm_atomic_helper_shutdown(drm); - drm_irq_uninstall(drm); + hdlcd_irq_uninstall(drm); pm_runtime_put(dev); if (pm_runtime_enabled(dev)) pm_runtime_disable(dev); diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h index fd438d177b64..909c39c28487 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.h +++ b/drivers/gpu/drm/arm/hdlcd_drv.h @@ -11,6 +11,7 @@ struct hdlcd_drm_private { struct clk *clk; struct drm_crtc crtc; struct drm_plane *plane; + unsigned int irq; #ifdef CONFIG_DEBUG_FS atomic_t buffer_underrun_count; atomic_t bus_error_count; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 15319967164e..6bfaefa01818 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -808,7 +808,7 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map; u64 dst_off = ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off; - struct dma_buf_map src_map = shadow_plane_state->map[0]; + struct dma_buf_map src_map = shadow_plane_state->data[0]; unsigned int offset_x, offset_y; u16 x, y; u8 x_offset, y_offset; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index f09b6dd8754c..1656d27b78b6 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -557,6 +556,51 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static void atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev) +{ + struct atmel_hlcdc_dc *dc = dev->dev_private; + unsigned int cfg = 0; + int i; + + /* Enable interrupts on activated layers */ + for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { + if (dc->layers[i]) + cfg |= ATMEL_HLCDC_LAYER_STATUS(i); + } + + regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg); +} + +static void atmel_hlcdc_dc_irq_disable(struct drm_device *dev) +{ + struct atmel_hlcdc_dc *dc = dev->dev_private; + unsigned int isr; + + regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff); + regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr); +} + +static int atmel_hlcdc_dc_irq_install(struct drm_device *dev, unsigned int irq) +{ + int ret; + + atmel_hlcdc_dc_irq_disable(dev); + + ret = devm_request_irq(dev->dev, irq, atmel_hlcdc_dc_irq_handler, 0, + dev->driver->name, dev); + if (ret) + return ret; + + atmel_hlcdc_dc_irq_postinstall(dev); + + return 0; +} + +static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev) +{ + atmel_hlcdc_dc_irq_disable(dev); +} + static const struct drm_mode_config_funcs mode_config_funcs = { .fb_create = drm_gem_fb_create, .atomic_check = drm_atomic_helper_check, @@ -647,7 +691,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) drm_mode_config_reset(dev); pm_runtime_get_sync(dev->dev); - ret = drm_irq_install(dev, dc->hlcdc->irq); + ret = atmel_hlcdc_dc_irq_install(dev, dc->hlcdc->irq); pm_runtime_put_sync(dev->dev); if (ret < 0) { dev_err(dev->dev, "failed to install IRQ handler\n"); @@ -676,7 +720,7 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) drm_mode_config_cleanup(dev); pm_runtime_get_sync(dev->dev); - drm_irq_uninstall(dev); + atmel_hlcdc_dc_irq_uninstall(dev); pm_runtime_put_sync(dev->dev); dev->dev_private = NULL; @@ -685,40 +729,10 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) clk_disable_unprepare(dc->hlcdc->periph_clk); } -static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev) -{ - struct atmel_hlcdc_dc *dc = dev->dev_private; - unsigned int cfg = 0; - int i; - - /* Enable interrupts on activated layers */ - for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { - if (dc->layers[i]) - cfg |= ATMEL_HLCDC_LAYER_STATUS(i); - } - - regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg); - - return 0; -} - -static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev) -{ - struct atmel_hlcdc_dc *dc = dev->dev_private; - unsigned int isr; - - regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff); - regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr); -} - DEFINE_DRM_GEM_CMA_FOPS(fops); static const struct drm_driver atmel_hlcdc_dc_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .irq_handler = atmel_hlcdc_dc_irq_handler, - .irq_preinstall = atmel_hlcdc_dc_irq_uninstall, - .irq_postinstall = atmel_hlcdc_dc_irq_postinstall, - .irq_uninstall = atmel_hlcdc_dc_irq_uninstall, DRM_GEM_CMA_DRIVER_OPS, .fops = &fops, .name = "atmel-hlcdc", diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 920824d8df2f..14d73fb1dd15 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -384,6 +384,25 @@ static int anx7625_odfc_config(struct anx7625_data *ctx, return ret; } +/* + * The MIPI source video data exist large variation (e.g. 59Hz ~ 61Hz), + * anx7625 defined K ratio for matching MIPI input video clock and + * DP output video clock. Increase K value can match bigger video data + * variation. IVO panel has small variation than DP CTS spec, need + * decrease the K value. + */ +static int anx7625_set_k_value(struct anx7625_data *ctx) +{ + struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data; + + if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1) + return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, + MIPI_DIGITAL_ADJ_1, 0x3B); + + return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, + MIPI_DIGITAL_ADJ_1, 0x3D); +} + static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx) { struct device *dev = &ctx->client->dev; @@ -470,9 +489,8 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx) MIPI_PLL_N_NUM_15_8, (n >> 8) & 0xff); ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, MIPI_PLL_N_NUM_7_0, (n & 0xff)); - /* Diff */ - ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, - MIPI_DIGITAL_ADJ_1, 0x3D); + + anx7625_set_k_value(ctx); ret |= anx7625_odfc_config(ctx, post_divider - 1); diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index 034c3840028f..6dcf64c703f9 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -210,7 +210,9 @@ #define MIPI_VIDEO_STABLE_CNT 0x0A #define MIPI_LANE_CTRL_10 0x0F -#define MIPI_DIGITAL_ADJ_1 0x1B +#define MIPI_DIGITAL_ADJ_1 0x1B +#define IVO_MID0 0x26 +#define IVO_MID1 0xCF #define MIPI_PLL_M_NUM_23_16 0x1E #define MIPI_PLL_M_NUM_15_8 0x1F diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 7149ed40af83..2f2a09adb4bc 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -536,6 +536,8 @@ static int it66121_bridge_attach(struct drm_bridge *bridge, return -EINVAL; ret = drm_bridge_attach(bridge->encoder, ctx->next_bridge, bridge, flags); + if (ret) + return ret; ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG, IT66121_CLK_BANK_PWROFF_RCLK, 0); diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index cd0fccdd8dfd..41d48a393e7f 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -739,6 +739,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, } pdata->dsi = dsi; + /* We never want the next bridge to *also* create a connector: */ + flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; + /* Attach the next bridge */ ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge, &pdata->bridge, flags); diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 53e58bbb6cf5..60a6b21474b1 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -63,9 +63,9 @@ static bool drm_is_current_master_locked(struct drm_file *fpriv) { - /* Either drm_device.master_mutex or drm_file.master_lookup_lock - * should be held here. - */ + lockdep_assert_once(lockdep_is_held(&fpriv->master_lookup_lock) || + lockdep_is_held(&fpriv->minor->dev->master_mutex)); + return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; } diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index 4865870cc60e..e570398abd78 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -339,7 +339,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p if (ret) return ret; - return drm_gem_fb_vmap(fb, shadow_plane_state->map); + return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data); } EXPORT_SYMBOL(drm_gem_prepare_shadow_fb); diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 5731a6a1dfa5..3c75d79dbb65 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -315,19 +315,25 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty); * drm_gem_fb_vmap - maps all framebuffer BOs into kernel address space * @fb: the framebuffer * @map: returns the mapping's address for each BO + * @data: returns the data address for each BO, can be NULL * * This function maps all buffer objects of the given framebuffer into * kernel address space and stores them in struct dma_buf_map. If the * mapping operation fails for one of the BOs, the function unmaps the * already established mappings automatically. * + * Callers that want to access a BO's stored data should pass @data. + * The argument returns the addresses of the data stored in each BO. This + * is different from @map if the framebuffer's offsets field is non-zero. + * * See drm_gem_fb_vunmap() for unmapping. * * Returns: * 0 on success, or a negative errno code otherwise. */ int drm_gem_fb_vmap(struct drm_framebuffer *fb, - struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]) + struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES], + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]) { struct drm_gem_object *obj; unsigned int i; @@ -344,6 +350,15 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb, goto err_drm_gem_vunmap; } + if (data) { + for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) { + memcpy(&data[i], &map[i], sizeof(data[i])); + if (dma_buf_map_is_null(&data[i])) + continue; + dma_buf_map_incr(&data[i], fb->offsets[i]); + } + } + return 0; err_drm_gem_vunmap: diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 4a853011549a..13e1d5c4ec82 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -60,46 +60,14 @@ #include #include #include -#include +#include #include #include #include "drm_internal.h" -/** - * DOC: irq helpers - * - * The DRM core provides very simple support helpers to enable IRQ handling on a - * device through the drm_irq_install() and drm_irq_uninstall() functions. This - * only supports devices with a single interrupt on the main device stored in - * &drm_device.dev and set as the device parameter in drm_dev_alloc(). - * - * These IRQ helpers are strictly optional. Since these helpers don't automatically - * clean up the requested interrupt like e.g. devm_request_irq() they're not really - * recommended. - */ - -/** - * drm_irq_install - install IRQ handler - * @dev: DRM device - * @irq: IRQ number to install the handler for - * - * Initializes the IRQ related data. Installs the handler, calling the driver - * &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before - * and after the installation. - * - * This is the simplified helper interface provided for drivers with no special - * needs. - * - * @irq must match the interrupt number that would be passed to request_irq(), - * if called directly instead of using this helper function. - * - * &drm_driver.irq_handler is called to handle the registered interrupt. - * - * Returns: - * Zero on success or a negative error code on failure. - */ -int drm_irq_install(struct drm_device *dev, int irq) +#if IS_ENABLED(CONFIG_DRM_LEGACY) +static int drm_legacy_irq_install(struct drm_device *dev, int irq) { int ret; unsigned long sh_flags = 0; @@ -144,24 +112,8 @@ int drm_irq_install(struct drm_device *dev, int irq) return ret; } -EXPORT_SYMBOL(drm_irq_install); -/** - * drm_irq_uninstall - uninstall the IRQ handler - * @dev: DRM device - * - * Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ - * handler. This should only be called by drivers which used drm_irq_install() - * to set up their interrupt handler. - * - * Note that for kernel modesetting drivers it is a bug if this function fails. - * The sanity checks are only to catch buggy user modesetting drivers which call - * the same function through an ioctl. - * - * Returns: - * Zero on success or a negative error code on failure. - */ -int drm_irq_uninstall(struct drm_device *dev) +int drm_legacy_irq_uninstall(struct drm_device *dev) { unsigned long irqflags; bool irq_enabled; @@ -207,41 +159,8 @@ int drm_irq_uninstall(struct drm_device *dev) return 0; } -EXPORT_SYMBOL(drm_irq_uninstall); +EXPORT_SYMBOL(drm_legacy_irq_uninstall); -static void devm_drm_irq_uninstall(void *data) -{ - drm_irq_uninstall(data); -} - -/** - * devm_drm_irq_install - install IRQ handler - * @dev: DRM device - * @irq: IRQ number to install the handler for - * - * devm_drm_irq_install is a help function of drm_irq_install. - * - * if the driver uses devm_drm_irq_install, there is no need - * to call drm_irq_uninstall when the drm module get unloaded, - * as this will done automagically. - * - * Returns: - * Zero on success or a negative error code on failure. - */ -int devm_drm_irq_install(struct drm_device *dev, int irq) -{ - int ret; - - ret = drm_irq_install(dev, irq); - if (ret) - return ret; - - return devm_add_action_or_reset(dev->dev, - devm_drm_irq_uninstall, dev); -} -EXPORT_SYMBOL(devm_drm_irq_install); - -#if IS_ENABLED(CONFIG_DRM_LEGACY) int drm_legacy_irq_control(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -270,13 +189,13 @@ int drm_legacy_irq_control(struct drm_device *dev, void *data, ctl->irq != irq) return -EINVAL; mutex_lock(&dev->struct_mutex); - ret = drm_irq_install(dev, irq); + ret = drm_legacy_irq_install(dev, irq); mutex_unlock(&dev->struct_mutex); return ret; case DRM_UNINST_HANDLER: mutex_lock(&dev->struct_mutex); - ret = drm_irq_uninstall(dev); + ret = drm_legacy_irq_uninstall(dev); mutex_unlock(&dev->struct_mutex); return ret; diff --git a/drivers/gpu/drm/drm_legacy_misc.c b/drivers/gpu/drm/drm_legacy_misc.c index 83db43b7a25e..d4c5434062d7 100644 --- a/drivers/gpu/drm/drm_legacy_misc.c +++ b/drivers/gpu/drm/drm_legacy_misc.c @@ -35,7 +35,6 @@ #include #include -#include #include #include "drm_internal.h" @@ -78,7 +77,7 @@ int drm_legacy_setup(struct drm_device * dev) void drm_legacy_dev_reinit(struct drm_device *dev) { if (dev->irq_enabled) - drm_irq_uninstall(dev); + drm_legacy_irq_uninstall(dev); mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 735f4f34bcc4..72989ed1baba 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -145,6 +145,39 @@ static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { .atomic_disable = drm_simple_kms_crtc_disable, }; +static void drm_simple_kms_crtc_reset(struct drm_crtc *crtc) +{ + struct drm_simple_display_pipe *pipe; + + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); + if (!pipe->funcs || !pipe->funcs->reset_crtc) + return drm_atomic_helper_crtc_reset(crtc); + + return pipe->funcs->reset_crtc(pipe); +} + +static struct drm_crtc_state *drm_simple_kms_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct drm_simple_display_pipe *pipe; + + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); + if (!pipe->funcs || !pipe->funcs->duplicate_crtc_state) + return drm_atomic_helper_crtc_duplicate_state(crtc); + + return pipe->funcs->duplicate_crtc_state(pipe); +} + +static void drm_simple_kms_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) +{ + struct drm_simple_display_pipe *pipe; + + pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); + if (!pipe->funcs || !pipe->funcs->destroy_crtc_state) + drm_atomic_helper_crtc_destroy_state(crtc, state); + else + pipe->funcs->destroy_crtc_state(pipe, state); +} + static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc) { struct drm_simple_display_pipe *pipe; @@ -168,12 +201,12 @@ static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc) } static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = { - .reset = drm_atomic_helper_crtc_reset, + .reset = drm_simple_kms_crtc_reset, .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = drm_simple_kms_crtc_duplicate_state, + .atomic_destroy_state = drm_simple_kms_crtc_destroy_state, .enable_vblank = drm_simple_kms_crtc_enable_vblank, .disable_vblank = drm_simple_kms_crtc_disable_vblank, }; diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 977b6509bb4b..b701cda86d0c 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1739,10 +1739,10 @@ static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe, static bool drm_wait_vblank_supported(struct drm_device *dev) { - if (IS_ENABLED(CONFIG_DRM_LEGACY)) { - if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY))) - return dev->irq_enabled; - } +#if IS_ENABLED(CONFIG_DRM_LEGACY) + if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY))) + return dev->irq_enabled; +#endif return drm_dev_has_vblank(dev); } diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 7528e8a2d359..660fe573db96 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ static const struct regmap_config fsl_dcu_regmap_config = { .volatile_reg = fsl_dcu_drm_is_volatile_reg, }; -static void fsl_dcu_irq_uninstall(struct drm_device *dev) +static void fsl_dcu_irq_reset(struct drm_device *dev) { struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; @@ -59,58 +58,6 @@ static void fsl_dcu_irq_uninstall(struct drm_device *dev) regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0); } -static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) -{ - struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; - int ret; - - ret = fsl_dcu_drm_modeset_init(fsl_dev); - if (ret < 0) { - dev_err(dev->dev, "failed to initialize mode setting\n"); - return ret; - } - - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); - if (ret < 0) { - dev_err(dev->dev, "failed to initialize vblank\n"); - goto done; - } - - ret = drm_irq_install(dev, fsl_dev->irq); - if (ret < 0) { - dev_err(dev->dev, "failed to install IRQ handler\n"); - goto done; - } - - if (legacyfb_depth != 16 && legacyfb_depth != 24 && - legacyfb_depth != 32) { - dev_warn(dev->dev, - "Invalid legacyfb_depth. Defaulting to 24bpp\n"); - legacyfb_depth = 24; - } - - return 0; -done: - drm_kms_helper_poll_fini(dev); - - drm_mode_config_cleanup(dev); - drm_irq_uninstall(dev); - dev->dev_private = NULL; - - return ret; -} - -static void fsl_dcu_unload(struct drm_device *dev) -{ - drm_atomic_helper_shutdown(dev); - drm_kms_helper_poll_fini(dev); - - drm_mode_config_cleanup(dev); - drm_irq_uninstall(dev); - - dev->dev_private = NULL; -} - static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -132,15 +79,82 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) return IRQ_HANDLED; } +static int fsl_dcu_irq_install(struct drm_device *dev, unsigned int irq) +{ + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + fsl_dcu_irq_reset(dev); + + return request_irq(irq, fsl_dcu_drm_irq, 0, dev->driver->name, dev); +} + +static void fsl_dcu_irq_uninstall(struct drm_device *dev) +{ + struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; + + fsl_dcu_irq_reset(dev); + free_irq(fsl_dev->irq, dev); +} + +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) +{ + struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; + int ret; + + ret = fsl_dcu_drm_modeset_init(fsl_dev); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize mode setting\n"); + return ret; + } + + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize vblank\n"); + goto done_vblank; + } + + ret = fsl_dcu_irq_install(dev, fsl_dev->irq); + if (ret < 0) { + dev_err(dev->dev, "failed to install IRQ handler\n"); + goto done_irq; + } + + if (legacyfb_depth != 16 && legacyfb_depth != 24 && + legacyfb_depth != 32) { + dev_warn(dev->dev, + "Invalid legacyfb_depth. Defaulting to 24bpp\n"); + legacyfb_depth = 24; + } + + return 0; +done_irq: + drm_kms_helper_poll_fini(dev); + + drm_mode_config_cleanup(dev); +done_vblank: + dev->dev_private = NULL; + + return ret; +} + +static void fsl_dcu_unload(struct drm_device *dev) +{ + drm_atomic_helper_shutdown(dev); + drm_kms_helper_poll_fini(dev); + + drm_mode_config_cleanup(dev); + fsl_dcu_irq_uninstall(dev); + + dev->dev_private = NULL; +} + DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops); static const struct drm_driver fsl_dcu_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, - .irq_handler = fsl_dcu_drm_irq, - .irq_preinstall = fsl_dcu_irq_uninstall, - .irq_uninstall = fsl_dcu_irq_uninstall, DRM_GEM_CMA_DRIVER_OPS, .fops = &fsl_dcu_drm_fops, .name = "fsl-dcu-drm", diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index f07641dfa5a4..20ace6010f9f 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -32,6 +32,7 @@ #include "psb_drv.h" #include "psb_reg.h" #include "psb_intel_reg.h" +#include "psb_irq.h" #include #include diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 3850842d58f3..58bce1a60a4d 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,7 @@ #include "power.h" #include "psb_drv.h" #include "psb_intel_reg.h" +#include "psb_irq.h" #include "psb_reg.h" static const struct drm_driver driver; @@ -380,7 +380,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - drm_irq_install(dev, pdev->irq); + psb_irq_install(dev, pdev->irq); dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ @@ -515,10 +515,6 @@ static const struct drm_driver driver = { .lastclose = drm_fb_helper_lastclose, .num_ioctls = ARRAY_SIZE(psb_ioctls), - .irq_preinstall = psb_irq_preinstall, - .irq_postinstall = psb_irq_postinstall, - .irq_uninstall = psb_irq_uninstall, - .irq_handler = psb_irq_handler, .dumb_create = psb_gem_dumb_create, .ioctls = psb_ioctls, diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index d6e7c2c2c947..f2bae270ca7b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -624,11 +624,6 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev) } /* psb_irq.c */ -extern irqreturn_t psb_irq_handler(int irq, void *arg); -extern void psb_irq_preinstall(struct drm_device *dev); -extern int psb_irq_postinstall(struct drm_device *dev); -extern void psb_irq_uninstall(struct drm_device *dev); - extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 104009e78487..deb1fbc1f748 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -8,6 +8,7 @@ * **************************************************************************/ +#include #include #include "power.h" @@ -222,7 +223,7 @@ static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2) PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2); } -irqreturn_t psb_irq_handler(int irq, void *arg) +static irqreturn_t psb_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_psb_private *dev_priv = dev->dev_private; @@ -304,7 +305,7 @@ void psb_irq_preinstall(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } -int psb_irq_postinstall(struct drm_device *dev) +void psb_irq_postinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; @@ -332,12 +333,31 @@ int psb_irq_postinstall(struct drm_device *dev) dev_priv->ops->hotplug_enable(dev, true); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); +} + +int psb_irq_install(struct drm_device *dev, unsigned int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + psb_irq_preinstall(dev); + + /* PCI devices require shared interrupts. */ + ret = request_irq(irq, psb_irq_handler, IRQF_SHARED, dev->driver->name, dev); + if (ret) + return ret; + + psb_irq_postinstall(dev); + return 0; } void psb_irq_uninstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; + struct pci_dev *pdev = to_pci_dev(dev->dev); unsigned long irqflags; unsigned int i; @@ -366,6 +386,8 @@ void psb_irq_uninstall(struct drm_device *dev) /* This register is safe even if display island is off */ PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); + + free_irq(pdev->irq, dev); } /* diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h index 17c9b0b62471..a97cb49393d8 100644 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ b/drivers/gpu/drm/gma500/psb_irq.h @@ -19,9 +19,9 @@ bool sysirq_init(struct drm_device *dev); void sysirq_uninit(struct drm_device *dev); void psb_irq_preinstall(struct drm_device *dev); -int psb_irq_postinstall(struct drm_device *dev); +void psb_irq_postinstall(struct drm_device *dev); +int psb_irq_install(struct drm_device *dev, unsigned int irq); void psb_irq_uninstall(struct drm_device *dev); -irqreturn_t psb_irq_handler(int irq, void *arg); int psb_enable_vblank(struct drm_crtc *crtc); void psb_disable_vblank(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 7e009f562b30..b9b0e435ea0f 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -153,6 +153,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach; u8 compression = gdrm->compression; struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; + struct dma_buf_map map_data[DRM_FORMAT_MAX_PLANES]; void *vaddr, *buf; size_t pitch, len; int ret = 0; @@ -162,11 +163,11 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, if (len > gdrm->bulk_len) return -E2BIG; - ret = drm_gem_fb_vmap(fb, map); + ret = drm_gem_fb_vmap(fb, map, map_data); if (ret) return ret; - vaddr = map[0].vaddr + fb->offsets[0]; + vaddr = map_data[0].vaddr; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index 3aaee4730ec6..6dd4717d3e1e 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -105,7 +105,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe, crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, plane_state->fb->pitches[0]); - hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->map[0]); + hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]); } static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe, @@ -133,7 +133,7 @@ static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_rect rect; if (drm_atomic_helper_damage_merged(old_state, state, &rect)) { - hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->map[0], &rect); + hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect); hyperv_update_dirt(hv->hdev, &rect); } } diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index d78c82af367c..9fb4dd63342f 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -209,7 +208,7 @@ static int i810_dma_cleanup(struct drm_device *dev) * is freed, it's too late. */ if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled) - drm_irq_uninstall(dev); + drm_legacy_irq_uninstall(dev); if (dev->dev_private) { int i; diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index d261f7a03b18..a5df1c8d34cd 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -701,29 +701,6 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, } } -static void ingenic_drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state) -{ - /* - * Just your regular drm_atomic_helper_commit_tail(), but only calls - * drm_atomic_helper_wait_for_vblanks() if priv->no_vblank. - */ - struct drm_device *dev = old_state->dev; - struct ingenic_drm *priv = drm_device_get_priv(dev); - - drm_atomic_helper_commit_modeset_disables(dev, old_state); - - drm_atomic_helper_commit_planes(dev, old_state, 0); - - drm_atomic_helper_commit_modeset_enables(dev, old_state); - - drm_atomic_helper_commit_hw_done(old_state); - - if (!priv->no_vblank) - drm_atomic_helper_wait_for_vblanks(dev, old_state); - - drm_atomic_helper_cleanup_planes(dev, old_state); -} - static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg) { struct ingenic_drm *priv = drm_device_get_priv(arg); @@ -744,6 +721,9 @@ static int ingenic_drm_enable_vblank(struct drm_crtc *crtc) { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); + if (priv->no_vblank) + return -EINVAL; + regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ); @@ -851,7 +831,7 @@ static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = { }; static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = { - .atomic_commit_tail = ingenic_drm_atomic_helper_commit_tail, + .atomic_commit_tail = drm_atomic_helper_commit_tail, }; static void ingenic_drm_unbind_all(void *d) @@ -984,9 +964,6 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) priv->dma_hwdescs->hwdesc_pal.cmd = JZ_LCD_CMD_ENABLE_PAL | (sizeof(priv->dma_hwdescs->palette) / 4); - if (soc_info->has_osd) - priv->ipu_plane = drm_plane_from_index(drm, 0); - primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0; drm_plane_helper_add(primary, &ingenic_drm_plane_helper_funcs); diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c index 96ea1a2c11dd..be192f6da9f1 100644 --- a/drivers/gpu/drm/kmb/kmb_drv.c +++ b/drivers/gpu/drm/kmb/kmb_drv.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -399,14 +398,29 @@ static void kmb_irq_reset(struct drm_device *drm) kmb_write_lcd(to_kmb(drm), LCD_INT_ENABLE, 0); } +static int kmb_irq_install(struct drm_device *drm, unsigned int irq) +{ + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + kmb_irq_reset(drm); + + return request_irq(irq, kmb_isr, 0, drm->driver->name, drm); +} + +static void kmb_irq_uninstall(struct drm_device *drm) +{ + struct kmb_drm_private *kmb = to_kmb(drm); + + kmb_irq_reset(drm); + free_irq(kmb->irq_lcd, drm); +} + DEFINE_DRM_GEM_CMA_FOPS(fops); static const struct drm_driver kmb_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .irq_handler = kmb_isr, - .irq_preinstall = kmb_irq_reset, - .irq_uninstall = kmb_irq_reset, /* GEM Operations */ .fops = &fops, DRM_GEM_CMA_DRIVER_OPS_VMAP, @@ -428,7 +442,7 @@ static int kmb_remove(struct platform_device *pdev) of_node_put(kmb->crtc.port); kmb->crtc.port = NULL; pm_runtime_get_sync(drm->dev); - drm_irq_uninstall(drm); + kmb_irq_uninstall(drm); pm_runtime_put_sync(drm->dev); pm_runtime_disable(drm->dev); @@ -518,7 +532,7 @@ static int kmb_probe(struct platform_device *pdev) if (ret) goto err_free; - ret = drm_irq_install(&kmb->drm, kmb->irq_lcd); + ret = kmb_irq_install(&kmb->drm, kmb->irq_lcd); if (ret < 0) { drm_err(&kmb->drm, "failed to install IRQ handler\n"); goto err_irq; diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 403efc1f1a7c..331c2f0da57a 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -949,7 +949,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup) * is freed, it's too late. */ if (dev->irq_enabled) - drm_irq_uninstall(dev); + drm_legacy_irq_uninstall(dev); if (dev->dev_private) { drm_mga_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 84395d81ab9b..f61401c70b90 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 42fedef53882..d4f766522483 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o +mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o mgag200_pll.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index f7a0537c0d0a..196f74a0834e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -43,6 +43,22 @@ #define ATTR_INDEX 0x1fc0 #define ATTR_DATA 0x1fc1 +#define WREG_MISC(v) \ + WREG8(MGA_MISC_OUT, v) + +#define RREG_MISC(v) \ + ((v) = RREG8(MGA_MISC_IN)) + +#define WREG_MISC_MASKED(v, mask) \ + do { \ + u8 misc_; \ + u8 mask_ = (mask); \ + RREG_MISC(misc_); \ + misc_ &= ~mask_; \ + misc_ |= ((v) & mask_); \ + WREG_MISC(misc_); \ + } while (0) + #define WREG_ATTR(reg, v) \ do { \ RREG8(0x1fda); \ @@ -110,6 +126,48 @@ #define MGAG200_MAX_FB_HEIGHT 4096 #define MGAG200_MAX_FB_WIDTH 4096 +struct mga_device; +struct mgag200_pll; + +/* + * Stores parameters for programming the PLLs + * + * Fref: reference frequency (A: 25.175 Mhz, B: 28.361, C: XX Mhz) + * Fo: output frequency + * Fvco = Fref * (N / M) + * Fo = Fvco / P + * + * S = [0..3] + */ +struct mgag200_pll_values { + unsigned int m; + unsigned int n; + unsigned int p; + unsigned int s; +}; + +struct mgag200_pll_funcs { + int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc); + void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc); +}; + +struct mgag200_pll { + struct mga_device *mdev; + + const struct mgag200_pll_funcs *funcs; +}; + +struct mgag200_crtc_state { + struct drm_crtc_state base; + + struct mgag200_pll_values pixpllc; +}; + +static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_state *base) +{ + return container_of(base, struct mgag200_crtc_state, base); +} + #define to_mga_connector(x) container_of(x, struct mga_connector, base) struct mga_i2c_chan { @@ -180,8 +238,8 @@ struct mga_device { } g200se; } model; - struct mga_connector connector; + struct mgag200_pll pixpll; struct drm_simple_display_pipe display_pipe; }; @@ -200,4 +258,7 @@ void mgag200_i2c_destroy(struct mga_i2c_chan *i2c); /* mgag200_mm.c */ int mgag200_mm_init(struct mga_device *mdev); + /* mgag200_pll.c */ +int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev); + #endif /* __MGAG200_DRV_H__ */ diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 3b3059f471c2..fd98e8bbc550 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -110,712 +110,6 @@ static inline void mga_wait_busy(struct mga_device *mdev) } while ((status & 0x01) && time_before(jiffies, timeout)); } -/* - * PLL setup - */ - -static int mgag200_g200_set_plls(struct mga_device *mdev, long clock) -{ - struct drm_device *dev = &mdev->base; - const int post_div_max = 7; - const int in_div_min = 1; - const int in_div_max = 6; - const int feed_div_min = 7; - const int feed_div_max = 127; - u8 testm, testn; - u8 n = 0, m = 0, p, s; - long f_vco; - long computed; - long delta, tmp_delta; - long ref_clk = mdev->model.g200.ref_clk; - long p_clk_min = mdev->model.g200.pclk_min; - long p_clk_max = mdev->model.g200.pclk_max; - - if (clock > p_clk_max) { - drm_err(dev, "Pixel Clock %ld too high\n", clock); - return 1; - } - - if (clock < p_clk_min >> 3) - clock = p_clk_min >> 3; - - f_vco = clock; - for (p = 0; - p <= post_div_max && f_vco < p_clk_min; - p = (p << 1) + 1, f_vco <<= 1) - ; - - delta = clock; - - for (testm = in_div_min; testm <= in_div_max; testm++) { - for (testn = feed_div_min; testn <= feed_div_max; testn++) { - computed = ref_clk * (testn + 1) / (testm + 1); - if (computed < f_vco) - tmp_delta = f_vco - computed; - else - tmp_delta = computed - f_vco; - if (tmp_delta < delta) { - delta = tmp_delta; - m = testm; - n = testn; - } - } - } - f_vco = ref_clk * (n + 1) / (m + 1); - if (f_vco < 100000) - s = 0; - else if (f_vco < 140000) - s = 1; - else if (f_vco < 180000) - s = 2; - else - s = 3; - - drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", - clock, f_vco, m, n, p, s); - - WREG_DAC(MGA1064_PIX_PLLC_M, m); - WREG_DAC(MGA1064_PIX_PLLC_N, n); - WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3))); - - return 0; -} - -#define P_ARRAY_SIZE 9 - -static int mga_g200se_set_plls(struct mga_device *mdev, long clock) -{ - u32 unique_rev_id = mdev->model.g200se.unique_rev_id; - unsigned int vcomax, vcomin, pllreffreq; - unsigned int delta, tmpdelta, permitteddelta; - unsigned int testp, testm, testn; - unsigned int p, m, n; - unsigned int computed; - unsigned int pvalues_e4[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; - unsigned int fvv; - unsigned int i; - - if (unique_rev_id <= 0x03) { - - m = n = p = 0; - vcomax = 320000; - vcomin = 160000; - pllreffreq = 25000; - - delta = 0xffffffff; - permitteddelta = clock * 5 / 1000; - - for (testp = 8; testp > 0; testp /= 2) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testn = 17; testn < 256; testn++) { - for (testm = 1; testm < 32; testm++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm - 1; - n = testn - 1; - p = testp - 1; - } - } - } - } - } else { - - - m = n = p = 0; - vcomax = 1600000; - vcomin = 800000; - pllreffreq = 25000; - - if (clock < 25000) - clock = 25000; - - clock = clock * 2; - - delta = 0xFFFFFFFF; - /* Permited delta is 0.5% as VESA Specification */ - permitteddelta = clock * 5 / 1000; - - for (i = 0 ; i < P_ARRAY_SIZE ; i++) { - testp = pvalues_e4[i]; - - if ((clock * testp) > vcomax) - continue; - if ((clock * testp) < vcomin) - continue; - - for (testn = 50; testn <= 256; testn++) { - for (testm = 1; testm <= 32; testm++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm - 1; - n = testn - 1; - p = testp - 1; - } - } - } - } - - fvv = pllreffreq * (n + 1) / (m + 1); - fvv = (fvv - 800000) / 50000; - - if (fvv > 15) - fvv = 15; - - p |= (fvv << 4); - m |= 0x80; - - clock = clock / 2; - } - - if (delta > permitteddelta) { - pr_warn("PLL delta too large\n"); - return 1; - } - - WREG_DAC(MGA1064_PIX_PLLC_M, m); - WREG_DAC(MGA1064_PIX_PLLC_N, n); - WREG_DAC(MGA1064_PIX_PLLC_P, p); - - if (unique_rev_id >= 0x04) { - WREG_DAC(0x1a, 0x09); - msleep(20); - WREG_DAC(0x1a, 0x01); - - } - - return 0; -} - -static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) -{ - unsigned int vcomax, vcomin, pllreffreq; - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn, testp2; - unsigned int p, m, n; - unsigned int computed; - int i, j, tmpcount, vcount; - bool pll_locked = false; - u8 tmp; - - m = n = p = 0; - - delta = 0xffffffff; - - if (mdev->type == G200_EW3) { - - vcomax = 800000; - vcomin = 400000; - pllreffreq = 25000; - - for (testp = 1; testp < 8; testp++) { - for (testp2 = 1; testp2 < 8; testp2++) { - if (testp < testp2) - continue; - if ((clock * testp * testp2) > vcomax) - continue; - if ((clock * testp * testp2) < vcomin) - continue; - for (testm = 1; testm < 26; testm++) { - for (testn = 32; testn < 2048 ; testn++) { - computed = (pllreffreq * testn) / - (testm * testp * testp2); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = ((testn & 0x100) >> 1) | - (testm); - n = (testn & 0xFF); - p = ((testn & 0x600) >> 3) | - (testp2 << 3) | - (testp); - } - } - } - } - } - } else { - - vcomax = 550000; - vcomin = 150000; - pllreffreq = 48000; - - for (testp = 1; testp < 9; testp++) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testm = 1; testm < 17; testm++) { - for (testn = 1; testn < 151; testn++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn - 1; - m = (testm - 1) | - ((n >> 1) & 0x80); - p = testp - 1; - } - } - } - } - } - - for (i = 0; i <= 32 && pll_locked == false; i++) { - if (i > 0) { - WREG8(MGAREG_CRTC_INDEX, 0x1e); - tmp = RREG8(MGAREG_CRTC_DATA); - if (tmp < 0xff) - WREG8(MGAREG_CRTC_DATA, tmp+1); - } - - /* set pixclkdis to 1 */ - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_REMHEADCTL_CLKDIS; - WREG8(DAC_DATA, tmp); - - /* select PLL Set C */ - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; - WREG8(DAC_DATA, tmp); - - udelay(500); - - /* reset the PLL */ - WREG8(DAC_INDEX, MGA1064_VREF_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~0x04; - WREG8(DAC_DATA, tmp); - - udelay(50); - - /* program pixel pll register */ - WREG_DAC(MGA1064_WB_PIX_PLLC_N, n); - WREG_DAC(MGA1064_WB_PIX_PLLC_M, m); - WREG_DAC(MGA1064_WB_PIX_PLLC_P, p); - - udelay(50); - - /* turn pll on */ - WREG8(DAC_INDEX, MGA1064_VREF_CTL); - tmp = RREG8(DAC_DATA); - tmp |= 0x04; - WREG_DAC(MGA1064_VREF_CTL, tmp); - - udelay(500); - - /* select the pixel pll */ - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; - tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; - WREG8(DAC_DATA, tmp); - - /* reset dotclock rate bit */ - WREG8(MGAREG_SEQ_INDEX, 1); - tmp = RREG8(MGAREG_SEQ_DATA); - tmp &= ~0x8; - WREG8(MGAREG_SEQ_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - vcount = RREG8(MGAREG_VCOUNT); - - for (j = 0; j < 30 && pll_locked == false; j++) { - tmpcount = RREG8(MGAREG_VCOUNT); - if (tmpcount < vcount) - vcount = 0; - if ((tmpcount - vcount) > 2) - pll_locked = true; - else - udelay(5); - } - } - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_REMHEADCTL_CLKDIS; - WREG_DAC(MGA1064_REMHEADCTL, tmp); - return 0; -} - -static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) -{ - unsigned int vcomax, vcomin, pllreffreq; - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n; - unsigned int computed; - u8 tmp; - - m = n = p = 0; - vcomax = 550000; - vcomin = 150000; - pllreffreq = 50000; - - delta = 0xffffffff; - - for (testp = 16; testp > 0; testp--) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testn = 1; testn < 257; testn++) { - for (testm = 1; testm < 17; testm++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn - 1; - m = testm - 1; - p = testp - 1; - } - } - } - } - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); - tmp = RREG8(DAC_DATA); - WREG8(DAC_DATA, tmp & ~0x40); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - WREG_DAC(MGA1064_EV_PIX_PLLC_M, m); - WREG_DAC(MGA1064_EV_PIX_PLLC_N, n); - WREG_DAC(MGA1064_EV_PIX_PLLC_P, p); - - udelay(50); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); - tmp = RREG8(DAC_DATA); - WREG8(DAC_DATA, tmp | 0x40); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= (0x3 << 2); - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - return 0; -} - -static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) -{ - unsigned int vcomax, vcomin, pllreffreq; - unsigned int delta, tmpdelta; - unsigned int testp, testm, testn; - unsigned int p, m, n; - unsigned int computed; - int i, j, tmpcount, vcount; - u8 tmp; - bool pll_locked = false; - - m = n = p = 0; - - if (mdev->type == G200_EH3) { - vcomax = 3000000; - vcomin = 1500000; - pllreffreq = 25000; - - delta = 0xffffffff; - - testp = 0; - - for (testm = 150; testm >= 6; testm--) { - if (clock * testm > vcomax) - continue; - if (clock * testm < vcomin) - continue; - for (testn = 120; testn >= 60; testn--) { - computed = (pllreffreq * testn) / testm; - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn; - m = testm; - p = testp; - } - if (delta == 0) - break; - } - if (delta == 0) - break; - } - } else { - - vcomax = 800000; - vcomin = 400000; - pllreffreq = 33333; - - delta = 0xffffffff; - - for (testp = 16; testp > 0; testp >>= 1) { - if (clock * testp > vcomax) - continue; - if (clock * testp < vcomin) - continue; - - for (testm = 1; testm < 33; testm++) { - for (testn = 17; testn < 257; testn++) { - computed = (pllreffreq * testn) / - (testm * testp); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - n = testn - 1; - m = (testm - 1); - p = testp - 1; - } - if ((clock * testp) >= 600000) - p |= 0x80; - } - } - } - } - for (i = 0; i <= 32 && pll_locked == false; i++) { - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= 0x3 << 2; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG_DAC(MGA1064_EH_PIX_PLLC_M, m); - WREG_DAC(MGA1064_EH_PIX_PLLC_N, n); - WREG_DAC(MGA1064_EH_PIX_PLLC_P, p); - - udelay(500); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - vcount = RREG8(MGAREG_VCOUNT); - - for (j = 0; j < 30 && pll_locked == false; j++) { - tmpcount = RREG8(MGAREG_VCOUNT); - if (tmpcount < vcount) - vcount = 0; - if ((tmpcount - vcount) > 2) - pll_locked = true; - else - udelay(5); - } - } - - return 0; -} - -static int mga_g200er_set_plls(struct mga_device *mdev, long clock) -{ - static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; - unsigned int vcomax, vcomin, pllreffreq; - unsigned int delta, tmpdelta; - int testr, testn, testm, testo; - unsigned int p, m, n; - unsigned int computed, vco; - int tmp; - - m = n = p = 0; - vcomax = 1488000; - vcomin = 1056000; - pllreffreq = 48000; - - delta = 0xffffffff; - - for (testr = 0; testr < 4; testr++) { - if (delta == 0) - break; - for (testn = 5; testn < 129; testn++) { - if (delta == 0) - break; - for (testm = 3; testm >= 0; testm--) { - if (delta == 0) - break; - for (testo = 5; testo < 33; testo++) { - vco = pllreffreq * (testn + 1) / - (testr + 1); - if (vco < vcomin) - continue; - if (vco > vcomax) - continue; - computed = vco / (m_div_val[testm] * (testo + 1)); - if (computed > clock) - tmpdelta = computed - clock; - else - tmpdelta = clock - computed; - if (tmpdelta < delta) { - delta = tmpdelta; - m = testm | (testo << 3); - n = testn; - p = testr | (testr << 3); - } - } - } - } - } - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; - WREG8(DAC_DATA, tmp); - - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); - tmp = RREG8(DAC_DATA); - tmp |= MGA1064_REMHEADCTL_CLKDIS; - WREG8(DAC_DATA, tmp); - - tmp = RREG8(MGAREG_MEM_MISC_READ); - tmp |= (0x3<<2) | 0xc0; - WREG8(MGAREG_MEM_MISC_WRITE, tmp); - - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); - tmp = RREG8(DAC_DATA); - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; - WREG8(DAC_DATA, tmp); - - udelay(500); - - WREG_DAC(MGA1064_ER_PIX_PLLC_N, n); - WREG_DAC(MGA1064_ER_PIX_PLLC_M, m); - WREG_DAC(MGA1064_ER_PIX_PLLC_P, p); - - udelay(50); - - return 0; -} - -static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock) -{ - u8 misc; - - switch(mdev->type) { - case G200_PCI: - case G200_AGP: - return mgag200_g200_set_plls(mdev, clock); - case G200_SE_A: - case G200_SE_B: - return mga_g200se_set_plls(mdev, clock); - case G200_WB: - case G200_EW3: - return mga_g200wb_set_plls(mdev, clock); - case G200_EV: - return mga_g200ev_set_plls(mdev, clock); - case G200_EH: - case G200_EH3: - return mga_g200eh_set_plls(mdev, clock); - case G200_ER: - return mga_g200er_set_plls(mdev, clock); - } - - misc = RREG8(MGA_MISC_IN); - misc &= ~MGAREG_MISC_CLK_SEL_MASK; - misc |= MGAREG_MISC_CLK_SEL_MGA_MSK; - WREG8(MGA_MISC_OUT, misc); - - return 0; -} - static void mgag200_g200wb_hold_bmc(struct mga_device *mdev) { u8 tmp; @@ -1570,7 +864,9 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc *crtc = &pipe->crtc; struct drm_device *dev = crtc->dev; struct mga_device *mdev = to_mga_device(dev); + struct mgag200_pll *pixpll = &mdev->pixpll; struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); struct drm_framebuffer *fb = plane_state->fb; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_rect fullscreen = { @@ -1585,7 +881,8 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, mgag200_set_format_regs(mdev, fb); mgag200_set_mode_regs(mdev, adjusted_mode); - mgag200_crtc_set_plls(mdev, adjusted_mode->clock); + + pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc); if (mdev->type == G200_ER) mgag200_g200er_reset_tagfifo(mdev); @@ -1601,7 +898,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, mga_crtc_load_lut(crtc); mgag200_enable_display(mdev); - mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->map[0]); + mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]); } static void @@ -1619,8 +916,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state) { struct drm_plane *plane = plane_state->plane; + struct drm_device *dev = plane->dev; + struct mga_device *mdev = to_mga_device(dev); + struct mgag200_pll *pixpll = &mdev->pixpll; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); struct drm_framebuffer *new_fb = plane_state->fb; struct drm_framebuffer *fb = NULL; + int ret; if (!new_fb) return 0; @@ -1631,6 +933,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, if (!fb || (fb->format != new_fb->format)) crtc_state->mode_changed = true; /* update PLL settings */ + if (crtc_state->mode_changed) { + ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock, + &mgag200_crtc_state->pixpllc); + if (ret) + return ret; + } + return 0; } @@ -1650,7 +959,54 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, return; if (drm_atomic_helper_damage_merged(old_state, state, &damage)) - mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->map[0]); + mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]); +} + +static struct drm_crtc_state * +mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct drm_crtc_state *crtc_state = crtc->state; + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + struct mgag200_crtc_state *new_mgag200_crtc_state; + + if (!crtc_state) + return NULL; + + new_mgag200_crtc_state = kzalloc(sizeof(*new_mgag200_crtc_state), GFP_KERNEL); + if (!new_mgag200_crtc_state) + return NULL; + __drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base); + + memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc, + sizeof(new_mgag200_crtc_state->pixpllc)); + + return &new_mgag200_crtc_state->base; +} + +static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state) +{ + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); + + __drm_atomic_helper_crtc_destroy_state(&mgag200_crtc_state->base); + kfree(mgag200_crtc_state); +} + +static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct mgag200_crtc_state *mgag200_crtc_state; + + if (crtc->state) { + mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state); + crtc->state = NULL; /* must be set to NULL here */ + } + + mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL); + if (!mgag200_crtc_state) + return; + __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base); } static const struct drm_simple_display_pipe_funcs @@ -1660,6 +1016,9 @@ mgag200_simple_display_pipe_funcs = { .disable = mgag200_simple_display_pipe_disable, .check = mgag200_simple_display_pipe_check, .update = mgag200_simple_display_pipe_update, + .reset_crtc = mgag200_simple_display_pipe_reset_crtc, + .duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state, + .destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state, DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, }; @@ -1726,6 +1085,10 @@ int mgag200_modeset_init(struct mga_device *mdev) return ret; } + ret = mgag200_pixpll_init(&mdev->pixpll, mdev); + if (ret) + return ret; + ret = drm_simple_display_pipe_init(dev, pipe, &mgag200_simple_display_pipe_funcs, mgag200_simple_display_pipe_formats, diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c new file mode 100644 index 000000000000..7c903cf19c0d --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_pll.c @@ -0,0 +1,992 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include + +#include "mgag200_drv.h" + +/* + * G200 + */ + +static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + struct mga_device *mdev = pixpll->mdev; + struct drm_device *dev = &mdev->base; + const int post_div_max = 7; + const int in_div_min = 1; + const int in_div_max = 6; + const int feed_div_min = 7; + const int feed_div_max = 127; + u8 testp, testm, testn; + u8 n = 0, m = 0, p, s; + long f_vco; + long computed; + long delta, tmp_delta; + long ref_clk = mdev->model.g200.ref_clk; + long p_clk_min = mdev->model.g200.pclk_min; + long p_clk_max = mdev->model.g200.pclk_max; + + if (clock > p_clk_max) { + drm_err(dev, "Pixel Clock %ld too high\n", clock); + return -EINVAL; + } + + if (clock < p_clk_min >> 3) + clock = p_clk_min >> 3; + + f_vco = clock; + for (testp = 0; + testp <= post_div_max && f_vco < p_clk_min; + testp = (testp << 1) + 1, f_vco <<= 1) + ; + p = testp + 1; + + delta = clock; + + for (testm = in_div_min; testm <= in_div_max; testm++) { + for (testn = feed_div_min; testn <= feed_div_max; testn++) { + computed = ref_clk * (testn + 1) / (testm + 1); + if (computed < f_vco) + tmp_delta = f_vco - computed; + else + tmp_delta = computed - f_vco; + if (tmp_delta < delta) { + delta = tmp_delta; + m = testm + 1; + n = testn + 1; + } + } + } + f_vco = ref_clk * n / m; + if (f_vco < 100000) + s = 0; + else if (f_vco < 140000) + s = 1; + else if (f_vco < 180000) + s = 2; + else + s = 3; + + drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", + clock, f_vco, m, n, p, s); + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void +mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) +{ + struct mga_device *mdev = pixpll->mdev; + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = { + .compute = mgag200_pixpll_compute_g200, + .update = mgag200_pixpll_update_g200, +}; + +/* + * G200SE + */ + +static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 320000; + static const unsigned int vcomin = 160000; + static const unsigned int pllreffreq = 25000; + + unsigned int delta, tmpdelta, permitteddelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + permitteddelta = clock * 5 / 1000; + + for (testp = 8; testp > 0; testp /= 2) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testn = 17; testn < 256; testn++) { + for (testm = 1; testm < 32; testm++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm; + n = testn; + p = testp; + } + } + } + } + + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll, + const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + struct mga_device *mdev = pixpll->mdev; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); +} + +static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 1600000; + static const unsigned int vcomin = 800000; + static const unsigned int pllreffreq = 25000; + static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; + + unsigned int delta, tmpdelta, permitteddelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + unsigned int fvv; + unsigned int i; + + m = n = p = s = 0; + delta = 0xffffffff; + + if (clock < 25000) + clock = 25000; + clock = clock * 2; + + /* Permited delta is 0.5% as VESA Specification */ + permitteddelta = clock * 5 / 1000; + + for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) { + testp = pvalues_e4[i]; + + if ((clock * testp) > vcomax) + continue; + if ((clock * testp) < vcomin) + continue; + + for (testn = 50; testn <= 256; testn++) { + for (testm = 1; testm <= 32; testm++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm; + n = testn; + p = testp; + } + } + } + } + + fvv = pllreffreq * n / m; + fvv = (fvv - 800000) / 50000; + if (fvv > 15) + fvv = 15; + s = fvv << 1; + + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll, + const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp; + struct mga_device *mdev = pixpll->mdev; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); + + WREG_DAC(0x1a, 0x09); + msleep(20); + WREG_DAC(0x1a, 0x01); +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = { + .compute = mgag200_pixpll_compute_g200se_00, + .update = mgag200_pixpll_update_g200se_00, +}; + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = { + .compute = mgag200_pixpll_compute_g200se_04, + .update = mgag200_pixpll_update_g200se_04, +}; + +/* + * G200WB + */ + +static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 550000; + static const unsigned int vcomin = 150000; + static const unsigned int pllreffreq = 48000; + + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 1; testp < 9; testp++) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testm = 1; testm < 17; testm++) { + for (testn = 1; testn < 151; testn++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + s = 0; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void +mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + int i, j, tmpcount, vcount; + struct mga_device *mdev = pixpll->mdev; + bool pll_locked = false; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + for (i = 0; i <= 32 && pll_locked == false; i++) { + if (i > 0) { + WREG8(MGAREG_CRTC_INDEX, 0x1e); + tmp = RREG8(MGAREG_CRTC_DATA); + if (tmp < 0xff) + WREG8(MGAREG_CRTC_DATA, tmp+1); + } + + /* set pixclkdis to 1 */ + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_REMHEADCTL_CLKDIS; + WREG8(DAC_DATA, tmp); + + /* select PLL Set C */ + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; + WREG8(DAC_DATA, tmp); + + udelay(500); + + /* reset the PLL */ + WREG8(DAC_INDEX, MGA1064_VREF_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~0x04; + WREG8(DAC_DATA, tmp); + + udelay(50); + + /* program pixel pll register */ + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); + + udelay(50); + + /* turn pll on */ + WREG8(DAC_INDEX, MGA1064_VREF_CTL); + tmp = RREG8(DAC_DATA); + tmp |= 0x04; + WREG_DAC(MGA1064_VREF_CTL, tmp); + + udelay(500); + + /* select the pixel pll */ + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; + tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; + WREG8(DAC_DATA, tmp); + + /* reset dotclock rate bit */ + WREG8(MGAREG_SEQ_INDEX, 1); + tmp = RREG8(MGAREG_SEQ_DATA); + tmp &= ~0x8; + WREG8(MGAREG_SEQ_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + vcount = RREG8(MGAREG_VCOUNT); + + for (j = 0; j < 30 && pll_locked == false; j++) { + tmpcount = RREG8(MGAREG_VCOUNT); + if (tmpcount < vcount) + vcount = 0; + if ((tmpcount - vcount) > 2) + pll_locked = true; + else + udelay(5); + } + } + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_REMHEADCTL_CLKDIS; + WREG_DAC(MGA1064_REMHEADCTL, tmp); +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = { + .compute = mgag200_pixpll_compute_g200wb, + .update = mgag200_pixpll_update_g200wb, +}; + +/* + * G200EV + */ + +static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 550000; + static const unsigned int vcomin = 150000; + static const unsigned int pllreffreq = 50000; + + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 16; testp > 0; testp--) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testn = 1; testn < 257; testn++) { + for (testm = 1; testm < 17; testm++) { + computed = (pllreffreq * testn) / + (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void +mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + struct mga_device *mdev = pixpll->mdev; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); + tmp = RREG8(DAC_DATA); + WREG8(DAC_DATA, tmp & ~0x40); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp); + + udelay(50); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); + tmp = RREG8(DAC_DATA); + WREG8(DAC_DATA, tmp | 0x40); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= (0x3 << 2); + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = { + .compute = mgag200_pixpll_compute_g200ev, + .update = mgag200_pixpll_update_g200ev, +}; + +/* + * G200EH + */ + +static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 800000; + static const unsigned int vcomin = 400000; + static const unsigned int pllreffreq = 33333; + + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 16; testp > 0; testp >>= 1) { + if (clock * testp > vcomax) + continue; + if (clock * testp < vcomin) + continue; + + for (testm = 1; testm < 33; testm++) { + for (testn = 17; testn < 257; testn++) { + computed = (pllreffreq * testn) / (testm * testp); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn; + m = testm; + p = testp; + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void +mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + int i, j, tmpcount, vcount; + struct mga_device *mdev = pixpll->mdev; + bool pll_locked = false; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + for (i = 0; i <= 32 && pll_locked == false; i++) { + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= 0x3 << 2; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp); + + udelay(500); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + vcount = RREG8(MGAREG_VCOUNT); + + for (j = 0; j < 30 && pll_locked == false; j++) { + tmpcount = RREG8(MGAREG_VCOUNT); + if (tmpcount < vcount) + vcount = 0; + if ((tmpcount - vcount) > 2) + pll_locked = true; + else + udelay(5); + } + } +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = { + .compute = mgag200_pixpll_compute_g200eh, + .update = mgag200_pixpll_update_g200eh, +}; + +/* + * G200EH3 + */ + +static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 3000000; + static const unsigned int vcomin = 1500000; + static const unsigned int pllreffreq = 25000; + + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + testp = 0; + + for (testm = 150; testm >= 6; testm--) { + if (clock * testm > vcomax) + continue; + if (clock * testm < vcomin) + continue; + for (testn = 120; testn >= 60; testn--) { + computed = (pllreffreq * testn) / testm; + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + n = testn + 1; + m = testm + 1; + p = testp + 1; + } + if (delta == 0) + break; + } + if (delta == 0) + break; + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = { + .compute = mgag200_pixpll_compute_g200eh3, + .update = mgag200_pixpll_update_g200eh, // same as G200EH +}; + +/* + * G200ER + */ + +static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 1488000; + static const unsigned int vcomin = 1056000; + static const unsigned int pllreffreq = 48000; + static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; + + unsigned int delta, tmpdelta; + int testr, testn, testm, testo; + unsigned int p, m, n, s; + unsigned int computed, vco; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testr = 0; testr < 4; testr++) { + if (delta == 0) + break; + for (testn = 5; testn < 129; testn++) { + if (delta == 0) + break; + for (testm = 3; testm >= 0; testm--) { + if (delta == 0) + break; + for (testo = 5; testo < 33; testo++) { + vco = pllreffreq * (testn + 1) / + (testr + 1); + if (vco < vcomin) + continue; + if (vco > vcomax) + continue; + computed = vco / (m_div_val[testm] * (testo + 1)); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = (testm | (testo << 3)) + 1; + n = testn + 1; + p = testr + 1; + s = testr; + } + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static void +mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) +{ + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; + struct mga_device *mdev = pixpll->mdev; + + pixpllcm = pixpllc->m - 1; + pixpllcn = pixpllc->n - 1; + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + + xpixpllcm = pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; + WREG8(DAC_DATA, tmp); + + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); + tmp = RREG8(DAC_DATA); + tmp |= MGA1064_REMHEADCTL_CLKDIS; + WREG8(DAC_DATA, tmp); + + tmp = RREG8(MGAREG_MEM_MISC_READ); + tmp |= (0x3<<2) | 0xc0; + WREG8(MGAREG_MEM_MISC_WRITE, tmp); + + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); + tmp = RREG8(DAC_DATA); + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; + WREG8(DAC_DATA, tmp); + + udelay(500); + + WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); + WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); + WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); + + udelay(50); +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = { + .compute = mgag200_pixpll_compute_g200er, + .update = mgag200_pixpll_update_g200er, +}; + +/* + * G200EW3 + */ + +static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock, + struct mgag200_pll_values *pixpllc) +{ + static const unsigned int vcomax = 800000; + static const unsigned int vcomin = 400000; + static const unsigned int pllreffreq = 25000; + + unsigned int delta, tmpdelta; + unsigned int testp, testm, testn, testp2; + unsigned int p, m, n, s; + unsigned int computed; + + m = n = p = s = 0; + delta = 0xffffffff; + + for (testp = 1; testp < 8; testp++) { + for (testp2 = 1; testp2 < 8; testp2++) { + if (testp < testp2) + continue; + if ((clock * testp * testp2) > vcomax) + continue; + if ((clock * testp * testp2) < vcomin) + continue; + for (testm = 1; testm < 26; testm++) { + for (testn = 32; testn < 2048 ; testn++) { + computed = (pllreffreq * testn) / (testm * testp * testp2); + if (computed > clock) + tmpdelta = computed - clock; + else + tmpdelta = clock - computed; + if (tmpdelta < delta) { + delta = tmpdelta; + m = testm + 1; + n = testn + 1; + p = testp + 1; + s = testp2; + } + } + } + } + } + + pixpllc->m = m; + pixpllc->n = n; + pixpllc->p = p; + pixpllc->s = s; + + return 0; +} + +static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = { + .compute = mgag200_pixpll_compute_g200ew3, + .update = mgag200_pixpll_update_g200wb, // same as G200WB +}; + +/* + * PLL initialization + */ + +int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + + pixpll->mdev = mdev; + + switch (mdev->type) { + case G200_PCI: + case G200_AGP: + pixpll->funcs = &mgag200_pixpll_funcs_g200; + break; + case G200_SE_A: + case G200_SE_B: + if (mdev->model.g200se.unique_rev_id >= 0x04) + pixpll->funcs = &mgag200_pixpll_funcs_g200se_04; + else + pixpll->funcs = &mgag200_pixpll_funcs_g200se_00; + break; + case G200_WB: + pixpll->funcs = &mgag200_pixpll_funcs_g200wb; + break; + case G200_EV: + pixpll->funcs = &mgag200_pixpll_funcs_g200ev; + break; + case G200_EH: + pixpll->funcs = &mgag200_pixpll_funcs_g200eh; + break; + case G200_EH3: + pixpll->funcs = &mgag200_pixpll_funcs_g200eh3; + break; + case G200_ER: + pixpll->funcs = &mgag200_pixpll_funcs_g200er; + break; + case G200_EW3: + pixpll->funcs = &mgag200_pixpll_funcs_g200ew3; + break; + default: + drm_err(dev, "unknown device type %d\n", mdev->type); + return -ENODEV; + } + + return 0; +} diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index 977be0565c06..60e705283fe8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -222,11 +222,10 @@ #define MGAREG_MISC_IOADSEL (0x1 << 0) #define MGAREG_MISC_RAMMAPEN (0x1 << 1) -#define MGAREG_MISC_CLK_SEL_MASK GENMASK(3, 2) -#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2) -#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2) -#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2) -#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2) +#define MGAREG_MISC_CLKSEL_MASK GENMASK(3, 2) +#define MGAREG_MISC_CLKSEL_VGA25 (0x0 << 2) +#define MGAREG_MISC_CLKSEL_VGA28 (0x1 << 2) +#define MGAREG_MISC_CLKSEL_MGA (0x3 << 2) #define MGAREG_MISC_VIDEO_DIS (0x1 << 4) #define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5) #define MGAREG_MISC_HSYNCPOL BIT(6) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1594ae39d54f..a332b09a5a11 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -201,6 +200,71 @@ void msm_rmw(void __iomem *addr, u32 mask, u32 or) msm_writel(val | or, addr); } +static irqreturn_t msm_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + return kms->funcs->irq(kms); +} + +static void msm_irq_preinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + kms->funcs->irq_preinstall(kms); +} + +static int msm_irq_postinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + if (kms->funcs->irq_postinstall) + return kms->funcs->irq_postinstall(kms); + + return 0; +} + +static int msm_irq_install(struct drm_device *dev, unsigned int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + msm_irq_preinstall(dev); + + ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev); + if (ret) + return ret; + + ret = msm_irq_postinstall(dev); + if (ret) { + free_irq(irq, dev); + return ret; + } + + return 0; +} + +static void msm_irq_uninstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + kms->funcs->irq_uninstall(kms); + free_irq(kms->irq, dev); +} + struct msm_vblank_work { struct work_struct work; int crtc_id; @@ -265,7 +329,7 @@ static int msm_drm_uninit(struct device *dev) } /* We must cancel and cleanup any pending vblank enable/disable - * work before drm_irq_uninstall() to avoid work re-enabling an + * work before msm_irq_uninstall() to avoid work re-enabling an * irq after uninstall has disabled it. */ @@ -294,7 +358,7 @@ static int msm_drm_uninit(struct device *dev) drm_mode_config_cleanup(ddev); pm_runtime_get_sync(dev); - drm_irq_uninstall(ddev); + msm_irq_uninstall(ddev); pm_runtime_put_sync(dev); if (kms && kms->funcs) @@ -553,7 +617,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (kms) { pm_runtime_get_sync(dev); - ret = drm_irq_install(ddev, kms->irq); + ret = msm_irq_install(ddev, kms->irq); pm_runtime_put_sync(dev); if (ret < 0) { DRM_DEV_ERROR(dev, "failed to install IRQ handler\n"); @@ -662,43 +726,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) context_close(ctx); } -static irqreturn_t msm_irq(int irq, void *arg) -{ - struct drm_device *dev = arg; - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - return kms->funcs->irq(kms); -} - -static void msm_irq_preinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - kms->funcs->irq_preinstall(kms); -} - -static int msm_irq_postinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - - if (kms->funcs->irq_postinstall) - return kms->funcs->irq_postinstall(kms); - - return 0; -} - -static void msm_irq_uninstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - kms->funcs->irq_uninstall(kms); -} - int msm_crtc_enable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -1051,10 +1078,6 @@ static const struct drm_driver msm_driver = { .open = msm_open, .postclose = msm_postclose, .lastclose = drm_fb_helper_lastclose, - .irq_handler = msm_irq, - .irq_preinstall = msm_irq_preinstall, - .irq_postinstall = msm_irq_postinstall, - .irq_uninstall = msm_irq_uninstall, .dumb_create = msm_gem_dumb_create, .dumb_map_offset = msm_gem_dumb_map_offset, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 086a2d59b8c8..9de7c42e1071 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -150,7 +150,7 @@ struct msm_kms { const struct msm_kms_funcs *funcs; struct drm_device *dev; - /* irq number to be passed on to drm_irq_install */ + /* irq number to be passed on to msm_irq_install */ int irq; /* mapper-id used to request GEM buffer mapped for scanout: */ diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index c277d3f61a5e..ec0432fe1bdf 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -153,6 +152,49 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb) return 0; } +static irqreturn_t mxsfb_irq_handler(int irq, void *data) +{ + struct drm_device *drm = data; + struct mxsfb_drm_private *mxsfb = drm->dev_private; + u32 reg; + + reg = readl(mxsfb->base + LCDC_CTRL1); + + if (reg & CTRL1_CUR_FRAME_DONE_IRQ) + drm_crtc_handle_vblank(&mxsfb->crtc); + + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); + + return IRQ_HANDLED; +} + +static void mxsfb_irq_disable(struct drm_device *drm) +{ + struct mxsfb_drm_private *mxsfb = drm->dev_private; + + mxsfb_enable_axi_clk(mxsfb); + mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc); + mxsfb_disable_axi_clk(mxsfb); +} + +static int mxsfb_irq_install(struct drm_device *dev, int irq) +{ + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + mxsfb_irq_disable(dev); + + return request_irq(irq, mxsfb_irq_handler, 0, dev->driver->name, dev); +} + +static void mxsfb_irq_uninstall(struct drm_device *dev) +{ + struct mxsfb_drm_private *mxsfb = dev->dev_private; + + mxsfb_irq_disable(dev); + free_irq(mxsfb->irq, dev); +} + static int mxsfb_load(struct drm_device *drm, const struct mxsfb_devdata *devdata) { @@ -226,8 +268,13 @@ static int mxsfb_load(struct drm_device *drm, drm_mode_config_reset(drm); + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto err_vblank; + mxsfb->irq = ret; + pm_runtime_get_sync(drm->dev); - ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); + ret = mxsfb_irq_install(drm, mxsfb->irq); pm_runtime_put_sync(drm->dev); if (ret < 0) { @@ -255,7 +302,7 @@ static void mxsfb_unload(struct drm_device *drm) drm_mode_config_cleanup(drm); pm_runtime_get_sync(drm->dev); - drm_irq_uninstall(drm); + mxsfb_irq_uninstall(drm); pm_runtime_put_sync(drm->dev); drm->dev_private = NULL; @@ -263,38 +310,10 @@ static void mxsfb_unload(struct drm_device *drm) pm_runtime_disable(drm->dev); } -static void mxsfb_irq_disable(struct drm_device *drm) -{ - struct mxsfb_drm_private *mxsfb = drm->dev_private; - - mxsfb_enable_axi_clk(mxsfb); - mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc); - mxsfb_disable_axi_clk(mxsfb); -} - -static irqreturn_t mxsfb_irq_handler(int irq, void *data) -{ - struct drm_device *drm = data; - struct mxsfb_drm_private *mxsfb = drm->dev_private; - u32 reg; - - reg = readl(mxsfb->base + LCDC_CTRL1); - - if (reg & CTRL1_CUR_FRAME_DONE_IRQ) - drm_crtc_handle_vblank(&mxsfb->crtc); - - writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); - - return IRQ_HANDLED; -} - DEFINE_DRM_GEM_CMA_FOPS(fops); static const struct drm_driver mxsfb_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .irq_handler = mxsfb_irq_handler, - .irq_preinstall = mxsfb_irq_disable, - .irq_uninstall = mxsfb_irq_disable, DRM_GEM_CMA_DRIVER_OPS, .fops = &fops, .name = "mxsfb-drm", diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index 7c720e226fdf..ddb5b0417a82 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -33,6 +33,8 @@ struct mxsfb_drm_private { struct clk *clk_axi; struct clk *clk_disp_axi; + unsigned int irq; + struct drm_device *drm; struct { struct drm_plane primary; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 093e1f7163b3..bb5d1cacd97e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1659,23 +1659,27 @@ static void nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); struct nouveau_connector *nv_connector = nv50_outp_get_old_connector(state, nv_encoder); +#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nouveau_backlight *backlight = nv_connector->backlight; +#endif struct drm_dp_aux *aux = &nv_connector->aux; int ret; u8 pwr; +#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT if (backlight && backlight->uses_dpcd) { ret = drm_edp_backlight_disable(aux, &backlight->edp_info); if (ret < 0) NV_ERROR(drm, "Failed to disable backlight on [CONNECTOR:%d:%s]: %d\n", nv_connector->base.base.id, nv_connector->base.name, ret); } +#endif if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { - int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr); + ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr); if (ret == 0) { pwr &= ~DP_SET_POWER_MASK; diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 8e021b57875d..0e4f3cac0fef 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3126,6 +3126,38 @@ static const struct panel_desc logictechno_lt170410_2whc = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct drm_display_mode logictechno_lttd800480070_l6wh_rt_mode = { + .clock = 33000, + .hdisplay = 800, + .hsync_start = 800 + 154, + .hsync_end = 800 + 154 + 3, + .htotal = 800 + 154 + 3 + 43, + .vdisplay = 480, + .vsync_start = 480 + 47, + .vsync_end = 480 + 47 + 3, + .vtotal = 480 + 47 + 3 + 20, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc logictechno_lttd800480070_l6wh_rt = { + .modes = &logictechno_lttd800480070_l6wh_rt_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 154, + .height = 86, + }, + .delay = { + .prepare = 45, + .enable = 100, + .disable = 100, + .unprepare = 45 + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE, + .connector_type = DRM_MODE_CONNECTOR_DPI, +}; + static const struct drm_display_mode mitsubishi_aa070mc01_mode = { .clock = 30400, .hdisplay = 800, @@ -3192,6 +3224,37 @@ static const struct panel_desc mitsubishi_aa070mc01 = { .bus_flags = DRM_BUS_FLAG_DE_HIGH, }; +static const struct display_timing multi_inno_mi1010ait_1cp_timing = { + .pixelclock = { 68900000, 70000000, 73400000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 30, 60, 71 }, + .hback_porch = { 30, 60, 71 }, + .hsync_len = { 10, 10, 48 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 5, 10, 10 }, + .vback_porch = { 5, 10, 10 }, + .vsync_len = { 5, 6, 13 }, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | + DISPLAY_FLAGS_DE_HIGH, +}; + +static const struct panel_desc multi_inno_mi1010ait_1cp = { + .timings = &multi_inno_mi1010ait_1cp_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 217, + .height = 136, + }, + .delay = { + .enable = 50, + .disable = 50, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct display_timing nec_nl12880bc20_05_timing = { .pixelclock = { 67000000, 71000000, 75000000 }, .hactive = { 1280, 1280, 1280 }, @@ -4675,9 +4738,15 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "logictechno,lt170410-2whc", .data = &logictechno_lt170410_2whc, + }, { + .compatible = "logictechno,lttd800480070-l6wh-rt", + .data = &logictechno_lttd800480070_l6wh_rt, }, { .compatible = "mitsubishi,aa070mc01-ca1", .data = &mitsubishi_aa070mc01, + }, { + .compatible = "multi-inno,mi1010ait-1cp", + .data = &multi_inno_mi1010ait_1cp, }, { .compatible = "nec,nl12880bc20-05", .data = &nec_nl12880bc20_05, diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index 2a2933c16308..c04d84a69dd2 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include @@ -603,7 +602,7 @@ int r128_do_cleanup_cce(struct drm_device *dev) * is freed, it's too late. */ if (dev->irq_enabled) - drm_irq_uninstall(dev); + drm_legacy_irq_uninstall(dev); if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c8dd68152d65..b74cebca1f89 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -607,10 +607,6 @@ static const struct drm_driver kms_driver = { .postclose = radeon_driver_postclose_kms, .lastclose = radeon_driver_lastclose_kms, .unload = radeon_driver_unload_kms, - .irq_preinstall = radeon_driver_irq_preinstall_kms, - .irq_postinstall = radeon_driver_irq_postinstall_kms, - .irq_uninstall = radeon_driver_irq_uninstall_kms, - .irq_handler = radeon_driver_irq_handler_kms, .ioctls = radeon_ioctls_kms, .num_ioctls = ARRAY_SIZE(radeon_ioctls_kms), .dumb_create = radeon_mode_dumb_create, diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index a36ce826d0c0..3907785d0798 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include @@ -51,7 +51,7 @@ * radeon_irq_process is a macro that points to the per-asic * irq handler callback. */ -irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg) +static irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct radeon_device *rdev = dev->dev_private; @@ -118,7 +118,7 @@ static void radeon_dp_work_func(struct work_struct *work) * Gets the hw ready to enable irqs (all asics). * This function disables all interrupt sources on the GPU. */ -void radeon_driver_irq_preinstall_kms(struct drm_device *dev) +static void radeon_driver_irq_preinstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; unsigned long irqflags; @@ -150,7 +150,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) * Handles stuff to be done after enabling irqs (all asics). * Returns 0 on success. */ -int radeon_driver_irq_postinstall_kms(struct drm_device *dev) +static int radeon_driver_irq_postinstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -169,7 +169,7 @@ int radeon_driver_irq_postinstall_kms(struct drm_device *dev) * * This function disables all interrupt sources on the GPU (all asics). */ -void radeon_driver_irq_uninstall_kms(struct drm_device *dev) +static void radeon_driver_irq_uninstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; unsigned long irqflags; @@ -194,6 +194,36 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } +static int radeon_irq_install(struct radeon_device *rdev, int irq) +{ + struct drm_device *dev = rdev->ddev; + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + radeon_driver_irq_preinstall_kms(dev); + + /* PCI devices require shared interrupts. */ + ret = request_irq(irq, radeon_driver_irq_handler_kms, + IRQF_SHARED, dev->driver->name, dev); + if (ret) + return ret; + + radeon_driver_irq_postinstall_kms(dev); + + return 0; +} + +static void radeon_irq_uninstall(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + + radeon_driver_irq_uninstall_kms(dev); + free_irq(pdev->irq, dev); +} + /** * radeon_msi_ok - asic specific msi checks * @@ -314,7 +344,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); rdev->irq.installed = true; - r = drm_irq_install(rdev->ddev, rdev->pdev->irq); + r = radeon_irq_install(rdev, rdev->pdev->irq); if (r) { rdev->irq.installed = false; flush_delayed_work(&rdev->hotplug_work); @@ -335,7 +365,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) void radeon_irq_kms_fini(struct radeon_device *rdev) { if (rdev->irq.installed) { - drm_irq_uninstall(rdev->ddev); + radeon_irq_uninstall(rdev); rdev->irq.installed = false; if (rdev->msi_enabled) pci_disable_msi(rdev->pdev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.h b/drivers/gpu/drm/radeon/radeon_kms.h index 9b97bf38acd4..36e73cea9215 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.h +++ b/drivers/gpu/drm/radeon/radeon_kms.h @@ -31,9 +31,5 @@ u32 radeon_get_vblank_counter_kms(struct drm_crtc *crtc); int radeon_enable_vblank_kms(struct drm_crtc *crtc); void radeon_disable_vblank_kms(struct drm_crtc *crtc); -irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg); -void radeon_driver_irq_preinstall_kms(struct drm_device *dev); -int radeon_driver_irq_postinstall_kms(struct drm_device *dev); -void radeon_driver_irq_uninstall_kms(struct drm_device *dev); #endif /* __RADEON_KMS_H__ */ diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c index 66e3c86eb5c7..d620f35688da 100644 --- a/drivers/gpu/drm/tidss/tidss_drv.c +++ b/drivers/gpu/drm/tidss/tidss_drv.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -118,11 +117,6 @@ static const struct drm_driver tidss_driver = { .date = "20180215", .major = 1, .minor = 0, - - .irq_preinstall = tidss_irq_preinstall, - .irq_postinstall = tidss_irq_postinstall, - .irq_handler = tidss_irq_handler, - .irq_uninstall = tidss_irq_uninstall, }; static int tidss_probe(struct platform_device *pdev) @@ -172,10 +166,11 @@ static int tidss_probe(struct platform_device *pdev) ret = irq; goto err_runtime_suspend; } + tidss->irq = irq; - ret = drm_irq_install(ddev, irq); + ret = tidss_irq_install(ddev, irq); if (ret) { - dev_err(dev, "drm_irq_install failed: %d\n", ret); + dev_err(dev, "tidss_irq_install failed: %d\n", ret); goto err_runtime_suspend; } @@ -196,7 +191,7 @@ static int tidss_probe(struct platform_device *pdev) return 0; err_irq_uninstall: - drm_irq_uninstall(ddev); + tidss_irq_uninstall(ddev); err_runtime_suspend: #ifndef CONFIG_PM @@ -219,7 +214,7 @@ static int tidss_remove(struct platform_device *pdev) drm_atomic_helper_shutdown(ddev); - drm_irq_uninstall(ddev); + tidss_irq_uninstall(ddev); #ifndef CONFIG_PM /* If we don't have PM, we need to call suspend manually */ diff --git a/drivers/gpu/drm/tidss/tidss_drv.h b/drivers/gpu/drm/tidss/tidss_drv.h index 7de4bba52e6f..d7f27b0b0315 100644 --- a/drivers/gpu/drm/tidss/tidss_drv.h +++ b/drivers/gpu/drm/tidss/tidss_drv.h @@ -27,6 +27,8 @@ struct tidss_device { unsigned int num_planes; struct drm_plane *planes[TIDSS_MAX_PLANES]; + unsigned int irq; + spinlock_t wait_lock; /* protects the irq masks */ dispc_irq_t irq_mask; /* enabled irqs in addition to wait_list */ }; diff --git a/drivers/gpu/drm/tidss/tidss_irq.c b/drivers/gpu/drm/tidss/tidss_irq.c index 2ed3e3296776..0c681c7600bc 100644 --- a/drivers/gpu/drm/tidss/tidss_irq.c +++ b/drivers/gpu/drm/tidss/tidss_irq.c @@ -4,6 +4,9 @@ * Author: Tomi Valkeinen */ +#include + +#include #include #include "tidss_crtc.h" @@ -50,7 +53,7 @@ void tidss_irq_disable_vblank(struct drm_crtc *crtc) spin_unlock_irqrestore(&tidss->wait_lock, flags); } -irqreturn_t tidss_irq_handler(int irq, void *arg) +static irqreturn_t tidss_irq_handler(int irq, void *arg) { struct drm_device *ddev = (struct drm_device *)arg; struct tidss_device *tidss = to_tidss(ddev); @@ -90,7 +93,7 @@ void tidss_irq_resume(struct tidss_device *tidss) spin_unlock_irqrestore(&tidss->wait_lock, flags); } -void tidss_irq_preinstall(struct drm_device *ddev) +static void tidss_irq_preinstall(struct drm_device *ddev) { struct tidss_device *tidss = to_tidss(ddev); @@ -104,7 +107,7 @@ void tidss_irq_preinstall(struct drm_device *ddev) tidss_runtime_put(tidss); } -int tidss_irq_postinstall(struct drm_device *ddev) +static void tidss_irq_postinstall(struct drm_device *ddev) { struct tidss_device *tidss = to_tidss(ddev); unsigned long flags; @@ -129,6 +132,22 @@ int tidss_irq_postinstall(struct drm_device *ddev) spin_unlock_irqrestore(&tidss->wait_lock, flags); tidss_runtime_put(tidss); +} + +int tidss_irq_install(struct drm_device *ddev, unsigned int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + tidss_irq_preinstall(ddev); + + ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev); + if (ret) + return ret; + + tidss_irq_postinstall(ddev); return 0; } @@ -140,4 +159,6 @@ void tidss_irq_uninstall(struct drm_device *ddev) tidss_runtime_get(tidss); dispc_set_irqenable(tidss->dispc, 0); tidss_runtime_put(tidss); + + free_irq(tidss->irq, ddev); } diff --git a/drivers/gpu/drm/tidss/tidss_irq.h b/drivers/gpu/drm/tidss/tidss_irq.h index 4aaad5dfd7c2..b512614d5863 100644 --- a/drivers/gpu/drm/tidss/tidss_irq.h +++ b/drivers/gpu/drm/tidss/tidss_irq.h @@ -67,10 +67,8 @@ struct tidss_device; void tidss_irq_enable_vblank(struct drm_crtc *crtc); void tidss_irq_disable_vblank(struct drm_crtc *crtc); -void tidss_irq_preinstall(struct drm_device *ddev); -int tidss_irq_postinstall(struct drm_device *ddev); +int tidss_irq_install(struct drm_device *ddev, unsigned int irq); void tidss_irq_uninstall(struct drm_device *ddev); -irqreturn_t tidss_irq_handler(int irq, void *arg); void tidss_irq_resume(struct tidss_device *tidss); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f1d3a9f919fd..6b03f89a98d4 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -124,6 +123,39 @@ static int cpufreq_transition(struct notifier_block *nb, } #endif +static irqreturn_t tilcdc_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct tilcdc_drm_private *priv = dev->dev_private; + + return tilcdc_crtc_irq(priv->crtc); +} + +static int tilcdc_irq_install(struct drm_device *dev, unsigned int irq) +{ + struct tilcdc_drm_private *priv = dev->dev_private; + int ret; + + ret = request_irq(irq, tilcdc_irq, 0, dev->driver->name, dev); + if (ret) + return ret; + + priv->irq_enabled = false; + + return 0; +} + +static void tilcdc_irq_uninstall(struct drm_device *dev) +{ + struct tilcdc_drm_private *priv = dev->dev_private; + + if (!priv->irq_enabled) + return; + + free_irq(priv->irq, dev); + priv->irq_enabled = false; +} + /* * DRM operations: */ @@ -145,7 +177,7 @@ static void tilcdc_fini(struct drm_device *dev) drm_dev_unregister(dev); drm_kms_helper_poll_fini(dev); - drm_irq_uninstall(dev); + tilcdc_irq_uninstall(dev); drm_mode_config_cleanup(dev); if (priv->clk) @@ -336,7 +368,12 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev) goto init_failed; } - ret = drm_irq_install(ddev, platform_get_irq(pdev, 0)); + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto init_failed; + priv->irq = ret; + + ret = tilcdc_irq_install(ddev, priv->irq); if (ret < 0) { dev_err(dev, "failed to install IRQ handler\n"); goto init_failed; @@ -360,13 +397,6 @@ init_failed: return ret; } -static irqreturn_t tilcdc_irq(int irq, void *arg) -{ - struct drm_device *dev = arg; - struct tilcdc_drm_private *priv = dev->dev_private; - return tilcdc_crtc_irq(priv->crtc); -} - #if defined(CONFIG_DEBUG_FS) static const struct { const char *name; @@ -454,7 +484,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops); static const struct drm_driver tilcdc_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .irq_handler = tilcdc_irq, DRM_GEM_CMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index d29806ca8817..b818448c83f6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -46,6 +46,8 @@ struct tilcdc_drm_private { struct clk *clk; /* functional clock */ int rev; /* IP revision */ + unsigned int irq; + /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; /* @@ -82,6 +84,7 @@ struct tilcdc_drm_private { bool is_registered; bool is_componentized; + bool irq_enabled; }; /* Sub-module for display. Since we don't know at compile time what panels diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index a8b476a59c0d..4611ec408506 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -435,7 +435,7 @@ static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb); - cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->map[0]); + cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->data[0]); } static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe, @@ -451,7 +451,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe, cirrus_mode_set(cirrus, &crtc->mode, state->fb); if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - cirrus_fb_blit_rect(state->fb, &shadow_plane_state->map[0], &rect); + cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect); } static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = { diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index cf7287fccd72..6bc0c298739c 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -554,7 +554,7 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT; - gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->map[0], &rect); + gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect); } static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) @@ -572,7 +572,7 @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_rect rect; if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->map[0], &rect); + gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect); } static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = { diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 08ae66b1e6f5..481b48bde047 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -639,7 +639,7 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_framebuffer *fb = plane_state->fb; - void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */ + void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ struct drm_device *dev = &sdev->dev; int idx; @@ -677,7 +677,7 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev); struct drm_plane_state *plane_state = pipe->plane.state; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */ + void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ struct drm_framebuffer *fb = plane_state->fb; struct drm_device *dev = &sdev->dev; struct drm_rect clip; diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 8a6b94b1511b..32232228dae9 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -379,7 +379,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, udl->mode_buf_len = wrptr - buf; - udl_handle_damage(fb, &shadow_plane_state->map[0], 0, 0, fb->width, fb->height); + udl_handle_damage(fb, &shadow_plane_state->data[0], 0, 0, fb->width, fb->height); if (!crtc_state->mode_changed) return; @@ -422,7 +422,7 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, return; if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect)) - udl_handle_damage(fb, &shadow_plane_state->map[0], rect.x1, rect.y1, + udl_handle_damage(fb, &shadow_plane_state->data[0], rect.x1, rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1); } diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index 972c83b720aa..4227a915b06a 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -398,7 +398,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, u32 height = new_state->crtc_h; struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state); - struct dma_buf_map map = shadow_plane_state->map[0]; + struct dma_buf_map map = shadow_plane_state->data[0]; u8 *src = map.vaddr; /* TODO: Use mapping abstraction properly */ size_t data_size, mask_size; u32 flags; diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 73335feb712f..f6c16c5aee68 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -168,10 +168,6 @@ static struct drm_driver vc4_drm_driver = { DRIVER_SYNCOBJ), .open = vc4_open, .postclose = vc4_close, - .irq_handler = vc4_irq, - .irq_preinstall = vc4_irq_preinstall, - .irq_postinstall = vc4_irq_postinstall, - .irq_uninstall = vc4_irq_uninstall, #if defined(CONFIG_DEBUG_FS) .debugfs_init = vc4_debugfs_init, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 5dceadc61600..ef73e0aaf726 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -74,6 +74,8 @@ struct vc4_perfmon { struct vc4_dev { struct drm_device base; + unsigned int irq; + struct vc4_hvs *hvs; struct vc4_v3d *v3d; struct vc4_dpi *dpi; @@ -895,9 +897,9 @@ extern struct platform_driver vc4_vec_driver; extern struct platform_driver vc4_txp_driver; /* vc4_irq.c */ -irqreturn_t vc4_irq(int irq, void *arg); -void vc4_irq_preinstall(struct drm_device *dev); -int vc4_irq_postinstall(struct drm_device *dev); +void vc4_irq_enable(struct drm_device *dev); +void vc4_irq_disable(struct drm_device *dev); +int vc4_irq_install(struct drm_device *dev, int irq); void vc4_irq_uninstall(struct drm_device *dev); void vc4_irq_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index e226c24e543f..20fa8e34c20b 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -45,6 +45,10 @@ * current job can make progress. */ +#include + +#include + #include "vc4_drv.h" #include "vc4_regs.h" @@ -192,7 +196,7 @@ vc4_irq_finish_render_job(struct drm_device *dev) schedule_work(&vc4->job_done_work); } -irqreturn_t +static irqreturn_t vc4_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -234,8 +238,8 @@ vc4_irq(int irq, void *arg) return status; } -void -vc4_irq_preinstall(struct drm_device *dev) +static void +vc4_irq_prepare(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -251,24 +255,22 @@ vc4_irq_preinstall(struct drm_device *dev) V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); } -int -vc4_irq_postinstall(struct drm_device *dev) +void +vc4_irq_enable(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); if (!vc4->v3d) - return 0; + return; /* Enable the render done interrupts. The out-of-memory interrupt is * enabled as soon as we have a binner BO allocated. */ V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE); - - return 0; } void -vc4_irq_uninstall(struct drm_device *dev) +vc4_irq_disable(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -282,11 +284,37 @@ vc4_irq_uninstall(struct drm_device *dev) V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS); /* Finish any interrupt handler still in flight. */ - disable_irq(dev->irq); + disable_irq(vc4->irq); cancel_work_sync(&vc4->overflow_mem_work); } +int vc4_irq_install(struct drm_device *dev, int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + vc4_irq_prepare(dev); + + ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev); + if (ret) + return ret; + + vc4_irq_enable(dev); + + return 0; +} + +void vc4_irq_uninstall(struct drm_device *dev) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + + vc4_irq_disable(dev); + free_irq(vc4->irq, dev); +} + /** Reinitializes interrupt registers when a GPU reset is performed. */ void vc4_irq_reset(struct drm_device *dev) { diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 73d63d72575b..7bb3067f8425 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -10,8 +10,6 @@ #include #include -#include - #include "vc4_drv.h" #include "vc4_regs.h" @@ -361,7 +359,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev) struct vc4_v3d *v3d = dev_get_drvdata(dev); struct vc4_dev *vc4 = v3d->vc4; - vc4_irq_uninstall(&vc4->base); + vc4_irq_disable(&vc4->base); clk_disable_unprepare(v3d->clk); @@ -381,8 +379,8 @@ static int vc4_v3d_runtime_resume(struct device *dev) vc4_v3d_init_hw(&vc4->base); /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */ - enable_irq(vc4->base.irq); - vc4_irq_postinstall(&vc4->base); + enable_irq(vc4->irq); + vc4_irq_enable(&vc4->base); return 0; } @@ -448,7 +446,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) vc4_v3d_init_hw(drm); - ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + vc4->irq = ret; + + ret = vc4_irq_install(drm, vc4->irq); if (ret) { DRM_ERROR("Failed to install IRQ handler\n"); return ret; @@ -473,7 +476,7 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master, pm_runtime_disable(dev); - drm_irq_uninstall(drm); + vc4_irq_uninstall(drm); /* Disable the binner's overflow memory address, so the next * driver probe (if any) doesn't try to reuse our old diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index dae1bacd86c1..c9afa1a51f23 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -29,7 +29,6 @@ #include #include -#include #include #include "via_drv.h" @@ -86,7 +85,7 @@ int via_final_context(struct drm_device *dev, int context) /* Last context, perform cleanup */ if (list_is_singular(&dev->ctxlist)) { DRM_DEBUG("Last Context\n"); - drm_irq_uninstall(dev); + drm_legacy_irq_uninstall(dev); via_cleanup_futex(dev_priv); via_do_cleanup_map(dev); } diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 807a27a16365..e45dbf14b307 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -98,6 +98,8 @@ struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj, } else { bo->uuid_state = STATE_ERR; } + } else if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)) { + bo->uuid_state = STATE_ERR; } exp_info.ops = &virtgpu_dmabuf_ops.ops; diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 49f109c3a2b3..9e8204be9a14 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -257,7 +257,7 @@ void vkms_composer_worker(struct work_struct *work) return; if (wb_pending) - vaddr_out = crtc_state->active_writeback->map[0].vaddr; + vaddr_out = crtc_state->active_writeback->data[0].vaddr; ret = compose_active_planes(&vaddr_out, primary_composer, crtc_state); diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8bc9e3f52e1f..d48c23d40ce5 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -22,6 +22,7 @@ struct vkms_writeback_job { struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; }; struct vkms_composer { diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 8a56fbf572b0..32409e15244b 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -111,7 +111,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect)); memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect)); memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer)); - memcpy(&composer->map, &shadow_plane_state->map, sizeof(composer->map)); + memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map)); drm_framebuffer_get(&composer->fb); composer->offset = fb->offsets[0]; composer->pitch = fb->pitches[0]; diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 425b6c6b8cad..8694227f555f 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -75,7 +75,7 @@ static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector, if (!vkmsjob) return -ENOMEM; - ret = drm_gem_fb_vmap(job->fb, vkmsjob->map); + ret = drm_gem_fb_vmap(job->fb, vkmsjob->map, vkmsjob->data); if (ret) { DRM_ERROR("vmap failed: %d\n", ret); goto err_kfree; diff --git a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h index 35bd2852189f..1f6e3bbc6605 100644 --- a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h +++ b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h @@ -97,19 +97,18 @@ typedef __attribute__((aligned(32))) struct MKSGuestStatInfoEntry { } MKSGuestStatInfoEntry; #define INVALID_PPN64 ((PPN64)0x000fffffffffffffULL) -#define vmw_num_pages(size) (PAGE_ALIGN(size) >> PAGE_SHIFT) #define MKS_GUEST_STAT_INSTANCE_DESC_LENGTH 1024 #define MKS_GUEST_STAT_INSTANCE_MAX_STATS 4096 -#define MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS \ - (vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ +#define MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS \ + (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ sizeof(MKSGuestStatCounterTime))) -#define MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS \ - (vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ +#define MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS \ + (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ sizeof(MKSGuestStatInfoEntry))) #define MKS_GUEST_STAT_AVERAGE_NAME_LENGTH 40 -#define MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS \ - (vmw_num_pages(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ +#define MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS \ + (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \ MKS_GUEST_STAT_AVERAGE_NAME_LENGTH)) /* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 362f56d5b12b..9e3e1429db94 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -405,7 +405,7 @@ static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size, bool user) { static size_t struct_size, user_struct_size; - size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + size_t num_pages = PFN_UP(size); size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *)); if (unlikely(struct_size == 0)) { @@ -474,7 +474,6 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, struct ttm_placement *placement, struct ttm_buffer_object **p_bo) { - unsigned npages = PAGE_ALIGN(size) >> PAGE_SHIFT; struct ttm_operation_ctx ctx = { false, false }; struct ttm_buffer_object *bo; size_t acc_size; @@ -485,7 +484,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, return -ENOMEM; acc_size = ttm_round_pot(sizeof(*bo)); - acc_size += ttm_round_pot(npages * sizeof(void *)); + acc_size += ttm_round_pot(PFN_UP(size) * sizeof(void *)); acc_size += ttm_round_pot(sizeof(struct ttm_tt)); ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index 81b84570da0a..3c06df2a5474 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -358,8 +358,7 @@ static void vmw_cmdbuf_ctx_submit(struct vmw_cmdbuf_man *man, break; } - list_del(&entry->list); - list_add_tail(&entry->list, &ctx->hw_submitted); + list_move_tail(&entry->list, &ctx->hw_submitted); ctx->num_hw_submitted++; } @@ -802,7 +801,7 @@ static int vmw_cmdbuf_alloc_space(struct vmw_cmdbuf_man *man, { struct vmw_cmdbuf_alloc_info info; - info.page_size = PAGE_ALIGN(size) >> PAGE_SHIFT; + info.page_size = PFN_UP(size); info.node = node; info.done = false; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 9487faff5229..8381750db81b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -169,8 +169,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list) case VMW_CMDBUF_RES_DEL: ret = drm_ht_insert_item(&entry->man->resources, &entry->hash); BUG_ON(ret); - list_del(&entry->head); - list_add_tail(&entry->head, &entry->man->list); + list_move_tail(&entry->head, &entry->man->list); entry->state = VMW_CMDBUF_RES_COMMITTED; break; default: diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index c84a16c1def0..17a98db00017 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -607,8 +607,7 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv, if (num_entries < co_info[type].min_initial_entries) { vcotbl->res.backup_size = co_info[type].min_initial_entries * co_info[type].size; - vcotbl->res.backup_size = - (vcotbl->res.backup_size + PAGE_SIZE - 1) & PAGE_MASK; + vcotbl->res.backup_size = PFN_ALIGN(vcotbl->res.backup_size); } vcotbl->scrubbed = true; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 63437270cbca..a833751099b5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1295,7 +1295,6 @@ extern struct vmw_cmdbuf_res_manager * vmw_context_res_man(struct vmw_resource *ctx); extern struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx, SVGACOTableType cotable_type); -extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx); struct vmw_ctx_binding_state; extern struct vmw_ctx_binding_state * vmw_context_binding_state(struct vmw_resource *ctx); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 338c6e2613ea..74fa41909213 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -100,7 +100,7 @@ static int vmw_cursor_update_bo(struct vmw_private *dev_priv, int ret; kmap_offset = 0; - kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT; + kmap_num = PFN_UP(width*height*4); ret = ttm_bo_reserve(&bo->base, true, false, NULL); if (unlikely(ret != 0)) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index c8e578f63c9c..f9394207dd3c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -256,8 +256,7 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, if (!otables[i].enabled) continue; - otables[i].size = - (otables[i].size + PAGE_SIZE - 1) & PAGE_MASK; + otables[i].size = PFN_ALIGN(otables[i].size); bo_size += otables[i].size; } @@ -385,7 +384,7 @@ static unsigned long vmw_mob_calculate_pt_pages(unsigned long data_pages) while (likely(data_size > PAGE_SIZE)) { data_size = DIV_ROUND_UP(data_size, PAGE_SIZE); data_size *= VMW_PPN_SIZE; - tot_size += (data_size + PAGE_SIZE - 1) & PAGE_MASK; + tot_size += PFN_ALIGN(data_size); } return tot_size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index ed9c7b3a1e08..e50fb82a3030 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -1016,9 +1016,9 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data, struct page *page; MKSGuestStatInstanceDescriptor *pdesc; - const size_t num_pages_stat = vmw_num_pages(arg->stat_len); - const size_t num_pages_info = vmw_num_pages(arg->info_len); - const size_t num_pages_strs = vmw_num_pages(arg->strs_len); + const size_t num_pages_stat = PFN_UP(arg->stat_len); + const size_t num_pages_info = PFN_UP(arg->info_len); + const size_t num_pages_strs = PFN_UP(arg->strs_len); long desc_len; long nr_pinned_stat; long nr_pinned_info; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 3b6f6044c325..8d1e869cc196 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -353,8 +353,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, static int vmw_resource_buf_alloc(struct vmw_resource *res, bool interruptible) { - unsigned long size = - (res->backup_size + PAGE_SIZE - 1) & PAGE_MASK; + unsigned long size = PFN_ALIGN(res->backup_size); struct vmw_buffer_object *backup; int ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index b3c8d2da6f1a..b8dd62529104 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -981,8 +981,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, goto no_reserve; /* Map and copy shader bytecode. */ - ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, - &map); + ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map); if (unlikely(ret != 0)) { ttm_bo_unreserve(&buf->base); goto no_reserve; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 0eba47762bed..5d53a5f9d123 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -865,7 +865,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, user_srf->prime.base.shareable = false; user_srf->prime.base.tfile = NULL; if (drm_is_primary_client(file_priv)) - user_srf->master = drm_master_get(file_priv->master); + user_srf->master = drm_file_get_master(file_priv); /** * From this point, the generic resource management functions @@ -1534,7 +1534,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, user_srf = container_of(srf, struct vmw_user_surface, srf); if (drm_is_primary_client(file_priv)) - user_srf->master = drm_master_get(file_priv->master); + user_srf->master = drm_file_get_master(file_priv); res = &user_srf->srf.res; diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index f588f967bb14..604b1d1b2d72 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -191,20 +191,6 @@ struct drm_device { */ struct list_head clientlist; - /** - * @irq_enabled: - * - * Indicates that interrupt handling is enabled, specifically vblank - * handling. Drivers which don't use drm_irq_install() need to set this - * to true manually. - */ - bool irq_enabled; - - /** - * @irq: Used by the drm_irq_install() and drm_irq_unistall() helpers. - */ - int irq; - /** * @vblank_disable_immediate: * @@ -372,6 +358,10 @@ struct drm_device { /* Scatter gather memory */ struct drm_sg_mem *sg; + + /* IRQs */ + bool irq_enabled; + int irq; #endif }; diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index b439ae1921b8..0cd95953cdf5 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -137,10 +137,6 @@ enum drm_driver_feature { * @DRIVER_HAVE_IRQ: * * Legacy irq support. Only for legacy drivers. Do not use. - * - * New drivers can either use the drm_irq_install() and - * drm_irq_uninstall() helper functions, or roll their own irq support - * code by calling request_irq() directly. */ DRIVER_HAVE_IRQ = BIT(30), /** @@ -271,42 +267,6 @@ struct drm_driver { */ void (*release) (struct drm_device *); - /** - * @irq_handler: - * - * Interrupt handler called when using drm_irq_install(). Not used by - * drivers which implement their own interrupt handling. - */ - irqreturn_t(*irq_handler) (int irq, void *arg); - - /** - * @irq_preinstall: - * - * Optional callback used by drm_irq_install() which is called before - * the interrupt handler is registered. This should be used to clear out - * any pending interrupts (from e.g. firmware based drives) and reset - * the interrupt handling registers. - */ - void (*irq_preinstall) (struct drm_device *dev); - - /** - * @irq_postinstall: - * - * Optional callback used by drm_irq_install() which is called after - * the interrupt handler is registered. This should be used to enable - * interrupt generation in the hardware. - */ - int (*irq_postinstall) (struct drm_device *dev); - - /** - * @irq_uninstall: - * - * Optional callback used by drm_irq_uninstall() which is called before - * the interrupt handler is unregistered. This should be used to disable - * interrupt generation in the hardware. - */ - void (*irq_uninstall) (struct drm_device *dev); - /** * @master_set: * @@ -504,6 +464,10 @@ struct drm_driver { int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); int (*dma_quiescent) (struct drm_device *); int (*context_dtor) (struct drm_device *dev, int context); + irqreturn_t (*irq_handler)(int irq, void *arg); + void (*irq_preinstall)(struct drm_device *dev); + int (*irq_postinstall)(struct drm_device *dev); + void (*irq_uninstall)(struct drm_device *dev); u32 (*get_vblank_counter)(struct drm_device *dev, unsigned int pipe); int (*enable_vblank)(struct drm_device *dev, unsigned int pipe); void (*disable_vblank)(struct drm_device *dev, unsigned int pipe); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 759328a5eeb2..deccfd39e6db 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -336,7 +336,7 @@ struct edid { u8 features; /* Color characteristics */ u8 red_green_lo; - u8 black_white_lo; + u8 blue_white_lo; u8 red_x; u8 red_y; u8 green_x; diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 726cfe0ff5f5..a3acb7ac3550 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -233,6 +233,10 @@ struct drm_file { * this only matches &drm_device.master if the master is the currently * active one. * + * To update @master, both &drm_device.master_mutex and + * @master_lookup_lock need to be held, therefore holding either of + * them is safe and enough for the read side. + * * When dereferencing this pointer, either hold struct * &drm_device.master_mutex for the duration of the pointer's use, or * use drm_file_get_master() if struct &drm_device.master_mutex is not diff --git a/include/drm/drm_gem_atomic_helper.h b/include/drm/drm_gem_atomic_helper.h index f9f8b6f0494a..48222a107873 100644 --- a/include/drm/drm_gem_atomic_helper.h +++ b/include/drm/drm_gem_atomic_helper.h @@ -42,6 +42,14 @@ struct drm_shadow_plane_state { * prepare_fb callback and removed in the cleanup_fb callback. */ struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; + + /** + * @data: Address of each framebuffer BO's data + * + * The address of the data stored in each mapping. This is different + * for framebuffers with non-zero offset fields. + */ + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; }; /** diff --git a/include/drm/drm_gem_framebuffer_helper.h b/include/drm/drm_gem_framebuffer_helper.h index ff2024dd7b77..905727719ead 100644 --- a/include/drm/drm_gem_framebuffer_helper.h +++ b/include/drm/drm_gem_framebuffer_helper.h @@ -40,7 +40,8 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd); int drm_gem_fb_vmap(struct drm_framebuffer *fb, - struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]); + struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES], + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]); void drm_gem_fb_vunmap(struct drm_framebuffer *fb, struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]); int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir); diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h deleted file mode 100644 index 631b22f9757d..000000000000 --- a/include/drm/drm_irq.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 Intel Corp. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _DRM_IRQ_H_ -#define _DRM_IRQ_H_ - -struct drm_device; - -int drm_irq_install(struct drm_device *dev, int irq); -int drm_irq_uninstall(struct drm_device *dev); -int devm_drm_irq_install(struct drm_device *dev, int irq); -#endif diff --git a/include/drm/drm_legacy.h b/include/drm/drm_legacy.h index b17e79e12bc2..58dc8d8cc907 100644 --- a/include/drm/drm_legacy.h +++ b/include/drm/drm_legacy.h @@ -192,6 +192,9 @@ do { \ void drm_legacy_idlelock_take(struct drm_lock_data *lock); void drm_legacy_idlelock_release(struct drm_lock_data *lock); +/* drm_irq.c */ +int drm_legacy_irq_uninstall(struct drm_device *dev); + /* drm_pci.c */ #ifdef CONFIG_PCI diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index cf07132d4ee8..0b3647e614dd 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h @@ -153,6 +153,33 @@ struct drm_simple_display_pipe_funcs { */ void (*disable_vblank)(struct drm_simple_display_pipe *pipe); + /** + * @reset_crtc: + * + * Optional, called by &drm_crtc_funcs.reset. Please read the + * documentation for the &drm_crtc_funcs.reset hook for more details. + */ + void (*reset_crtc)(struct drm_simple_display_pipe *pipe); + + /** + * @duplicate_crtc_state: + * + * Optional, called by &drm_crtc_funcs.atomic_duplicate_state. Please + * read the documentation for the &drm_crtc_funcs.atomic_duplicate_state + * hook for more details. + */ + struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe); + + /** + * @destroy_crtc_state: + * + * Optional, called by &drm_crtc_funcs.atomic_destroy_state. Please + * read the documentation for the &drm_crtc_funcs.atomic_destroy_state + * hook for more details. + */ + void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state); + /** * @reset_plane: * diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 678b2006be78..8b32b4bdd590 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -54,7 +54,7 @@ struct dma_buf_ops { * device), and otherwise need to fail the attach operation. * * The exporter should also in general check whether the current - * allocation fullfills the DMA constraints of the new device. If this + * allocation fulfills the DMA constraints of the new device. If this * is not the case, and the allocation cannot be moved, it should also * fail the attach operation. * @@ -161,7 +161,7 @@ struct dma_buf_ops { * * Returns: * - * A &sg_table scatter list of or the backing storage of the DMA buffer, + * A &sg_table scatter list of the backing storage of the DMA buffer, * already mapped into the device address space of the &device attached * with the provided &dma_buf_attachment. The addresses and lengths in * the scatter list are PAGE_SIZE aligned. @@ -183,7 +183,7 @@ struct dma_buf_ops { * * This is called by dma_buf_unmap_attachment() and should unmap and * release the &sg_table allocated in @map_dma_buf, and it is mandatory. - * For static dma_buf handling this might also unpins the backing + * For static dma_buf handling this might also unpin the backing * storage if this is the last mapping of the DMA buffer. */ void (*unmap_dma_buf)(struct dma_buf_attachment *, @@ -252,7 +252,7 @@ struct dma_buf_ops { * This callback is used by the dma_buf_mmap() function * * Note that the mapping needs to be incoherent, userspace is expected - * to braket CPU access using the DMA_BUF_IOCTL_SYNC interface. + * to bracket CPU access using the DMA_BUF_IOCTL_SYNC interface. * * Because dma-buf buffers have invariant size over their lifetime, the * dma-buf core checks whether a vma is too large and rejects such @@ -580,7 +580,7 @@ static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf) /** * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic - * mappinsg + * mappings * @attach: the DMA-buf attachment to check * * Returns true if a DMA-buf importer wants to call the map/unmap functions with diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 5cf387813754..9fe165beb0f9 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); #define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0) -#define lockdep_assert_held(l) do { \ - WARN_ON(debug_locks && \ - lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \ - } while (0) +#define lockdep_assert(cond) \ + do { WARN_ON(debug_locks && !(cond)); } while (0) -#define lockdep_assert_not_held(l) do { \ - WARN_ON(debug_locks && \ - lockdep_is_held(l) == LOCK_STATE_HELD); \ - } while (0) +#define lockdep_assert_once(cond) \ + do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0) -#define lockdep_assert_held_write(l) do { \ - WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \ - } while (0) +#define lockdep_assert_held(l) \ + lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) -#define lockdep_assert_held_read(l) do { \ - WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \ - } while (0) +#define lockdep_assert_not_held(l) \ + lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD) -#define lockdep_assert_held_once(l) do { \ - WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \ - } while (0) +#define lockdep_assert_held_write(l) \ + lockdep_assert(lockdep_is_held_type(l, 0)) -#define lockdep_assert_none_held_once() do { \ - WARN_ON_ONCE(debug_locks && current->lockdep_depth); \ - } while (0) +#define lockdep_assert_held_read(l) \ + lockdep_assert(lockdep_is_held_type(l, 1)) + +#define lockdep_assert_held_once(l) \ + lockdep_assert_once(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) + +#define lockdep_assert_none_held_once() \ + lockdep_assert_once(!current->lockdep_depth) #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) @@ -407,6 +405,9 @@ extern int lock_is_held(const void *); extern int lockdep_is_held(const void *); #define lockdep_is_held_type(l, r) (1) +#define lockdep_assert(c) do { } while (0) +#define lockdep_assert_once(c) do { } while (0) + #define lockdep_assert_held(l) do { (void)(l); } while (0) #define lockdep_assert_not_held(l) do { (void)(l); } while (0) #define lockdep_assert_held_write(l) do { (void)(l); } while (0)