提交 f0f21aa5 编写于 作者: D Dave Airlie

Merge branch 'exynos-drm-fixes' of...

Merge branch 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

Inki writes:

"This pull request includes some bug fixes, code cleanups and exception codes.
If there is any problem, please kindly let me know."

* 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: add check for the device power status
  drm/exynos: Make 'drm_hdmi_get_edid' static
  drm/exynos: fimd and ipp are broken on multiplatform
  drm/exynos: don't include plat/gpio-cfg.h
  drm/exynos: Remove "internal" interrupt handling
  drm/exynos: Add missing static specifiers in exynos_drm_rotator.c
  drm/exynos: Replace mdelay with usleep_range
  drm/exynos: Make ipp_handle_cmd_work static
  drm/exynos: Make g2d_userptr_get_dma_addr static
  drm/exynos: consider DMA_NONE flag to dmabuf import
  drm/exynos: free sg object if dma_map_sg is failed
  drm/exynos: added validation of edid for vidi connection
  drm/exynos: let drm handle edid allocations
...@@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF ...@@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF
config DRM_EXYNOS_FIMD config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD" bool "Exynos DRM FIMD"
depends on DRM_EXYNOS && !FB_S3C depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
help help
Choose this option if you want to use Exynos FIMD for DRM. Choose this option if you want to use Exynos FIMD for DRM.
...@@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D ...@@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D
config DRM_EXYNOS_IPP config DRM_EXYNOS_IPP
bool "Exynos DRM IPP" bool "Exynos DRM IPP"
depends on DRM_EXYNOS depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
help help
Choose this option if you want to use IPP feature for DRM. Choose this option if you want to use IPP feature for DRM.
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#define MAX_EDID 256
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
drm_connector) drm_connector)
...@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
to_exynos_connector(connector); to_exynos_connector(connector);
struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_manager *manager = exynos_connector->manager;
struct exynos_drm_display_ops *display_ops = manager->display_ops; struct exynos_drm_display_ops *display_ops = manager->display_ops;
unsigned int count; struct edid *edid = NULL;
unsigned int count = 0;
int ret;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
* because lcd panel has only one mode. * because lcd panel has only one mode.
*/ */
if (display_ops->get_edid) { if (display_ops->get_edid) {
int ret; edid = display_ops->get_edid(manager->dev, connector);
void *edid; if (IS_ERR_OR_NULL(edid)) {
ret = PTR_ERR(edid);
edid = kzalloc(MAX_EDID, GFP_KERNEL); edid = NULL;
if (!edid) { DRM_ERROR("Panel operation get_edid failed %d\n", ret);
DRM_ERROR("failed to allocate edid\n"); goto out;
return 0;
} }
ret = display_ops->get_edid(manager->dev, connector, count = drm_add_edid_modes(connector, edid);
edid, MAX_EDID); if (count < 0) {
if (ret < 0) { DRM_ERROR("Add edid modes failed %d\n", count);
DRM_ERROR("failed to get edid data.\n"); goto out;
kfree(edid);
edid = NULL;
return 0;
} }
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
kfree(edid);
} else { } else {
struct exynos_drm_panel_info *panel; struct exynos_drm_panel_info *panel;
struct drm_display_mode *mode = drm_mode_create(connector->dev); struct drm_display_mode *mode = drm_mode_create(connector->dev);
...@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
count = 1; count = 1;
} }
out:
kfree(edid);
return count; return count;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
struct exynos_drm_dmabuf_attachment { struct exynos_drm_dmabuf_attachment {
struct sg_table sgt; struct sg_table sgt;
enum dma_data_direction dir; enum dma_data_direction dir;
bool is_mapped;
}; };
static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
...@@ -72,17 +73,10 @@ static struct sg_table * ...@@ -72,17 +73,10 @@ static struct sg_table *
DRM_DEBUG_PRIME("%s\n", __FILE__); DRM_DEBUG_PRIME("%s\n", __FILE__);
if (WARN_ON(dir == DMA_NONE))
return ERR_PTR(-EINVAL);
/* just return current sgt if already requested. */ /* just return current sgt if already requested. */
if (exynos_attach->dir == dir) if (exynos_attach->dir == dir && exynos_attach->is_mapped)
return &exynos_attach->sgt; return &exynos_attach->sgt;
/* reattaching is not allowed. */
if (WARN_ON(exynos_attach->dir != DMA_NONE))
return ERR_PTR(-EBUSY);
buf = gem_obj->buffer; buf = gem_obj->buffer;
if (!buf) { if (!buf) {
DRM_ERROR("buffer is null.\n"); DRM_ERROR("buffer is null.\n");
...@@ -107,13 +101,17 @@ static struct sg_table * ...@@ -107,13 +101,17 @@ static struct sg_table *
wr = sg_next(wr); wr = sg_next(wr);
} }
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); if (dir != DMA_NONE) {
if (!nents) { nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
DRM_ERROR("failed to map sgl with iommu.\n"); if (!nents) {
sgt = ERR_PTR(-EIO); DRM_ERROR("failed to map sgl with iommu.\n");
goto err_unlock; sg_free_table(sgt);
sgt = ERR_PTR(-EIO);
goto err_unlock;
}
} }
exynos_attach->is_mapped = true;
exynos_attach->dir = dir; exynos_attach->dir = dir;
attach->priv = exynos_attach; attach->priv = exynos_attach;
......
...@@ -148,8 +148,8 @@ struct exynos_drm_overlay { ...@@ -148,8 +148,8 @@ struct exynos_drm_overlay {
struct exynos_drm_display_ops { struct exynos_drm_display_ops {
enum exynos_drm_output_type type; enum exynos_drm_output_type type;
bool (*is_connected)(struct device *dev); bool (*is_connected)(struct device *dev);
int (*get_edid)(struct device *dev, struct drm_connector *connector, struct edid *(*get_edid)(struct device *dev,
u8 *edid, int len); struct drm_connector *connector);
void *(*get_panel)(struct device *dev); void *(*get_panel)(struct device *dev);
int (*check_timing)(struct device *dev, void *timing); int (*check_timing)(struct device *dev, void *timing);
int (*power_on)(struct device *dev, int mode); int (*power_on)(struct device *dev, int mode);
......
...@@ -324,7 +324,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev, ...@@ -324,7 +324,7 @@ static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev,
g2d_userptr = NULL; g2d_userptr = NULL;
} }
dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
unsigned long userptr, unsigned long userptr,
unsigned long size, unsigned long size,
struct drm_file *filp, struct drm_file *filp,
......
...@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev) ...@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev)
return false; return false;
} }
static int drm_hdmi_get_edid(struct device *dev, static struct edid *drm_hdmi_get_edid(struct device *dev,
struct drm_connector *connector, u8 *edid, int len) struct drm_connector *connector)
{ {
struct drm_hdmi_context *ctx = to_context(dev); struct drm_hdmi_context *ctx = to_context(dev);
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (hdmi_ops && hdmi_ops->get_edid) if (hdmi_ops && hdmi_ops->get_edid)
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
len);
return 0; return NULL;
} }
static int drm_hdmi_check_timing(struct device *dev, void *timing) static int drm_hdmi_check_timing(struct device *dev, void *timing)
......
...@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context { ...@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context {
struct exynos_hdmi_ops { struct exynos_hdmi_ops {
/* display */ /* display */
bool (*is_connected)(void *ctx); bool (*is_connected)(void *ctx);
int (*get_edid)(void *ctx, struct drm_connector *connector, struct edid *(*get_edid)(void *ctx,
u8 *edid, int len); struct drm_connector *connector);
int (*check_timing)(void *ctx, void *timing); int (*check_timing)(void *ctx, void *timing);
int (*power_on)(void *ctx, int mode); int (*power_on)(void *ctx, int mode);
......
...@@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, ...@@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
} }
} }
void ipp_handle_cmd_work(struct device *dev, static void ipp_handle_cmd_work(struct device *dev,
struct exynos_drm_ippdrv *ippdrv, struct exynos_drm_ippdrv *ippdrv,
struct drm_exynos_ipp_cmd_work *cmd_work, struct drm_exynos_ipp_cmd_work *cmd_work,
struct drm_exynos_ipp_cmd_node *c_node) struct drm_exynos_ipp_cmd_node *c_node)
......
...@@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev) ...@@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev)
return 0; return 0;
} }
struct rot_limit_table rot_limit_tbl = { static struct rot_limit_table rot_limit_tbl = {
.ycbcr420_2p = { .ycbcr420_2p = {
.min_w = 32, .min_w = 32,
.min_h = 32, .min_h = 32,
...@@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = { ...@@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = {
}, },
}; };
struct platform_device_id rotator_driver_ids[] = { static struct platform_device_id rotator_driver_ids[] = {
{ {
.name = "exynos-rot", .name = "exynos-rot",
.driver_data = (unsigned long)&rot_limit_tbl, .driver_data = (unsigned long)&rot_limit_tbl,
......
...@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev) ...@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev)
return ctx->connected ? true : false; return ctx->connected ? true : false;
} }
static int vidi_get_edid(struct device *dev, struct drm_connector *connector, static struct edid *vidi_get_edid(struct device *dev,
u8 *edid, int len) struct drm_connector *connector)
{ {
struct vidi_context *ctx = get_vidi_context(dev); struct vidi_context *ctx = get_vidi_context(dev);
struct edid *edid;
int edid_len;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, ...@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
*/ */
if (!ctx->raw_edid) { if (!ctx->raw_edid) {
DRM_DEBUG_KMS("raw_edid is null.\n"); DRM_DEBUG_KMS("raw_edid is null.\n");
return -EFAULT; return ERR_PTR(-EFAULT);
} }
memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
* EDID_LENGTH, len)); edid = kzalloc(edid_len, GFP_KERNEL);
if (!edid) {
DRM_DEBUG_KMS("failed to allocate edid\n");
return ERR_PTR(-ENOMEM);
}
return 0; memcpy(edid, ctx->raw_edid, edid_len);
return edid;
} }
static void *vidi_get_panel(struct device *dev) static void *vidi_get_panel(struct device *dev)
...@@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, ...@@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
struct exynos_drm_manager *manager; struct exynos_drm_manager *manager;
struct exynos_drm_display_ops *display_ops; struct exynos_drm_display_ops *display_ops;
struct drm_exynos_vidi_connection *vidi = data; struct drm_exynos_vidi_connection *vidi = data;
struct edid *raw_edid;
int edid_len; int edid_len;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, ...@@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
} }
if (vidi->connection) { if (vidi->connection) {
if (!vidi->edid) { struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid;
DRM_DEBUG_KMS("edid data is null.\n"); if (!drm_edid_is_valid(raw_edid)) {
DRM_DEBUG_KMS("edid data is invalid.\n");
return -EINVAL; return -EINVAL;
} }
raw_edid = (struct edid *)(uint32_t)vidi->edid;
edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
if (!ctx->raw_edid) { if (!ctx->raw_edid) {
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <plat/gpio-cfg.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
...@@ -98,8 +97,7 @@ struct hdmi_context { ...@@ -98,8 +97,7 @@ struct hdmi_context {
void __iomem *regs; void __iomem *regs;
void *parent_ctx; void *parent_ctx;
int external_irq; int irq;
int internal_irq;
struct i2c_client *ddc_port; struct i2c_client *ddc_port;
struct i2c_client *hdmiphy_port; struct i2c_client *hdmiphy_port;
...@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx) ...@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx)
return hdata->hpd; return hdata->hpd;
} }
static int hdmi_get_edid(void *ctx, struct drm_connector *connector, static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
u8 *edid, int len)
{ {
struct edid *raw_edid; struct edid *raw_edid;
struct hdmi_context *hdata = ctx; struct hdmi_context *hdata = ctx;
...@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, ...@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
if (!hdata->ddc_port) if (!hdata->ddc_port)
return -ENODEV; return ERR_PTR(-ENODEV);
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
if (raw_edid) { if (!raw_edid)
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); return ERR_PTR(-ENODEV);
memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
* EDID_LENGTH, len));
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
raw_edid->width_cm, raw_edid->height_cm);
kfree(raw_edid);
} else {
return -ENODEV;
}
return 0; hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
raw_edid->width_cm, raw_edid->height_cm);
return raw_edid;
} }
static int hdmi_v13_check_timing(struct fb_videomode *check_timing) static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
...@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) ...@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
/* resetting HDMI core */ /* resetting HDMI core */
hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
mdelay(10); usleep_range(10000, 12000);
hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
mdelay(10); usleep_range(10000, 12000);
} }
static void hdmi_conf_init(struct hdmi_context *hdata) static void hdmi_conf_init(struct hdmi_context *hdata)
{ {
struct hdmi_infoframe infoframe; struct hdmi_infoframe infoframe;
/* disable HPD interrupts */ /* disable HPD interrupts from HDMI IP block, use GPIO instead */
hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
...@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) ...@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
if (val & HDMI_PHY_STATUS_READY) if (val & HDMI_PHY_STATUS_READY)
break; break;
mdelay(1); usleep_range(1000, 2000);
} }
/* steady state not achieved */ /* steady state not achieved */
if (tries == 0) { if (tries == 0) {
...@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) ...@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
if (val & HDMI_PHY_STATUS_READY) if (val & HDMI_PHY_STATUS_READY)
break; break;
mdelay(1); usleep_range(1000, 2000);
} }
/* steady state not achieved */ /* steady state not achieved */
if (tries == 0) { if (tries == 0) {
...@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) ...@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
/* reset hdmiphy */ /* reset hdmiphy */
hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
mdelay(10); usleep_range(10000, 12000);
hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
mdelay(10); usleep_range(10000, 12000);
} }
static void hdmiphy_poweron(struct hdmi_context *hdata) static void hdmiphy_poweron(struct hdmi_context *hdata)
...@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) ...@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
return; return;
} }
mdelay(10); usleep_range(10000, 12000);
/* operation mode */ /* operation mode */
operation[0] = 0x1f; operation[0] = 0x1f;
...@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx) ...@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx)
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
mutex_lock(&hdata->hdmi_mutex);
if (!hdata->powered) {
mutex_unlock(&hdata->hdmi_mutex);
return;
}
mutex_unlock(&hdata->hdmi_mutex);
hdmi_conf_apply(hdata); hdmi_conf_apply(hdata);
} }
...@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = { ...@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
.dpms = hdmi_dpms, .dpms = hdmi_dpms,
}; };
static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) static irqreturn_t hdmi_irq_thread(int irq, void *arg)
{ {
struct exynos_drm_hdmi_context *ctx = arg; struct exynos_drm_hdmi_context *ctx = arg;
struct hdmi_context *hdata = ctx->ctx; struct hdmi_context *hdata = ctx->ctx;
...@@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) ...@@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
{
struct exynos_drm_hdmi_context *ctx = arg;
struct hdmi_context *hdata = ctx->ctx;
u32 intc_flag;
intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
/* clearing flags for HPD plug/unplug */
if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
DRM_DEBUG_KMS("unplugged\n");
hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
HDMI_INTC_FLAG_HPD_UNPLUG);
}
if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
DRM_DEBUG_KMS("plugged\n");
hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
HDMI_INTC_FLAG_HPD_PLUG);
}
if (ctx->drm_dev)
drm_helper_hpd_irq_event(ctx->drm_dev);
return IRQ_HANDLED;
}
static int hdmi_resources_init(struct hdmi_context *hdata) static int hdmi_resources_init(struct hdmi_context *hdata)
{ {
struct device *dev = hdata->dev; struct device *dev = hdata->dev;
...@@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev)
hdata->hdmiphy_port = hdmi_hdmiphy; hdata->hdmiphy_port = hdmi_hdmiphy;
hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); hdata->irq = gpio_to_irq(hdata->hpd_gpio);
if (hdata->external_irq < 0) { if (hdata->irq < 0) {
DRM_ERROR("failed to get GPIO external irq\n"); DRM_ERROR("failed to get GPIO irq\n");
ret = hdata->external_irq; ret = hdata->irq;
goto err_hdmiphy;
}
hdata->internal_irq = platform_get_irq(pdev, 0);
if (hdata->internal_irq < 0) {
DRM_ERROR("failed to get platform internal irq\n");
ret = hdata->internal_irq;
goto err_hdmiphy; goto err_hdmiphy;
} }
hdata->hpd = gpio_get_value(hdata->hpd_gpio); hdata->hpd = gpio_get_value(hdata->hpd_gpio);
ret = request_threaded_irq(hdata->external_irq, NULL, ret = request_threaded_irq(hdata->irq, NULL,
hdmi_external_irq_thread, IRQF_TRIGGER_RISING | hdmi_irq_thread, IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"hdmi_external", drm_hdmi_ctx); "hdmi", drm_hdmi_ctx);
if (ret) { if (ret) {
DRM_ERROR("failed to register hdmi external interrupt\n"); DRM_ERROR("failed to register hdmi interrupt\n");
goto err_hdmiphy; goto err_hdmiphy;
} }
ret = request_threaded_irq(hdata->internal_irq, NULL,
hdmi_internal_irq_thread, IRQF_ONESHOT,
"hdmi_internal", drm_hdmi_ctx);
if (ret) {
DRM_ERROR("failed to register hdmi internal interrupt\n");
goto err_free_irq;
}
/* Attach HDMI Driver to common hdmi. */ /* Attach HDMI Driver to common hdmi. */
exynos_hdmi_drv_attach(drm_hdmi_ctx); exynos_hdmi_drv_attach(drm_hdmi_ctx);
...@@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev) ...@@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev)
return 0; return 0;
err_free_irq:
free_irq(hdata->external_irq, drm_hdmi_ctx);
err_hdmiphy: err_hdmiphy:
i2c_del_driver(&hdmiphy_driver); i2c_del_driver(&hdmiphy_driver);
err_ddc: err_ddc:
...@@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev) ...@@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev)
pm_runtime_disable(dev); pm_runtime_disable(dev);
free_irq(hdata->internal_irq, hdata); free_irq(hdata->irq, hdata);
free_irq(hdata->external_irq, hdata);
/* hdmiphy i2c driver */ /* hdmiphy i2c driver */
...@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev) ...@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev)
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
disable_irq(hdata->internal_irq); disable_irq(hdata->irq);
disable_irq(hdata->external_irq);
hdata->hpd = false; hdata->hpd = false;
if (ctx->drm_dev) if (ctx->drm_dev)
...@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev) ...@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev)
hdata->hpd = gpio_get_value(hdata->hpd_gpio); hdata->hpd = gpio_get_value(hdata->hpd_gpio);
enable_irq(hdata->external_irq); enable_irq(hdata->irq);
enable_irq(hdata->internal_irq);
if (!pm_runtime_suspended(dev)) { if (!pm_runtime_suspended(dev)) {
DRM_DEBUG_KMS("%s : Already resumed\n", __func__); DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
......
...@@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx) ...@@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx)
/* waiting until VP_SRESET_PROCESSING is 0 */ /* waiting until VP_SRESET_PROCESSING is 0 */
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
break; break;
mdelay(10); usleep_range(10000, 12000);
} }
WARN(tries == 0, "failed to reset Video Processor\n"); WARN(tries == 0, "failed to reset Video Processor\n");
} }
...@@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win) ...@@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win)
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
mutex_lock(&mixer_ctx->mixer_mutex);
if (!mixer_ctx->powered) {
mutex_unlock(&mixer_ctx->mixer_mutex);
return;
}
mutex_unlock(&mixer_ctx->mixer_mutex);
if (win > 1 && mixer_ctx->vp_enabled) if (win > 1 && mixer_ctx->vp_enabled)
vp_video_buffer(mixer_ctx, win); vp_video_buffer(mixer_ctx, win);
else else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册