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:
committed by
Gerrit Code Review
parent
64cd25c62a
commit
3e89ee402e
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user