From patchwork Sun Jan 16 03:49:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Walls X-Patchwork-Id: 481661 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0G4uONu007118 for ; Sun, 16 Jan 2011 04:56:25 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754385Ab1APDuW (ORCPT ); Sat, 15 Jan 2011 22:50:22 -0500 Received: from proofpoint-cluster.metrocast.net ([65.175.128.136]:5092 "EHLO proofpoint-cluster.metrocast.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754353Ab1APDuV (ORCPT ); Sat, 15 Jan 2011 22:50:21 -0500 Received: from [192.168.1.2] (d-216-36-28-191.cpe.metrocast.net [216.36.28.191]) (authenticated bits=0) by pear.metrocast.net (8.13.8/8.13.8) with ESMTP id p0G3np2a010567; Sun, 16 Jan 2011 03:49:51 GMT Subject: [RFC PATCH] ir-kbd-i2c, lirc_zilog: Allow bridge drivers to pass an IR trasnceiver mutex to I2C IR modules From: Andy Walls To: Jarod Wilson , Jean Delvare , Linux Media Mailing List , Janne Grunau , Jarod Wilson Cc: Mauro Carvalho Chehab Date: Sat, 15 Jan 2011 22:49:48 -0500 Message-ID: <1295149788.7147.34.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.28.3 (2.28.3-1.fc12) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.2.15, 1.0.148, 0.0.0000 definitions=2011-01-07_07:2011-01-07, 2011-01-07, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 ipscore=0 suspectscore=0 phishscore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx engine=5.0.0-1012030000 definitions=main-1101070029 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sun, 16 Jan 2011 04:56:25 +0000 (UTC) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 676e5be..da1ef93 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -701,6 +701,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->serialize_lock); mutex_init(&cx->gpio_lock); + mutex_init(&cx->ir_transceiver_lock); mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index f6f3e50..82dc747 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -626,6 +626,7 @@ struct cx18 { struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; struct IR_i2c_init_data ir_i2c_init_data; + struct mutex ir_transceiver_lock; /* gpio */ u32 gpio_dir; diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index c330fb9..7782de1 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -96,10 +96,12 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: + case CX18_HW_Z8F0811_IR_TX_HAUP: init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = RC_TYPE_RC5; init_data->name = cx->card_name; + init_data->transceiver_lock = &cx->ir_transceiver_lock; info.platform_data = init_data; break; } diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index f7d1ee5..df4a02a 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -304,6 +304,7 @@ static int hdpvr_probe(struct usb_interface *interface, mutex_init(&dev->io_mutex); mutex_init(&dev->i2c_mutex); + mutex_init(&dev->ir_transceiver_mutex); mutex_init(&dev->usbc_mutex); dev->usbc_buf = kmalloc(64, GFP_KERNEL); if (!dev->usbc_buf) { diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 24966aa..b1e68b8 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -48,13 +48,15 @@ static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap, memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, type, I2C_NAME_SIZE); - /* Our default information for ir-kbd-i2c.c to use */ + /* Our default information for ir-kbd-i2c.c and lirc_zilog.c to use */ switch (addr) { case Z8F0811_IR_RX_I2C_ADDR: + case Z8F0811_IR_TX_I2C_ADDR: init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = RC_TYPE_RC5; init_data->name = "HD PVR"; + init_data->transceiver_lock = &dev->ir_transceiver_mutex; info.platform_data = init_data; break; } diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 37f1e4c..00c8563 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -112,6 +112,7 @@ struct hdpvr_device { /* For passing data to ir-kbd-i2c */ struct IR_i2c_init_data ir_i2c_init_data; + struct mutex ir_transceiver_mutex; /* usb control transfer buffer and lock */ struct mutex usbc_mutex; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index c87b6bc..6714e1e 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -245,7 +245,15 @@ static void ir_key_poll(struct IR_i2c *ir) int rc; dprintk(2,"ir_poll_key\n"); + + if (ir->transceiver_lock) + mutex_lock(ir->transceiver_lock); + rc = ir->get_key(ir, &ir_key, &ir_raw); + + if (ir->transceiver_lock) + mutex_unlock(ir->transceiver_lock); + if (rc < 0) { dprintk(2,"error\n"); return; @@ -362,6 +370,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->get_key = get_key_avermedia_cardbus; break; } + + ir->transceiver_lock = init_data->transceiver_lock; } if (!rc) { diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 3994642..ea2afeb 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -713,6 +713,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ mutex_init(&itv->serialize_lock); + mutex_init(&itv->ir_transceiver_lock); mutex_init(&itv->i2c_bus_lock); mutex_init(&itv->udma.lock); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 04bacdb..2c8d7c1 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -699,6 +699,7 @@ struct ivtv { struct mutex i2c_bus_lock; /* lock i2c bus */ struct IR_i2c_init_data ir_i2c_init_data; + struct mutex ir_transceiver_lock; /* Program Index information */ u32 pgm_info_offset; /* start of pgm info in encoder memory */ diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index e103b8f..4233b48 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -184,7 +184,21 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) if (hw & IVTV_HW_IR_TX_ANY) { if (itv->hw_flags & IVTV_HW_IR_TX_ANY) return -1; + + /* Our default information for lirc_zilog.c to use */ + switch (hw) { + case IVTV_HW_Z8F0811_IR_TX_HAUP: + /* Default to grey remote */ + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = + IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = itv->card_name; + init_data->transceiver_lock = &itv->ir_transceiver_lock; + break; + } memset(&info, 0, sizeof(struct i2c_board_info)); + info.platform_data = init_data; strlcpy(info.type, type, I2C_NAME_SIZE); return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? -1 : 0; @@ -217,6 +231,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; + init_data->transceiver_lock = &itv->ir_transceiver_lock; break; case IVTV_HW_I2C_IR_RX_ADAPTEC: init_data->get_key = get_key_adaptec; diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index 18fae54..8185581 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -59,6 +59,7 @@ #include #include +#include struct IR_rx { /* RX device */ @@ -89,6 +90,7 @@ struct IR { struct lirc_driver l; struct mutex ir_lock; + struct mutex *xcvr_lock; int open; struct i2c_adapter *adapter; @@ -175,10 +177,10 @@ static int add_to_buf(struct IR *ir) * Lock i2c bus for the duration. RX/TX chips interfere so * this is worth it */ - mutex_lock(&ir->ir_lock); + mutex_lock(ir->xcvr_lock); if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return -ENODATA; } @@ -190,7 +192,7 @@ static int add_to_buf(struct IR *ir) if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); if (failures >= 3) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); zilog_error("unable to read from the IR chip " "after 3 resets, giving up\n"); return ret; @@ -202,23 +204,23 @@ static int add_to_buf(struct IR *ir) set_current_state(TASK_UNINTERRUPTIBLE); if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return -ENODATA; } schedule_timeout((100 * HZ + 999) / 1000); ir->tx->need_boot = 1; ++failures; - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); continue; } if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return -ENODATA; } ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); if (ret != sizeof(keybuf)) { zilog_error("i2c_master_recv failed with %d -- " "keeping last read buffer\n", ret); @@ -920,7 +922,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, return -EINVAL; /* Lock i2c bus for the duration */ - mutex_lock(&ir->ir_lock); + mutex_lock(ir->xcvr_lock); /* Send each keypress */ for (i = 0; i < n;) { @@ -928,7 +930,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, int command; if (copy_from_user(&command, buf + i, sizeof(command))) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return -EFAULT; } @@ -944,7 +946,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, ret = send_code(tx, (unsigned)command >> 16, (unsigned)command & 0xFFFF); if (ret == -EPROTO) { - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return ret; } } @@ -961,7 +963,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, if (failures >= 3) { zilog_error("unable to send to the IR chip " "after 3 resets, giving up\n"); - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return ret; } set_current_state(TASK_UNINTERRUPTIBLE); @@ -973,7 +975,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, } /* Release i2c bus */ - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); /* All looks good */ return n; @@ -1079,15 +1081,15 @@ static int open(struct inode *node, struct file *filep) return -ENODEV; /* increment in use count */ - mutex_lock(&ir->ir_lock); + mutex_lock(ir->xcvr_lock); ++ir->open; ret = set_use_inc(ir); if (ret != 0) { --ir->open; - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return ret; } - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); /* stash our IR struct */ filep->private_data = ir; @@ -1106,10 +1108,10 @@ static int close(struct inode *node, struct file *filep) } /* decrement in use count */ - mutex_lock(&ir->ir_lock); + mutex_lock(ir->xcvr_lock); --ir->open; set_use_dec(ir); - mutex_unlock(&ir->ir_lock); + mutex_unlock(ir->xcvr_lock); return 0; } @@ -1251,6 +1253,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct IR *ir; struct i2c_adapter *adap = client->adapter; + const struct IR_i2c_init_data *init_data = client->dev.platform_data; int ret; bool tx_probe = false; @@ -1288,6 +1291,12 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->adapter = adap; mutex_init(&ir->ir_lock); + /* Use bridge driver's transceiver lock, if provided */ + if (init_data != NULL) + ir->xcvr_lock = init_data->transceiver_lock; + if (ir->xcvr_lock == NULL) + ir->xcvr_lock = &ir->ir_lock; + /* set lirc_dev stuff */ memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); ir->l.minor = minor; /* module option */ diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 768aa77..5893fd8 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -21,6 +21,7 @@ struct IR_i2c { char name[32]; char phys[32]; int (*get_key)(struct IR_i2c*, u32*, u32*); + struct mutex *transceiver_lock; }; enum ir_kbd_get_key_fn { @@ -48,5 +49,7 @@ struct IR_i2c_init_data { enum ir_kbd_get_key_fn internal_get_key_func; struct rc_dev *rc_dev; + + struct mutex *transceiver_lock; }; #endif