Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3192e006 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] bttv: fix audio hooks

as reported by smatch:
	drivers/media/pci/bt8xx/bttv-audio-hook.c:201 lt9415_audio() warn: bitwise AND condition is false here
	drivers/media/pci/bt8xx/bttv-audio-hook.c:241 winfast2000_audio() warn: bitwise AND condition is false here
	drivers/media/pci/bt8xx/bttv-audio-hook.c:276 pvbt878p9b_audio() warn: bitwise AND condition is false here
	drivers/media/pci/bt8xx/bttv-audio-hook.c:307 fv2000s_audio() warn: bitwise AND condition is false here
	drivers/media/pci/bt8xx/bttv-audio-hook.c:334 windvr_audio() warn: bitwise AND condition is false here
	drivers/media/pci/bt8xx/bttv-audio-hook.c:371 adtvk503_audio() warn: bitwise AND condition is false here

there are some serious issues at the audio hook implementation.

They're not following what's specified at the DocBook:
	http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-g-tuner.html#tuner-audmode



Basically, it was assuming that the audmode (V4L2_TUNER_MODE_foo)
is a variable with a bit maskk. However, it isn't.

The bitmask only applies to rxsubchans field (V4L2_TUNER_SUB_foo).

As the code is also too complex, and not all hooks were returning
both audmode and rxsubchans to a VIDIOC_G_TUNER, rewrite the
functions, in order to fix both for get and set tuner ioctls.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent b674ac29
Loading
Loading
Loading
Loading
+275 −168
Original line number Diff line number Diff line
@@ -54,23 +54,33 @@ void winview_volume(struct bttv *btv, __u16 volume)

void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	unsigned int con = 0;
	unsigned int con;

	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	if (set) {
	gpio_inout(0x300, 0x300);
		if (t->audmode & V4L2_TUNER_MODE_LANG1)
	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG1:
	default:
		con = 0x000;
		if (t->audmode & V4L2_TUNER_MODE_LANG2)
		break;
	case V4L2_TUNER_MODE_LANG2:
		con = 0x300;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)
		break;
	case V4L2_TUNER_MODE_STEREO:
		con = 0x200;
/*		if (t->audmode & V4L2_TUNER_MODE_MONO)
 *			con = 0x100; */
		gpio_bits(0x300, con);
	} else {
		t->audmode = V4L2_TUNER_MODE_STEREO |
			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
		break;
	}
	gpio_bits(0x300, con);
}

void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
@@ -82,16 +92,16 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)

	val = gpio_read();
	if (set) {
		con = 0x000;
		if (t->audmode & V4L2_TUNER_MODE_LANG2) {
			if (t->audmode & V4L2_TUNER_MODE_LANG1) {
				/* LANG1 + LANG2 */
				con = 0x100;
			}
			else {
				/* LANG2 */
		switch (t->audmode) {
		case V4L2_TUNER_MODE_LANG2:
			con = 0x300;
			}
			break;
		case V4L2_TUNER_MODE_LANG1_LANG2:
			con = 0x100;
			break;
		default:
			con = 0x000;
			break;
		}
		if (con != (val & 0x300)) {
			gpio_bits(0x300, con);
@@ -102,27 +112,31 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
		switch (val & 0x70) {
		  case 0x10:
			t->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
			break;
		  case 0x30:
			t->rxsubchans = V4L2_TUNER_SUB_LANG2;
			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
			break;
		  case 0x50:
			t->rxsubchans = V4L2_TUNER_SUB_LANG1;
			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
			break;
		  case 0x60:
			t->rxsubchans = V4L2_TUNER_SUB_STEREO;
			t->audmode = V4L2_TUNER_MODE_STEREO;
			break;
		  case 0x70:
			t->rxsubchans = V4L2_TUNER_SUB_MONO;
			t->audmode = V4L2_TUNER_MODE_MONO;
			break;
		  default:
			t->rxsubchans = V4L2_TUNER_SUB_MONO |
					 V4L2_TUNER_SUB_STEREO |
					 V4L2_TUNER_SUB_LANG1 |
					 V4L2_TUNER_SUB_LANG2;
			t->audmode = V4L2_TUNER_MODE_LANG1;
		}
		t->audmode = V4L2_TUNER_MODE_STEREO |
			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
	}
}

@@ -142,43 +156,64 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)

void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	int val = 0;
	int val;

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG2:   /* SAP */
		val = 0x02;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)
		break;
	case V4L2_TUNER_MODE_STEREO:
		val = 0x01;
		if (val) {
		break;
	default:
		return;
	}
	gpio_bits(0x03, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "avermedia");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1;
		return;
	}
}


void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	int val = 0;

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG2:   /* SAP */
		val = 0x01;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
		break;
	case V4L2_TUNER_MODE_STEREO:
		val = 0x02;
		break;
	default:
		val = 0;
		break;
	}
	btaor(val, ~0x03, BT848_GPIO_DATA);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "avermedia");
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
		return;
	}
}

/* Lifetec 9415 handling */
@@ -192,23 +227,32 @@ void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
		return;
	}

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG2:	/* A2 SAP */
		val = 0x0080;
		if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
		break;
	case V4L2_TUNER_MODE_STEREO:	/* A2 stereo */
		val = 0x0880;
		if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
		    (t->audmode & V4L2_TUNER_MODE_MONO))
		break;
	default:
		val = 0;
		break;
	}

	gpio_bits(0x0880, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "lt9415");
	} else {
		/* autodetect doesn't work with this card :-( */
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
		return;
	}
}

/* TDA9821 on TerraTV+ Bt848, Bt878 */
@@ -216,46 +260,70 @@ void terratv_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	unsigned int con = 0;

	if (set) {
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	gpio_inout(0x180000, 0x180000);
		if (t->audmode & V4L2_TUNER_MODE_LANG2)
	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG2:
		con = 0x080000;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)
		break;
	case V4L2_TUNER_MODE_STEREO:
		con = 0x180000;
		break;
	default:
		con = 0;
		break;
	}
	gpio_bits(0x180000, con);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "terratv");
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
	}
}


void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	unsigned long val = 0;
	unsigned long val;

	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	if (set) {
	/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
		if (t->audmode & V4L2_TUNER_MODE_MONO)		/* Mono */
			val = 0x420000;
		if (t->audmode & V4L2_TUNER_MODE_LANG1)	/* Mono */
	switch (t->audmode) {
	case V4L2_TUNER_MODE_MONO:
	case V4L2_TUNER_MODE_LANG1:
		val = 0x420000;
		if (t->audmode & V4L2_TUNER_MODE_LANG2)	/* SAP */
		break;
	case V4L2_TUNER_MODE_LANG2: /* SAP */
		val = 0x410000;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)	/* Stereo */
		break;
	case V4L2_TUNER_MODE_STEREO:
		val = 0x020000;
		if (val) {
		break;
	default:
		return;
	}

	gpio_bits(0x430000, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "winfast2000");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
	}
}

/*
 * Dariusz Kowalewski <darekk@automex.pl>
@@ -272,24 +340,34 @@ void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
	if (btv->radio_user)
		return;

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
			val = 0x01;
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}
		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {

	switch (t->audmode) {
	case V4L2_TUNER_MODE_MONO:
		val = 0x01;
		break;
	case V4L2_TUNER_MODE_LANG1:
	case V4L2_TUNER_MODE_LANG2:
	case V4L2_TUNER_MODE_STEREO:
		val = 0x02;
		break;
	default:
		return;
	}
		if (val) {

	gpio_bits(0x03, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "pvbt878p9b");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
	}
}

/*
 * Dariusz Kowalewski <darekk@automex.pl>
@@ -298,29 +376,38 @@ void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
 */
void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	unsigned int val = 0xffff;
	unsigned int val;

	if (btv->radio_user)
		return;

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
			val = 0x0000;
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}
		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {

	switch (t->audmode) {
	case V4L2_TUNER_MODE_MONO:
		val = 0x0000;
		break;
	case V4L2_TUNER_MODE_LANG1:
	case V4L2_TUNER_MODE_LANG2:
	case V4L2_TUNER_MODE_STEREO:
		val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
		break;
	default:
		return;
	}
		if (val != 0xffff) {
	gpio_bits(0x1800, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "fv2000s");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
	}
}

/*
 * sound control for Canopus WinDVR PCI
@@ -328,27 +415,34 @@ void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
 */
void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
	unsigned long val = 0;
	unsigned long val;

	if (set) {
		if (t->audmode & V4L2_TUNER_MODE_MONO)
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	switch (t->audmode) {
	case V4L2_TUNER_MODE_MONO:
		val = 0x040000;
		if (t->audmode & V4L2_TUNER_MODE_LANG1)
			val = 0;
		if (t->audmode & V4L2_TUNER_MODE_LANG2)
		break;
	case V4L2_TUNER_MODE_LANG2:
		val = 0x100000;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)
			val = 0;
		if (val) {
		break;
	default:
		return;
	}

	gpio_bits(0x140000, val);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "windvr");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
	}
}

/*
 * sound control for AD-TVK503
@@ -360,23 +454,36 @@ void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)

	/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */

	if (set) {
	if (!set) {
		/* Not much to do here */
		t->audmode = V4L2_TUNER_MODE_LANG1;
		t->rxsubchans = V4L2_TUNER_SUB_MONO |
				V4L2_TUNER_SUB_STEREO |
				V4L2_TUNER_SUB_LANG1 |
				V4L2_TUNER_SUB_LANG2;

		return;
	}

	/* btor(***, BT848_GPIO_OUT_EN); */
		if (t->audmode & V4L2_TUNER_MODE_LANG1)
	switch (t->audmode) {
	case V4L2_TUNER_MODE_LANG1:
		con = 0x00000000;
		if (t->audmode & V4L2_TUNER_MODE_LANG2)
		break;
	case V4L2_TUNER_MODE_LANG2:
		con = 0x00180000;
		if (t->audmode & V4L2_TUNER_MODE_STEREO)
		break;
	case V4L2_TUNER_MODE_STEREO:
		con = 0x00000000;
		if (t->audmode & V4L2_TUNER_MODE_MONO)
		break;
	case V4L2_TUNER_MODE_MONO:
		con = 0x00060000;
		if (con != 0xffffff) {
		break;
	default:
		return;
	}

	gpio_bits(0x1e0000, con);
	if (bttv_gpio)
		bttv_gpio_tracking(btv, "adtvk503");
}
	} else {
		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
	}
}