diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-08-27 15:37:44 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-08-27 15:37:44 -0300 |
commit | 9976ff45b0466fd6f4af371ea858da991303d254 (patch) | |
tree | b018122b1e146b4a4cc082f7f01e2a11a66dba2e /linux/drivers/media/video | |
parent | 400532679931f60d0cc69daf583c0687c9d3a0bf (diff) | |
parent | 2f20e641a6d539f439414588e220787eb28a954c (diff) | |
download | mediapointer-dvb-s2-9976ff45b0466fd6f4af371ea858da991303d254.tar.gz mediapointer-dvb-s2-9976ff45b0466fd6f4af371ea858da991303d254.tar.bz2 |
merge: http://linuxtv.org/hg/~hverkuil/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r-- | linux/drivers/media/video/cx25840/cx25840-core.c | 55 | ||||
-rw-r--r-- | linux/drivers/media/video/cx25840/cx25840-core.h | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-i2c.c | 2 |
3 files changed, 50 insertions, 11 deletions
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 49b43f2a1..2a24fc38a 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -190,9 +190,24 @@ static void cx25836_initialize(struct i2c_client *client) cx25840_and_or(client, 0x15b, ~0x1e, 0x10); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +static void cx25840_work_handler(struct work_struct *work) +{ + struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work); +#else +void cx25840_work_handler(void *arg) +{ + struct cx25840_state *state = arg; +#endif + cx25840_loadfw(state->c); + wake_up(&state->fw_wait); +} + static void cx25840_initialize(struct i2c_client *client) { + DEFINE_WAIT(wait); struct cx25840_state *state = i2c_get_clientdata(client); + struct workqueue_struct *q; /* datasheet startup in numbered steps, refer to page 3-77 */ /* 2. */ @@ -208,7 +223,23 @@ static void cx25840_initialize(struct i2c_client *client) cx25840_write(client, 0x13c, 0x01); cx25840_write(client, 0x13c, 0x00); /* 5. */ - cx25840_loadfw(client); + /* Do the firmware load in a work handler to prevent. + Otherwise the kernel is blocked waiting for the + bit-banging i2c interface to finish uploading the + firmware. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&state->fw_work, cx25840_work_handler); +#else + INIT_WORK(&state->fw_work, cx25840_work_handler, state); +#endif + init_waitqueue_head(&state->fw_wait); + q = create_singlethread_workqueue("cx25840_fw"); + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + /* 6. */ cx25840_write(client, 0x115, 0x8c); cx25840_write(client, 0x116, 0x07); @@ -890,11 +921,10 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, #endif return 0; - state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); - if (state == 0) + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) return -ENOMEM; - client = &state->c; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_cx25840; @@ -903,7 +933,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, #endif snprintf(client->name, sizeof(client->name) - 1, "cx25840"); - v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1); + v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1); device_id = cx25840_read(client, 0x101) << 8; device_id |= cx25840_read(client, 0x100); @@ -912,26 +942,32 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, * 0x83 for the cx2583x and 0x84 for the cx2584x */ if ((device_id & 0xff00) == 0x8300) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; - state->is_cx25836 = 1; } else if ((device_id & 0xff00) == 0x8400) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); - state->is_cx25836 = 0; } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); - kfree(state); + kfree(client); return 0; } + state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + /* Note: revision '(device_id & 0x0f) == 2' was never built. The marking skips from 0x1 == 22 to 0x3 == 23. */ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", (device_id & 0xfff0) >> 4, (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), - address << 1, adapter->name); + client->addr << 1, client->adapter->name); i2c_set_clientdata(client, state); + state->c = client; + state->is_cx25836 = ((device_id & 0xff00) == 0x8300); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; @@ -972,6 +1008,7 @@ static int cx25840_detach_client(struct i2c_client *client) } kfree(state); + kfree(client); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index d35e04ee5..ae5dbf207 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -36,7 +36,7 @@ extern int cx25840_debug; #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) struct cx25840_state { - struct i2c_client c; + struct i2c_client *c; int pvr150_workaround; int radio; enum cx25840_video_input vid_input; @@ -49,6 +49,8 @@ struct cx25840_state { u32 rev; int is_cx25836; int is_initialized; + wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ + struct work_struct fw_work; /* work entry for fw load */ }; /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index c24975b6e..02b520060 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -541,7 +541,7 @@ static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { .setscl = ivtv_setscl_old, .getsda = ivtv_getsda_old, .getscl = ivtv_getscl_old, - .udelay = 10, + .udelay = 5, .timeout = 200, }; |