From a5663a2a616b5d3918e6949788bd7d2cf88d8313 Mon Sep 17 00:00:00 2001 From: kfx Date: Sat, 14 May 2011 16:58:22 +0800 Subject: [PATCH] update hdmi dirver: unregister err and update i2c driver:support direct mode --- drivers/i2c/busses/i2c-rk29.c | 21 ++++++++++++++-- drivers/i2c/i2c-core.c | 27 +++++++++++++++++++++ drivers/video/hdmi/hdmi-new/chips/anx7150.c | 4 +-- drivers/video/hdmi/hdmi-new/hdmi-core.c | 9 +++++-- drivers/video/hdmi/hdmi-old/hdmi-core.c | 9 +++++-- include/linux/i2c.h | 3 ++- 6 files changed, 64 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk29.c b/drivers/i2c/busses/i2c-rk29.c index 1b8e6c73c1b8..a2b5b30d3d51 100755 --- a/drivers/i2c/busses/i2c-rk29.c +++ b/drivers/i2c/busses/i2c-rk29.c @@ -484,8 +484,25 @@ static int rk29_xfer_msg(struct i2c_adapter *adap, goto exit; } if(msg->flags & I2C_M_RD) - { - if((ret = rk29_i2c_recv_msg(i2c, msg)) != 0) + { + if(msg->flags & I2C_M_REG8_DIRECT) + { + struct i2c_msg msg1 = *msg; + struct i2c_msg msg2 = *msg; + msg1.len = 1; + msg2.len = msg->len - 1; + msg2.buf = msg->buf + 1; + + if((ret = rk29_i2c_send_msg(i2c, &msg1)) != 0) + i2c_err(i2c->dev, "rk29_i2c_send_msg timeout\n"); + if((ret = rk29_i2c_recv_msg(i2c, &msg2)) != 0) + { + i2c_err(i2c->dev, "rk29_i2c_recv_msg timeout\n"); + goto exit; + } + + } + else if((ret = rk29_i2c_recv_msg(i2c, msg)) != 0) { i2c_err(i2c->dev, "rk29_i2c_recv_msg timeout\n"); goto exit; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 48862c7c776a..4b728449fa6c 100755 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1315,6 +1315,33 @@ int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, i EXPORT_SYMBOL(i2c_master_reg8_recv); +int i2c_master_reg8_direct_send(struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate) +{ + return i2c_master_reg8_send(client, reg, buf, count, scl_rate); +} +EXPORT_SYMBOL(i2c_master_reg8_direct_send); + +int i2c_master_reg8_direct_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate) +{ + struct i2c_adapter *adap=client->adapter; + struct i2c_msg msg; + int ret; + char tx_buf[count+1]; + + tx_buf[0] = reg; + msg.addr = client->addr; + msg.flags = client->flags | I2C_M_REG8_DIRECT | I2C_M_RD; + msg.len = count + 1; + msg.buf = tx_buf; + msg.scl_rate = scl_rate; + msg.udelay = client->udelay; + + ret = i2c_transfer(adap, &msg, 1); + memcpy(buf, tx_buf + 1, count); + return (ret == 1) ? count : ret; +} +EXPORT_SYMBOL(i2c_master_reg8_direct_recv); + int i2c_master_reg16_send(struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate) { struct i2c_adapter *adap=client->adapter; diff --git a/drivers/video/hdmi/hdmi-new/chips/anx7150.c b/drivers/video/hdmi/hdmi-new/chips/anx7150.c index a87bc0dc7560..bc0866042639 100755 --- a/drivers/video/hdmi/hdmi-new/chips/anx7150.c +++ b/drivers/video/hdmi/hdmi-new/chips/anx7150.c @@ -258,7 +258,7 @@ static int anx7150_i2c_probe(struct i2c_client *client,const struct i2c_device_i dev_info(&client->dev, "anx7150 i2c probe ok\n"); return 0; err_free_irq: - free_irq(anx->irq, hdmi); + free_irq(anx->irq, NULL); err_gpio_free: gpio_free(client->irq); err_hdmi_unregister: @@ -272,7 +272,7 @@ static int __devexit anx7150_i2c_remove(struct i2c_client *client) struct anx7150_pdata *anx = (struct anx7150_pdata *)i2c_get_clientdata(client); struct hdmi *hdmi = anx->hdmi; - free_irq(anx->irq, anx); + free_irq(anx->irq, NULL); gpio_free(client->irq); hdmi_unregister(hdmi); anx = NULL; diff --git a/drivers/video/hdmi/hdmi-new/hdmi-core.c b/drivers/video/hdmi/hdmi-new/hdmi-core.c index b134ae422129..34132c1692c1 100755 --- a/drivers/video/hdmi/hdmi-new/hdmi-core.c +++ b/drivers/video/hdmi/hdmi-new/hdmi-core.c @@ -117,14 +117,19 @@ success: } void hdmi_unregister(struct hdmi *hdmi) { + int id; + + if(!hdmi) + return; + id = hdmi->id; flush_scheduled_work(); hdmi_remove_attrs(hdmi); device_unregister(hdmi->dev); kfree(hdmi); hdmi = NULL; - ref_info[hdmi->id].ref = 0; - ref_info[hdmi->id].hdmi = NULL; + ref_info[id].ref = 0; + ref_info[id].hdmi = NULL; } struct hdmi *get_hdmi_struct(int nr) { diff --git a/drivers/video/hdmi/hdmi-old/hdmi-core.c b/drivers/video/hdmi/hdmi-old/hdmi-core.c index 5375f6c20916..6b03ab29562e 100755 --- a/drivers/video/hdmi/hdmi-old/hdmi-core.c +++ b/drivers/video/hdmi/hdmi-old/hdmi-core.c @@ -97,11 +97,16 @@ success: } void hdmi_unregister(struct hdmi *hdmi) { + int id; + + if(!hdmi) + return; + id = hdmi->id; flush_scheduled_work(); hdmi_remove_attrs(hdmi); device_unregister(hdmi->dev); - ref_info[hdmi->id].ref = 0; - ref_info[hdmi->id].hdmi = NULL; + ref_info[id].ref = 0; + ref_info[id].hdmi = NULL; } struct hdmi *get_hdmi_struct(int nr) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 82828c02105b..8d3d0315ef62 100755 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -522,7 +522,8 @@ struct i2c_msg { #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ -#define I2C_M_NEED_DELAY 0x8000 // add by kfx +#define I2C_M_NEED_DELAY 0x0020 // add by kfx +#define I2C_M_REG8_DIRECT 0x0040 // add by kfx __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ __u32 scl_rate; // add by kfx -- 2.34.1