diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-02 17:52:19 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-02 17:52:19 -0800 |
commit | f2f1756d7de37cc8ca17705c5bc3dfcbfb589ab9 (patch) | |
tree | 49d28fd08917f7a4e03b0bb983f2ecf2388681f8 /drivers | |
parent | b8ef289daa313b3e5eb6564ed1c2758ddb6e3d6f (diff) | |
parent | bed3c1de66d04f9e5efcdfc5b8035f3354c4ffcc (diff) |
Merge branch 'media_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'media_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6:
[media] fix saa7111 non-detection
[media] rc/streamzap: fix reporting response times
[media] mceusb: really fix remaining keybounce issues
[media] rc: use time unit conversion macros correctly
[media] rc/ir-lirc-codec: add back debug spew
[media] ir-kbd-i2c: improve remote behavior with z8 behind usb
[media] lirc_zilog: z8 on usb doesn't like back-to-back i2c_master_send
[media] hdpvr: fix up i2c device registration
[media] rc/mce: add mappings for missing keys
[media] gspca - zc3xx: Discard the partial frames
[media] gspca - zc3xx: Fix bad images with the sensor hv7131r
[media] gspca - zc3xx: Bad delay when given by a table
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/rc/ir-lirc-codec.c | 6 | ||||
-rw-r--r-- | drivers/media/rc/keymaps/rc-rc6-mce.c | 6 | ||||
-rw-r--r-- | drivers/media/rc/mceusb.c | 9 | ||||
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 6 | ||||
-rw-r--r-- | drivers/media/rc/streamzap.c | 14 | ||||
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 31 | ||||
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr-core.c | 24 | ||||
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr-i2c.c | 30 | ||||
-rw-r--r-- | drivers/media/video/hdpvr/hdpvr.h | 3 | ||||
-rw-r--r-- | drivers/media/video/ir-kbd-i2c.c | 13 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 | ||||
-rw-r--r-- | drivers/media/video/saa7115.c | 2 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_zilog.c | 32 |
13 files changed, 135 insertions, 42 deletions
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index f011c5d9dea1..1c5cc65ea1e1 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -1,4 +1,4 @@ -/* ir-lirc-codec.c - ir-core to classic lirc interface bridge +/* ir-lirc-codec.c - rc-core to classic lirc interface bridge * * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com> * @@ -47,6 +47,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) /* Carrier reports */ if (ev.carrier_report) { sample = LIRC_FREQUENCY(ev.carrier); + IR_dprintk(2, "carrier report (freq: %d)\n", sample); /* Packet end */ } else if (ev.timeout) { @@ -62,6 +63,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) return 0; sample = LIRC_TIMEOUT(ev.duration / 1000); + IR_dprintk(2, "timeout report (duration: %d)\n", sample); /* Normal sample */ } else { @@ -85,6 +87,8 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : LIRC_SPACE(ev.duration / 1000); + IR_dprintk(2, "delivering %uus %s to lirc_dev\n", + TO_US(ev.duration), TO_STR(ev.pulse)); } lirc_buffer_write(dev->raw->lirc.drv->rbuf, diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index 3bf3337875d1..2f5dc0622b94 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -3,6 +3,9 @@ * * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com> * + * See http://mediacenterguides.com/book/export/html/31 for details on + * key mappings. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -60,6 +63,9 @@ static struct rc_map_table rc6_mce[] = { { 0x800f0426, KEY_EPG }, /* Guide */ { 0x800f0427, KEY_ZOOM }, /* Aspect */ + { 0x800f0432, KEY_MODE }, /* Visualization */ + { 0x800f0433, KEY_PRESENTATION }, /* Slide Show */ + { 0x800f0434, KEY_EJECTCD }, { 0x800f043a, KEY_BRIGHTNESSUP }, { 0x800f0446, KEY_TV }, diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 079353e5d558..6df0a4980645 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -816,7 +816,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) switch (ir->buf_in[index]) { /* 2-byte return value commands */ case MCE_CMD_S_TIMEOUT: - ir->rc->timeout = MS_TO_NS((hi << 8 | lo) / 2); + ir->rc->timeout = US_TO_NS((hi << 8 | lo) / 2); break; /* 1-byte return value commands */ @@ -855,9 +855,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) break; case PARSE_IRDATA: ir->rem--; + init_ir_raw_event(&rawir); rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) - * MS_TO_US(MCE_TIME_UNIT); + * US_TO_NS(MCE_TIME_UNIT); dev_dbg(ir->dev, "Storing %s with duration %d\n", rawir.pulse ? "pulse" : "space", @@ -883,6 +884,8 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) i, ir->rem + 1, false); if (ir->rem) ir->parser_state = PARSE_IRDATA; + else + ir_raw_event_reset(ir->rc); break; } @@ -1060,7 +1063,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) rc->priv = ir; rc->driver_type = RC_DRIVER_IR_RAW; rc->allowed_protos = RC_TYPE_ALL; - rc->timeout = MS_TO_NS(1000); + rc->timeout = US_TO_NS(1000); if (!ir->flags.no_tx) { rc->s_tx_mask = mceusb_set_tx_mask; rc->s_tx_carrier = mceusb_set_tx_carrier; diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index dd4caf8ef80b..273d9d674792 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -460,7 +460,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) return 0; } - carrier = (count * 1000000) / duration; + carrier = MS_TO_NS(count) / duration; if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) nvt_dbg("WTF? Carrier frequency out of range!"); @@ -612,8 +612,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) sample = nvt->buf[i]; rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); - rawir.duration = (sample & BUF_LEN_MASK) - * SAMPLE_PERIOD * 1000; + rawir.duration = US_TO_NS((sample & BUF_LEN_MASK) + * SAMPLE_PERIOD); if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { if (nvt->rawir.pulse == rawir.pulse) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 6e2911c2abfb..e435d94c0776 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -164,7 +164,7 @@ static void sz_push_full_pulse(struct streamzap_ir *sz, sz->signal_start.tv_usec - sz->signal_last.tv_usec); rawir.duration -= sz->sum; - rawir.duration *= 1000; + rawir.duration = US_TO_NS(rawir.duration); rawir.duration &= IR_MAX_DURATION; } sz_push(sz, rawir); @@ -177,7 +177,7 @@ static void sz_push_full_pulse(struct streamzap_ir *sz, rawir.duration = ((int) value) * SZ_RESOLUTION; rawir.duration += SZ_RESOLUTION / 2; sz->sum += rawir.duration; - rawir.duration *= 1000; + rawir.duration = US_TO_NS(rawir.duration); rawir.duration &= IR_MAX_DURATION; sz_push(sz, rawir); } @@ -197,7 +197,7 @@ static void sz_push_full_space(struct streamzap_ir *sz, rawir.duration = ((int) value) * SZ_RESOLUTION; rawir.duration += SZ_RESOLUTION / 2; sz->sum += rawir.duration; - rawir.duration *= 1000; + rawir.duration = US_TO_NS(rawir.duration); sz_push(sz, rawir); } @@ -273,6 +273,7 @@ static void streamzap_callback(struct urb *urb) if (sz->timeout_enabled) sz_push(sz, rawir); ir_raw_event_handle(sz->rdev); + ir_raw_event_reset(sz->rdev); } else { sz_push_full_space(sz, sz->buf_in[i]); } @@ -290,6 +291,7 @@ static void streamzap_callback(struct urb *urb) } } + ir_raw_event_handle(sz->rdev); usb_submit_urb(urb, GFP_ATOMIC); return; @@ -430,13 +432,13 @@ static int __devinit streamzap_probe(struct usb_interface *intf, sz->decoder_state = PulseSpace; /* FIXME: don't yet have a way to set this */ sz->timeout_enabled = true; - sz->rdev->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & + sz->rdev->timeout = ((US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION) & IR_MAX_DURATION) | 0x03000000); #if 0 /* not yet supported, depends on patches from maxim */ /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ - sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; - sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; + sz->min_timeout = US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION); + sz->max_timeout = US_TO_NS(SZ_TIMEOUT * SZ_RESOLUTION); #endif do_gettimeofday(&sz->signal_start); diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 865216e9362c..47236a58bf33 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -5793,7 +5793,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, break; default: /* case 0xdd: * delay */ - msleep(action->val / 64 + 10); + msleep(action->idx); break; } action++; @@ -5830,7 +5830,7 @@ static void setmatrix(struct gspca_dev *gspca_dev) [SENSOR_GC0305] = gc0305_matrix, [SENSOR_HDCS2020b] = NULL, [SENSOR_HV7131B] = NULL, - [SENSOR_HV7131R] = NULL, + [SENSOR_HV7131R] = po2030_matrix, [SENSOR_ICM105A] = po2030_matrix, [SENSOR_MC501CB] = NULL, [SENSOR_MT9V111_1] = gc0305_matrix, @@ -5936,6 +5936,7 @@ static void setquality(struct gspca_dev *gspca_dev) case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_HV7131B: + case SENSOR_HV7131R: case SENSOR_OV7620: case SENSOR_PAS202B: case SENSOR_PO2030: @@ -6108,11 +6109,13 @@ static void send_unknown(struct gspca_dev *gspca_dev, int sensor) reg_w(gspca_dev, 0x02, 0x003b); reg_w(gspca_dev, 0x00, 0x0038); break; + case SENSOR_HV7131R: case SENSOR_PAS202B: reg_w(gspca_dev, 0x03, 0x003b); reg_w(gspca_dev, 0x0c, 0x003a); reg_w(gspca_dev, 0x0b, 0x0039); - reg_w(gspca_dev, 0x0b, 0x0038); + if (sensor == SENSOR_PAS202B) + reg_w(gspca_dev, 0x0b, 0x0038); break; } } @@ -6704,10 +6707,13 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x02, 0x003b); reg_w(gspca_dev, 0x00, 0x0038); break; + case SENSOR_HV7131R: case SENSOR_PAS202B: reg_w(gspca_dev, 0x03, 0x003b); reg_w(gspca_dev, 0x0c, 0x003a); reg_w(gspca_dev, 0x0b, 0x0039); + if (sd->sensor == SENSOR_HV7131R) + reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN); break; } @@ -6720,6 +6726,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_PAS202B: case SENSOR_GC0305: + case SENSOR_HV7131R: case SENSOR_TAS5130C: reg_r(gspca_dev, 0x0008); /* fall thru */ @@ -6760,6 +6767,12 @@ static int sd_start(struct gspca_dev *gspca_dev) /* ms-win + */ reg_w(gspca_dev, 0x40, 0x0117); break; + case SENSOR_HV7131R: + i2c_write(gspca_dev, 0x25, 0x04, 0x00); /* exposure */ + i2c_write(gspca_dev, 0x26, 0x93, 0x00); + i2c_write(gspca_dev, 0x27, 0xe0, 0x00); + reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); + break; case SENSOR_GC0305: case SENSOR_TAS5130C: reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ @@ -6808,9 +6821,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ + /* check the JPEG end of frame */ + if (len >= 3 + && data[len - 3] == 0xff && data[len - 2] == 0xd9) { +/*fixme: what does the last byte mean?*/ gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); + data, len - 1); + return; + } + + /* check the JPEG start of a frame */ + if (data[0] == 0xff && data[1] == 0xd8) { /* put the JPEG header in the new frame */ gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index a6572e5ae369..a27d93b503a5 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -283,6 +283,7 @@ static int hdpvr_probe(struct usb_interface *interface, struct hdpvr_device *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + struct i2c_client *client; size_t buffer_size; int i; int retval = -ENOMEM; @@ -381,13 +382,21 @@ static int hdpvr_probe(struct usb_interface *interface, #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) retval = hdpvr_register_i2c_adapter(dev); if (retval < 0) { - v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); + v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); goto error; } - retval = hdpvr_register_i2c_ir(dev); - if (retval < 0) - v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n"); + client = hdpvr_register_ir_rx_i2c(dev); + if (!client) { + v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n"); + goto reg_fail; + } + + client = hdpvr_register_ir_tx_i2c(dev); + if (!client) { + v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n"); + goto reg_fail; + } #endif /* let the user know what node this device is now attached to */ @@ -395,6 +404,10 @@ static int hdpvr_probe(struct usb_interface *interface, video_device_node_name(dev->video_dev)); return 0; +reg_fail: +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_adapter(&dev->i2c_adapter); +#endif error: if (dev) { /* Destroy single thread */ @@ -424,6 +437,9 @@ static void hdpvr_disconnect(struct usb_interface *interface) mutex_lock(&dev->io_mutex); hdpvr_cancel_queue(dev); mutex_unlock(&dev->io_mutex); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_adapter(&dev->i2c_adapter); +#endif video_unregister_device(dev->video_dev); atomic_dec(&dev_nr); } diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 89b71faeaac2..e53fa55d56a1 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -31,26 +31,34 @@ #define Z8F0811_IR_RX_I2C_ADDR 0x71 -static struct i2c_board_info hdpvr_i2c_board_info = { - I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR), - I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR), -}; +struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev) +{ + struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; + struct i2c_board_info hdpvr_ir_tx_i2c_board_info = { + I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR), + }; + + init_data->name = "HD-PVR"; + hdpvr_ir_tx_i2c_board_info.platform_data = init_data; -int hdpvr_register_i2c_ir(struct hdpvr_device *dev) + return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info); +} + +struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev) { - struct i2c_client *c; struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; + struct i2c_board_info hdpvr_ir_rx_i2c_board_info = { + I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR), + }; /* Our default information for ir-kbd-i2c.c to use */ 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"; - hdpvr_i2c_board_info.platform_data = init_data; - - c = i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info); + init_data->name = "HD-PVR"; + hdpvr_ir_rx_i2c_board_info.platform_data = init_data; - return (c == NULL) ? -ENODEV : 0; + return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info); } static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index ee74e3be9a6a..072f23c570f3 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -313,7 +313,8 @@ int hdpvr_cancel_queue(struct hdpvr_device *dev); /* i2c adapter registration */ int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); -int hdpvr_register_i2c_ir(struct hdpvr_device *dev); +struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev); +struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev); /*========================================================================*/ /* buffer management */ diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index d2b20ad383a3..a221ad68b330 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -128,6 +128,19 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { + int ret; + unsigned char buf[1] = { 0 }; + + /* + * This is the same apparent "are you ready?" poll command observed + * watching Windows driver traffic and implemented in lirc_zilog. With + * this added, we get far saner remote behavior with z8 chips on usb + * connected devices, even with the default polling interval of 100ms. + */ + ret = i2c_master_send(ir->c, buf, 1); + if (ret != 1) + return (ret < 0) ? ret : -EINVAL; + return get_key_haup_common (ir, ir_key, ir_raw, 6, 3); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index ccc884948f34..451ecd485f97 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -597,7 +597,6 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = RC_TYPE_RC5; init_data->name = hdw->hdw_desc->description; - init_data->polling_interval = 260; /* ms From lirc_zilog */ /* IR Receiver */ info.addr = 0x71; info.platform_data = init_data; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f35459d1f42f..0db90922ee93 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1565,7 +1565,7 @@ static int saa711x_probe(struct i2c_client *client, chip_id = name[5]; /* Check whether this chip is part of the saa711x series */ - if (memcmp(name, "1f711", 5)) { + if (memcmp(name + 1, "f711", 4)) { v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", client->addr << 1, name); return -ENODEV; diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index 3fe5f4160194..0aad0d7a74a3 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -495,7 +495,7 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block) /* send boot data to the IR TX device */ static int send_boot_data(struct IR_tx *tx) { - int ret; + int ret, i; unsigned char buf[4]; /* send the boot block */ @@ -503,7 +503,7 @@ static int send_boot_data(struct IR_tx *tx) if (ret != 0) return ret; - /* kick it off? */ + /* Hit the go button to activate the new boot data */ buf[0] = 0x00; buf[1] = 0x20; ret = i2c_master_send(tx->c, buf, 2); @@ -511,7 +511,19 @@ static int send_boot_data(struct IR_tx *tx) zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } - ret = i2c_master_send(tx->c, buf, 1); + + /* + * Wait for zilog to settle after hitting go post boot block upload. + * Without this delay, the HD-PVR and HVR-1950 both return an -EIO + * upon attempting to get firmware revision, and tx probe thus fails. + */ + for (i = 0; i < 10; i++) { + ret = i2c_master_send(tx->c, buf, 1); + if (ret == 1) + break; + udelay(100); + } + if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; @@ -523,8 +535,8 @@ static int send_boot_data(struct IR_tx *tx) zilog_error("i2c_master_recv failed with %d\n", ret); return 0; } - if (buf[0] != 0x80) { - zilog_error("unexpected IR TX response: %02x\n", buf[0]); + if ((buf[0] != 0x80) && (buf[0] != 0xa0)) { + zilog_error("unexpected IR TX init response: %02x\n", buf[0]); return 0; } zilog_notify("Zilog/Hauppauge IR blaster firmware version " @@ -827,7 +839,15 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } - ret = i2c_master_send(tx->c, buf, 1); + + /* Give the z8 a moment to process data block */ + for (i = 0; i < 10; i++) { + ret = i2c_master_send(tx->c, buf, 1); + if (ret == 1) + break; + udelay(100); + } + if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; |