Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 219236
b: refs/heads/master
c: df2b9b0
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Drake authored and Mauro Carvalho Chehab committed Oct 21, 2010
1 parent 5383305 commit c49db93
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a716e9d75f04ff71fb5e391a7a189b6f1b032bbc
refs/heads/master: df2b9b0f9c02689ce3b3f0b5dbc6c9b272bbe1ab
36 changes: 17 additions & 19 deletions trunk/drivers/media/video/cafe_ccic.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ static int cafe_smbus_write_data(struct cafe_camera *cam,
{
unsigned int rval;
unsigned long flags;
DEFINE_WAIT(the_wait);

spin_lock_irqsave(&cam->dev_lock, flags);
rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
Expand All @@ -378,28 +377,27 @@ static int cafe_smbus_write_data(struct cafe_camera *cam,
cafe_reg_write(cam, REG_TWSIC1, rval);
spin_unlock_irqrestore(&cam->dev_lock, flags);

/* Unfortunately, reading TWSIC1 too soon after sending a command
* causes the device to die.
* Use a busy-wait because we often send a large quantity of small
* commands at-once; using msleep() would cause a lot of context
* switches which take longer than 2ms, resulting in a noticable
* boot-time and capture-start delays.
*/
mdelay(2);

/*
* Time to wait for the write to complete. THIS IS A RACY
* WAY TO DO IT, but the sad fact is that reading the TWSIC1
* register too quickly after starting the operation sends
* the device into a place that may be kinder and better, but
* which is absolutely useless for controlling the sensor. In
* practice we have plenty of time to get into our sleep state
* before the interrupt hits, and the worst case is that we
* time out and then see that things completed, so this seems
* the best way for now.
* Another sad fact is that sometimes, commands silently complete but
* cafe_smbus_write_done() never becomes aware of this.
* This happens at random and appears to possible occur with any
* command.
* We don't understand why this is. We work around this issue
* with the timeout in the wait below, assuming that all commands
* complete within the timeout.
*/
do {
prepare_to_wait(&cam->smbus_wait, &the_wait,
TASK_UNINTERRUPTIBLE);
schedule_timeout(1); /* even 1 jiffy is too long */
finish_wait(&cam->smbus_wait, &the_wait);
} while (!cafe_smbus_write_done(cam));

#ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT
wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
CAFE_SMBUS_TIMEOUT);
#endif

spin_lock_irqsave(&cam->dev_lock, flags);
rval = cafe_reg_read(cam, REG_TWSIC1);
spin_unlock_irqrestore(&cam->dev_lock, flags);
Expand Down

0 comments on commit c49db93

Please sign in to comment.