diff options
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_irq.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_kms.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_v3d.c | 3 |
8 files changed, 77 insertions, 49 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index e3c29729da2e..ceb385fd69c5 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -111,13 +111,6 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, return 0; } -static void vc4_lastclose(struct drm_device *dev) -{ - struct vc4_dev *vc4 = to_vc4_dev(dev); - - drm_fbdev_cma_restore_mode(vc4->fbdev); -} - static const struct vm_operations_struct vc4_vm_ops = { .fault = vc4_fault, .open = drm_gem_vm_open, @@ -159,7 +152,7 @@ static struct drm_driver vc4_drm_driver = { DRIVER_HAVE_IRQ | DRIVER_RENDER | DRIVER_PRIME), - .lastclose = vc4_lastclose, + .lastclose = drm_fb_helper_lastclose, .irq_handler = vc4_irq, .irq_preinstall = vc4_irq_preinstall, .irq_postinstall = vc4_irq_postinstall, @@ -301,12 +294,10 @@ static void vc4_drm_unbind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = platform_get_drvdata(pdev); - struct vc4_dev *vc4 = to_vc4_dev(drm); drm_dev_unregister(drm); - if (vc4->fbdev) - drm_fbdev_cma_fini(vc4->fbdev); + drm_fb_cma_fbdev_fini(drm); drm_mode_config_cleanup(drm); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 9c0d380c96f2..3af22936d9b3 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -39,8 +39,6 @@ struct vc4_dev { struct vc4_dsi *dsi1; struct vc4_vec *vec; - struct drm_fbdev_cma *fbdev; - struct vc4_hang_state *hang_state; /* The kernel-space BO cache. Tracks buffers that have been diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 638540943c61..c94cce96544c 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -146,7 +146,7 @@ vc4_save_hang_state(struct drm_device *dev) struct vc4_exec_info *exec[2]; struct vc4_bo *bo; unsigned long irqflags; - unsigned int i, j, unref_list_count, prev_idx; + unsigned int i, j, k, unref_list_count; kernel_state = kcalloc(1, sizeof(*kernel_state), GFP_KERNEL); if (!kernel_state) @@ -182,7 +182,7 @@ vc4_save_hang_state(struct drm_device *dev) return; } - prev_idx = 0; + k = 0; for (i = 0; i < 2; i++) { if (!exec[i]) continue; @@ -197,7 +197,7 @@ vc4_save_hang_state(struct drm_device *dev) WARN_ON(!refcount_read(&bo->usecnt)); refcount_inc(&bo->usecnt); drm_gem_object_get(&exec[i]->bo[j]->base); - kernel_state->bo[j + prev_idx] = &exec[i]->bo[j]->base; + kernel_state->bo[k++] = &exec[i]->bo[j]->base; } list_for_each_entry(bo, &exec[i]->unref_list, unref_head) { @@ -205,12 +205,12 @@ vc4_save_hang_state(struct drm_device *dev) * because they are naturally unpurgeable. */ drm_gem_object_get(&bo->base.base); - kernel_state->bo[j + prev_idx] = &bo->base.base; - j++; + kernel_state->bo[k++] = &bo->base.base; } - prev_idx = j + 1; } + WARN_ON_ONCE(k != state->bo_count); + if (exec[0]) state->start_bin = exec[0]->ct0ca; if (exec[1]) @@ -436,6 +436,19 @@ vc4_flush_caches(struct drm_device *dev) VC4_SET_FIELD(0xf, V3D_SLCACTL_ICC)); } +static void +vc4_flush_texture_caches(struct drm_device *dev) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + + V3D_WRITE(V3D_L2CACTL, + V3D_L2CACTL_L2CCLR); + + V3D_WRITE(V3D_SLCACTL, + VC4_SET_FIELD(0xf, V3D_SLCACTL_T1CC) | + VC4_SET_FIELD(0xf, V3D_SLCACTL_T0CC)); +} + /* Sets the registers for the next job to be actually be executed in * the hardware. * @@ -474,6 +487,14 @@ vc4_submit_next_render_job(struct drm_device *dev) if (!exec) return; + /* A previous RCL may have written to one of our textures, and + * our full cache flush at bin time may have occurred before + * that RCL completed. Flush the texture cache now, but not + * the instructions or uniforms (since we don't write those + * from an RCL). + */ + vc4_flush_texture_caches(dev); + submit_cl(dev, 1, exec->ct1ca, exec->ct1ea); } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 0b2088264039..984501e3f0b0 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -287,7 +287,6 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); kfree(edid); return ret; @@ -695,7 +694,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } } +static enum drm_mode_status +vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc, + const struct drm_display_mode *mode) +{ + /* HSM clock must be 108% of the pixel clock. Additionally, + * the AXI clock needs to be at least 25% of pixel clock, but + * HSM ends up being the limiting factor. + */ + if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { + .mode_valid = vc4_hdmi_encoder_mode_valid, .disable = vc4_hdmi_encoder_disable, .enable = vc4_hdmi_encoder_enable, }; diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index 26eddbb62893..3dd62d75f531 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -209,9 +209,6 @@ vc4_irq_postinstall(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); - /* Undo the effects of a previous vc4_irq_uninstall. */ - enable_irq(dev->irq); - /* Enable both the render done and out of memory interrupts. */ V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS); diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 50c4959b5bd3..4256f294c346 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -19,17 +19,11 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include "vc4_drv.h" -static void vc4_output_poll_changed(struct drm_device *dev) -{ - struct vc4_dev *vc4 = to_vc4_dev(dev); - - drm_fbdev_cma_hotplug_event(vc4->fbdev); -} - static void vc4_atomic_complete_commit(struct drm_atomic_state *state) { @@ -194,7 +188,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, } static const struct drm_mode_config_funcs vc4_mode_funcs = { - .output_poll_changed = vc4_output_poll_changed, + .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = vc4_atomic_commit, .fb_create = vc4_fb_create, @@ -224,12 +218,8 @@ int vc4_kms_load(struct drm_device *dev) drm_mode_config_reset(dev); - if (dev->mode_config.num_connector) { - vc4->fbdev = drm_fbdev_cma_init(dev, 32, - dev->mode_config.num_connector); - if (IS_ERR(vc4->fbdev)) - vc4->fbdev = NULL; - } + if (dev->mode_config.num_connector) + drm_fb_cma_fbdev_init(dev, 32, 0); drm_kms_helper_poll_init(dev); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 423a23ed8fc2..515f97997624 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -86,7 +86,6 @@ static const struct hvs_format { u32 hvs; /* HVS_FORMAT_* */ u32 pixel_order; bool has_alpha; - bool flip_cbcr; } hvs_formats[] = { { .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, @@ -121,30 +120,52 @@ static const struct hvs_format { .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false, }, { + .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888, + .pixel_order = HVS_PIXEL_ORDER_XRGB, .has_alpha = false, + }, + { + .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888, + .pixel_order = HVS_PIXEL_ORDER_XBGR, .has_alpha = false, + }, + { .drm = DRM_FORMAT_YUV422, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCBCR, }, { .drm = DRM_FORMAT_YVU422, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, - .flip_cbcr = true, + .pixel_order = HVS_PIXEL_ORDER_XYCRCB, }, { .drm = DRM_FORMAT_YUV420, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCBCR, }, { .drm = DRM_FORMAT_YVU420, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, - .flip_cbcr = true, + .pixel_order = HVS_PIXEL_ORDER_XYCRCB, }, { .drm = DRM_FORMAT_NV12, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCBCR, + }, + { + .drm = DRM_FORMAT_NV21, + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCRCB, }, { .drm = DRM_FORMAT_NV16, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCBCR, + }, + { + .drm = DRM_FORMAT_NV61, + .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, + .pixel_order = HVS_PIXEL_ORDER_XYCRCB, }, }; @@ -617,15 +638,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, * The pointers may be any byte address. */ vc4_state->ptr0_offset = vc4_state->dlist_count; - if (!format->flip_cbcr) { - for (i = 0; i < num_planes; i++) - vc4_dlist_write(vc4_state, vc4_state->offsets[i]); - } else { - WARN_ON_ONCE(num_planes != 3); - vc4_dlist_write(vc4_state, vc4_state->offsets[0]); - vc4_dlist_write(vc4_state, vc4_state->offsets[2]); - vc4_dlist_write(vc4_state, vc4_state->offsets[1]); - } + for (i = 0; i < num_planes; i++) + vc4_dlist_write(vc4_state, vc4_state->offsets[i]); /* Pointer Context Word 0/1/2: Written by the HVS */ for (i = 0; i < num_planes; i++) diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 622cd43840b8..493f392b3a0a 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -327,6 +327,9 @@ static int vc4_v3d_runtime_resume(struct device *dev) return ret; vc4_v3d_init_hw(vc4->dev); + + /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */ + enable_irq(vc4->dev->irq); vc4_irq_postinstall(vc4->dev); return 0; |