patch-2.4.2 linux/drivers/media/video/tvaudio.c
Next file: linux/drivers/media/video/tvmixer.c
Previous file: linux/drivers/media/video/tuner.h
Back to the patch index
Back to the overall index
- Lines: 237
- Date:
Mon Feb 19 14:43:36 2001
- Orig file:
v2.4.1/linux/drivers/media/video/tvaudio.c
- Orig date:
Tue Dec 5 12:43:47 2000
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c
@@ -22,7 +22,7 @@
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/videodev.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
@@ -112,13 +112,14 @@
audiocmd shadow;
/* current settings */
- __u16 left,right,treble,bass;
+ __u16 left,right,treble,bass,mode;
/* thread */
struct task_struct *thread;
struct semaphore *notify;
wait_queue_head_t wq;
- int wake,done;
+ struct timer_list wt;
+ int done;
};
@@ -245,6 +246,12 @@
* if available, ...
*/
+static void chip_thread_wake(unsigned long data)
+{
+ struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+ wake_up_interruptible(&chip->wq);
+}
+
static int chip_thread(void *data)
{
struct CHIPSTATE *chip = data;
@@ -266,37 +273,44 @@
up(chip->notify);
for (;;) {
- if (chip->done)
- break;
- if (!chip->wake) {
- interruptible_sleep_on(&chip->wq);
- dprintk("%s: thread wakeup\n", chip->c.name);
- if (chip->done || signal_pending(current))
- break;
- }
- chip->wake = 0;
-
- /* wait some time -- let the audio hardware
- figure the current mode */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ);
- if (signal_pending(current))
+ interruptible_sleep_on(&chip->wq);
+ dprintk("%s: thread wakeup\n", chip->c.name);
+ if (chip->done || signal_pending(current))
break;
- if (chip->wake)
+
+ if (0 != chip->mode)
+ /* don't do anything if mode != auto */
continue;
-
+
+ /* have a look what's going on */
dprintk("%s: thread checkmode\n", chip->c.name);
desc->checkmode(chip);
+
+ /* schedule next check */
+ mod_timer(&chip->wt, jiffies+2*HZ);
}
chip->thread = NULL;
dprintk("%s: thread exiting\n", chip->c.name);
if(chip->notify != NULL)
- up_and_exit(chip->notify,0);
+ up(chip->notify);
return 0;
}
+void generic_checkmode(struct CHIPSTATE *chip)
+{
+ struct CHIPDESC *desc = chiplist + chip->type;
+ int mode = desc->getmode(chip);
+
+ if (mode & VIDEO_SOUND_STEREO)
+ desc->setmode(chip,VIDEO_SOUND_STEREO);
+ else if (mode & VIDEO_SOUND_LANG1)
+ desc->setmode(chip,VIDEO_SOUND_LANG1);
+ else
+ desc->setmode(chip,VIDEO_SOUND_MONO);
+}
+
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda9840 */
@@ -313,10 +327,24 @@
#define TDA9840_DUALBA 0x16
#define TDA9840_EXTERNAL 0x7a
+#define TDA9840_DS_DUAL 0x20 /* Dual sound identified */
+#define TDA9840_ST_STEREO 0x40 /* Stereo sound identified */
+#define TDA9840_PONRES 0x80 /* Power-on reset detected if = 1 */
+
int tda9840_getmode(struct CHIPSTATE *chip)
{
- return VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
- VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ int val, mode;
+
+ val = chip_read(chip);
+ mode = VIDEO_SOUND_MONO;
+ if (val & TDA9840_DS_DUAL)
+ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ if (val & TDA9840_ST_STEREO)
+ mode |= VIDEO_SOUND_STEREO;
+
+ dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+ val, mode);
+ return mode;
}
void tda9840_setmode(struct CHIPSTATE *chip, int mode)
@@ -617,6 +645,12 @@
{
int sw_data = chip->shadow.bytes[TDA9873_SW+1] & 0xe3;
/* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
+
+ if (sw_data & 3) {
+ dprintk("tda9873_setmode(): external input\n");
+ return;
+ }
+
dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
dprintk("tda9873_setmode(): sw_data = %d\n", sw_data);
@@ -638,16 +672,6 @@
chip_write(chip,TDA9873_SW,sw_data);
}
-void tda9873_checkmode(struct CHIPSTATE *chip)
-{
- int mode = tda9873_getmode(chip);
-
- if (mode & VIDEO_SOUND_STEREO)
- tda9873_setmode(chip,VIDEO_SOUND_STEREO);
- if (mode & VIDEO_SOUND_LANG1)
- tda9873_setmode(chip,VIDEO_SOUND_LANG1);
-}
-
int tda9873_checkit(struct CHIPSTATE *chip)
{
int rc;
@@ -751,6 +775,7 @@
getmode: tda9840_getmode,
setmode: tda9840_setmode,
+ checkmode: generic_checkmode,
init: { 2, { TDA9840_SW, 0x2a } }
},
@@ -762,12 +787,17 @@
addr_lo: I2C_TDA985x_L >> 1,
addr_hi: I2C_TDA985x_H >> 1,
registers: 3,
+ flags: CHIP_HAS_INPUTSEL,
getmode: tda9873_getmode,
setmode: tda9873_setmode,
- checkmode: tda9873_checkmode,
+ checkmode: generic_checkmode,
- init: { 4, { TDA9873_SW, 0xa0, 0x06, 0x03 } }
+ init: { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
+ inputreg: TDA9873_SW,
+ inputmute: 0xc0,
+ inputmap: {0xa4, 0xa2, 0xa4, 0xa4, 0xc0}
+
},
{
name: "tda9850",
@@ -873,7 +903,10 @@
inputreg: PIC16C54_REG_MISC,
inputmap: {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
- PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE},
+ PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+ PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+ PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE,
+ PIC16C54_MISC_SND_NOTMUTE},
inputmute: PIC16C54_MISC_SND_MUTE,
},
{ name: NULL } /* EOF */
@@ -947,11 +980,12 @@
/* start async thread */
DECLARE_MUTEX_LOCKED(sem);
chip->notify = &sem;
+ chip->wt.function = chip_thread_wake;
+ chip->wt.data = (unsigned long)chip;
init_waitqueue_head(&chip->wq);
kernel_thread(chip_thread,(void *)chip,0);
down(&sem);
chip->notify = NULL;
- chip->wake++;
wake_up_interruptible(&chip->wq);
}
return 0;
@@ -1048,17 +1082,19 @@
chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
}
- if (desc->setmode && va->mode)
+ if (desc->setmode && va->mode) {
+ chip->mode = va->mode;
desc->setmode(chip,va->mode);
+ }
break;
}
case VIDIOCSFREQ:
{
+ chip->mode = 0; /* automatic */
if (desc->checkmode) {
desc->setmode(chip,VIDEO_SOUND_MONO);
- chip->wake++;
- wake_up_interruptible(&chip->wq);
- /* the thread will call checkmode() a second later */
+ mod_timer(&chip->wt, jiffies+2*HZ);
+ /* the thread will call checkmode() later */
}
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)