summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/pvrusb2
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/pvrusb2')
-rw-r--r--linux/drivers/media/video/pvrusb2/Kconfig5
-rw-r--r--linux/drivers/media/video/pvrusb2/Makefile3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.c14
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-context.c16
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-context.h3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c598
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h123
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c23
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c16
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-demod.c127
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-demod.h38
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c8
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c370
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h205
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c2171
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h156
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c6
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c72
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c208
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-io.c37
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-io.h13
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c35
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-main.c30
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-std.c408
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-std.h61
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c420
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c2
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c480
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c24
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c15
32 files changed, 3414 insertions, 2277 deletions
diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig
index 207efa6c0..7e727fe14 100644
--- a/linux/drivers/media/video/pvrusb2/Kconfig
+++ b/linux/drivers/media/video/pvrusb2/Kconfig
@@ -1,9 +1,10 @@
config VIDEO_PVRUSB2
tristate "Hauppauge WinTV-PVR USB2 support"
- depends on VIDEO_V4L1 && USB && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
+ select VIDEO_CX2341X
select VIDEO_SAA711X
select VIDEO_MSP3400
---help---
@@ -34,7 +35,7 @@ config VIDEO_PVRUSB2_24XXX
warned.
config VIDEO_PVRUSB2_SYSFS
- bool "pvrusb2 sysfs support"
+ bool "pvrusb2 sysfs support (EXPERIMENTAL)"
default y
depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
---help---
diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile
index ce78cd00f..02e414210 100644
--- a/linux/drivers/media/video/pvrusb2/Makefile
+++ b/linux/drivers/media/video/pvrusb2/Makefile
@@ -8,8 +8,9 @@ obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
pvrusb2-encoder.o pvrusb2-video-v4l.o \
- pvrusb2-eeprom.o pvrusb2-tuner.o pvrusb2-demod.o \
+ pvrusb2-eeprom.o pvrusb2-tuner.o \
pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
+ pvrusb2-ctrl.o pvrusb2-std.o \
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
$(obj-pvrusb2-24xxx-y) \
$(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 7d5997bdc..9d1a126be 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -45,16 +45,16 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
- if (hdw->controls[PVR2_CID_INPUT].value == PVR2_CVAL_INPUT_TV) {
+ if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
struct v4l2_tuner vt;
memset(&vt,0,sizeof(vt));
- vt.audmode = hdw->controls[PVR2_CID_AUDIOMODE].value;
+ vt.audmode = hdw->audiomode_val;
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
}
route.input = MSP_INPUT_DEFAULT;
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
- switch (hdw->controls[PVR2_CID_INPUT].value) {
+ switch (hdw->input_val) {
case PVR2_CVAL_INPUT_TV:
break;
case PVR2_CVAL_INPUT_RADIO:
@@ -79,8 +79,8 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
static int check_stereo(struct pvr2_msp3400_handler *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return ((hdw->controls[PVR2_CID_INPUT].dirty != 0)||
- (hdw->controls[PVR2_CID_AUDIOMODE].dirty != 0));
+ return (hdw->input_dirty ||
+ hdw->audiomode_dirty);
}
@@ -146,8 +146,8 @@ static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
{
- ctxt->client->handler = 0;
- ctxt->hdw->audio_stat = 0;
+ ctxt->client->handler = NULL;
+ ctxt->hdw->audio_stat = NULL;
kfree(ctxt);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-context.c b/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
index f3fd61f21..f129f316d 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -47,11 +47,9 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp)
static void pvr2_context_poll(struct pvr2_context *mp)
{
- pvr2_trace(PVR2_TRACE_DEBUG,"pvr2_context_poll BEGIN");
pvr2_context_enter(mp); do {
pvr2_hdw_poll(mp->hdw);
} while (0); pvr2_context_exit(mp);
- pvr2_trace(PVR2_TRACE_DEBUG,"pvr2_context_poll END");
}
@@ -79,7 +77,7 @@ struct pvr2_context *pvr2_context_create(
const struct usb_device_id *devid,
void (*setup_func)(struct pvr2_context *))
{
- struct pvr2_context *mp = 0;
+ struct pvr2_context *mp = NULL;
mp = kmalloc(sizeof(*mp),GFP_KERNEL);
if (!mp) goto done;
memset(mp,0,sizeof(*mp));
@@ -89,7 +87,7 @@ struct pvr2_context *pvr2_context_create(
mp->hdw = pvr2_hdw_create(intf,devid);
if (!mp->hdw) {
pvr2_context_destroy(mp);
- mp = 0;
+ mp = NULL;
goto done;
}
@@ -147,7 +145,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
{
cp->hdw = mp->hdw;
cp->mc_head = mp;
- cp->mc_next = 0;
+ cp->mc_next = NULL;
cp->mc_prev = mp->mc_last;
if (mp->mc_last) {
mp->mc_last->mc_next = cp;
@@ -162,8 +160,8 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
{
if (!cp->stream) return;
pvr2_stream_kill(cp->stream->stream);
- cp->stream->user = 0;
- cp->stream = 0;
+ cp->stream->user = NULL;
+ cp->stream = NULL;
}
@@ -181,7 +179,7 @@ void pvr2_channel_done(struct pvr2_channel *cp)
} else {
mp->mc_first = cp->mc_next;
}
- cp->hdw = 0;
+ cp->hdw = NULL;
}
@@ -214,7 +212,7 @@ struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
{
struct pvr2_ioread *cp;
cp = pvr2_ioread_create();
- if (!cp) return 0;
+ if (!cp) return NULL;
pvr2_ioread_setup(cp,sp->stream);
pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
return cp;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-context.h b/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
index 910086ba2..69c1f3a92 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
@@ -22,8 +22,7 @@
#include "compat.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-#include <asm/atomic.h>
-#include <asm/mutex.h>
+#include <linux/mutex.h>
#else
#include <asm/semaphore.h>
#endif
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
new file mode 100644
index 000000000..999c5e223
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -0,0 +1,598 @@
+/*
+ *
+ * $Id$
+ *
+ * Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "pvrusb2-ctrl.h"
+#include "pvrusb2-hdw-internal.h"
+#include "compat.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
+{
+ return pvr2_ctrl_set_mask_value(cptr,~0,val);
+}
+
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+{
+ int ret = 0;
+ if (!cptr) return -EINVAL;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->set_value != 0) {
+ if (cptr->info->type == pvr2_ctl_bitmask) {
+ mask &= cptr->info->def.type_bitmask.valid_bits;
+ } else if (cptr->info->type == pvr2_ctl_int) {
+ if (val < cptr->info->def.type_int.min_value) {
+ break;
+ }
+ if (val > cptr->info->def.type_int.max_value) {
+ break;
+ }
+ } else if (cptr->info->type == pvr2_ctl_enum) {
+ if (val >= cptr->info->def.type_enum.count) {
+ break;
+ }
+ } else if (cptr->info->type != pvr2_ctl_bool) {
+ break;
+ }
+ ret = cptr->info->set_value(cptr,mask,val);
+ } else {
+ ret = -EPERM;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
+{
+ int ret = 0;
+ if (!cptr) return -EINVAL;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ ret = cptr->info->get_value(cptr,valptr);
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return pvr2_ctl_int;
+ return cptr->info->type;
+}
+
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
+{
+ int ret = 0;
+ if (!cptr) return 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_int) {
+ ret = cptr->info->def.type_int.max_value;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
+{
+ int ret = 0;
+ if (!cptr) return 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_int) {
+ ret = cptr->info->def.type_int.min_value;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
+{
+ int ret = 0;
+ if (!cptr) return 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_int) {
+ ret = cptr->info->default_value;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
+{
+ int ret = 0;
+ if (!cptr) return 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_enum) {
+ ret = cptr->info->def.type_enum.count;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
+{
+ int ret = 0;
+ if (!cptr) return 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_bitmask) {
+ ret = cptr->info->def.type_bitmask.valid_bits;
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return NULL;
+ return cptr->info->name;
+}
+
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return NULL;
+ return cptr->info->desc;
+}
+
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+ char *bptr,unsigned int bmax,
+ unsigned int *blen)
+{
+ int ret = -EINVAL;
+ if (!cptr) return 0;
+ *blen = 0;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_enum) {
+ const char **names;
+ names = cptr->info->def.type_enum.value_names;
+ if ((val >= 0) &&
+ (val < cptr->info->def.type_enum.count)) {
+ if (names[val]) {
+ *blen = scnprintf(
+ bptr,bmax,"%s",
+ names[val]);
+ } else {
+ *blen = 0;
+ }
+ ret = 0;
+ }
+ } else if (cptr->info->type == pvr2_ctl_bitmask) {
+ const char **names;
+ unsigned int idx;
+ int msk;
+ names = cptr->info->def.type_bitmask.bit_names;
+ val &= cptr->info->def.type_bitmask.valid_bits;
+ for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
+ if (val & msk) {
+ *blen = scnprintf(bptr,bmax,"%s",
+ names[idx]);
+ ret = 0;
+ break;
+ }
+ }
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return 0;
+ return cptr->info->v4l_id;
+}
+
+
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
+{
+ unsigned int flags = 0;
+
+ if (cptr->info->get_v4lflags) {
+ flags = cptr->info->get_v4lflags(cptr);
+ }
+
+ if (cptr->info->set_value) {
+ flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+ } else {
+ flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ }
+
+ return flags;
+}
+
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return 0;
+ return cptr->info->set_value != 0;
+}
+
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
+{
+ if (!cptr) return 0;
+ if (!cptr->info->val_to_sym) return 0;
+ if (!cptr->info->sym_to_val) return 0;
+ return !0;
+}
+
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len)
+{
+ if (!cptr) return -EINVAL;
+ if (!cptr->info->val_to_sym) return -EINVAL;
+ return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
+ const char *buf,unsigned int len,
+ int *maskptr,int *valptr)
+{
+ if (!cptr) return -EINVAL;
+ if (!cptr->info->sym_to_val) return -EINVAL;
+ return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
+}
+
+
+static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
+ const char **names,
+ char *ptr,unsigned int len)
+{
+ unsigned int idx;
+ long sm,um;
+ int spcFl;
+ unsigned int uc,cnt;
+ const char *idStr;
+
+ spcFl = 0;
+ uc = 0;
+ um = 0;
+ for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
+ if (sm & msk) {
+ msk &= ~sm;
+ idStr = names[idx];
+ if (idStr) {
+ cnt = scnprintf(ptr,len,"%s%s%s",
+ (spcFl ? " " : ""),
+ (msk_only ? "" :
+ ((val & sm) ? "+" : "-")),
+ idStr);
+ ptr += cnt; len -= cnt; uc += cnt;
+ spcFl = !0;
+ } else {
+ um |= sm;
+ }
+ }
+ }
+ if (um) {
+ if (msk_only) {
+ cnt = scnprintf(ptr,len,"%s0x%lx",
+ (spcFl ? " " : ""),
+ um);
+ ptr += cnt; len -= cnt; uc += cnt;
+ spcFl = !0;
+ } else if (um & val) {
+ cnt = scnprintf(ptr,len,"%s+0x%lx",
+ (spcFl ? " " : ""),
+ um & val);
+ ptr += cnt; len -= cnt; uc += cnt;
+ spcFl = !0;
+ } else if (um & ~val) {
+ cnt = scnprintf(ptr,len,"%s+0x%lx",
+ (spcFl ? " " : ""),
+ um & ~val);
+ ptr += cnt; len -= cnt; uc += cnt;
+ spcFl = !0;
+ }
+ }
+ return uc;
+}
+
+
+static const char *boolNames[] = {
+ "false",
+ "true",
+ "no",
+ "yes",
+};
+
+
+static int parse_token(const char *ptr,unsigned int len,
+ int *valptr,
+ const char **names,unsigned int namecnt)
+{
+ char buf[33];
+ unsigned int slen;
+ unsigned int idx;
+ int negfl;
+ char *p2;
+ *valptr = 0;
+ if (!names) namecnt = 0;
+ for (idx = 0; idx < namecnt; idx++) {
+ if (!names[idx]) continue;
+ slen = strlen(names[idx]);
+ if (slen != len) continue;
+ if (memcmp(names[idx],ptr,slen)) continue;
+ *valptr = idx;
+ return 0;
+ }
+ negfl = 0;
+ if ((*ptr == '-') || (*ptr == '+')) {
+ negfl = (*ptr == '-');
+ ptr++; len--;
+ }
+ if (len >= sizeof(buf)) return -EINVAL;
+ memcpy(buf,ptr,len);
+ buf[len] = 0;
+ *valptr = simple_strtol(buf,&p2,0);
+ if (negfl) *valptr = -(*valptr);
+ if (*p2) return -EINVAL;
+ return 1;
+}
+
+
+static int parse_mtoken(const char *ptr,unsigned int len,
+ int *valptr,
+ const char **names,int valid_bits)
+{
+ char buf[33];
+ unsigned int slen;
+ unsigned int idx;
+ char *p2;
+ int msk;
+ *valptr = 0;
+ for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
+ if (!msk & valid_bits) continue;
+ valid_bits &= ~msk;
+ if (!names[idx]) continue;
+ slen = strlen(names[idx]);
+ if (slen != len) continue;
+ if (memcmp(names[idx],ptr,slen)) continue;
+ *valptr = msk;
+ return 0;
+ }
+ if (len >= sizeof(buf)) return -EINVAL;
+ memcpy(buf,ptr,len);
+ buf[len] = 0;
+ *valptr = simple_strtol(buf,&p2,0);
+ if (*p2) return -EINVAL;
+ return 0;
+}
+
+
+static int parse_tlist(const char *ptr,unsigned int len,
+ int *maskptr,int *valptr,
+ const char **names,int valid_bits)
+{
+ unsigned int cnt;
+ int mask,val,kv,mode,ret;
+ mask = 0;
+ val = 0;
+ ret = 0;
+ while (len) {
+ cnt = 0;
+ while ((cnt < len) &&
+ ((ptr[cnt] <= 32) ||
+ (ptr[cnt] >= 127))) cnt++;
+ ptr += cnt;
+ len -= cnt;
+ mode = 0;
+ if ((*ptr == '-') || (*ptr == '+')) {
+ mode = (*ptr == '-') ? -1 : 1;
+ ptr++;
+ len--;
+ }
+ cnt = 0;
+ while (cnt < len) {
+ if (ptr[cnt] <= 32) break;
+ if (ptr[cnt] >= 127) break;
+ cnt++;
+ }
+ if (!cnt) break;
+ if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
+ ret = -EINVAL;
+ break;
+ }
+ ptr += cnt;
+ len -= cnt;
+ switch (mode) {
+ case 0:
+ mask = valid_bits;
+ val |= kv;
+ break;
+ case -1:
+ mask |= kv;
+ val &= ~kv;
+ break;
+ case 1:
+ mask |= kv;
+ val |= kv;
+ break;
+ default:
+ break;
+ }
+ }
+ *maskptr = mask;
+ *valptr = val;
+ return ret;
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+ const char *ptr,unsigned int len,
+ int *maskptr,int *valptr)
+{
+ int ret = -EINVAL;
+ unsigned int cnt;
+
+ *maskptr = 0;
+ *valptr = 0;
+
+ cnt = 0;
+ while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
+ len -= cnt; ptr += cnt;
+ cnt = 0;
+ while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
+ (ptr[len-(cnt+1)] >= 127))) cnt++;
+ len -= cnt;
+
+ if (!len) return -EINVAL;
+
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ if (cptr->info->type == pvr2_ctl_int) {
+ ret = parse_token(ptr,len,valptr,NULL,0);
+ if ((ret >= 0) &&
+ ((*valptr < cptr->info->def.type_int.min_value) ||
+ (*valptr > cptr->info->def.type_int.max_value))) {
+ ret = -ERANGE;
+ }
+ if (maskptr) *maskptr = ~0;
+ } else if (cptr->info->type == pvr2_ctl_bool) {
+ ret = parse_token(
+ ptr,len,valptr,boolNames,
+ sizeof(boolNames)/sizeof(boolNames[0]));
+ if (ret == 1) {
+ *valptr = *valptr ? !0 : 0;
+ } else if (ret == 0) {
+ *valptr = (*valptr & 1) ? !0 : 0;
+ }
+ if (maskptr) *maskptr = 1;
+ } else if (cptr->info->type == pvr2_ctl_enum) {
+ ret = parse_token(
+ ptr,len,valptr,
+ cptr->info->def.type_enum.value_names,
+ cptr->info->def.type_enum.count);
+ if ((ret >= 0) &&
+ ((*valptr < 0) ||
+ (*valptr >= cptr->info->def.type_enum.count))) {
+ ret = -ERANGE;
+ }
+ if (maskptr) *maskptr = ~0;
+ } else if (cptr->info->type == pvr2_ctl_bitmask) {
+ ret = parse_tlist(
+ ptr,len,maskptr,valptr,
+ cptr->info->def.type_bitmask.bit_names,
+ cptr->info->def.type_bitmask.valid_bits);
+ }
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len)
+{
+ int ret = -EINVAL;
+
+ *len = 0;
+ if (cptr->info->type == pvr2_ctl_int) {
+ *len = scnprintf(buf,maxlen,"%d",val);
+ ret = 0;
+ } else if (cptr->info->type == pvr2_ctl_bool) {
+ *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
+ ret = 0;
+ } else if (cptr->info->type == pvr2_ctl_enum) {
+ const char **names;
+ names = cptr->info->def.type_enum.value_names;
+ if ((val >= 0) &&
+ (val < cptr->info->def.type_enum.count)) {
+ if (names[val]) {
+ *len = scnprintf(
+ buf,maxlen,"%s",
+ names[val]);
+ } else {
+ *len = 0;
+ }
+ ret = 0;
+ }
+ } else if (cptr->info->type == pvr2_ctl_bitmask) {
+ *len = gen_bitmask_string(
+ val & mask & cptr->info->def.type_bitmask.valid_bits,
+ ~0,!0,
+ cptr->info->def.type_bitmask.bit_names,
+ buf,maxlen);
+ }
+ return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len)
+{
+ int ret;
+ LOCK_TAKE(cptr->hdw->big_lock); do {
+ ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
+ buf,maxlen,len);
+ } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+ return ret;
+}
+
+
+/*
+ Stuff for Emacs to see, in order to encourage consistent editing style:
+ *** Local Variables: ***
+ *** mode: c ***
+ *** fill-column: 75 ***
+ *** tab-width: 8 ***
+ *** c-basic-offset: 8 ***
+ *** End: ***
+ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
new file mode 100644
index 000000000..c1680053c
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
@@ -0,0 +1,123 @@
+/*
+ *
+ * $Id$
+ *
+ * Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __PVRUSB2_CTRL_H
+#define __PVRUSB2_CTRL_H
+
+struct pvr2_ctrl;
+
+enum pvr2_ctl_type {
+ pvr2_ctl_int = 0,
+ pvr2_ctl_enum = 1,
+ pvr2_ctl_bitmask = 2,
+ pvr2_ctl_bool = 3,
+};
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *);
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *);
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *);
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
+ unsigned int *);
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
+
+/* Return V4L flags value for control (or zero if there is no v4l control
+ actually under this control) */
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *);
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *);
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
+ const char *buf,unsigned int len,
+ int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
+ const char *buf,unsigned int len,
+ int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value - must already be
+ inside of critical region. */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
+ int mask,int val,
+ char *buf,unsigned int maxlen,
+ unsigned int *len);
+
+#endif /* __PVRUSB2_CTRL_H */
+
+/*
+ Stuff for Emacs to see, in order to encourage consistent editing style:
+ *** Local Variables: ***
+ *** mode: c ***
+ *** fill-column: 75 ***
+ *** tab-width: 8 ***
+ *** c-basic-offset: 8 ***
+ *** End: ***
+ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 3cbce8eba..c80c26be6 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -58,7 +58,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
memset(&route,0,sizeof(route));
- switch(hdw->controls[PVR2_CID_INPUT].value) {
+ switch(hdw->input_val) {
case PVR2_CVAL_INPUT_TV:
vid_input = CX25840_COMPOSITE7;
aud_input = CX25840_AUDIO8;
@@ -91,7 +91,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
static int check_input(struct pvr2_v4l_cx2584x *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->controls[PVR2_CID_INPUT].dirty != 0;
+ return hdw->input_dirty != 0;
}
@@ -101,15 +101,18 @@ static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
struct pvr2_hdw *hdw = ctxt->hdw;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
- hdw->controls[PVR2_CID_SRATE].value);
- switch (hdw->controls[PVR2_CID_SRATE].value) {
+ hdw->srate_val);
+ switch (hdw->srate_val) {
default:
- case PVR2_CVAL_SRATE_48:
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
val = 48000;
break;
- case PVR2_CVAL_SRATE_44_1:
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
val = 44100;
break;
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+ val = 32000;
+ break;
}
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
}
@@ -118,7 +121,7 @@ static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->controls[PVR2_CID_SRATE].dirty != 0;
+ return hdw->srate_dirty != 0;
}
@@ -136,8 +139,8 @@ static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
{
- ctxt->client->handler = 0;
- ctxt->hdw->decoder_ctrl = 0;
+ ctxt->client->handler = NULL;
+ ctxt->hdw->decoder_ctrl = NULL;
kfree(ctxt);
}
@@ -218,7 +221,7 @@ static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
{
int ret;
- ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,0);
+ ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index 16e6ea317..f985f00d8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -32,11 +32,11 @@ struct debugifc_mask_item {
};
static struct debugifc_mask_item mask_items[] = {
- {"ENC_FIRMWARE",PVR2_SUBSYS_ENC_FIRMWARE},
- {"ENC_CFG",PVR2_SUBSYS_ENC_CFG},
- {"DIG_RUN",PVR2_SUBSYS_DIGITIZER_RUN},
- {"USB_RUN",PVR2_SUBSYS_USBSTREAM_RUN},
- {"ENC_RUN",PVR2_SUBSYS_ENC_RUN},
+ {"ENC_FIRMWARE",(1<<PVR2_SUBSYS_B_ENC_FIRMWARE)},
+ {"ENC_CFG",(1<<PVR2_SUBSYS_B_ENC_CFG)},
+ {"DIG_RUN",(1<<PVR2_SUBSYS_B_DIGITIZER_RUN)},
+ {"USB_RUN",(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)},
+ {"ENC_RUN",(1<<PVR2_SUBSYS_B_ENC_RUN)},
};
@@ -82,7 +82,7 @@ static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
unsigned int wlen;
unsigned int scnt;
- wptr = 0;
+ wptr = NULL;
wlen = 0;
scnt = debugifc_count_whitespace(buf,count);
consume_cnt += scnt; count -= scnt; buf += scnt;
@@ -337,8 +337,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
}
-int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
- unsigned int count)
+static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+ unsigned int count)
{
const char *wptr;
unsigned int wlen;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-demod.c b/linux/drivers/media/video/pvrusb2/pvrusb2-demod.c
deleted file mode 100644
index f082ecee2..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-demod.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *
- * $Id$
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "pvrusb2.h"
-#include "pvrusb2-util.h"
-#include "pvrusb2-demod.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "compat.h"
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-
-
-struct pvr2_demod_handler {
- struct pvr2_hdw *hdw;
- struct pvr2_i2c_client *client;
- struct pvr2_i2c_handler i2c_handler;
- int type_update_fl;
-};
-
-
-static void set_config(struct pvr2_demod_handler *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- int cfg = 0;
-
- switch (hdw->tuner_type) {
- case TUNER_PHILIPS_FM1216ME_MK3:
- case TUNER_PHILIPS_FM1236_MK3:
- cfg = TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE;
- break;
- default:
- break;
- }
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c demod set_config(0x%x)",cfg);
- pvr2_i2c_client_cmd(ctxt->client,TDA9887_SET_CONFIG,&cfg);
- ctxt->type_update_fl = 0;
-}
-
-
-static int demod_check(struct pvr2_demod_handler *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- if (hdw->tuner_updated) ctxt->type_update_fl = !0;
- return ctxt->type_update_fl != 0;
-}
-
-
-static void demod_update(struct pvr2_demod_handler *ctxt)
-{
- if (ctxt->type_update_fl) set_config(ctxt);
-}
-
-
-static void demod_detach(struct pvr2_demod_handler *ctxt)
-{
- ctxt->client->handler = 0;
- kfree(ctxt);
-}
-
-
-static unsigned int demod_describe(struct pvr2_demod_handler *ctxt,char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-demod");
-}
-
-
-const static struct pvr2_i2c_handler_functions tuner_funcs = {
- .detach = (void (*)(void *))demod_detach,
- .check = (int (*)(void *))demod_check,
- .update = (void (*)(void *))demod_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))demod_describe,
-};
-
-
-int pvr2_i2c_demod_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
- struct pvr2_demod_handler *ctxt;
- if (cp->handler) return 0;
-
- ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
- memset(ctxt,0,sizeof(*ctxt));
-
- ctxt->i2c_handler.func_data = ctxt;
- ctxt->i2c_handler.func_table = &tuner_funcs;
- ctxt->type_update_fl = !0;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- cp->handler = &ctxt->i2c_handler;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tda9887 V4L2 handler set up",
- cp->client->addr);
- return !0;
-}
-
-
-
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 70 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-demod.h b/linux/drivers/media/video/pvrusb2/pvrusb2-demod.h
deleted file mode 100644
index 4c4e40ffb..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-demod.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * $Id$
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __PVRUSB2_DEMOD_H
-#define __PVRUSB2_DEMOD_H
-
-#include "pvrusb2-i2c-core.h"
-
-int pvr2_i2c_demod_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
-
-#endif /* __PVRUSB2_DEMOD_H */
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 70 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
index 78bc968c0..e0e248b83 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
@@ -59,7 +59,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Failed to allocate memory"
" required to read eeprom");
- return 0;
+ return NULL;
}
trace_eeprom("Value for eeprom addr from controller was 0x%x",
@@ -83,7 +83,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
msg[0].flags = 0;
msg[0].len = mode16 ? 2 : 1;
msg[0].buf = iadd;
- msg[1].addr = hdw->eeprom_addr;
+ msg[1].addr = addr;
msg[1].flags = I2C_M_RD;
/* We have to do the actual eeprom data fetch ourselves, because
@@ -109,7 +109,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"eeprom fetch set offs err=%d",ret);
kfree(eeprom);
- return 0;
+ return NULL;
}
}
return eeprom;
@@ -147,7 +147,7 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
trace_eeprom("rev_str=%s",tvdata.rev_str);
hdw->tuner_type = tvdata.tuner_type;
hdw->serial_number = tvdata.serial_number;
- pvr2_hdw_internal_set_std_avail(hdw,tvdata.tuner_formats);
+ hdw->std_mask_eeprom = tvdata.tuner_formats;
kfree(eeprom);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index 2a93bcc96..657993fa8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -20,42 +20,14 @@
*
*/
+#include "compat.h"
#include <linux/device.h> // for linux/firmware.h
#include <linux/firmware.h>
-#include <media/cx2341x.h>
#include "pvrusb2-util.h"
#include "pvrusb2-encoder.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
-static u32 pvr_tbl_emphasis [] = {
- [PVR2_CVAL_AUDIOEMPHASIS_NONE] = 0x0 << 12,
- [PVR2_CVAL_AUDIOEMPHASIS_50_15] = 0x1 << 12,
- [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = 0x3 << 12,
-};
-
-static u32 pvr_tbl_srate[] = {
- [PVR2_CVAL_SRATE_48] = 0x01,
- [PVR2_CVAL_SRATE_44_1] = 0x00,
-};
-
-static u32 pvr_tbl_audiobitrate[] = {
- [PVR2_CVAL_AUDIOBITRATE_384] = 0xe << 4,
- [PVR2_CVAL_AUDIOBITRATE_320] = 0xd << 4,
- [PVR2_CVAL_AUDIOBITRATE_256] = 0xc << 4,
- [PVR2_CVAL_AUDIOBITRATE_224] = 0xb << 4,
- [PVR2_CVAL_AUDIOBITRATE_192] = 0xa << 4,
- [PVR2_CVAL_AUDIOBITRATE_160] = 0x9 << 4,
- [PVR2_CVAL_AUDIOBITRATE_128] = 0x8 << 4,
- [PVR2_CVAL_AUDIOBITRATE_112] = 0x7 << 4,
- [PVR2_CVAL_AUDIOBITRATE_96] = 0x6 << 4,
- [PVR2_CVAL_AUDIOBITRATE_80] = 0x5 << 4,
- [PVR2_CVAL_AUDIOBITRATE_64] = 0x4 << 4,
- [PVR2_CVAL_AUDIOBITRATE_56] = 0x3 << 4,
- [PVR2_CVAL_AUDIOBITRATE_48] = 0x2 << 4,
- [PVR2_CVAL_AUDIOBITRATE_32] = 0x1 << 4,
- [PVR2_CVAL_AUDIOBITRATE_VBR] = 0x0 << 4,
-};
/* Firmware mailbox flags - definitions found from ivtv */
@@ -64,7 +36,7 @@ static u32 pvr_tbl_audiobitrate[] = {
#define IVTV_MBOX_DRIVER_BUSY 0x00000001
-static int pvr2_write_encoder_words(struct pvr2_hdw *hdw,
+static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
const u32 *data, unsigned int dlen)
{
unsigned int idx;
@@ -94,7 +66,7 @@ static int pvr2_write_encoder_words(struct pvr2_hdw *hdw,
}
ret = pvr2_send_request(hdw,
hdw->cmd_buffer,1+(chunkCnt*7),
- 0,0);
+ NULL,0);
if (ret) return ret;
data += chunkCnt;
dlen -= chunkCnt;
@@ -105,7 +77,7 @@ static int pvr2_write_encoder_words(struct pvr2_hdw *hdw,
}
-static int pvr2_read_encoder_words(struct pvr2_hdw *hdw,int statusFl,
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
u32 *data, unsigned int dlen)
{
unsigned int idx;
@@ -146,15 +118,46 @@ static int pvr2_read_encoder_words(struct pvr2_hdw *hdw,int statusFl,
}
-static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
- int args, ...)
+/* This prototype is set up to be compatible with the
+ cx2341x_mbox_func prototype in cx2341x.h, which should be in
+ kernels 2.6.18 or later. We do this so that we can enable
+ cx2341x.ko to write to our encoder (by handing it a pointer to this
+ function). For earlier kernels this doesn't really matter. */
+static int pvr2_encoder_cmd(void *ctxt,
+ int cmd,
+ int arg_cnt_send,
+ int arg_cnt_recv,
+ u32 *argp)
{
unsigned int poll_count;
int ret = 0;
- va_list vl;
unsigned int idx;
+ /* These sizes look to be limited by the FX2 firmware implementation */
u32 wrData[16];
- u32 rdData[32];
+ u32 rdData[16];
+ struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
+
+#if 0
+ {
+ char buf[150];
+ unsigned int ccnt,bcnt;
+
+ bcnt = scnprintf(buf,sizeof(buf),"Encoder Cmd %02x (",cmd);
+ for (idx = 0; idx < arg_cnt_send; idx++) {
+ if (idx) {
+ ccnt = scnprintf(buf+bcnt,
+ sizeof(buf)-bcnt," ");
+ bcnt += ccnt;
+ }
+ ccnt = scnprintf(buf+bcnt,sizeof(buf)-bcnt,
+ "0x%x",argp[idx]);
+ bcnt += ccnt;
+ }
+ ccnt = scnprintf(buf+bcnt,sizeof(buf)-bcnt,")");
+ bcnt += ccnt;
+ pvr2_trace(PVR2_TRACE_ENCODER,"%.*s",bcnt,buf);
+ }
+#endif
/*
@@ -188,6 +191,28 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
*/
+ if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+ "Failed to write cx23416 command"
+ " - too many input arguments"
+ " (was given %u limit %u)",
+ arg_cnt_send,
+ (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
+ return -EINVAL;
+ }
+
+ if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+ "Failed to write cx23416 command"
+ " - too many return arguments"
+ " (was given %u limit %u)",
+ arg_cnt_recv,
+ (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
+ return -EINVAL;
+ }
+
LOCK_TAKE(hdw->ctl_lock); do {
@@ -195,25 +220,22 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
wrData[1] = cmd;
wrData[2] = 0;
wrData[3] = 0x00060000;
- va_start(vl, args);
- for (idx = 0; idx < args; idx++) {
- wrData[idx+4] = va_arg(vl, u32);
+ for (idx = 0; idx < arg_cnt_send; idx++) {
+ wrData[idx+4] = argp[idx];
}
- va_end(vl);
- args += 4;
- while (args < sizeof(wrData)/sizeof(wrData[0])) {
- wrData[args++] = 0;
+ for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
+ wrData[idx+4] = 0;
}
- ret = pvr2_write_encoder_words(hdw,wrData,args);
+ ret = pvr2_encoder_write_words(hdw,wrData,idx);
if (ret) break;
wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
- ret = pvr2_write_encoder_words(hdw,wrData,1);
+ ret = pvr2_encoder_write_words(hdw,wrData,1);
if (ret) break;
poll_count = 0;
while (1) {
if (poll_count < 10000000) poll_count++;
- ret = pvr2_read_encoder_words(hdw,!0,rdData,1);
+ ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
if (ret) break;
if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
break;
@@ -227,7 +249,7 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Encoder command: 0x%02x",cmd);
- for (idx = 4; idx < args; idx++) {
+ for (idx = 4; idx < arg_cnt_send; idx++) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Encoder arg%d: 0x%08x",
@@ -244,8 +266,11 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
}
if (ret) break;
wrData[0] = 0x7;
- ret = pvr2_read_encoder_words(hdw,0,rdData,16);
+ ret = pvr2_encoder_read_words(
+ hdw,0,rdData,
+ sizeof(rdData)/sizeof(rdData[0]));
if (ret) break;
+#if 0
for (idx = 0; idx < args; idx++) {
if (rdData[idx] != wrData[idx]) {
pvr2_trace(
@@ -255,9 +280,13 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
idx,wrData[idx],rdData[idx]);
}
}
+#endif
+ for (idx = 0; idx < arg_cnt_recv; idx++) {
+ argp[idx] = rdData[idx+4];
+ }
wrData[0] = 0x0;
- ret = pvr2_write_encoder_words(hdw,wrData,1);
+ ret = pvr2_encoder_write_words(hdw,wrData,1);
if (ret) break;
} while(0); LOCK_GIVE(hdw->ctl_lock);
@@ -265,163 +294,94 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd,
return ret;
}
-int pvr2_encoder_configure(struct pvr2_hdw *hdw)
+
+static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
+ int args, ...)
{
- int ret = 0, audio, i;
- int vd_std = hdw->controls[PVR2_CID_STDCUR].value;
- int height = hdw->controls[PVR2_CID_VRES].value;
- int width = hdw->controls[PVR2_CID_HRES].value;
- int height_full = !hdw->controls[PVR2_CID_INTERLACE].value;
-
- int is_30fps, is_ntsc;
-
- if (vd_std & V4L2_STD_NTSC) {
- is_ntsc=1;
- is_30fps=1;
- } else if (vd_std & V4L2_STD_PAL_M) {
- is_ntsc=0;
- is_30fps=1;
- } else {
- is_ntsc=0;
- is_30fps=0;
+ va_list vl;
+ unsigned int idx;
+ u32 data[12];
+
+ if (args > sizeof(data)/sizeof(data[0])) {
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+ "Failed to write cx23416 command"
+ " - too many arguments"
+ " (was given %u limit %u)",
+ args,(unsigned int)(sizeof(data)/sizeof(data[0])));
+ return -EINVAL;
}
- pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure");
-
- /* set stream output port. */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_OUTPUT_PORT, 2,
- 0x01, 0x02);
-
- /* set the Program Index Information. We want I,P,B frames (max 400) */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_PGM_INDEX_INFO, 2,
- 0x07, 0x0190);
-
- /* NOTE : windows driver sends these */
- /* Mike Isely <isely@pobox.com> 7-Mar-2006 The windows driver
- sends the following commands but if we do the same then
- many apps are no longer able to read the video stream.
- Leaving these out seems to do no harm at all, so they're
- commented out for that reason. */
-#ifdef notdef
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,1,0,0);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
-#endif
+ va_start(vl, args);
+ for (idx = 0; idx < args; idx++) {
+ data[idx] = va_arg(vl, u32);
+ }
+ va_end(vl);
- /* Strange compared to ivtv data. */
-#if 0
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
- 0x0120, 0x0120);
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
- 0x0131, 0x0131);
-#endif
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
- 0xf0, 0xf0);
+ return pvr2_encoder_cmd(hdw,cmd,args,0,data);
+}
- /* setup firmware to notify us about some events (don't know why...) */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
- 0, 0, 0x10000000, 0xffffffff);
+int pvr2_encoder_configure(struct pvr2_hdw *hdw)
+{
+ int ret;
+ pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
+ " (cx2341x module)");
+ hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
+ hdw->enc_ctl_state.width = hdw->res_hor_val;
+ hdw->enc_ctl_state.height = hdw->res_ver_val;
+ hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
+ (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
+ 0 : 1);
- /* set fps to 25 or 30 (1 or 0)*/
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1,
- is_30fps ? 0 : 1);
+ ret = 0;
- /* set encoding resolution */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2,
- (height_full ? height : (height / 2)),
- width);
- /* set encoding aspect ratio to 4:3 */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1,
- 0x02);
+ if (!ret) ret = pvr2_encoder_vcmd(
+ hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
+ 0xf0, 0xf0);
- /* VBI */
+ /* setup firmware to notify us about some events (don't know why...) */
+ if (!ret) ret = pvr2_encoder_vcmd(
+ hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
+ 0, 0, 0x10000000, 0xffffffff);
+
+ if (!ret) ret = pvr2_encoder_vcmd(
+ hdw,CX2341X_ENC_SET_VBI_LINE, 5,
+ 0xffffffff,0,0,0,0);
+
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Failed to configure cx32416");
+ return ret;
+ }
- if (hdw->config == pvr2_config_vbi) {
- int lines = 2 * (is_30fps ? 12 : 18);
- int size = (4*((lines*1443+3)/4)) / lines;
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_VBI_CONFIG, 7,
- 0xbd05, 1, 4,
- 0x25256262, 0x387f7f7f,
- lines , size);
-// 0x25256262, 0x13135454, lines , size);
- /* select vbi lines */
-#define line_used(l) (is_30fps ? (l >= 10 && l <= 21) : (l >= 6 && l <= 23))
- for (i = 2 ; i <= 24 ; i++){
- ret |= pvr2_write_encoder_vcmd(
- hdw,CX2341X_ENC_SET_VBI_LINE, 5,
- i-1,line_used(i), 0, 0, 0);
- ret |= pvr2_write_encoder_vcmd(
- hdw,CX2341X_ENC_SET_VBI_LINE, 5,
- (i-1) | (1 << 31),
- line_used(i), 0, 0, 0);
- }
- } else {
- ret |= pvr2_write_encoder_vcmd(
- hdw,CX2341X_ENC_SET_VBI_LINE, 5,
- 0xffffffff,0,0,0,0);
+ ret = cx2341x_update(hdw,pvr2_encoder_cmd,
+ (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
+ &hdw->enc_ctl_state);
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Error from cx2341x module code=%d",ret);
+ return ret;
}
- /* set stream type, depending on resolution. */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_STREAM_TYPE, 1,
- height_full ? 0x0a : 0x0b);
- /* set video bitrate */
- ret |= pvr2_write_encoder_vcmd(
- hdw, CX2341X_ENC_SET_BIT_RATE, 3,
- (hdw->controls[PVR2_CID_VBR].value ? 1 : 0),
- hdw->controls[PVR2_CID_AVERAGEVIDEOBITRATE].value,
- (u32) (hdw->controls[PVR2_CID_PEAKVIDEOBITRATE].value) / 400);
- /* setup GOP structure (GOP size = 0f or 0c, 3-1 = 2 B-frames) */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
- is_30fps ? 0x0f : 0x0c, 0x03);
-
- /* enable 3:2 pulldown */
- ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0);
-
- /* set GOP open/close property (open) */
- ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0);
-
- /* set audio stream properties 0x40b9? 0100 0000 1011 1001 */
- audio = (pvr_tbl_audiobitrate[hdw->controls[
- PVR2_CID_AUDIOBITRATE].value] |
- pvr_tbl_srate[hdw->controls[PVR2_CID_SRATE].value] |
- hdw->controls[PVR2_CID_AUDIOLAYER].value << 2 |
- (hdw->controls[PVR2_CID_AUDIOCRC].value ? 1 << 14 : 0) |
- pvr_tbl_emphasis[hdw->controls[
- PVR2_CID_AUDIOEMPHASIS].value]);
-
- ret |= pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1,
- audio);
-
- /* set dynamic noise reduction filter to manual, Horiz/Vert */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
- 0, 0x03);
-
- /* dynamic noise reduction filter param */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2
- , 0, 0);
-
- /* dynamic noise reduction median filter */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4,
- 0, 0xff, 0, 0xff);
-
- /* spacial prefiler parameter */
- ret |= pvr2_write_encoder_vcmd(hdw,
- CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
- 0x01, 0x01);
-
- /* initialize video input */
- ret |= pvr2_write_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
- if (!ret) {
- hdw->subsys_enabled_mask |= PVR2_SUBSYS_ENC_CFG;
+ ret = 0;
+
+ if (!ret) ret = pvr2_encoder_vcmd(
+ hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
+
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Failed to initialize cx32416 video input");
+ return ret;
}
- return ret;
+ hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+ memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
+ sizeof(struct cx2341x_mpeg_params));
+ hdw->enc_cur_valid = !0;
+ return 0;
}
+
int pvr2_encoder_start(struct pvr2_hdw *hdw)
{
int status;
@@ -434,17 +394,17 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
if (hdw->config == pvr2_config_vbi) {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
- 0x01,0x14);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+ 0x01,0x14);
} else if (hdw->config == pvr2_config_mpeg) {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
- 0,0x13);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+ 0,0x13);
} else {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
- 0,0x13);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+ 0,0x13);
}
if (!status) {
- hdw->subsys_enabled_mask |= PVR2_SUBSYS_ENC_RUN;
+ hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
}
return status;
}
@@ -457,14 +417,14 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
pvr2_write_register(hdw, 0x0048, 0xffffffff);
if (hdw->config == pvr2_config_vbi) {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
- 0x01,0x01,0x14);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+ 0x01,0x01,0x14);
} else if (hdw->config == pvr2_config_mpeg) {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
- 0x01,0,0x13);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+ 0x01,0,0x13);
} else {
- status = pvr2_write_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
- 0x01,0,0x13);
+ status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+ 0x01,0,0x13);
}
/* change some GPIO data */
@@ -474,7 +434,7 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
if (!status) {
- hdw->subsys_enabled_mask &= ~PVR2_SUBSYS_ENC_RUN;
+ hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
}
return status;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 9c5f0f74c..63e2299cb 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -34,60 +34,21 @@
*/
#include "compat.h"
+#include <linux/config.h>
#include <linux/videodev2.h>
#include <linux/i2c.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-#include <asm/atomic.h>
-#include <asm/mutex.h>
+#include <linux/mutex.h>
#else
#include <asm/semaphore.h>
#endif
#include "pvrusb2-hdw.h"
#include "pvrusb2-io.h"
-
-
-/* Definition of state variables that we can inspect & change. Numbers are
- assigned from zero counting up with no gaps. */
-#define PVR2_CID_BRIGHTNESS 0
-#define PVR2_CID_CONTRAST 1
-#define PVR2_CID_SATURATION 2
-#define PVR2_CID_HUE 3
-#define PVR2_CID_VOLUME 4
-#define PVR2_CID_BALANCE 5
-#define PVR2_CID_BASS 6
-#define PVR2_CID_TREBLE 7
-#define PVR2_CID_MUTE 8
-#define PVR2_CID_SRATE 9
-#define PVR2_CID_AUDIOBITRATE 10
-#define PVR2_CID_AUDIOCRC 11
-#define PVR2_CID_AUDIOEMPHASIS 12
-#define PVR2_CID_VBR 13
-#define PVR2_CID_AVERAGEVIDEOBITRATE 14
-#define PVR2_CID_PEAKVIDEOBITRATE 15
-#define PVR2_CID_STDAVAIL 16 // V4L2 video standard bit mask
-#define PVR2_CID_INPUT 17
-#define PVR2_CID_AUDIOMODE 18 // V4L2 standard audio mode enum
-#define PVR2_CID_FREQUENCY 19 // Units of Hz
-#define PVR2_CID_HRES 20
-#define PVR2_CID_VRES 21
-#define PVR2_CID_INTERLACE 22
-#define PVR2_CID_AUDIOLAYER 23
-#define PVR2_CID_CHANNEL 24
-#define PVR2_CID_CHANPROG_ID 25
-#define PVR2_CID_CHANPROG_FREQ 26
-#define PVR2_CID_SIGNAL_PRESENT 27
-#define PVR2_CID_STREAMING_ENABLED 28
-#define PVR2_CID_HSM 29
-#define PVR2_CID_SUBSYS_MASK 30
-#define PVR2_CID_SUBSYS_STREAM_MASK 31
-#define PVR2_CID_STDCUR 32 // V4L2 video standard bit mask
-#define PVR2_CID_STDNAME 33 // Enumeration of available standards
+#include <media/cx2341x.h>
/* Legal values for the SRATE state variable */
#define PVR2_CVAL_SRATE_48 0
#define PVR2_CVAL_SRATE_44_1 1
-#define PVR2_CVAL_SRATE_MIN PVR2_CVAL_SRATE_48
-#define PVR2_CVAL_SRATE_MAX PVR2_CVAL_SRATE_44_1
/* Legal values for the AUDIOBITRATE state variable */
#define PVR2_CVAL_AUDIOBITRATE_384 0
@@ -105,22 +66,16 @@
#define PVR2_CVAL_AUDIOBITRATE_48 12
#define PVR2_CVAL_AUDIOBITRATE_32 13
#define PVR2_CVAL_AUDIOBITRATE_VBR 14
-#define PVR2_CVAL_AUDIOBITRATE_MIN PVR2_CVAL_AUDIOBITRATE_384
-#define PVR2_CVAL_AUDIOBITRATE_MAX PVR2_CVAL_AUDIOBITRATE_VBR
/* Legal values for the AUDIOEMPHASIS state variable */
#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
-#define PVR2_CVAL_AUDIOEMPHASIS_MIN PVR2_CVAL_AUDIOEMPHASIS_NONE
-#define PVR2_CVAL_AUDIOEMPHASIS_MAX PVR2_CVAL_AUDIOEMPHASIS_CCITT
/* Legal values for PVR2_CID_HSM */
#define PVR2_CVAL_HSM_FAIL 0
#define PVR2_CVAL_HSM_FULL 1
#define PVR2_CVAL_HSM_HIGH 2
-#define PVR2_CVAL_HSM_MIN PVR2_CVAL_HSM_FAIL
-#define PVR2_CVAL_HSM_MAX PVR2_CVAL_HSM_HIGH
#define PVR2_VID_ENDPOINT 0x84
#define PVR2_UNK_ENDPOINT 0x86 /* maybe raw yuv ? */
@@ -135,37 +90,81 @@
struct pvr2_decoder;
-struct pvr2_ctl_def;
-struct pvr2_ctrl;
-
-typedef int (*pvr2_ctl_set_func)(struct pvr2_ctrl *,int val);
-typedef int (*pvr2_ctl_get_func)(struct pvr2_ctrl *);
-
-struct pvr2_ctl_def {
- int id;
+typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
+typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
+typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
+typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
+ char *,unsigned int,unsigned int *);
+typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
+ const char *,unsigned int,
+ int *mskp,int *valp);
+typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *);
+
+/* This structure describes a specific control. A table of these is set up
+ in pvrusb2-hdw.c. */
+struct pvr2_ctl_info {
+ /* Control's name suitable for use as an identifier */
const char *name;
+
+ /* Short description of control */
const char *desc;
- pvr2_ctl_set_func set_func;
- pvr2_ctl_get_func get_func;
- int mask_value;
- int max_value;
- int min_value;
+
+ /* Control's implementation */
+ pvr2_ctlf_get_value get_value; /* Get its value */
+ pvr2_ctlf_set_value set_value; /* Set its value */
+ pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */
+ pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */
+ pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */
+ pvr2_ctlf_clear_dirty clear_dirty; /* Clear dirty state */
+ pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */
+
+ /* Control's type (int, enum, bitmask) */
+ enum pvr2_ctl_type type;
+
+ /* Associated V4L control ID, if any */
+ int v4l_id;
+
+ /* Associated driver internal ID, if any */
+ int internal_id;
+
+ /* Don't implicitly initialize this control's value */
int skip_init;
+
+ /* Starting value for this control */
int default_value;
- int is_valid;
- const char **value_defs_ptr;
- unsigned int value_defs_count;
+
+ /* Type-specific control information */
+ union {
+ struct { /* Integer control */
+ long min_value; /* lower limit */
+ long max_value; /* upper limit */
+ } type_int;
+ struct { /* enumerated control */
+ unsigned int count; /* enum value count */
+ const char **value_names; /* symbol names */
+ } type_enum;
+ struct { /* bitmask control */
+ unsigned int valid_bits; /* bits in use */
+ const char **bit_names; /* symbol name/bit */
+ } type_bitmask;
+ } def;
};
+/* Same as pvr2_ctl_info, but includes storage for the control description */
+#define PVR2_CTLD_INFO_DESC_SIZE 32
+struct pvr2_ctld_info {
+ struct pvr2_ctl_info info;
+ char desc[PVR2_CTLD_INFO_DESC_SIZE];
+};
+
struct pvr2_ctrl {
+ const struct pvr2_ctl_info *info;
struct pvr2_hdw *hdw;
- const struct pvr2_ctl_def *ctl_def;
- int is_valid;
- int value;
- int dirty;
};
+
struct pvr2_audio_stat {
void *ctxt;
void (*detach)(void *);
@@ -203,6 +202,9 @@ struct pvr2_decoder_ctrl {
#define PVR2_HDW_TYPE_24XXX 1
#endif
+typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+#define PVR2_I2C_FUNC_CNT 128
+
/* This structure contains all state data directly needed to
manipulate the hardware (as opposed to complying with a kernel
interface) */
@@ -233,6 +235,8 @@ struct pvr2_hdw {
/* I2C stuff */
struct i2c_adapter i2c_adap;
struct i2c_algorithm i2c_algo;
+ pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
+ int i2c_cx25840_hack_state;
int i2c_linked;
unsigned int i2c_pend_types; /* Which types of update are needed */
unsigned long i2c_pend_mask; /* Change bits we need to scan */
@@ -247,6 +251,8 @@ struct pvr2_hdw {
/* Frequency table */
unsigned int freqTable[FREQTABLE_SIZE];
+ unsigned int freqProgSlot;
+ unsigned int freqSlot;
/* Stuff for handling low level control interaction with device */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
@@ -296,13 +302,25 @@ struct pvr2_hdw {
/* Tuner / frequency control stuff */
unsigned int tuner_type;
int tuner_updated;
- v4l2_std_id video_std_avail;
- v4l2_std_id video_std_cur;
- struct pvr2_ctl_def video_std_enum;
+ unsigned int freqVal;
+ int freqDirty;
+
+ /* Video standard handling */
+ v4l2_std_id std_mask_eeprom; // Hardware supported selections
+ v4l2_std_id std_mask_avail; // Which standards we may select from
+ v4l2_std_id std_mask_cur; // Currently selected standard(s)
+ unsigned int std_enum_cnt; // # of enumerated standards
+ int std_enum_cur; // selected standard enumeration value
+ int std_dirty; // True if std_mask_cur has changed
+ struct pvr2_ctl_info std_info_enum;
+ struct pvr2_ctl_info std_info_avail;
+ struct pvr2_ctl_info std_info_cur;
struct v4l2_standard *std_defs;
- const char **video_std_names;
- unsigned int std_cnt;
- int std_id;
+ const char **std_enum_names;
+
+ // Generated string names, one per actual V4L2 standard
+ const char *std_mask_ptrs[32];
+ char std_mask_names[32][10];
int unit_number; /* ID for driver instance */
unsigned long serial_number; /* ID for hardware itself */
@@ -321,19 +339,38 @@ struct pvr2_hdw {
int flag_bilingual;
struct pvr2_audio_stat *audio_stat;
- /* Every last bit of controllable state */
+ /* Control state needed for cx2341x module */
+ struct cx2341x_mpeg_params enc_cur_state;
+ struct cx2341x_mpeg_params enc_ctl_state;
+ /* True if an encoder attribute has changed */
+ int enc_stale;
+ /* True if enc_cur_state is valid */
+ int enc_cur_valid;
+
+ /* Control state */
+#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
+ VCREATE_DATA(brightness);
+ VCREATE_DATA(contrast);
+ VCREATE_DATA(saturation);
+ VCREATE_DATA(hue);
+ VCREATE_DATA(volume);
+ VCREATE_DATA(balance);
+ VCREATE_DATA(bass);
+ VCREATE_DATA(treble);
+ VCREATE_DATA(mute);
+ VCREATE_DATA(input);
+ VCREATE_DATA(audiomode);
+ VCREATE_DATA(res_hor);
+ VCREATE_DATA(res_ver);
+ VCREATE_DATA(srate);
+#undef VCREATE_DATA
+
+ struct pvr2_ctld_info *mpeg_ctrl_info;
+
struct pvr2_ctrl *controls;
+ unsigned int control_cnt;
};
-int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
-
-int pvr2_ctrl_internal_set_value(struct pvr2_ctrl *cptr,int val);
-int pvr2_ctrl_internal_get_value(struct pvr2_ctrl *cptr);
-
-int pvr2_hdw_internal_set_stdenum_cur(struct pvr2_hdw *hdw,int val);
-void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int msk);
-void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int msk);
-
#endif /* __PVRUSB2_HDW_INTERNAL_H */
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index f0de1e154..5ad657e89 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -27,6 +27,7 @@
#include <linux/videodev2.h>
#include <asm/semaphore.h>
#include "pvrusb2.h"
+#include "pvrusb2-std.h"
#include "pvrusb2-util.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-i2c-core.h"
@@ -53,14 +54,49 @@ static const char *pvr2_device_names[] = {
#endif
};
-static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = 0};
-DECLARE_MUTEX(pvr2_unit_sem);
+struct pvr2_string_table {
+ const char **lst;
+ unsigned int cnt;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+// Names of other client modules to request for 24xxx model hardware
+static const char *pvr2_client_24xxx[] = {
+ "cx25840",
+ "tuner",
+ "wm8775",
+};
+#endif
+
+// Names of other client modules to request for 29xxx model hardware
+static const char *pvr2_client_29xxx[] = {
+ "msp3400",
+ "saa7115",
+ "tuner",
+};
+
+static struct pvr2_string_table pvr2_client_lists[] = {
+ [PVR2_HDW_TYPE_29XXX] = {
+ pvr2_client_29xxx,
+ sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+ },
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+ [PVR2_HDW_TYPE_24XXX] = {
+ pvr2_client_24xxx,
+ sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+ },
+#endif
+};
+
+static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
+static DECLARE_MUTEX(pvr2_unit_sem);
static int ctlchg = 0;
static int initusbreset = 1;
static int procreload = 0;
static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
static int init_pause_msec = 0;
module_param(ctlchg, int, S_IRUGO|S_IWUSR);
@@ -74,6 +110,8 @@ MODULE_PARM_DESC(procreload,
"Attempt init failure recovery with firmware reload");
module_param_array(tuner, int, NULL, 0444);
MODULE_PARM_DESC(tuner,"specify installed tuner type");
+module_param_array(video_std, int, NULL, 0444);
+MODULE_PARM_DESC(video_std,"specify initial video standard");
module_param_array(tolerance, int, NULL, 0444);
MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
@@ -91,69 +129,105 @@ MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
/* size of a firmware chunk */
#define FIRMWARE_CHUNK_SIZE 0x2000
-static const char *control_values_srate[] = {
- [PVR2_CVAL_SRATE_48] = "48KHz",
- [PVR2_CVAL_SRATE_44_1] = "44.1KHz",
+/* Define the list of additional controls we'll dynamically construct based
+ on query of the cx2341x module. */
+struct pvr2_mpeg_ids {
+ const char *strid;
+ int id;
};
-
-
-static const char *control_values_audiobitrate[] = {
- [PVR2_CVAL_AUDIOBITRATE_384] = "384kb/s",
- [PVR2_CVAL_AUDIOBITRATE_320] = "320kb/s",
- [PVR2_CVAL_AUDIOBITRATE_256] = "256kb/s",
- [PVR2_CVAL_AUDIOBITRATE_224] = "224kb/s",
- [PVR2_CVAL_AUDIOBITRATE_192] = "192kb/s",
- [PVR2_CVAL_AUDIOBITRATE_160] = "160kb/s",
- [PVR2_CVAL_AUDIOBITRATE_128] = "128kb/s",
- [PVR2_CVAL_AUDIOBITRATE_112] = "112kb/s",
- [PVR2_CVAL_AUDIOBITRATE_96] = "96kb/s",
- [PVR2_CVAL_AUDIOBITRATE_80] = "80kb/s",
- [PVR2_CVAL_AUDIOBITRATE_64] = "64kb/s",
- [PVR2_CVAL_AUDIOBITRATE_56] = "56kb/s",
- [PVR2_CVAL_AUDIOBITRATE_48] = "48kb/s",
- [PVR2_CVAL_AUDIOBITRATE_32] = "32kb/s",
- [PVR2_CVAL_AUDIOBITRATE_VBR] = "VBR",
+static const struct pvr2_mpeg_ids mpeg_ids[] = {
+ {
+ .strid = "audio_layer",
+ .id = V4L2_CID_MPEG_AUDIO_ENCODING,
+ },{
+ .strid = "audio_bitrate",
+ .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+ },{
+ /* Already using audio_mode elsewhere :-( */
+ .strid = "mpeg_audio_mode",
+ .id = V4L2_CID_MPEG_AUDIO_MODE,
+ },{
+ .strid = "mpeg_audio_mode_extension",
+ .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+ },{
+ .strid = "audio_emphasis",
+ .id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
+ },{
+ .strid = "audio_crc",
+ .id = V4L2_CID_MPEG_AUDIO_CRC,
+ },{
+ .strid = "video_aspect",
+ .id = V4L2_CID_MPEG_VIDEO_ASPECT,
+ },{
+ .strid = "video_b_frames",
+ .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+ },{
+ .strid = "video_gop_size",
+ .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+ },{
+ .strid = "video_gop_closure",
+ .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+ },{
+ .strid = "video_pulldown",
+ .id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
+ },{
+ .strid = "video_bitrate_mode",
+ .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+ },{
+ .strid = "video_bitrate",
+ .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+ },{
+ .strid = "video_bitrate_peak",
+ .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+ },{
+ .strid = "video_temporal_decimation",
+ .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+ },{
+ .strid = "stream_type",
+ .id = V4L2_CID_MPEG_STREAM_TYPE,
+ },{
+ .strid = "video_spatial_filter_mode",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+ },{
+ .strid = "video_spatial_filter",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+ },{
+ .strid = "video_luma_spatial_filter_type",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+ },{
+ .strid = "video_chroma_spatial_filter_type",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+ },{
+ .strid = "video_temporal_filter_mode",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+ },{
+ .strid = "video_temporal_filter",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+ },{
+ .strid = "video_median_filter_type",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+ },{
+ .strid = "video_luma_median_filter_top",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+ },{
+ .strid = "video_luma_median_filter_bottom",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+ },{
+ .strid = "video_chroma_median_filter_top",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+ },{
+ .strid = "video_chroma_median_filter_bottom",
+ .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+ }
};
+#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
-
-static const char *control_values_audioemphasis[] = {
- [PVR2_CVAL_AUDIOEMPHASIS_NONE] = "None",
- [PVR2_CVAL_AUDIOEMPHASIS_50_15] = "50/15us",
- [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = "CCITT J.17",
+static const char *control_values_srate[] = {
+ [PVR2_CVAL_SRATE_48] = "48KHz",
+ [PVR2_CVAL_SRATE_44_1] = "44.1KHz",
};
-static const char *control_values_videostandard[] = {
- "PAL-B",
- "PAL-B1",
- "PAL-G",
- "PAL-H",
-
- "PAL-I",
- "PAL-D",
- "PAL-D1",
- "PAL-K",
-
- "PAL-M",
- "PAL-N",
- "PAL-Nc",
- "PAL-60",
-
- "NTSC-M",
- "NTSC-M-JP",
- "NTSC-443",
- 0,
-
- "SECAM-B",
- "SECAM-D",
- "SECAM-G",
- "SECAM-H",
-
- "SECAM-K",
- "SECAM-K1",
- "SECAM-L",
- "SECAM-LC",
-};
static const char *control_values_input[] = {
@@ -180,339 +254,581 @@ static const char *control_values_hsm[] = {
};
-#define VDEF(x) \
- .value_defs_ptr = x, \
- .value_defs_count = (sizeof(x)/sizeof(x[0]))
-
-static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value);
-static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val);
-static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr,int val);
-static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val);
-static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr);
-static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val);
-static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr);
-
-static struct pvr2_ctl_def control_defs[] =
-{
- [PVR2_CID_BRIGHTNESS] = {
- .id = V4L2_CID_BRIGHTNESS,
- .is_valid = !0,
+static const char *control_values_subsystem[] = {
+ [PVR2_SUBSYS_B_ENC_FIRMWARE] = "enc_firmware",
+ [PVR2_SUBSYS_B_ENC_CFG] = "enc_config",
+ [PVR2_SUBSYS_B_DIGITIZER_RUN] = "digitizer_run",
+ [PVR2_SUBSYS_B_USBSTREAM_RUN] = "usbstream_run",
+ [PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
+};
+
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
+static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
+static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
+static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
+static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+ unsigned long msk,
+ unsigned long val);
+static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+ unsigned long msk,
+ unsigned long val);
+static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+ unsigned int timeout,int probe_fl,
+ void *write_data,unsigned int write_len,
+ void *read_data,unsigned int read_len);
+static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res);
+static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res);
+
+static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+ *vp = hdw->freqTable[hdw->freqProgSlot-1];
+ } else {
+ *vp = 0;
+ }
+ return 0;
+}
+
+static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+ hdw->freqTable[hdw->freqProgSlot-1] = v;
+ }
+ return 0;
+}
+
+static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->freqProgSlot;
+ return 0;
+}
+
+static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
+ hdw->freqProgSlot = v;
+ }
+ return 0;
+}
+
+static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->freqSlot;
+ return 0;
+}
+
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ unsigned freq = 0;
+ struct pvr2_hdw *hdw = cptr->hdw;
+ hdw->freqSlot = v;
+ if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
+ freq = hdw->freqTable[hdw->freqSlot-1];
+ }
+ if (freq && (freq != hdw->freqVal)) {
+ hdw->freqVal = freq;
+ hdw->freqDirty = !0;
+ }
+ return 0;
+}
+
+static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->freqVal;
+ return 0;
+}
+
+static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
+{
+ return cptr->hdw->freqDirty != 0;
+}
+
+static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
+{
+ cptr->hdw->freqDirty = 0;
+}
+
+static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ hdw->freqVal = v;
+ hdw->freqDirty = !0;
+ hdw->freqSlot = 0;
+ return 0;
+}
+
+static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
+{
+ return cptr->hdw->enc_stale != 0;
+}
+
+static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
+{
+ cptr->hdw->enc_stale = 0;
+}
+
+static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ int ret;
+ struct v4l2_ext_controls cs;
+ struct v4l2_ext_control c1;
+ memset(&cs,0,sizeof(cs));
+ memset(&c1,0,sizeof(c1));
+ cs.controls = &c1;
+ cs.count = 1;
+ c1.id = cptr->info->v4l_id;
+ ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+ VIDIOC_G_EXT_CTRLS);
+ if (ret) return ret;
+ *vp = c1.value;
+ return 0;
+}
+
+static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ int ret;
+ struct v4l2_ext_controls cs;
+ struct v4l2_ext_control c1;
+ memset(&cs,0,sizeof(cs));
+ memset(&c1,0,sizeof(c1));
+ cs.controls = &c1;
+ cs.count = 1;
+ c1.id = cptr->info->v4l_id;
+ c1.value = v;
+ ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+ VIDIOC_S_EXT_CTRLS);
+ if (ret) return ret;
+ cptr->hdw->enc_stale = !0;
+ return 0;
+}
+
+static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
+{
+ struct v4l2_queryctrl qctrl;
+ struct pvr2_ctl_info *info;
+ qctrl.id = cptr->info->v4l_id;
+ cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
+ /* Strip out the const so we can adjust a function pointer. It's
+ OK to do this here because we know this is a dynamically created
+ control, so the underlying storage for the info pointer is (a)
+ private to us, and (b) not in read-only storage. Either we do
+ this or we significantly complicate the underlying control
+ implementation. */
+ info = (struct pvr2_ctl_info *)(cptr->info);
+ if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
+ if (info->set_value) {
+ info->set_value = NULL;
+ }
+ } else {
+ if (!(info->set_value)) {
+ info->set_value = ctrl_cx2341x_set;
+ }
+ }
+ return qctrl.flags;
+}
+
+static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->flag_streaming_enabled;
+ return 0;
+}
+
+static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ int result = pvr2_hdw_is_hsm(cptr->hdw);
+ *vp = PVR2_CVAL_HSM_FULL;
+ if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
+ if (result) *vp = PVR2_CVAL_HSM_HIGH;
+ return 0;
+}
+
+static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->std_mask_avail;
+ return 0;
+}
+
+static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ v4l2_std_id ns;
+ ns = hdw->std_mask_avail;
+ ns = (ns & ~m) | (v & m);
+ if (ns == hdw->std_mask_avail) return 0;
+ hdw->std_mask_avail = ns;
+ pvr2_hdw_internal_set_std_avail(hdw);
+ pvr2_hdw_internal_find_stdenum(hdw);
+ return 0;
+}
+
+static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
+ char *bufPtr,unsigned int bufSize,
+ unsigned int *len)
+{
+ *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
+ return 0;
+}
+
+static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
+ const char *bufPtr,unsigned int bufSize,
+ int *mskp,int *valp)
+{
+ int ret;
+ v4l2_std_id id;
+ ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
+ if (ret < 0) return ret;
+ if (mskp) *mskp = id;
+ if (valp) *valp = id;
+ return 0;
+}
+
+static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->std_mask_cur;
+ return 0;
+}
+
+static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ v4l2_std_id ns;
+ ns = hdw->std_mask_cur;
+ ns = (ns & ~m) | (v & m);
+ if (ns == hdw->std_mask_cur) return 0;
+ hdw->std_mask_cur = ns;
+ hdw->std_dirty = !0;
+ pvr2_hdw_internal_find_stdenum(hdw);
+ return 0;
+}
+
+static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+ return cptr->hdw->std_dirty != 0;
+}
+
+static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+ cptr->hdw->std_dirty = 0;
+}
+
+static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
+ PVR2_SIGNAL_OK) ? 1 : 0);
+ return 0;
+}
+
+static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->subsys_enabled_mask;
+ return 0;
+}
+
+static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v);
+ return 0;
+}
+
+static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->subsys_stream_mask;
+ return 0;
+}
+
+static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v);
+ return 0;
+}
+
+static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+ struct pvr2_hdw *hdw = cptr->hdw;
+ if (v < 0) return -EINVAL;
+ if (v > hdw->std_enum_cnt) return -EINVAL;
+ hdw->std_enum_cur = v;
+ if (!v) return 0;
+ v--;
+ if (hdw->std_mask_cur == hdw->std_defs[v].id) return 0;
+ hdw->std_mask_cur = hdw->std_defs[v].id;
+ hdw->std_dirty = !0;
+ return 0;
+}
+
+
+static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+ *vp = cptr->hdw->std_enum_cur;
+ return 0;
+}
+
+
+static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+ return cptr->hdw->std_dirty != 0;
+}
+
+
+static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+ cptr->hdw->std_dirty = 0;
+}
+
+
+#define DEFINT(vmin,vmax) \
+ .type = pvr2_ctl_int, \
+ .def.type_int.min_value = vmin, \
+ .def.type_int.max_value = vmax
+
+#define DEFENUM(tab) \
+ .type = pvr2_ctl_enum, \
+ .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
+ .def.type_enum.value_names = tab
+
+#define DEFBOOL \
+ .type = pvr2_ctl_bool
+
+#define DEFMASK(msk,tab) \
+ .type = pvr2_ctl_bitmask, \
+ .def.type_bitmask.valid_bits = msk, \
+ .def.type_bitmask.bit_names = tab
+
+#define DEFREF(vname) \
+ .set_value = ctrl_set_##vname, \
+ .get_value = ctrl_get_##vname, \
+ .is_dirty = ctrl_isdirty_##vname, \
+ .clear_dirty = ctrl_cleardirty_##vname
+
+
+#define VCREATE_FUNCS(vname) \
+static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
+{*vp = cptr->hdw->vname##_val; return 0;} \
+static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
+{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
+static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
+{return cptr->hdw->vname##_dirty != 0;} \
+static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
+{cptr->hdw->vname##_dirty = 0;}
+
+VCREATE_FUNCS(brightness)
+VCREATE_FUNCS(contrast)
+VCREATE_FUNCS(saturation)
+VCREATE_FUNCS(hue)
+VCREATE_FUNCS(volume)
+VCREATE_FUNCS(balance)
+VCREATE_FUNCS(bass)
+VCREATE_FUNCS(treble)
+VCREATE_FUNCS(mute)
+VCREATE_FUNCS(input)
+VCREATE_FUNCS(audiomode)
+VCREATE_FUNCS(res_hor)
+VCREATE_FUNCS(res_ver)
+VCREATE_FUNCS(srate)
+
+#define MIN_FREQ 55250000L
+#define MAX_FREQ 850000000L
+
+/* Table definition of all controls which can be manipulated */
+static const struct pvr2_ctl_info control_defs[] = {
+ {
+ .v4l_id = V4L2_CID_BRIGHTNESS,
.desc = "Brightness",
.name = "brightness",
- .min_value = 0,
- .max_value = 255,
.default_value = 128,
- },
- [PVR2_CID_CONTRAST] = {
- .id = V4L2_CID_CONTRAST,
- .is_valid = !0,
+ DEFREF(brightness),
+ DEFINT(0,255),
+ },{
+ .v4l_id = V4L2_CID_CONTRAST,
.desc = "Contrast",
.name = "contrast",
- .min_value = 0,
- .max_value = 127,
.default_value = 68,
- },
- [PVR2_CID_SATURATION] = {
- .id = V4L2_CID_SATURATION,
- .is_valid = !0,
+ DEFREF(contrast),
+ DEFINT(0,127),
+ },{
+ .v4l_id = V4L2_CID_SATURATION,
.desc = "Saturation",
.name = "saturation",
- .min_value = 0,
- .max_value = 127,
.default_value = 64,
- },
- [PVR2_CID_HUE] = {
- .id = V4L2_CID_HUE,
- .is_valid = !0,
+ DEFREF(saturation),
+ DEFINT(0,127),
+ },{
+ .v4l_id = V4L2_CID_HUE,
.desc = "Hue",
.name = "hue",
- .min_value = -128,
- .max_value = 127,
.default_value = 0,
- },
- [PVR2_CID_VOLUME] = {
- .id = V4L2_CID_AUDIO_VOLUME,
- .is_valid = !0,
+ DEFREF(hue),
+ DEFINT(-128,127),
+ },{
+ .v4l_id = V4L2_CID_AUDIO_VOLUME,
.desc = "Volume",
.name = "volume",
- .min_value = 0,
- .max_value = 65535,
.default_value = 65535,
- },
- [PVR2_CID_BALANCE] = {
- .id = V4L2_CID_AUDIO_BALANCE,
- .is_valid = !0,
+ DEFREF(volume),
+ DEFINT(0,65535),
+ },{
+ .v4l_id = V4L2_CID_AUDIO_BALANCE,
.desc = "Balance",
.name = "balance",
- .min_value = -32768,
- .max_value = 32767,
.default_value = 0,
- },
- [PVR2_CID_BASS] = {
- .id = V4L2_CID_AUDIO_BASS,
- .is_valid = !0,
+ DEFREF(balance),
+ DEFINT(-32768,32767),
+ },{
+ .v4l_id = V4L2_CID_AUDIO_BASS,
.desc = "Bass",
.name = "bass",
- .min_value = -32768,
- .max_value = 32767,
.default_value = 0,
- },
- [PVR2_CID_TREBLE] = {
- .id = V4L2_CID_AUDIO_TREBLE,
- .is_valid = !0,
+ DEFREF(bass),
+ DEFINT(-32768,32767),
+ },{
+ .v4l_id = V4L2_CID_AUDIO_TREBLE,
.desc = "Treble",
.name = "treble",
- .min_value = -32768,
- .max_value = 32767,
.default_value = 0,
- },
- [PVR2_CID_MUTE] = {
- .id = V4L2_CID_AUDIO_MUTE,
- .is_valid = !0,
+ DEFREF(treble),
+ DEFINT(-32768,32767),
+ },{
+ .v4l_id = V4L2_CID_AUDIO_MUTE,
.desc = "Mute",
.name = "mute",
- .min_value = 0,
- .max_value = 1,
- .default_value = 0,
- },
- [PVR2_CID_SRATE] = {
- .id = V4L2_CID_PVR_SRATE,
- .is_valid = !0,
- .desc = "Sample rate",
- .name = "srate",
- .min_value = PVR2_CVAL_SRATE_MIN,
- .max_value = PVR2_CVAL_SRATE_MAX,
- .default_value = PVR2_CVAL_SRATE_48,
- VDEF(control_values_srate),
- },
- [PVR2_CID_AUDIOBITRATE] = {
- .id = V4L2_CID_PVR_AUDIOBITRATE,
- .is_valid = !0,
- .desc = "Audio Bitrate",
- .name = "audio_bitrate",
- .min_value = PVR2_CVAL_AUDIOBITRATE_MIN,
- .max_value = PVR2_CVAL_AUDIOBITRATE_MAX,
- .default_value = PVR2_CVAL_AUDIOBITRATE_224,
- VDEF(control_values_audiobitrate),
- },
- [PVR2_CID_AUDIOCRC] = {
- .id = V4L2_CID_PVR_AUDIOCRC,
- .is_valid = !0,
- .desc = "Audio CRC",
- .name = "audio_crc",
- .min_value = 0,
- .max_value = 1,
- .default_value = 1,
- },
- [PVR2_CID_AUDIOEMPHASIS] = {
- .id = V4L2_CID_PVR_AUDIOEMPHASIS,
- .is_valid = !0,
- .desc = "Audio Emphasis",
- .name = "audio_emphasis",
- .min_value = PVR2_CVAL_AUDIOEMPHASIS_MIN,
- .max_value = PVR2_CVAL_AUDIOEMPHASIS_MAX,
- .default_value = PVR2_CVAL_AUDIOEMPHASIS_NONE,
- VDEF(control_values_audioemphasis),
- },
- [PVR2_CID_VBR] = {
- .id = V4L2_CID_PVR_VBR,
- .is_valid = !0,
- .desc = "Variable video bitrate",
- .name = "vbr",
- .min_value = 0,
- .max_value = 1,
.default_value = 0,
- },
- [PVR2_CID_AVERAGEVIDEOBITRATE] = {
- .id = V4L2_CID_PVR_VIDEOBITRATE,
- .is_valid = !0,
- .desc = "Average video bitrate",
- .name = "video_average_bitrate",
- .min_value = 1,
- .max_value = 20000000,
- .default_value = 6000000,
- },
- [PVR2_CID_PEAKVIDEOBITRATE] = {
- .id = V4L2_CID_PVR_VIDEOPEAK,
- .is_valid = !0,
- .desc = "Peak video bitrate",
- .name = "video_peak_bitrate",
- .min_value = 1,
- .max_value = 20000000,
- .default_value = 6000000,
- },
- [PVR2_CID_STDAVAIL] = {
- .is_valid = !0,
- .desc = "Video Standards Available Mask",
- .name = "video_standard_mask_available",
- .min_value = 0,
- .max_value = 0,
- .default_value = (int)V4L2_STD_UNKNOWN,
- .mask_value = (int)V4L2_STD_ALL,
- .get_func = pvr2_ctl_get_stdavail,
- VDEF(control_values_videostandard),
- },
- [PVR2_CID_INPUT] = {
- .id = V4L2_CID_PVR_INPUT,
- .is_valid = !0,
+ DEFREF(mute),
+ DEFBOOL,
+ },{
.desc = "Video Source",
.name = "input",
- .min_value = PVR2_CVAL_INPUT_MIN,
- .max_value = PVR2_CVAL_INPUT_MAX,
+ .internal_id = PVR2_CID_INPUT,
.default_value = PVR2_CVAL_INPUT_TV,
- VDEF(control_values_input),
- },
- [PVR2_CID_AUDIOMODE] = {
- .id = V4L2_CID_PVR_AUDIOMODE,
- .is_valid = !0,
+ DEFREF(input),
+ DEFENUM(control_values_input),
+ },{
.desc = "Audio Mode",
.name = "audio_mode",
- .min_value = V4L2_TUNER_MODE_MONO,
- .max_value = V4L2_TUNER_MODE_LANG1_LANG2,
+ .internal_id = PVR2_CID_AUDIOMODE,
.default_value = V4L2_TUNER_MODE_STEREO,
- VDEF(control_values_audiomode),
- },
- [PVR2_CID_FREQUENCY] = {
- .id = V4L2_CID_PVR_FREQUENCY,
- .is_valid = !0,
- .desc = "Tuner Frequency (Hz)",
- .name = "frequency",
- .min_value = 55250000L,
- .max_value = 850000000L,
- .default_value = 175250000L,
- },
- [PVR2_CID_HRES] = {
- .id = V4L2_CID_PVR_HRES,
- .is_valid = !0,
+ DEFREF(audiomode),
+ DEFENUM(control_values_audiomode),
+ },{
.desc = "Horizontal capture resolution",
.name = "resolution_hor",
- .min_value = 320,
- .max_value = 720,
+ .internal_id = PVR2_CID_HRES,
.default_value = 720,
- },
- [PVR2_CID_VRES] = {
- .id = V4L2_CID_PVR_VRES,
- .is_valid = !0,
+ DEFREF(res_hor),
+ DEFINT(320,720),
+ },{
.desc = "Vertical capture resolution",
.name = "resolution_ver",
- .min_value = 200,
- .max_value = 625,
+ .internal_id = PVR2_CID_VRES,
.default_value = 480,
- },
- [PVR2_CID_INTERLACE] = {
- .id = V4L2_CID_PVR_INTERLACE,
- .is_valid = !0,
- .desc = "Interlace mode",
- .name = "interlace",
- .min_value = 0,
- .max_value = 1,
- .default_value = 0,
- },
- [PVR2_CID_AUDIOLAYER] = {
- .is_valid = !0,
- .desc = "Audio Layer",
- .name = "audio_layer",
- .min_value = 0, /* This is all a wild guess */
- .max_value = 3,
- .default_value = 2, /* Appears to be all that is supported */
- },
- [PVR2_CID_CHANNEL] = {
- .is_valid = !0,
+ DEFREF(res_ver),
+ DEFINT(200,625),
+ },{
+ .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+ .desc = "Sample rate",
+ .name = "srate",
+ .default_value = PVR2_CVAL_SRATE_48,
+ DEFREF(srate),
+ DEFENUM(control_values_srate),
+ },{
+ .desc = "Tuner Frequency (Hz)",
+ .name = "frequency",
+ .internal_id = PVR2_CID_FREQUENCY,
+ .default_value = 175250000L,
+ .set_value = ctrl_freq_set,
+ .get_value = ctrl_freq_get,
+ .is_dirty = ctrl_freq_is_dirty,
+ .clear_dirty = ctrl_freq_clear_dirty,
+ DEFINT(MIN_FREQ,MAX_FREQ),
+ },{
.desc = "Channel",
.name = "channel",
- .min_value = 0,
- .max_value = FREQTABLE_SIZE,
- .default_value = 0,
- },
- [PVR2_CID_CHANPROG_ID] = {
- .is_valid = !0,
- .desc = "Channel Program ID",
- .name = "freq_table_channel",
- .min_value = 0,
- .max_value = FREQTABLE_SIZE,
- .default_value = 0,
- },
- [PVR2_CID_CHANPROG_FREQ] = {
- .is_valid = !0,
+ .set_value = ctrl_channel_set,
+ .get_value = ctrl_channel_get,
+ DEFINT(0,FREQTABLE_SIZE),
+ },{
.desc = "Channel Program Frequency",
.name = "freq_table_value",
- .min_value = 55250000L,
- .max_value = 850000000L,
- .skip_init = !0,
- .set_func = pvr2_ctl_set_chanprog_id,
- .get_func = pvr2_ctl_get_chanprog_id,
- },
- [PVR2_CID_SIGNAL_PRESENT] = {
- .is_valid = !0,
- .desc = "Signal Present",
- .name = "signal_present",
- .min_value = 0,
- .max_value = 1,
- .get_func = pvr2_ctl_get_signal,
- },
- [PVR2_CID_STREAMING_ENABLED] = {
- .is_valid = !0,
+ .set_value = ctrl_channelfreq_set,
+ .get_value = ctrl_channelfreq_get,
+ DEFINT(MIN_FREQ,MAX_FREQ),
+ },{
+ .desc = "Channel Program ID",
+ .name = "freq_table_channel",
+ .set_value = ctrl_channelprog_set,
+ .get_value = ctrl_channelprog_get,
+ DEFINT(0,FREQTABLE_SIZE),
+ },{
.desc = "Streaming Enabled",
.name = "streaming_enabled",
- .min_value = 0,
- .max_value = 1,
- .get_func = pvr2_ctl_get_streaming,
- },
- [PVR2_CID_HSM] = {
- .is_valid = !0,
+ .get_value = ctrl_streamingenabled_get,
+ DEFBOOL,
+ },{
.desc = "USB Speed",
.name = "usb_speed",
- .min_value = PVR2_CVAL_HSM_MIN,
- .max_value = PVR2_CVAL_HSM_MAX,
- .get_func = pvr2_ctl_get_hsm,
- VDEF(control_values_hsm),
- },
- [PVR2_CID_SUBSYS_MASK] = {
- .is_valid = !0,
+ .get_value = ctrl_hsm_get,
+ DEFENUM(control_values_hsm),
+ },{
+ .desc = "Signal Present",
+ .name = "signal_present",
+ .get_value = ctrl_signal_get,
+ DEFBOOL,
+ },{
+ .desc = "Video Standards Available Mask",
+ .name = "video_standard_mask_available",
+ .internal_id = PVR2_CID_STDAVAIL,
+ .skip_init = !0,
+ .get_value = ctrl_stdavail_get,
+ .set_value = ctrl_stdavail_set,
+ .val_to_sym = ctrl_std_val_to_sym,
+ .sym_to_val = ctrl_std_sym_to_val,
+ .type = pvr2_ctl_bitmask,
+ },{
+ .desc = "Video Standards In Use Mask",
+ .name = "video_standard_mask_active",
+ .internal_id = PVR2_CID_STDCUR,
+ .skip_init = !0,
+ .get_value = ctrl_stdcur_get,
+ .set_value = ctrl_stdcur_set,
+ .is_dirty = ctrl_stdcur_is_dirty,
+ .clear_dirty = ctrl_stdcur_clear_dirty,
+ .val_to_sym = ctrl_std_val_to_sym,
+ .sym_to_val = ctrl_std_sym_to_val,
+ .type = pvr2_ctl_bitmask,
+ },{
.desc = "Subsystem enabled mask",
.name = "debug_subsys_mask",
- .min_value = 0,
- .max_value = 0x7fffffff,
.skip_init = !0,
- .get_func = pvr2_ctl_get_subsys_mask,
- .set_func = pvr2_ctl_set_subsys_mask,
- },
- [PVR2_CID_SUBSYS_STREAM_MASK] = {
- .is_valid = !0,
+ .get_value = ctrl_subsys_get,
+ .set_value = ctrl_subsys_set,
+ DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+ },{
.desc = "Subsystem stream mask",
.name = "debug_subsys_stream_mask",
- .min_value = 0,
- .max_value = 0x7fffffff,
.skip_init = !0,
- .get_func = pvr2_ctl_get_subsys_stream_mask,
- .set_func = pvr2_ctl_set_subsys_stream_mask,
- },
- [PVR2_CID_STDCUR] = {
- .id = V4L2_CID_PVR_STDCUR,
- .is_valid = !0,
- .desc = "Video Standard In Use Mask",
- .name = "video_standard_mask_active",
- .min_value = 0,
- .max_value = 0,
- .default_value = (int)V4L2_STD_UNKNOWN,
- .mask_value = (int)V4L2_STD_ALL,
- .set_func = pvr2_ctl_set_stdcur,
- .get_func = pvr2_ctl_get_stdcur,
- VDEF(control_values_videostandard),
- },
+ .get_value = ctrl_subsys_stream_get,
+ .set_value = ctrl_subsys_stream_set,
+ DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+ },{
+ .desc = "Video Standard Name",
+ .name = "video_standard",
+ .internal_id = PVR2_CID_STDENUM,
+ .skip_init = !0,
+ .get_value = ctrl_stdenumcur_get,
+ .set_value = ctrl_stdenumcur_set,
+ .is_dirty = ctrl_stdenumcur_is_dirty,
+ .clear_dirty = ctrl_stdenumcur_clear_dirty,
+ .type = pvr2_ctl_enum,
+ }
};
-#undef VDEF
+#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
-#define CTRL_DEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
-#define CTRL_COUNT CTRL_DEF_COUNT+1
const char *pvr2_config_get_name(enum pvr2_config cfg)
{
@@ -537,14 +853,14 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
return hdw->serial_number;
}
-
+#if 0
struct pvr2_hdw *pvr2_hdw_find(int unit_number)
{
- if (unit_number < 0) return 0;
- if (unit_number >= PVR_NUM) return 0;
+ if (unit_number < 0) return NULL;
+ if (unit_number >= PVR_NUM) return NULL;
return unit_pointers[unit_number];
}
-
+#endif /* 0 */
int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
{
@@ -619,9 +935,9 @@ static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
* is not suitable for an usb transaction.
*
*/
-int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
+static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
{
- const struct firmware *fw_entry = 0;
+ const struct firmware *fw_entry = NULL;
void *fw_ptr;
unsigned int pipe;
int ret;
@@ -634,10 +950,7 @@ int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
"v4l-pvrusb2-24xxx-01.fw",
};
#endif
- static const struct {
- const char **lst;
- unsigned int cnt;
- } fw_file_defs[] = {
+ static const struct pvr2_string_table fw_file_defs[] = {
[PVR2_HDW_TYPE_29XXX] = {
fw_files_29xxx,
sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
@@ -720,14 +1033,14 @@ int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
{
- const struct firmware *fw_entry = 0;
+ const struct firmware *fw_entry = NULL;
void *fw_ptr;
unsigned int pipe, fw_len, fw_done;
int actual_length;
int ret = 0;
int fwidx;
static const char *fw_files[] = {
- "v4l-cx2341x-enc.fw",
+ CX2341X_FIRM_ENC_FILENAME,
};
trace_firmware("pvr2_upload_firmware2");
@@ -738,6 +1051,10 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
if (ret < 0) return ret;
fwidx = ret;
ret = 0;
+ /* Since we're about to completely reinitialize the encoder,
+ invalidate our cached copy of its configuration state. Next
+ time we configure the encoder, then we'll fully configure it. */
+ hdw->enc_cur_valid = 0;
/* First prepare firmware loading */
ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
@@ -825,17 +1142,17 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"firmware2 upload post-proc failure");
} else {
- hdw->subsys_enabled_mask |= PVR2_SUBSYS_ENC_FIRMWARE;
+ hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE);
}
return ret;
}
#define FIRMWARE_RECOVERY_BITS \
- (PVR2_SUBSYS_ENC_CFG | \
- PVR2_SUBSYS_ENC_RUN | \
- PVR2_SUBSYS_ENC_FIRMWARE | \
- PVR2_SUBSYS_USBSTREAM_RUN)
+ ((1<<PVR2_SUBSYS_B_ENC_CFG) | \
+ (1<<PVR2_SUBSYS_B_ENC_RUN) | \
+ (1<<PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+ (1<<PVR2_SUBSYS_B_USBSTREAM_RUN))
/*
@@ -867,8 +1184,9 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
reconfigure and start over.
*/
-void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,unsigned long val)
+static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+ unsigned long msk,
+ unsigned long val)
{
unsigned long nmsk;
unsigned long vmsk;
@@ -878,12 +1196,13 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
if (!hdw->flag_ok) return;
msk &= PVR2_SUBSYS_ALL;
+ nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk);
+ nmsk &= PVR2_SUBSYS_ALL;
for (;;) {
tryCount++;
- vmsk = hdw->subsys_enabled_mask & PVR2_SUBSYS_ALL;
- nmsk = (vmsk & ~msk) | (val & msk);
- if (!(nmsk ^ vmsk)) break;
+ if (!((nmsk ^ hdw->subsys_enabled_mask) &
+ PVR2_SUBSYS_ALL)) break;
if (tryCount > 4) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Too many retries when configuring device;"
@@ -903,7 +1222,7 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
vmsk = (nmsk ^ hdw->subsys_enabled_mask) &
hdw->subsys_enabled_mask;
if (vmsk) {
- if (vmsk & PVR2_SUBSYS_ENC_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_encoder_stop");
@@ -916,13 +1235,13 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
continue;
}
}
- if (vmsk & PVR2_SUBSYS_USBSTREAM_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_hdw_cmd_usbstream(0)");
pvr2_hdw_cmd_usbstream(hdw,0);
}
- if (vmsk & PVR2_SUBSYS_DIGITIZER_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" decoder disable");
@@ -935,7 +1254,7 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
" No decoder present");
}
hdw->subsys_enabled_mask &=
- ~PVR2_SUBSYS_DIGITIZER_RUN;
+ ~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
}
if (vmsk & PVR2_SUBSYS_CFG_ALL) {
hdw->subsys_enabled_mask &=
@@ -944,7 +1263,7 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
}
vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk;
if (vmsk) {
- if (vmsk & PVR2_SUBSYS_ENC_FIRMWARE) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_upload_firmware2");
@@ -957,7 +1276,7 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
break;
}
}
- if (vmsk & PVR2_SUBSYS_ENC_CFG) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_encoder_configure");
@@ -970,7 +1289,7 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
continue;
}
}
- if (vmsk & PVR2_SUBSYS_DIGITIZER_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" decoder enable");
@@ -983,15 +1302,15 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
" No decoder present");
}
hdw->subsys_enabled_mask |=
- PVR2_SUBSYS_DIGITIZER_RUN;
+ (1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
}
- if (vmsk & PVR2_SUBSYS_USBSTREAM_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_hdw_cmd_usbstream(1)");
pvr2_hdw_cmd_usbstream(hdw,!0);
}
- if (vmsk & PVR2_SUBSYS_ENC_RUN) {
+ if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
pvr2_trace(PVR2_TRACE_CTL,
"/*---TRACE_CTL----*/"
" pvr2_encoder_start");
@@ -1017,6 +1336,7 @@ void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
} while (0); LOCK_GIVE(hdw->big_lock);
}
+#if 0
void pvr2_hdw_subsys_bit_set(struct pvr2_hdw *hdw,unsigned long msk)
{
@@ -1029,6 +1349,7 @@ void pvr2_hdw_subsys_bit_clr(struct pvr2_hdw *hdw,unsigned long msk)
pvr2_hdw_subsys_bit_chg(hdw,msk,0);
}
+#endif /* 0 */
unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw)
{
@@ -1042,9 +1363,9 @@ unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw)
}
-void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val)
+static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+ unsigned long msk,
+ unsigned long val)
{
unsigned long val2;
msk &= PVR2_SUBSYS_ALL;
@@ -1066,13 +1387,7 @@ void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
}
-static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr)
-{
- return cptr->hdw->flag_streaming_enabled != 0;
-}
-
-
-int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl)
+static int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl)
{
if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0;
if (enableFl) {
@@ -1106,8 +1421,8 @@ int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
}
-int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw,
- enum pvr2_config config)
+static int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw,
+ enum pvr2_config config)
{
unsigned long sm = hdw->subsys_enabled_mask;
if (!hdw->flag_ok) return -EIO;
@@ -1142,6 +1457,17 @@ static int get_default_tuner_type(struct pvr2_hdw *hdw)
}
+static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
+{
+ int unit_number = hdw->unit_number;
+ int tp = 0;
+ if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+ tp = video_std[unit_number];
+ }
+ return tp;
+}
+
+
static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
{
int unit_number = hdw->unit_number;
@@ -1178,6 +1504,59 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
return result == 0;
}
+static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
+{
+ char buf[40];
+ unsigned int bcnt;
+ v4l2_std_id std1,std2;
+
+ std1 = get_default_standard(hdw);
+
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Supported video standard(s) reported by eeprom: %.*s",
+ bcnt,buf);
+
+ hdw->std_mask_avail = hdw->std_mask_eeprom;
+
+ std2 = std1 & ~hdw->std_mask_avail;
+ if (std2) {
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Expanding supported video standards"
+ " to include: %.*s",
+ bcnt,buf);
+ hdw->std_mask_avail |= std2;
+ }
+
+ pvr2_hdw_internal_set_std_avail(hdw);
+
+ if (std1) {
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Initial video standard forced to %.*s",
+ bcnt,buf);
+ hdw->std_mask_cur = std1;
+ hdw->std_dirty = !0;
+ pvr2_hdw_internal_find_stdenum(hdw);
+ return;
+ }
+
+ if (hdw->std_enum_cnt > 1) {
+ // Autoselect the first listed standard
+ hdw->std_enum_cur = 1;
+ hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id;
+ hdw->std_dirty = !0;
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Initial video standard auto-selected to %s",
+ hdw->std_defs[hdw->std_enum_cur-1].name);
+ return;
+ }
+
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Unable to select a viable initial video standard");
+}
+
static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
{
@@ -1216,6 +1595,10 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
}
if (!pvr2_hdw_dev_ok(hdw)) return;
+ for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) {
+ request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]);
+ }
+
pvr2_hdw_cmd_powerup(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
@@ -1229,12 +1612,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
pvr2_i2c_core_init(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < CTRL_COUNT; idx++) {
+ for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
cptr = hdw->controls + idx;
- if (!pvr2_ctrl_is_valid(cptr)) continue;
- if (cptr->ctl_def->skip_init) continue;
- pvr2_ctrl_internal_set_value(cptr,
- cptr->ctl_def->default_value);
+ if (cptr->info->skip_init) continue;
+ if (!cptr->info->set_value) continue;
+ cptr->info->set_value(cptr,~0,cptr->info->default_value);
}
// Do not use pvr2_reset_ctl_endpoints() here. It is not
@@ -1252,6 +1634,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
if (!pvr2_hdw_dev_ok(hdw)) return;
}
+ pvr2_hdw_setup_std(hdw);
+
if (!get_default_tuner_type(hdw)) {
pvr2_trace(PVR2_TRACE_INIT,
"pvr2_hdw_setup: Tuner type overridden to %d",
@@ -1264,23 +1648,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < hdw->std_cnt; idx++) {
- pvr2_trace(PVR2_TRACE_EEPROM,
- "Detected video standard %s (from eeprom)",
- hdw->std_defs[idx].name);
- }
- if (hdw->std_cnt) {
- pvr2_trace(PVR2_TRACE_EEPROM,
- "Initial video standard set to %s"
- " (detected from eeprom)",
- hdw->std_defs[hdw->std_id].name);
- } else {
- pvr2_trace(PVR2_TRACE_EEPROM,
- "Unable to select a viable video standard");
- }
-
- if (!pvr2_hdw_dev_ok(hdw)) return;
-
pvr2_hdw_commit_ctl_internal(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
@@ -1384,14 +1751,18 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
unsigned int idx,cnt1,cnt2;
struct pvr2_hdw *hdw;
unsigned int hdw_type;
+ int valid_std_mask;
+ struct pvr2_ctrl *cptr;
__u8 ifnum;
+ struct v4l2_queryctrl qctrl;
+ struct pvr2_ctl_info *ciptr;
hdw_type = devid - pvr2_device_table;
if (hdw_type >=
sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Bogus device type of %u reported",hdw_type);
- return 0;
+ return NULL;
}
hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
@@ -1399,34 +1770,113 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw,pvr2_device_names[hdw_type]);
if (!hdw) goto fail;
memset(hdw,0,sizeof(*hdw));
+ cx2341x_fill_defaults(&hdw->enc_ctl_state);
- // Initialize video standard enum dynamic control
- hdw->video_std_enum.name = "video_standard";
- hdw->video_std_enum.desc = "Video Standard Name";
- hdw->video_std_enum.id = 0; // ?????
- hdw->video_std_enum.set_func = pvr2_ctl_set_stdenumcur;
- hdw->video_std_enum.get_func = pvr2_ctl_get_stdenumcur;
- hdw->video_std_enum.mask_value = 0;
- hdw->video_std_enum.max_value = 0;
- hdw->video_std_enum.min_value = 0;
- hdw->video_std_enum.default_value = 0;
- hdw->video_std_enum.is_valid = !0;
-
- hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * CTRL_COUNT,
+ hdw->control_cnt = CTRLDEF_COUNT;
+ hdw->control_cnt += MPEGDEF_COUNT;
+ hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
GFP_KERNEL);
if (!hdw->controls) goto fail;
- memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * CTRL_COUNT);
+ memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
hdw->hdw_type = hdw_type;
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
+ cptr = hdw->controls + idx;
+ cptr->hdw = hdw;
+ }
+ for (idx = 0; idx < 32; idx++) {
+ hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
+ }
+ for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+ cptr = hdw->controls + idx;
+ cptr->info = control_defs+idx;
+ }
+ /* Define and configure additional controls from cx2341x module. */
+ hdw->mpeg_ctrl_info = kmalloc(
+ sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+ if (!hdw->mpeg_ctrl_info) goto fail;
+ memset(hdw->mpeg_ctrl_info,0,
+ sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
+ for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
+ cptr = hdw->controls + idx + CTRLDEF_COUNT;
+ ciptr = &(hdw->mpeg_ctrl_info[idx].info);
+ ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
+ ciptr->name = mpeg_ids[idx].strid;
+ ciptr->v4l_id = mpeg_ids[idx].id;
+ ciptr->skip_init = !0;
+ ciptr->get_value = ctrl_cx2341x_get;
+ ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
+ ciptr->is_dirty = ctrl_cx2341x_is_dirty;
+ if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
+ qctrl.id = ciptr->v4l_id;
+ cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
+ if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
+ ciptr->set_value = ctrl_cx2341x_set;
+ }
+ strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
+ PVR2_CTLD_INFO_DESC_SIZE);
+ hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
+ ciptr->default_value = qctrl.default_value;
+ switch (qctrl.type) {
+ default:
+ case V4L2_CTRL_TYPE_INTEGER:
+ ciptr->type = pvr2_ctl_int;
+ ciptr->def.type_int.min_value = qctrl.minimum;
+ ciptr->def.type_int.max_value = qctrl.maximum;
+ break;
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ ciptr->type = pvr2_ctl_bool;
+ break;
+ case V4L2_CTRL_TYPE_MENU:
+ ciptr->type = pvr2_ctl_enum;
+ ciptr->def.type_enum.value_names =
+ cx2341x_ctrl_get_menu(ciptr->v4l_id);
+ for (cnt1 = 0;
+ ciptr->def.type_enum.value_names[cnt1] != NULL;
+ cnt1++) { }
+ ciptr->def.type_enum.count = cnt1;
+ break;
+ }
+ cptr->info = ciptr;
+ }
- for (idx = 0; idx < CTRL_DEF_COUNT; idx++) {
- hdw->controls[idx].hdw = hdw;
- hdw->controls[idx].ctl_def = control_defs + idx;
- hdw->controls[idx].is_valid =
- hdw->controls[idx].ctl_def->is_valid;
+ // Initialize video standard enum dynamic control
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM);
+ if (cptr) {
+ memcpy(&hdw->std_info_enum,cptr->info,
+ sizeof(hdw->std_info_enum));
+ cptr->info = &hdw->std_info_enum;
+
+ }
+ // Initialize control data regarding video standard masks
+ valid_std_mask = pvr2_std_get_usable();
+ for (idx = 0; idx < 32; idx++) {
+ if (!(valid_std_mask & (1 << idx))) continue;
+ cnt1 = pvr2_std_id_to_str(
+ hdw->std_mask_names[idx],
+ sizeof(hdw->std_mask_names[idx])-1,
+ 1 << idx);
+ hdw->std_mask_names[idx][cnt1] = 0;
+ }
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
+ if (cptr) {
+ memcpy(&hdw->std_info_avail,cptr->info,
+ sizeof(hdw->std_info_avail));
+ cptr->info = &hdw->std_info_avail;
+ hdw->std_info_avail.def.type_bitmask.bit_names =
+ hdw->std_mask_ptrs;
+ hdw->std_info_avail.def.type_bitmask.valid_bits =
+ valid_std_mask;
+ }
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
+ if (cptr) {
+ memcpy(&hdw->std_info_cur,cptr->info,
+ sizeof(hdw->std_info_cur));
+ cptr->info = &hdw->std_info_cur;
+ hdw->std_info_cur.def.type_bitmask.bit_names =
+ hdw->std_mask_ptrs;
+ hdw->std_info_avail.def.type_bitmask.valid_bits =
+ valid_std_mask;
}
- hdw->controls[PVR2_CID_STDNAME].hdw = hdw;
- hdw->controls[PVR2_CID_STDNAME].ctl_def = &hdw->video_std_enum;
- hdw->controls[PVR2_CID_STDNAME].is_valid = !0;
hdw->eeprom_addr = -1;
hdw->unit_number = -1;
@@ -1468,7 +1918,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
/* Initialize the mask of subsystems that we will shut down when we
stop streaming. */
hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL;
- hdw->subsys_stream_mask |= PVR2_SUBSYS_ENC_CFG;
+ hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx",
hdw->subsys_stream_mask);
@@ -1490,40 +1940,41 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
if (hdw->controls) kfree(hdw->controls);
+ if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
kfree(hdw);
}
- return 0;
+ return NULL;
}
/* Remove _all_ associations between this driver and the underlying USB
layer. */
-void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
+static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
{
if (hdw->flag_disconnected) return;
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
if (hdw->ctl_read_urb) {
usb_kill_urb(hdw->ctl_read_urb);
usb_free_urb(hdw->ctl_read_urb);
- hdw->ctl_read_urb = 0;
+ hdw->ctl_read_urb = NULL;
}
if (hdw->ctl_write_urb) {
usb_kill_urb(hdw->ctl_write_urb);
usb_free_urb(hdw->ctl_write_urb);
- hdw->ctl_write_urb = 0;
+ hdw->ctl_write_urb = NULL;
}
if (hdw->ctl_read_buffer) {
kfree(hdw->ctl_read_buffer);
- hdw->ctl_read_buffer = 0;
+ hdw->ctl_read_buffer = NULL;
}
if (hdw->ctl_write_buffer) {
kfree(hdw->ctl_write_buffer);
- hdw->ctl_write_buffer = 0;
+ hdw->ctl_write_buffer = NULL;
}
pvr2_hdw_render_useless_unlocked(hdw);
hdw->flag_disconnected = !0;
- hdw->usb_dev = 0;
- hdw->usb_intf = 0;
+ hdw->usb_dev = NULL;
+ hdw->usb_intf = NULL;
}
@@ -1533,11 +1984,11 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
if (hdw->fw_buffer) {
kfree(hdw->fw_buffer);
- hdw->fw_buffer = 0;
+ hdw->fw_buffer = NULL;
}
if (hdw->vid_stream) {
pvr2_stream_destroy(hdw->vid_stream);
- hdw->vid_stream = 0;
+ hdw->vid_stream = NULL;
}
if (hdw->audio_stat) {
hdw->audio_stat->detach(hdw->audio_stat->ctxt);
@@ -1551,12 +2002,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
if ((hdw->unit_number >= 0) &&
(hdw->unit_number < PVR_NUM) &&
(unit_pointers[hdw->unit_number] == hdw)) {
- unit_pointers[hdw->unit_number] = 0;
+ unit_pointers[hdw->unit_number] = NULL;
}
} while (0); up(&pvr2_unit_sem);
- kfree(hdw->controls);
+ if (hdw->controls) kfree(hdw->controls);
+ if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
if (hdw->std_defs) kfree(hdw->std_defs);
- if (hdw->video_std_names) kfree(hdw->video_std_names);
+ if (hdw->std_enum_names) kfree(hdw->std_enum_names);
kfree(hdw);
}
@@ -1585,370 +2037,82 @@ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
}
-static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value)
-{
- /* This is a special case; the value to store is to an array, and
- the element to select is determined by PVR_CID_CHANPROG_ID. */
- struct pvr2_hdw *hdw = cptr->hdw;
- int id = hdw->controls[PVR2_CID_CHANPROG_ID].value;
- if ((id < 1) || (id > FREQTABLE_SIZE)) return 0;
- hdw->freqTable[id-1] = value;
- if (hdw->controls[PVR2_CID_CHANNEL].value == id) {
- /* If the current channel happens to be the slot we just
- set, then act like the current channel just got changed
- so we'll update that too. */
- hdw->controls[PVR2_CID_CHANNEL].dirty = !0;
- }
- return 0;
-}
-
-
-static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr)
+// Attempt to autoselect an appropriate value for std_enum_cur given
+// whatever is currently in std_mask_cur
+static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw)
{
- /* This is a special case; the value to return is from an array,
- and the element to select is determined by
- PVR_CID_CHANPROG_ID. */
- struct pvr2_hdw *hdw = cptr->hdw;
- int id = hdw->controls[PVR2_CID_CHANPROG_ID].value;
- if ((id < 1) || (id > FREQTABLE_SIZE)) return 0;
- return hdw->freqTable[id-1];
-}
-
-// Template data for possible enumerated video standards
-static struct v4l2_standard pvr_standards[] = {
- {
- .id = V4L2_STD_PAL_BG,
- .frameperiod =
- {
- .numerator = 1,
- .denominator= 25
- },
- .framelines = 625,
- .reserved = {0,0,0,0}
- }, {
- .id = V4L2_STD_PAL_I,
- .frameperiod =
- {
- .numerator = 1,
- .denominator= 25
- },
- .framelines = 625,
- .reserved = {0,0,0,0}
- }, {
- .id = V4L2_STD_PAL_DK,
- .frameperiod =
- {
- .numerator = 1,
- .denominator= 25
- },
- .framelines = 625,
- .reserved = {0,0,0,0}
- }, {
- .id = V4L2_STD_SECAM,
- .frameperiod =
- {
- .numerator = 1,
- .denominator= 25
- },
- .framelines = 625,
- .reserved = {0,0,0,0}
- }, {
- .id = V4L2_STD_NTSC_M,
- .frameperiod =
- {
- .numerator = 1001,
- .denominator= 30000
- },
- .framelines = 525,
- .reserved = {0,0,0,0}
- }, {
- .id = V4L2_STD_PAL_M,
- .frameperiod =
- {
- .numerator = 1001,
- .denominator= 30000
- },
- .framelines = 525,
- .reserved = {0,0,0,0}
- }
-};
-
-#define pvr_standards_cnt (sizeof(pvr_standards)/sizeof(pvr_standards[0]))
-
-
-struct name_data {
- struct v4l2_standard *std;
- unsigned int bcnt;
- unsigned int scnt;
-};
-
-static void name_build(struct name_data *dp,const char *str)
-{
- if (!dp->bcnt) {
- dp->bcnt = scnprintf(dp->std->name,
- sizeof(dp->std->name)-1,"%s",str);
- dp->scnt = 0;
- return;
- }
-
- dp->bcnt += scnprintf(dp->std->name+dp->bcnt,
- sizeof(dp->std->name)-(1+dp->bcnt),
- "%s%s",
- (dp->scnt ? "/" : "-"),str);
- (dp->scnt)++;
-}
-
-// Generate a descriptive name for a given standard
-static void name_bucket(struct v4l2_standard *std)
-{
- struct name_data nd;
- nd.std = std;
- nd.bcnt = 0;
- if (std->id & (V4L2_STD_PAL_B|
- V4L2_STD_PAL_B1|
- V4L2_STD_PAL_G|
- V4L2_STD_PAL_H|
- V4L2_STD_PAL_I|
- V4L2_STD_PAL_D|
- V4L2_STD_PAL_D1|
- V4L2_STD_PAL_K)) {
- name_build(&nd,"PAL");
- if (std->id & V4L2_STD_PAL_B) name_build(&nd,"B");
- if (std->id & V4L2_STD_PAL_B1) name_build(&nd,"B1");
- if (std->id & V4L2_STD_PAL_D) name_build(&nd,"D");
- if (std->id & V4L2_STD_PAL_D1) name_build(&nd,"D1");
- if (std->id & V4L2_STD_PAL_G) name_build(&nd,"G");
- if (std->id & V4L2_STD_PAL_H) name_build(&nd,"H");
- if (std->id & V4L2_STD_PAL_I) name_build(&nd,"I");
- if (std->id & V4L2_STD_PAL_K) name_build(&nd,"K");
- if (std->id & V4L2_STD_PAL_M) name_build(&nd,"M");
- if (std->id & V4L2_STD_PAL_N) name_build(&nd,"N");
- if (std->id & V4L2_STD_PAL_Nc) name_build(&nd,"Nc");
- if (std->id & V4L2_STD_PAL_60) name_build(&nd,"60");
- std->name[nd.bcnt] = 0;
- return;
- }
- if (std->id & (V4L2_STD_NTSC_M|
- V4L2_STD_NTSC_M_JP|
- V4L2_STD_NTSC_443)) {
- name_build(&nd,"NTSC");
- if (std->id & V4L2_STD_NTSC_M) name_build(&nd,"M");
- if (std->id & V4L2_STD_NTSC_M_JP) name_build(&nd,"Mjp");
- if (std->id & V4L2_STD_NTSC_443) name_build(&nd,"443");
- std->name[nd.bcnt] = 0;
- return;
- }
- if (std->id & (V4L2_STD_SECAM_B|
- V4L2_STD_SECAM_D|
- V4L2_STD_SECAM_G|
- V4L2_STD_SECAM_H|
- V4L2_STD_SECAM_K|
- V4L2_STD_SECAM_K1|
- V4L2_STD_SECAM_L|
- V4L2_STD_SECAM_LC)) {
- name_build(&nd,"SECAM");
- if (std->id & V4L2_STD_SECAM_B) name_build(&nd,"B");
- if (std->id & V4L2_STD_SECAM_D) name_build(&nd,"D");
- if (std->id & V4L2_STD_SECAM_G) name_build(&nd,"G");
- if (std->id & V4L2_STD_SECAM_H) name_build(&nd,"H");
- if (std->id & V4L2_STD_SECAM_K) name_build(&nd,"K");
- if (std->id & V4L2_STD_SECAM_K1) name_build(&nd,"K1");
- if (std->id & V4L2_STD_SECAM_L) name_build(&nd,"L");
- if (std->id & V4L2_STD_SECAM_LC) name_build(&nd,"LC");
- std->name[nd.bcnt] = 0;
- return;
+ unsigned int idx;
+ for (idx = 1; idx < hdw->std_enum_cnt; idx++) {
+ if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) {
+ hdw->std_enum_cur = idx;
+ return;
+ }
}
- std->name[0] = 0;
+ hdw->std_enum_cur = 0;
}
-// Given a mask of viable video standards to choose from, generate an
-// appropriate array of v4l2_standard data that corresponds to it and set
-// up related state in the driver to match.
-void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int arg)
+// Calculate correct set of enumerated standards based on currently known
+// set of available standards bits.
+static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw)
{
- v4l2_std_id buckets[pvr_standards_cnt];
- unsigned int idx1,idx2,std_cnt;
- v4l2_std_id mmsk,amsk;
-
- amsk = (v4l2_std_id)arg;
+ struct v4l2_standard *newstd;
+ unsigned int std_cnt;
+ unsigned int idx;
- // Figure out which standard groups we can work with
- std_cnt = 0;
- mmsk = 0;
- for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) {
- buckets[idx1] = pvr_standards[idx1].id & amsk;
- if (!buckets[idx1]) continue;
- mmsk |= buckets[idx1];
- amsk &= ~buckets[idx1];
- std_cnt++;
- }
-
- if (amsk) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Failed to bucketize the following standards: 0x%llx",
- amsk);
- }
+ newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail);
if (hdw->std_defs) {
kfree(hdw->std_defs);
- hdw->std_defs = 0;
+ hdw->std_defs = NULL;
}
- if (hdw->video_std_names) {
- kfree(hdw->video_std_names);
- hdw->video_std_names = 0;
+ hdw->std_enum_cnt = 0;
+ if (hdw->std_enum_names) {
+ kfree(hdw->std_enum_names);
+ hdw->std_enum_names = NULL;
}
- hdw->std_cnt = 0;
if (!std_cnt) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
- "Failed to identify any viable standard groups");
- hdw->video_std_avail = 0;
- pvr2_hdw_internal_set_std_cur(hdw,0);
- return;
- }
-
- if (std_cnt) {
- // Allocate new video standard array
- hdw->std_defs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
- GFP_KERNEL);
- hdw->std_cnt = std_cnt;
- memset(hdw->std_defs,0,sizeof(struct v4l2_standard) * std_cnt);
- hdw->video_std_names = kmalloc(sizeof(char *) * std_cnt,
- GFP_KERNEL);
- memset(hdw->video_std_names,0,sizeof(char *) * std_cnt);
- idx2 = 0;
-
- // Initialize video standard array
- for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) {
- if (!buckets[idx1]) continue;
- memcpy(hdw->std_defs + idx2,
- pvr_standards + idx1,
- sizeof(struct v4l2_standard));
- hdw->std_defs[idx2].id = buckets[idx1];
- idx2++;
- }
-
- // Generate a name for each known video standard
- for (idx1 = 0; idx1 < std_cnt; idx1++) {
- name_bucket(hdw->std_defs + idx1);
- hdw->video_std_names[idx1] =
- hdw->std_defs[idx1].name;
- }
-
- // Set up the dynamic control for this standard
- hdw->video_std_enum.value_defs_ptr = hdw->video_std_names;
- hdw->video_std_enum.value_defs_count = std_cnt;
- }
-
- hdw->video_std_avail = mmsk;
- if (!(hdw->video_std_avail & hdw->video_std_cur)) {
- // Reselect standard if there isn't one that matches...
- pvr2_hdw_internal_set_stdenum_cur(hdw,0);
- }
-}
-
-
-unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *hdw)
-{
- return hdw->std_cnt;
-}
-
-
-const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,
- unsigned int idx)
-{
- if (idx >= hdw->std_cnt) return 0;
- return hdw->std_defs + idx;
-}
-
-
-int pvr2_hdw_internal_set_stdenum_cur(struct pvr2_hdw *hdw,int val)
-{
- if (val < 0) return -EINVAL;
- if (val >= hdw->std_cnt) return -EINVAL;
- pvr2_hdw_internal_set_std_cur(hdw,hdw->std_defs[val].id);
- return 0;
-}
-
-
-void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int val)
-{
- unsigned int idx;
- v4l2_std_id msk,id;
-
- id = (v4l2_std_id)val;
- // Only select from available standards
- id &= hdw->video_std_avail;
-
- // Only select a single bit
- for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
- if (!(id & msk)) continue;
- id = msk;
- break;
+ "WARNING: Failed to identify any viable standards");
}
-
- // Get out if nothing found
- if (!msk) return;
-
- // Fix up standard group now
- hdw->video_std_cur = id;
- hdw->controls[PVR2_CID_STDCUR].value = id;
- hdw->controls[PVR2_CID_STDCUR].dirty = !0;
- for (idx = 0; idx < hdw->std_cnt; idx++) {
- if (hdw->std_defs[idx].id & id) {
- hdw->std_id = idx;
- return;
- }
+ hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);
+ hdw->std_enum_names[0] = "none";
+ for (idx = 0; idx < std_cnt; idx++) {
+ hdw->std_enum_names[idx+1] =
+ newstd[idx].name;
}
-
- // Should never really get here, but just in case...
- hdw->std_id = 0;
+ // Set up the dynamic control for this standard
+ hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;
+ hdw->std_info_enum.def.type_enum.count = std_cnt+1;
+ hdw->std_defs = newstd;
+ hdw->std_enum_cnt = std_cnt+1;
+ hdw->std_enum_cur = 0;
+ hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
}
-static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val)
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,
+ struct v4l2_standard *std,
+ unsigned int idx)
{
- pvr2_hdw_internal_set_std_cur(cptr->hdw,val);
- return 0;
-}
-
-
-static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr)
-{
- return (int)(cptr->hdw->video_std_cur);
-}
-
-
-static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val)
-{
- if (val < 0) return -EINVAL;
- if (val >= cptr->hdw->std_cnt) return -EINVAL;
- cptr->hdw->std_id = val;
- pvr2_hdw_internal_set_std_cur(cptr->hdw,
- cptr->hdw->std_id);
- return 0;
-}
-
-
-static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr)
-{
- return cptr->hdw->std_id;
-}
-
-
-static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr)
-{
- return (int)(cptr->hdw->video_std_avail);
+ int ret = -EINVAL;
+ if (!idx) return ret;
+ LOCK_TAKE(hdw->big_lock); do {
+ if (idx >= hdw->std_enum_cnt) break;
+ idx--;
+ memcpy(std,hdw->std_defs+idx,sizeof(*std));
+ ret = 0;
+ } while (0); LOCK_GIVE(hdw->big_lock);
+ return ret;
}
/* Get the number of defined controls */
unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
{
- return CTRL_COUNT;
+ return hdw->control_cnt;
}
@@ -1956,228 +2120,79 @@ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
unsigned int idx)
{
- if (idx < 0) return 0;
- if (idx >= CTRL_COUNT) return 0;
+ if (idx >= hdw->control_cnt) return NULL;
return hdw->controls + idx;
}
-/* Given an ID, retrieve the control structure associated with it. */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *hdw,unsigned int ctl_id)
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
+ unsigned int ctl_id)
{
struct pvr2_ctrl *cptr;
unsigned int idx;
int i;
/* This could be made a lot more efficient, but for now... */
- for (idx = 0; idx < CTRL_COUNT; idx++) {
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
- i = cptr->ctl_def->id;
+ i = cptr->info->internal_id;
if (i && (i == ctl_id)) return cptr;
}
-
- return 0;
+ return NULL;
}
-/* Set the current value of a given control. This assumes we are already
- inside our critical region. */
-int pvr2_ctrl_internal_set_value(struct pvr2_ctrl *cptr,int value)
+/* Given a V4L ID, retrieve the control structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
{
- const struct pvr2_ctl_def *dptr;
- int ret;
- if (!cptr) return -EINVAL;
- if (!cptr->is_valid) return -EINVAL;
- dptr = cptr->ctl_def;
- if (!dptr->is_valid) return -EINVAL;
- if (value < dptr->min_value) return -EINVAL;
- if (value > dptr->max_value) return -EINVAL;
- if (dptr->set_func) {
- ret = dptr->set_func(cptr,value);
- pvr2_i2c_core_check_stale(cptr->hdw);
- pvr2_i2c_core_sync(cptr->hdw);
- return ret;
- } else if (dptr->get_func) {
- /* If there's no "set" function yet there is still a "get"
- function, then treat this as a read-only value. */
- return -EINVAL;
- }
- if ((cptr->value != value) || (ctlchg != 0)) {
- cptr->value = value;
- cptr->dirty = !0;
- }
- return 0;
-}
-
+ struct pvr2_ctrl *cptr;
+ unsigned int idx;
+ int i;
-/* Get the current value of a given control. This assumes that we are
- already inside our critical region. */
-int pvr2_ctrl_internal_get_value(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- if (!cptr->is_valid) return 0;
- dptr = cptr->ctl_def;
- if (!dptr->is_valid) return 0;
- if (dptr->get_func) {
- return dptr->get_func(cptr);
+ /* This could be made a lot more efficient, but for now... */
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
+ cptr = hdw->controls + idx;
+ i = cptr->info->v4l_id;
+ if (i && (i == ctl_id)) return cptr;
}
-
- return cptr->value;
+ return NULL;
}
-/* Set the current value of the given control. */
-int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
+/* Given a V4L ID for its immediate predecessor, retrieve the control
+ structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
+ unsigned int ctl_id)
{
- int ret;
- if (!cptr) return -EINVAL;
- LOCK_TAKE(cptr->hdw->big_lock); do {
- ret = pvr2_ctrl_internal_set_value(cptr,val);
- } while(0); LOCK_GIVE(cptr->hdw->big_lock);
- return ret;
-}
-
-
-/* Get the current value of the given control. */
-int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr)
-{
- int ret;
- if (!cptr) return -EINVAL;
- LOCK_TAKE(cptr->hdw->big_lock); do {
- ret = pvr2_ctrl_internal_get_value(cptr);
- } while(0); LOCK_GIVE(cptr->hdw->big_lock);
- return ret;
-}
-
+ struct pvr2_ctrl *cptr,*cp2;
+ unsigned int idx;
+ int i;
-/* Return the type of the given control (int, enum, or bit mask). */
-int pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return PVR2_CTRL_TYPE_INVALID;
- dptr = cptr->ctl_def;
- if (dptr->mask_value) {
- return PVR2_CTRL_TYPE_BITMASK;
- }
- if (dptr->value_defs_ptr) {
- return PVR2_CTRL_TYPE_ENUM;
+ /* This could be made a lot more efficient, but for now... */
+ cp2 = NULL;
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
+ cptr = hdw->controls + idx;
+ i = cptr->info->v4l_id;
+ if (!i) continue;
+ if (i <= ctl_id) continue;
+ if (cp2 && (cp2->info->v4l_id < i)) continue;
+ cp2 = cptr;
}
- return PVR2_CTRL_TYPE_INT;
-}
-
-
-/* Return the minimum legal value for a given control. This command is
- only relevant for int or enum types. */
-int pvr2_ctrl_get_min_value(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->min_value;
-}
-
-
-/* Return the maximum legal value for a given control. This command is
- only relevant for int or enum types. */
-int pvr2_ctrl_get_max_value(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->max_value;
-}
-
-
-/* Return the default value for a given control. */
-int pvr2_ctrl_get_default_value(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->default_value;
-}
-
-
-/* Return a mask of which bits are used within the bit mask of a given
- control. This command is only relevant for bit mask types. */
-int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->mask_value;
-}
-
-
-/* Return true if this is a valid control. */
-int pvr2_ctrl_is_valid(struct pvr2_ctrl *cptr)
-{
- if (!cptr) return 0;
- return cptr->is_valid;
-}
-
-
-/* Return true if the control can be set (otherwise it may only be read,
- assuming that it is valid). */
-int pvr2_ctrl_is_writeable(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- if (!dptr->is_valid) return 0;
- if (dptr->set_func) return !0;
- if (dptr->get_func) return 0;
- return !0;
-}
-
-
-/* Return the control's name, or null if there isn't a name or the control
- isn't otherwise valid. */
-const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->name;
-}
-
-
-/* Return the control's description, or null if there isn't a name or the
- control isn't otherwise valid. */
-const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
-{
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- return dptr->desc;
+ return cp2;
+ return NULL;
}
-/* Return the name for an enumeration value or bit mask position for the
- given control. If the control is not an enumeration or bit mask type,
- then return null. */
-const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *cptr,int val)
+static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
{
- int msk,idx;
- const struct pvr2_ctl_def *dptr;
- if (!cptr) return 0;
- dptr = cptr->ctl_def;
- if (dptr->mask_value) {
- for (idx = 0, msk = 1;
- (idx < dptr->value_defs_count) && msk;
- idx++, msk <<= 1) {
- if (val & msk) {
- return dptr->value_defs_ptr[idx];
- }
- }
- } else {
- val -= dptr->min_value;
- if (val < 0) return 0;
- if (val >= dptr->value_defs_count) return 0;
- return dptr->value_defs_ptr[val];
+ switch (tp) {
+ case pvr2_ctl_int: return "integer";
+ case pvr2_ctl_enum: return "enum";
+ case pvr2_ctl_bool: return "boolean";
+ case pvr2_ctl_bitmask: return "bitmask";
}
- return 0;
+ return "";
}
@@ -2188,69 +2203,38 @@ const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *cptr,int val)
state(s) back to their previous value before this function was called.
Thus we can automatically reconfigure affected pieces of the driver as
controls are changed. */
-int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
+static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
{
unsigned long saved_subsys_mask = hdw->subsys_enabled_mask;
unsigned long stale_subsys_mask = 0;
unsigned int idx;
- const struct pvr2_ctl_def *dptr;
struct pvr2_ctrl *cptr;
int value;
- const char *ctl_name;
- const char *ctl_value;
int commit_flag = 0;
+ char buf[100];
+ unsigned int bcnt,ccnt;
- /* Let's see if the channel changed and we have to update the
- frequency because of it. This setup means one can tune the
- receiver either by just setting the channel (using the frequency
- table), or by directly programming the frequency. How do we
- resolve the obvious conflict here? The direct frequency takes
- priority; if directly set then we commit that value and force
- the channel to zero which is interpreted to mean "none". If on
- the other hand we see that the channel has been set and it's a
- legal value, then we copy that into the frequency. The metaphor
- here is similar to when you tune your digital radio: You an
- either set a frequency directly or punch up a pre-programmed
- station. Either way a frequency is set, and if you do use a
- preset, then the radio also shows you which preset it is - until
- you override that by directly entering a new frequency. */
- if (hdw->controls[PVR2_CID_FREQUENCY].dirty) {
- /* Frequency has been directly set, so clear out the
- channel. */
- hdw->controls[PVR2_CID_CHANNEL].value = 0;
- } else if (hdw->controls[PVR2_CID_CHANNEL].dirty) {
- int id = hdw->controls[PVR2_CID_CHANNEL].value;
- if ((id > 0) && (id <= FREQTABLE_SIZE)) {
- if (hdw->controls[PVR2_CID_FREQUENCY].value !=
- hdw->freqTable[id-1]) {
- hdw->controls[PVR2_CID_FREQUENCY].value =
- hdw->freqTable[id-1];
- hdw->controls[PVR2_CID_FREQUENCY].dirty = !0;
- }
- }
- }
-
- for (idx = 0; idx < CTRL_COUNT; idx++) {
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
- if (!cptr->dirty) continue;
+ if (cptr->info->is_dirty == 0) continue;
+ if (!cptr->info->is_dirty(cptr)) continue;
if (!commit_flag) {
commit_flag = !0;
}
- value = cptr->value;
- dptr = cptr->ctl_def;
- ctl_name = dptr->name;
- if (dptr->value_defs_ptr) {
- if (value < dptr->value_defs_count) {
- ctl_value = dptr->value_defs_ptr[value];
- } else {
- ctl_value = "<out of range>";
- }
- } else {
- ctl_value = "<integer>";
- }
+
+ bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
+ cptr->info->name);
+ value = 0;
+ cptr->info->get_value(cptr,&value);
+ pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
+ buf+bcnt,
+ sizeof(buf)-bcnt,&ccnt);
+ bcnt += ccnt;
+ bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
+ get_ctrl_typename(cptr->info->type));
pvr2_trace(PVR2_TRACE_CTL,
- "/*--TRACE_COMMIT--*/ \"%s\" <-- %d (%s)",
- ctl_name,value,ctl_value);
+ "/*--TRACE_COMMIT--*/ %.*s",
+ bcnt,buf);
}
if (!commit_flag) {
@@ -2261,52 +2245,61 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
/* When video standard changes, reset the hres and vres values -
but if the user has pending changes there, then let the changes
take priority. */
- if (hdw->controls[PVR2_CID_STDCUR].dirty) {
+ if (hdw->std_dirty) {
/* Rewrite the vertical resolution to be appropriate to the
video standard that has been selected. */
int nvres;
- if (hdw->video_std_cur & V4L2_STD_525_60) {
+ if (hdw->std_mask_cur & V4L2_STD_525_60) {
nvres = 480;
} else {
nvres = 576;
}
- if (nvres != hdw->controls[PVR2_CID_VRES].value) {
- hdw->controls[PVR2_CID_VRES].value = nvres;
- hdw->controls[PVR2_CID_VRES].dirty = !0;
- }
- if (!hdw->controls[PVR2_CID_INTERLACE].value) {
- hdw->controls[PVR2_CID_INTERLACE].value = 0;
- hdw->controls[PVR2_CID_INTERLACE].dirty = !0;
+ if (nvres != hdw->res_ver_val) {
+ hdw->res_ver_val = nvres;
+ hdw->res_ver_dirty = !0;
}
}
- if (hdw->controls[PVR2_CID_STDCUR].dirty ||
- hdw->controls[PVR2_CID_VRES].dirty ||
- hdw->controls[PVR2_CID_HRES].dirty ||
- hdw->controls[PVR2_CID_INTERLACE].dirty ||
- hdw->controls[PVR2_CID_VBR].dirty ||
- hdw->controls[PVR2_CID_AVERAGEVIDEOBITRATE].dirty ||
- hdw->controls[PVR2_CID_PEAKVIDEOBITRATE].dirty ||
- hdw->controls[PVR2_CID_AUDIOBITRATE].dirty ||
- hdw->controls[PVR2_CID_SRATE].dirty ||
- hdw->controls[PVR2_CID_AUDIOLAYER].dirty ||
- hdw->controls[PVR2_CID_AUDIOCRC].dirty ||
- hdw->controls[PVR2_CID_AUDIOEMPHASIS].dirty) {
+ if (hdw->std_dirty ||
+#if 0 /* Don't toggle encoder for now - seems to work better this way */
+ hdw->enc_stale ||
+ hdw->srate_dirty ||
+ hdw->res_ver_dirty ||
+ hdw->res_hor_dirty ||
+#endif
+ 0) {
/* If any of this changes, then the encoder needs to be
reconfigured, and we need to reset the stream. */
- stale_subsys_mask |= PVR2_SUBSYS_ENC_CFG;
+ stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
stale_subsys_mask |= hdw->subsys_stream_mask;
}
+ if (hdw->srate_dirty) {
+ /* Write new sample rate into control structure since
+ * the master copy is stale. We must track srate
+ * separate from the mpeg control structure because
+ * other logic also uses this value. */
+ struct v4l2_ext_controls cs;
+ struct v4l2_ext_control c1;
+ memset(&cs,0,sizeof(cs));
+ memset(&c1,0,sizeof(c1));
+ cs.controls = &c1;
+ cs.count = 1;
+ c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
+ c1.value = hdw->srate_val;
+ cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS);
+ }
+
/* Scan i2c core at this point - before we clear all the dirty
bits. Various parts of the i2c core will notice dirty bits as
appropriate and arrange to broadcast or directly send updates to
the client drivers in order to keep everything in sync */
pvr2_i2c_core_check_stale(hdw);
- for (idx = 0; idx < CTRL_COUNT; idx++) {
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
- cptr->dirty = 0;
+ if (!cptr->info->clear_dirty) continue;
+ cptr->info->clear_dirty(cptr);
}
/* Now execute i2c core update */
@@ -2354,14 +2347,14 @@ void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
}
}
-
+#if 0
void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw)
{
LOCK_TAKE(hdw->big_lock); do {
pvr2_hdw_poll_trigger_unlocked(hdw);
} while (0); LOCK_GIVE(hdw->big_lock);
}
-
+#endif /* 0 */
/* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
@@ -2371,10 +2364,10 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
/* Return bit mask indicating signal status */
-unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
+static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
{
unsigned int msk = 0;
- switch (hdw->controls[PVR2_CID_INPUT].value) {
+ switch (hdw->input_val) {
case PVR2_CVAL_INPUT_TV:
case PVR2_CVAL_INPUT_RADIO:
if (hdw->decoder_ctrl &&
@@ -2398,42 +2391,6 @@ unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
}
-static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr)
-{
- return cptr->hdw->subsys_enabled_mask;
-}
-
-
-static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val)
-{
- pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,~0,val);
- return 0;
-}
-
-
-static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr)
-{
- return cptr->hdw->subsys_stream_mask;
-}
-
-
-static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr,
- int val)
-{
- pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,~0,val);
- return 0;
-}
-
-
-static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr)
-{
- int result = pvr2_hdw_is_hsm(cptr->hdw);
- if (result < 0) return PVR2_CVAL_HSM_FAIL;
- if (result) return PVR2_CVAL_HSM_HIGH;
- return PVR2_CVAL_HSM_FULL;
-}
-
-
int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
{
int result;
@@ -2449,13 +2406,6 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
}
-static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr)
-{
- return ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
- PVR2_SIGNAL_OK) ? 1 : 0);
-}
-
-
/* Return bit mask indicating signal status */
unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
{
@@ -2476,11 +2426,16 @@ struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
{
+ int nr = pvr2_hdw_get_unit_number(hdw);
LOCK_TAKE(hdw->big_lock); do {
hdw->log_requested = !0;
+ printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
pvr2_i2c_core_check_stale(hdw);
hdw->log_requested = 0;
pvr2_i2c_core_sync(hdw);
+ pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
+ cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
+ printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
} while (0); LOCK_GIVE(hdw->big_lock);
}
@@ -2496,7 +2451,7 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
pvr2_trace(PVR2_TRACE_FIRMWARE,
"Cleaning up after CPU firmware fetch");
kfree(hdw->fw_buffer);
- hdw->fw_buffer = 0;
+ hdw->fw_buffer = NULL;
hdw->fw_size = 0;
/* Now release the CPU. It will disconnect and
reconnect later. */
@@ -2590,7 +2545,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
hdw->v4l_minor_number = v;
}
-
+#if 0
void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw)
{
if (!hdw->usb_dev) return;
@@ -2605,7 +2560,7 @@ void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw)
usb_sndbulkpipe(hdw->usb_dev,
PVR2_CTL_WRITE_ENDPOINT & 0x7f));
}
-
+#endif /* 0 */
static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
{
@@ -2640,10 +2595,10 @@ static void pvr2_ctl_timeout(unsigned long data)
}
-int pvr2_send_request_ex(struct pvr2_hdw *hdw,
- unsigned int timeout,int probe_fl,
- void *write_data,unsigned int write_len,
- void *read_data,unsigned int read_len)
+static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+ unsigned int timeout,int probe_fl,
+ void *write_data,unsigned int write_len,
+ void *read_data,unsigned int read_len)
{
unsigned int idx;
int status = 0;
@@ -2944,7 +2899,7 @@ int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
}
-int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
+static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
{
int ret = 0;
@@ -2968,7 +2923,7 @@ int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
}
-int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
+static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
{
int ret;
@@ -2985,7 +2940,7 @@ int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
}
-int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
+static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
{
int ret;
@@ -3001,13 +2956,13 @@ int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
}
-void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
+static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
{
if (!hdw->flag_ok) return;
pvr2_trace(PVR2_TRACE_INIT,"render_useless");
hdw->flag_ok = 0;
if (hdw->vid_stream) {
- pvr2_stream_setup(hdw->vid_stream,0,0,0);
+ pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
}
hdw->flag_streaming_enabled = 0;
hdw->subsys_enabled_mask = 0;
@@ -3026,7 +2981,7 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
{
int ret;
pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
- ret = usb_lock_device_for_reset(hdw->usb_dev,0);
+ ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
if (ret == 1) {
ret = usb_reset_device(hdw->usb_dev);
usb_unlock_device(hdw->usb_dev);
@@ -3075,7 +3030,7 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
hdw->flag_ok = !0;
hdw->cmd_buffer[0] = 0xdd;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+ status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
} while (0); LOCK_GIVE(hdw->ctl_lock);
return status;
}
@@ -3087,7 +3042,7 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
LOCK_TAKE(hdw->ctl_lock); do {
pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
hdw->cmd_buffer[0] = 0xde;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+ status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
} while (0); LOCK_GIVE(hdw->ctl_lock);
return status;
}
@@ -3114,18 +3069,18 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
}
-int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
{
int status;
LOCK_TAKE(hdw->ctl_lock); do {
hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+ status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
} while (0); LOCK_GIVE(hdw->ctl_lock);
if (!status) {
hdw->subsys_enabled_mask =
((hdw->subsys_enabled_mask &
- ~PVR2_SUBSYS_USBSTREAM_RUN) |
- (runFl ? PVR2_SUBSYS_USBSTREAM_RUN : 0));
+ ~(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) |
+ (runFl ? (1<<PVR2_SUBSYS_B_USBSTREAM_RUN) : 0));
}
return status;
}
@@ -3212,7 +3167,7 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
}
-int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
{
int result;
LOCK_TAKE(hdw->ctl_lock); do {
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 4101f4097..4e886328d 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -25,41 +25,25 @@
#include <linux/usb.h>
#include <linux/videodev2.h>
#include "pvrusb2-io.h"
+#include "pvrusb2-ctrl.h"
-#define PVR2_CTRL_TYPE_INVALID 0
-#define PVR2_CTRL_TYPE_ENUM 1
-#define PVR2_CTRL_TYPE_INT 2
-#define PVR2_CTRL_TYPE_BITMASK 3
-
-/* Private V4L2-compatible controls available in this driver */
-#define V4L2_CID_PVR_SRATE (V4L2_CID_PRIVATE_BASE)
-#define V4L2_CID_PVR_AUDIOBITRATE (V4L2_CID_PRIVATE_BASE+1)
-#define V4L2_CID_PVR_AUDIOCRC (V4L2_CID_PRIVATE_BASE+2)
-#define V4L2_CID_PVR_AUDIOEMPHASIS (V4L2_CID_PRIVATE_BASE+3)
-#define V4L2_CID_PVR_VBR (V4L2_CID_PRIVATE_BASE+4)
-#define V4L2_CID_PVR_VIDEOBITRATE (V4L2_CID_PRIVATE_BASE+5)
-#define V4L2_CID_PVR_VIDEOPEAK (V4L2_CID_PRIVATE_BASE+6)
-#define V4L2_CID_PVR_VIDEOSTANDARD (V4L2_CID_PRIVATE_BASE+7)
-
-/* Deliberate gap for CIDs we don't want apps to discover */
-#define V4L2_CID_PVR_GAP (V4L2_CID_PRIVATE_BASE+8)
-
-/* Additional explicit controls needed by V4L2 ioctl implementation */
-#define V4L2_CID_PVR_STDCUR (V4L2_CID_PVR_GAP+1)
-#define V4L2_CID_PVR_INPUT (V4L2_CID_PVR_GAP+2)
-#define V4L2_CID_PVR_AUDIOMODE (V4L2_CID_PVR_GAP+3)
-#define V4L2_CID_PVR_FREQUENCY (V4L2_CID_PVR_GAP+4)
-#define V4L2_CID_PVR_HRES (V4L2_CID_PVR_GAP+5)
-#define V4L2_CID_PVR_VRES (V4L2_CID_PVR_GAP+6)
-#define V4L2_CID_PVR_INTERLACE (V4L2_CID_PVR_GAP+7)
+
+/* Private internal control ids, look these up with
+ pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */
+#define PVR2_CID_STDENUM 1
+#define PVR2_CID_STDCUR 2
+#define PVR2_CID_STDAVAIL 3
+#define PVR2_CID_INPUT 4
+#define PVR2_CID_AUDIOMODE 5
+#define PVR2_CID_FREQUENCY 6
+#define PVR2_CID_HRES 7
+#define PVR2_CID_VRES 8
/* Legal values for the INPUT state variable */
#define PVR2_CVAL_INPUT_TV 0
#define PVR2_CVAL_INPUT_SVIDEO 1
#define PVR2_CVAL_INPUT_COMPOSITE 2
#define PVR2_CVAL_INPUT_RADIO 3
-#define PVR2_CVAL_INPUT_MIN PVR2_CVAL_INPUT_TV
-#define PVR2_CVAL_INPUT_MAX PVR2_CVAL_INPUT_RADIO
/* Values that pvr2_hdw_get_signal_status() returns */
#define PVR2_SIGNAL_OK 0x0001
@@ -71,19 +55,19 @@
independently stopped / started. Usually you don't want to mess with
this directly (let the driver handle things itself), but it is useful
for debugging. */
-#define PVR2_SUBSYS_ENC_FIRMWARE (1 << 0)
-#define PVR2_SUBSYS_ENC_CFG (1 << 1)
-#define PVR2_SUBSYS_DIGITIZER_RUN (1 << 2)
-#define PVR2_SUBSYS_USBSTREAM_RUN (1 << 3)
-#define PVR2_SUBSYS_ENC_RUN (1 << 4)
+#define PVR2_SUBSYS_B_ENC_FIRMWARE 0
+#define PVR2_SUBSYS_B_ENC_CFG 1
+#define PVR2_SUBSYS_B_DIGITIZER_RUN 2
+#define PVR2_SUBSYS_B_USBSTREAM_RUN 3
+#define PVR2_SUBSYS_B_ENC_RUN 4
#define PVR2_SUBSYS_CFG_ALL ( \
- PVR2_SUBSYS_ENC_FIRMWARE | \
- PVR2_SUBSYS_ENC_CFG )
+ (1 << PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+ (1 << PVR2_SUBSYS_B_ENC_CFG) )
#define PVR2_SUBSYS_RUN_ALL ( \
- PVR2_SUBSYS_DIGITIZER_RUN | \
- PVR2_SUBSYS_USBSTREAM_RUN | \
- PVR2_SUBSYS_ENC_RUN )
+ (1 << PVR2_SUBSYS_B_DIGITIZER_RUN) | \
+ (1 << PVR2_SUBSYS_B_USBSTREAM_RUN) | \
+ (1 << PVR2_SUBSYS_B_ENC_RUN) )
#define PVR2_SUBSYS_ALL ( \
PVR2_SUBSYS_CFG_ALL | \
PVR2_SUBSYS_RUN_ALL )
@@ -99,8 +83,6 @@ const char *pvr2_config_get_name(enum pvr2_config);
struct pvr2_hdw;
-struct pvr2_ctrl;
-
/* Create and return a structure for interacting with the underlying
hardware */
struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
@@ -110,7 +92,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
void pvr2_hdw_poll(struct pvr2_hdw *);
/* Trigger a poll to take place later at a convenient time */
-void pvr2_hdw_poll_trigger(struct pvr2_hdw *);
void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *);
/* Register a callback used to trigger a future poll */
@@ -118,9 +99,6 @@ void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *,
void (*func)(void *),
void *data);
-/* Get pointer to structure given unit number */
-struct pvr2_hdw *pvr2_hdw_find(int unit_number);
-
/* Destroy hardware interaction structure */
void pvr2_hdw_destroy(struct pvr2_hdw *);
@@ -155,59 +133,15 @@ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *);
/* Retrieve a control handle given its index (0..count-1) */
struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int);
-/* Retrieve a control handle given its well known ID */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *,unsigned int ctl_id);
-
-/* Set the current value of the given control. */
-int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
-
-/* Get the current value of the given control. */
-int pvr2_ctrl_get_value(struct pvr2_ctrl *);
-
-/* Return the type of the given control (int, enum, or bit mask). */
-int pvr2_ctrl_get_type(struct pvr2_ctrl *);
-
-/* Return the minimum legal value for a given control. This command is
- only relevant for int or enum types. */
-int pvr2_ctrl_get_min_value(struct pvr2_ctrl *);
-
-/* Return the maximum legal value for a given control. This command is
- only relevant for int or enum types. */
-int pvr2_ctrl_get_max_value(struct pvr2_ctrl *);
-
-/* Return a mask of which bits are used within the bit mask of a given
- control. This command is only relevant for bit mask types. */
-int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *);
-
-/* Return the default value for a given control. */
-int pvr2_ctrl_get_default_value(struct pvr2_ctrl *);
-
-/* Return true if this is a valid control. */
-int pvr2_ctrl_is_valid(struct pvr2_ctrl *);
+/* Retrieve a control handle given its internal ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int);
-/* Return true if the control can be set (otherwise it may only be read,
- assuming that it is valid). */
-int pvr2_ctrl_is_writeable(struct pvr2_ctrl *);
+/* Retrieve a control handle given its V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id);
-/* Return the control's name, or null if there isn't a name or the control
- isn't otherwise valid. */
-const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
-
-/* Return the control's description, or null if there isn't a name or the
- control isn't otherwise valid. */
-const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
-
-/* Return the name for an enumeration value or bit mask position for the
- given control. If the control is not an enumeration or bit mask type,
- then return null. */
-const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *,int val);
-
-/* Return the number of support standard groups */
-unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *);
-
-/* Return a pointer to a v4l2 standard descriptor for a given group */
-const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *,
- unsigned int idx);
+/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+ unsigned int ctl_id);
/* Commit all control changes made up to this point */
int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
@@ -233,18 +167,16 @@ int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config);
/* Get handle to video output stream */
struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
+/* Emit a video standard struct */
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
+ unsigned int idx);
+
/* Enable / disable various pieces of hardware. Items to change are
identified by bit positions within msk, and new state for each item is
identified by corresponding bit positions within val. */
void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
unsigned long msk,unsigned long val);
-/* Shortcut for pvr2_hdw_subsys_bit_chg(hdw,msk,msk) */
-void pvr2_hdw_subsys_bit_set(struct pvr2_hdw *hdw,unsigned long msk);
-
-/* Shortcut for pvr2_hdw_subsys_bit_chg(hdw,msk,0) */
-void pvr2_hdw_subsys_bit_clr(struct pvr2_hdw *hdw,unsigned long msk);
-
/* Retrieve mask indicating which pieces of hardware are currently enabled
/ configured. */
unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *);
@@ -284,34 +216,18 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
/* The following entry points are all lower level things you normally don't
want to worry about. */
-/* Attempt to recover from a USB foul-up (in practice I find that if you
- have to do this, then it's already too late). */
-void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw);
-
/* Issue a command and get a response from the device. LOTS of higher
level stuff is built on this. */
int pvr2_send_request(struct pvr2_hdw *,
void *write_ptr,unsigned int write_len,
void *read_ptr,unsigned int read_len);
-/* Issue a command and get a response from the device. This extended
- version includes a probe flag (which if set means that device errors
- should not be logged or treated as fatal) and a timeout in jiffies.
- This can be used to non-lethally probe the health of endpoint 1. */
-int pvr2_send_request_ex(struct pvr2_hdw *,unsigned int timeout,int probe_fl,
- void *write_ptr,unsigned int write_len,
- void *read_ptr,unsigned int read_len);
-
/* Slightly higher level device communication functions. */
int pvr2_write_register(struct pvr2_hdw *, u16, u32);
-int pvr2_read_register(struct pvr2_hdw *, u16, u32 *);
-int pvr2_write_u16(struct pvr2_hdw *, u16, int);
-int pvr2_write_u8(struct pvr2_hdw *, u8, int);
/* Call if for any reason we can't talk to the hardware anymore - this will
cause the driver to stop flailing on the device. */
void pvr2_hdw_render_useless(struct pvr2_hdw *);
-void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *);
/* Set / clear 8051's reset bit */
void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int);
@@ -330,12 +246,6 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
/* Order decoder to reset */
int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
-/* Stop / start video stream transport */
-int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
-
-/* Find I2C address of eeprom */
-int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *);
-
/* Direct manipulation of GPIO bits */
int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *);
int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index 89d0da053..db80b1aa3 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -26,7 +26,6 @@
#include "pvrusb2-i2c-cmd-v4l2.h"
#include "pvrusb2-audio.h"
#include "pvrusb2-tuner.h"
-#include "pvrusb2-demod.h"
#include "pvrusb2-video-v4l.h"
#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
#include "pvrusb2-cx2584x-v4l.h"
@@ -90,11 +89,6 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
return;
}
}
- if (id == I2C_DRIVERID_TDA9887) {
- if (pvr2_i2c_demod_setup(hdw,cp)) {
- return;
- }
- }
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index fb83cd2c9..8a9933dec 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -24,13 +24,12 @@
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
#include <linux/videodev2.h>
-#include <linux/videodev2.h>
static void set_standard(struct pvr2_hdw *hdw)
{
v4l2_std_id vs;
- vs = hdw->controls[PVR2_CID_STDCUR].value;
+ vs = hdw->std_mask_cur;
pvr2_trace(PVR2_TRACE_CHIPS,
"i2c v4l2 set_standard(0x%llx)",(__u64)vs);
@@ -40,7 +39,7 @@ static void set_standard(struct pvr2_hdw *hdw)
static int check_standard(struct pvr2_hdw *hdw)
{
- return hdw->controls[PVR2_CID_STDCUR].dirty != 0;
+ return hdw->std_dirty != 0;
}
@@ -56,32 +55,30 @@ static void set_bcsh(struct pvr2_hdw *hdw)
struct v4l2_control ctrl;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
" b=%d c=%d s=%d h=%d",
- hdw->controls[PVR2_CID_BRIGHTNESS].value,
- hdw->controls[PVR2_CID_CONTRAST].value,
- hdw->controls[PVR2_CID_SATURATION].value,
- hdw->controls[PVR2_CID_HUE].value);
+ hdw->brightness_val,hdw->contrast_val,
+ hdw->saturation_val,hdw->hue_val);
memset(&ctrl,0,sizeof(ctrl));
ctrl.id = V4L2_CID_BRIGHTNESS;
- ctrl.value = hdw->controls[PVR2_CID_BRIGHTNESS].value;
+ ctrl.value = hdw->brightness_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_CONTRAST;
- ctrl.value = hdw->controls[PVR2_CID_CONTRAST].value;
+ ctrl.value = hdw->contrast_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_SATURATION;
- ctrl.value = hdw->controls[PVR2_CID_SATURATION].value;
+ ctrl.value = hdw->saturation_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_HUE;
- ctrl.value = hdw->controls[PVR2_CID_HUE].value;
+ ctrl.value = hdw->hue_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
}
static int check_bcsh(struct pvr2_hdw *hdw)
{
- return (hdw->controls[PVR2_CID_BRIGHTNESS].dirty ||
- hdw->controls[PVR2_CID_CONTRAST].dirty ||
- hdw->controls[PVR2_CID_SATURATION].dirty ||
- hdw->controls[PVR2_CID_HUE].dirty);
+ return (hdw->brightness_dirty ||
+ hdw->contrast_dirty ||
+ hdw->saturation_dirty ||
+ hdw->hue_dirty);
}
@@ -98,37 +95,37 @@ static void set_volume(struct pvr2_hdw *hdw)
pvr2_trace(PVR2_TRACE_CHIPS,
"i2c v4l2 set_volume"
"(vol=%d bal=%d bas=%d treb=%d mute=%d)",
- hdw->controls[PVR2_CID_VOLUME].value,
- hdw->controls[PVR2_CID_BALANCE].value,
- hdw->controls[PVR2_CID_BASS].value,
- hdw->controls[PVR2_CID_TREBLE].value,
- hdw->controls[PVR2_CID_MUTE].value);
+ hdw->volume_val,
+ hdw->balance_val,
+ hdw->bass_val,
+ hdw->treble_val,
+ hdw->mute_val);
memset(&ctrl,0,sizeof(ctrl));
ctrl.id = V4L2_CID_AUDIO_MUTE;
- ctrl.value = hdw->controls[PVR2_CID_MUTE].value ? 1 : 0;
+ ctrl.value = hdw->mute_val ? 1 : 0;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_VOLUME;
- ctrl.value = hdw->controls[PVR2_CID_VOLUME].value;
+ ctrl.value = hdw->volume_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_BALANCE;
- ctrl.value = hdw->controls[PVR2_CID_BALANCE].value;
+ ctrl.value = hdw->balance_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_BASS;
- ctrl.value = hdw->controls[PVR2_CID_BASS].value;
+ ctrl.value = hdw->bass_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_TREBLE;
- ctrl.value = hdw->controls[PVR2_CID_TREBLE].value;
+ ctrl.value = hdw->treble_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
}
static int check_volume(struct pvr2_hdw *hdw)
{
- return (hdw->controls[PVR2_CID_VOLUME].dirty ||
- hdw->controls[PVR2_CID_BALANCE].dirty ||
- hdw->controls[PVR2_CID_BASS].dirty ||
- hdw->controls[PVR2_CID_TREBLE].dirty ||
- hdw->controls[PVR2_CID_MUTE].dirty);
+ return (hdw->volume_dirty ||
+ hdw->balance_dirty ||
+ hdw->bass_dirty ||
+ hdw->treble_dirty ||
+ hdw->mute_dirty);
}
@@ -143,7 +140,7 @@ static void set_frequency(struct pvr2_hdw *hdw)
{
unsigned long fv;
struct v4l2_frequency freq;
- fv = hdw->controls[PVR2_CID_FREQUENCY].value;
+ fv = hdw->freqVal;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
memset(&freq,0,sizeof(freq));
freq.frequency = fv / 62500;
@@ -155,7 +152,7 @@ static void set_frequency(struct pvr2_hdw *hdw)
static int check_frequency(struct pvr2_hdw *hdw)
{
- return hdw->controls[PVR2_CID_FREQUENCY].dirty != 0;
+ return hdw->freqDirty != 0;
}
@@ -173,8 +170,8 @@ static void set_size(struct pvr2_hdw *hdw)
memset(&fmt,0,sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = hdw->controls[PVR2_CID_HRES].value;
- fmt.fmt.pix.height = hdw->controls[PVR2_CID_VRES].value;
+ fmt.fmt.pix.width = hdw->res_hor_val;
+ fmt.fmt.pix.height = hdw->res_ver_val;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
fmt.fmt.pix.width,fmt.fmt.pix.height);
@@ -185,8 +182,7 @@ static void set_size(struct pvr2_hdw *hdw)
static int check_size(struct pvr2_hdw *hdw)
{
- return (hdw->controls[PVR2_CID_HRES].dirty ||
- hdw->controls[PVR2_CID_VRES].dirty);
+ return (hdw->res_hor_dirty || hdw->res_ver_dirty);
}
@@ -200,7 +196,7 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
static void do_log(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
- pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,0);
+ pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL);
}
@@ -221,7 +217,7 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
{
pvr2_i2c_client_cmd(cp,
- (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),0);
+ (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 9a96273f2..95c2f071a 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -38,6 +38,10 @@ static unsigned int i2c_scan = 0;
module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
+ unsigned int detail,
+ char *buf,unsigned int maxlen);
+
static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
u8 i2c_addr, /* I2C address we're talking to */
u8 *data, /* Data to write */
@@ -112,8 +116,22 @@ static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
#endif
if (!data) dlen = 0;
- if (dlen > (sizeof(hdw->cmd_buffer) - 4)) return -ENOTSUPP;
- if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) return -ENOTSUPP;
+ if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Killing an I2C read to %u that has wlen too large"
+ " (desired=%u limit=%u)",
+ i2c_addr,
+ dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
+ return -ENOTSUPP;
+ }
+ if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Killing an I2C read to %u that has rlen too large"
+ " (desired=%u limit=%u)",
+ i2c_addr,
+ rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
+ return -ENOTSUPP;
+ }
LOCK_TAKE(hdw->ctl_lock);
@@ -164,6 +182,130 @@ static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
return ret;
}
+/* This is the common low level entry point for doing I2C operations to the
+ hardware. */
+static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
+ u8 i2c_addr,
+ u8 *wdata,
+ u16 wlen,
+ u8 *rdata,
+ u16 rlen)
+{
+ if (!rdata) rlen = 0;
+ if (!wdata) wlen = 0;
+ if (rlen || !wlen) {
+ return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+ } else {
+ return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
+ }
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+
+/* This is a special entry point that is entered if an I2C operation is
+ attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this
+ part doesn't work, but we know it is really there. So let's look for
+ the autodetect attempt and just return success if we see that. */
+static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
+ u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+ if (!(rlen || wlen)) {
+ // This is a probe attempt. Just let it succeed.
+ return 0;
+ }
+ return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+}
+
+/* This is a special entry point that is entered if an I2C operation is
+ attempted to a cx25840 chip on model 24xxx hardware. This chip can
+ sometimes wedge itself. Worse still, when this happens msp3400 can
+ falsely detect this part and then the system gets hosed up after msp3400
+ gets confused and dies. What we want to do here is try to keep msp3400
+ away and also try to notice if the chip is wedged and send a warning to
+ the system log. */
+static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
+ u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+ int ret;
+ unsigned int subaddr;
+ u8 wbuf[2];
+ int state = hdw->i2c_cx25840_hack_state;
+
+ if (!(rlen || wlen)) {
+ // Probe attempt - always just succeed and don't bother the
+ // hardware (this helps to make the state machine further
+ // down somewhat easier).
+ return 0;
+ }
+
+ if (state == 3) {
+ return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+ }
+
+ /* We're looking for the exact pattern where the revision register
+ is being read. The cx25840 module will always look at the
+ revision register first. Any other pattern of access therefore
+ has to be a probe attempt from somebody else so we'll reject it.
+ Normally we could just let each client just probe the part
+ anyway, but when the cx25840 is wedged, msp3400 will get a false
+ positive and that just screws things up... */
+
+ if (wlen == 0) {
+ switch (state) {
+ case 1: subaddr = 0x0100; break;
+ case 2: subaddr = 0x0101; break;
+ default: goto fail;
+ }
+ } else if (wlen == 2) {
+ subaddr = (wdata[0] << 8) | wdata[1];
+ switch (subaddr) {
+ case 0x0100: state = 1; break;
+ case 0x0101: state = 2; break;
+ default: goto fail;
+ }
+ } else {
+ goto fail;
+ }
+ if (!rlen) goto success;
+ state = 0;
+ if (rlen != 1) goto fail;
+
+ /* If we get to here then we have a legitimate read for one of the
+ two revision bytes, so pass it through. */
+ wbuf[0] = subaddr >> 8;
+ wbuf[1] = subaddr;
+ ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
+
+ if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "WARNING: Detected a wedged cx25840 chip;"
+ " the device will not work.");
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "WARNING: Try power cycling the pvrusb2 device.");
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "WARNING: Disabling further access to the device"
+ " to prevent other foul-ups.");
+ // This blocks all further communication with the part.
+ hdw->i2c_func[0x44] = NULL;
+ pvr2_hdw_render_useless(hdw);
+ goto fail;
+ }
+
+ /* Success! */
+ pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
+ state = 3;
+
+ success:
+ hdw->i2c_cx25840_hack_state = state;
+ return 0;
+
+ fail:
+ hdw->i2c_cx25840_hack_state = state;
+ return -EIO;
+}
+
+#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */
+
/* This is a very, very limited I2C adapter implementation. We can only
support what we actually know will work on the device... */
static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -171,12 +313,24 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
int num)
{
int ret = -ENOTSUPP;
+ pvr2_i2c_func funcp = NULL;
struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
+ if (!num) {
+ ret = -EINVAL;
+ goto done;
+ }
if ((msgs[0].flags & I2C_M_NOSTART)) {
trace_i2c("i2c refusing I2C_M_NOSTART");
goto done;
}
+ if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
+ funcp = hdw->i2c_func[msgs[0].addr];
+ }
+ if (!funcp) {
+ ret = -EIO;
+ goto done;
+ }
if (num == 1) {
if (msgs[0].flags & I2C_M_RD) {
@@ -184,8 +338,7 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
u16 tcnt,bcnt,offs;
if (!msgs[0].len) {
/* Length == 0 read. This is a probe. */
- if (pvr2_i2c_read(hdw,msgs[0].addr,
- 0,0,0,0)) {
+ if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) {
ret = -EIO;
goto done;
}
@@ -202,9 +355,8 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
if (bcnt > sizeof(hdw->cmd_buffer)-1) {
bcnt = sizeof(hdw->cmd_buffer)-1;
}
- if (pvr2_i2c_read(hdw,msgs[0].addr,
- 0,0,
- msgs[0].buf+offs,bcnt)) {
+ if (funcp(hdw,msgs[0].addr,NULL,0,
+ msgs[0].buf+offs,bcnt)) {
ret = -EIO;
goto done;
}
@@ -216,13 +368,19 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
} else {
/* Simple write */
ret = 1;
- if (pvr2_i2c_write(hdw,msgs[0].addr,
- msgs[0].buf,msgs[0].len)) {
+ if (funcp(hdw,msgs[0].addr,
+ msgs[0].buf,msgs[0].len,NULL,0)) {
ret = -EIO;
}
goto done;
}
} else if (num == 2) {
+ if (msgs[0].addr != msgs[1].addr) {
+ trace_i2c("i2c refusing 2 phase transfer with"
+ " conflicting target addresses");
+ ret = -ENOTSUPP;
+ goto done;
+ }
if ((!((msgs[0].flags & I2C_M_RD))) &&
(msgs[1].flags & I2C_M_RD)) {
u16 tcnt,bcnt,wcnt,offs;
@@ -238,9 +396,9 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
if (bcnt > sizeof(hdw->cmd_buffer)-1) {
bcnt = sizeof(hdw->cmd_buffer)-1;
}
- if (pvr2_i2c_read(hdw,msgs[0].addr,
- msgs[0].buf,wcnt,
- msgs[1].buf+offs,bcnt)) {
+ if (funcp(hdw,msgs[0].addr,
+ msgs[0].buf,wcnt,
+ msgs[1].buf+offs,bcnt)) {
ret = -EIO;
goto done;
}
@@ -574,9 +732,9 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
}
-unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
- unsigned int detail,
- char *buf,unsigned int maxlen)
+static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
+ unsigned int detail,
+ char *buf,unsigned int maxlen)
{
unsigned int ccnt,bcnt;
int spcfl = 0;
@@ -743,7 +901,7 @@ static void do_i2c_scan(struct pvr2_hdw *hdw)
msg[0].addr = 0;
msg[0].flags = I2C_M_RD;
msg[0].len = 0;
- msg[0].buf = 0;
+ msg[0].buf = NULL;
printk("%s: i2c scan beginning\n",hdw->name);
for (i = 0; i < 128; i++) {
msg[0].addr = i;
@@ -757,6 +915,24 @@ static void do_i2c_scan(struct pvr2_hdw *hdw)
void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
{
+ unsigned int idx;
+
+ // The default action for all possible I2C addresses is just to do
+ // the transfer normally.
+ for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
+ hdw->i2c_func[idx] = pvr2_i2c_basic_op;
+ }
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+ // If however we're dealing with new hardware, insert some hacks in
+ // the I2C transfer stack to let things work better.
+ if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+ hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+ hdw->i2c_func[0x44] = i2c_hack_cx25840;
+ }
+#endif
+
+ // Configure the adapter and set up everything else related to it.
memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index e8af5b0ed..6d7e25247 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -75,9 +75,6 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
PVR2_I2C_DETAIL_DEBUG |\
PVR2_I2C_DETAIL_HANDLER |\
PVR2_I2C_DETAIL_CTLMASK)
-unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *,
- unsigned int detail_mask,
- char *buf,unsigned int maxlen);
void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-io.c b/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
index a6bc3befe..1c1cf9024 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -26,8 +26,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-#include <asm/atomic.h>
-#include <asm/mutex.h>
+#include <linux/mutex.h>
#else
#include <asm/semaphore.h>
#endif
@@ -114,7 +113,7 @@ struct pvr2_buffer {
struct urb *purb;
};
-const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
{
switch (st) {
case pvr2_buffer_state_none: return "none";
@@ -125,7 +124,8 @@ const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
return "unknown";
}
-void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
+#ifdef SANITY_CHECK_BUFFERS
+static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
{
pvr2_trace(PVR2_TRACE_INFO,
"buffer%s%s %p state=%s id=%d status=%d"
@@ -136,10 +136,11 @@ void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
(bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
(bp ? bp->id : 0),
(bp ? bp->status : 0),
- (bp ? bp->stream : 0),
- (bp ? bp->purb : 0),
+ (bp ? bp->stream : NULL),
+ (bp ? bp->purb : NULL),
(bp ? bp->signature : 0));
}
+#endif /* SANITY_CHECK_BUFFERS */
static void pvr2_buffer_remove(struct pvr2_buffer *bp)
{
@@ -305,7 +306,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp)
pvr2_buffer_wipe(bp);
pvr2_buffer_set_none(bp);
bp->signature = 0;
- bp->stream = 0;
+ bp->stream = NULL;
if (bp->purb) usb_free_urb(bp->purb);
pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
" bufferDone %p",bp);
@@ -360,13 +361,13 @@ static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
struct pvr2_buffer *bp;
bp = sp->buffers[sp->buffer_total_count - 1];
/* Paranoia */
- sp->buffers[sp->buffer_total_count - 1] = 0;
+ sp->buffers[sp->buffer_total_count - 1] = NULL;
(sp->buffer_total_count)--;
pvr2_buffer_done(bp);
kfree(bp);
}
if (scnt < sp->buffer_slot_count) {
- struct pvr2_buffer **nb = 0;
+ struct pvr2_buffer **nb = NULL;
if (scnt) {
nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
if (!nb) return -ENOMEM;
@@ -534,10 +535,12 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
}
/* Query / set the nominal buffer count */
+#if 0
int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
{
return sp->buffer_target_count;
}
+#endif /* 0 */
int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
{
@@ -553,21 +556,21 @@ int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
{
struct list_head *lp = sp->idle_list.next;
- if (lp == &sp->idle_list) return 0;
+ if (lp == &sp->idle_list) return NULL;
return list_entry(lp,struct pvr2_buffer,list_overhead);
}
struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
{
struct list_head *lp = sp->ready_list.next;
- if (lp == &sp->ready_list) return 0;
+ if (lp == &sp->ready_list) return NULL;
return list_entry(lp,struct pvr2_buffer,list_overhead);
}
struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
{
- if (id < 0) return 0;
- if (id >= sp->buffer_total_count) return 0;
+ if (id < 0) return NULL;
+ if (id >= sp->buffer_total_count) return NULL;
return sp->buffers[id];
}
@@ -576,6 +579,8 @@ int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
return sp->r_count;
}
+#if 0
+
int pvr2_stream_get_idle_count(struct pvr2_stream *sp)
{
return sp->i_count;
@@ -588,6 +593,8 @@ void pvr2_stream_flush(struct pvr2_stream *sp)
} while(0); mutex_unlock(&sp->mutex);
}
+#endif /* 0 */
+
void pvr2_stream_kill(struct pvr2_stream *sp)
{
struct pvr2_buffer *bp;
@@ -641,6 +648,7 @@ int pvr2_buffer_queue(struct pvr2_buffer *bp)
return ret;
}
+#if 0
int pvr2_buffer_idle(struct pvr2_buffer *bp)
{
struct pvr2_stream *sp;
@@ -655,6 +663,7 @@ int pvr2_buffer_idle(struct pvr2_buffer *bp)
} while(0); mutex_unlock(&sp->mutex);
return 0;
}
+#endif /* 0 */
int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
{
@@ -694,10 +703,12 @@ int pvr2_buffer_get_status(struct pvr2_buffer *bp)
return bp->status;
}
+#if 0
enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *bp)
{
return bp->state;
}
+#endif /* 0 */
int pvr2_buffer_get_id(struct pvr2_buffer *bp)
{
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-io.h b/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
index 65e11385b..96285ad23 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -36,8 +36,6 @@ enum pvr2_buffer_state {
struct pvr2_stream;
struct pvr2_buffer;
-const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
-
/* Initialize / tear down stream structure */
struct pvr2_stream *pvr2_stream_create(void);
void pvr2_stream_destroy(struct pvr2_stream *);
@@ -49,7 +47,6 @@ void pvr2_stream_set_callback(struct pvr2_stream *,
void *data);
/* Query / set the nominal buffer count */
-int pvr2_stream_get_buffer_count(struct pvr2_stream *);
int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
/* Get a pointer to a buffer that is either idle, ready, or is specified
@@ -59,12 +56,8 @@ struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
/* Find out how many buffers are idle or ready */
-int pvr2_stream_get_idle_count(struct pvr2_stream *);
int pvr2_stream_get_ready_count(struct pvr2_stream *);
-/* Kill all pending operations */
-void pvr2_stream_flush(struct pvr2_stream *);
-
/* Kill all pending buffers and throw away any ready buffers as well */
void pvr2_stream_kill(struct pvr2_stream *);
@@ -77,18 +70,12 @@ unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
/* Retrieve completion code for given ready buffer */
int pvr2_buffer_get_status(struct pvr2_buffer *);
-/* Retrieve state of given buffer */
-enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *);
-
/* Retrieve ID of given buffer */
int pvr2_buffer_get_id(struct pvr2_buffer *);
/* Start reading into given buffer (kill it if needed) */
int pvr2_buffer_queue(struct pvr2_buffer *);
-/* Move buffer back to idle pool (kill it if needed) */
-int pvr2_buffer_idle(struct pvr2_buffer *);
-
#endif /* __PVRUSB2_IO_H */
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index f81a0c225..06d3d9a38 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -26,8 +26,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-#include <asm/atomic.h>
-#include <asm/mutex.h>
+#include <linux/mutex.h>
#else
#include <asm/semaphore.h>
#endif
@@ -64,7 +63,7 @@ static int pvr2_ioread_init(struct pvr2_ioread *cp)
{
unsigned int idx;
- cp->stream = 0;
+ cp->stream = NULL;
mutex_init(&cp->mutex);
for (idx = 0; idx < BUFFER_COUNT; idx++) {
@@ -87,7 +86,7 @@ static void pvr2_ioread_done(struct pvr2_ioread *cp)
{
unsigned int idx;
- pvr2_ioread_setup(cp,0);
+ pvr2_ioread_setup(cp,NULL);
for (idx = 0; idx < BUFFER_COUNT; idx++) {
if (!(cp->buffer_storage[idx])) continue;
kfree(cp->buffer_storage[idx]);
@@ -98,12 +97,12 @@ struct pvr2_ioread *pvr2_ioread_create(void)
{
struct pvr2_ioread *cp;
cp = kmalloc(sizeof(*cp),GFP_KERNEL);
- if (!cp) return 0;
+ if (!cp) return NULL;
pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
memset(cp,0,sizeof(*cp));
if (pvr2_ioread_init(cp) < 0) {
kfree(cp);
- return 0;
+ return NULL;
}
return cp;
}
@@ -115,7 +114,7 @@ void pvr2_ioread_destroy(struct pvr2_ioread *cp)
pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
if (cp->sync_key_ptr) {
kfree(cp->sync_key_ptr);
- cp->sync_key_ptr = 0;
+ cp->sync_key_ptr = NULL;
}
kfree(cp);
}
@@ -134,7 +133,7 @@ void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
if (sync_key_len != cp->sync_key_len) {
if (cp->sync_key_ptr) {
kfree(cp->sync_key_ptr);
- cp->sync_key_ptr = 0;
+ cp->sync_key_ptr = NULL;
}
cp->sync_key_len = 0;
if (sync_key_len) {
@@ -154,8 +153,8 @@ static void pvr2_ioread_stop(struct pvr2_ioread *cp)
pvr2_trace(PVR2_TRACE_START_STOP,
"/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
pvr2_stream_kill(cp->stream);
- cp->c_buf = 0;
- cp->c_data_ptr = 0;
+ cp->c_buf = NULL;
+ cp->c_data_ptr = NULL;
cp->c_data_len = 0;
cp->c_data_offs = 0;
cp->enabled = 0;
@@ -189,8 +188,8 @@ static int pvr2_ioread_start(struct pvr2_ioread *cp)
}
}
cp->enabled = !0;
- cp->c_buf = 0;
- cp->c_data_ptr = 0;
+ cp->c_buf = NULL;
+ cp->c_data_ptr = NULL;
cp->c_data_len = 0;
cp->c_data_offs = 0;
cp->stream_running = 0;
@@ -224,7 +223,7 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
pvr2_ioread_stop(cp);
pvr2_stream_kill(cp->stream);
pvr2_stream_set_buffer_count(cp->stream,0);
- cp->stream = 0;
+ cp->stream = NULL;
}
if (sp) {
pvr2_trace(PVR2_TRACE_START_STOP,
@@ -261,12 +260,14 @@ int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
return ret;
}
+#if 0
int pvr2_ioread_get_enabled(struct pvr2_ioread *cp)
{
return cp->enabled != 0;
}
+#endif /* 0 */
-int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
+static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
{
int stat;
@@ -284,8 +285,8 @@ int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
pvr2_ioread_stop(cp);
return 0;
}
- cp->c_buf = 0;
- cp->c_data_ptr = 0;
+ cp->c_buf = NULL;
+ cp->c_data_ptr = NULL;
cp->c_data_len = 0;
cp->c_data_offs = 0;
}
@@ -317,7 +318,7 @@ int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
return !0;
}
-void pvr2_ioread_filter(struct pvr2_ioread *cp)
+static void pvr2_ioread_filter(struct pvr2_ioread *cp)
{
unsigned int idx;
if (!cp->enabled) return;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
index 6b002597f..1d362f833 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
@@ -33,7 +33,6 @@ void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
const char *sync_key_ptr,
unsigned int sync_key_len);
int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
-int pvr2_ioread_get_enabled(struct pvr2_ioread *);
int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt);
int pvr2_ioread_avail(struct pvr2_ioread *);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
index 988f32ad4..494eb85cb 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -47,14 +47,6 @@
PVR2_TRACE_INFO| \
PVR2_TRACE_TOLERANCE| \
PVR2_TRACE_TRAP| \
- PVR2_TRACE_FIRMWARE| \
- PVR2_TRACE_EEPROM | \
- PVR2_TRACE_INIT | \
- PVR2_TRACE_I2C | \
- PVR2_TRACE_CHIPS | \
- PVR2_TRACE_START_STOP | \
- PVR2_TRACE_CTL | \
- PVR2_TRACE_DEBUGIFC | \
0)
int pvrusb2_debug = DEFAULT_DEBUG_MASK;
@@ -63,7 +55,7 @@ module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "Debug trace mask");
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-static struct pvr2_sysfs_class *class_ptr = 0;
+static struct pvr2_sysfs_class *class_ptr = NULL;
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
static void pvr_setup_attach(struct pvr2_context *pvr)
@@ -114,12 +106,12 @@ static void pvr_disconnect(struct usb_interface *intf)
static struct usb_driver pvr_driver = {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
- owner: THIS_MODULE,
+ .owner = THIS_MODULE,
#endif
- name: "pvrusb2",
- id_table: pvr2_device_table,
- probe: pvr_probe,
- disconnect: pvr_disconnect
+ .name = "pvrusb2",
+ .id_table = pvr2_device_table,
+ .probe = pvr_probe,
+ .disconnect = pvr_disconnect
};
/*
@@ -134,16 +126,6 @@ static int __init pvr_init(void)
pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
- /* Auto-load various support modules (with which we may
- indirectly interact) */
- request_module("msp3400");
- request_module("cx25840");
- request_module("saa7115");
- request_module("tuner");
- request_module("tveeprom");
- request_module("tda9887");
- request_module("wm8775");
-
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
class_ptr = pvr2_sysfs_class_create();
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-std.c b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c
new file mode 100644
index 000000000..f95c598ff
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -0,0 +1,408 @@
+/*
+ *
+ * $Id$
+ *
+ * Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "pvrusb2-std.h"
+#include "pvrusb2-debug.h"
+#include <asm/string.h>
+#include <linux/slab.h>
+
+struct std_name {
+ const char *name;
+ v4l2_std_id id;
+};
+
+
+#define CSTD_PAL \
+ (V4L2_STD_PAL_B| \
+ V4L2_STD_PAL_B1| \
+ V4L2_STD_PAL_G| \
+ V4L2_STD_PAL_H| \
+ V4L2_STD_PAL_I| \
+ V4L2_STD_PAL_D| \
+ V4L2_STD_PAL_D1| \
+ V4L2_STD_PAL_K| \
+ V4L2_STD_PAL_M| \
+ V4L2_STD_PAL_N| \
+ V4L2_STD_PAL_Nc| \
+ V4L2_STD_PAL_60)
+
+#define CSTD_NTSC \
+ (V4L2_STD_NTSC_M| \
+ V4L2_STD_NTSC_M_JP| \
+ V4L2_STD_NTSC_M_KR| \
+ V4L2_STD_NTSC_443)
+
+#define CSTD_SECAM \
+ (V4L2_STD_SECAM_B| \
+ V4L2_STD_SECAM_D| \
+ V4L2_STD_SECAM_G| \
+ V4L2_STD_SECAM_H| \
+ V4L2_STD_SECAM_K| \
+ V4L2_STD_SECAM_K1| \
+ V4L2_STD_SECAM_L| \
+ V4L2_STD_SECAM_LC)
+
+#define TSTD_B (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
+#define TSTD_B1 (V4L2_STD_PAL_B1)
+#define TSTD_D (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
+#define TSTD_D1 (V4L2_STD_PAL_D1)
+#define TSTD_G (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
+#define TSTD_H (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
+#define TSTD_I (V4L2_STD_PAL_I)
+#define TSTD_K (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
+#define TSTD_K1 (V4L2_STD_SECAM_K1)
+#define TSTD_L (V4L2_STD_SECAM_L)
+#define TSTD_M (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
+#define TSTD_N (V4L2_STD_PAL_N)
+#define TSTD_Nc (V4L2_STD_PAL_Nc)
+#define TSTD_60 (V4L2_STD_PAL_60)
+
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
+
+/* Mapping of standard bits to color system */
+const static struct std_name std_groups[] = {
+ {"PAL",CSTD_PAL},
+ {"NTSC",CSTD_NTSC},
+ {"SECAM",CSTD_SECAM},
+};
+
+/* Mapping of standard bits to modulation system */
+const static struct std_name std_items[] = {
+ {"B",TSTD_B},
+ {"B1",TSTD_B1},
+ {"D",TSTD_D},
+ {"D1",TSTD_D1},
+ {"G",TSTD_G},
+ {"H",TSTD_H},
+ {"I",TSTD_I},
+ {"K",TSTD_K},
+ {"K1",TSTD_K1},
+ {"L",TSTD_L},
+ {"LC",V4L2_STD_SECAM_LC},
+ {"M",TSTD_M},
+ {"Mj",V4L2_STD_NTSC_M_JP},
+ {"443",V4L2_STD_NTSC_443},
+ {"Mk",V4L2_STD_NTSC_M_KR},
+ {"N",TSTD_N},
+ {"Nc",TSTD_Nc},
+ {"60",TSTD_60},
+};
+
+
+// Search an array of std_name structures and return a pointer to the
+// element with the matching name.
+static const struct std_name *find_std_name(const struct std_name *arrPtr,
+ unsigned int arrSize,
+ const char *bufPtr,
+ unsigned int bufSize)
+{
+ unsigned int idx;
+ const struct std_name *p;
+ for (idx = 0; idx < arrSize; idx++) {
+ p = arrPtr + idx;
+ if (strlen(p->name) != bufSize) continue;
+ if (!memcmp(bufPtr,p->name,bufSize)) return p;
+ }
+ return NULL;
+}
+
+
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+ unsigned int bufSize)
+{
+ v4l2_std_id id = 0;
+ v4l2_std_id cmsk = 0;
+ v4l2_std_id t;
+ int mMode = 0;
+ unsigned int cnt;
+ char ch;
+ const struct std_name *sp;
+
+ while (bufSize) {
+ if (!mMode) {
+ cnt = 0;
+ while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
+ if (cnt >= bufSize) return 0; // No more characters
+ sp = find_std_name(
+ std_groups,
+ sizeof(std_groups)/sizeof(std_groups[0]),
+ bufPtr,cnt);
+ if (!sp) return 0; // Illegal color system name
+ cnt++;
+ bufPtr += cnt;
+ bufSize -= cnt;
+ mMode = !0;
+ cmsk = sp->id;
+ continue;
+ }
+ cnt = 0;
+ while (cnt < bufSize) {
+ ch = bufPtr[cnt];
+ if (ch == ';') {
+ mMode = 0;
+ break;
+ }
+ if (ch == '/') break;
+ cnt++;
+ }
+ sp = find_std_name(std_items,
+ sizeof(std_items)/sizeof(std_items[0]),
+ bufPtr,cnt);
+ if (!sp) return 0; // Illegal modulation system ID
+ t = sp->id & cmsk;
+ if (!t) return 0; // Specific color + modulation system illegal
+ id |= t;
+ if (cnt < bufSize) cnt++;
+ bufPtr += cnt;
+ bufSize -= cnt;
+ }
+
+ if (idPtr) *idPtr = id;
+ return !0;
+}
+
+
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+ v4l2_std_id id)
+{
+ unsigned int idx1,idx2;
+ const struct std_name *ip,*gp;
+ int gfl,cfl;
+ unsigned int c1,c2;
+ cfl = 0;
+ c1 = 0;
+ for (idx1 = 0;
+ idx1 < sizeof(std_groups)/sizeof(std_groups[0]);
+ idx1++) {
+ gp = std_groups + idx1;
+ gfl = 0;
+ for (idx2 = 0;
+ idx2 < sizeof(std_items)/sizeof(std_items[0]);
+ idx2++) {
+ ip = std_items + idx2;
+ if (!(gp->id & ip->id & id)) continue;
+ if (!gfl) {
+ if (cfl) {
+ c2 = scnprintf(bufPtr,bufSize,";");
+ c1 += c2;
+ bufSize -= c2;
+ bufPtr += c2;
+ }
+ cfl = !0;
+ c2 = scnprintf(bufPtr,bufSize,
+ "%s-",gp->name);
+ gfl = !0;
+ } else {
+ c2 = scnprintf(bufPtr,bufSize,"/");
+ }
+ c1 += c2;
+ bufSize -= c2;
+ bufPtr += c2;
+ c2 = scnprintf(bufPtr,bufSize,
+ ip->name);
+ c1 += c2;
+ bufSize -= c2;
+ bufPtr += c2;
+ }
+ }
+ return c1;
+}
+
+
+// Template data for possible enumerated video standards. Here we group
+// standards which share common frame rates and resolution.
+static struct v4l2_standard generic_standards[] = {
+ {
+ .id = (TSTD_B|TSTD_B1|
+ TSTD_D|TSTD_D1|
+ TSTD_G|
+ TSTD_H|
+ TSTD_I|
+ TSTD_K|TSTD_K1|
+ TSTD_L|
+ V4L2_STD_SECAM_LC |
+ TSTD_N|TSTD_Nc),
+ .frameperiod =
+ {
+ .numerator = 1,
+ .denominator= 25
+ },
+ .framelines = 625,
+ .reserved = {0,0,0,0}
+ }, {
+ .id = (TSTD_M|
+ V4L2_STD_NTSC_M_JP|
+ V4L2_STD_NTSC_M_KR),
+ .frameperiod =
+ {
+ .numerator = 1001,
+ .denominator= 30000
+ },
+ .framelines = 525,
+ .reserved = {0,0,0,0}
+ }, { // This is a total wild guess
+ .id = (TSTD_60),
+ .frameperiod =
+ {
+ .numerator = 1001,
+ .denominator= 30000
+ },
+ .framelines = 525,
+ .reserved = {0,0,0,0}
+ }, { // This is total wild guess
+ .id = V4L2_STD_NTSC_443,
+ .frameperiod =
+ {
+ .numerator = 1001,
+ .denominator= 30000
+ },
+ .framelines = 525,
+ .reserved = {0,0,0,0}
+ }
+};
+
+#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0]))
+
+static struct v4l2_standard *match_std(v4l2_std_id id)
+{
+ unsigned int idx;
+ for (idx = 0; idx < generic_standards_cnt; idx++) {
+ if (generic_standards[idx].id & id) {
+ return generic_standards + idx;
+ }
+ }
+ return NULL;
+}
+
+static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
+{
+ struct v4l2_standard *template;
+ int idx;
+ unsigned int bcnt;
+ template = match_std(id);
+ if (!template) return 0;
+ idx = std->index;
+ memcpy(std,template,sizeof(*template));
+ std->index = idx;
+ std->id = id;
+ bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
+ std->name[bcnt] = 0;
+ pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s",
+ std->index,std->name);
+ return !0;
+}
+
+/* These are special cases of combined standards that we should enumerate
+ separately if the component pieces are present. */
+static v4l2_std_id std_mixes[] = {
+ V4L2_STD_PAL_B | V4L2_STD_PAL_G,
+ V4L2_STD_PAL_D | V4L2_STD_PAL_K,
+ V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
+ V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
+};
+
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ v4l2_std_id id)
+{
+ unsigned int std_cnt = 0;
+ unsigned int idx,bcnt,idx2;
+ v4l2_std_id idmsk,cmsk,fmsk;
+ struct v4l2_standard *stddefs;
+
+ if (pvrusb2_debug & PVR2_TRACE_INIT) {
+ char buf[50];
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+ pvr2_trace(
+ PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)",
+ (int)id,bcnt,buf);
+ }
+
+ *countptr = 0;
+ std_cnt = 0;
+ fmsk = 0;
+ for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
+ if (!(idmsk & cmsk)) continue;
+ cmsk &= ~idmsk;
+ if (match_std(idmsk)) {
+ std_cnt++;
+ continue;
+ }
+ fmsk |= idmsk;
+ }
+
+ for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) {
+ if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+ }
+
+ if (fmsk) {
+ char buf[50];
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+ "WARNING:"
+ " Failed to classify the following standard(s): %.*s",
+ bcnt,buf);
+ }
+
+ pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)",
+ std_cnt);
+ if (!std_cnt) return NULL; // paranoia
+
+ stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
+ GFP_KERNEL);
+ memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt);
+ for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx;
+
+ idx = 0;
+
+ /* Enumerate potential special cases */
+ for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) &&
+ (idx < std_cnt)); idx2++) {
+ if (!(id & std_mixes[idx2])) continue;
+ if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
+ }
+ /* Now enumerate individual pieces */
+ for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
+ if (!(idmsk & cmsk)) continue;
+ cmsk &= ~idmsk;
+ if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
+ idx++;
+ }
+
+ *countptr = std_cnt;
+ return stddefs;
+}
+
+v4l2_std_id pvr2_std_get_usable(void)
+{
+ return CSTD_ALL;
+}
+
+
+/*
+ Stuff for Emacs to see, in order to encourage consistent editing style:
+ *** Local Variables: ***
+ *** mode: c ***
+ *** fill-column: 75 ***
+ *** tab-width: 8 ***
+ *** c-basic-offset: 8 ***
+ *** End: ***
+ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-std.h b/linux/drivers/media/video/pvrusb2/pvrusb2-std.h
new file mode 100644
index 000000000..dc9ef5bb3
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-std.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * $Id$
+ *
+ * Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __PVRUSB2_STD_H
+#define __PVRUSB2_STD_H
+
+#include "compat.h"
+#include <linux/videodev2.h>
+
+// Convert string describing one or more video standards into a mask of V4L
+// standard bits. Return true if conversion succeeds otherwise return
+// false. String is expected to be of the form: C1-x/y;C2-a/b where C1 and
+// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
+// modulation schemes (e.g. "M", "B", "G", etc).
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+ unsigned int bufSize);
+
+// Convert any arbitrary set of video standard bits into an unambiguous
+// readable string. Return value is the number of bytes consumed in the
+// buffer. The formatted string is of a form that can be parsed by our
+// sibling std_std_to_id() function.
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+ v4l2_std_id id);
+
+// Create an array of suitable v4l2_standard structures given a bit mask of
+// video standards to support. The array is allocated from the heap, and
+// the number of elements is returned in the first argument.
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ v4l2_std_id id);
+
+// Return mask of which video standard bits are valid
+v4l2_std_id pvr2_std_get_usable(void);
+
+#endif /* __PVRUSB2_STD_H */
+
+/*
+ Stuff for Emacs to see, in order to encourage consistent editing style:
+ *** Local Variables: ***
+ *** mode: c ***
+ *** fill-column: 75 ***
+ *** tab-width: 8 ***
+ *** c-basic-offset: 8 ***
+ *** End: ***
+ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 053c0b24c..4770bc3be 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/config.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/semaphore.h>
@@ -55,14 +56,17 @@ struct pvr2_sysfs_debugifc {
struct pvr2_sysfs_ctl_item {
struct class_device_attribute attr_name;
+ struct class_device_attribute attr_type;
struct class_device_attribute attr_min;
struct class_device_attribute attr_max;
struct class_device_attribute attr_enum;
+ struct class_device_attribute attr_bits;
struct class_device_attribute attr_val;
+ struct class_device_attribute attr_custom;
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *chptr;
struct pvr2_sysfs_ctl_item *item_next;
- struct attribute *attr_gen[5];
+ struct attribute *attr_gen[7];
struct attribute_group grp;
char name[80];
};
@@ -80,7 +84,7 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
+ if (!cptr) return -EINVAL;
name = pvr2_ctrl_get_desc(cptr);
pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);
@@ -90,237 +94,203 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
return scnprintf(buf,PAGE_SIZE,"%s\n",name);
}
+static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
+{
+ struct pvr2_ctrl *cptr;
+ struct pvr2_sysfs *sfp;
+ const char *name;
+ enum pvr2_ctl_type tp;
+
+ sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ if (!sfp) return -EINVAL;
+ cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+ if (!cptr) return -EINVAL;
+
+ tp = pvr2_ctrl_get_type(cptr);
+ switch (tp) {
+ case pvr2_ctl_int: name = "integer"; break;
+ case pvr2_ctl_enum: name = "enum"; break;
+ case pvr2_ctl_bitmask: name = "bitmask"; break;
+ case pvr2_ctl_bool: name = "boolean"; break;
+ default: name = "?"; break;
+ }
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name);
+
+ if (!name) return -EINVAL;
+
+ return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
- int val;
+ long val;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
- val = pvr2_ctrl_get_min_value(cptr);
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %d",sfp,id,val);
+ if (!cptr) return -EINVAL;
+ val = pvr2_ctrl_get_min(cptr);
- return scnprintf(buf,PAGE_SIZE,"%d\n",val);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
+
+ return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
}
static ssize_t show_max(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
- int val;
+ long val;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
- val = pvr2_ctrl_get_max_value(cptr);
+ if (!cptr) return -EINVAL;
+ val = pvr2_ctrl_get_max(cptr);
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %d",sfp,id,val);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
- return scnprintf(buf,PAGE_SIZE,"%d\n",val);
+ return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
}
-static ssize_t show_val_int(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
- int val;
+ int val,ret;
+ unsigned int cnt = 0;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
- val = pvr2_ctrl_get_value(cptr);
+ if (!cptr) return -EINVAL;
+
+ ret = pvr2_ctrl_get_value(cptr,&val);
+ if (ret < 0) return ret;
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_int(cid=%d) is %d",
- sfp,id,val);
+ ret = pvr2_ctrl_value_to_sym(cptr,~0,val,
+ buf,PAGE_SIZE-1,&cnt);
- return scnprintf(buf,PAGE_SIZE,"%d\n",val);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
+ sfp,id,cnt,buf,val);
+ buf[cnt] = '\n';
+ return cnt+1;
}
-static ssize_t show_val_enum(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
- int val;
- const char *name;
+ int val,ret;
+ unsigned int cnt = 0;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
+ if (!cptr) return -EINVAL;
- val = pvr2_ctrl_get_value(cptr);
- name = pvr2_ctrl_get_value_name(cptr,val);
+ ret = pvr2_ctrl_get_value(cptr,&val);
+ if (ret < 0) return ret;
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_enum(cid=%d) is %s (%d)",
- sfp,id,name,val);
+ ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val,
+ buf,PAGE_SIZE-1,&cnt);
- return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
+ sfp,id,cnt,buf,val);
+ buf[cnt] = '\n';
+ return cnt+1;
}
static ssize_t show_enum(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
- int minval,maxval,val;
- const char *name;
- ssize_t cnt = 0;
+ long val;
+ unsigned int bcnt,ccnt,ecnt;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
- minval = pvr2_ctrl_get_min_value(cptr);
- maxval = pvr2_ctrl_get_max_value(cptr);
- for (val = minval; val <= maxval; val++) {
- name = pvr2_ctrl_get_value_name(cptr,val);
- cnt += scnprintf(buf+cnt,PAGE_SIZE-cnt,"%s\n",name);
+ if (!cptr) return -EINVAL;
+ ecnt = pvr2_ctrl_get_cnt(cptr);
+ bcnt = 0;
+ for (val = 0; val < ecnt; val++) {
+ pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+ if (!ccnt) continue;
+ bcnt += ccnt;
+ if (bcnt >= PAGE_SIZE) break;
+ buf[bcnt] = '\n';
+ bcnt++;
}
pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);
- return cnt;
+ return bcnt;
}
-static int store_val_any(int id,struct pvr2_sysfs *sfp,
- const char *buf,unsigned int count)
+static ssize_t show_bits(int id,struct class_device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
- int val,minval,maxval;
- int ch,ret;
- const char *nv;
- unsigned int nl;
- int negfl;
-
- /* Trim leading / trailing whitespace */
- while (count) {
- ch = buf[0];
- if ((ch > 32) && (ch < 127)) break;
- buf++;
- count--;
- }
- while (count) {
- ch = buf[count-1];
- if ((ch > 32) && (ch < 127)) break;
- count--;
- }
+ struct pvr2_sysfs *sfp;
+ int valid_bits,msk;
+ unsigned int bcnt,ccnt;
+ sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
- if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;
-
- /* Is this an enum? Look for a string value */
- minval = pvr2_ctrl_get_min_value(cptr);
- maxval = pvr2_ctrl_get_max_value(cptr);
- for (val = minval; val <= maxval; val++) {
- nv = pvr2_ctrl_get_value_name(cptr,val);
- if ((!nv) && (val == minval)) break; /* Not an enum */
- pvr2_sysfs_trace("pvr2_sysfs(%p) trying ctl_id %d val %d",
- sfp,id,val);
- if (!nv) {
- pvr2_sysfs_trace("pvr2_sysfs(%p) no pointer",sfp);
- continue;
- }
- nl = strlen(nv);
- if (nl != count) {
- pvr2_sysfs_trace("pvr2_sysfs(%p) count mismatch"
- " %d != %d",
- sfp,count,nl);
- continue;
- }
- if (memcmp(buf,nv,nl)) {
- pvr2_sysfs_trace(
- "pvr2_sysfs(%p) name mismatch"
- " >>%.*s<< != >>%.*s<<",
- sfp,nl,buf,nl,nv);
- continue;
- }
- pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)"
- " is enum %s",
- sfp,id,nv);
- ret = pvr2_ctrl_set_value(cptr,val);
- pvr2_hdw_commit_ctl(sfp->channel.hdw);
- return 0;
- }
- if (val > minval) {
- pvr2_sysfs_trace(
- "pvr2_sysfs(%p) store_val_any(cid=%d)"
- " unmatched enum >>%.*s<<",
- sfp,id,count,buf);
+ if (!cptr) return -EINVAL;
+ valid_bits = pvr2_ctrl_get_mask(cptr);
+ bcnt = 0;
+ for (msk = 1; valid_bits; msk <<= 1) {
+ if (!(msk & valid_bits)) continue;
+ valid_bits &= ~msk;
+ pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+ bcnt += ccnt;
+ if (bcnt >= PAGE_SIZE) break;
+ buf[bcnt] = '\n';
+ bcnt++;
}
-
- /* Try to parse as a number */
- negfl = 0;
- val = 0;
- if (count) {
- if (buf[0] == '-') {
- negfl = !0;
- buf++;
- count--;
- } else if (buf[0] == '+') {
- buf++;
- count--;
- }
- }
- while (count) {
- ch = buf[0];
- if ((ch < '0') || (ch > '9')) break;
- val = val * 10;
- val += (ch - '0');
- buf++;
- count--;
- }
- if (!count) {
- if (negfl) val = -val;
- pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)"
- " int is %d",
- sfp,id,val);
-
- ret = pvr2_ctrl_set_value(cptr,val);
- pvr2_hdw_commit_ctl(sfp->channel.hdw);
- return ret;
- }
-
- return -EINVAL;
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);
+ return bcnt;
}
-static int store_val_multi(int id,struct pvr2_sysfs *sfp,
- const char *buf,unsigned int count)
+static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
+ const char *buf,unsigned int count)
{
- unsigned int count2;
+ struct pvr2_ctrl *cptr;
int ret;
+ int mask,val;
- while (count) {
- count2 = 0;
- while ((count2 < count) && (buf[count2] != '\n')) count2++;
- ret = store_val_any(id,sfp,buf,count2);
- if (ret < 0) return ret;
- if (count2 < count) count2++;
- buf += count2;
- count -= count2;
+ cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+ if (customfl) {
+ ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val);
+ } else {
+ ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val);
}
- return 0;
+ if (ret < 0) return ret;
+ ret = pvr2_ctrl_set_mask_value(cptr,mask,val);
+ pvr2_hdw_commit_ctl(sfp->channel.hdw);
+ return ret;
}
-static ssize_t store_val_int(int id,struct class_device *class_dev,
+static ssize_t store_val_norm(int id,struct class_device *class_dev,
const char *buf,size_t count)
{
struct pvr2_sysfs *sfp;
int ret;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
- ret = store_val_multi(id,sfp,buf,count);
+ ret = store_val_any(id,0,sfp,buf,count);
if (!ret) ret = count;
return ret;
}
-static ssize_t store_val_enum(int id,struct class_device *class_dev,
- const char *buf,size_t count)
+static ssize_t store_val_custom(int id,struct class_device *class_dev,
+ const char *buf,size_t count)
{
struct pvr2_sysfs *sfp;
int ret;
sfp = (struct pvr2_sysfs *)class_dev->class_data;
- ret = store_val_multi(id,sfp,buf,count);
+ ret = store_val_any(id,1,sfp,buf,count);
if (!ret) ret = count;
return ret;
}
@@ -348,13 +318,15 @@ static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf
#define CREATE_BATCH(ctl_id) \
CREATE_SHOW_INSTANCE(show_name,ctl_id) \
+CREATE_SHOW_INSTANCE(show_type,ctl_id) \
CREATE_SHOW_INSTANCE(show_min,ctl_id) \
CREATE_SHOW_INSTANCE(show_max,ctl_id) \
-CREATE_SHOW_INSTANCE(show_val_int,ctl_id) \
-CREATE_SHOW_INSTANCE(show_val_enum,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
-CREATE_STORE_INSTANCE(store_val_int,ctl_id) \
-CREATE_STORE_INSTANCE(store_val_enum,ctl_id)
+CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
CREATE_BATCH(0)
CREATE_BATCH(1)
@@ -390,30 +362,60 @@ CREATE_BATCH(30)
CREATE_BATCH(31)
CREATE_BATCH(32)
CREATE_BATCH(33)
+CREATE_BATCH(34)
+CREATE_BATCH(35)
+CREATE_BATCH(36)
+CREATE_BATCH(37)
+CREATE_BATCH(38)
+CREATE_BATCH(39)
+CREATE_BATCH(40)
+CREATE_BATCH(41)
+CREATE_BATCH(42)
+CREATE_BATCH(43)
+CREATE_BATCH(44)
+CREATE_BATCH(45)
+CREATE_BATCH(46)
+CREATE_BATCH(47)
+CREATE_BATCH(48)
+CREATE_BATCH(49)
+CREATE_BATCH(50)
+CREATE_BATCH(51)
+CREATE_BATCH(52)
+CREATE_BATCH(53)
+CREATE_BATCH(54)
+CREATE_BATCH(55)
+CREATE_BATCH(56)
+CREATE_BATCH(57)
+CREATE_BATCH(58)
+CREATE_BATCH(59)
struct pvr2_sysfs_func_set {
ssize_t (*show_name)(struct class_device *,char *);
+ ssize_t (*show_type)(struct class_device *,char *);
ssize_t (*show_min)(struct class_device *,char *);
ssize_t (*show_max)(struct class_device *,char *);
ssize_t (*show_enum)(struct class_device *,char *);
- ssize_t (*show_val_int)(struct class_device *,char *);
- ssize_t (*show_val_enum)(struct class_device *,char *);
- ssize_t (*store_val_int)(struct class_device *,
- const char *,size_t);
- ssize_t (*store_val_enum)(struct class_device *,
+ ssize_t (*show_bits)(struct class_device *,char *);
+ ssize_t (*show_val_norm)(struct class_device *,char *);
+ ssize_t (*store_val_norm)(struct class_device *,
const char *,size_t);
+ ssize_t (*show_val_custom)(struct class_device *,char *);
+ ssize_t (*store_val_custom)(struct class_device *,
+ const char *,size_t);
};
#define INIT_BATCH(ctl_id) \
[ctl_id] = { \
.show_name = show_name_##ctl_id, \
+ .show_type = show_type_##ctl_id, \
.show_min = show_min_##ctl_id, \
.show_max = show_max_##ctl_id, \
.show_enum = show_enum_##ctl_id, \
- .show_val_int = show_val_int_##ctl_id, \
- .show_val_enum = show_val_enum_##ctl_id, \
- .store_val_int = store_val_int_##ctl_id, \
- .store_val_enum = store_val_enum_##ctl_id, \
+ .show_bits = show_bits_##ctl_id, \
+ .show_val_norm = show_val_norm_##ctl_id, \
+ .store_val_norm = store_val_norm_##ctl_id, \
+ .show_val_custom = show_val_custom_##ctl_id, \
+ .store_val_custom = store_val_custom_##ctl_id, \
} \
static struct pvr2_sysfs_func_set funcs[] = {
@@ -451,6 +453,32 @@ static struct pvr2_sysfs_func_set funcs[] = {
INIT_BATCH(31),
INIT_BATCH(32),
INIT_BATCH(33),
+ INIT_BATCH(34),
+ INIT_BATCH(35),
+ INIT_BATCH(36),
+ INIT_BATCH(37),
+ INIT_BATCH(38),
+ INIT_BATCH(39),
+ INIT_BATCH(40),
+ INIT_BATCH(41),
+ INIT_BATCH(42),
+ INIT_BATCH(43),
+ INIT_BATCH(44),
+ INIT_BATCH(45),
+ INIT_BATCH(46),
+ INIT_BATCH(47),
+ INIT_BATCH(48),
+ INIT_BATCH(49),
+ INIT_BATCH(50),
+ INIT_BATCH(51),
+ INIT_BATCH(52),
+ INIT_BATCH(53),
+ INIT_BATCH(54),
+ INIT_BATCH(55),
+ INIT_BATCH(56),
+ INIT_BATCH(57),
+ INIT_BATCH(58),
+ INIT_BATCH(59),
};
@@ -459,7 +487,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
struct pvr2_sysfs_ctl_item *cip;
struct pvr2_sysfs_func_set *fp;
struct pvr2_ctrl *cptr;
- unsigned int cnt;
+ unsigned int cnt,acnt;
if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
return;
@@ -477,7 +505,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->cptr = cptr;
cip->chptr = sfp;
- cip->item_next = 0;
+ cip->item_next = NULL;
if (sfp->item_last) {
sfp->item_last->item_next = cip;
} else {
@@ -490,6 +518,11 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_name.attr.mode = S_IRUGO;
cip->attr_name.show = fp->show_name;
+ cip->attr_type.attr.owner = THIS_MODULE;
+ cip->attr_type.attr.name = "type";
+ cip->attr_type.attr.mode = S_IRUGO;
+ cip->attr_type.show = fp->show_type;
+
cip->attr_min.attr.owner = THIS_MODULE;
cip->attr_min.attr.name = "min_val";
cip->attr_min.attr.mode = S_IRUGO;
@@ -504,28 +537,51 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_val.attr.name = "cur_val";
cip->attr_val.attr.mode = S_IRUGO;
+ cip->attr_custom.attr.owner = THIS_MODULE;
+ cip->attr_custom.attr.name = "custom_val";
+ cip->attr_custom.attr.mode = S_IRUGO;
+
cip->attr_enum.attr.owner = THIS_MODULE;
cip->attr_enum.attr.name = "enum_val";
cip->attr_enum.attr.mode = S_IRUGO;
cip->attr_enum.show = fp->show_enum;
- if (pvr2_ctrl_is_writeable(cptr)) {
+ cip->attr_bits.attr.owner = THIS_MODULE;
+ cip->attr_bits.attr.name = "bit_val";
+ cip->attr_bits.attr.mode = S_IRUGO;
+ cip->attr_bits.show = fp->show_bits;
+
+ if (pvr2_ctrl_is_writable(cptr)) {
cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
+ cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
}
- cip->attr_gen[0] = &cip->attr_name.attr;
- cip->attr_gen[1] = &cip->attr_val.attr;
- if (pvr2_ctrl_get_type(cptr) == PVR2_CTRL_TYPE_ENUM) {
+ acnt = 0;
+ cip->attr_gen[acnt++] = &cip->attr_name.attr;
+ cip->attr_gen[acnt++] = &cip->attr_type.attr;
+ cip->attr_gen[acnt++] = &cip->attr_val.attr;
+ cip->attr_val.show = fp->show_val_norm;
+ cip->attr_val.store = fp->store_val_norm;
+ if (pvr2_ctrl_has_custom_symbols(cptr)) {
+ cip->attr_gen[acnt++] = &cip->attr_custom.attr;
+ cip->attr_custom.show = fp->show_val_custom;
+ cip->attr_custom.store = fp->store_val_custom;
+ }
+ switch (pvr2_ctrl_get_type(cptr)) {
+ case pvr2_ctl_enum:
// Control is an enumeration
- cip->attr_gen[2] = &cip->attr_enum.attr;
- cip->attr_val.show = fp->show_val_enum;
- cip->attr_val.store = fp->store_val_enum;
- } else {
+ cip->attr_gen[acnt++] = &cip->attr_enum.attr;
+ break;
+ case pvr2_ctl_int:
// Control is an integer
- cip->attr_val.show = fp->show_val_int;
- cip->attr_val.store = fp->store_val_int;
- cip->attr_gen[2] = &cip->attr_min.attr;
- cip->attr_gen[3] = &cip->attr_max.attr;
+ cip->attr_gen[acnt++] = &cip->attr_min.attr;
+ cip->attr_gen[acnt++] = &cip->attr_max.attr;
+ break;
+ case pvr2_ctl_bitmask:
+ // Control is an bitmask
+ cip->attr_gen[acnt++] = &cip->attr_bits.attr;
+ break;
+ default: break;
}
cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
@@ -570,7 +626,7 @@ static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
&sfp->debugifc->attr_debuginfo);
class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
kfree(sfp->debugifc);
- sfp->debugifc = 0;
+ sfp->debugifc = NULL;
}
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
@@ -623,9 +679,9 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
- sfp->class_dev->class_data = 0;
+ sfp->class_dev->class_data = NULL;
class_device_unregister(sfp->class_dev);
- sfp->class_dev = 0;
+ sfp->class_dev = NULL;
}
@@ -684,13 +740,13 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
- sfp->attr_v4l_minor_number.store = 0;
+ sfp->attr_v4l_minor_number.store = NULL;
class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
sfp->attr_unit_number.attr.owner = THIS_MODULE;
sfp->attr_unit_number.attr.name = "unit_number";
sfp->attr_unit_number.attr.mode = S_IRUGO;
sfp->attr_unit_number.show = unit_number_show;
- sfp->attr_unit_number.store = 0;
+ sfp->attr_unit_number.store = NULL;
class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
pvr2_sysfs_add_controls(sfp);
@@ -755,7 +811,7 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
pvr2_sysfs_trace(
"Registration failed for pvr2_sysfs_class id=%p",clp);
kfree(clp);
- clp = 0;
+ clp = NULL;
}
return clp;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
index 8bf7cc142..e196d92a6 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
@@ -70,7 +70,7 @@ static void tuner_update(struct pvr2_tuner_handler *ctxt)
static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt)
{
- ctxt->client->handler = 0;
+ ctxt->client->handler = NULL;
kfree(ctxt);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 51491e67c..2ca67413d 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -22,8 +22,7 @@
#include "compat.h"
#include <linux/kernel.h>
-#include <linux/videodev.h>
-
+#include <linux/version.h>
#include "pvrusb2-context.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2.h"
@@ -33,22 +32,25 @@
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
-
-#define PVR_WIDTH_DVD 720
-#define PVR_WIDTH_SVCD 480
-#define PVR_WIDTH_VCD 352
-
-#define PVR_HEIGHT_PAL 480
-#define PVR_HEIGHT_NTSC 576
-
struct pvr2_v4l2_dev;
struct pvr2_v4l2_fh;
struct pvr2_v4l2;
+/* V4L no longer provide the ability to set / get a private context pointer
+ (i.e. video_get_drvdata / video_set_drvdata), which means we have to
+ concoct our own context locating mechanism. Supposedly this is intended
+ to simplify driver implementation. It's not clear to me how that can
+ possibly be true. Our solution here is to maintain a lookup table of
+ our context instances, indexed by the minor device number of the V4L
+ device. See pvr2_v4l2_open() for some implications of this approach. */
+static struct pvr2_v4l2_dev *devices[256];
+static DEFINE_MUTEX(device_lock);
+
struct pvr2_v4l2_dev {
struct pvr2_v4l2 *v4lp;
struct video_device *vdev;
struct pvr2_context_stream *stream;
+ int ctxt_idx;
enum pvr2_config config;
};
@@ -80,7 +82,7 @@ static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "Offset for device's minor");
-struct v4l2_capability pvr_capability ={
+static struct v4l2_capability pvr_capability ={
.driver = "pvrusb2",
.card = "Hauppauge WinTV pvr-usb2",
.bus_info = "usb",
@@ -125,7 +127,7 @@ static struct v4l2_tuner pvr_v4l2_tuners[]= {
#endif
};
-struct v4l2_fmtdesc pvr_fmtdesc [] = {
+static struct v4l2_fmtdesc pvr_fmtdesc [] = {
{
.index = 0,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -141,7 +143,7 @@ struct v4l2_fmtdesc pvr_fmtdesc [] = {
#define PVR_FORMAT_PIX 0
#define PVR_FORMAT_VBI 1
-struct v4l2_format pvr_format [] = {
+static struct v4l2_format pvr_format [] = {
[PVR_FORMAT_PIX] = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt = {
@@ -246,46 +248,25 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *vs = (struct v4l2_standard *)arg;
- const struct v4l2_standard *src;
int idx = vs->index;
-
- src = pvr2_hdw_get_stdenum_value(hdw,idx);
- if (!src) break;
-
- memcpy(vs, src, sizeof(struct v4l2_standard));
- vs->index = idx;
-
- ret = 0;
+ ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
break;
}
case VIDIOC_G_STD:
{
- struct pvr2_ctrl *cptr;
- v4l2_std_id *vs = (v4l2_std_id *)arg;
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- *vs = pvr2_ctrl_get_value(cptr);
- ret = 0;
+ int val = 0;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
+ *(v4l2_std_id *)arg = val;
break;
}
case VIDIOC_S_STD:
{
- struct pvr2_ctrl *cptr;
- v4l2_std_id *vs = (v4l2_std_id *)arg;
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- pvr2_ctrl_set_value(cptr,*vs);
- ret = 0;
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
+ *(v4l2_std_id *)arg);
break;
}
@@ -294,16 +275,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
struct pvr2_ctrl *cptr;
struct v4l2_input *vi = (struct v4l2_input *)arg;
struct v4l2_input tmp;
+ unsigned int cnt;
- if ((vi->index > PVR2_CVAL_INPUT_MAX) ||
- (vi->index < PVR2_CVAL_INPUT_MIN)) {
- break;
- }
-
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT);
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
memset(&tmp,0,sizeof(tmp));
tmp.index = vi->index;
+ ret = 0;
switch (vi->index) {
case PVR2_CVAL_INPUT_TV:
case PVR2_CVAL_INPUT_RADIO:
@@ -313,11 +291,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case PVR2_CVAL_INPUT_COMPOSITE:
tmp.type = V4L2_INPUT_TYPE_CAMERA;
break;
+ default:
+ ret = -EINVAL;
+ break;
}
+ if (ret < 0) break;
- strlcpy(tmp.name,
- pvr2_ctrl_get_value_name(cptr,vi->index),
- sizeof(tmp.name));
+ cnt = 0;
+ pvr2_ctrl_get_valname(cptr,vi->index,
+ tmp.name,sizeof(tmp.name)-1,&cnt);
+ tmp.name[cnt] = 0;
/* Don't bother with audioset, since this driver currently
always switches the audio whenever the video is
@@ -339,31 +322,20 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
{
struct pvr2_ctrl *cptr;
struct v4l2_input *vi = (struct v4l2_input *)arg;
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- vi->index = pvr2_ctrl_get_value(cptr);
- ret = 0;
+ int val;
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+ val = 0;
+ ret = pvr2_ctrl_get_value(cptr,&val);
+ vi->index = val;
break;
}
case VIDIOC_S_INPUT:
{
- struct pvr2_ctrl *cptr;
struct v4l2_input *vi = (struct v4l2_input *)arg;
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- ret = 0;
- if (pvr2_ctrl_set_value(cptr,vi->index)) {
- ret = -EINVAL;
- }
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+ vi->index);
break;
}
@@ -386,9 +358,9 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_G_TUNER:
{
- struct pvr2_ctrl *cptr;
struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
unsigned int status_mask;
+ int val;
if (vt->index !=0) break;
status_mask = pvr2_hdw_get_signal_status(hdw);
@@ -410,66 +382,44 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
vt->signal = 65535;
}
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_AUDIOMODE);
- vt->audmode = pvr2_ctrl_get_value(cptr);
-
- ret = 0;
+ val = 0;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+ &val);
+ vt->audmode = val;
break;
}
case VIDIOC_S_TUNER:
{
- struct pvr2_ctrl *cptr;
struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
if (vt->index != 0)
break;
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_AUDIOMODE);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- pvr2_ctrl_set_value(cptr,vt->audmode);
- ret = 0;
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+ vt->audmode);
}
case VIDIOC_S_FREQUENCY:
{
- struct pvr2_ctrl *cptr;
const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
-
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_FREQUENCY);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- pvr2_ctrl_set_value(cptr,vf->frequency * 62500);
-
- ret = 0;
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+ vf->frequency * 62500);
break;
}
case VIDIOC_G_FREQUENCY:
{
- struct pvr2_ctrl *cptr;
struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
- int val;
-
- cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_FREQUENCY);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
-
- val = pvr2_ctrl_get_value(cptr);
-
+ int val = 0;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+ &val);
val /= 62500;
vf->frequency = val;
-
- ret = 0;
break;
}
@@ -489,24 +439,21 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_FMT:
{
struct v4l2_format *vf = (struct v4l2_format *)arg;
-
+ int val;
switch(vf->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
sizeof(struct v4l2_format));
- vf->fmt.pix.width =
- pvr2_ctrl_get_value(
- pvr2_hdw_get_ctrl(hdw,
- V4L2_CID_PVR_HRES));
- if (pvr2_ctrl_get_value(
- pvr2_hdw_get_ctrl(
- hdw,V4L2_CID_PVR_INTERLACE))) {
- vf->fmt.pix.width /= 2;
- }
- vf->fmt.pix.height =
- pvr2_ctrl_get_value(
- pvr2_hdw_get_ctrl(hdw,
- V4L2_CID_PVR_VRES));
+ val = 0;
+ pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
+ &val);
+ vf->fmt.pix.width = val;
+ val = 0;
+ pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
+ &val);
+ vf->fmt.pix.height = val;
ret = 0;
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
@@ -530,37 +477,32 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
int h = vf->fmt.pix.height;
int w = vf->fmt.pix.width;
- int vd_std, hf, hh;
- vd_std = pvr2_ctrl_get_value(
- pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR));
- if (vd_std & V4L2_STD_525_60) {
- hf=480;
- } else {
- hf=576;
+ if (h < 200) {
+ h = 200;
+ } else if (h > 625) {
+ h = 625;
+ }
+ if (w < 320) {
+ w = 320;
+ } else if (w > 720) {
+ w = 720;
}
- hh = (int) (hf / 2);
memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
sizeof(struct v4l2_format));
- if (w > 720)
- vf->fmt.pix.width = 720;
- vf->fmt.pix.width &= 0xff0;
- vf->fmt.pix.height = (h > hh) ? hf : hh;
+ vf->fmt.pix.width = w;
+ vf->fmt.pix.height = h;
- if (cmd == VIDIOC_S_FMT){
+ if (cmd == VIDIOC_S_FMT) {
pvr2_ctrl_set_value(
- pvr2_hdw_get_ctrl(hdw,
- V4L2_CID_PVR_HRES),
+ pvr2_hdw_get_ctrl_by_id(hdw,
+ PVR2_CID_HRES),
vf->fmt.pix.width);
pvr2_ctrl_set_value(
- pvr2_hdw_get_ctrl(hdw,
- V4L2_CID_PVR_VRES),
+ pvr2_hdw_get_ctrl_by_id(hdw,
+ PVR2_CID_VRES),
vf->fmt.pix.height);
- pvr2_ctrl_set_value(
- pvr2_hdw_get_ctrl(
- hdw,V4L2_CID_PVR_INTERLACE),
- vf->fmt.pix.height != hf);
}
} break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
@@ -592,92 +534,154 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
{
struct pvr2_ctrl *cptr;
struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
- cptr = pvr2_hdw_get_ctrl(hdw,vc->id);
-
- if (!pvr2_ctrl_is_valid(cptr)) {
+ ret = 0;
+ if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+ cptr = pvr2_hdw_get_ctrl_nextv4l(
+ hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
+ if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
+ } else {
+ cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
+ }
+ if (!cptr) {
+ pvr2_trace(PVR2_TRACE_V4LIOCTL,
+ "QUERYCTRL id=0x%x not implemented here",
+ vc->id);
ret = -EINVAL;
break;
}
+ pvr2_trace(PVR2_TRACE_V4LIOCTL,
+ "QUERYCTRL id=0x%x mapping name=%s (%s)",
+ vc->id,pvr2_ctrl_get_name(cptr),
+ pvr2_ctrl_get_desc(cptr));
+ strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
+ vc->flags = pvr2_ctrl_get_v4lflags(cptr);
+ vc->default_value = pvr2_ctrl_get_def(cptr);
switch (pvr2_ctrl_get_type(cptr)) {
- case PVR2_CTRL_TYPE_ENUM:
+ case pvr2_ctl_enum:
vc->type = V4L2_CTRL_TYPE_MENU;
+ vc->minimum = 0;
+ vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
+ vc->step = 1;
+ break;
+ case pvr2_ctl_bool:
+ vc->type = V4L2_CTRL_TYPE_BOOLEAN;
+ vc->minimum = 0;
+ vc->maximum = 1;
+ vc->step = 1;
break;
- case PVR2_CTRL_TYPE_INT:
+ case pvr2_ctl_int:
vc->type = V4L2_CTRL_TYPE_INTEGER;
+ vc->minimum = pvr2_ctrl_get_min(cptr);
+ vc->maximum = pvr2_ctrl_get_max(cptr);
+ vc->step = 1;
break;
default:
+ pvr2_trace(PVR2_TRACE_V4LIOCTL,
+ "QUERYCTRL id=0x%x name=%s not mappable",
+ vc->id,pvr2_ctrl_get_name(cptr));
ret = -EINVAL;
break;
}
-
- strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
- vc->minimum = pvr2_ctrl_get_min_value(cptr);
- vc->maximum = pvr2_ctrl_get_max_value(cptr);
- vc->default_value = pvr2_ctrl_get_default_value(cptr);
- vc->step = 1;
- ret = 0;
break;
}
case VIDIOC_QUERYMENU:
{
- struct pvr2_ctrl *cptr;
struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
- const char *value_name;
- cptr = pvr2_hdw_get_ctrl(hdw,vm->id);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
- value_name = pvr2_ctrl_get_value_name(cptr,vm->index);
- if (value_name) {
- strlcpy(vm->name,value_name,sizeof(vm->name));
- ret = 0;
- } else {
- ret = -EINVAL;
- }
-
+ unsigned int cnt = 0;
+ ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
+ vm->index,
+ vm->name,sizeof(vm->name)-1,
+ &cnt);
+ vm->name[cnt] = 0;
break;
}
case VIDIOC_G_CTRL:
{
- struct pvr2_ctrl *cptr;
struct v4l2_control *vc = (struct v4l2_control *)arg;
-
- cptr = pvr2_hdw_get_ctrl(hdw,vc->id);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
- }
- ret = 0;
- vc->value = pvr2_ctrl_get_value(cptr);
+ int val = 0;
+ ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+ &val);
+ vc->value = val;
break;
}
case VIDIOC_S_CTRL:
{
- struct pvr2_ctrl *cptr;
struct v4l2_control *vc = (struct v4l2_control *)arg;
+ ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+ vc->value);
+ break;
+ }
- cptr = pvr2_hdw_get_ctrl(hdw,vc->id);
- if (!pvr2_ctrl_is_valid(cptr)) {
- ret = -EINVAL;
- break;
+ case VIDIOC_G_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *ctls =
+ (struct v4l2_ext_controls *)arg;
+ struct v4l2_ext_control *ctrl;
+ unsigned int idx;
+ int val;
+ for (idx = 0; idx < ctls->count; idx++) {
+ ctrl = ctls->controls + idx;
+ ret = pvr2_ctrl_get_value(
+ pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
+ if (ret) {
+ ctls->error_idx = idx;
+ break;
+ }
+ /* Ensure that if read as a 64 bit value, the user
+ will still get a hopefully sane value */
+ ctrl->value64 = 0;
+ ctrl->value = val;
}
+ break;
+ }
- ret = pvr2_ctrl_set_value(cptr,vc->value);
+ case VIDIOC_S_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *ctls =
+ (struct v4l2_ext_controls *)arg;
+ struct v4l2_ext_control *ctrl;
+ unsigned int idx;
+ for (idx = 0; idx < ctls->count; idx++) {
+ ctrl = ctls->controls + idx;
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
+ ctrl->value);
+ if (ret) {
+ ctls->error_idx = idx;
+ break;
+ }
+ }
break;
}
- case VIDIOC_LOG_STATUS:
+ case VIDIOC_TRY_EXT_CTRLS:
{
- int nr = pvr2_hdw_get_unit_number(hdw);
+ struct v4l2_ext_controls *ctls =
+ (struct v4l2_ext_controls *)arg;
+ struct v4l2_ext_control *ctrl;
+ struct pvr2_ctrl *pctl;
+ unsigned int idx;
+ /* For the moment just validate that the requested control
+ actually exists. */
+ for (idx = 0; idx < ctls->count; idx++) {
+ ctrl = ctls->controls + idx;
+ pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
+ if (!pctl) {
+ ret = -EINVAL;
+ ctls->error_idx = idx;
+ break;
+ }
+ }
+ break;
+ }
- printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
+ case VIDIOC_LOG_STATUS:
+ {
pvr2_hdw_trigger_module_log(hdw);
- printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
ret = 0;
break;
}
@@ -691,11 +695,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
if (ret < 0) {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl failure, ret=%d",ret);
} else {
- if (pvrusb2_debug & PVR2_TRACE_ERROR_LEGS) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+ pvr2_trace(PVR2_TRACE_V4LIOCTL,
"pvr2_v4l2_do_ioctl failure, ret=%d"
" command was:",ret);
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
@@ -713,9 +717,14 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{
- pvr2_trace(PVR2_TRACE_INIT,
- "unregistering device video%d [%s]",
- dip->vdev->minor,pvr2_config_get_name(dip->config));
+ printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
+ dip->vdev->minor,pvr2_config_get_name(dip->config));
+ if (dip->ctxt_idx >= 0) {
+ mutex_lock(&device_lock);
+ devices[dip->ctxt_idx] = NULL;
+ dip->ctxt_idx = -1;
+ mutex_unlock(&device_lock);
+ }
video_unregister_device(dip->vdev);
}
@@ -731,7 +740,7 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
}
-void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
+static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
{
struct pvr2_v4l2 *vp;
vp = container_of(chp,struct pvr2_v4l2,channel);
@@ -741,8 +750,8 @@ void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
}
-int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
/* Temporary hack : use ivtv api until a v4l2 one is available. */
@@ -753,7 +762,7 @@ int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
}
-int pvr2_v4l2_release(struct inode *inode, struct file *file)
+static int pvr2_v4l2_release(struct inode *inode, struct file *file)
{
struct pvr2_v4l2_fh *fhp = file->private_data;
struct pvr2_v4l2 *vp = fhp->vhead;
@@ -767,9 +776,9 @@ int pvr2_v4l2_release(struct inode *inode, struct file *file)
hdw = fhp->channel.mc_head->hdw;
pvr2_hdw_set_streaming(hdw,0);
sp = pvr2_ioread_get_stream(fhp->rhp);
- if (sp) pvr2_stream_set_callback(sp,0,0);
+ if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
pvr2_ioread_destroy(fhp->rhp);
- fhp->rhp = 0;
+ fhp->rhp = NULL;
}
v4l2_prio_close(&vp->prio, &fhp->prio);
file->private_data = NULL;
@@ -785,9 +794,9 @@ int pvr2_v4l2_release(struct inode *inode, struct file *file)
} else {
vp->vfirst = fhp->vnext;
}
- fhp->vnext = 0;
- fhp->vprev = 0;
- fhp->vhead = 0;
+ fhp->vnext = NULL;
+ fhp->vprev = NULL;
+ fhp->vhead = NULL;
pvr2_channel_done(&fhp->channel);
pvr2_trace(PVR2_TRACE_STRUCT,
"Destroying pvr_v4l2_fh id=%p",fhp);
@@ -800,14 +809,45 @@ int pvr2_v4l2_release(struct inode *inode, struct file *file)
}
-int pvr2_v4l2_open(struct inode *inode, struct file *file)
+static int pvr2_v4l2_open(struct inode *inode, struct file *file)
{
- struct video_device *vdev = video_devdata(file);
- struct pvr2_v4l2_dev *dip =
- (struct pvr2_v4l2_dev *)video_get_drvdata(vdev);
+ struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */
struct pvr2_v4l2_fh *fhp;
- struct pvr2_v4l2 *vp = dip->v4lp;
- struct pvr2_hdw *hdw = vp->channel.hdw;
+ struct pvr2_v4l2 *vp;
+ struct pvr2_hdw *hdw;
+
+ mutex_lock(&device_lock);
+ /* MCI 7-Jun-2006 Even though we're just doing what amounts to an
+ atomic read of the device mapping array here, we still need the
+ mutex. The problem is that there is a tiny race possible when
+ we register the device. We can't update the device mapping
+ array until after the device has been registered, owing to the
+ fact that we can't know the minor device number until after the
+ registration succeeds. And if another thread tries to open the
+ device in the window of time after registration but before the
+ map is updated, then it will get back an erroneous null pointer
+ and the open will result in a spurious failure. The only way to
+ prevent that is to (a) be inside the mutex here before we access
+ the array, and (b) cover the entire registration process later
+ on with this same mutex. Thus if we get inside the mutex here,
+ then we can be assured that the registration process actually
+ completed correctly. This is an unhappy complication from the
+ use of global data in a driver that lives in a preemptible
+ environment. It sure would be nice if the video device itself
+ had a means for storing and retrieving a local context pointer.
+ Oh wait. It did. But now it's gone. Silly me. */
+ {
+ unsigned int midx = iminor(file->f_dentry->d_inode);
+ if (midx < sizeof(devices)/sizeof(devices[0])) {
+ dip = devices[midx];
+ }
+ }
+ mutex_unlock(&device_lock);
+
+ if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
+
+ vp = dip->v4lp;
+ hdw = vp->channel.hdw;
pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
@@ -829,7 +869,7 @@ int pvr2_v4l2_open(struct inode *inode, struct file *file)
pvr2_context_enter(vp->channel.mc_head); do {
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
- fhp->vnext = 0;
+ fhp->vnext = NULL;
fhp->vprev = vp->vlast;
if (vp->vlast) {
vp->vlast->vnext = fhp;
@@ -872,7 +912,7 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
if (!fh->rhp) {
- pvr2_channel_claim_stream(&fh->channel,0);
+ pvr2_channel_claim_stream(&fh->channel,NULL);
return -ENOMEM;
}
@@ -1055,7 +1095,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
dip->vdev->dev = &usbdev->dev;
#endif
dip->vdev->release = video_device_release;
- video_set_drvdata(dip->vdev,dip);
+ mutex_lock(&device_lock);
mindevnum = -1;
unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
@@ -1066,10 +1106,17 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
(video_register_device(dip->vdev, v4l_type, -1) < 0)) {
err("Failed to register pvrusb2 v4l video device");
} else {
- pvr2_trace(PVR2_TRACE_INIT,
- "registered device video%d [%s]",
- dip->vdev->minor,pvr2_config_get_name(dip->config));
+ printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
+ dip->vdev->minor,pvr2_config_get_name(dip->config));
+ }
+
+ if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
+ (devices[dip->vdev->minor] == NULL)) {
+ dip->ctxt_idx = dip->vdev->minor;
+ devices[dip->ctxt_idx] = dip;
}
+ mutex_unlock(&device_lock);
+
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
dip->vdev->minor);
}
@@ -1082,6 +1129,7 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
vp = kmalloc(sizeof(*vp),GFP_KERNEL);
if (!vp) return vp;
memset(vp,0,sizeof(*vp));
+ vp->video_dev.ctxt_idx = -1;
pvr2_channel_init(&vp->channel,mnp);
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index dde031bb8..05f2cddeb 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -54,9 +54,8 @@ static void set_input(struct pvr2_v4l_decoder *ctxt)
struct pvr2_hdw *hdw = ctxt->hdw;
struct v4l2_routing route;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",
- hdw->controls[PVR2_CID_INPUT].value);
- switch(hdw->controls[PVR2_CID_INPUT].value){
+ pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
+ switch(hdw->input_val) {
case PVR2_CVAL_INPUT_TV:
route.input = SAA7115_COMPOSITE4;
break;
@@ -79,7 +78,7 @@ static void set_input(struct pvr2_v4l_decoder *ctxt)
static int check_input(struct pvr2_v4l_decoder *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->controls[PVR2_CID_INPUT].dirty != 0;
+ return hdw->input_dirty != 0;
}
@@ -89,15 +88,18 @@ static void set_audio(struct pvr2_v4l_decoder *ctxt)
struct pvr2_hdw *hdw = ctxt->hdw;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d",
- hdw->controls[PVR2_CID_SRATE].value);
- switch (hdw->controls[PVR2_CID_SRATE].value) {
+ hdw->srate_val);
+ switch (hdw->srate_val) {
default:
- case PVR2_CVAL_SRATE_48:
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
val = 48000;
break;
- case PVR2_CVAL_SRATE_44_1:
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
val = 44100;
break;
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+ val = 32000;
+ break;
}
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
}
@@ -106,7 +108,7 @@ static void set_audio(struct pvr2_v4l_decoder *ctxt)
static int check_audio(struct pvr2_v4l_decoder *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->controls[PVR2_CID_SRATE].dirty != 0;
+ return hdw->srate_dirty != 0;
}
@@ -124,8 +126,8 @@ static const struct pvr2_v4l_decoder_ops decoder_ops[] = {
static void decoder_detach(struct pvr2_v4l_decoder *ctxt)
{
- ctxt->client->handler = 0;
- ctxt->hdw->decoder_ctrl = 0;
+ ctxt->client->handler = NULL;
+ ctxt->hdw->decoder_ctrl = NULL;
kfree(ctxt);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index 79334980c..2413e5198 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -48,25 +48,24 @@ struct pvr2_v4l_wm8775 {
static void set_input(struct pvr2_v4l_wm8775 *ctxt)
{
- struct v4l2_audio inp;
+ struct v4l2_routing route;
struct pvr2_hdw *hdw = ctxt->hdw;
int msk = 0;
- memset(&inp,0,sizeof(inp));
+ memset(&route,0,sizeof(route));
pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)",
- hdw->controls[PVR2_CID_INPUT].value,msk);
+ hdw->input_val,msk);
// Always point to input #1 no matter what
- inp.index = 2;
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_AUDIO,&inp);
+ route.input = 2;
+ pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
}
-
static int check_input(struct pvr2_v4l_wm8775 *ctxt)
{
struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->controls[PVR2_CID_INPUT].dirty != 0;
+ return hdw->input_dirty != 0;
}
@@ -90,7 +89,7 @@ static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt,
static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt)
{
- ctxt->client->handler = 0;
+ ctxt->client->handler = NULL;
kfree(ctxt);
}