Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
- KNC One TV-Station RDS (saa7134)
*/
-
+
/* Addresses to scan */
static unsigned short normal_i2c[] = {
I2C_CLIENT_INSMOD;
/* insmod options */
-static int debug = 0;
-static char *pal = "b";
-static char *secam = "l";
+static unsigned int debug = 0;
MODULE_PARM(debug,"i");
-MODULE_PARM(pal,"s");
-MODULE_PARM(secam,"s");
MODULE_LICENSE("GPL");
/* ---------------------------------------------------------------------- */
+#define UNSET (-1U)
+#define PREFIX "tda9885/6/7: "
#define dprintk if (debug) printk
struct tda9887 {
- struct i2c_client client;
- int radio,tvnorm;
- int pinnacle_id;
+ struct i2c_client client;
+ v4l2_std_id std;
+ unsigned int radio;
+ unsigned int pinnacle_id;
+ unsigned int using_v4l2;
+};
+
+struct tvnorm {
+ v4l2_std_id std;
+ char *name;
+ unsigned char b;
+ unsigned char c;
+ unsigned char e;
};
static struct i2c_driver driver;
// TDA defines
//
-//// first reg
+//// first reg (b)
#define cVideoTrapBypassOFF 0x00 // bit b0
#define cVideoTrapBypassON 0x01 // bit b0
#define cOutputPort2Inactive 0x80 // bit b7
-//// second reg
+//// second reg (c)
#define cDeemphasisOFF 0x00 // bit c5
#define cDeemphasisON 0x20 // bit c5
#define cAudioGain6 0x80 // bit c7
-//// third reg
+//// third reg (e)
#define cAudioIF_4_5 0x00 // bit e0:1
#define cAudioIF_5_5 0x01 // bit e0:1
#define cAudioIF_6_0 0x02 // bit e0:1
#define cAgcOutON 0x80 // bit e7
#define cAgcOutOFF 0x00 // bit e7
-static int tda9887_miro(struct tda9887 *t)
+/* ---------------------------------------------------------------------- */
+
+static struct tvnorm tvnorms[] = {
+ {
+ .std = V4L2_STD_PAL_BG,
+ .name = "PAL-BG",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cAudioIF_5_5 |
+ cVideoIF_38_90 ),
+ },{
+ .std = V4L2_STD_PAL_I,
+ .name = "PAL-I",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cAudioIF_6_0 |
+ cVideoIF_38_90 ),
+ },{
+ .std = V4L2_STD_PAL_DK,
+ .name = "PAL-DK",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cAudioIF_6_5 |
+ cVideoIF_38_00 ),
+ },{
+ .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N,
+ .name = "PAL-M/N",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis75 ),
+ .e = ( cAudioIF_4_5 |
+ cVideoIF_45_75 ),
+ },{
+ .std = V4L2_STD_SECAM_L,
+ .name = "SECAM-L",
+ .b = ( cPositiveAmTV |
+ cQSS ),
+ .e = ( cAudioIF_6_5 |
+ cVideoIF_38_90 ),
+ },{
+ .std = V4L2_STD_SECAM_DK,
+ .name = "SECAM-DK",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cAudioIF_6_5 |
+ cVideoIF_38_00 ),
+ },{
+ .std = V4L2_STD_NTSC_M,
+ .name = "NTSC-M",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cGating_36 |
+ cAudioIF_4_5 |
+ cVideoIF_45_75 ),
+ },{
+ .std = V4L2_STD_NTSC_M_JP,
+ .name = "NTSC-JP",
+ .b = ( cNegativeFmTV |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cGating_36 |
+ cAudioIF_4_5 |
+ cVideoIF_58_75 ),
+ }
+};
+
+static struct tvnorm radio = {
+ .name = "radio",
+ .b = ( cFmRadio |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50 ),
+ .e = ( cAudioIF_5_5 |
+ cRadioIF_38_90 ),
+};
+
+/* ---------------------------------------------------------------------- */
+
+static void dump_read_message(unsigned char *buf)
{
- int rc;
- u8 bData[4] = { 0 };
- u8 bVideoIF = 0;
- u8 bAudioIF = 0;
- u8 bDeEmphasis = 0;
- u8 bDeEmphVal = 0;
- u8 bModulation = 0;
- u8 bCarrierMode = 0;
- u8 bOutPort1 = cOutputPort1Inactive;
-#if 0
- u8 bOutPort2 = cOutputPort2Inactive & mbTADState; // store i2c tuner state
-#else
- u8 bOutPort2 = cOutputPort2Inactive;
-#endif
- u8 bVideoTrap = cVideoTrapBypassOFF;
-#if 1
- u8 bTopAdjust = 0x0e /* -2dB */;
-#else
- u8 bTopAdjust = 0;
-#endif
+ static char *afc[16] = {
+ "- 12.5 kHz",
+ "- 37.5 kHz",
+ "- 62.5 kHz",
+ "- 87.5 kHz",
+ "-112.5 kHz",
+ "-137.5 kHz",
+ "-162.5 kHz",
+ "-187.5 kHz [min]",
+ "+187.5 kHz [max]",
+ "+162.5 kHz",
+ "+137.5 kHz",
+ "+112.5 kHz",
+ "+ 87.5 kHz",
+ "+ 62.5 kHz",
+ "+ 37.5 kHz",
+ "+ 12.5 kHz",
+ };
+ printk(PREFIX "read: 0x%2x\n", buf[0]);
+ printk(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
+ printk(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
+ printk(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
+ printk(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
+}
-#if 0
- if (mParams.fVideoTrap)
- bVideoTrap = cVideoTrapBypassON;
-#endif
+static void dump_write_message(unsigned char *buf)
+{
+ static char *sound[4] = {
+ "AM/TV",
+ "FM/radio",
+ "FM/TV",
+ "FM/radio"
+ };
+ static char *adjust[32] = {
+ "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
+ "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
+ "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
+ "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
+ };
+ static char *deemph[4] = {
+ "no", "no", "75", "50"
+ };
+ static char *carrier[4] = {
+ "4.5 MHz",
+ "5.5 MHz",
+ "6.0 MHz",
+ "6.5 MHz / AM"
+ };
+ static char *vif[8] = {
+ "58.75 MHz",
+ "45.75 MHz",
+ "38.9 MHz",
+ "38.0 MHz",
+ "33.9 MHz",
+ "33.4 MHz",
+ "45.75 MHz + pin13",
+ "38.9 MHz + pin13",
+ };
+ static char *rif[4] = {
+ "44 MHz",
+ "52 MHz",
+ "52 MHz",
+ "44 MHz",
+ };
+
+ printk(PREFIX "write: byte B 0x%02x\n",buf[1]);
+ printk(" B0 video mode : %s\n",
+ (buf[1] & 0x01) ? "video trap" : "sound trap");
+ printk(" B1 auto mute fm : %s\n",
+ (buf[1] & 0x02) ? "yes" : "no");
+ printk(" B2 carrier mode : %s\n",
+ (buf[1] & 0x04) ? "QSS" : "Intercarrier");
+ printk(" B3-4 tv sound/radio : %s\n",
+ sound[(buf[1] & 0x18) >> 3]);
+ printk(" B5 force mute audio: %s\n",
+ (buf[1] & 0x20) ? "yes" : "no");
+ printk(" B6 output port 1 : %s\n",
+ (buf[1] & 0x40) ? "high" : "low");
+ printk(" B7 output port 2 : %s\n",
+ (buf[1] & 0x80) ? "high" : "low");
+
+ printk(PREFIX "write: byte C 0x%02x\n",buf[2]);
+ printk(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]);
+ printk(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]);
+ printk(" C7 audio gain : %s\n",
+ (buf[2] & 0x80) ? "-6" : "0");
+
+ printk(PREFIX "write: byte E 0x%02x\n",buf[3]);
+ printk(" E0-1 sound carrier : %s\n",
+ carrier[(buf[3] & 0x03)]);
+ printk(" E6 l pll ganting : %s\n",
+ (buf[3] & 0x40) ? "36" : "13");
+
+ if (buf[1] & 0x08) {
+ /* radio */
+ printk(" E2-4 video if : %s\n",
+ rif[(buf[3] & 0x0c) >> 2]);
+ printk(" E7 vif agc output : %s\n",
+ (buf[3] & 0x80)
+ ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio")
+ : "fm radio carrier afc");
+ } else {
+ /* video */
+ printk(" E2-4 video if : %s\n",
+ vif[(buf[3] & 0x1c) >> 2]);
+ printk(" E5 tuner gain : %s\n",
+ (buf[3] & 0x80)
+ ? ((buf[3] & 0x20) ? "external" : "normal")
+ : ((buf[3] & 0x20) ? "minimum" : "normal"));
+ printk(" E7 vif agc output : %s\n",
+ (buf[3] & 0x80)
+ ? ((buf[3] & 0x20)
+ ? "pin3 port, pin22 vif agc out"
+ : "pin22 port, pin3 vif acg ext in")
+ : "pin3+pin22 port");
+ }
+ printk("--\n");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
+{
+ struct tvnorm *norm = NULL;
+ int i;
if (t->radio) {
- bVideoTrap = cVideoTrapBypassOFF;
- bCarrierMode = cQSS;
- bModulation = cFmRadio;
- bOutPort1 = cOutputPort1Inactive;
- bDeEmphasis = cDeemphasisON;
- if (3 == t->pinnacle_id) {
- /* ntsc */
- bDeEmphVal = cDeemphasis75;
- bAudioIF = cAudioIF_4_5;
- bVideoIF = cRadioIF_45_75;
- } else {
- /* pal */
- bAudioIF = cAudioIF_5_5;
- bVideoIF = cRadioIF_38_90;
- bDeEmphVal = cDeemphasis50;
+ norm = &radio;
+ } else {
+ for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
+ if (tvnorms[i].std & t->std) {
+ norm = tvnorms+i;
+ break;
+ }
}
+ }
+ if (NULL == norm) {
+ dprintk(PREFIX "Oops: no tvnorm entry found\n");
+ return -1;
+ }
+
+ dprintk(PREFIX "configure for: %s\n",norm->name);
+ buf[1] = norm->b;
+ buf[2] = norm->c;
+ buf[3] = norm->e;
+ return 0;
+}
+
+static unsigned int port1 = 1;
+static unsigned int port2 = 1;
+static unsigned int qss = UNSET;
+static unsigned int adjust = 0x10;
+MODULE_PARM(port1,"i");
+MODULE_PARM(port2,"i");
+MODULE_PARM(qss,"i");
+MODULE_PARM(adjust,"i");
+
+static int tda9887_set_insmod(struct tda9887 *t, char *buf)
+{
+ if (port1)
+ buf[1] |= cOutputPort1Inactive;
+ if (port2)
+ buf[1] |= cOutputPort2Inactive;
+ if (UNSET != qss) {
+ if (qss)
+ buf[1] |= cQSS;
+ else
+ buf[1] &= ~cQSS;
+ }
+
+ if (adjust >= 0x00 && adjust < 0x20)
+ buf[2] |= adjust;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
- } else if (t->tvnorm == VIDEO_MODE_PAL) {
- bDeEmphasis = cDeemphasisON;
- bDeEmphVal = cDeemphasis50;
- bModulation = cNegativeFmTV;
- bOutPort1 = cOutputPort1Inactive;
+static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
+{
+ unsigned int bCarrierMode = UNSET;
+
+ if (t->std & V4L2_STD_PAL) {
if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
bCarrierMode = cIntercarrier;
} else {
- // stereo boards
bCarrierMode = cQSS;
}
- switch (pal[0]) {
- case 'b':
- case 'g':
- case 'h':
- bVideoIF = cVideoIF_38_90;
- bAudioIF = cAudioIF_5_5;
- break;
- case 'd':
- bVideoIF = cVideoIF_38_00;
- bAudioIF = cAudioIF_6_5;
- break;
- case 'i':
- bVideoIF = cVideoIF_38_90;
- bAudioIF = cAudioIF_6_0;
- break;
- case 'm':
- case 'n':
- bVideoIF = cVideoIF_45_75;
- bAudioIF = cAudioIF_4_5;
- bDeEmphVal = cDeemphasis75;
- if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
- bCarrierMode = cIntercarrier;
- } else {
- bCarrierMode = cQSS;
- }
- break;
- }
-
- } else if (t->tvnorm == VIDEO_MODE_SECAM) {
- bAudioIF = cAudioIF_6_5;
- bDeEmphasis = cDeemphasisON;
- bDeEmphVal = cDeemphasis50;
- bModulation = cNegativeFmTV;
- bCarrierMode = cQSS;
- bOutPort1 = cOutputPort1Inactive;
- switch (secam[0]) {
- case 'd':
- bVideoIF = cVideoIF_38_00;
- break;
- case 'k':
- bVideoIF = cVideoIF_38_90;
- break;
- case 'l':
- bVideoIF = cVideoIF_38_90;
- bDeEmphasis = cDeemphasisOFF;
- bDeEmphVal = cDeemphasis75;
- bModulation = cPositiveAmTV;
- break;
- case 'L' /* L1 */:
- bVideoIF = cVideoIF_33_90;
- bDeEmphasis = cDeemphasisOFF;
- bDeEmphVal = cDeemphasis75;
- bModulation = cPositiveAmTV;
- break;
- }
-
- } else if (t->tvnorm == VIDEO_MODE_NTSC) {
- bVideoIF = cVideoIF_45_75;
- bAudioIF = cAudioIF_4_5;
- bDeEmphasis = cDeemphasisON;
- bDeEmphVal = cDeemphasis75;
- bModulation = cNegativeFmTV;
- bOutPort1 = cOutputPort1Inactive;
+ }
+ if (t->std & V4L2_STD_NTSC) {
if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
bCarrierMode = cIntercarrier;
} else {
}
}
- bData[1] = bVideoTrap | // B0: video trap bypass
- cAutoMuteFmInactive | // B1: auto mute
- bCarrierMode | // B2: InterCarrier for PAL else QSS
- bModulation | // B3 - B4: positive AM TV for SECAM only
- cForcedMuteAudioOFF | // B5: forced Audio Mute (off)
- bOutPort1 | // B6: Out Port 1
- bOutPort2; // B7: Out Port 2
- bData[2] = bTopAdjust | // C0 - C4: Top Adjust 0 == -16dB 31 == 15dB
- bDeEmphasis | // C5: De-emphasis on/off
- bDeEmphVal | // C6: De-emphasis 50/75 microsec
- cAudioGain0; // C7: normal audio gain
- bData[3] = bAudioIF | // E0 - E1: Sound IF
- bVideoIF | // E2 - E4: Video IF
- cTunerGainNormal | // E5: Tuner gain (normal)
- cGating_18 | // E6: Gating (18%)
- cAgcOutOFF; // E7: VAGC (off)
-
- dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x [pinnacle_id=%d]\n",
- bData[1],bData[2],bData[3],t->pinnacle_id);
- if (4 != (rc = i2c_master_send(&t->client,bData,4)))
- printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
+ if (bCarrierMode != UNSET) {
+ buf[1] &= ~0x04;
+ buf[1] |= bCarrierMode;
+ }
return 0;
}
/* ---------------------------------------------------------------------- */
-#if 0
-/* just for reference: old knc-one saa7134 stuff */
-static unsigned char buf_pal_bg[] = { 0x00, 0x16, 0x70, 0x49 };
-static unsigned char buf_pal_i[] = { 0x00, 0x16, 0x70, 0x4a };
-static unsigned char buf_pal_dk[] = { 0x00, 0x16, 0x70, 0x4b };
-static unsigned char buf_pal_l[] = { 0x00, 0x06, 0x50, 0x4b };
-static unsigned char buf_fm_stereo[] = { 0x00, 0x0e, 0x0d, 0x77 };
-#endif
-
-static unsigned char buf_pal_bg[] = { 0x00, 0x96, 0x70, 0x49 };
-static unsigned char buf_pal_i[] = { 0x00, 0x96, 0x70, 0x4a };
-static unsigned char buf_pal_dk[] = { 0x00, 0x96, 0x70, 0x4b };
-static unsigned char buf_pal_l[] = { 0x00, 0x86, 0x50, 0x4b };
-static unsigned char buf_fm_stereo[] = { 0x00, 0x8e, 0x0d, 0x77 };
-static unsigned char buf_ntsc[] = { 0x00, 0x96, 0x70, 0x44 };
-static unsigned char buf_ntsc_jp[] = { 0x00, 0x96, 0x70, 0x40 };
+static char *pal = "-";
+MODULE_PARM(pal,"s");
+static char *secam = "-";
+MODULE_PARM(secam,"s");
-static int tda9887_configure(struct tda9887 *t)
+static int tda9887_fixup_std(struct tda9887 *t)
{
- unsigned char *buf = NULL;
- int rc;
-
- if (t->radio) {
- dprintk("tda9885/6/7: FM Radio mode\n");
- buf = buf_fm_stereo;
-
- } else if (t->tvnorm == VIDEO_MODE_PAL) {
- dprintk("tda9885/6/7: PAL-%c mode\n",pal[0]);
+ /* get more precise norm info from insmod option */
+ if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
switch (pal[0]) {
case 'b':
+ case 'B':
case 'g':
- buf = buf_pal_bg;
+ case 'G':
+ dprintk(PREFIX "insmod fixup: PAL => PAL-BG\n");
+ t->std = V4L2_STD_PAL_BG;
break;
case 'i':
- buf = buf_pal_i;
+ case 'I':
+ dprintk(PREFIX "insmod fixup: PAL => PAL-I\n");
+ t->std = V4L2_STD_PAL_I;
+ break;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n");
+ t->std = V4L2_STD_PAL_DK;
break;
+ }
+ }
+ if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
+ switch (secam[0]) {
case 'd':
+ case 'D':
case 'k':
- buf = buf_pal_dk;
+ case 'K':
+ dprintk(PREFIX "insmod fixup: SECAM => SECAM-DK\n");
+ t->std = V4L2_STD_SECAM_DK;
break;
case 'l':
- buf = buf_pal_l;
+ case 'L':
+ dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n");
+ t->std = V4L2_STD_SECAM_L;
break;
}
+ }
+ return 0;
+}
- } else if (t->tvnorm == VIDEO_MODE_NTSC) {
- dprintk("tda9885/6/7: NTSC mode\n");
- buf = buf_ntsc;
+static int tda9887_status(struct tda9887 *t)
+{
+ unsigned char buf[1];
+ int rc;
- } else if (t->tvnorm == VIDEO_MODE_SECAM) {
- dprintk("tda9885/6/7: SECAM mode\n");
- buf = buf_pal_l;
+ memset(buf,0,sizeof(buf));
+ if (1 != (rc = i2c_master_recv(&t->client,buf,1)))
+ printk(PREFIX "i2c i/o error: rc == %d (should be 1)\n",rc);
+ dump_read_message(buf);
+ return 0;
+}
- } else if (t->tvnorm == 6 /* BTTV hack */) {
- dprintk("tda9885/6/7: NTSC-Japan mode\n");
- buf = buf_ntsc_jp;
- }
+static int tda9887_configure(struct tda9887 *t)
+{
+ unsigned char buf[4];
+ int rc;
- if (NULL == buf) {
- printk("tda9885/6/7 unknown norm=%d\n",t->tvnorm);
- return 0;
+ memset(buf,0,sizeof(buf));
+ tda9887_set_tvnorm(t,buf);
+ if (UNSET != t->pinnacle_id) {
+ tda9887_set_pinnacle(t,buf);
}
+ tda9887_set_insmod(t,buf);
- dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x\n",
+ dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
buf[1],buf[2],buf[3]);
+ if (debug > 1)
+ dump_write_message(buf);
+
if (4 != (rc = i2c_master_send(&t->client,buf,4)))
- printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
+ printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc);
+
+ if (debug > 2) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ tda9887_status(t);
+ }
return 0;
}
client_template.adapter = adap;
client_template.addr = addr;
- printk("tda9887: chip found @ 0x%x\n", addr<<1);
+ printk(PREFIX "chip found @ 0x%x\n", addr<<1);
if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
memset(t,0,sizeof(*t));
- t->client = client_template;
- t->pinnacle_id = -1;
- t->tvnorm=VIDEO_MODE_PAL;
+ t->client = client_template;
+ t->std = 0;;
+ t->pinnacle_id = UNSET;
i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
return 0;
}
+#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \
+ printk(PREFIX "switching to v4l2\n"); \
+ t->using_v4l2 = 1;
+#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \
+ printk(PREFIX "ignore v4l1 call\n"); \
+ return 0; }
+
static int
tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
/* --- configuration --- */
case AUDC_SET_RADIO:
t->radio = 1;
- if (-1 != t->pinnacle_id)
- tda9887_miro(t);
- else
- tda9887_configure(t);
+ tda9887_configure(t);
break;
case AUDC_CONFIG_PINNACLE:
int *i = arg;
t->pinnacle_id = *i;
- tda9887_miro(t);
+ tda9887_configure(t);
break;
}
/* --- v4l ioctls --- */
kernel pointer here... */
case VIDIOCSCHAN:
{
+ static const v4l2_std_id map[] = {
+ [ VIDEO_MODE_PAL ] = V4L2_STD_PAL,
+ [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M,
+ [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
+ [ 4 /* bttv */ ] = V4L2_STD_PAL_M,
+ [ 5 /* bttv */ ] = V4L2_STD_PAL_N,
+ [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
+ };
struct video_channel *vc = arg;
- t->radio = 0;
- t->tvnorm = vc->norm;
- if (-1 != t->pinnacle_id)
- tda9887_miro(t);
- else
- tda9887_configure(t);
+ CHECK_V4L2;
+ t->radio = 0;
+ if (vc->norm < ARRAY_SIZE(map))
+ t->std = map[vc->norm];
+ tda9887_fixup_std(t);
+ tda9887_configure(t);
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ SWITCH_V4L2;
+ t->radio = 0;
+ t->std = *id;
+ tda9887_fixup_std(t);
+ tda9887_configure(t);
break;
}
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ SWITCH_V4L2;
+ if (V4L2_TUNER_ANALOG_TV == f->type) {
+ if (t->radio == 0)
+ return 0;
+ t->radio = 0;
+ }
+ if (V4L2_TUNER_RADIO == f->type) {
+ if (t->radio == 1)
+ return 0;
+ t->radio = 1;
+ }
+ tda9887_configure(t);
+ }
default:
/* nothing */
break;