int dfp_regs[DFP_COUNT];
/* thread */
- struct task_struct *thread;
+ pid_t tpid;
+ struct completion texit;
wait_queue_head_t wq;
- struct semaphore *notify;
- int active,restart,rmmod;
+ int active:1;
+ int restart:1;
+ int rmmod:1;
int watch_stereo;
struct timer_list wake_stereo;
#define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@')
#define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
-#define MSP3400_MAX 4
-static struct i2c_client *msps[MSP3400_MAX];
-
#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
/* ---------------------------------------------------------------------- */
-#define dprintk if (debug) printk
+#define dprintk if (debug >= 1) printk
+#define d2printk if (debug >= 2) printk
MODULE_PARM(once,"i");
MODULE_PARM(debug,"i");
* in the ioctl while doing the sound carrier & stereo detect
*/
+static int msp34xx_sleep(struct msp3400c *msp, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&msp->wq, &wait);
+ if (!msp->rmmod) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (timeout < 0)
+ schedule();
+ else
+ schedule_timeout(timeout);
+ }
+ remove_wait_queue(&msp->wq, &wait);
+ return msp->rmmod || signal_pending(current);
+}
+
static void msp3400c_stereo_wake(unsigned long data)
{
struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */
struct CARRIER_DETECT *cd;
int count, max1,max2,val1,val2, val,this;
- lock_kernel();
daemonize("msp3400");
- msp->thread = current;
- unlock_kernel();
-
+ allow_signal(SIGTERM);
printk("msp3400: daemon started\n");
- if(msp->notify != NULL)
- up(msp->notify);
for (;;) {
- if (msp->rmmod)
- goto done;
- if (debug > 1)
- printk("msp3400: thread: sleep\n");
- interruptible_sleep_on(&msp->wq);
- if (debug > 1)
- printk("msp3400: thread: wakeup\n");
- if (msp->rmmod || signal_pending(current))
+ d2printk("msp3400: thread: sleep\n");
+ if (msp34xx_sleep(msp,-1))
goto done;
+ d2printk("msp3400: thread: wakeup\n");
msp->active = 1;
if (msp->watch_stereo) {
}
/* some time for the tuner to sync */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/5);
- if (signal_pending(current))
+ if (msp34xx_sleep(msp,HZ/5))
goto done;
restart:
for (this = 0; this < count; this++) {
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10);
- if (signal_pending(current))
+ if (msp34xx_sleep(msp,HZ/10))
goto done;
if (msp->restart)
msp->restart = 0;
for (this = 0; this < count; this++) {
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10);
- if (signal_pending(current))
+ if (msp34xx_sleep(msp,HZ/10))
goto done;
if (msp->restart)
goto restart;
}
done:
- dprintk(KERN_DEBUG "msp3400: thread: exit\n");
msp->active = 0;
- msp->thread = NULL;
-
- if(msp->notify != NULL)
- up(msp->notify);
- return 0;
+ dprintk(KERN_DEBUG "msp3400: thread: exit\n");
+ complete_and_exit(&msp->texit, 0);
}
/* ----------------------------------------------------------------------- */
struct msp3400c *msp = i2c_get_clientdata(client);
int mode,val,i,std;
- lock_kernel();
daemonize("msp3410 [auto]");
- msp->thread = current;
- unlock_kernel();
-
+ allow_signal(SIGTERM);
printk("msp3410: daemon started\n");
- if(msp->notify != NULL)
- up(msp->notify);
-
+
for (;;) {
- if (msp->rmmod)
- goto done;
- if (debug > 1)
- printk(KERN_DEBUG "msp3410: thread: sleep\n");
- interruptible_sleep_on(&msp->wq);
- if (debug > 1)
- printk(KERN_DEBUG "msp3410: thread: wakeup\n");
- if (msp->rmmod || signal_pending(current))
+ d2printk(KERN_DEBUG "msp3410: thread: sleep\n");
+ if (msp34xx_sleep(msp,-1))
goto done;
+ d2printk(KERN_DEBUG "msp3410: thread: wakeup\n");
msp->active = 1;
if (msp->watch_stereo) {
}
/* some time for the tuner to sync */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/5);
- if (signal_pending(current))
+ if (msp34xx_sleep(msp,HZ/5))
goto done;
restart:
} else {
/* triggered autodetect */
for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10);
- if (signal_pending(current))
+ if (msp34xx_sleep(msp,HZ/10))
goto done;
if (msp->restart)
goto restart;
}
done:
- dprintk(KERN_DEBUG "msp3410: thread: exit\n");
msp->active = 0;
- msp->thread = NULL;
-
- if(msp->notify != NULL)
- up(msp->notify);
+ dprintk(KERN_DEBUG "msp3410: thread: exit\n");
+ complete_and_exit(&msp->texit, 0);
return 0;
}
static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
{
- DECLARE_MUTEX_LOCKED(sem);
struct msp3400c *msp;
struct i2c_client *c;
- int i, rc;
+ int i;
client_template.adapter = adap;
client_template.addr = addr;
printk("\n");
/* startup control thread */
- msp->notify = &sem;
- rc = kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread,
- (void *)c, 0);
- if (rc < 0)
+ init_completion(&msp->texit);
+ msp->tpid = kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread,
+ (void *)c, 0);
+ if (msp->tpid < 0)
printk(KERN_WARNING "msp34xx: kernel_thread() failed\n");
- else
- down(&sem);
- msp->notify = NULL;
wake_up_interruptible(&msp->wq);
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (NULL == msps[i]) {
- msps[i] = c;
- break;
- }
- }
-
/* done */
i2c_attach_client(c);
return 0;
static int msp_detach(struct i2c_client *client)
{
- DECLARE_MUTEX_LOCKED(sem);
struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
/* shutdown control thread */
- del_timer(&msp->wake_stereo);
- if (msp->thread)
- {
- msp->notify = &sem;
+ del_timer_sync(&msp->wake_stereo);
+ if (msp->tpid >= 0) {
msp->rmmod = 1;
wake_up_interruptible(&msp->wq);
- down(&sem);
- msp->notify = NULL;
+ wait_for_completion(&msp->texit);
}
msp3400c_reset(client);
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (client == msps[i]) {
- msps[i] = NULL;
- break;
- }
- }
-
i2c_detach_client(client);
kfree(msp);
kfree(client);
if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, msp_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ switch (adap->id) {
+ case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
+ case I2C_ALGO_BIT | I2C_HW_B_BT848:
+ //case I2C_ALGO_SAA7134:
return i2c_probe(adap, &addr_data, msp_attach);
+ break;
+ }
#endif
return 0;
}
__u16 left,right,treble,bass,mode;
int prevmode;
int norm;
+
/* thread */
- struct task_struct *thread;
- struct semaphore *notify;
+ pid_t tpid;
+ struct completion texit;
wait_queue_head_t wq;
struct timer_list wt;
int done;
static int chip_thread(void *data)
{
+ DECLARE_WAITQUEUE(wait, current);
struct CHIPSTATE *chip = data;
struct CHIPDESC *desc = chiplist + chip->type;
- lock_kernel();
daemonize("%s",i2c_clientname(&chip->c));
- chip->thread = current;
- unlock_kernel();
-
+ allow_signal(SIGTERM);
dprintk("%s: thread started\n", i2c_clientname(&chip->c));
- if(chip->notify != NULL)
- up(chip->notify);
for (;;) {
- interruptible_sleep_on(&chip->wq);
- dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
+ add_wait_queue(&chip->wq, &wait);
+ if (!chip->done) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ remove_wait_queue(&chip->wq, &wait);
if (chip->done || signal_pending(current))
break;
+ dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
/* don't do anything for radio or if mode != auto */
if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
mod_timer(&chip->wt, jiffies+2*HZ);
}
- chip->thread = NULL;
dprintk("%s: thread exiting\n", i2c_clientname(&chip->c));
- if(chip->notify != NULL)
- up(chip->notify);
-
+ complete_and_exit(&chip->texit, 0);
return 0;
}
{
struct CHIPSTATE *chip;
struct CHIPDESC *desc;
- int rc;
chip = kmalloc(sizeof(*chip),GFP_KERNEL);
if (!chip)
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
}
+ chip->tpid = -1;
if (desc->checkmode) {
/* start async thread */
- DECLARE_MUTEX_LOCKED(sem);
- chip->notify = &sem;
init_timer(&chip->wt);
chip->wt.function = chip_thread_wake;
chip->wt.data = (unsigned long)chip;
init_waitqueue_head(&chip->wq);
- rc = kernel_thread(chip_thread,(void *)chip,0);
- if (rc < 0)
+ init_completion(&chip->texit);
+ chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
+ if (chip->tpid < 0)
printk(KERN_WARNING "%s: kernel_thread() failed\n",
i2c_clientname(&chip->c));
- else
- down(&sem);
- chip->notify = NULL;
wake_up_interruptible(&chip->wq);
}
return 0;
{
struct CHIPSTATE *chip = i2c_get_clientdata(client);
- del_timer(&chip->wt);
- if (NULL != chip->thread) {
+ del_timer_sync(&chip->wt);
+ if (chip->tpid >= 0) {
/* shutdown async thread */
- DECLARE_MUTEX_LOCKED(sem);
- chip->notify = &sem;
chip->done = 1;
wake_up_interruptible(&chip->wq);
- down(&sem);
- chip->notify = NULL;
+ wait_for_completion(&chip->texit);
}
i2c_detach_client(&chip->c);