Commit 7f7a4795 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2020-09-09' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes for v5.9-rc5:
- Fix double free in virtio.
- Add missing put_device in sun4i, and other fixes.
- Small ingenic fixes.
- Handle sun4i alpha on lowest plane correctly.
- Remove output->enabled from virtio, as it should use crtc_state.
- Fix tve200 enable/disable.
- Documentation fix.
- Fix virtio unblank.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/478b49d1-b1b3-c983-7056-8a89249be435@mblankhorst.nl
parents 7bf23bfb fc7f148f
...@@ -179,7 +179,7 @@ DMA Fence uABI/Sync File ...@@ -179,7 +179,7 @@ DMA Fence uABI/Sync File
:internal: :internal:
Indefinite DMA Fences Indefinite DMA Fences
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
At various times &dma_fence with an indefinite time until dma_fence_wait() At various times &dma_fence with an indefinite time until dma_fence_wait()
finishes have been proposed. Examples include: finishes have been proposed. Examples include:
......
...@@ -316,9 +316,9 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) ...@@ -316,9 +316,9 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
* name of the dma-buf if the same piece of memory is used for multiple * name of the dma-buf if the same piece of memory is used for multiple
* purpose between different devices. * purpose between different devices.
* *
* @dmabuf [in] dmabuf buffer that will be renamed. * @dmabuf: [in] dmabuf buffer that will be renamed.
* @buf: [in] A piece of userspace memory that contains the name of * @buf: [in] A piece of userspace memory that contains the name of
* the dma-buf. * the dma-buf.
* *
* Returns 0 on success. If the dma-buf buffer is already attached to * Returns 0 on success. If the dma-buf buffer is already attached to
* devices, return -EBUSY. * devices, return -EBUSY.
......
...@@ -222,6 +222,7 @@ EXPORT_SYMBOL(dma_fence_chain_ops); ...@@ -222,6 +222,7 @@ EXPORT_SYMBOL(dma_fence_chain_ops);
* @chain: the chain node to initialize * @chain: the chain node to initialize
* @prev: the previous fence * @prev: the previous fence
* @fence: the current fence * @fence: the current fence
* @seqno: the sequence number to use for the fence chain
* *
* Initialize a new chain node and either start a new chain or add the node to * Initialize a new chain node and either start a new chain or add the node to
* the existing chain of the previous fence. * the existing chain of the previous fence.
......
...@@ -673,7 +673,7 @@ static void ingenic_drm_unbind_all(void *d) ...@@ -673,7 +673,7 @@ static void ingenic_drm_unbind_all(void *d)
component_unbind_all(priv->dev, &priv->drm); component_unbind_all(priv->dev, &priv->drm);
} }
static int ingenic_drm_bind(struct device *dev) static int ingenic_drm_bind(struct device *dev, bool has_components)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
const struct jz_soc_info *soc_info; const struct jz_soc_info *soc_info;
...@@ -808,7 +808,7 @@ static int ingenic_drm_bind(struct device *dev) ...@@ -808,7 +808,7 @@ static int ingenic_drm_bind(struct device *dev)
return ret; return ret;
} }
if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) { if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) {
ret = component_bind_all(dev, drm); ret = component_bind_all(dev, drm);
if (ret) { if (ret) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
...@@ -939,6 +939,11 @@ static int ingenic_drm_bind(struct device *dev) ...@@ -939,6 +939,11 @@ static int ingenic_drm_bind(struct device *dev)
return ret; return ret;
} }
static int ingenic_drm_bind_with_components(struct device *dev)
{
return ingenic_drm_bind(dev, true);
}
static int compare_of(struct device *dev, void *data) static int compare_of(struct device *dev, void *data)
{ {
return dev->of_node == data; return dev->of_node == data;
...@@ -957,7 +962,7 @@ static void ingenic_drm_unbind(struct device *dev) ...@@ -957,7 +962,7 @@ static void ingenic_drm_unbind(struct device *dev)
} }
static const struct component_master_ops ingenic_master_ops = { static const struct component_master_ops ingenic_master_ops = {
.bind = ingenic_drm_bind, .bind = ingenic_drm_bind_with_components,
.unbind = ingenic_drm_unbind, .unbind = ingenic_drm_unbind,
}; };
...@@ -968,16 +973,15 @@ static int ingenic_drm_probe(struct platform_device *pdev) ...@@ -968,16 +973,15 @@ static int ingenic_drm_probe(struct platform_device *pdev)
struct device_node *np; struct device_node *np;
if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
return ingenic_drm_bind(dev); return ingenic_drm_bind(dev, false);
/* IPU is at port address 8 */ /* IPU is at port address 8 */
np = of_graph_get_remote_node(dev->of_node, 8, 0); np = of_graph_get_remote_node(dev->of_node, 8, 0);
if (!np) { if (!np)
dev_err(dev, "Unable to get IPU node\n"); return ingenic_drm_bind(dev, false);
return -EINVAL;
}
drm_of_component_match_add(dev, &match, compare_of, np); drm_of_component_match_add(dev, &match, compare_of, np);
of_node_put(np);
return component_master_add_with_match(dev, &ingenic_master_ops, match); return component_master_add_with_match(dev, &ingenic_master_ops, match);
} }
......
...@@ -589,8 +589,7 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, ...@@ -589,8 +589,7 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
/* We can't have an alpha plane at the lowest position */ /* We can't have an alpha plane at the lowest position */
if (!backend->quirks->supports_lowest_plane_alpha && if (!backend->quirks->supports_lowest_plane_alpha &&
(plane_states[0]->fb->format->has_alpha || (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))
(plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE)))
return -EINVAL; return -EINVAL;
for (i = 1; i < num_planes; i++) { for (i = 1; i < num_planes; i++) {
...@@ -995,7 +994,6 @@ static const struct sun4i_backend_quirks sun6i_backend_quirks = { ...@@ -995,7 +994,6 @@ static const struct sun4i_backend_quirks sun6i_backend_quirks = {
static const struct sun4i_backend_quirks sun7i_backend_quirks = { static const struct sun4i_backend_quirks sun7i_backend_quirks = {
.needs_output_muxing = true, .needs_output_muxing = true,
.supports_lowest_plane_alpha = true,
}; };
static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = { static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = {
......
...@@ -1433,14 +1433,18 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon, ...@@ -1433,14 +1433,18 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) && if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
encoder->encoder_type == DRM_MODE_ENCODER_TMDS) { encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id); ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
if (ret) if (ret) {
put_device(&pdev->dev);
return ret; return ret;
}
} }
if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) { if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id); ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
if (ret) if (ret) {
put_device(&pdev->dev);
return ret; return ret;
}
} }
return 0; return 0;
......
...@@ -889,7 +889,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi, ...@@ -889,7 +889,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0), regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
sun6i_dsi_dcs_build_pkt_hdr(dsi, msg)); sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
bounce = kzalloc(msg->tx_len + sizeof(crc), GFP_KERNEL); bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL);
if (!bounce) if (!bounce)
return -ENOMEM; return -ENOMEM;
...@@ -900,7 +900,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi, ...@@ -900,7 +900,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc)); memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
len += sizeof(crc); len += sizeof(crc);
regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, len); regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4));
regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1); regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
kfree(bounce); kfree(bounce);
......
...@@ -211,7 +211,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, ...@@ -211,7 +211,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
return 0; return 0;
} }
static bool sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format) static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
{ {
if (!format->is_yuv) if (!format->is_yuv)
return SUN8I_CSC_MODE_OFF; return SUN8I_CSC_MODE_OFF;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/version.h> #include <linux/version.h>
#include <linux/dma-buf.h> #include <linux/dma-buf.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/delay.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
...@@ -130,9 +131,25 @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe, ...@@ -130,9 +131,25 @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe,
struct drm_connector *connector = priv->connector; struct drm_connector *connector = priv->connector;
u32 format = fb->format->format; u32 format = fb->format->format;
u32 ctrl1 = 0; u32 ctrl1 = 0;
int retries;
clk_prepare_enable(priv->clk); clk_prepare_enable(priv->clk);
/* Reset the TVE200 and wait for it to come back online */
writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
for (retries = 0; retries < 5; retries++) {
usleep_range(30000, 50000);
if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET)
continue;
else
break;
}
if (retries == 5 &&
readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) {
dev_err(drm->dev, "can't get hardware out of reset\n");
return;
}
/* Function 1 */ /* Function 1 */
ctrl1 |= TVE200_CTRL_CSMODE; ctrl1 |= TVE200_CTRL_CSMODE;
/* Interlace mode for CCIR656: parameterize? */ /* Interlace mode for CCIR656: parameterize? */
...@@ -230,8 +247,9 @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe) ...@@ -230,8 +247,9 @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe)
drm_crtc_vblank_off(crtc); drm_crtc_vblank_off(crtc);
/* Disable and Power Down */ /* Disable put into reset and Power Down */
writel(0, priv->regs + TVE200_CTRL); writel(0, priv->regs + TVE200_CTRL);
writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
} }
...@@ -279,6 +297,8 @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) ...@@ -279,6 +297,8 @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
struct drm_device *drm = crtc->dev; struct drm_device *drm = crtc->dev;
struct tve200_drm_dev_private *priv = drm->dev_private; struct tve200_drm_dev_private *priv = drm->dev_private;
/* Clear any IRQs and enable */
writel(0xFF, priv->regs + TVE200_INT_CLR);
writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN); writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
return 0; return 0;
} }
......
...@@ -97,9 +97,6 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -97,9 +97,6 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state) struct drm_crtc_state *old_state)
{ {
struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc);
output->enabled = true;
} }
static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc,
...@@ -111,7 +108,6 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -111,7 +108,6 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc,
virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0);
virtio_gpu_notify(vgdev); virtio_gpu_notify(vgdev);
output->enabled = false;
} }
static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
...@@ -123,6 +119,17 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -123,6 +119,17 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_state) struct drm_crtc_state *old_state)
{ {
struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc);
/*
* virtio-gpu can't do modeset and plane update operations
* independent from each other. So the actual modeset happens
* in the plane update callback, and here we just check
* whenever we must force the modeset.
*/
if (drm_atomic_crtc_needs_modeset(crtc->state)) {
output->needs_modeset = true;
}
} }
static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = {
......
...@@ -137,7 +137,7 @@ struct virtio_gpu_output { ...@@ -137,7 +137,7 @@ struct virtio_gpu_output {
struct edid *edid; struct edid *edid;
int cur_x; int cur_x;
int cur_y; int cur_y;
bool enabled; bool needs_modeset;
}; };
#define drm_crtc_to_virtio_gpu_output(x) \ #define drm_crtc_to_virtio_gpu_output(x) \
container_of(x, struct virtio_gpu_output, crtc) container_of(x, struct virtio_gpu_output, crtc)
......
...@@ -151,7 +151,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, ...@@ -151,7 +151,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
if (ret < 0) if (ret < 0)
return -EINVAL; return -EINVAL;
shmem->pages = drm_gem_shmem_get_pages_sgt(&bo->base.base); /*
* virtio_gpu uses drm_gem_shmem_get_sg_table instead of
* drm_gem_shmem_get_pages_sgt because virtio has it's own set of
* dma-ops. This is discouraged for other drivers, but should be fine
* since virtio_gpu doesn't support dma-buf import from other devices.
*/
shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base);
if (!shmem->pages) { if (!shmem->pages) {
drm_gem_shmem_unpin(&bo->base.base); drm_gem_shmem_unpin(&bo->base.base);
return -EINVAL; return -EINVAL;
......
...@@ -142,7 +142,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, ...@@ -142,7 +142,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
if (WARN_ON(!output)) if (WARN_ON(!output))
return; return;
if (!plane->state->fb || !output->enabled) { if (!plane->state->fb || !output->crtc.state->active) {
DRM_DEBUG("nofb\n"); DRM_DEBUG("nofb\n");
virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, virtio_gpu_cmd_set_scanout(vgdev, output->index, 0,
plane->state->src_w >> 16, plane->state->src_w >> 16,
...@@ -163,7 +163,9 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, ...@@ -163,7 +163,9 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
plane->state->src_w != old_state->src_w || plane->state->src_w != old_state->src_w ||
plane->state->src_h != old_state->src_h || plane->state->src_h != old_state->src_h ||
plane->state->src_x != old_state->src_x || plane->state->src_x != old_state->src_x ||
plane->state->src_y != old_state->src_y) { plane->state->src_y != old_state->src_y ||
output->needs_modeset) {
output->needs_modeset = false;
DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
bo->hw_res_handle, bo->hw_res_handle,
plane->state->crtc_w, plane->state->crtc_h, plane->state->crtc_w, plane->state->crtc_h,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment