hdmi: cec: fix quick standby then wake-up crash

Change-Id: Ic0449e795e55b65112fd65c1685286fbcfbea10b
Signed-off-by: Shen Zhenyi <szy@rock-chips.com>
This commit is contained in:
Shen Zhenyi
2016-04-19 16:35:14 +08:00
committed by Gerrit Code Review
parent 64cd25c62a
commit 3e89ee402e
6 changed files with 55 additions and 27 deletions

View File

@@ -1,34 +1,54 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/firmware.h>
#include <linux/ioctl.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include "rockchip-hdmi-cec.h"
#include "linux/ioctl.h"
#include "linux/pagemap.h"
static struct cec_device *cec_dev;
static int cecreadframe(struct cec_framedata *frame)
{
if (frame == NULL || !cec_dev ||
cec_dev->readframe == NULL || !cec_dev->enable)
return -1;
else
return cec_dev->readframe(cec_dev->hdmi, frame);
int ret = -1;
if (!frame || !cec_dev || !cec_dev->readframe || !cec_dev->enable) {
return ret;
} else {
mutex_lock(&cec_dev->hdmi->pclk_lock);
ret = cec_dev->readframe(cec_dev->hdmi, frame);
mutex_unlock(&cec_dev->hdmi->pclk_lock);
return ret;
}
}
static int cecsendframe(struct cec_framedata *frame)
{
if (frame == NULL || !cec_dev || cec_dev->readframe == NULL)
return -1;
else
return cec_dev->sendframe(cec_dev->hdmi, frame);
int ret = -1;
if (!frame || !cec_dev || !cec_dev->sendframe) {
return ret;
} else {
mutex_lock(&cec_dev->hdmi->pclk_lock);
ret = cec_dev->sendframe(cec_dev->hdmi, frame);
mutex_unlock(&cec_dev->hdmi->pclk_lock);
return ret;
}
}
static void cecsetlogicaddr(int addr)
{
if (!cec_dev || !cec_dev->setceclogicaddr) {
return;
} else {
mutex_lock(&cec_dev->hdmi->pclk_lock);
cec_dev->setceclogicaddr(cec_dev->hdmi, addr);
mutex_unlock(&cec_dev->hdmi->pclk_lock);
}
}
static void cecworkfunc(struct work_struct *work)
@@ -191,9 +211,7 @@ static long cec_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case HDMI_IOCTL_CECSETLA:
ret = copy_from_user(&cec_dev->address_logic,
argp, sizeof(int));
if (cec_dev->setceclogicaddr)
cec_dev->setceclogicaddr(cec_dev->hdmi,
cec_dev->address_logic);
cecsetlogicaddr(cec_dev->address_logic);
break;
case HDMI_IOCTL_CECSEND:
ret = copy_from_user(&cecsendtemp, argp,

View File

@@ -488,6 +488,7 @@ struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
memset(hdmi, 0, sizeof(struct hdmi));
mutex_init(&hdmi->lock);
mutex_init(&hdmi->pclk_lock);
hdmi->property = property;
hdmi->ops = ops;

View File

@@ -393,6 +393,7 @@ struct hdmi {
struct hdmi_ops *ops;
struct mutex lock; /* mutex for hdmi operation */
struct mutex pclk_lock; /* mutex for pclk operation */
struct workqueue_struct *workqueue;
bool uboot; /* if true, HDMI is initialized in uboot*/

View File

@@ -200,12 +200,6 @@ void ext_pll_set_27m_out(void)
0x1d);
}
#define HDMI_PD_ON (1 << 0)
#define HDMI_PCLK_ON (1 << 1)
#define HDMI_HDCPCLK_ON (1 << 2)
#define HDMI_CECCLK_ON (1 << 3)
#define HDMI_EXT_PHY_CLK_ON (1 << 4)
static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
{
if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
@@ -334,7 +328,9 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
0, 1);
if (hdmi_dev->hdcp2_en)
hdmi_dev->hdcp2_en(0);
mutex_lock(&hdmi->pclk_lock);
rockchip_hdmiv2_clk_disable(hdmi_dev);
mutex_unlock(&hdmi->pclk_lock);
#ifdef CONFIG_PINCTRL
if (hdmi_dev->soctype == HDMI_SOC_RK3288)
gpio_state =
@@ -359,7 +355,9 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
pinctrl_select_state(pins->p,
pins->default_state);
#endif
mutex_lock(&hdmi->pclk_lock);
rockchip_hdmiv2_clk_enable(hdmi_dev);
mutex_unlock(&hdmi->pclk_lock);
rockchip_hdmiv2_dev_initial(hdmi_dev);
if (hdmi->ops->hdcp_power_on_cb)
hdmi->ops->hdcp_power_on_cb();

View File

@@ -15,6 +15,12 @@
#define HDMIDBG(format, ...)
#endif
#define HDMI_PD_ON BIT(0)
#define HDMI_PCLK_ON BIT(1)
#define HDMI_HDCPCLK_ON BIT(2)
#define HDMI_CECCLK_ON BIT(3)
#define HDMI_EXT_PHY_CLK_ON BIT(4)
struct hdmi_dev_phy_para {
u32 maxfreq;
int pre_emphasis;

View File

@@ -21,7 +21,7 @@ static int rockchip_hdmiv2_cec_readframe(struct hdmi *hdmi,
int i, count;
char *data = (char *)frame;
if (frame == NULL)
if (((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) || !frame)
return -1;
count = hdmi_readl(hdmi_dev, CEC_RX_CNT);
CECDBG("%s count %d\n", __func__, count);
@@ -40,6 +40,8 @@ void rockchip_hdmiv2_cec_setcecla(struct hdmi *hdmi, int ceclgaddr)
struct hdmi_dev *hdmi_dev = hdmi->property->priv;
short val;
if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0)
return;
if (ceclgaddr < 0 || ceclgaddr > 16)
return;
val = 1 << ceclgaddr;
@@ -53,6 +55,8 @@ static int rockchip_hdmiv2_cec_sendframe(struct hdmi *hdmi,
struct hdmi_dev *hdmi_dev = hdmi->property->priv;
int i, interrupt;
if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0)
return CEC_SEND_NACK;
CECDBG("TX srcdestaddr %02x opcode %02x ",
frame->srcdestaddr, frame->opcode);
if (frame->argcount) {