Commit cd4c5a48 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'imx-drm-fixes-2019-02-12' of git://git.pengutronix.de/pza/linux into drm-fixes

drm/imx: plane, ldb, and ipu-v3 fixes

- Fix CSI register offsets for i.MX51 and i.MX53.
- Fix delayed page flip completion events on i.MX6QP due to unexpected
  behaviour of the PRE when issuing NOP buffer updates to the same
  buffer address.
- Stop throwing errors for plane updates on disabled CRTCs when a
  userspace process is killed while a plane update is pending.
- Add missing of_node_put cleanup in imx_ldb_bind.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Philipp Zabel <p.zabel@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/1549990602.4800.11.camel@pengutronix.de
parents d1393711 eb0200a4
...@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
int bus_format; int bus_format;
ret = of_property_read_u32(child, "reg", &i); ret = of_property_read_u32(child, "reg", &i);
if (ret || i < 0 || i > 1) if (ret || i < 0 || i > 1) {
return -EINVAL; ret = -EINVAL;
goto free_child;
}
if (!of_device_is_available(child)) if (!of_device_is_available(child))
continue; continue;
...@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
channel = &imx_ldb->channel[i]; channel = &imx_ldb->channel[i];
channel->ldb = imx_ldb; channel->ldb = imx_ldb;
channel->chno = i; channel->chno = i;
channel->child = child;
/* /*
* The output port is port@4 with an external 4-port mux or * The output port is port@4 with an external 4-port mux or
...@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
imx_ldb->lvds_mux ? 4 : 2, 0, imx_ldb->lvds_mux ? 4 : 2, 0,
&channel->panel, &channel->bridge); &channel->panel, &channel->bridge);
if (ret && ret != -ENODEV) if (ret && ret != -ENODEV)
return ret; goto free_child;
/* panel ddc only if there is no bridge */ /* panel ddc only if there is no bridge */
if (!channel->bridge) { if (!channel->bridge) {
ret = imx_ldb_panel_ddc(dev, channel, child); ret = imx_ldb_panel_ddc(dev, channel, child);
if (ret) if (ret)
return ret; goto free_child;
} }
bus_format = of_get_bus_format(dev, child); bus_format = of_get_bus_format(dev, child);
...@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
if (bus_format < 0) { if (bus_format < 0) {
dev_err(dev, "could not determine data mapping: %d\n", dev_err(dev, "could not determine data mapping: %d\n",
bus_format); bus_format);
return bus_format; ret = bus_format;
goto free_child;
} }
channel->bus_format = bus_format; channel->bus_format = bus_format;
channel->child = child;
ret = imx_ldb_register(drm, channel); ret = imx_ldb_register(drm, channel);
if (ret) if (ret) {
return ret; channel->child = NULL;
goto free_child;
}
} }
dev_set_drvdata(dev, imx_ldb); dev_set_drvdata(dev, imx_ldb);
return 0; return 0;
free_child:
of_node_put(child);
return ret;
} }
static void imx_ldb_unbind(struct device *dev, struct device *master, static void imx_ldb_unbind(struct device *dev, struct device *master,
......
...@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, ...@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
if (ret) if (ret)
return ret; return ret;
/* CRTC should be enabled */ /* nothing to check when disabling or disabled */
if (!crtc_state->enable) if (!crtc_state->enable)
return -EINVAL; return 0;
switch (plane->type) { switch (plane->type) {
case DRM_PLANE_TYPE_PRIMARY: case DRM_PLANE_TYPE_PRIMARY:
......
...@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = { ...@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {
.cpmem_ofs = 0x1f000000, .cpmem_ofs = 0x1f000000,
.srm_ofs = 0x1f040000, .srm_ofs = 0x1f040000,
.tpm_ofs = 0x1f060000, .tpm_ofs = 0x1f060000,
.csi0_ofs = 0x1f030000, .csi0_ofs = 0x1e030000,
.csi1_ofs = 0x1f038000, .csi1_ofs = 0x1e038000,
.ic_ofs = 0x1e020000, .ic_ofs = 0x1e020000,
.disp0_ofs = 0x1e040000, .disp0_ofs = 0x1e040000,
.disp1_ofs = 0x1e048000, .disp1_ofs = 0x1e048000,
...@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = { ...@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {
.cpmem_ofs = 0x07000000, .cpmem_ofs = 0x07000000,
.srm_ofs = 0x07040000, .srm_ofs = 0x07040000,
.tpm_ofs = 0x07060000, .tpm_ofs = 0x07060000,
.csi0_ofs = 0x07030000, .csi0_ofs = 0x06030000,
.csi1_ofs = 0x07038000, .csi1_ofs = 0x06038000,
.ic_ofs = 0x06020000, .ic_ofs = 0x06020000,
.disp0_ofs = 0x06040000, .disp0_ofs = 0x06040000,
.disp1_ofs = 0x06048000, .disp1_ofs = 0x06048000,
......
...@@ -106,6 +106,7 @@ struct ipu_pre { ...@@ -106,6 +106,7 @@ struct ipu_pre {
void *buffer_virt; void *buffer_virt;
bool in_use; bool in_use;
unsigned int safe_window_end; unsigned int safe_window_end;
unsigned int last_bufaddr;
}; };
static DEFINE_MUTEX(ipu_pre_list_mutex); static DEFINE_MUTEX(ipu_pre_list_mutex);
...@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, ...@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF); writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
pre->last_bufaddr = bufaddr;
val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) | val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) | IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
...@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr) ...@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
unsigned short current_yblock; unsigned short current_yblock;
u32 val; u32 val;
if (bufaddr == pre->last_bufaddr)
return;
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
pre->last_bufaddr = bufaddr;
do { do {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
......
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