From 4b065a8018a42e1e0345298dc04c33e831695664 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Feb 2009 14:32:50 +0100 Subject: vino: convert to video_ioctl2. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 490 ++++++++++++++------------------------- 1 file changed, 173 insertions(+), 317 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 349ef053f..357f81f62 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -2888,35 +2888,7 @@ static int vino_find_data_format(__u32 pixelformat) return VINO_DATA_FMT_NONE; } -static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) -{ - int data_norm = VINO_DATA_NORM_NONE; - unsigned long flags; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch(vcs->input) { - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - if (index == 0) { - data_norm = VINO_DATA_NORM_PAL; - } else if (index == 1) { - data_norm = VINO_DATA_NORM_NTSC; - } else if (index == 2) { - data_norm = VINO_DATA_NORM_SECAM; - } - break; - case VINO_INPUT_D1: - if (index == 0) { - data_norm = VINO_DATA_NORM_D1; - } - break; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return data_norm; -} - -static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) +static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) { int input = VINO_INPUT_NONE; unsigned long flags; @@ -2995,7 +2967,8 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) /* V4L2 ioctls */ -static void vino_v4l2_querycap(struct v4l2_capability *cap) +static int vino_querycap(struct file *file, void *__fh, + struct v4l2_capability *cap) { memset(cap, 0, sizeof(struct v4l2_capability)); @@ -3007,16 +2980,18 @@ static void vino_v4l2_querycap(struct v4l2_capability *cap) V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE + return 0; } -static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, +static int vino_enum_input(struct file *file, void *__fh, struct v4l2_input *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index = i->index; int input; dprintk("requested index = %d\n", index); - input = vino_enum_input(vcs, index); + input = vino_int_enum_input(vcs, index); if (input == VINO_INPUT_NONE) return -EINVAL; @@ -3038,9 +3013,10 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_input(struct vino_channel_settings *vcs, +static int vino_g_input(struct file *file, void *__fh, unsigned int *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index; int input; unsigned long flags; @@ -3061,52 +3037,24 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_input(struct vino_channel_settings *vcs, - unsigned int *i) +static int vino_s_input(struct file *file, void *__fh, + unsigned int i) { + struct vino_channel_settings *vcs = video_drvdata(file); int input; - dprintk("requested input = %d\n", *i); + dprintk("requested input = %d\n", i); - input = vino_enum_input(vcs, *i); + input = vino_int_enum_input(vcs, i); if (input == VINO_INPUT_NONE) return -EINVAL; return vino_set_input(vcs, input); } -static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, - struct v4l2_standard *s) -{ - int index = s->index; - int data_norm; - - data_norm = vino_enum_data_norm(vcs, index); - dprintk("standard index = %d\n", index); - - if (data_norm == VINO_DATA_NORM_NONE) - return -EINVAL; - - dprintk("standard name = %s\n", - vino_data_norms[data_norm].description); - - memset(s, 0, sizeof(struct v4l2_standard)); - s->index = index; - - s->id = vino_data_norms[data_norm].std; - s->frameperiod.numerator = 1; - s->frameperiod.denominator = - vino_data_norms[data_norm].fps_max; - s->framelines = - vino_data_norms[data_norm].framelines; - strcpy(s->name, - vino_data_norms[data_norm].description); - - return 0; -} - -static int vino_v4l2_querystd(struct vino_channel_settings *vcs, +static int vino_querystd(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int err = 0; @@ -3142,9 +3090,10 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_std(struct vino_channel_settings *vcs, +static int vino_g_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -3157,9 +3106,10 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_std(struct vino_channel_settings *vcs, +static int vino_s_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int ret = 0; @@ -3211,185 +3161,152 @@ out: return ret; } -static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs, +static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_fmtdesc *fd) { enum v4l2_buf_type type = fd->type; int index = fd->index; + dprintk("format index = %d\n", index); - switch (fd->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if ((fd->index < 0) || - (fd->index >= VINO_DATA_FMT_COUNT)) - return -EINVAL; - dprintk("format name = %s\n", - vino_data_formats[index].description); - - memset(fd, 0, sizeof(struct v4l2_fmtdesc)); - fd->index = index; - fd->type = type; - fd->pixelformat = vino_data_formats[index].pixelformat; - strcpy(fd->description, vino_data_formats[index].description); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: + if ((fd->index < 0) || + (fd->index >= VINO_DATA_FMT_COUNT)) return -EINVAL; - } - + dprintk("format name = %s\n", + vino_data_formats[index].description); + + memset(fd, 0, sizeof(struct v4l2_fmtdesc)); + fd->index = index; + fd->type = type; + fd->pixelformat = vino_data_formats[index].pixelformat; + strcpy(fd->description, vino_data_formats[index].description); return 0; } -static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, +static int vino_try_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); struct vino_channel_settings tempvcs; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; + dprintk("requested: w = %d, h = %d\n", + pf->width, pf->height); - dprintk("requested: w = %d, h = %d\n", - pf->width, pf->height); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - tempvcs.data_format = vino_find_data_format(pf->pixelformat); - if (tempvcs.data_format == VINO_DATA_FMT_NONE) { - tempvcs.data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[tempvcs.data_format]. - pixelformat; - } + tempvcs.data_format = vino_find_data_format(pf->pixelformat); + if (tempvcs.data_format == VINO_DATA_FMT_NONE) { + tempvcs.data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[tempvcs.data_format]. + pixelformat; + } - /* data format must be set before clipping/scaling */ - vino_set_scaling(&tempvcs, pf->width, pf->height); + /* data format must be set before clipping/scaling */ + vino_set_scaling(&tempvcs, pf->width, pf->height); - dprintk("data format = %s\n", - vino_data_formats[tempvcs.data_format].description); + dprintk("data format = %s\n", + vino_data_formats[tempvcs.data_format].description); - pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / - tempvcs.decimation; - pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; + pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / + tempvcs.decimation; + pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = tempvcs.line_size; - pf->sizeimage = tempvcs.line_size * - (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; - pf->colorspace = - vino_data_formats[tempvcs.data_format].colorspace; - - pf->priv = 0; - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = tempvcs.line_size; + pf->sizeimage = tempvcs.line_size * + (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; + pf->colorspace = + vino_data_formats[tempvcs.data_format].colorspace; + pf->priv = 0; return 0; } -static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, +static int vino_g_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - pf->width = (vcs->clipping.right - vcs->clipping.left) / - vcs->decimation; - pf->height = (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->pixelformat = - vino_data_formats[vcs->data_format].pixelformat; + pf->width = (vcs->clipping.right - vcs->clipping.left) / + vcs->decimation; + pf->height = (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->pixelformat = + vino_data_formats[vcs->data_format].pixelformat; - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - pf->priv = 0; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, +static int vino_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); int data_format; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - data_format = vino_find_data_format(pf->pixelformat); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (data_format == VINO_DATA_FMT_NONE) { - vcs->data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[vcs->data_format]. - pixelformat; - } else { - vcs->data_format = data_format; - } + data_format = vino_find_data_format(pf->pixelformat); - /* data format must be set before clipping/scaling */ - vino_set_scaling(vcs, pf->width, pf->height); + if (data_format == VINO_DATA_FMT_NONE) { + vcs->data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[vcs->data_format]. + pixelformat; + } else { + vcs->data_format = data_format; + } - dprintk("data format = %s\n", - vino_data_formats[vcs->data_format].description); + /* data format must be set before clipping/scaling */ + vino_set_scaling(vcs, pf->width, pf->height); - pf->width = vcs->clipping.right - vcs->clipping.left; - pf->height = vcs->clipping.bottom - vcs->clipping.top; + dprintk("data format = %s\n", + vino_data_formats[vcs->data_format].description); - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->width = vcs->clipping.right - vcs->clipping.left; + pf->height = vcs->clipping.bottom - vcs->clipping.top; - pf->priv = 0; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, +static int vino_cropcap(struct file *file, void *__fh, struct v4l2_cropcap *ccap) { + struct vino_channel_settings *vcs = video_drvdata(file); const struct vino_data_norm *norm; unsigned long flags; @@ -3419,9 +3336,10 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, +static int vino_g_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3443,9 +3361,10 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, +static int vino_s_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3465,9 +3384,10 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, +static int vino_g_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3495,9 +3415,10 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, +static int vino_s_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3528,9 +3449,10 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, +static int vino_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *rb) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3610,9 +3532,10 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, fb->id, fb->size, fb->data_size, fb->offset); } -static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, +static int vino_querybuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3645,9 +3568,10 @@ static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, +static int vino_qbuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3683,10 +3607,11 @@ static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, - struct v4l2_buffer *b, - unsigned int nonblocking) +static int vino_dqbuf(struct file *file, void *__fh, + struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); + unsigned int nonblocking = file->f_flags & O_NONBLOCK; if (vcs->reading) return -EBUSY; @@ -3758,8 +3683,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_streamon(struct vino_channel_settings *vcs) +static int vino_streamon(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned int incoming; int ret; if (vcs->reading) @@ -3796,8 +3723,10 @@ static int vino_v4l2_streamon(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) +static int vino_streamoff(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3810,9 +3739,10 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, +static int vino_queryctrl(struct file *file, void *__fh, struct v4l2_queryctrl *queryctrl) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3859,9 +3789,10 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, +static int vino_g_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3932,9 +3863,10 @@ out: return err; } -static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, +static int vino_s_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -4241,112 +4173,6 @@ error: return ret; } -static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - -#ifdef VINO_DEBUG - switch (_IOC_TYPE(cmd)) { - case 'v': - dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); - break; - case 'V': - dprintk("ioctl(): V4L2 %s (0x%08x)\n", - v4l2_ioctl_names[_IOC_NR(cmd)], cmd); - break; - default: - dprintk("ioctl(): unsupported command 0x%08x\n", cmd); - } -#endif - - switch (cmd) { - /* V4L2 interface */ - case VIDIOC_QUERYCAP: { - vino_v4l2_querycap(arg); - break; - } - case VIDIOC_ENUMINPUT: { - return vino_v4l2_enuminput(vcs, arg); - } - case VIDIOC_G_INPUT: { - return vino_v4l2_g_input(vcs, arg); - } - case VIDIOC_S_INPUT: { - return vino_v4l2_s_input(vcs, arg); - } - case VIDIOC_ENUMSTD: { - return vino_v4l2_enumstd(vcs, arg); - } - case VIDIOC_QUERYSTD: { - return vino_v4l2_querystd(vcs, arg); - } - case VIDIOC_G_STD: { - return vino_v4l2_g_std(vcs, arg); - } - case VIDIOC_S_STD: { - return vino_v4l2_s_std(vcs, arg); - } - case VIDIOC_ENUM_FMT: { - return vino_v4l2_enum_fmt(vcs, arg); - } - case VIDIOC_TRY_FMT: { - return vino_v4l2_try_fmt(vcs, arg); - } - case VIDIOC_G_FMT: { - return vino_v4l2_g_fmt(vcs, arg); - } - case VIDIOC_S_FMT: { - return vino_v4l2_s_fmt(vcs, arg); - } - case VIDIOC_CROPCAP: { - return vino_v4l2_cropcap(vcs, arg); - } - case VIDIOC_G_CROP: { - return vino_v4l2_g_crop(vcs, arg); - } - case VIDIOC_S_CROP: { - return vino_v4l2_s_crop(vcs, arg); - } - case VIDIOC_G_PARM: { - return vino_v4l2_g_parm(vcs, arg); - } - case VIDIOC_S_PARM: { - return vino_v4l2_s_parm(vcs, arg); - } - case VIDIOC_REQBUFS: { - return vino_v4l2_reqbufs(vcs, arg); - } - case VIDIOC_QUERYBUF: { - return vino_v4l2_querybuf(vcs, arg); - } - case VIDIOC_QBUF: { - return vino_v4l2_qbuf(vcs, arg); - } - case VIDIOC_DQBUF: { - return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK); - } - case VIDIOC_STREAMON: { - return vino_v4l2_streamon(vcs); - } - case VIDIOC_STREAMOFF: { - return vino_v4l2_streamoff(vcs); - } - case VIDIOC_QUERYCTRL: { - return vino_v4l2_queryctrl(vcs, arg); - } - case VIDIOC_G_CTRL: { - return vino_v4l2_g_ctrl(vcs, arg); - } - case VIDIOC_S_CTRL: { - return vino_v4l2_s_ctrl(vcs, arg); - } - default: - return -ENOIOCTLCMD; - } - - return 0; -} - static long vino_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -4356,7 +4182,7 @@ static long vino_ioctl(struct file *file, if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; - ret = video_usercopy(file, cmd, arg, vino_do_ioctl); + ret = video_ioctl2(file, cmd, arg); mutex_unlock(&vcs->mutex); @@ -4368,6 +4194,34 @@ static long vino_ioctl(struct file *file, /* __initdata */ static int vino_init_stage; +const struct v4l2_ioctl_ops vino_ioctl_ops = { + .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap, + .vidioc_querycap = vino_querycap, + .vidioc_enum_input = vino_enum_input, + .vidioc_g_input = vino_g_input, + .vidioc_s_input = vino_s_input, + .vidioc_g_std = vino_g_std, + .vidioc_s_std = vino_s_std, + .vidioc_querystd = vino_querystd, + .vidioc_cropcap = vino_cropcap, + .vidioc_s_crop = vino_s_crop, + .vidioc_g_crop = vino_g_crop, + .vidioc_s_parm = vino_s_parm, + .vidioc_g_parm = vino_g_parm, + .vidioc_reqbufs = vino_reqbufs, + .vidioc_querybuf = vino_querybuf, + .vidioc_qbuf = vino_qbuf, + .vidioc_dqbuf = vino_dqbuf, + .vidioc_streamon = vino_streamon, + .vidioc_streamoff = vino_streamoff, + .vidioc_queryctrl = vino_queryctrl, + .vidioc_g_ctrl = vino_g_ctrl, + .vidioc_s_ctrl = vino_s_ctrl, +}; + static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, @@ -4380,6 +4234,8 @@ static const struct v4l2_file_operations vino_fops = { static struct video_device v4l_device_template = { .name = "NOT SET", .fops = &vino_fops, + .ioctl_ops = &vino_ioctl_ops, + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, .minor = -1, }; -- cgit v1.2.3 From 6b667a7c08554109a944d6816a8f7a50b65492fe Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Feb 2009 15:31:13 +0100 Subject: vino: minor renames From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 357f81f62..bdd035cf9 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -289,7 +289,7 @@ struct vino_channel_settings { struct vino_interrupt_data int_data; /* V4L support */ - struct video_device *v4l_device; + struct video_device *vdev; }; struct vino_client { @@ -347,8 +347,8 @@ static struct vino_settings *vino_drvdata; static const char *vino_driver_name = "vino"; static const char *vino_driver_description = "SGI VINO"; static const char *vino_bus_name = "GIO64 bus"; -static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; -static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; +static const char *vino_vdev_name_a = "SGI VINO Channel A"; +static const char *vino_vdev_name_b = "SGI VINO Channel B"; static void vino_capture_tasklet(unsigned long channel); @@ -4231,7 +4231,7 @@ static const struct v4l2_file_operations vino_fops = { .poll = vino_poll, }; -static struct video_device v4l_device_template = { +static struct video_device vdev_template = { .name = "NOT SET", .fops = &vino_fops, .ioctl_ops = &vino_ioctl_ops, @@ -4243,24 +4243,24 @@ static void vino_module_cleanup(int stage) { switch(stage) { case 10: - video_unregister_device(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + video_unregister_device(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; case 9: - video_unregister_device(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; + video_unregister_device(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; case 8: vino_i2c_del_bus(); case 7: free_irq(SGI_VINO_IRQ, NULL); case 6: - if (vino_drvdata->b.v4l_device) { - video_device_release(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + if (vino_drvdata->b.vdev) { + video_device_release(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; } case 5: - if (vino_drvdata->a.v4l_device) { - video_device_release(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; + if (vino_drvdata->a.vdev) { + video_device_release(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; } case 4: /* all entries in dma_cpu dummy table have the same address */ @@ -4402,19 +4402,19 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, spin_lock_init(&vcs->fb_queue.queue_lock); init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); - vcs->v4l_device = video_device_alloc(); - if (!vcs->v4l_device) { + vcs->vdev = video_device_alloc(); + if (!vcs->vdev) { vino_module_cleanup(vino_init_stage); return -ENOMEM; } vino_init_stage++; - memcpy(vcs->v4l_device, &v4l_device_template, + memcpy(vcs->vdev, &vdev_template, sizeof(struct video_device)); - strcpy(vcs->v4l_device->name, name); - vcs->v4l_device->release = video_device_release; + strcpy(vcs->vdev->name, name); + vcs->vdev->release = video_device_release; - video_set_drvdata(vcs->v4l_device, vcs); + video_set_drvdata(vcs->vdev, vcs); return 0; } @@ -4440,12 +4440,12 @@ static int __init vino_module_init(void) spin_lock_init(&vino_drvdata->input_lock); ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A, - vino_v4l_device_name_a); + vino_vdev_name_a); if (ret) return ret; ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B, - vino_v4l_device_name_b); + vino_vdev_name_b); if (ret) return ret; @@ -4469,7 +4469,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = video_register_device(vino_drvdata->a.v4l_device, + ret = video_register_device(vino_drvdata->a.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel A Video4Linux-device " @@ -4479,7 +4479,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = video_register_device(vino_drvdata->b.v4l_device, + ret = video_register_device(vino_drvdata->b.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel B Video4Linux-device " -- cgit v1.2.3 From 33161971ac895973f70bb79980c85248ebfb7699 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 11:31:05 +0100 Subject: saa7191: convert to v4l2-i2c-drv-legacy.h From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7191.c | 161 +++++++++++++++--------------------- 1 file changed, 67 insertions(+), 94 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index c4f169c95..f8313aa44 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "compat.h" #include "saa7191.h" @@ -33,6 +35,10 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + // #define SAA7191_DEBUG #ifdef SAA7191_DEBUG @@ -55,8 +61,6 @@ struct saa7191 { int norm; }; -static struct i2c_driver i2c_driver_saa7191; - static const u8 initseq[] = { 0, /* Subaddress */ @@ -562,83 +566,6 @@ static int saa7191_set_control(struct i2c_client *client, /* I2C-interface */ -static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) -{ - int err = 0; - struct saa7191 *decoder; - struct i2c_client *client; - - printk(KERN_INFO "Philips SAA7191 driver version %s\n", - SAA7191_MODULE_VERSION); - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return -ENOMEM; - decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); - if (!decoder) { - err = -ENOMEM; - goto out_free_client; - } - - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_saa7191; - client->flags = 0; - strcpy(client->name, "saa7191 client"); - i2c_set_clientdata(client, decoder); - - decoder->client = client; - - err = i2c_attach_client(client); - if (err) - goto out_free_decoder; - - err = saa7191_write_block(client, sizeof(initseq), initseq); - if (err) { - printk(KERN_ERR "SAA7191 initialization failed\n"); - goto out_detach_client; - } - - printk(KERN_INFO "SAA7191 initialized\n"); - - decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_PAL; - - err = saa7191_autodetect_norm(client); - if (err && (err != -EBUSY)) { - printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); - } - - return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_decoder: - kfree(decoder); -out_free_client: - kfree(client); - return err; -} - -static int saa7191_probe(struct i2c_adapter *adap) -{ - /* Always connected to VINO */ - if (adap->id == I2C_HW_SGI_VINO) - return saa7191_attach(adap, SAA7191_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; -} - -static int saa7191_detach(struct i2c_client *client) -{ - struct saa7191 *decoder = i2c_get_clientdata(client); - - i2c_detach_client(client); - kfree(decoder); - kfree(client); - return 0; -} - static int saa7191_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -784,25 +711,71 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, return 0; } -static struct i2c_driver i2c_driver_saa7191 = { - .driver = { - .name = "saa7191", - }, - .id = I2C_DRIVERID_SAA7191, - .attach_adapter = saa7191_probe, - .detach_client = saa7191_detach, - .command = saa7191_command -}; +static int saa7191_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err = 0; + struct saa7191 *decoder; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); -static int saa7191_init(void) + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; + + i2c_set_clientdata(client, decoder); + + decoder->client = client; + + err = saa7191_write_block(client, sizeof(initseq), initseq); + if (err) { + printk(KERN_ERR "SAA7191 initialization failed\n"); + kfree(decoder); + return err; + } + + printk(KERN_INFO "SAA7191 initialized\n"); + + decoder->input = SAA7191_INPUT_COMPOSITE; + decoder->norm = SAA7191_NORM_PAL; + + err = saa7191_autodetect_norm(client); + if (err && (err != -EBUSY)) + printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); + + return 0; +} + +static int saa7191_remove(struct i2c_client *client) { - return i2c_add_driver(&i2c_driver_saa7191); + struct saa7191 *decoder = i2c_get_clientdata(client); + + kfree(decoder); + return 0; } -static void saa7191_exit(void) +static int saa7191_legacy_probe(struct i2c_adapter *adapter) { - i2c_del_driver(&i2c_driver_saa7191); + return adapter->id == I2C_HW_SGI_VINO; } -module_init(saa7191_init); -module_exit(saa7191_exit); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7191_id[] = { + { "saa7191", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7191_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7191", + .driverid = I2C_DRIVERID_SAA7191, + .command = saa7191_command, + .probe = saa7191_probe, + .remove = saa7191_remove, + .legacy_probe = saa7191_legacy_probe, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7191_id, +#endif +}; -- cgit v1.2.3 From 9c0e40e186e68445ec869433c25a88c2eb4a7229 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 27 Feb 2009 13:05:10 +0100 Subject: vino/indycam/saa7191: convert to i2c modules to V4L2. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/indycam.c | 236 +++++++-------------- linux/drivers/media/video/indycam.h | 19 +- linux/drivers/media/video/saa7191.c | 228 ++++++--------------- linux/drivers/media/video/saa7191.h | 26 +-- linux/drivers/media/video/vino.c | 396 ++++++++++-------------------------- 5 files changed, 259 insertions(+), 646 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c index 84b9e4f2b..492f1e6cb 100644 --- a/linux/drivers/media/video/indycam.c +++ b/linux/drivers/media/video/indycam.c @@ -19,10 +19,11 @@ #include #include -#include /* IndyCam decodes stream of photons into digital image representation ;-) */ -#include +#include #include +#include +#include #include "indycam.h" @@ -33,6 +34,10 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + // #define INDYCAM_DEBUG #ifdef INDYCAM_DEBUG @@ -48,8 +53,6 @@ struct indycam { u8 version; }; -static struct i2c_driver i2c_driver_indycam; - static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ @@ -138,44 +141,44 @@ static void indycam_regdump_debug(struct i2c_client *client) #endif static int indycam_get_control(struct i2c_client *client, - struct indycam_control *ctrl) + struct v4l2_control *ctrl) { struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) return -EIO; - if (ctrl->type == INDYCAM_CONTROL_AGC) + if (ctrl->id == V4L2_CID_AUTOGAIN) ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) ? 1 : 0; else ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) ? 1 : 0; break; - case INDYCAM_CONTROL_SHUTTER: + case V4L2_CID_EXPOSURE: ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); if (ret) return -EIO; ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); break; - case INDYCAM_CONTROL_GAIN: + case V4L2_CID_GAIN: ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_RED_BALANCE: + case V4L2_CID_RED_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_BLUE_BALANCE: + case V4L2_CID_BLUE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; @@ -195,7 +198,7 @@ static int indycam_get_control(struct i2c_client *client, return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_read_reg(client, INDYCAM_REG_GAMMA, ®); @@ -214,20 +217,20 @@ static int indycam_get_control(struct i2c_client *client, } static int indycam_set_control(struct i2c_client *client, - struct indycam_control *ctrl) + struct v4l2_control *ctrl) { struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) break; - if (ctrl->type == INDYCAM_CONTROL_AGC) { + if (ctrl->id == V4L2_CID_AUTOGAIN) { if (ctrl->value) reg |= INDYCAM_CONTROL_AGCENA; else @@ -241,18 +244,18 @@ static int indycam_set_control(struct i2c_client *client, ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); break; - case INDYCAM_CONTROL_SHUTTER: + case V4L2_CID_EXPOSURE: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); break; - case INDYCAM_CONTROL_GAIN: + case V4L2_CID_GAIN: ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); break; - case INDYCAM_CONTROL_RED_BALANCE: + case V4L2_CID_RED_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, ctrl->value); break; - case INDYCAM_CONTROL_BLUE_BALANCE: + case V4L2_CID_BLUE_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; @@ -264,7 +267,7 @@ static int indycam_set_control(struct i2c_client *client, ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, ctrl->value); @@ -279,44 +282,50 @@ static int indycam_set_control(struct i2c_client *client, /* I2C-interface */ -static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) +static int indycam_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + /* The old video_decoder interface just isn't enough, + * so we'll use some custom commands. */ + switch (cmd) { + case VIDIOC_G_CTRL: + return indycam_get_control(client, arg); + + case VIDIOC_S_CTRL: + return indycam_set_control(client, arg); + + default: + return -EINVAL; + } + + return 0; +} + +static int indycam_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int err = 0; struct indycam *camera; - struct i2c_client *client; - printk(KERN_INFO "SGI IndyCam driver version %s\n", - INDYCAM_MODULE_VERSION); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; camera = kzalloc(sizeof(struct indycam), GFP_KERNEL); - if (!camera) { - err = -ENOMEM; - goto out_free_client; - } + if (!camera) + return -ENOMEM; - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_indycam; - client->flags = 0; - strcpy(client->name, "IndyCam client"); i2c_set_clientdata(client, camera); camera->client = client; - err = i2c_attach_client(client); - if (err) - goto out_free_camera; - camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { - err = -ENODEV; - goto out_detach_client; + kfree(camera); + return -ENODEV; } + printk(KERN_INFO "IndyCam v%d.%d detected\n", INDYCAM_VERSION_MAJOR(camera->version), INDYCAM_VERSION_MINOR(camera->version)); @@ -327,8 +336,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initialization failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } indycam_regdump(client); @@ -338,8 +347,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { printk(KERN_ERR "IndyCam: White balancing camera failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } indycam_regdump(client); @@ -347,124 +356,37 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) printk(KERN_INFO "IndyCam initialized\n"); return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_camera: - kfree(camera); -out_free_client: - kfree(client); - return err; } -static int indycam_probe(struct i2c_adapter *adap) -{ - /* Indy specific crap */ - if (adap->id == I2C_HW_SGI_VINO) - return indycam_attach(adap, INDYCAM_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; -} - -static int indycam_detach(struct i2c_client *client) +static int indycam_remove(struct i2c_client *client) { struct indycam *camera = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(camera); - kfree(client); return 0; } -static int indycam_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int indycam_legacy_probe(struct i2c_adapter *adapter) { - // struct indycam *camera = i2c_get_clientdata(client); - - /* The old video_decoder interface just isn't enough, - * so we'll use some custom commands. */ - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_NTSC; - cap->inputs = 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; - - *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC | - DECODER_STATUS_COLOR; - break; - } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_NTSC: - break; - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - // struct video_picture *pic = arg; - /* TODO: convert values for indycam_set_controls() */ - break; - } - case DECODER_INDYCAM_GET_CONTROL: { - return indycam_get_control(client, arg); - } - case DECODER_INDYCAM_SET_CONTROL: { - return indycam_set_control(client, arg); - } - default: - return -EINVAL; - } - - return 0; + return adapter->id == I2C_HW_SGI_VINO; } -static struct i2c_driver i2c_driver_indycam = { - .driver = { - .name = "indycam", - }, - .id = I2C_DRIVERID_INDYCAM, - .attach_adapter = indycam_probe, - .detach_client = indycam_detach, - .command = indycam_command, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id indycam_id[] = { + { "indycam", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, indycam_id); -static int __init indycam_init(void) -{ - return i2c_add_driver(&i2c_driver_indycam); -} - -static void __exit indycam_exit(void) -{ - i2c_del_driver(&i2c_driver_indycam); -} - -module_init(indycam_init); -module_exit(indycam_exit); +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "indycam", + .driverid = I2C_DRIVERID_INDYCAM, + .command = indycam_command, + .probe = indycam_probe, + .remove = indycam_remove, + .legacy_probe = indycam_legacy_probe, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = indycam_id, +#endif +}; diff --git a/linux/drivers/media/video/indycam.h b/linux/drivers/media/video/indycam.h index e6ee82063..881f21c47 100644 --- a/linux/drivers/media/video/indycam.h +++ b/linux/drivers/media/video/indycam.h @@ -87,22 +87,7 @@ /* Driver interface definitions */ -#define INDYCAM_CONTROL_AGC 0 /* boolean */ -#define INDYCAM_CONTROL_AWB 1 /* boolean */ -#define INDYCAM_CONTROL_SHUTTER 2 -#define INDYCAM_CONTROL_GAIN 3 -#define INDYCAM_CONTROL_RED_BALANCE 4 -#define INDYCAM_CONTROL_BLUE_BALANCE 5 -#define INDYCAM_CONTROL_RED_SATURATION 6 -#define INDYCAM_CONTROL_BLUE_SATURATION 7 -#define INDYCAM_CONTROL_GAMMA 8 - -struct indycam_control { - u8 type; - s32 value; -}; - -#define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) -#define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) +#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0) +#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1) #endif diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index f8313aa44..2c4c8ac5c 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include #include #include @@ -58,7 +57,7 @@ struct saa7191 { u8 reg[25]; int input; - int norm; + v4l2_std_id norm; }; static const u8 initseq[] = { @@ -192,7 +191,7 @@ static int saa7191_set_input(struct i2c_client *client, int input) return 0; } -static int saa7191_set_norm(struct i2c_client *client, int norm) +static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) { struct saa7191 *decoder = i2c_get_clientdata(client); u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); @@ -200,24 +199,20 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); int err; - switch(norm) { - case SAA7191_NORM_PAL: + if (norm & V4L2_STD_PAL) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - case SAA7191_NORM_NTSC: + } else if (norm & V4L2_STD_NTSC) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~SAA7191_CTL3_AUFD; ctl3 |= SAA7191_CTL3_FSEL; chcv = SAA7191_CHCV_NTSC; - break; - case SAA7191_NORM_SECAM: + } else if (norm & V4L2_STD_SECAM) { stdc |= SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - default: + } else { return -EINVAL; } @@ -235,7 +230,7 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, stdc, chcv); - dprintk("norm: %d\n", norm); + dprintk("norm: %llx\n", norm); return 0; } @@ -263,15 +258,19 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) return -EBUSY; } -static int saa7191_autodetect_norm_extended(struct i2c_client *client) +static int saa7191_autodetect_norm_extended(struct i2c_client *client, + v4l2_std_id *norm) { + struct saa7191 *decoder = i2c_get_clientdata(client); u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); u8 status; + v4l2_std_id old_norm = decoder->norm; int err = 0; dprintk("SAA7191 extended signal auto-detection...\n"); + *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); @@ -302,14 +301,15 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60Hz signal -> NTSC */ dprintk("60Hz signal: NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + *norm = V4L2_STD_NTSC; + return 0; } /* 50Hz signal */ dprintk("50Hz signal: Trying PAL...\n"); /* try PAL first */ - err = saa7191_set_norm(client, SAA7191_NORM_PAL); + err = saa7191_set_norm(client, V4L2_STD_PAL); if (err) goto out; @@ -322,20 +322,20 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - err = -EAGAIN; - goto out; + saa7191_set_norm(client, old_norm); + return -EAGAIN; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); - return 0; + *norm = V4L2_STD_PAL; + return saa7191_set_norm(client, old_norm); } dprintk("No color detected with PAL - Trying SECAM...\n"); /* no color detected ? -> try SECAM */ - err = saa7191_set_norm(client, - SAA7191_NORM_SECAM); + err = saa7191_set_norm(client, V4L2_STD_SECAM); if (err) goto out; @@ -355,29 +355,14 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) if (status & SAA7191_STATUS_CODE) { /* Color detected -> SECAM */ dprintk("SECAM\n"); - return 0; + *norm = V4L2_STD_SECAM; + return saa7191_set_norm(client, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); - /* still no color detected ? - * -> set norm back to PAL */ - err = saa7191_set_norm(client, - SAA7191_NORM_PAL); - if (err) - goto out; - out: - ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - if (ctl3 & SAA7191_CTL3_AUFD) { - ctl3 &= ~(SAA7191_CTL3_AUFD); - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); - if (err) { - err = -EIO; - } - } - - return err; + return saa7191_set_norm(client, old_norm); } static int saa7191_autodetect_norm(struct i2c_client *client) @@ -404,26 +389,26 @@ static int saa7191_autodetect_norm(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60hz signal -> NTSC */ dprintk("NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + return saa7191_set_norm(client, V4L2_STD_NTSC); } else { /* 50hz signal -> PAL */ dprintk("PAL\n"); - return saa7191_set_norm(client, SAA7191_NORM_PAL); + return saa7191_set_norm(client, V4L2_STD_PAL); } } static int saa7191_get_control(struct i2c_client *client, - struct saa7191_control *ctrl) + struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) >> SAA7191_LUMA_BPSS_SHIFT; @@ -441,13 +426,13 @@ static int saa7191_get_control(struct i2c_client *client, case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) >> SAA7191_GAIN_LFIS_SHIFT; break; - case SAA7191_CONTROL_HUE: + case V4L2_CID_HUE: reg = saa7191_read_reg(client, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; @@ -479,17 +464,17 @@ static int saa7191_get_control(struct i2c_client *client, } static int saa7191_set_control(struct i2c_client *client, - struct saa7191_control *ctrl) + struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) @@ -511,7 +496,7 @@ static int saa7191_set_control(struct i2c_client *client, case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; else @@ -523,7 +508,7 @@ static int saa7191_set_control(struct i2c_client *client, } ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); break; - case SAA7191_CONTROL_HUE: + case V4L2_CID_HUE: reg = ctrl->value & 0xff; if (reg < 0x80) reg += 0x80; @@ -569,141 +554,42 @@ static int saa7191_set_control(struct i2c_client *client, static int saa7191_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7191 *decoder = i2c_get_clientdata(client); - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; - cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; + case VIDIOC_INT_G_INPUT_STATUS: { + u32 *iarg = arg; u8 status; - int res = 0; + int res = V4L2_IN_ST_NO_SIGNAL; - if (saa7191_read_status(client, &status)) { + if (saa7191_read_status(client, &status)) return -EIO; - } if ((status & SAA7191_STATUS_HLCK) == 0) - res |= DECODER_STATUS_GOOD; - if (status & SAA7191_STATUS_CODE) - res |= DECODER_STATUS_COLOR; - switch (decoder->norm) { - case SAA7191_NORM_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case SAA7191_NORM_PAL: - res |= DECODER_STATUS_PAL; - break; - case SAA7191_NORM_SECAM: - res |= DECODER_STATUS_SECAM; - break; - case SAA7191_NORM_AUTO: - default: - if (status & SAA7191_STATUS_FIDT) - res |= DECODER_STATUS_NTSC; - else - res |= DECODER_STATUS_PAL; - break; - } + res = 0; + if (!(status & SAA7191_STATUS_CODE)) + res |= V4L2_IN_ST_NO_COLOR; *iarg = res; break; } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_AUTO: - return saa7191_autodetect_norm(client); - case VIDEO_MODE_PAL: - return saa7191_set_norm(client, SAA7191_NORM_PAL); - case VIDEO_MODE_NTSC: - return saa7191_set_norm(client, SAA7191_NORM_NTSC); - case VIDEO_MODE_SECAM: - return saa7191_set_norm(client, SAA7191_NORM_SECAM); - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - switch (client->adapter->id) { - case I2C_HW_SGI_VINO: - return saa7191_set_input(client, *iarg); - default: - if (*iarg != 0) - return -EINVAL; - } - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - struct video_picture *pic = arg; - unsigned val; - int err; - - val = (pic->hue >> 8) - 0x80; + case VIDIOC_QUERYSTD: + return saa7191_autodetect_norm_extended(client, arg); - err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); - if (err) - return -EIO; + case VIDIOC_S_STD: { + v4l2_std_id *istd = arg; - break; + return saa7191_set_norm(client, *istd); } - case DECODER_SAA7191_GET_STATUS: { - struct saa7191_status *status = arg; - u8 status_reg; - - if (saa7191_read_status(client, &status_reg)) - return -EIO; - - status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) - ? 1 : 0; - status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) - ? 1 : 0; - status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; + case VIDIOC_INT_S_VIDEO_ROUTING: { + struct v4l2_routing *route = arg; - status->input = decoder->input; - status->norm = decoder->norm; - - break; + return saa7191_set_input(client, route->input); } - case DECODER_SAA7191_SET_NORM: { - int *norm = arg; - - switch (*norm) { - case SAA7191_NORM_AUTO: - return saa7191_autodetect_norm(client); - case SAA7191_NORM_AUTO_EXT: - return saa7191_autodetect_norm_extended(client); - default: - return saa7191_set_norm(client, *norm); - } - } - case DECODER_SAA7191_GET_CONTROL: { + + case VIDIOC_G_CTRL: return saa7191_get_control(client, arg); - } - case DECODER_SAA7191_SET_CONTROL: { + + case VIDIOC_S_CTRL: return saa7191_set_control(client, arg); - } + default: return -EINVAL; } @@ -738,7 +624,7 @@ static int saa7191_probe(struct i2c_client *client, printk(KERN_INFO "SAA7191 initialized\n"); decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_PAL; + decoder->norm = V4L2_STD_PAL; err = saa7191_autodetect_norm(client); if (err && (err != -EBUSY)) diff --git a/linux/drivers/media/video/saa7191.h b/linux/drivers/media/video/saa7191.h index a2310da19..803c74d60 100644 --- a/linux/drivers/media/video/saa7191.h +++ b/linux/drivers/media/video/saa7191.h @@ -176,11 +176,9 @@ #define SAA7191_INPUT_COMPOSITE 0 #define SAA7191_INPUT_SVIDEO 1 -#define SAA7191_NORM_AUTO 0 #define SAA7191_NORM_PAL 1 #define SAA7191_NORM_NTSC 2 #define SAA7191_NORM_SECAM 3 -#define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */ struct saa7191_status { /* 0=no signal, 1=signal detected */ @@ -232,24 +230,16 @@ struct saa7191_status { #define SAA7191_VNR_MAX 0x03 #define SAA7191_VNR_DEFAULT 0x00 -#define SAA7191_CONTROL_BANDPASS 0 -#define SAA7191_CONTROL_BANDPASS_WEIGHT 1 -#define SAA7191_CONTROL_CORING 2 -#define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */ -#define SAA7191_CONTROL_CHROMA_GAIN 4 -#define SAA7191_CONTROL_HUE 5 -#define SAA7191_CONTROL_VTRC 6 /* boolean */ -#define SAA7191_CONTROL_LUMA_DELAY 7 -#define SAA7191_CONTROL_VNR 8 - -struct saa7191_control { - u8 type; - s32 value; -}; +#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0) +#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1) +#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2) +#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3) +#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4) +#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5) +#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6) +#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7) #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) -#define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control) -#define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control) #endif diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index bdd035cf9..6b87a55a9 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -139,10 +138,6 @@ MODULE_LICENSE("GPL"); #define VINO_DATA_NORM_PAL 1 #define VINO_DATA_NORM_SECAM 2 #define VINO_DATA_NORM_D1 3 -/* The following are special entries that can be used to - * autodetect the norm. */ -#define VINO_DATA_NORM_AUTO 0xfe -#define VINO_DATA_NORM_AUTO_EXT 0xff #define VINO_DATA_NORM_COUNT 4 @@ -360,11 +355,11 @@ static const struct vino_input vino_inputs[] = { .name = "Composite", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "S-Video", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "D1/IndyCam", .std = V4L2_STD_NTSC, } @@ -376,17 +371,17 @@ static const struct vino_data_format vino_data_formats[] = { .bpp = 1, .pixelformat = V4L2_PIX_FMT_GREY, .colorspace = V4L2_COLORSPACE_SMPTE170M, - },{ + }, { .description = "8-bit dithered RGB 3-3-2", .bpp = 1, .pixelformat = V4L2_PIX_FMT_RGB332, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "32-bit RGB", .bpp = 4, .pixelformat = V4L2_PIX_FMT_RGB32, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "YUV 4:2:2", .bpp = 2, .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? @@ -417,7 +412,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_NTSC_HEIGHT / 2 - 1, .right = VINO_NTSC_WIDTH, }, - },{ + }, { .description = "PAL", .std = V4L2_STD_PAL, .fps_min = 5, @@ -439,7 +434,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "SECAM", .std = V4L2_STD_SECAM, .fps_min = 5, @@ -461,7 +456,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "NTSC/D1", .std = V4L2_STD_NTSC, .fps_min = 6, @@ -497,9 +492,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AGC_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AGC, 0 }, - },{ + }, { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Automatic White Balance", @@ -507,9 +500,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AWB_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AWB, 0 }, - },{ + }, { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", @@ -517,29 +508,23 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAIN_MAX, .step = 1, .default_value = INDYCAM_GAIN_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = INDYCAM_CONTROL_RED_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Saturation", .minimum = INDYCAM_RED_SATURATION_MIN, .maximum = INDYCAM_RED_SATURATION_MAX, .step = 1, .default_value = INDYCAM_RED_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = INDYCAM_CONTROL_BLUE_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Saturation", .minimum = INDYCAM_BLUE_SATURATION_MIN, .maximum = INDYCAM_BLUE_SATURATION_MAX, .step = 1, .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 }, - },{ + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Balance", @@ -547,9 +532,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_RED_BALANCE_MAX, .step = 1, .default_value = INDYCAM_RED_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Balance", @@ -557,9 +540,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_BLUE_BALANCE_MAX, .step = 1, .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Shutter Control", @@ -567,9 +548,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_SHUTTER_MAX, .step = 1, .default_value = INDYCAM_SHUTTER_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_SHUTTER, 0 }, - },{ + }, { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gamma", @@ -577,8 +556,6 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAMMA_MAX, .step = 1, .default_value = INDYCAM_GAMMA_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAMMA, 0 }, } }; @@ -593,88 +570,70 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { .maximum = SAA7191_HUE_MAX, .step = 1, .default_value = SAA7191_HUE_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_HUE, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = SAA7191_CONTROL_BANDPASS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass", .minimum = SAA7191_BANDPASS_MIN, .maximum = SAA7191_BANDPASS_MAX, .step = 1, .default_value = SAA7191_BANDPASS_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = SAA7191_CONTROL_BANDPASS_WEIGHT, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass Weight", .minimum = SAA7191_BANDPASS_WEIGHT_MIN, .maximum = SAA7191_BANDPASS_WEIGHT_MAX, .step = 1, .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 2, + }, { + .id = SAA7191_CONTROL_CORING, .type = V4L2_CTRL_TYPE_INTEGER, .name = "HF Luminance Coring", .minimum = SAA7191_CORING_MIN, .maximum = SAA7191_CORING_MAX, .step = 1, .default_value = SAA7191_CORING_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CORING, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 3, + }, { + .id = SAA7191_CONTROL_FORCE_COLOUR, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Force Colour", .minimum = SAA7191_FORCE_COLOUR_MIN, .maximum = SAA7191_FORCE_COLOUR_MAX, .step = 1, .default_value = SAA7191_FORCE_COLOUR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 4, + }, { + .id = SAA7191_CONTROL_CHROMA_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Chrominance Gain Control", .minimum = SAA7191_CHROMA_GAIN_MIN, .maximum = SAA7191_CHROMA_GAIN_MAX, .step = 1, .default_value = SAA7191_CHROMA_GAIN_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 5, + }, { + .id = SAA7191_CONTROL_VTRC, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "VTR Time Constant", .minimum = SAA7191_VTRC_MIN, .maximum = SAA7191_VTRC_MAX, .step = 1, .default_value = SAA7191_VTRC_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VTRC, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 6, + }, { + .id = SAA7191_CONTROL_LUMA_DELAY, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Delay Compensation", .minimum = SAA7191_LUMA_DELAY_MIN, .maximum = SAA7191_LUMA_DELAY_MAX, .step = 1, .default_value = SAA7191_LUMA_DELAY_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 7, + }, { + .id = SAA7191_CONTROL_VNR, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Vertical Noise Reduction", .minimum = SAA7191_VNR_MIN, .maximum = SAA7191_VNR_MAX, .step = 1, .default_value = SAA7191_VNR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VNR, 0 }, } }; @@ -2494,77 +2453,6 @@ static int vino_get_saa7191_input(int input) } } -static int vino_get_saa7191_norm(unsigned int data_norm) -{ - switch (data_norm) { - case VINO_DATA_NORM_AUTO: - return SAA7191_NORM_AUTO; - case VINO_DATA_NORM_AUTO_EXT: - return SAA7191_NORM_AUTO_EXT; - case VINO_DATA_NORM_PAL: - return SAA7191_NORM_PAL; - case VINO_DATA_NORM_NTSC: - return SAA7191_NORM_NTSC; - case VINO_DATA_NORM_SECAM: - return SAA7191_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_saa7191_norm(): " - "invalid norm!\n"); - return -1; - } -} - -static int vino_get_from_saa7191_norm(int saa7191_norm) -{ - switch (saa7191_norm) { - case SAA7191_NORM_PAL: - return VINO_DATA_NORM_PAL; - case SAA7191_NORM_NTSC: - return VINO_DATA_NORM_NTSC; - case SAA7191_NORM_SECAM: - return VINO_DATA_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): " - "invalid norm!\n"); - return VINO_DATA_NORM_NONE; - } -} - -static int vino_saa7191_set_norm(unsigned int *data_norm) -{ - int saa7191_norm, new_data_norm; - int err = 0; - - saa7191_norm = vino_get_saa7191_norm(*data_norm); - - err = i2c_decoder_command(DECODER_SAA7191_SET_NORM, - &saa7191_norm); - if (err) - goto out; - - if ((*data_norm == VINO_DATA_NORM_AUTO) - || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) { - struct saa7191_status status; - - err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS, - &status); - if (err) - goto out; - - new_data_norm = - vino_get_from_saa7191_norm(status.norm); - if (new_data_norm == VINO_DATA_NORM_NONE) { - err = -EINVAL; - goto out; - } - - *data_norm = (unsigned int)new_data_norm; - } - -out: - return err; -} - /* execute with input_lock locked */ static int vino_is_input_owner(struct vino_channel_settings *vcs) { @@ -2597,15 +2485,16 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) vcs->data_norm = VINO_DATA_NORM_D1; } else if (vino_drvdata->decoder.driver && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { - int input, data_norm; - int saa7191_input; + int input; + int data_norm; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; i2c_use_client(vino_drvdata->decoder.driver); input = VINO_INPUT_COMPOSITE; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); if (ret) { ret = -EINVAL; goto out; @@ -2616,12 +2505,15 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = i2c_decoder_command(VIDIOC_S_STD, &norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2688,11 +2580,11 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) if (vino_drvdata->decoder.owner == vcs->channel) { int data_norm; - int saa7191_input; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); if (ret) { vino_drvdata->decoder.owner = VINO_NO_CHANNEL; ret = -EINVAL; @@ -2704,12 +2596,15 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = i2c_decoder_command(VIDIOC_S_STD, &norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2737,8 +2632,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) if (vcs2->input == VINO_INPUT_D1) { vino_drvdata->camera.owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - camera.driver); + i2c_release_client(vino_drvdata->camera.driver); vino_drvdata->camera.owner = VINO_NO_CHANNEL; } } @@ -2833,18 +2727,16 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, switch (vcs->input) { case VINO_INPUT_D1: /* only one "norm" supported */ - if ((data_norm != VINO_DATA_NORM_D1) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + if (data_norm != VINO_DATA_NORM_D1) return -EINVAL; break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { + v4l2_std_id norm; + if ((data_norm != VINO_DATA_NORM_PAL) && (data_norm != VINO_DATA_NORM_NTSC) - && (data_norm != VINO_DATA_NORM_SECAM) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + && (data_norm != VINO_DATA_NORM_SECAM)) return -EINVAL; spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); @@ -2852,7 +2744,8 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, /* Don't hold spinlocks while setting norm * as it may take a while... */ - err = vino_saa7191_set_norm(&data_norm); + norm = vino_data_norms[data_norm].std; + err = i2c_decoder_command(VIDIOC_S_STD, &norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); @@ -3002,14 +2895,8 @@ static int vino_enum_input(struct file *file, void *__fh, i->std = vino_inputs[input].std; strcpy(i->name, vino_inputs[input].name); - if ((input == VINO_INPUT_COMPOSITE) - || (input == VINO_INPUT_SVIDEO)) { - struct saa7191_status status; - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL; - i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR; - } - + if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) + i2c_decoder_command(VIDIOC_INT_G_INPUT_STATUS, &i->status); return 0; } @@ -3066,19 +2953,7 @@ static int vino_querystd(struct file *file, void *__fh, break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_status status; - - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - - if (status.signal) { - if (status.signal_60hz) { - *std = V4L2_STD_NTSC; - } else { - *std = V4L2_STD_PAL | V4L2_STD_SECAM; - } - } else { - *std = vino_inputs[vcs->input].std; - } + i2c_decoder_command(VIDIOC_QUERYSTD, std); break; } default: @@ -3130,12 +3005,7 @@ static int vino_s_std(struct file *file, void *__fh, if (vcs->input == VINO_INPUT_D1) goto out; - if (((*std) & V4L2_STD_PAL) - && ((*std) & V4L2_STD_NTSC) - && ((*std) & V4L2_STD_SECAM)) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT, - &flags); - } else if ((*std) & V4L2_STD_PAL) { + if ((*std) & V4L2_STD_PAL) { ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, &flags); } else if ((*std) & V4L2_STD_NTSC) { @@ -3801,56 +3671,38 @@ static int vino_g_ctrl(struct file *file, void *__fh, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - goto found1; + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - - err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL, - &indycam_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = indycam_ctrl.value; + err = i2c_camera_command(VIDIOC_G_CTRL, &control); + if (err) + err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - goto found2; + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - - err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL, - &saa7191_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = saa7191_ctrl.value; + err = i2c_decoder_command(VIDIOC_G_CTRL, &control); + if (err) + err = -EINVAL; break; } default: @@ -3880,65 +3732,43 @@ static int vino_s_ctrl(struct file *file, void *__fh, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_indycam_v4l2_controls[i].minimum) - && (control->value <= - vino_indycam_v4l2_controls[i]. - maximum)) { - goto found1; - } else { - err = -ERANGE; - goto out; - } + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - indycam_ctrl.value = control->value; - - err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL, - &indycam_ctrl); + if (err) + goto out; + if (control->value < vino_indycam_v4l2_controls[i].minimum || + control->value > vino_indycam_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } + err = i2c_camera_command(VIDIOC_S_CTRL, &control); if (err) err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_saa7191_v4l2_controls[i].minimum) - && (control->value <= - vino_saa7191_v4l2_controls[i]. - maximum)) { - goto found2; - } else { - err = -ERANGE; - goto out; - } + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - saa7191_ctrl.value = control->value; + if (err) + goto out; + if (control->value < vino_saa7191_v4l2_controls[i].minimum || + control->value > vino_saa7191_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } - err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL, - &saa7191_ctrl); + err = i2c_decoder_command(VIDIOC_S_CTRL, &control); if (err) err = -EINVAL; break; -- cgit v1.2.3 From 86772b4bbf98d80df9084f91a47c6290f2d4a25b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 23:38:10 +0100 Subject: indycam: convert to v4l2_subdev From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/indycam.c | 128 ++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 57 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c index 492f1e6cb..9c09fe1b8 100644 --- a/linux/drivers/media/video/indycam.c +++ b/linux/drivers/media/video/indycam.c @@ -22,7 +22,8 @@ /* IndyCam decodes stream of photons into digital image representation ;-) */ #include #include -#include +#include +#include #include #include "indycam.h" @@ -49,10 +50,15 @@ I2C_CLIENT_INSMOD; #endif struct indycam { - struct i2c_client *client; + struct v4l2_subdev sd; u8 version; }; +static inline struct indycam *to_indycam(struct v4l2_subdev *sd) +{ + return container_of(sd, struct indycam, sd); +} + static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ @@ -66,8 +72,9 @@ static const u8 initseq[] = { /* IndyCam register handling */ -static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) +static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; if (reg == INDYCAM_REG_RESET) { @@ -90,12 +97,12 @@ static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) return 0; } -static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) +static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int err; - if ((reg == INDYCAM_REG_BRIGHTNESS) - || (reg == INDYCAM_REG_VERSION)) { + if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) { dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); return 0; @@ -111,13 +118,13 @@ static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) return err; } -static int indycam_write_block(struct i2c_client *client, u8 reg, +static int indycam_write_block(struct v4l2_subdev *sd, u8 reg, u8 length, u8 *data) { int i, err; for (i = 0; i < length; i++) { - err = indycam_write_reg(client, reg + i, data[i]); + err = indycam_write_reg(sd, reg + i, data[i]); if (err) return err; } @@ -128,29 +135,28 @@ static int indycam_write_block(struct i2c_client *client, u8 reg, /* Helper functions */ #ifdef INDYCAM_DEBUG -static void indycam_regdump_debug(struct i2c_client *client) +static void indycam_regdump_debug(struct v4l2_subdev *sd) { int i; u8 val; for (i = 0; i < 9; i++) { - indycam_read_reg(client, i, &val); + indycam_read_reg(sd, i, &val); dprintk("Reg %d = 0x%02x\n", i, val); } } #endif -static int indycam_get_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; switch (ctrl->id) { case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTO_WHITE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) return -EIO; if (ctrl->id == V4L2_CID_AUTOGAIN) @@ -161,38 +167,38 @@ static int indycam_get_control(struct i2c_client *client, ? 1 : 0; break; case V4L2_CID_EXPOSURE: - ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, ®); if (ret) return -EIO; ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); break; case V4L2_CID_GAIN: - ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case V4L2_CID_RED_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case V4L2_CID_BLUE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_RED_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_SATURATION, ®); if (ret) return -EIO; @@ -200,7 +206,7 @@ static int indycam_get_control(struct i2c_client *client, break; case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_GAMMA, ®); if (ret) return -EIO; @@ -216,17 +222,16 @@ static int indycam_get_control(struct i2c_client *client, return ret; } -static int indycam_set_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; switch (ctrl->id) { case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTO_WHITE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) break; @@ -242,34 +247,34 @@ static int indycam_set_control(struct i2c_client *client, reg &= ~INDYCAM_CONTROL_AWBCTL; } - ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg); break; case V4L2_CID_EXPOSURE: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); - ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg); break; case V4L2_CID_GAIN: - ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); + ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value); break; case V4L2_CID_RED_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, + ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE, ctrl->value); break; case V4L2_CID_BLUE_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, + ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA, ctrl->value); } break; @@ -282,30 +287,39 @@ static int indycam_set_control(struct i2c_client *client, /* I2C-interface */ -static int indycam_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int indycam_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) { - /* The old video_decoder interface just isn't enough, - * so we'll use some custom commands. */ - switch (cmd) { - case VIDIOC_G_CTRL: - return indycam_get_control(client, arg); - - case VIDIOC_S_CTRL: - return indycam_set_control(client, arg); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct indycam *camera = to_indycam(sd); - default: - return -EINVAL; - } + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM, + camera->version); +} - return 0; +static int indycam_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops indycam_core_ops = { + .g_chip_ident = indycam_g_chip_ident, + .g_ctrl = indycam_g_ctrl, + .s_ctrl = indycam_s_ctrl, +}; + +static const struct v4l2_subdev_ops indycam_ops = { + .core = &indycam_core_ops, +}; + static int indycam_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; struct indycam *camera; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -314,9 +328,8 @@ static int indycam_probe(struct i2c_client *client, if (!camera) return -ENOMEM; - i2c_set_clientdata(client, camera); - - camera->client = client; + sd = &camera->sd; + v4l2_i2c_subdev_init(sd, client, &indycam_ops); camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); @@ -330,20 +343,20 @@ static int indycam_probe(struct i2c_client *client, INDYCAM_VERSION_MAJOR(camera->version), INDYCAM_VERSION_MINOR(camera->version)); - indycam_regdump(client); + indycam_regdump(sd); // initialize - err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); + err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initialization failed\n"); kfree(camera); return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); // white balance - err = indycam_write_reg(client, INDYCAM_REG_CONTROL, + err = indycam_write_reg(sd, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { printk(KERN_ERR "IndyCam: White balancing camera failed\n"); @@ -351,7 +364,7 @@ static int indycam_probe(struct i2c_client *client, return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); printk(KERN_INFO "IndyCam initialized\n"); @@ -360,9 +373,10 @@ static int indycam_probe(struct i2c_client *client, static int indycam_remove(struct i2c_client *client) { - struct indycam *camera = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(camera); + v4l2_device_unregister_subdev(sd); + kfree(to_indycam(sd)); return 0; } -- cgit v1.2.3 From 6e3bf4e0c794fd26a3532ea033dbbf6e28e0b44d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 23:58:12 +0100 Subject: saa7191: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7191.c | 240 +++++++++++++++++++----------------- 1 file changed, 126 insertions(+), 114 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index 2c4c8ac5c..970b99924 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -21,7 +21,8 @@ #include #include -#include +#include +#include #include #include "compat.h" @@ -50,7 +51,7 @@ I2C_CLIENT_INSMOD; #define SAA7191_SYNC_DELAY 100 /* milliseconds */ struct saa7191 { - struct i2c_client *client; + struct v4l2_subdev sd; /* the register values are stored here as the actual * I2C-registers are write-only */ @@ -60,6 +61,11 @@ struct saa7191 { v4l2_std_id norm; }; +static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7191, sd); +} + static const u8 initseq[] = { 0, /* Subaddress */ @@ -104,15 +110,14 @@ static const u8 initseq[] = { /* SAA7191 register handling */ -static u8 saa7191_read_reg(struct i2c_client *client, - u8 reg) +static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg) { - return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; + return to_saa7191(sd)->reg[reg]; } -static int saa7191_read_status(struct i2c_client *client, - u8 *value) +static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; ret = i2c_master_recv(client, value, 1); @@ -125,21 +130,23 @@ static int saa7191_read_status(struct i2c_client *client, } -static int saa7191_write_reg(struct i2c_client *client, u8 reg, - u8 value) +static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { - ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + to_saa7191(sd)->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } /* the first byte of data must be the first subaddress number (register) */ -static int saa7191_write_block(struct i2c_client *client, +static int saa7191_write_block(struct v4l2_subdev *sd, u8 length, const u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7191 *decoder = to_saa7191(sd); int i; int ret; - struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client); for (i = 0; i < (length - 1); i++) { decoder->reg[data[0] + i] = data[i + 1]; } @@ -156,14 +163,15 @@ static int saa7191_write_block(struct i2c_client *client, /* Helper functions */ -static int saa7191_set_input(struct i2c_client *client, int input) +static int saa7191_s_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA); - u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK); + struct saa7191 *decoder = to_saa7191(sd); + u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA); + u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK); int err; - switch (input) { + switch (route->input) { case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | SAA7191_IOCK_GPSW2); @@ -179,24 +187,24 @@ static int saa7191_set_input(struct i2c_client *client, int input) return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma); + err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock); + err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock); if (err) return -EIO; - decoder->input = input; + decoder->input = route->input; return 0; } -static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) +static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); + u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV); int err; if (norm & V4L2_STD_PAL) { @@ -216,13 +224,13 @@ static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv); + err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv); if (err) return -EIO; @@ -235,14 +243,14 @@ static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) return 0; } -static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) +static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status) { int i = 0; dprintk("Checking for signal...\n"); for (i = 0; i < SAA7191_SYNC_COUNT; i++) { - if (saa7191_read_status(client, status)) + if (saa7191_read_status(sd, status)) return -EIO; if (((*status) & SAA7191_STATUS_HLCK) == 0) { @@ -258,12 +266,11 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) return -EBUSY; } -static int saa7191_autodetect_norm_extended(struct i2c_client *client, - v4l2_std_id *norm) +static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); u8 status; v4l2_std_id old_norm = decoder->norm; int err = 0; @@ -274,19 +281,19 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) { err = -EIO; goto out; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; } ctl3 |= SAA7191_CTL3_AUFD; - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; @@ -294,7 +301,7 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; @@ -309,39 +316,39 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, dprintk("50Hz signal: Trying PAL...\n"); /* try PAL first */ - err = saa7191_set_norm(client, V4L2_STD_PAL); + err = saa7191_s_std(sd, V4L2_STD_PAL); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - saa7191_set_norm(client, old_norm); + saa7191_s_std(sd, old_norm); return -EAGAIN; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); *norm = V4L2_STD_PAL; - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with PAL - Trying SECAM...\n"); /* no color detected ? -> try SECAM */ - err = saa7191_set_norm(client, V4L2_STD_SECAM); + err = saa7191_s_std(sd, V4L2_STD_SECAM); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; @@ -356,16 +363,16 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, /* Color detected -> SECAM */ dprintk("SECAM\n"); *norm = V4L2_STD_SECAM; - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); out: - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } -static int saa7191_autodetect_norm(struct i2c_client *client) +static int saa7191_autodetect_norm(struct v4l2_subdev *sd) { u8 status; @@ -373,7 +380,7 @@ static int saa7191_autodetect_norm(struct i2c_client *client) dprintk("Reading status...\n"); - if (saa7191_read_status(client, &status)) + if (saa7191_read_status(sd, &status)) return -EIO; dprintk("Checking for signal...\n"); @@ -389,16 +396,15 @@ static int saa7191_autodetect_norm(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60hz signal -> NTSC */ dprintk("NTSC\n"); - return saa7191_set_norm(client, V4L2_STD_NTSC); + return saa7191_s_std(sd, V4L2_STD_NTSC); } else { /* 50hz signal -> PAL */ dprintk("PAL\n"); - return saa7191_set_norm(client, V4L2_STD_PAL); + return saa7191_s_std(sd, V4L2_STD_PAL); } } -static int saa7191_get_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; @@ -407,7 +413,7 @@ static int saa7191_get_control(struct i2c_client *client, case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) @@ -425,7 +431,7 @@ static int saa7191_get_control(struct i2c_client *client, break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else @@ -433,7 +439,7 @@ static int saa7191_get_control(struct i2c_client *client, >> SAA7191_GAIN_LFIS_SHIFT; break; case V4L2_CID_HUE: - reg = saa7191_read_reg(client, SAA7191_REG_HUEC); + reg = saa7191_read_reg(sd, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; else @@ -441,18 +447,18 @@ static int saa7191_get_control(struct i2c_client *client, ctrl->value = (s32)reg; break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; break; case SAA7191_CONTROL_LUMA_DELAY: - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) >> SAA7191_CTL3_YDEL_SHIFT; if (ctrl->value >= 4) ctrl->value -= 8; break; case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) >> SAA7191_CTL4_VNOI_SHIFT; break; @@ -463,8 +469,7 @@ static int saa7191_get_control(struct i2c_client *client, return ret; } -static int saa7191_set_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; @@ -473,7 +478,7 @@ static int saa7191_set_control(struct i2c_client *client, case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; @@ -491,11 +496,11 @@ static int saa7191_set_control(struct i2c_client *client, & SAA7191_LUMA_CORI_MASK; break; } - ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg); break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; @@ -506,7 +511,7 @@ static int saa7191_set_control(struct i2c_client *client, reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) & SAA7191_GAIN_LFIS_MASK; } - ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg); break; case V4L2_CID_HUE: reg = ctrl->value & 0xff; @@ -514,33 +519,33 @@ static int saa7191_set_control(struct i2c_client *client, reg += 0x80; else reg -= 0x80; - ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg); break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); if (ctrl->value) reg |= SAA7191_STDC_VTRC; else reg &= ~SAA7191_STDC_VTRC; - ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg); break; case SAA7191_CONTROL_LUMA_DELAY: { s32 value = ctrl->value; if (value < 0) value += 8; - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); reg &= ~SAA7191_CTL3_YDEL_MASK; reg |= (value << SAA7191_CTL3_YDEL_SHIFT) & SAA7191_CTL3_YDEL_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg); break; } case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); reg &= ~SAA7191_CTL4_VNOI_MASK; reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) & SAA7191_CTL4_VNOI_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg); break; default: ret = -EINVAL; @@ -551,57 +556,64 @@ static int saa7191_set_control(struct i2c_client *client, /* I2C-interface */ -static int saa7191_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) { - switch (cmd) { - case VIDIOC_INT_G_INPUT_STATUS: { - u32 *iarg = arg; - u8 status; - int res = V4L2_IN_ST_NO_SIGNAL; + u8 status_reg; + int res = V4L2_IN_ST_NO_SIGNAL; - if (saa7191_read_status(client, &status)) - return -EIO; - if ((status & SAA7191_STATUS_HLCK) == 0) - res = 0; - if (!(status & SAA7191_STATUS_CODE)) - res |= V4L2_IN_ST_NO_COLOR; - *iarg = res; - break; - } + if (saa7191_read_status(sd, &status_reg)) + return -EIO; + if ((status_reg & SAA7191_STATUS_HLCK) == 0) + res = 0; + if (!(status_reg & SAA7191_STATUS_CODE)) + res |= V4L2_IN_ST_NO_COLOR; + *status = res; + return 0; +} - case VIDIOC_QUERYSTD: - return saa7191_autodetect_norm_extended(client, arg); - case VIDIOC_S_STD: { - v4l2_std_id *istd = arg; +static int saa7191_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - return saa7191_set_norm(client, *istd); - } - case VIDIOC_INT_S_VIDEO_ROUTING: { - struct v4l2_routing *route = arg; + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); +} - return saa7191_set_input(client, route->input); - } +static int saa7191_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} - case VIDIOC_G_CTRL: - return saa7191_get_control(client, arg); +/* ----------------------------------------------------------------------- */ - case VIDIOC_S_CTRL: - return saa7191_set_control(client, arg); +static const struct v4l2_subdev_core_ops saa7191_core_ops = { + .g_chip_ident = saa7191_g_chip_ident, + .g_ctrl = saa7191_g_ctrl, + .s_ctrl = saa7191_s_ctrl, +}; - default: - return -EINVAL; - } +static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = { + .s_std = saa7191_s_std, +}; - return 0; -} +static const struct v4l2_subdev_video_ops saa7191_video_ops = { + .s_routing = saa7191_s_routing, + .querystd = saa7191_querystd, + .g_input_status = saa7191_g_input_status, +}; + +static const struct v4l2_subdev_ops saa7191_ops = { + .core = &saa7191_core_ops, + .video = &saa7191_video_ops, +}; static int saa7191_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; struct saa7191 *decoder; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -610,11 +622,10 @@ static int saa7191_probe(struct i2c_client *client, if (!decoder) return -ENOMEM; - i2c_set_clientdata(client, decoder); - - decoder->client = client; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7191_ops); - err = saa7191_write_block(client, sizeof(initseq), initseq); + err = saa7191_write_block(sd, sizeof(initseq), initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); kfree(decoder); @@ -626,7 +637,7 @@ static int saa7191_probe(struct i2c_client *client, decoder->input = SAA7191_INPUT_COMPOSITE; decoder->norm = V4L2_STD_PAL; - err = saa7191_autodetect_norm(client); + err = saa7191_autodetect_norm(sd); if (err && (err != -EBUSY)) printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); @@ -635,9 +646,10 @@ static int saa7191_probe(struct i2c_client *client, static int saa7191_remove(struct i2c_client *client) { - struct saa7191 *decoder = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(decoder); + v4l2_device_unregister_subdev(sd); + kfree(to_saa7191(sd)); return 0; } -- cgit v1.2.3 From 7120d49dac791b2c3097ae0522c50bb3ca45be66 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 22:53:47 +0100 Subject: vino: introduce v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 6b87a55a9..d5c42049b 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include @@ -295,6 +295,7 @@ struct vino_client { }; struct vino_settings { + struct v4l2_device v4l2_dev; struct vino_channel_settings a; struct vino_channel_settings b; @@ -3999,7 +4000,6 @@ over: ret = POLLIN | POLLRDNORM; error: - return ret; } @@ -4056,7 +4056,7 @@ static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, .release = vino_close, - .ioctl = vino_ioctl, + .unlocked_ioctl = vino_ioctl, .mmap = vino_mmap, .poll = vino_poll, }; @@ -4072,27 +4072,27 @@ static struct video_device vdev_template = { static void vino_module_cleanup(int stage) { switch(stage) { - case 10: + case 11: video_unregister_device(vino_drvdata->b.vdev); vino_drvdata->b.vdev = NULL; - case 9: + case 10: video_unregister_device(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; - case 8: + case 9: vino_i2c_del_bus(); - case 7: + case 8: free_irq(SGI_VINO_IRQ, NULL); - case 6: + case 7: if (vino_drvdata->b.vdev) { video_device_release(vino_drvdata->b.vdev); vino_drvdata->b.vdev = NULL; } - case 5: + case 6: if (vino_drvdata->a.vdev) { video_device_release(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; } - case 4: + case 5: /* all entries in dma_cpu dummy table have the same address */ dma_unmap_single(NULL, vino_drvdata->dummy_desc_table.dma_cpu[0], @@ -4102,8 +4102,10 @@ static void vino_module_cleanup(int stage) (void *)vino_drvdata-> dummy_desc_table.dma_cpu, vino_drvdata->dummy_desc_table.dma); - case 3: + case 4: free_page(vino_drvdata->dummy_page); + case 3: + v4l2_device_unregister(&vino_drvdata->v4l2_dev); case 2: kfree(vino_drvdata); case 1: @@ -4158,6 +4160,7 @@ static int vino_probe(void) static int vino_init(void) { dma_addr_t dma_dummy_address; + int err; int i; vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL); @@ -4166,6 +4169,12 @@ static int vino_init(void) return -ENOMEM; } vino_init_stage++; + strlcpy(vino_drvdata->v4l2_dev.name, "vino", + sizeof(vino_drvdata->v4l2_dev.name)); + err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev); + if (err) + return err; + vino_init_stage++; /* create a dummy dma descriptor */ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA); @@ -4243,6 +4252,7 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, sizeof(struct video_device)); strcpy(vcs->vdev->name, name); vcs->vdev->release = video_device_release; + vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev; video_set_drvdata(vcs->vdev, vcs); @@ -4297,6 +4307,7 @@ static int __init vino_module_init(void) vino_module_cleanup(vino_init_stage); return ret; } + i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev); vino_init_stage++; ret = video_register_device(vino_drvdata->a.vdev, -- cgit v1.2.3 From e8550a40016b1ca262d0fc9502d8d7d868420849 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 23:18:26 +0100 Subject: vino: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 207 +++++++++++++-------------------------- 1 file changed, 67 insertions(+), 140 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index d5c42049b..8a96ee7db 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -287,20 +287,17 @@ struct vino_channel_settings { struct video_device *vdev; }; -struct vino_client { - /* the channel which owns this client: - * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ - unsigned int owner; - struct i2c_client *driver; -}; - struct vino_settings { struct v4l2_device v4l2_dev; struct vino_channel_settings a; struct vino_channel_settings b; - struct vino_client decoder; - struct vino_client camera; + /* the channel which owns this client: + * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ + unsigned int decoder_owner; + struct v4l2_subdev *decoder; + unsigned int camera_owner; + struct v4l2_subdev *camera; /* a lock for vino register access */ spinlock_t vino_lock; @@ -340,6 +337,11 @@ static struct sgi_vino *vino; static struct vino_settings *vino_drvdata; +#define camera_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->camera, o, f, ##args) +#define decoder_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args) + static const char *vino_driver_name = "vino"; static const char *vino_driver_description = "SGI VINO"; static const char *vino_bus_name = "GIO64 bus"; @@ -670,66 +672,12 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = .ack_timeout = 1000, }; -/* - * There are two possible clients on VINO I2C bus, so we limit usage only - * to them. - */ -static int i2c_vino_client_reg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch (client->driver->id) { - case I2C_DRIVERID_SAA7191: - if (vino_drvdata->decoder.driver) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = client; - break; - case I2C_DRIVERID_INDYCAM: - if (vino_drvdata->camera.driver) - ret = -EBUSY; - else - vino_drvdata->camera.driver = client; - break; - default: - ret = -ENODEV; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static int i2c_vino_client_unreg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (client == vino_drvdata->decoder.driver) { - if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = NULL; - } else if (client == vino_drvdata->camera.driver) { - if (vino_drvdata->camera.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->camera.driver = NULL; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - static struct i2c_adapter vino_i2c_adapter = { .name = "VINO I2C bus", .id = I2C_HW_SGI_VINO, .algo_data = &i2c_sgi_vino_data, - .client_register = &i2c_vino_client_reg, - .client_unregister = &i2c_vino_client_unreg, + .owner = THIS_MODULE, }; static int vino_i2c_add_bus(void) @@ -742,20 +690,6 @@ static int vino_i2c_del_bus(void) return i2c_del_adapter(&vino_i2c_adapter); } -static int i2c_camera_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->camera.driver-> - driver->command(vino_drvdata->camera.driver, - cmd, arg); -} - -static int i2c_decoder_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->decoder.driver-> - driver->command(vino_drvdata->decoder.driver, - cmd, arg); -} - /* VINO framebuffer/DMA descriptor management */ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, @@ -2460,9 +2394,9 @@ static int vino_is_input_owner(struct vino_channel_settings *vcs) switch(vcs->input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - return (vino_drvdata->decoder.owner == vcs->channel); + return vino_drvdata->decoder_owner == vcs->channel; case VINO_INPUT_D1: - return (vino_drvdata->camera.owner == vcs->channel); + return vino_drvdata->camera_owner == vcs->channel; default: return 0; } @@ -2478,24 +2412,22 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) spin_lock_irqsave(&vino_drvdata->input_lock, flags); /* First try D1 and then SAA7191 */ - if (vino_drvdata->camera.driver - && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; + if (vino_drvdata->camera + && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) { + vino_drvdata->camera_owner = vcs->channel; vcs->input = VINO_INPUT_D1; vcs->data_norm = VINO_DATA_NORM_D1; - } else if (vino_drvdata->decoder.driver - && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { + } else if (vino_drvdata->decoder + && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) { int input; int data_norm; v4l2_std_id norm; struct v4l2_routing route = { 0, 0 }; - i2c_use_client(vino_drvdata->decoder.driver); input = VINO_INPUT_COMPOSITE; route.input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); + ret = decoder_call(video, s_routing, &route); if (ret) { ret = -EINVAL; goto out; @@ -2506,7 +2438,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + ret = decoder_call(video, querystd, &norm); if (!ret) { for (data_norm = 0; data_norm < 3; data_norm++) { if (vino_data_norms[data_norm].std & norm) @@ -2514,7 +2446,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = i2c_decoder_command(VIDIOC_S_STD, &norm); + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2524,7 +2456,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) goto out; } - vino_drvdata->decoder.owner = vcs->channel; + vino_drvdata->decoder_owner = vcs->channel; vcs->input = input; vcs->data_norm = data_norm; @@ -2569,25 +2501,24 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) switch (input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - if (!vino_drvdata->decoder.driver) { + if (!vino_drvdata->decoder) { ret = -EINVAL; goto out; } - if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = vcs->channel; + if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) { + vino_drvdata->decoder_owner = vcs->channel; } - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { int data_norm; v4l2_std_id norm; struct v4l2_routing route = { 0, 0 }; route.input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); + ret = decoder_call(video, s_routing, &route); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2597,7 +2528,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + ret = decoder_call(video, querystd, &norm); if (!ret) { for (data_norm = 0; data_norm < 3; data_norm++) { if (vino_data_norms[data_norm].std & norm) @@ -2605,13 +2536,13 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = i2c_decoder_command(VIDIOC_S_STD, &norm); + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2628,36 +2559,31 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) vcs->data_norm = vcs2->data_norm; } - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { /* Transfer the ownership or release the input */ if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } } break; case VINO_INPUT_D1: - if (!vino_drvdata->camera.driver) { + if (!vino_drvdata->camera) { ret = -EINVAL; goto out; } - if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; - } + if (vino_drvdata->camera_owner == VINO_NO_CHANNEL) + vino_drvdata->camera_owner = vcs->channel; - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { /* Transfer the ownership or release the input */ if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } @@ -2694,20 +2620,18 @@ static void vino_release_input(struct vino_channel_settings *vcs) /* Release ownership of the channel * and if the other channel takes input from * the same source, transfer the ownership */ - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } - } else if (vino_drvdata->decoder.owner == vcs->channel) { + } else if (vino_drvdata->decoder_owner == vcs->channel) { if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } vcs->input = VINO_INPUT_NONE; @@ -2746,7 +2670,7 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, * as it may take a while... */ norm = vino_data_norms[data_norm].std; - err = i2c_decoder_command(VIDIOC_S_STD, &norm); + err = decoder_call(tuner, s_std, norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); @@ -2788,7 +2712,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2800,7 +2724,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_D1; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2809,7 +2733,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_SVIDEO; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_D1; @@ -2827,7 +2751,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) __u32 index = 0; // FIXME: detect when no inputs available - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2839,7 +2763,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 2; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2848,7 +2772,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 1; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_D1: index = 0; @@ -2897,7 +2821,7 @@ static int vino_enum_input(struct file *file, void *__fh, strcpy(i->name, vino_inputs[input].name); if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) - i2c_decoder_command(VIDIOC_INT_G_INPUT_STATUS, &i->status); + decoder_call(video, g_input_status, &i->status); return 0; } @@ -2954,7 +2878,7 @@ static int vino_querystd(struct file *file, void *__fh, break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - i2c_decoder_command(VIDIOC_QUERYSTD, std); + decoder_call(video, querystd, std); break; } default: @@ -3683,7 +3607,7 @@ static int vino_g_ctrl(struct file *file, void *__fh, if (err) goto out; - err = i2c_camera_command(VIDIOC_G_CTRL, &control); + err = camera_call(core, g_ctrl, control); if (err) err = -EINVAL; break; @@ -3701,7 +3625,7 @@ static int vino_g_ctrl(struct file *file, void *__fh, if (err) goto out; - err = i2c_decoder_command(VIDIOC_G_CTRL, &control); + err = decoder_call(core, g_ctrl, control); if (err) err = -EINVAL; break; @@ -3747,7 +3671,7 @@ static int vino_s_ctrl(struct file *file, void *__fh, err = -ERANGE; goto out; } - err = i2c_camera_command(VIDIOC_S_CTRL, &control); + err = camera_call(core, s_ctrl, control); if (err) err = -EINVAL; break; @@ -3769,7 +3693,7 @@ static int vino_s_ctrl(struct file *file, void *__fh, goto out; } - err = i2c_decoder_command(VIDIOC_S_CTRL, &control); + err = decoder_call(core, s_ctrl, control); if (err) err = -EINVAL; break; @@ -4261,6 +4185,7 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, static int __init vino_module_init(void) { + unsigned short addr[] = { 0, I2C_CLIENT_END }; int ret; printk(KERN_INFO "SGI VINO driver version %s\n", @@ -4330,10 +4255,12 @@ static int __init vino_module_init(void) } vino_init_stage++; -#ifdef MODULE - request_module("saa7191"); - request_module("indycam"); -#endif + addr[0] = 0x45; + vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "saa7191", "saa7191", addr); + addr[0] = 0x2b; + vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "indycam", "indycam", addr); dprintk("init complete!\n"); -- cgit v1.2.3 From 662eeaff4dbeccc9958ac8d31e8b50b9fb058b4c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 23:23:43 +0100 Subject: saa7191, indycam: remove compat code. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/indycam.c | 17 +++-------------- linux/drivers/media/video/saa7191.c | 17 +++-------------- 2 files changed, 6 insertions(+), 28 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c index 9c09fe1b8..f2da0550b 100644 --- a/linux/drivers/media/video/indycam.c +++ b/linux/drivers/media/video/indycam.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "indycam.h" @@ -35,9 +35,11 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif // #define INDYCAM_DEBUG @@ -297,11 +299,6 @@ static int indycam_g_chip_ident(struct v4l2_subdev *sd, camera->version); } -static int indycam_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops indycam_core_ops = { @@ -380,11 +377,6 @@ static int indycam_remove(struct i2c_client *client) return 0; } -static int indycam_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_SGI_VINO; -} - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id indycam_id[] = { { "indycam", 0 }, @@ -395,11 +387,8 @@ MODULE_DEVICE_TABLE(i2c, indycam_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "indycam", - .driverid = I2C_DRIVERID_INDYCAM, - .command = indycam_command, .probe = indycam_probe, .remove = indycam_remove, - .legacy_probe = indycam_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = indycam_id, #endif diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index 970b99924..9df505e0f 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "compat.h" #include "saa7191.h" @@ -35,9 +35,11 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif // #define SAA7191_DEBUG @@ -580,11 +582,6 @@ static int saa7191_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); } -static int saa7191_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7191_core_ops = { @@ -653,11 +650,6 @@ static int saa7191_remove(struct i2c_client *client) return 0; } -static int saa7191_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_SGI_VINO; -} - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id saa7191_id[] = { { "saa7191", 0 }, @@ -668,11 +660,8 @@ MODULE_DEVICE_TABLE(i2c, saa7191_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7191", - .driverid = I2C_DRIVERID_SAA7191, - .command = saa7191_command, .probe = saa7191_probe, .remove = saa7191_remove, - .legacy_probe = saa7191_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = saa7191_id, #endif -- cgit v1.2.3 From da03bb58104d244cbf33a6672940e8c52a06ce5b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 28 Feb 2009 12:09:24 +0100 Subject: gspca - mars: Bad webcam register values tied to saturation. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/mars.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c index c5a19b5bc..5d54893eb 100644 --- a/linux/drivers/media/video/gspca/mars.c +++ b/linux/drivers/media/video/gspca/mars.c @@ -69,10 +69,10 @@ static struct ctrl sd_ctrls[] = { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", - .minimum = 0, - .maximum = 220, + .minimum = 1, + .maximum = 255, .step = 1, -#define COLOR_DEF 190 +#define COLOR_DEF 200 .default_value = COLOR_DEF, }, .set = sd_setcolors, @@ -191,7 +191,7 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int err_code; u8 *data; - int i, val; + int i; data = gspca_dev->usb_buf; @@ -253,9 +253,11 @@ static int sd_start(struct gspca_dev *gspca_dev) data[1] = 0; /* reg 94, Y Gain (auto) */ #if 1 /*jfm: from win trace*/ - val = sd->colors * 0x40 + 0x400; - data[2] = val; /* reg 0x5f/0x60 (LE) = saturation */ - data[3] = val >> 8; + /* reg 0x5f/0x60 (LE) = saturation */ + /* h (60): xxxx x100 + * l (5f): xxxx x000 */ + data[2] = sd->colors << 3; + data[3] = ((sd->colors >> 2) & 0xf8) | 0x04; data[4] = sd->brightness; /* reg 0x61 = brightness */ data[5] = 0x00; #else @@ -403,10 +405,11 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) sd->colors = val; if (gspca_dev->streaming) { - val = val * 0x40 + 0x400; + + /* see sd_start */ gspca_dev->usb_buf[0] = 0x5f; - gspca_dev->usb_buf[1] = val; - gspca_dev->usb_buf[2] = val >> 8; + gspca_dev->usb_buf[1] = sd->colors << 3; + gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04; reg_w(gspca_dev, 3); } return 0; -- cgit v1.2.3 From 675a1a53c3d2ca166e3fe921f4f23c2d0f42e5e4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 28 Feb 2009 12:23:25 +0100 Subject: gspca - vc032x: Bad matrix for sensor mi1310_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 72cbf56c9..f1c149476 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2316,7 +2316,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_MI1310_SOC: GammaT = mi1320_gamma; - MatrixT = mi0360_matrix; + MatrixT = mi1320_matrix; switch (mode) { case 1: init = mi1310_socinitQVGA_JPG; /* 320x240 */ -- cgit v1.2.3 From 3b38addc33a36ea34a73f3f910df0901feb4ff1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 22 Feb 2009 21:54:11 +0100 Subject: m5602-s5k4aa: Split up the initial sensor probe in chunks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Gregory Lardiere The previous probe rotine tried to read 6 bytes in one chunk which currently isn't allowed. This is the rev. 10346 243399e67c41 readded with a high priority. Priority: high Signed-off-by: Gregory Lardiere Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 2bd7d4d99..7e79f7eca 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -104,7 +104,11 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) -- cgit v1.2.3 From 4f899007909f749fc8b3657af8a776636f71446d Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 15:55:38 +0200 Subject: Add init code for NetUP Dual DVB-S2 CI card From: Abylay Ospan Add init code for NetUP Dual DVB-S2 CI card The card based on cx23885 PCI-e bridge, CiMax SP2 Common Interface chips, STM lnbh24 LNB power chip, stv6110 tuners and stv0900 demodulator. Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/netup-init.c | 125 +++++++++++++++++++++++++ linux/drivers/media/video/cx23885/netup-init.h | 25 +++++ 2 files changed, 150 insertions(+) create mode 100644 linux/drivers/media/video/cx23885/netup-init.c create mode 100644 linux/drivers/media/video/cx23885/netup-init.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/netup-init.c b/linux/drivers/media/video/cx23885/netup-init.c new file mode 100644 index 000000000..f4893e69c --- /dev/null +++ b/linux/drivers/media/video/cx23885/netup-init.c @@ -0,0 +1,125 @@ +/* + * netup-init.c + * + * NetUP Dual DVB-S2 CI driver + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx23885.h" + +static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val) +{ + int ret; + u8 buf[3]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 3 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = val; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); +} + +static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val) +{ + int ret; + u8 buf[6]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 6 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = val & 0xff; + buf[3] = (val >> 8) & 0xff; + buf[4] = (val >> 16) & 0xff; + buf[5] = val >> 24; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); +} + +static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 2 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); + + msg.flags = I2C_M_RD; + msg.len = 1; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c read error!\n", __func__); + + return buf[0]; +} + +static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask, + u8 or_value) +{ + i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value); +} +/* set 27MHz on AUX_CLK */ +void netup_initialize(struct cx23885_dev *dev) +{ + struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2]; + struct i2c_adapter *i2c = &i2c_bus->i2c_adap; + + /* Stop microcontroller */ + i2c_av_and_or(i2c, 0x803, ~0x10, 0x00); + + /* Aux PLL frac for 27 MHz */ + i2c_av_write4(i2c, 0x114, 0xea0eb3); + + /* Aux PLL int for 27 MHz */ + i2c_av_write4(i2c, 0x110, 0x090319); + + /* start microcontroller */ + i2c_av_and_or(i2c, 0x803, ~0x10, 0x10); +} diff --git a/linux/drivers/media/video/cx23885/netup-init.h b/linux/drivers/media/video/cx23885/netup-init.h new file mode 100644 index 000000000..d26ae4b15 --- /dev/null +++ b/linux/drivers/media/video/cx23885/netup-init.h @@ -0,0 +1,25 @@ +/* + * netup-init.h + * + * NetUP Dual DVB-S2 CI driver + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +extern void netup_initialize(struct cx23885_dev *dev); -- cgit v1.2.3 From c5af2a81fc6384ecc8880bacedc8b1d0de19cb15 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 16:00:18 +0200 Subject: Add EEPROM code for NetUP Dual DVB-S2 CI card. From: Abylay Ospan Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/netup-eeprom.c | 117 +++++++++++++++++++++++ linux/drivers/media/video/cx23885/netup-eeprom.h | 42 ++++++++ 2 files changed, 159 insertions(+) create mode 100644 linux/drivers/media/video/cx23885/netup-eeprom.c create mode 100644 linux/drivers/media/video/cx23885/netup-eeprom.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/netup-eeprom.c b/linux/drivers/media/video/cx23885/netup-eeprom.c new file mode 100644 index 000000000..26b934cd7 --- /dev/null +++ b/linux/drivers/media/video/cx23885/netup-eeprom.c @@ -0,0 +1,117 @@ + +/* + * netup-eeprom.c + * + * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +# +#include "cx23885.h" +#include "netup-eeprom.h" + +#define EEPROM_I2C_ADDR 0x50 + +int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr) +{ + int ret; + unsigned char buf[2]; + + /* Read from EEPROM */ + struct i2c_msg msg[] = { + { + .addr = EEPROM_I2C_ADDR, + .flags = 0, + .buf = &buf[0], + .len = 1 + }, { + .addr = EEPROM_I2C_ADDR, + .flags = I2C_M_RD, + .buf = &buf[1], + .len = 1 + } + + }; + + buf[0] = addr; + buf[1] = 0x0; + + ret = i2c_transfer(i2c_adap, msg, 2); + + if (ret != 2) { + printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret); + return -1; + } + + return buf[1]; +}; + +int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data) +{ + int ret; + unsigned char bufw[2]; + + /* Write into EEPROM */ + struct i2c_msg msg[] = { + { + .addr = EEPROM_I2C_ADDR, + .flags = 0, + .buf = &bufw[0], + .len = 2 + } + }; + + bufw[0] = addr; + bufw[1] = data; + + ret = i2c_transfer(i2c_adap, msg, 1); + + if (ret != 1) { + printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret); + return -1; + } + + mdelay(10); /* prophylactic delay, datasheet write cycle time = 5 ms */ + return 0; +}; + +void netup_get_card_info(struct i2c_adapter *i2c_adap, + struct netup_card_info *cinfo) +{ + int i, j; + + cinfo->rev = netup_eeprom_read(i2c_adap, 13); + + for (i = 0, j = 0; i < 6; i++, j++) + cinfo->port[0].mac[j] = netup_eeprom_read(i2c_adap, i); + + for (i = 6, j = 0; i < 12; i++, j++) + cinfo->port[1].mac[j] = netup_eeprom_read(i2c_adap, i); +#if 0 + printk(KERN_INFO "NetUP Dual DVB-S2 CI card rev=0x%x MAC1=%02X:%02X:" + "%02X:%02X:%02X:%02X MAC2=%02X:%02X:%02X:%02X:%02X:%02X\n", cinfo->rev, + cinfo->port[0].mac[0], cinfo->port[0].mac[1], + cinfo->port[0].mac[2], cinfo->port[0].mac[3], + cinfo->port[0].mac[4], cinfo->port[0].mac[5], + cinfo->port[1].mac[0], cinfo->port[1].mac[1], + cinfo->port[1].mac[2], cinfo->port[1].mac[3], + cinfo->port[1].mac[4], cinfo->port[1].mac[5]); +#endif +}; diff --git a/linux/drivers/media/video/cx23885/netup-eeprom.h b/linux/drivers/media/video/cx23885/netup-eeprom.h new file mode 100644 index 000000000..13926e18f --- /dev/null +++ b/linux/drivers/media/video/cx23885/netup-eeprom.h @@ -0,0 +1,42 @@ +/* + * netup-eeprom.h + * + * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef NETUP_EEPROM_H +#define NETUP_EEPROM_H + +struct netup_port_info { + u8 mac[6];/* card MAC address */ +}; + +struct netup_card_info { + struct netup_port_info port[2];/* ports - 1,2 */ + u8 rev;/* card revision */ +}; + +extern int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr); +extern int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data); +extern void netup_get_card_info(struct i2c_adapter *i2c_adap, + struct netup_card_info *cinfo); + +#endif -- cgit v1.2.3 From 97d2d4b112f4149c2e4e420343c48cfbaef5483d Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 16:06:00 +0200 Subject: Add CIMax(R) SP2 Common Interface code for NetUP Dual DVB-S2 CI card From: Abylay Ospan Add CIMax2 Common Interface code for NetUP Dual DVB-S2 CI card. SmarDTV CIMax(R) SP2 is Dual CableCARD, DVB Common Interface and OpenCable Hardware Controller. Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/cimax2.c | 484 +++++++++++++++++++++++++++++ linux/drivers/media/video/cx23885/cimax2.h | 47 +++ 2 files changed, 531 insertions(+) create mode 100644 linux/drivers/media/video/cx23885/cimax2.c create mode 100644 linux/drivers/media/video/cx23885/cimax2.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cimax2.c b/linux/drivers/media/video/cx23885/cimax2.c new file mode 100644 index 000000000..193d9b4cc --- /dev/null +++ b/linux/drivers/media/video/cx23885/cimax2.c @@ -0,0 +1,484 @@ +/* + * cimax2.c + * + * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx23885.h" +#include "dvb_ca_en50221.h" +/**** Bit definitions for MC417_RWD and MC417_OEN registers *** + bits 31-16 ++-----------+ +| Reserved | ++-----------+ + bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 ++-------+-------+-------+-------+-------+-------+-------+-------+ +| WR# | RD# | | ACK# | ADHI | ADLO | CS1# | CS0# | ++-------+-------+-------+-------+-------+-------+-------+-------+ + bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 ++-------+-------+-------+-------+-------+-------+-------+-------+ +| DATA7| DATA6| DATA5| DATA4| DATA3| DATA2| DATA1| DATA0| ++-------+-------+-------+-------+-------+-------+-------+-------+ +***/ +/* MC417 */ +#define NETUP_DATA 0x000000ff +#define NETUP_WR 0x00008000 +#define NETUP_RD 0x00004000 +#define NETUP_ACK 0x00001000 +#define NETUP_ADHI 0x00000800 +#define NETUP_ADLO 0x00000400 +#define NETUP_CS1 0x00000200 +#define NETUP_CS0 0x00000100 +#define NETUP_EN_ALL 0x00001000 +#define NETUP_CTRL_OFF (NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD) +#define NETUP_CI_CTL 0x04 +#define NETUP_CI_RD 1 + + +static unsigned int ci_dbg; +module_param(ci_dbg, int, 0644); +MODULE_PARM_DESC(ci_dbg, "Enable CI debugging"); + +#define ci_dbg_print(args...) \ + do { \ + if (ci_dbg) \ + printk(KERN_DEBUG args); \ + } while (0) + +/* stores all private variables for communication with CI */ +struct netup_ci_state { + struct dvb_ca_en50221 ca; + struct mutex ca_mutex; + struct i2c_adapter *i2c_adap; + u8 ci_i2c_addr; + int status; + struct work_struct work; + void *priv; +}; + +struct mutex gpio_mutex;/* Two CiMax's uses same GPIO lines */ + +int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, + u8 *buf, int len) +{ + int ret; + struct i2c_msg msg[] = { + { + .addr = addr, + .flags = 0, + .buf = ®, + .len = 1 + }, { + .addr = addr, + .flags = I2C_M_RD, + .buf = buf, + .len = len + } + }; + + ret = i2c_transfer(i2c_adap, msg, 2); + + if (ret != 2) { + ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n", + __func__, reg, ret); + + return -1; + } + + ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n", + __func__, addr, reg, buf[0]); + + return 0; +} + +int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, + u8 *buf, int len) +{ + int ret; + u8 buffer[len + 1]; + + struct i2c_msg msg = { + .addr = addr, + .flags = 0, + .buf = &buffer[0], + .len = len + 1 + }; + + buffer[0] = reg; + memcpy(&buffer[1], buf, len); + + ret = i2c_transfer(i2c_adap, &msg, 1); + + if (ret != 1) { + ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n", + __func__, reg, ret); + return -1; + } + + return 0; +} + +int netup_ci_get_mem(struct cx23885_dev *dev) +{ + int mem; + unsigned long timeout = jiffies + msecs_to_jiffies(1); + + for (;;) { + mem = cx_read(MC417_RWD); + if ((mem & NETUP_ACK) == 0) + break; + if (time_after(jiffies, timeout)) + break; + udelay(1); + } + + cx_set(MC417_RWD, NETUP_CTRL_OFF); + + return mem & 0xff; +} + +int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, + u8 flag, u8 read, u8 addr, u8 data) +{ + struct netup_ci_state *state = en50221->data; + struct cx23885_tsport *port = state->priv; + struct cx23885_dev *dev = port->dev; + + u8 store; + int mem; + int ret; + + if (0 != slot) + return -EINVAL; + + ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &store, 1); + if (ret != 0) + return ret; + + store &= ~0x0c; + store |= flag; + + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &store, 1); + if (ret != 0) + return ret; + + mutex_lock(&gpio_mutex); + + /* write addr */ + cx_write(MC417_OEN, NETUP_EN_ALL); + cx_write(MC417_RWD, NETUP_CTRL_OFF | + NETUP_ADLO | (0xff & addr)); + cx_clear(MC417_RWD, NETUP_ADLO); + cx_write(MC417_RWD, NETUP_CTRL_OFF | + NETUP_ADHI | (0xff & (addr >> 8))); + cx_clear(MC417_RWD, NETUP_ADHI); + + if (read) /* data in */ + cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA); + else /* data out */ + cx_write(MC417_RWD, NETUP_CTRL_OFF | data); + + /* choose chip */ + cx_clear(MC417_RWD, + (state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1); + /* read/write */ + cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR); + mem = netup_ci_get_mem(dev); + + mutex_unlock(&gpio_mutex); + + if (!read) + if (mem < 0) + return -EREMOTEIO; + + ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__, + (read) ? "read" : "write", addr, + (flag == NETUP_CI_CTL) ? "ctl" : "mem", + (read) ? mem : data); + + if (read) + return mem; + + return 0; +} + +int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr) +{ + return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0); +} + +int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data) +{ + return netup_ci_op_cam(en50221, slot, 0, 0, addr, data); +} + +int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) +{ + return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, + NETUP_CI_RD, addr, 0); +} + +int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, + u8 addr, u8 data) +{ + return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data); +} + +int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) +{ + struct netup_ci_state *state = en50221->data; + u8 buf = 0x80; + int ret; + + if (0 != slot) + return -EINVAL; + + udelay(500); + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); + + if (ret != 0) + return ret; + + udelay(500); + + buf = 0x00; + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); + + msleep(1000); + dvb_ca_en50221_camready_irq(&state->ca, 0); + + return 0; + +} + +int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) +{ + /* not implemented */ + return 0; +} + +int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot) +{ + struct netup_ci_state *state = en50221->data; + u8 buf = 0x60; + + if (0 != slot) + return -EINVAL; + + return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); +} + +/* work handler */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void netup_read_ci_status(void *_state) +#else +static void netup_read_ci_status(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct netup_ci_state *state = _state; +#else + struct netup_ci_state *state = + container_of(work, struct netup_ci_state, work); +#endif + u8 buf[33]; + int ret; + + ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf[0], 33); + + if (ret != 0) + return; + + ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, " + "TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0], + buf[32]); + + if (buf[0] && 1) + state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + else + state->status = 0; +} + +/* CI irq handler */ +int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status) +{ + struct cx23885_tsport *port = NULL; + struct netup_ci_state *state = NULL; + + if (pci_status & PCI_MSK_GPIO0) + port = &dev->ts1; + else if (pci_status & PCI_MSK_GPIO1) + port = &dev->ts2; + else /* who calls ? */ + return 0; + + state = port->port_priv; + + schedule_work(&state->work); + + return 1; +} + +int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) +{ + struct netup_ci_state *state = en50221->data; + + if (0 != slot) + return -EINVAL; + + return state->status; +} + +int netup_ci_init(struct cx23885_tsport *port) +{ + struct netup_ci_state *state; + u8 cimax_init[34] = { + 0x00, /* module A control*/ + 0x00, /* auto select mask high A */ + 0x00, /* auto select mask low A */ + 0x00, /* auto select pattern high A */ + 0x00, /* auto select pattern low A */ + 0x44, /* memory access time A */ + 0x00, /* invert input A */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* module B control*/ + 0x00, /* auto select mask high B */ + 0x00, /* auto select mask low B */ + 0x00, /* auto select pattern high B */ + 0x00, /* auto select pattern low B */ + 0x44, /* memory access time B */ + 0x00, /* invert input B */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* auto select mask high Ext */ + 0x00, /* auto select mask low Ext */ + 0x00, /* auto select pattern high Ext */ + 0x00, /* auto select pattern low Ext */ + 0x00, /* RFU */ + 0x02, /* destination - module A */ + 0x01, /* power on (use it like store place) */ + 0x00, /* RFU */ + 0x00, /* int status read only */ + 0x01, /* all int unmasked */ + 0x04, /* int config */ + 0x00, /* USCG1 */ + 0x04, /* ack active low */ + 0x00, /* LOCK = 0 */ + 0x33, /* serial mode, rising in, rising out, MSB first*/ + 0x31, /* syncronization */ + }; + int ret; + + ci_dbg_print("%s\n", __func__); + state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL); + if (!state) { + ci_dbg_print("%s: Unable create CI structure!\n", __func__); + ret = -ENOMEM; + goto err; + } + + port->port_priv = state; + + switch (port->nr) { + case 1: + state->ci_i2c_addr = 0x40; + mutex_init(&gpio_mutex); + break; + case 2: + state->ci_i2c_addr = 0x41; + break; + } + + state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap; + state->ca.owner = THIS_MODULE; + state->ca.read_attribute_mem = netup_ci_read_attribute_mem; + state->ca.write_attribute_mem = netup_ci_write_attribute_mem; + state->ca.read_cam_control = netup_ci_read_cam_ctl; + state->ca.write_cam_control = netup_ci_write_cam_ctl; + state->ca.slot_reset = netup_ci_slot_reset; + state->ca.slot_shutdown = netup_ci_slot_shutdown; + state->ca.slot_ts_enable = netup_ci_slot_ts_ctl; + state->ca.poll_slot_status = netup_poll_ci_slot_status; + state->ca.data = state; + state->priv = port; + + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &cimax_init[0], 34); + /* lock registers */ + ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0x1f, &cimax_init[0x18], 1); + /* power on slots */ + ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0x18, &cimax_init[0x18], 1); + + if (0 != ret) + goto err; + + ret = dvb_ca_en50221_init(&port->frontends.adapter, + &state->ca, + /* flags */ 0, + /* n_slots */ 1); + if (0 != ret) + goto err; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&state->work, netup_read_ci_status, state); +#else + INIT_WORK(&state->work, netup_read_ci_status); +#endif + + ci_dbg_print("%s: CI initialized!\n", __func__); + + return 0; +err: + ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret); + kfree(state); + return ret; +} + +void netup_ci_exit(struct cx23885_tsport *port) +{ + struct netup_ci_state *state; + + if (NULL == port) + return; + + state = (struct netup_ci_state *)port->port_priv; + if (NULL == state) + return; + + if (NULL == state->ca.data) + return; + + dvb_ca_en50221_release(&state->ca); + kfree(state); +} diff --git a/linux/drivers/media/video/cx23885/cimax2.h b/linux/drivers/media/video/cx23885/cimax2.h new file mode 100644 index 000000000..518744a4c --- /dev/null +++ b/linux/drivers/media/video/cx23885/cimax2.h @@ -0,0 +1,47 @@ +/* + * cimax2.h + * + * CIMax(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef CIMAX2_H +#define CIMAX2_H +#include "dvb_ca_en50221.h" + +extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr); +extern int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data); +extern int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, + int slot, u8 addr); +extern int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data); +extern int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status); +extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open); +extern int netup_ci_init(struct cx23885_tsport *port); +extern void netup_ci_exit(struct cx23885_tsport *port); + +#endif -- cgit v1.2.3 From 3a63a3eeda797603e69808ed6ccda24dc1211f56 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:16:40 +0200 Subject: Add support for ST STV6110 silicon tuner. From: Igor M. Liplianin The tuner is used in NetUP Dual DVB-S2 CI card. http://linuxtv.org/wiki/index.php/NetUP_Dual_DVB_S2_CI Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/stv6110.c | 457 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/stv6110.h | 62 ++++ 4 files changed, 527 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/stv6110.c create mode 100644 linux/drivers/media/dvb/frontends/stv6110.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 002695607..649ac75aa 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -83,6 +83,13 @@ config DVB_STV0299 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_STV6110 + tristate "ST STV6110 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S silicon tuner module. Say Y when you want to support this tuner. + config DVB_TDA8083 tristate "Philips TDA8083 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index af7bdf0ad..1d180fc71 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -64,4 +64,5 @@ obj-$(CONFIG_DVB_SI21XX) += si21xx.o obj-$(CONFIG_DVB_STV0288) += stv0288.o obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_S921) += s921.o +obj-$(CONFIG_DVB_STV6110) += stv6110.o diff --git a/linux/drivers/media/dvb/frontends/stv6110.c b/linux/drivers/media/dvb/frontends/stv6110.c new file mode 100644 index 000000000..94fd0fdae --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110.c @@ -0,0 +1,457 @@ +/* + * stv6110.c + * + * Driver for ST STV6110 satellite tuner IC. + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include "stv6110.h" +#include "cx23885.h" + +static int debug; + +struct stv6110_priv { + int i2c_address; + struct i2c_adapter *i2c; + + u32 mclk; + u8 regs[8]; +}; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG args); \ + } while (0) + +static s32 abssub(s32 a, s32 b) +{ + if (a > b) + return a - b; + else + return b - a; +}; + +static int stv6110_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[], + int start, int len) +{ + struct stv6110_priv *priv = fe->tuner_priv; + int rc; + u8 cmdbuf[len + 1]; + struct i2c_msg msg = { + .addr = priv->i2c_address, + .flags = 0, + .buf = cmdbuf, + .len = len + 1 + }; + + dprintk("%s\n", __func__); + + if (start + len > 8) + return -EINVAL; + + memcpy(&cmdbuf[1], buf, len); + cmdbuf[0] = start; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + rc = i2c_transfer(priv->i2c, &msg, 1); + if (rc != 1) + dprintk("%s: i2c error\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[], + int start, int len) +{ + struct stv6110_priv *priv = fe->tuner_priv; + int rc; + u8 reg[] = { start }; + struct i2c_msg msg_wr = { + .addr = priv->i2c_address, + .flags = 0, + .buf = reg, + .len = 1, + }; + + struct i2c_msg msg_rd = { + .addr = priv->i2c_address, + .flags = I2C_M_RD, + .buf = regs, + .len = len, + }; + /* write subaddr */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + rc = i2c_transfer(priv->i2c, &msg_wr, 1); + if (rc != 1) + dprintk("%s: i2c error\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + /* read registers */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + rc = i2c_transfer(priv->i2c, &msg_rd, 1); + if (rc != 1) + dprintk("%s: i2c error\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + memcpy(&priv->regs[start], regs, len); + + return 0; +} + +static int stv6110_read_reg(struct dvb_frontend *fe, int start) +{ + u8 buf[] = { 0 }; + stv6110_read_regs(fe, buf, start, 1); + + return buf[0]; +} + +static int stv6110_sleep(struct dvb_frontend *fe) +{ + u8 reg[] = { 0 }; + stv6110_write_regs(fe, reg, 0, 1); + + return 0; +} + +static u32 carrier_width(u32 symbol_rate, fe_rolloff_t rolloff) +{ + u32 rlf; + + switch (rolloff) { + case ROLLOFF_20: + rlf = 20; + break; + case ROLLOFF_25: + rlf = 25; + break; + default: + rlf = 35; + break; + } + + return symbol_rate + ((symbol_rate * rlf) / 100); +} + +static int stv6110_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) +{ + struct stv6110_priv *priv = fe->tuner_priv; + u8 r8, ret = 0x04; + int i; + + if ((bandwidth / 2) > 36000000) /*BW/2 max=31+5=36 mhz for r8=31*/ + r8 = 31; + else if ((bandwidth / 2) < 5000000) /* BW/2 min=5Mhz for F=0 */ + r8 = 0; + else /*if 5 < BW/2 < 36*/ + r8 = (bandwidth / 2) / 1000000 - 5; + + /* ctrl3, RCCLKOFF = 0 Activate the calibration Clock */ + /* ctrl3, CF = r8 Set the LPF value */ + priv->regs[RSTV6110_CTRL3] &= ~((1 << 6) | 0x1f); + priv->regs[RSTV6110_CTRL3] |= (r8 & 0x1f); + stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1); + /* stat1, CALRCSTRT = 1 Start LPF auto calibration*/ + priv->regs[RSTV6110_STAT1] |= 0x02; + stv6110_write_regs(fe, &priv->regs[RSTV6110_STAT1], RSTV6110_STAT1, 1); + + i = 0; + /* Wait for CALRCSTRT == 0 */ + while ((i < 10) && (ret != 0)) { + ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x02); + mdelay(1); /* wait for LPF auto calibration */ + i++; + } + + /* RCCLKOFF = 1 calibration done, desactivate the calibration Clock */ + priv->regs[RSTV6110_CTRL3] |= (1 << 6); + stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1); + return 0; +} + +static int stv6110_init(struct dvb_frontend *fe) +{ + struct stv6110_priv *priv = fe->tuner_priv; + u8 buf0[] = { 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e }; + + memcpy(priv->regs, buf0, 8); + /* K = (Reference / 1000000) - 16 */ + priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3); + priv->regs[RSTV6110_CTRL1] |= + ((((priv->mclk / 1000000) - 16) & 0x1f) << 3); + + stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8); + msleep(1); + stv6110_set_bandwidth(fe, 72000000); + + return 0; +} + +static int stv6110_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct stv6110_priv *priv = fe->tuner_priv; + u32 nbsteps, divider, psd2, freq; + u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + stv6110_read_regs(fe, regs, 0, 8); + /*N*/ + divider = (priv->regs[RSTV6110_TUNING2] & 0x0f) << 8; + divider += priv->regs[RSTV6110_TUNING1]; + + /*R*/ + nbsteps = (priv->regs[RSTV6110_TUNING2] >> 6) & 3; + /*p*/ + psd2 = (priv->regs[RSTV6110_TUNING2] >> 4) & 1; + + freq = divider * (priv->mclk / 1000); + freq /= (1 << (nbsteps + psd2)); + freq /= 4; + + *frequency = freq; + + return 0; +} + +static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency) +{ + struct stv6110_priv *priv = fe->tuner_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u8 ret = 0x04; + u32 divider, ref, p, presc, i, result_freq, vco_freq; + s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val; + s32 srate; u8 gain; + + dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__, + frequency, priv->mclk); + + /* K = (Reference / 1000000) - 16 */ + priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3); + priv->regs[RSTV6110_CTRL1] |= + ((((priv->mclk / 1000000) - 16) & 0x1f) << 3); + + /* BB_GAIN = db/2 */ + if (fe->ops.set_property && fe->ops.get_property) { + srate = c->symbol_rate; + dprintk("%s: Get Frontend parameters: srate=%d\n", + __func__, srate); + } else + srate = 15000000; + + if (srate >= 15000000) + gain = 3; /* +6 dB */ + else if (srate >= 5000000) + gain = 3; /* +6 dB */ + else + gain = 3; /* +6 dB */ + + priv->regs[RSTV6110_CTRL2] &= ~0x0f; + priv->regs[RSTV6110_CTRL2] |= (gain & 0x0f); + + if (frequency <= 1023000) { + p = 1; + presc = 0; + } else if (frequency <= 1300000) { + p = 1; + presc = 1; + } else if (frequency <= 2046000) { + p = 0; + presc = 0; + } else { + p = 0; + presc = 1; + } + /* DIV4SEL = p*/ + priv->regs[RSTV6110_TUNING2] &= ~(1 << 4); + priv->regs[RSTV6110_TUNING2] |= (p << 4); + + /* PRESC32ON = presc */ + priv->regs[RSTV6110_TUNING2] &= ~(1 << 5); + priv->regs[RSTV6110_TUNING2] |= (presc << 5); + + p_val = (int)(1 << (p + 1)) * 10;/* P = 2 or P = 4 */ + for (r_div = 0; r_div <= 3; r_div++) { + p_calc = (priv->mclk / 100000); + p_calc /= (1 << (r_div + 1)); + if ((abssub(p_calc, p_val)) < (abssub(p_calc_opt, p_val))) + r_div_opt = r_div; + + p_calc_opt = (priv->mclk / 100000); + p_calc_opt /= (1 << (r_div_opt + 1)); + } + + ref = priv->mclk / ((1 << (r_div_opt + 1)) * (1 << (p + 1))); + divider = (((frequency * 1000) + (ref >> 1)) / ref); + + /* RDIV = r_div_opt */ + priv->regs[RSTV6110_TUNING2] &= ~(3 << 6); + priv->regs[RSTV6110_TUNING2] |= (((r_div_opt) & 3) << 6); + + /* NDIV_MSB = MSB(divider) */ + priv->regs[RSTV6110_TUNING2] &= ~0x0f; + priv->regs[RSTV6110_TUNING2] |= (((divider) >> 8) & 0x0f); + + /* NDIV_LSB, LSB(divider) */ + priv->regs[RSTV6110_TUNING1] = (divider & 0xff); + + /* CALVCOSTRT = 1 VCO Auto Calibration */ + priv->regs[RSTV6110_STAT1] |= 0x04; + stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], + RSTV6110_CTRL1, 8); + + i = 0; + /* Wait for CALVCOSTRT == 0 */ + while ((i < 10) && (ret != 0)) { + ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x04); + msleep(1); /* wait for VCO auto calibration */ + i++; + } + + ret = stv6110_read_reg(fe, RSTV6110_STAT1); + stv6110_get_frequency(fe, &result_freq); + + vco_freq = divider * ((priv->mclk / 1000) / ((1 << (r_div_opt + 1)))); + dprintk("%s, stat1=%x, lo_freq=%d kHz, vco_frec=%d kHz\n", __func__, + ret, result_freq, vco_freq); + + return 0; +} + +static int stv6110_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 bandwidth = carrier_width(c->symbol_rate, c->rolloff); + + stv6110_set_frequency(fe, c->frequency); + stv6110_set_bandwidth(fe, bandwidth); + + return 0; +} + +static int stv6110_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct stv6110_priv *priv = fe->tuner_priv; + u8 r8 = 0; + u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + stv6110_read_regs(fe, regs, 0, 8); + + /* CF */ + r8 = priv->regs[RSTV6110_CTRL3] & 0x1f; + *bandwidth = (r8 + 5) * 2000000;/* x2 for ZIF tuner BW/2 = F+5 Mhz */ + + return 0; +} + +static struct dvb_tuner_ops stv6110_tuner_ops = { + .info = { + .name = "ST STV6110", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 1000, + }, + .init = stv6110_init, + .release = stv6110_release, + .sleep = stv6110_sleep, + .set_params = stv6110_set_params, + .get_frequency = stv6110_get_frequency, + .set_frequency = stv6110_set_frequency, + .get_bandwidth = stv6110_get_bandwidth, + .set_bandwidth = stv6110_set_bandwidth, + +}; + +struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, + const struct stv6110_config *config, + struct i2c_adapter *i2c) +{ + struct stv6110_priv *priv = NULL; + u8 reg0[] = { 0x00, 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e }; + + struct i2c_msg msg[] = { + { + .addr = config->i2c_address, + .flags = 0, + .buf = reg0, + .len = 9 + } + }; + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = i2c_transfer(i2c, msg, 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 1) + return NULL; + + priv = kzalloc(sizeof(struct stv6110_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c_address = config->i2c_address; + priv->i2c = i2c; + priv->mclk = config->mclk; + + memcpy(&priv->regs, ®0[1], 8); + + memcpy(&fe->ops.tuner_ops, &stv6110_tuner_ops, + sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = priv; + printk(KERN_INFO "STV6110 attached on addr=%x!\n", priv->i2c_address); + + return fe; +} +EXPORT_SYMBOL(stv6110_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("ST STV6110 driver"); +MODULE_AUTHOR("Igor M. Liplianin"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/stv6110.h b/linux/drivers/media/dvb/frontends/stv6110.h new file mode 100644 index 000000000..1c0314d6a --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110.h @@ -0,0 +1,62 @@ +/* + * stv6110.h + * + * Driver for ST STV6110 satellite tuner IC. + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __DVB_STV6110_H__ +#define __DVB_STV6110_H__ + +#include +#include "dvb_frontend.h" + +/* registers */ +#define RSTV6110_CTRL1 0 +#define RSTV6110_CTRL2 1 +#define RSTV6110_TUNING1 2 +#define RSTV6110_TUNING2 3 +#define RSTV6110_CTRL3 4 +#define RSTV6110_STAT1 5 +#define RSTV6110_STAT2 6 +#define RSTV6110_STAT3 7 + +struct stv6110_config { + u8 i2c_address; + u32 mclk; + int iq_wiring; +}; + +#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, + const struct stv6110_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, + const struct stv6110_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif -- cgit v1.2.3 From d28ebd352e3ba605339c028654d46fd140bbc58d Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:24:18 +0200 Subject: Add support for ST LNBH24 LNB power controller. From: Igor M. Liplianin The controller consist of two independent parts. Every part is similar to LNBP21, but has configurable i2c address. It is used in NetUP Dual DVB-S2 CI card. http://linuxtv.org/wiki/index.php/NetUP_Dual_DVB_S2_CI Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/Kconfig | 4 +-- linux/drivers/media/dvb/frontends/lnbh24.h | 55 ++++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/lnbp21.c | 41 +++++++++++++++++----- linux/drivers/media/dvb/frontends/lnbp21.h | 50 +++++++++++++++++++-------- 4 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/lnbh24.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 649ac75aa..d3cfced2c 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -453,11 +453,11 @@ comment "SEC control devices for DVB-S" depends on DVB_CORE config DVB_LNBP21 - tristate "LNBP21 SEC controller" + tristate "LNBP21/LNBH24 SEC controllers" depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help - An SEC control chip. + An SEC control chips. config DVB_ISL6405 tristate "ISL6405 SEC controller" diff --git a/linux/drivers/media/dvb/frontends/lnbh24.h b/linux/drivers/media/dvb/frontends/lnbh24.h new file mode 100644 index 000000000..c059b1653 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lnbh24.h @@ -0,0 +1,55 @@ +/* + * lnbh24.h - driver for lnb supply and control ic lnbh24 + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LNBH24_H +#define _LNBH24_H + +/* system register bits */ +#define LNBH24_OLF 0x01 +#define LNBH24_OTF 0x02 +#define LNBH24_EN 0x04 +#define LNBH24_VSEL 0x08 +#define LNBH24_LLC 0x10 +#define LNBH24_TEN 0x20 +#define LNBH24_TTX 0x40 +#define LNBH24_PCL 0x80 + +#include + +#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \ + && defined(MODULE)) +/* override_set and override_clear control which + system register bits (above) to always set & clear */ +extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear, u8 i2c_addr); +#else +static inline struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear, u8 i2c_addr) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c index 76f935d97..772a0bbb0 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.c +++ b/linux/drivers/media/dvb/frontends/lnbp21.c @@ -1,7 +1,8 @@ /* - * lnbp21.h - driver for lnb supply and control ic lnbp21 + * lnbp21.c - driver for lnb supply and control ic lnbp21 * * Copyright (C) 2006 Oliver Endriss + * Copyright (C) 2009 Igor M. Liplianin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,18 +34,21 @@ #include "dvb_frontend.h" #include "lnbp21.h" +#include "lnbh24.h" struct lnbp21 { u8 config; u8 override_or; u8 override_and; struct i2c_adapter *i2c; + u8 i2c_addr; }; -static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +static int lnbp21_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) { struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, + struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0, .buf = &lnbp21->config, .len = sizeof(lnbp21->config) }; @@ -72,7 +76,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) { struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, + struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0, .buf = &lnbp21->config, .len = sizeof(lnbp21->config) }; @@ -97,15 +101,18 @@ static void lnbp21_release(struct dvb_frontend *fe) fe->sec_priv = NULL; } -struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear, u8 i2c_addr, u8 config) { struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); if (!lnbp21) return NULL; /* default configuration */ - lnbp21->config = LNBP21_ISEL; + lnbp21->config = config; lnbp21->i2c = i2c; + lnbp21->i2c_addr = i2c_addr; fe->sec_priv = lnbp21; /* bits which should be forced to '1' */ @@ -126,11 +133,29 @@ struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter * /* override frontend ops */ fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr); return fe; } + +struct dvb_frontend *lnbp24_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear, u8 i2c_addr) +{ + return lnbx2x_attach(fe, i2c, override_set, override_clear, + i2c_addr, LNBH24_TTX); +} +EXPORT_SYMBOL(lnbh24_attach); + +struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear) +{ + return lnbx2x_attach(fe, i2c, override_set, override_clear, + 0x08, LNBP21_ISEL); +} EXPORT_SYMBOL(lnbp21_attach); -MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21"); -MODULE_AUTHOR("Oliver Endriss"); +MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24"); +MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h index b87458874..fcdf1c650 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.h +++ b/linux/drivers/media/dvb/frontends/lnbp21.h @@ -28,26 +28,48 @@ #define _LNBP21_H /* system register bits */ -#define LNBP21_OLF 0x01 /* [R-only] 0=OK; 1=over current limit flag*/ -#define LNBP21_OTF 0x02 /* [R-only] 0=OK; 1=over temperature flag (150degC typ) */ -#define LNBP21_EN 0x04 /* [RW] 0=disable LNB power, enable loopthrough; 1=enable LNB power, disable loopthrough*/ -#define LNBP21_VSEL 0x08 /* [RW] 0=low voltage (13/14V, vert pol); 1=high voltage (18/19V,horiz pol) */ -#define LNBP21_LLC 0x10 /* [RW] increase LNB voltage by 1V: 0=13/18V; 1=14/19V */ -#define LNBP21_TEN 0x20 /* [RW] 0=tone controlled by DSQIN pin; 1=tone enable, disable DSQIN */ -#define LNBP21_ISEL 0x40 /* [RW] current limit select 0:Iout=500-650mA,Isc=300mA ; 1:Iout=400-550mA,Isc=200mA*/ -#define LNBP21_PCL 0x80 /* [RW] short-circuit prot: 0=pulsed (dynamic) curr limiting; 1=static curr limiting*/ +/* [RO] 0=OK; 1=over current limit flag */ +#define LNBP21_OLF 0x01 +/* [RO] 0=OK; 1=over temperature flag (150 C) */ +#define LNBP21_OTF 0x02 +/* [RW] 0=disable LNB power, enable loopthrough + 1=enable LNB power, disable loopthrough */ +#define LNBP21_EN 0x04 +/* [RW] 0=low voltage (13/14V, vert pol) + 1=high voltage (18/19V,horiz pol) */ +#define LNBP21_VSEL 0x08 +/* [RW] increase LNB voltage by 1V: + 0=13/18V; 1=14/19V */ +#define LNBP21_LLC 0x10 +/* [RW] 0=tone controlled by DSQIN pin + 1=tone enable, disable DSQIN */ +#define LNBP21_TEN 0x20 +/* [RW] current limit select: + 0:Iout=500-650mA Isc=300mA + 1:Iout=400-550mA Isc=200mA */ +#define LNBP21_ISEL 0x40 +/* [RW] short-circuit protect: + 0=pulsed (dynamic) curr limiting + 1=static curr limiting */ +#define LNBP21_PCL 0x80 #include -#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) && defined(MODULE)) -/* override_set and override_clear control which system register bits (above) to always set & clear */ -extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); +#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \ + && defined(MODULE)) +/* override_set and override_clear control which + system register bits (above) to always set & clear */ +extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear); #else -static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 override_set, + u8 override_clear) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -#endif // CONFIG_DVB_LNBP21 +#endif -#endif // _LNBP21_H +#endif -- cgit v1.2.3 From 751f6c61ef5f94acc81c1725f51bf59bca9127fa Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:35:25 +0200 Subject: Add headers for ST STV0900 dual demodulator. From: Igor M. Liplianin The IC consist of two dependent parts. It may use single or dual mode. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900.h | 62 + linux/drivers/media/dvb/frontends/stv0900_reg.h | 3787 +++++++++++++++++++++++ 2 files changed, 3849 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/stv0900.h create mode 100644 linux/drivers/media/dvb/frontends/stv0900_reg.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900.h b/linux/drivers/media/dvb/frontends/stv0900.h new file mode 100644 index 000000000..8a1332c20 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv0900.h @@ -0,0 +1,62 @@ +/* + * stv0900.h + * + * Driver for ST STV0900 satellite demodulator IC. + * + * Copyright (C) ST Microelectronics. + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef STV0900_H +#define STV0900_H + +#include +#include "dvb_frontend.h" + +struct stv0900_config { + u8 demod_address; + u32 xtal; + u8 clkmode;/* 0 for CLKI, 2 for XTALI */ + + u8 diseqc_mode; + + u8 path1_mode; + u8 path2_mode; + + u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */ + u8 tun2_maddress; + u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ + u8 tun2_adc; +}; + +#if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, + struct i2c_adapter *i2c, int demod); +#else +static inline struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, + struct i2c_adapter *i2c, int demod) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif + diff --git a/linux/drivers/media/dvb/frontends/stv0900_reg.h b/linux/drivers/media/dvb/frontends/stv0900_reg.h new file mode 100644 index 000000000..264f9cf9a --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv0900_reg.h @@ -0,0 +1,3787 @@ +/* + * stv0900_reg.h + * + * Driver for ST STV0900 satellite demodulator IC. + * + * Copyright (C) ST Microelectronics. + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef STV0900_REG_H +#define STV0900_REG_H + +/*MID*/ +#define R0900_MID 0xf100 +#define F0900_MCHIP_IDENT 0xf10000f0 +#define F0900_MRELEASE 0xf100000f + +/*DACR1*/ +#define R0900_DACR1 0xf113 +#define F0900_DAC_MODE 0xf11300e0 +#define F0900_DAC_VALUE1 0xf113000f + +/*DACR2*/ +#define R0900_DACR2 0xf114 +#define F0900_DAC_VALUE0 0xf11400ff + +/*OUTCFG*/ +#define R0900_OUTCFG 0xf11c +#define F0900_INV_DATA6 0xf11c0080 +#define F0900_OUTSERRS1_HZ 0xf11c0040 +#define F0900_OUTSERRS2_HZ 0xf11c0020 +#define F0900_OUTSERRS3_HZ 0xf11c0010 +#define F0900_OUTPARRS3_HZ 0xf11c0008 +#define F0900_OUTHZ3_CONTROL 0xf11c0007 + +/*MODECFG*/ +#define R0900_MODECFG 0xf11d +#define F0900_FECSPY_SEL_2 0xf11d0020 +#define F0900_HWARE_SEL_2 0xf11d0010 +#define F0900_PKTDEL_SEL_2 0xf11d0008 +#define F0900_DISEQC_SEL_2 0xf11d0004 +#define F0900_VIT_SEL_2 0xf11d0002 +#define F0900_DEMOD_SEL_2 0xf11d0001 + +/*IRQSTATUS3*/ +#define R0900_IRQSTATUS3 0xf120 +#define F0900_SPLL_LOCK 0xf1200020 +#define F0900_SSTREAM_LCK_3 0xf1200010 +#define F0900_SSTREAM_LCK_2 0xf1200008 +#define F0900_SSTREAM_LCK_1 0xf1200004 +#define F0900_SDVBS1_PRF_2 0xf1200002 +#define F0900_SDVBS1_PRF_1 0xf1200001 + +/*IRQSTATUS2*/ +#define R0900_IRQSTATUS2 0xf121 +#define F0900_SSPY_ENDSIM_3 0xf1210080 +#define F0900_SSPY_ENDSIM_2 0xf1210040 +#define F0900_SSPY_ENDSIM_1 0xf1210020 +#define F0900_SPKTDEL_ERROR_2 0xf1210010 +#define F0900_SPKTDEL_LOCKB_2 0xf1210008 +#define F0900_SPKTDEL_LOCK_2 0xf1210004 +#define F0900_SPKTDEL_ERROR_1 0xf1210002 +#define F0900_SPKTDEL_LOCKB_1 0xf1210001 + +/*IRQSTATUS1*/ +#define R0900_IRQSTATUS1 0xf122 +#define F0900_SPKTDEL_LOCK_1 0xf1220080 +#define F0900_SEXTPINB2 0xf1220040 +#define F0900_SEXTPIN2 0xf1220020 +#define F0900_SEXTPINB1 0xf1220010 +#define F0900_SEXTPIN1 0xf1220008 +#define F0900_SDEMOD_LOCKB_2 0xf1220004 +#define F0900_SDEMOD_LOCK_2 0xf1220002 +#define F0900_SDEMOD_IRQ_2 0xf1220001 + +/*IRQSTATUS0*/ +#define R0900_IRQSTATUS0 0xf123 +#define F0900_SDEMOD_LOCKB_1 0xf1230080 +#define F0900_SDEMOD_LOCK_1 0xf1230040 +#define F0900_SDEMOD_IRQ_1 0xf1230020 +#define F0900_SBCH_ERRFLAG 0xf1230010 +#define F0900_SDISEQC2RX_IRQ 0xf1230008 +#define F0900_SDISEQC2TX_IRQ 0xf1230004 +#define F0900_SDISEQC1RX_IRQ 0xf1230002 +#define F0900_SDISEQC1TX_IRQ 0xf1230001 + +/*IRQMASK3*/ +#define R0900_IRQMASK3 0xf124 +#define F0900_MPLL_LOCK 0xf1240020 +#define F0900_MSTREAM_LCK_3 0xf1240010 +#define F0900_MSTREAM_LCK_2 0xf1240008 +#define F0900_MSTREAM_LCK_1 0xf1240004 +#define F0900_MDVBS1_PRF_2 0xf1240002 +#define F0900_MDVBS1_PRF_1 0xf1240001 + +/*IRQMASK2*/ +#define R0900_IRQMASK2 0xf125 +#define F0900_MSPY_ENDSIM_3 0xf1250080 +#define F0900_MSPY_ENDSIM_2 0xf1250040 +#define F0900_MSPY_ENDSIM_1 0xf1250020 +#define F0900_MPKTDEL_ERROR_2 0xf1250010 +#define F0900_MPKTDEL_LOCKB_2 0xf1250008 +#define F0900_MPKTDEL_LOCK_2 0xf1250004 +#define F0900_MPKTDEL_ERROR_1 0xf1250002 +#define F0900_MPKTDEL_LOCKB_1 0xf1250001 + +/*IRQMASK1*/ +#define R0900_IRQMASK1 0xf126 +#define F0900_MPKTDEL_LOCK_1 0xf1260080 +#define F0900_MEXTPINB2 0xf1260040 +#define F0900_MEXTPIN2 0xf1260020 +#define F0900_MEXTPINB1 0xf1260010 +#define F0900_MEXTPIN1 0xf1260008 +#define F0900_MDEMOD_LOCKB_2 0xf1260004 +#define F0900_MDEMOD_LOCK_2 0xf1260002 +#define F0900_MDEMOD_IRQ_2 0xf1260001 + +/*IRQMASK0*/ +#define R0900_IRQMASK0 0xf127 +#define F0900_MDEMOD_LOCKB_1 0xf1270080 +#define F0900_MDEMOD_LOCK_1 0xf1270040 +#define F0900_MDEMOD_IRQ_1 0xf1270020 +#define F0900_MBCH_ERRFLAG 0xf1270010 +#define F0900_MDISEQC2RX_IRQ 0xf1270008 +#define F0900_MDISEQC2TX_IRQ 0xf1270004 +#define F0900_MDISEQC1RX_IRQ 0xf1270002 +#define F0900_MDISEQC1TX_IRQ 0xf1270001 + +/*I2CCFG*/ +#define R0900_I2CCFG 0xf129 +#define F0900_I2C2_FASTMODE 0xf1290080 +#define F0900_STATUS_WR2 0xf1290040 +#define F0900_I2C2ADDR_INC 0xf1290030 +#define F0900_I2C_FASTMODE 0xf1290008 +#define F0900_STATUS_WR 0xf1290004 +#define F0900_I2CADDR_INC 0xf1290003 + +/*P1_I2CRPT*/ +#define R0900_P1_I2CRPT 0xf12a +#define F0900_P1_I2CT_ON 0xf12a0080 +#define F0900_P1_ENARPT_LEVEL 0xf12a0070 +#define F0900_P1_SCLT_DELAY 0xf12a0008 +#define F0900_P1_STOP_ENABLE 0xf12a0004 +#define F0900_P1_STOP_SDAT2SDA 0xf12a0002 + +/*P2_I2CRPT*/ +#define R0900_P2_I2CRPT 0xf12b +#define F0900_P2_I2CT_ON 0xf12b0080 +#define F0900_P2_ENARPT_LEVEL 0xf12b0070 +#define F0900_P2_SCLT_DELAY 0xf12b0008 +#define F0900_P2_STOP_ENABLE 0xf12b0004 +#define F0900_P2_STOP_SDAT2SDA 0xf12b0002 + +/*CLKI2CFG*/ +#define R0900_CLKI2CFG 0xf140 +#define F0900_CLKI2_OPD 0xf1400080 +#define F0900_CLKI2_CONFIG 0xf140007e +#define F0900_CLKI2_XOR 0xf1400001 + +/*GPIO1CFG*/ +#define R0900_GPIO1CFG 0xf141 +#define F0900_GPIO1_OPD 0xf1410080 +#define F0900_GPIO1_CONFIG 0xf141007e +#define F0900_GPIO1_XOR 0xf1410001 + +/*GPIO2CFG*/ +#define R0900_GPIO2CFG 0xf142 +#define F0900_GPIO2_OPD 0xf1420080 +#define F0900_GPIO2_CONFIG 0xf142007e +#define F0900_GPIO2_XOR 0xf1420001 + +/*GPIO3CFG*/ +#define R0900_GPIO3CFG 0xf143 +#define F0900_GPIO3_OPD 0xf1430080 +#define F0900_GPIO3_CONFIG 0xf143007e +#define F0900_GPIO3_XOR 0xf1430001 + +/*GPIO4CFG*/ +#define R0900_GPIO4CFG 0xf144 +#define F0900_GPIO4_OPD 0xf1440080 +#define F0900_GPIO4_CONFIG 0xf144007e +#define F0900_GPIO4_XOR 0xf1440001 + +/*GPIO5CFG*/ +#define R0900_GPIO5CFG 0xf145 +#define F0900_GPIO5_OPD 0xf1450080 +#define F0900_GPIO5_CONFIG 0xf145007e +#define F0900_GPIO5_XOR 0xf1450001 + +/*GPIO6CFG*/ +#define R0900_GPIO6CFG 0xf146 +#define F0900_GPIO6_OPD 0xf1460080 +#define F0900_GPIO6_CONFIG 0xf146007e +#define F0900_GPIO6_XOR 0xf1460001 + +/*GPIO7CFG*/ +#define R0900_GPIO7CFG 0xf147 +#define F0900_GPIO7_OPD 0xf1470080 +#define F0900_GPIO7_CONFIG 0xf147007e +#define F0900_GPIO7_XOR 0xf1470001 + +/*GPIO8CFG*/ +#define R0900_GPIO8CFG 0xf148 +#define F0900_GPIO8_OPD 0xf1480080 +#define F0900_GPIO8_CONFIG 0xf148007e +#define F0900_GPIO8_XOR 0xf1480001 + +/*GPIO9CFG*/ +#define R0900_GPIO9CFG 0xf149 +#define F0900_GPIO9_OPD 0xf1490080 +#define F0900_GPIO9_CONFIG 0xf149007e +#define F0900_GPIO9_XOR 0xf1490001 + +/*GPIO10CFG*/ +#define R0900_GPIO10CFG 0xf14a +#define F0900_GPIO10_OPD 0xf14a0080 +#define F0900_GPIO10_CONFIG 0xf14a007e +#define F0900_GPIO10_XOR 0xf14a0001 + +/*GPIO11CFG*/ +#define R0900_GPIO11CFG 0xf14b +#define F0900_GPIO11_OPD 0xf14b0080 +#define F0900_GPIO11_CONFIG 0xf14b007e +#define F0900_GPIO11_XOR 0xf14b0001 + +/*GPIO12CFG*/ +#define R0900_GPIO12CFG 0xf14c +#define F0900_GPIO12_OPD 0xf14c0080 +#define F0900_GPIO12_CONFIG 0xf14c007e +#define F0900_GPIO12_XOR 0xf14c0001 + +/*GPIO13CFG*/ +#define R0900_GPIO13CFG 0xf14d +#define F0900_GPIO13_OPD 0xf14d0080 +#define F0900_GPIO13_CONFIG 0xf14d007e +#define F0900_GPIO13_XOR 0xf14d0001 + +/*CS0CFG*/ +#define R0900_CS0CFG 0xf14e +#define F0900_CS0_OPD 0xf14e0080 +#define F0900_CS0_CONFIG 0xf14e007e +#define F0900_CS0_XOR 0xf14e0001 + +/*CS1CFG*/ +#define R0900_CS1CFG 0xf14f +#define F0900_CS1_OPD 0xf14f0080 +#define F0900_CS1_CONFIG 0xf14f007e +#define F0900_CS1_XOR 0xf14f0001 + +/*STDBYCFG*/ +#define R0900_STDBYCFG 0xf150 +#define F0900_STDBY_OPD 0xf1500080 +#define F0900_STDBY_CONFIG 0xf150007e +#define F0900_STBDY_XOR 0xf1500001 + +/*DIRCLKCFG*/ +#define R0900_DIRCLKCFG 0xf151 +#define F0900_DIRCLK_OPD 0xf1510080 +#define F0900_DIRCLK_CONFIG 0xf151007e +#define F0900_DIRCLK_XOR 0xf1510001 + +/*AGCRF1CFG*/ +#define R0900_AGCRF1CFG 0xf152 +#define F0900_AGCRF1_OPD 0xf1520080 +#define F0900_AGCRF1_CONFIG 0xf152007e +#define F0900_AGCRF1_XOR 0xf1520001 + +/*SDAT1CFG*/ +#define R0900_SDAT1CFG 0xf153 +#define F0900_SDAT1_OPD 0xf1530080 +#define F0900_SDAT1_CONFIG 0xf153007e +#define F0900_SDAT1_XOR 0xf1530001 + +/*SCLT1CFG*/ +#define R0900_SCLT1CFG 0xf154 +#define F0900_SCLT1_OPD 0xf1540080 +#define F0900_SCLT1_CONFIG 0xf154007e +#define F0900_SCLT1_XOR 0xf1540001 + +/*DISEQCO1CFG*/ +#define R0900_DISEQCO1CFG 0xf155 +#define F0900_DISEQCO1_OPD 0xf1550080 +#define F0900_DISEQCO1_CONFIG 0xf155007e +#define F0900_DISEQC1_XOR 0xf1550001 + +/*AGCRF2CFG*/ +#define R0900_AGCRF2CFG 0xf156 +#define F0900_AGCRF2_OPD 0xf1560080 +#define F0900_AGCRF2_CONFIG 0xf156007e +#define F0900_AGCRF2_XOR 0xf1560001 + +/*SDAT2CFG*/ +#define R0900_SDAT2CFG 0xf157 +#define F0900_SDAT2_OPD 0xf1570080 +#define F0900_SDAT2_CONFIG 0xf157007e +#define F0900_SDAT2_XOR 0xf1570001 + +/*SCLT2CFG*/ +#define R0900_SCLT2CFG 0xf158 +#define F0900_SCLT2_OPD 0xf1580080 +#define F0900_SCLT2_CONFIG 0xf158007e +#define F0900_SCLT2_XOR 0xf1580001 + +/*DISEQCO2CFG*/ +#define R0900_DISEQCO2CFG 0xf159 +#define F0900_DISEQCO2_OPD 0xf1590080 +#define F0900_DISEQCO2_CONFIG 0xf159007e +#define F0900_DISEQC2_XOR 0xf1590001 + +/*CLKOUT27CFG*/ +#define R0900_CLKOUT27CFG 0xf15a +#define F0900_CLKOUT27_OPD 0xf15a0080 +#define F0900_CLKOUT27_CONFIG 0xf15a007e +#define F0900_CLKOUT27_XOR 0xf15a0001 + +/*ERROR1CFG*/ +#define R0900_ERROR1CFG 0xf15b +#define F0900_ERROR1_OPD 0xf15b0080 +#define F0900_ERROR1_CONFIG 0xf15b007e +#define F0900_ERROR1_XOR 0xf15b0001 + +/*DPN1CFG*/ +#define R0900_DPN1CFG 0xf15c +#define F0900_DPN1_OPD 0xf15c0080 +#define F0900_DPN1_CONFIG 0xf15c007e +#define F0900_DPN1_XOR 0xf15c0001 + +/*STROUT1CFG*/ +#define R0900_STROUT1CFG 0xf15d +#define F0900_STROUT1_OPD 0xf15d0080 +#define F0900_STROUT1_CONFIG 0xf15d007e +#define F0900_STROUT1_XOR 0xf15d0001 + +/*CLKOUT1CFG*/ +#define R0900_CLKOUT1CFG 0xf15e +#define F0900_CLKOUT1_OPD 0xf15e0080 +#define F0900_CLKOUT1_CONFIG 0xf15e007e +#define F0900_CLKOUT1_XOR 0xf15e0001 + +/*DATA71CFG*/ +#define R0900_DATA71CFG 0xf15f +#define F0900_DATA71_OPD 0xf15f0080 +#define F0900_DATA71_CONFIG 0xf15f007e +#define F0900_DATA71_XOR 0xf15f0001 + +/*ERROR2CFG*/ +#define R0900_ERROR2CFG 0xf160 +#define F0900_ERROR2_OPD 0xf1600080 +#define F0900_ERROR2_CONFIG 0xf160007e +#define F0900_ERROR2_XOR 0xf1600001 + +/*DPN2CFG*/ +#define R0900_DPN2CFG 0xf161 +#define F0900_DPN2_OPD 0xf1610080 +#define F0900_DPN2_CONFIG 0xf161007e +#define F0900_DPN2_XOR 0xf1610001 + +/*STROUT2CFG*/ +#define R0900_STROUT2CFG 0xf162 +#define F0900_STROUT2_OPD 0xf1620080 +#define F0900_STROUT2_CONFIG 0xf162007e +#define F0900_STROUT2_XOR 0xf1620001 + +/*CLKOUT2CFG*/ +#define R0900_CLKOUT2CFG 0xf163 +#define F0900_CLKOUT2_OPD 0xf1630080 +#define F0900_CLKOUT2_CONFIG 0xf163007e +#define F0900_CLKOUT2_XOR 0xf1630001 + +/*DATA72CFG*/ +#define R0900_DATA72CFG 0xf164 +#define F0900_DATA72_OPD 0xf1640080 +#define F0900_DATA72_CONFIG 0xf164007e +#define F0900_DATA72_XOR 0xf1640001 + +/*ERROR3CFG*/ +#define R0900_ERROR3CFG 0xf165 +#define F0900_ERROR3_OPD 0xf1650080 +#define F0900_ERROR3_CONFIG 0xf165007e +#define F0900_ERROR3_XOR 0xf1650001 + +/*DPN3CFG*/ +#define R0900_DPN3CFG 0xf166 +#define F0900_DPN3_OPD 0xf1660080 +#define F0900_DPN3_CONFIG 0xf166007e +#define F0900_DPN3_XOR 0xf1660001 + +/*STROUT3CFG*/ +#define R0900_STROUT3CFG 0xf167 +#define F0900_STROUT3_OPD 0xf1670080 +#define F0900_STROUT3_CONFIG 0xf167007e +#define F0900_STROUT3_XOR 0xf1670001 + +/*CLKOUT3CFG*/ +#define R0900_CLKOUT3CFG 0xf168 +#define F0900_CLKOUT3_OPD 0xf1680080 +#define F0900_CLKOUT3_CONFIG 0xf168007e +#define F0900_CLKOUT3_XOR 0xf1680001 + +/*DATA73CFG*/ +#define R0900_DATA73CFG 0xf169 +#define F0900_DATA73_OPD 0xf1690080 +#define F0900_DATA73_CONFIG 0xf169007e +#define F0900_DATA73_XOR 0xf1690001 + +/*FSKTFC2*/ +#define R0900_FSKTFC2 0xf170 +#define F0900_FSKT_KMOD 0xf17000fc +#define F0900_FSKT_CAR2 0xf1700003 + +/*FSKTFC1*/ +#define R0900_FSKTFC1 0xf171 +#define F0900_FSKT_CAR1 0xf17100ff + +/*FSKTFC0*/ +#define R0900_FSKTFC0 0xf172 +#define F0900_FSKT_CAR0 0xf17200ff + +/*FSKTDELTAF1*/ +#define R0900_FSKTDELTAF1 0xf173 +#define F0900_FSKT_DELTAF1 0xf173000f + +/*FSKTDELTAF0*/ +#define R0900_FSKTDELTAF0 0xf174 +#define F0900_FSKT_DELTAF0 0xf17400ff + +/*FSKTCTRL*/ +#define R0900_FSKTCTRL 0xf175 +#define F0900_FSKT_EN_SGN 0xf1750040 +#define F0900_FSKT_MOD_SGN 0xf1750020 +#define F0900_FSKT_MOD_EN 0xf175001c +#define F0900_FSKT_DACMODE 0xf1750003 + +/*FSKRFC2*/ +#define R0900_FSKRFC2 0xf176 +#define F0900_FSKR_DETSGN 0xf1760040 +#define F0900_FSKR_OUTSGN 0xf1760020 +#define F0900_FSKR_KAGC 0xf176001c +#define F0900_FSKR_CAR2 0xf1760003 + +/*FSKRFC1*/ +#define R0900_FSKRFC1 0xf177 +#define F0900_FSKR_CAR1 0xf17700ff + +/*FSKRFC0*/ +#define R0900_FSKRFC0 0xf178 +#define F0900_FSKR_CAR0 0xf17800ff + +/*FSKRK1*/ +#define R0900_FSKRK1 0xf179 +#define F0900_FSKR_K1_EXP 0xf17900e0 +#define F0900_FSKR_K1_MANT 0xf179001f + +/*FSKRK2*/ +#define R0900_FSKRK2 0xf17a +#define F0900_FSKR_K2_EXP 0xf17a00e0 +#define F0900_FSKR_K2_MANT 0xf17a001f + +/*FSKRAGCR*/ +#define R0900_FSKRAGCR 0xf17b +#define F0900_FSKR_OUTCTL 0xf17b00c0 +#define F0900_FSKR_AGC_REF 0xf17b003f + +/*FSKRAGC*/ +#define R0900_FSKRAGC 0xf17c +#define F0900_FSKR_AGC_ACCU 0xf17c00ff + +/*FSKRALPHA*/ +#define R0900_FSKRALPHA 0xf17d +#define F0900_FSKR_ALPHA_EXP 0xf17d001c +#define F0900_FSKR_ALPHA_M 0xf17d0003 + +/*FSKRPLTH1*/ +#define R0900_FSKRPLTH1 0xf17e +#define F0900_FSKR_BETA 0xf17e00f0 +#define F0900_FSKR_PLL_TRESH1 0xf17e000f + +/*FSKRPLTH0*/ +#define R0900_FSKRPLTH0 0xf17f +#define F0900_FSKR_PLL_TRESH0 0xf17f00ff + +/*FSKRDF1*/ +#define R0900_FSKRDF1 0xf180 +#define F0900_FSKR_OUT 0xf1800080 +#define F0900_FSKR_DELTAF1 0xf180001f + +/*FSKRDF0*/ +#define R0900_FSKRDF0 0xf181 +#define F0900_FSKR_DELTAF0 0xf18100ff + +/*FSKRSTEPP*/ +#define R0900_FSKRSTEPP 0xf182 +#define F0900_FSKR_STEP_PLUS 0xf18200ff + +/*FSKRSTEPM*/ +#define R0900_FSKRSTEPM 0xf183 +#define F0900_FSKR_STEP_MINUS 0xf18300ff + +/*FSKRDET1*/ +#define R0900_FSKRDET1 0xf184 +#define F0900_FSKR_DETECT 0xf1840080 +#define F0900_FSKR_CARDET_ACCU1 0xf184000f + +/*FSKRDET0*/ +#define R0900_FSKRDET0 0xf185 +#define F0900_FSKR_CARDET_ACCU0 0xf18500ff + +/*FSKRDTH1*/ +#define R0900_FSKRDTH1 0xf186 +#define F0900_FSKR_CARLOSS_THRESH1 0xf18600f0 +#define F0900_FSKR_CARDET_THRESH1 0xf186000f + +/*FSKRDTH0*/ +#define R0900_FSKRDTH0 0xf187 +#define F0900_FSKR_CARDET_THRESH0 0xf18700ff + +/*FSKRLOSS*/ +#define R0900_FSKRLOSS 0xf188 +#define F0900_FSKR_CARLOSS_THRESH0 0xf18800ff + +/*P2_DISTXCTL*/ +#define R0900_P2_DISTXCTL 0xf190 +#define F0900_P2_TIM_OFF 0xf1900080 +#define F0900_P2_DISEQC_RESET 0xf1900040 +#define F0900_P2_TIM_CMD 0xf1900030 +#define F0900_P2_DIS_PRECHARGE 0xf1900008 +#define F0900_P2_DISTX_MODE 0xf1900007 + +/*P2_DISRXCTL*/ +#define R0900_P2_DISRXCTL 0xf191 +#define F0900_P2_RECEIVER_ON 0xf1910080 +#define F0900_P2_IGNO_SHORT22K 0xf1910040 +#define F0900_P2_ONECHIP_TRX 0xf1910020 +#define F0900_P2_EXT_ENVELOP 0xf1910010 +#define F0900_P2_PIN_SELECT 0xf191000c +#define F0900_P2_IRQ_RXEND 0xf1910002 +#define F0900_P2_IRQ_4NBYTES 0xf1910001 + +/*P2_DISRX_ST0*/ +#define R0900_P2_DISRX_ST0 0xf194 +#define F0900_P2_RX_END 0xf1940080 +#define F0900_P2_RX_ACTIVE 0xf1940040 +#define F0900_P2_SHORT_22KHZ 0xf1940020 +#define F0900_P2_CONT_TONE 0xf1940010 +#define F0900_P2_FIFO_4BREADY 0xf1940008 +#define F0900_P2_FIFO_EMPTY 0xf1940004 +#define F0900_P2_ABORT_DISRX 0xf1940001 + +/*P2_DISRX_ST1*/ +#define R0900_P2_DISRX_ST1 0xf195 +#define F0900_P2_RX_FAIL 0xf1950080 +#define F0900_P2_FIFO_PARITYFAIL 0xf1950040 +#define F0900_P2_RX_NONBYTE 0xf1950020 +#define F0900_P2_FIFO_OVERFLOW 0xf1950010 +#define F0900_P2_FIFO_BYTENBR 0xf195000f + +/*P2_DISRXDATA*/ +#define R0900_P2_DISRXDATA 0xf196 +#define F0900_P2_DISRX_DATA 0xf19600ff + +/*P2_DISTXDATA*/ +#define R0900_P2_DISTXDATA 0xf197 +#define F0900_P2_DISEQC_FIFO 0xf19700ff + +/*P2_DISTXSTATUS*/ +#define R0900_P2_DISTXSTATUS 0xf198 +#define F0900_P2_TX_FAIL 0xf1980080 +#define F0900_P2_FIFO_FULL 0xf1980040 +#define F0900_P2_TX_IDLE 0xf1980020 +#define F0900_P2_GAP_BURST 0xf1980010 +#define F0900_P2_TXFIFO_BYTES 0xf198000f + +/*P2_F22TX*/ +#define R0900_P2_F22TX 0xf199 +#define F0900_P2_F22_REG 0xf19900ff + +/*P2_F22RX*/ +#define R0900_P2_F22RX 0xf19a +#define F0900_P2_F22RX_REG 0xf19a00ff + +/*P2_ACRPRESC*/ +#define R0900_P2_ACRPRESC 0xf19c +#define F0900_P2_ACR_CODFRDY 0xf19c0008 +#define F0900_P2_ACR_PRESC 0xf19c0007 + +/*P2_ACRDIV*/ +#define R0900_P2_ACRDIV 0xf19d +#define F0900_P2_ACR_DIV 0xf19d00ff + +/*P1_DISTXCTL*/ +#define R0900_P1_DISTXCTL 0xf1a0 +#define F0900_P1_TIM_OFF 0xf1a00080 +#define F0900_P1_DISEQC_RESET 0xf1a00040 +#define F0900_P1_TIM_CMD 0xf1a00030 +#define F0900_P1_DIS_PRECHARGE 0xf1a00008 +#define F0900_P1_DISTX_MODE 0xf1a00007 + +/*P1_DISRXCTL*/ +#define R0900_P1_DISRXCTL 0xf1a1 +#define F0900_P1_RECEIVER_ON 0xf1a10080 +#define F0900_P1_IGNO_SHORT22K 0xf1a10040 +#define F0900_P1_ONECHIP_TRX 0xf1a10020 +#define F0900_P1_EXT_ENVELOP 0xf1a10010 +#define F0900_P1_PIN_SELECT 0xf1a1000c +#define F0900_P1_IRQ_RXEND 0xf1a10002 +#define F0900_P1_IRQ_4NBYTES 0xf1a10001 + +/*P1_DISRX_ST0*/ +#define R0900_P1_DISRX_ST0 0xf1a4 +#define F0900_P1_RX_END 0xf1a40080 +#define F0900_P1_RX_ACTIVE 0xf1a40040 +#define F0900_P1_SHORT_22KHZ 0xf1a40020 +#define F0900_P1_CONT_TONE 0xf1a40010 +#define F0900_P1_FIFO_4BREADY 0xf1a40008 +#define F0900_P1_FIFO_EMPTY 0xf1a40004 +#define F0900_P1_ABORT_DISRX 0xf1a40001 + +/*P1_DISRX_ST1*/ +#define R0900_P1_DISRX_ST1 0xf1a5 +#define F0900_P1_RX_FAIL 0xf1a50080 +#define F0900_P1_FIFO_PARITYFAIL 0xf1a50040 +#define F0900_P1_RX_NONBYTE 0xf1a50020 +#define F0900_P1_FIFO_OVERFLOW 0xf1a50010 +#define F0900_P1_FIFO_BYTENBR 0xf1a5000f + +/*P1_DISRXDATA*/ +#define R0900_P1_DISRXDATA 0xf1a6 +#define F0900_P1_DISRX_DATA 0xf1a600ff + +/*P1_DISTXDATA*/ +#define R0900_P1_DISTXDATA 0xf1a7 +#define F0900_P1_DISEQC_FIFO 0xf1a700ff + +/*P1_DISTXSTATUS*/ +#define R0900_P1_DISTXSTATUS 0xf1a8 +#define F0900_P1_TX_FAIL 0xf1a80080 +#define F0900_P1_FIFO_FULL 0xf1a80040 +#define F0900_P1_TX_IDLE 0xf1a80020 +#define F0900_P1_GAP_BURST 0xf1a80010 +#define F0900_P1_TXFIFO_BYTES 0xf1a8000f + +/*P1_F22TX*/ +#define R0900_P1_F22TX 0xf1a9 +#define F0900_P1_F22_REG 0xf1a900ff + +/*P1_F22RX*/ +#define R0900_P1_F22RX 0xf1aa +#define F0900_P1_F22RX_REG 0xf1aa00ff + +/*P1_ACRPRESC*/ +#define R0900_P1_ACRPRESC 0xf1ac +#define F0900_P1_ACR_CODFRDY 0xf1ac0008 +#define F0900_P1_ACR_PRESC 0xf1ac0007 + +/*P1_ACRDIV*/ +#define R0900_P1_ACRDIV 0xf1ad +#define F0900_P1_ACR_DIV 0xf1ad00ff + +/*NCOARSE*/ +#define R0900_NCOARSE 0xf1b3 +#define F0900_M_DIV 0xf1b300ff + +/*SYNTCTRL*/ +#define R0900_SYNTCTRL 0xf1b6 +#define F0900_STANDBY 0xf1b60080 +#define F0900_BYPASSPLLCORE 0xf1b60040 +#define F0900_SELX1RATIO 0xf1b60020 +#define F0900_I2C_TUD 0xf1b60010 +#define F0900_STOP_PLL 0xf1b60008 +#define F0900_BYPASSPLLFSK 0xf1b60004 +#define F0900_SELOSCI 0xf1b60002 +#define F0900_BYPASSPLLADC 0xf1b60001 + +/*FILTCTRL*/ +#define R0900_FILTCTRL 0xf1b7 +#define F0900_INV_CLK135 0xf1b70080 +#define F0900_PERM_BYPDIS 0xf1b70040 +#define F0900_SEL_FSKCKDIV 0xf1b70004 +#define F0900_INV_CLKFSK 0xf1b70002 +#define F0900_BYPASS_APPLI 0xf1b70001 + +/*PLLSTAT*/ +#define R0900_PLLSTAT 0xf1b8 +#define F0900_ACM_SEL 0xf1b80080 +#define F0900_DTV_SEL 0xf1b80040 +#define F0900_PLLLOCK 0xf1b80001 + +/*STOPCLK1*/ +#define R0900_STOPCLK1 0xf1c2 +#define F0900_STOP_CLKPKDT2 0xf1c20040 +#define F0900_STOP_CLKPKDT1 0xf1c20020 +#define F0900_STOP_CLKFEC 0xf1c20010 +#define F0900_STOP_CLKADCI2 0xf1c20008 +#define F0900_INV_CLKADCI2 0xf1c20004 +#define F0900_STOP_CLKADCI1 0xf1c20002 +#define F0900_INV_CLKADCI1 0xf1c20001 + +/*STOPCLK2*/ +#define R0900_STOPCLK2 0xf1c3 +#define F0900_STOP_CLKSAMP2 0xf1c30010 +#define F0900_STOP_CLKSAMP1 0xf1c30008 +#define F0900_STOP_CLKVIT2 0xf1c30004 +#define F0900_STOP_CLKVIT1 0xf1c30002 +#define F0900_STOP_CLKTS 0xf1c30001 + +/*TSTTNR0*/ +#define R0900_TSTTNR0 0xf1df +#define F0900_SEL_FSK 0xf1df0080 +#define F0900_FSK_PON 0xf1df0004 +#define F0900_FSK_OPENLOOP 0xf1df0002 + +/*TSTTNR1*/ +#define R0900_TSTTNR1 0xf1e0 +#define F0900_BYPASS_ADC1 0xf1e00080 +#define F0900_INVADC1_CKOUT 0xf1e00040 +#define F0900_SELIQSRC1 0xf1e00030 +#define F0900_ADC1_PON 0xf1e00002 +#define F0900_ADC1_INMODE 0xf1e00001 + +/*TSTTNR2*/ +#define R0900_TSTTNR2 0xf1e1 +#define F0900_DISEQC1_PON 0xf1e10020 +#define F0900_DISEQC1_TEST 0xf1e1001f + +/*TSTTNR3*/ +#define R0900_TSTTNR3 0xf1e2 +#define F0900_BYPASS_ADC2 0xf1e20080 +#define F0900_INVADC2_CKOUT 0xf1e20040 +#define F0900_SELIQSRC2 0xf1e20030 +#define F0900_ADC2_PON 0xf1e20002 +#define F0900_ADC2_INMODE 0xf1e20001 + +/*TSTTNR4*/ +#define R0900_TSTTNR4 0xf1e3 +#define F0900_DISEQC2_PON 0xf1e30020 +#define F0900_DISEQC2_TEST 0xf1e3001f + +/*P2_IQCONST*/ +#define R0900_P2_IQCONST 0xf200 +#define F0900_P2_CONSTEL_SELECT 0xf2000060 +#define F0900_P2_IQSYMB_SEL 0xf200001f + +/*P2_NOSCFG*/ +#define R0900_P2_NOSCFG 0xf201 +#define F0900_P2_DUMMYPL_NOSDATA 0xf2010020 +#define F0900_P2_NOSPLH_BETA 0xf2010018 +#define F0900_P2_NOSDATA_BETA 0xf2010007 + +/*P2_ISYMB*/ +#define R0900_P2_ISYMB 0xf202 +#define F0900_P2_I_SYMBOL 0xf20201ff + +/*P2_QSYMB*/ +#define R0900_P2_QSYMB 0xf203 +#define F0900_P2_Q_SYMBOL 0xf20301ff + +/*P2_AGC1CFG*/ +#define R0900_P2_AGC1CFG 0xf204 +#define F0900_P2_DC_FROZEN 0xf2040080 +#define F0900_P2_DC_CORRECT 0xf2040040 +#define F0900_P2_AMM_FROZEN 0xf2040020 +#define F0900_P2_AMM_CORRECT 0xf2040010 +#define F0900_P2_QUAD_FROZEN 0xf2040008 +#define F0900_P2_QUAD_CORRECT 0xf2040004 +#define F0900_P2_DCCOMP_SLOW 0xf2040002 +#define F0900_P2_IQMISM_SLOW 0xf2040001 + +/*P2_AGC1CN*/ +#define R0900_P2_AGC1CN 0xf206 +#define F0900_P2_AGC1_LOCKED 0xf2060080 +#define F0900_P2_AGC1_OVERFLOW 0xf2060040 +#define F0900_P2_AGC1_NOSLOWLK 0xf2060020 +#define F0900_P2_AGC1_MINPOWER 0xf2060010 +#define F0900_P2_AGCOUT_FAST 0xf2060008 +#define F0900_P2_AGCIQ_BETA 0xf2060007 + +/*P2_AGC1REF*/ +#define R0900_P2_AGC1REF 0xf207 +#define F0900_P2_AGCIQ_REF 0xf20700ff + +/*P2_IDCCOMP*/ +#define R0900_P2_IDCCOMP 0xf208 +#define F0900_P2_IAVERAGE_ADJ 0xf20801ff + +/*P2_QDCCOMP*/ +#define R0900_P2_QDCCOMP 0xf209 +#define F0900_P2_QAVERAGE_ADJ 0xf20901ff + +/*P2_POWERI*/ +#define R0900_P2_POWERI 0xf20a +#define F0900_P2_POWER_I 0xf20a00ff + +/*P2_POWERQ*/ +#define R0900_P2_POWERQ 0xf20b +#define F0900_P2_POWER_Q 0xf20b00ff + +/*P2_AGC1AMM*/ +#define R0900_P2_AGC1AMM 0xf20c +#define F0900_P2_AMM_VALUE 0xf20c00ff + +/*P2_AGC1QUAD*/ +#define R0900_P2_AGC1QUAD 0xf20d +#define F0900_P2_QUAD_VALUE 0xf20d01ff + +/*P2_AGCIQIN1*/ +#define R0900_P2_AGCIQIN1 0xf20e +#define F0900_P2_AGCIQ_VALUE1 0xf20e00ff + +/*P2_AGCIQIN0*/ +#define R0900_P2_AGCIQIN0 0xf20f +#define F0900_P2_AGCIQ_VALUE0 0xf20f00ff + +/*P2_DEMOD*/ +#define R0900_P2_DEMOD 0xf210 +#define F0900_P2_DEMOD_STOP 0xf2100040 +#define F0900_P2_SPECINV_CONTROL 0xf2100030 +#define F0900_P2_FORCE_ENASAMP 0xf2100008 +#define F0900_P2_MANUAL_ROLLOFF 0xf2100004 +#define F0900_P2_ROLLOFF_CONTROL 0xf2100003 + +/*P2_DMDMODCOD*/ +#define R0900_P2_DMDMODCOD 0xf211 +#define F0900_P2_MANUAL_MODCOD 0xf2110080 +#define F0900_P2_DEMOD_MODCOD 0xf211007c +#define F0900_P2_DEMOD_TYPE 0xf2110003 + +/*P2_DSTATUS*/ +#define R0900_P2_DSTATUS 0xf212 +#define F0900_P2_CAR_LOCK 0xf2120080 +#define F0900_P2_TMGLOCK_QUALITY 0xf2120060 +#define F0900_P2_SDVBS1_ENABLE 0xf2120010 +#define F0900_P2_LOCK_DEFINITIF 0xf2120008 +#define F0900_P2_TIMING_IS_LOCKED 0xf2120004 +#define F0900_P2_COARSE_TMGLOCK 0xf2120002 +#define F0900_P2_COARSE_CARLOCK 0xf2120001 + +/*P2_DSTATUS2*/ +#define R0900_P2_DSTATUS2 0xf213 +#define F0900_P2_DEMOD_DELOCK 0xf2130080 +#define F0900_P2_DEMOD_TIMEOUT 0xf2130040 +#define F0900_P2_MODCODRQ_SYNCTAG 0xf2130020 +#define F0900_P2_POLYPH_SATEVENT 0xf2130010 +#define F0900_P2_AGC1_NOSIGNALACK 0xf2130008 +#define F0900_P2_AGC2_OVERFLOW 0xf2130004 +#define F0900_P2_CFR_OVERFLOW 0xf2130002 +#define F0900_P2_GAMMA_OVERUNDER 0xf2130001 + +/*P2_DMDCFGMD*/ +#define R0900_P2_DMDCFGMD 0xf214 +#define F0900_P2_DVBS2_ENABLE 0xf2140080 +#define F0900_P2_DVBS1_ENABLE 0xf2140040 +#define F0900_P2_CFR_AUTOSCAN 0xf2140020 +#define F0900_P2_SCAN_ENABLE 0xf2140010 +#define F0900_P2_TUN_AUTOSCAN 0xf2140008 +#define F0900_P2_NOFORCE_RELOCK 0xf2140004 +#define F0900_P2_TUN_RNG 0xf2140003 + +/*P2_DMDCFG2*/ +#define R0900_P2_DMDCFG2 0xf215 +#define F0900_P2_AGC1_WAITLOCK 0xf2150080 +#define F0900_P2_S1S2_SEQUENTIAL 0xf2150040 +#define F0900_P2_OVERFLOW_TIMEOUT 0xf2150020 +#define F0900_P2_SCANFAIL_TIMEOUT 0xf2150010 +#define F0900_P2_DMDTOUT_BACK 0xf2150008 +#define F0900_P2_CARLOCK_S1ENABLE 0xf2150004 +#define F0900_P2_COARSE_LK3MODE 0xf2150002 +#define F0900_P2_COARSE_LK2MODE 0xf2150001 + +/*P2_DMDISTATE*/ +#define R0900_P2_DMDISTATE 0xf216 +#define F0900_P2_I2C_NORESETDMODE 0xf2160080 +#define F0900_P2_FORCE_ETAPED 0xf2160040 +#define F0900_P2_SDMDRST_DIRCLK 0xf2160020 +#define F0900_P2_I2C_DEMOD_MODE 0xf216001f + +/*P2_DMDT0M*/ +#define R0900_P2_DMDT0M 0xf217 +#define F0900_P2_DMDT0_MIN 0xf21700ff + +/*P2_DMDSTATE*/ +#define R0900_P2_DMDSTATE 0xf21b +#define F0900_P2_DEMOD_LOCKED 0xf21b0080 +#define F0900_P2_HEADER_MODE 0xf21b0060 +#define F0900_P2_DEMOD_MODE 0xf21b001f + +/*P2_DMDFLYW*/ +#define R0900_P2_DMDFLYW 0xf21c +#define F0900_P2_I2C_IRQVAL 0xf21c00f0 +#define F0900_P2_FLYWHEEL_CPT 0xf21c000f + +/*P2_DSTATUS3*/ +#define R0900_P2_DSTATUS3 0xf21d +#define F0900_P2_CFR_ZIGZAG 0xf21d0080 +#define F0900_P2_DEMOD_CFGMODE 0xf21d0060 +#define F0900_P2_GAMMA_LOWBAUDRATE 0xf21d0010 +#define F0900_P2_RELOCK_MODE 0xf21d0008 +#define F0900_P2_DEMOD_FAIL 0xf21d0004 +#define F0900_P2_ETAPE1A_DVBXMEM 0xf21d0003 + +/*P2_DMDCFG3*/ +#define R0900_P2_DMDCFG3 0xf21e +#define F0900_P2_DVBS1_TMGWAIT 0xf21e0080 +#define F0900_P2_NO_BWCENTERING 0xf21e0040 +#define F0900_P2_INV_SEQSRCH 0xf21e0020 +#define F0900_P2_DIS_SFRUPLOW_TRK 0xf21e0010 +#define F0900_P2_NOSTOP_FIFOFULL 0xf21e0008 +#define F0900_P2_LOCKTIME_MODE 0xf21e0007 + +/*P2_DMDCFG4*/ +#define R0900_P2_DMDCFG4 0xf21f +#define F0900_P2_TUNER_NRELAUNCH 0xf21f0008 +#define F0900_P2_DIS_CLKENABLE 0xf21f0004 +#define F0900_P2_DIS_HDRDIVLOCK 0xf21f0002 +#define F0900_P2_NO_TNRWBINIT 0xf21f0001 + +/*P2_CORRELMANT*/ +#define R0900_P2_CORRELMANT 0xf220 +#define F0900_P2_CORREL_MANT 0xf22000ff + +/*P2_CORRELABS*/ +#define R0900_P2_CORRELABS 0xf221 +#define F0900_P2_CORREL_ABS 0xf22100ff + +/*P2_CORRELEXP*/ +#define R0900_P2_CORRELEXP 0xf222 +#define F0900_P2_CORREL_ABSEXP 0xf22200f0 +#define F0900_P2_CORREL_EXP 0xf222000f + +/*P2_PLHMODCOD*/ +#define R0900_P2_PLHMODCOD 0xf224 +#define F0900_P2_SPECINV_DEMOD 0xf2240080 +#define F0900_P2_PLH_MODCOD 0xf224007c +#define F0900_P2_PLH_TYPE 0xf2240003 + +/*P2_AGCK32*/ +#define R0900_P2_AGCK32 0xf22b +#define F0900_P2_R3ADJOFF_32APSK 0xf22b0080 +#define F0900_P2_R2ADJOFF_32APSK 0xf22b0040 +#define F0900_P2_R1ADJOFF_32APSK 0xf22b0020 +#define F0900_P2_RADJ_32APSK 0xf22b001f + +/*P2_AGC2O*/ +#define R0900_P2_AGC2O 0xf22c +#define F0900_P2_AGC2REF_ADJUSTING 0xf22c0080 +#define F0900_P2_AGC2_COARSEFAST 0xf22c0040 +#define F0900_P2_AGC2_LKSQRT 0xf22c0020 +#define F0900_P2_AGC2_LKMODE 0xf22c0010 +#define F0900_P2_AGC2_LKEQUA 0xf22c0008 +#define F0900_P2_AGC2_COEF 0xf22c0007 + +/*P2_AGC2REF*/ +#define R0900_P2_AGC2REF 0xf22d +#define F0900_P2_AGC2_REF 0xf22d00ff + +/*P2_AGC1ADJ*/ +#define R0900_P2_AGC1ADJ 0xf22e +#define F0900_P2_AGC1ADJ_MANUAL 0xf22e0080 +#define F0900_P2_AGC1_ADJUSTED 0xf22e017f + +/*P2_AGC2I1*/ +#define R0900_P2_AGC2I1 0xf236 +#define F0900_P2_AGC2_INTEGRATOR1 0xf23600ff + +/*P2_AGC2I0*/ +#define R0900_P2_AGC2I0 0xf237 +#define F0900_P2_AGC2_INTEGRATOR0 0xf23700ff + +/*P2_CARCFG*/ +#define R0900_P2_CARCFG 0xf238 +#define F0900_P2_CFRUPLOW_AUTO 0xf2380080 +#define F0900_P2_CFRUPLOW_TEST 0xf2380040 +#define F0900_P2_EN_CAR2CENTER 0xf2380020 +#define F0900_P2_CARHDR_NODIV8 0xf2380010 +#define F0900_P2_I2C_ROTA 0xf2380008 +#define F0900_P2_ROTAON 0xf2380004 +#define F0900_P2_PH_DET_ALGO 0xf2380003 + +/*P2_ACLC*/ +#define R0900_P2_ACLC 0xf239 +#define F0900_P2_STOP_S2ALPHA 0xf23900c0 +#define F0900_P2_CAR_ALPHA_MANT 0xf2390030 +#define F0900_P2_CAR_ALPHA_EXP 0xf239000f + +/*P2_BCLC*/ +#define R0900_P2_BCLC 0xf23a +#define F0900_P2_STOP_S2BETA 0xf23a00c0 +#define F0900_P2_CAR_BETA_MANT 0xf23a0030 +#define F0900_P2_CAR_BETA_EXP 0xf23a000f + +/*P2_CARFREQ*/ +#define R0900_P2_CARFREQ 0xf23d +#define F0900_P2_KC_COARSE_EXP 0xf23d00f0 +#define F0900_P2_BETA_FREQ 0xf23d000f + +/*P2_CARHDR*/ +#define R0900_P2_CARHDR 0xf23e +#define F0900_P2_K_FREQ_HDR 0xf23e00ff + +/*P2_LDT*/ +#define R0900_P2_LDT 0xf23f +#define F0900_P2_CARLOCK_THRES 0xf23f01ff + +/*P2_LDT2*/ +#define R0900_P2_LDT2 0xf240 +#define F0900_P2_CARLOCK_THRES2 0xf24001ff + +/*P2_CFRICFG*/ +#define R0900_P2_CFRICFG 0xf241 +#define F0900_P2_CFRINIT_UNVALRNG 0xf2410080 +#define F0900_P2_CFRINIT_LUNVALCPT 0xf2410040 +#define F0900_P2_CFRINIT_ABORTDBL 0xf2410020 +#define F0900_P2_CFRINIT_ABORTPRED 0xf2410010 +#define F0900_P2_CFRINIT_UNVALSKIP 0xf2410008 +#define F0900_P2_CFRINIT_CSTINC 0xf2410004 +#define F0900_P2_NEG_CFRSTEP 0xf2410001 + +/*P2_CFRUP1*/ +#define R0900_P2_CFRUP1 0xf242 +#define F0900_P2_CFR_UP1 0xf24201ff + +/*P2_CFRUP0*/ +#define R0900_P2_CFRUP0 0xf243 +#define F0900_P2_CFR_UP0 0xf24300ff + +/*P2_CFRLOW1*/ +#define R0900_P2_CFRLOW1 0xf246 +#define F0900_P2_CFR_LOW1 0xf24601ff + +/*P2_CFRLOW0*/ +#define R0900_P2_CFRLOW0 0xf247 +#define F0900_P2_CFR_LOW0 0xf24700ff + +/*P2_CFRINIT1*/ +#define R0900_P2_CFRINIT1 0xf248 +#define F0900_P2_CFR_INIT1 0xf24801ff + +/*P2_CFRINIT0*/ +#define R0900_P2_CFRINIT0 0xf249 +#define F0900_P2_CFR_INIT0 0xf24900ff + +/*P2_CFRINC1*/ +#define R0900_P2_CFRINC1 0xf24a +#define F0900_P2_MANUAL_CFRINC 0xf24a0080 +#define F0900_P2_CFR_INC1 0xf24a017f + +/*P2_CFRINC0*/ +#define R0900_P2_CFRINC0 0xf24b +#define F0900_P2_CFR_INC0 0xf24b00f0 + +/*P2_CFR2*/ +#define R0900_P2_CFR2 0xf24c +#define F0900_P2_CAR_FREQ2 0xf24c01ff + +/*P2_CFR1*/ +#define R0900_P2_CFR1 0xf24d +#define F0900_P2_CAR_FREQ1 0xf24d00ff + +/*P2_CFR0*/ +#define R0900_P2_CFR0 0xf24e +#define F0900_P2_CAR_FREQ0 0xf24e00ff + +/*P2_LDI*/ +#define R0900_P2_LDI 0xf24f +#define F0900_P2_LOCK_DET_INTEGR 0xf24f01ff + +/*P2_TMGCFG*/ +#define R0900_P2_TMGCFG 0xf250 +#define F0900_P2_TMGLOCK_BETA 0xf25000c0 +#define F0900_P2_NOTMG_GROUPDELAY 0xf2500020 +#define F0900_P2_DO_TIMING_CORR 0xf2500010 +#define F0900_P2_MANUAL_SCAN 0xf250000c +#define F0900_P2_TMG_MINFREQ 0xf2500003 + +/*P2_RTC*/ +#define R0900_P2_RTC 0xf251 +#define F0900_P2_TMGALPHA_EXP 0xf25100f0 +#define F0900_P2_TMGBETA_EXP 0xf251000f + +/*P2_RTCS2*/ +#define R0900_P2_RTCS2 0xf252 +#define F0900_P2_TMGALPHAS2_EXP 0xf25200f0 +#define F0900_P2_TMGBETAS2_EXP 0xf252000f + +/*P2_TMGTHRISE*/ +#define R0900_P2_TMGTHRISE 0xf253 +#define F0900_P2_TMGLOCK_THRISE 0xf25300ff + +/*P2_TMGTHFALL*/ +#define R0900_P2_TMGTHFALL 0xf254 +#define F0900_P2_TMGLOCK_THFALL 0xf25400ff + +/*P2_SFRUPRATIO*/ +#define R0900_P2_SFRUPRATIO 0xf255 +#define F0900_P2_SFR_UPRATIO 0xf25500ff + +/*P2_SFRLOWRATIO*/ +#define R0900_P2_SFRLOWRATIO 0xf256 +#define F0900_P2_SFR_LOWRATIO 0xf25600ff + +/*P2_KREFTMG*/ +#define R0900_P2_KREFTMG 0xf258 +#define F0900_P2_KREF_TMG 0xf25800ff + +/*P2_SFRSTEP*/ +#define R0900_P2_SFRSTEP 0xf259 +#define F0900_P2_SFR_SCANSTEP 0xf25900f0 +#define F0900_P2_SFR_CENTERSTEP 0xf259000f + +/*P2_TMGCFG2*/ +#define R0900_P2_TMGCFG2 0xf25a +#define F0900_P2_DIS_AUTOSAMP 0xf25a0008 +#define F0900_P2_SCANINIT_QUART 0xf25a0004 +#define F0900_P2_NOTMG_DVBS1DERAT 0xf25a0002 +#define F0900_P2_SFRRATIO_FINE 0xf25a0001 + +/*P2_SFRINIT1*/ +#define R0900_P2_SFRINIT1 0xf25e +#define F0900_P2_SFR_INIT1 0xf25e00ff + +/*P2_SFRINIT0*/ +#define R0900_P2_SFRINIT0 0xf25f +#define F0900_P2_SFR_INIT0 0xf25f00ff + +/*P2_SFRUP1*/ +#define R0900_P2_SFRUP1 0xf260 +#define F0900_P2_AUTO_GUP 0xf2600080 +#define F0900_P2_SYMB_FREQ_UP1 0xf260007f + +/*P2_SFRUP0*/ +#define R0900_P2_SFRUP0 0xf261 +#define F0900_P2_SYMB_FREQ_UP0 0xf26100ff + +/*P2_SFRLOW1*/ +#define R0900_P2_SFRLOW1 0xf262 +#define F0900_P2_AUTO_GLOW 0xf2620080 +#define F0900_P2_SYMB_FREQ_LOW1 0xf262007f + +/*P2_SFRLOW0*/ +#define R0900_P2_SFRLOW0 0xf263 +#define F0900_P2_SYMB_FREQ_LOW0 0xf26300ff + +/*P2_SFR3*/ +#define R0900_P2_SFR3 0xf264 +#define F0900_P2_SYMB_FREQ3 0xf26400ff + +/*P2_SFR2*/ +#define R0900_P2_SFR2 0xf265 +#define F0900_P2_SYMB_FREQ2 0xf26500ff + +/*P2_SFR1*/ +#define R0900_P2_SFR1 0xf266 +#define F0900_P2_SYMB_FREQ1 0xf26600ff + +/*P2_SFR0*/ +#define R0900_P2_SFR0 0xf267 +#define F0900_P2_SYMB_FREQ0 0xf26700ff + +/*P2_TMGREG2*/ +#define R0900_P2_TMGREG2 0xf268 +#define F0900_P2_TMGREG2 0xf26800ff + +/*P2_TMGREG1*/ +#define R0900_P2_TMGREG1 0xf269 +#define F0900_P2_TMGREG1 0xf26900ff + +/*P2_TMGREG0*/ +#define R0900_P2_TMGREG0 0xf26a +#define F0900_P2_TMGREG0 0xf26a00ff + +/*P2_TMGLOCK1*/ +#define R0900_P2_TMGLOCK1 0xf26b +#define F0900_P2_TMGLOCK_LEVEL1 0xf26b01ff + +/*P2_TMGLOCK0*/ +#define R0900_P2_TMGLOCK0 0xf26c +#define F0900_P2_TMGLOCK_LEVEL0 0xf26c00ff + +/*P2_TMGOBS*/ +#define R0900_P2_TMGOBS 0xf26d +#define F0900_P2_ROLLOFF_STATUS 0xf26d00c0 +#define F0900_P2_SCAN_SIGN 0xf26d0030 +#define F0900_P2_TMG_SCANNING 0xf26d0008 +#define F0900_P2_CHCENTERING_MODE 0xf26d0004 +#define F0900_P2_TMG_SCANFAIL 0xf26d0002 + +/*P2_EQUALCFG*/ +#define R0900_P2_EQUALCFG 0xf26f +#define F0900_P2_NOTMG_NEGALWAIT 0xf26f0080 +#define F0900_P2_EQUAL_ON 0xf26f0040 +#define F0900_P2_SEL_EQUALCOR 0xf26f0038 +#define F0900_P2_MU_EQUALDFE 0xf26f0007 + +/*P2_EQUAI1*/ +#define R0900_P2_EQUAI1 0xf270 +#define F0900_P2_EQUA_ACCI1 0xf27001ff + +/*P2_EQUAQ1*/ +#define R0900_P2_EQUAQ1 0xf271 +#define F0900_P2_EQUA_ACCQ1 0xf27101ff + +/*P2_EQUAI2*/ +#define R0900_P2_EQUAI2 0xf272 +#define F0900_P2_EQUA_ACCI2 0xf27201ff + +/*P2_EQUAQ2*/ +#define R0900_P2_EQUAQ2 0xf273 +#define F0900_P2_EQUA_ACCQ2 0xf27301ff + +/*P2_EQUAI3*/ +#define R0900_P2_EQUAI3 0xf274 +#define F0900_P2_EQUA_ACCI3 0xf27401ff + +/*P2_EQUAQ3*/ +#define R0900_P2_EQUAQ3 0xf275 +#define F0900_P2_EQUA_ACCQ3 0xf27501ff + +/*P2_EQUAI4*/ +#define R0900_P2_EQUAI4 0xf276 +#define F0900_P2_EQUA_ACCI4 0xf27601ff + +/*P2_EQUAQ4*/ +#define R0900_P2_EQUAQ4 0xf277 +#define F0900_P2_EQUA_ACCQ4 0xf27701ff + +/*P2_EQUAI5*/ +#define R0900_P2_EQUAI5 0xf278 +#define F0900_P2_EQUA_ACCI5 0xf27801ff + +/*P2_EQUAQ5*/ +#define R0900_P2_EQUAQ5 0xf279 +#define F0900_P2_EQUA_ACCQ5 0xf27901ff + +/*P2_EQUAI6*/ +#define R0900_P2_EQUAI6 0xf27a +#define F0900_P2_EQUA_ACCI6 0xf27a01ff + +/*P2_EQUAQ6*/ +#define R0900_P2_EQUAQ6 0xf27b +#define F0900_P2_EQUA_ACCQ6 0xf27b01ff + +/*P2_EQUAI7*/ +#define R0900_P2_EQUAI7 0xf27c +#define F0900_P2_EQUA_ACCI7 0xf27c01ff + +/*P2_EQUAQ7*/ +#define R0900_P2_EQUAQ7 0xf27d +#define F0900_P2_EQUA_ACCQ7 0xf27d01ff + +/*P2_EQUAI8*/ +#define R0900_P2_EQUAI8 0xf27e +#define F0900_P2_EQUA_ACCI8 0xf27e01ff + +/*P2_EQUAQ8*/ +#define R0900_P2_EQUAQ8 0xf27f +#define F0900_P2_EQUA_ACCQ8 0xf27f01ff + +/*P2_NNOSDATAT1*/ +#define R0900_P2_NNOSDATAT1 0xf280 +#define F0900_P2_NOSDATAT_NORMED1 0xf28000ff + +/*P2_NNOSDATAT0*/ +#define R0900_P2_NNOSDATAT0 0xf281 +#define F0900_P2_NOSDATAT_NORMED0 0xf28100ff + +/*P2_NNOSDATA1*/ +#define R0900_P2_NNOSDATA1 0xf282 +#define F0900_P2_NOSDATA_NORMED1 0xf28200ff + +/*P2_NNOSDATA0*/ +#define R0900_P2_NNOSDATA0 0xf283 +#define F0900_P2_NOSDATA_NORMED0 0xf28300ff + +/*P2_NNOSPLHT1*/ +#define R0900_P2_NNOSPLHT1 0xf284 +#define F0900_P2_NOSPLHT_NORMED1 0xf28400ff + +/*P2_NNOSPLHT0*/ +#define R0900_P2_NNOSPLHT0 0xf285 +#define F0900_P2_NOSPLHT_NORMED0 0xf28500ff + +/*P2_NNOSPLH1*/ +#define R0900_P2_NNOSPLH1 0xf286 +#define F0900_P2_NOSPLH_NORMED1 0xf28600ff + +/*P2_NNOSPLH0*/ +#define R0900_P2_NNOSPLH0 0xf287 +#define F0900_P2_NOSPLH_NORMED0 0xf28700ff + +/*P2_NOSDATAT1*/ +#define R0900_P2_NOSDATAT1 0xf288 +#define F0900_P2_NOSDATAT_UNNORMED1 0xf28800ff + +/*P2_NOSDATAT0*/ +#define R0900_P2_NOSDATAT0 0xf289 +#define F0900_P2_NOSDATAT_UNNORMED0 0xf28900ff + +/*P2_NOSDATA1*/ +#define R0900_P2_NOSDATA1 0xf28a +#define F0900_P2_NOSDATA_UNNORMED1 0xf28a00ff + +/*P2_NOSDATA0*/ +#define R0900_P2_NOSDATA0 0xf28b +#define F0900_P2_NOSDATA_UNNORMED0 0xf28b00ff + +/*P2_NOSPLHT1*/ +#define R0900_P2_NOSPLHT1 0xf28c +#define F0900_P2_NOSPLHT_UNNORMED1 0xf28c00ff + +/*P2_NOSPLHT0*/ +#define R0900_P2_NOSPLHT0 0xf28d +#define F0900_P2_NOSPLHT_UNNORMED0 0xf28d00ff + +/*P2_NOSPLH1*/ +#define R0900_P2_NOSPLH1 0xf28e +#define F0900_P2_NOSPLH_UNNORMED1 0xf28e00ff + +/*P2_NOSPLH0*/ +#define R0900_P2_NOSPLH0 0xf28f +#define F0900_P2_NOSPLH_UNNORMED0 0xf28f00ff + +/*P2_CAR2CFG*/ +#define R0900_P2_CAR2CFG 0xf290 +#define F0900_P2_DESCRAMB_OFF 0xf2900080 +#define F0900_P2_PN4_SELECT 0xf2900040 +#define F0900_P2_CFR2_STOPDVBS1 0xf2900020 +#define F0900_P2_STOP_CFR2UPDATE 0xf2900010 +#define F0900_P2_STOP_NCO2UPDATE 0xf2900008 +#define F0900_P2_ROTA2ON 0xf2900004 +#define F0900_P2_PH_DET_ALGO2 0xf2900003 + +/*P2_ACLC2*/ +#define R0900_P2_ACLC2 0xf291 +#define F0900_P2_CAR2_PUNCT_ADERAT 0xf2910040 +#define F0900_P2_CAR2_ALPHA_MANT 0xf2910030 +#define F0900_P2_CAR2_ALPHA_EXP 0xf291000f + +/*P2_BCLC2*/ +#define R0900_P2_BCLC2 0xf292 +#define F0900_P2_DVBS2_NIP 0xf2920080 +#define F0900_P2_CAR2_PUNCT_BDERAT 0xf2920040 +#define F0900_P2_CAR2_BETA_MANT 0xf2920030 +#define F0900_P2_CAR2_BETA_EXP 0xf292000f + +/*P2_CFR22*/ +#define R0900_P2_CFR22 0xf293 +#define F0900_P2_CAR2_FREQ2 0xf29301ff + +/*P2_CFR21*/ +#define R0900_P2_CFR21 0xf294 +#define F0900_P2_CAR2_FREQ1 0xf29400ff + +/*P2_CFR20*/ +#define R0900_P2_CFR20 0xf295 +#define F0900_P2_CAR2_FREQ0 0xf29500ff + +/*P2_ACLC2S2Q*/ +#define R0900_P2_ACLC2S2Q 0xf297 +#define F0900_P2_ENAB_SPSKSYMB 0xf2970080 +#define F0900_P2_CAR2S2_QADERAT 0xf2970040 +#define F0900_P2_CAR2S2_Q_ALPH_M 0xf2970030 +#define F0900_P2_CAR2S2_Q_ALPH_E 0xf297000f + +/*P2_ACLC2S28*/ +#define R0900_P2_ACLC2S28 0xf298 +#define F0900_P2_OLDI3Q_MODE 0xf2980080 +#define F0900_P2_CAR2S2_8ADERAT 0xf2980040 +#define F0900_P2_CAR2S2_8_ALPH_M 0xf2980030 +#define F0900_P2_CAR2S2_8_ALPH_E 0xf298000f + +/*P2_ACLC2S216A*/ +#define R0900_P2_ACLC2S216A 0xf299 +#define F0900_P2_CAR2S2_16ADERAT 0xf2990040 +#define F0900_P2_CAR2S2_16A_ALPH_M 0xf2990030 +#define F0900_P2_CAR2S2_16A_ALPH_E 0xf299000f + +/*P2_ACLC2S232A*/ +#define R0900_P2_ACLC2S232A 0xf29a +#define F0900_P2_CAR2S2_32ADERAT 0xf29a0040 +#define F0900_P2_CAR2S2_32A_ALPH_M 0xf29a0030 +#define F0900_P2_CAR2S2_32A_ALPH_E 0xf29a000f + +/*P2_BCLC2S2Q*/ +#define R0900_P2_BCLC2S2Q 0xf29c +#define F0900_P2_DVBS2S2Q_NIP 0xf29c0080 +#define F0900_P2_CAR2S2_QBDERAT 0xf29c0040 +#define F0900_P2_CAR2S2_Q_BETA_M 0xf29c0030 +#define F0900_P2_CAR2S2_Q_BETA_E 0xf29c000f + +/*P2_BCLC2S28*/ +#define R0900_P2_BCLC2S28 0xf29d +#define F0900_P2_DVBS2S28_NIP 0xf29d0080 +#define F0900_P2_CAR2S2_8BDERAT 0xf29d0040 +#define F0900_P2_CAR2S2_8_BETA_M 0xf29d0030 +#define F0900_P2_CAR2S2_8_BETA_E 0xf29d000f + +/*P2_BCLC2S216A*/ +#define R0900_P2_BCLC2S216A 0xf29e +#define F0900_P2_DVBS2S216A_NIP 0xf29e0080 +#define F0900_P2_CAR2S2_16BDERAT 0xf29e0040 +#define F0900_P2_CAR2S2_16A_BETA_M 0xf29e0030 +#define F0900_P2_CAR2S2_16A_BETA_E 0xf29e000f + +/*P2_BCLC2S232A*/ +#define R0900_P2_BCLC2S232A 0xf29f +#define F0900_P2_DVBS2S232A_NIP 0xf29f0080 +#define F0900_P2_CAR2S2_32BDERAT 0xf29f0040 +#define F0900_P2_CAR2S2_32A_BETA_M 0xf29f0030 +#define F0900_P2_CAR2S2_32A_BETA_E 0xf29f000f + +/*P2_PLROOT2*/ +#define R0900_P2_PLROOT2 0xf2ac +#define F0900_P2_SHORTFR_DISABLE 0xf2ac0080 +#define F0900_P2_LONGFR_DISABLE 0xf2ac0040 +#define F0900_P2_DUMMYPL_DISABLE 0xf2ac0020 +#define F0900_P2_SHORTFR_AVOID 0xf2ac0010 +#define F0900_P2_PLSCRAMB_MODE 0xf2ac000c +#define F0900_P2_PLSCRAMB_ROOT2 0xf2ac0003 + +/*P2_PLROOT1*/ +#define R0900_P2_PLROOT1 0xf2ad +#define F0900_P2_PLSCRAMB_ROOT1 0xf2ad00ff + +/*P2_PLROOT0*/ +#define R0900_P2_PLROOT0 0xf2ae +#define F0900_P2_PLSCRAMB_ROOT0 0xf2ae00ff + +/*P2_MODCODLST0*/ +#define R0900_P2_MODCODLST0 0xf2b0 +#define F0900_P2_EN_TOKEN31 0xf2b00080 +#define F0900_P2_SYNCTAG_SELECT 0xf2b00040 +#define F0900_P2_MODCODRQ_MODE 0xf2b00030 + +/*P2_MODCODLST1*/ +#define R0900_P2_MODCODLST1 0xf2b1 +#define F0900_P2_DIS_MODCOD29 0xf2b100f0 +#define F0900_P2_DIS_32PSK_9_10 0xf2b1000f + +/*P2_MODCODLST2*/ +#define R0900_P2_MODCODLST2 0xf2b2 +#define F0900_P2_DIS_32PSK_8_9 0xf2b200f0 +#define F0900_P2_DIS_32PSK_5_6 0xf2b2000f + +/*P2_MODCODLST3*/ +#define R0900_P2_MODCODLST3 0xf2b3 +#define F0900_P2_DIS_32PSK_4_5 0xf2b300f0 +#define F0900_P2_DIS_32PSK_3_4 0xf2b3000f + +/*P2_MODCODLST4*/ +#define R0900_P2_MODCODLST4 0xf2b4 +#define F0900_P2_DIS_16PSK_9_10 0xf2b400f0 +#define F0900_P2_DIS_16PSK_8_9 0xf2b4000f + +/*P2_MODCODLST5*/ +#define R0900_P2_MODCODLST5 0xf2b5 +#define F0900_P2_DIS_16PSK_5_6 0xf2b500f0 +#define F0900_P2_DIS_16PSK_4_5 0xf2b5000f + +/*P2_MODCODLST6*/ +#define R0900_P2_MODCODLST6 0xf2b6 +#define F0900_P2_DIS_16PSK_3_4 0xf2b600f0 +#define F0900_P2_DIS_16PSK_2_3 0xf2b6000f + +/*P2_MODCODLST7*/ +#define R0900_P2_MODCODLST7 0xf2b7 +#define F0900_P2_DIS_8P_9_10 0xf2b700f0 +#define F0900_P2_DIS_8P_8_9 0xf2b7000f + +/*P2_MODCODLST8*/ +#define R0900_P2_MODCODLST8 0xf2b8 +#define F0900_P2_DIS_8P_5_6 0xf2b800f0 +#define F0900_P2_DIS_8P_3_4 0xf2b8000f + +/*P2_MODCODLST9*/ +#define R0900_P2_MODCODLST9 0xf2b9 +#define F0900_P2_DIS_8P_2_3 0xf2b900f0 +#define F0900_P2_DIS_8P_3_5 0xf2b9000f + +/*P2_MODCODLSTA*/ +#define R0900_P2_MODCODLSTA 0xf2ba +#define F0900_P2_DIS_QP_9_10 0xf2ba00f0 +#define F0900_P2_DIS_QP_8_9 0xf2ba000f + +/*P2_MODCODLSTB*/ +#define R0900_P2_MODCODLSTB 0xf2bb +#define F0900_P2_DIS_QP_5_6 0xf2bb00f0 +#define F0900_P2_DIS_QP_4_5 0xf2bb000f + +/*P2_MODCODLSTC*/ +#define R0900_P2_MODCODLSTC 0xf2bc +#define F0900_P2_DIS_QP_3_4 0xf2bc00f0 +#define F0900_P2_DIS_QP_2_3 0xf2bc000f + +/*P2_MODCODLSTD*/ +#define R0900_P2_MODCODLSTD 0xf2bd +#define F0900_P2_DIS_QP_3_5 0xf2bd00f0 +#define F0900_P2_DIS_QP_1_2 0xf2bd000f + +/*P2_MODCODLSTE*/ +#define R0900_P2_MODCODLSTE 0xf2be +#define F0900_P2_DIS_QP_2_5 0xf2be00f0 +#define F0900_P2_DIS_QP_1_3 0xf2be000f + +/*P2_MODCODLSTF*/ +#define R0900_P2_MODCODLSTF 0xf2bf +#define F0900_P2_DIS_QP_1_4 0xf2bf00f0 +#define F0900_P2_DDEMOD_SET 0xf2bf0002 +#define F0900_P2_DDEMOD_MASK 0xf2bf0001 + +/*P2_DMDRESCFG*/ +#define R0900_P2_DMDRESCFG 0xf2c6 +#define F0900_P2_DMDRES_RESET 0xf2c60080 +#define F0900_P2_DMDRES_NOISESQR 0xf2c60010 +#define F0900_P2_DMDRES_STRALL 0xf2c60008 +#define F0900_P2_DMDRES_NEWONLY 0xf2c60004 +#define F0900_P2_DMDRES_NOSTORE 0xf2c60002 +#define F0900_P2_DMDRES_AGC2MEM 0xf2c60001 + +/*P2_DMDRESADR*/ +#define R0900_P2_DMDRESADR 0xf2c7 +#define F0900_P2_SUSP_PREDCANAL 0xf2c70080 +#define F0900_P2_DMDRES_VALIDCFR 0xf2c70040 +#define F0900_P2_DMDRES_MEMFULL 0xf2c70030 +#define F0900_P2_DMDRES_RESNBR 0xf2c7000f + +/*P2_DMDRESDATA7*/ +#define R0900_P2_DMDRESDATA7 0xf2c8 +#define F0900_P2_DMDRES_DATA7 0xf2c800ff + +/*P2_DMDRESDATA6*/ +#define R0900_P2_DMDRESDATA6 0xf2c9 +#define F0900_P2_DMDRES_DATA6 0xf2c900ff + +/*P2_DMDRESDATA5*/ +#define R0900_P2_DMDRESDATA5 0xf2ca +#define F0900_P2_DMDRES_DATA5 0xf2ca00ff + +/*P2_DMDRESDATA4*/ +#define R0900_P2_DMDRESDATA4 0xf2cb +#define F0900_P2_DMDRES_DATA4 0xf2cb00ff + +/*P2_DMDRESDATA3*/ +#define R0900_P2_DMDRESDATA3 0xf2cc +#define F0900_P2_DMDRES_DATA3 0xf2cc00ff + +/*P2_DMDRESDATA2*/ +#define R0900_P2_DMDRESDATA2 0xf2cd +#define F0900_P2_DMDRES_DATA2 0xf2cd00ff + +/*P2_DMDRESDATA1*/ +#define R0900_P2_DMDRESDATA1 0xf2ce +#define F0900_P2_DMDRES_DATA1 0xf2ce00ff + +/*P2_DMDRESDATA0*/ +#define R0900_P2_DMDRESDATA0 0xf2cf +#define F0900_P2_DMDRES_DATA0 0xf2cf00ff + +/*P2_FFEI1*/ +#define R0900_P2_FFEI1 0xf2d0 +#define F0900_P2_FFE_ACCI1 0xf2d001ff + +/*P2_FFEQ1*/ +#define R0900_P2_FFEQ1 0xf2d1 +#define F0900_P2_FFE_ACCQ1 0xf2d101ff + +/*P2_FFEI2*/ +#define R0900_P2_FFEI2 0xf2d2 +#define F0900_P2_FFE_ACCI2 0xf2d201ff + +/*P2_FFEQ2*/ +#define R0900_P2_FFEQ2 0xf2d3 +#define F0900_P2_FFE_ACCQ2 0xf2d301ff + +/*P2_FFEI3*/ +#define R0900_P2_FFEI3 0xf2d4 +#define F0900_P2_FFE_ACCI3 0xf2d401ff + +/*P2_FFEQ3*/ +#define R0900_P2_FFEQ3 0xf2d5 +#define F0900_P2_FFE_ACCQ3 0xf2d501ff + +/*P2_FFEI4*/ +#define R0900_P2_FFEI4 0xf2d6 +#define F0900_P2_FFE_ACCI4 0xf2d601ff + +/*P2_FFEQ4*/ +#define R0900_P2_FFEQ4 0xf2d7 +#define F0900_P2_FFE_ACCQ4 0xf2d701ff + +/*P2_FFECFG*/ +#define R0900_P2_FFECFG 0xf2d8 +#define F0900_P2_EQUALFFE_ON 0xf2d80040 +#define F0900_P2_EQUAL_USEDSYMB 0xf2d80030 +#define F0900_P2_MU_EQUALFFE 0xf2d80007 + +/*P2_TNRCFG*/ +#define R0900_P2_TNRCFG 0xf2e0 +#define F0900_P2_TUN_ACKFAIL 0xf2e00080 +#define F0900_P2_TUN_TYPE 0xf2e00070 +#define F0900_P2_TUN_SECSTOP 0xf2e00008 +#define F0900_P2_TUN_VCOSRCH 0xf2e00004 +#define F0900_P2_TUN_MADDRESS 0xf2e00003 + +/*P2_TNRCFG2*/ +#define R0900_P2_TNRCFG2 0xf2e1 +#define F0900_P2_TUN_IQSWAP 0xf2e10080 +#define F0900_P2_STB6110_STEP2MHZ 0xf2e10040 +#define F0900_P2_STB6120_DBLI2C 0xf2e10020 +#define F0900_P2_DIS_FCCK 0xf2e10010 +#define F0900_P2_DIS_LPEN 0xf2e10008 +#define F0900_P2_DIS_BWCALC 0xf2e10004 +#define F0900_P2_SHORT_WAITSTATES 0xf2e10002 +#define F0900_P2_DIS_2BWAGC1 0xf2e10001 + +/*P2_TNRXTAL*/ +#define R0900_P2_TNRXTAL 0xf2e4 +#define F0900_P2_TUN_MCLKDECIMAL 0xf2e400e0 +#define F0900_P2_TUN_XTALFREQ 0xf2e4001f + +/*P2_TNRSTEPS*/ +#define R0900_P2_TNRSTEPS 0xf2e7 +#define F0900_P2_TUNER_BW1P6 0xf2e70080 +#define F0900_P2_BWINC_OFFSET 0xf2e70070 +#define F0900_P2_SOFTSTEP_RNG 0xf2e70008 +#define F0900_P2_TUN_BWOFFSET 0xf2e70107 + +/*P2_TNRGAIN*/ +#define R0900_P2_TNRGAIN 0xf2e8 +#define F0900_P2_TUN_KDIVEN 0xf2e800c0 +#define F0900_P2_STB6X00_OCK 0xf2e80030 +#define F0900_P2_TUN_GAIN 0xf2e8000f + +/*P2_TNRRF1*/ +#define R0900_P2_TNRRF1 0xf2e9 +#define F0900_P2_TUN_RFFREQ2 0xf2e900ff + +/*P2_TNRRF0*/ +#define R0900_P2_TNRRF0 0xf2ea +#define F0900_P2_TUN_RFFREQ1 0xf2ea00ff + +/*P2_TNRBW*/ +#define R0900_P2_TNRBW 0xf2eb +#define F0900_P2_TUN_RFFREQ0 0xf2eb00c0 +#define F0900_P2_TUN_BW 0xf2eb003f + +/*P2_TNRADJ*/ +#define R0900_P2_TNRADJ 0xf2ec +#define F0900_P2_STB61X0_RCLK 0xf2ec0080 +#define F0900_P2_STB61X0_CALTIME 0xf2ec0040 +#define F0900_P2_STB6X00_DLB 0xf2ec0038 +#define F0900_P2_STB6000_FCL 0xf2ec0007 + +/*P2_TNRCTL2*/ +#define R0900_P2_TNRCTL2 0xf2ed +#define F0900_P2_STB61X0_LCP1_RCCKOFF 0xf2ed0080 +#define F0900_P2_STB61X0_LCP0 0xf2ed0040 +#define F0900_P2_STB61X0_XTOUT_RFOUTS 0xf2ed0020 +#define F0900_P2_STB61X0_XTON_MCKDV 0xf2ed0010 +#define F0900_P2_STB61X0_CALOFF_DCOFF 0xf2ed0008 +#define F0900_P2_STB6110_LPT 0xf2ed0004 +#define F0900_P2_STB6110_RX 0xf2ed0002 +#define F0900_P2_STB6110_SYN 0xf2ed0001 + +/*P2_TNRCFG3*/ +#define R0900_P2_TNRCFG3 0xf2ee +#define F0900_P2_STB6120_DISCTRL1 0xf2ee0080 +#define F0900_P2_STB6120_INVORDER 0xf2ee0040 +#define F0900_P2_STB6120_ENCTRL6 0xf2ee0020 +#define F0900_P2_TUN_PLLFREQ 0xf2ee001c +#define F0900_P2_TUN_I2CFREQ_MODE 0xf2ee0003 + +/*P2_TNRLAUNCH*/ +#define R0900_P2_TNRLAUNCH 0xf2f0 + +/*P2_TNRLD*/ +#define R0900_P2_TNRLD 0xf2f0 +#define F0900_P2_TUNLD_VCOING 0xf2f00080 +#define F0900_P2_TUN_REG1FAIL 0xf2f00040 +#define F0900_P2_TUN_REG2FAIL 0xf2f00020 +#define F0900_P2_TUN_REG3FAIL 0xf2f00010 +#define F0900_P2_TUN_REG4FAIL 0xf2f00008 +#define F0900_P2_TUN_REG5FAIL 0xf2f00004 +#define F0900_P2_TUN_BWING 0xf2f00002 +#define F0900_P2_TUN_LOCKED 0xf2f00001 + +/*P2_TNROBSL*/ +#define R0900_P2_TNROBSL 0xf2f6 +#define F0900_P2_TUN_I2CABORTED 0xf2f60080 +#define F0900_P2_TUN_LPEN 0xf2f60040 +#define F0900_P2_TUN_FCCK 0xf2f60020 +#define F0900_P2_TUN_I2CLOCKED 0xf2f60010 +#define F0900_P2_TUN_PROGDONE 0xf2f6000c +#define F0900_P2_TUN_RFRESTE1 0xf2f60003 + +/*P2_TNRRESTE*/ +#define R0900_P2_TNRRESTE 0xf2f7 +#define F0900_P2_TUN_RFRESTE0 0xf2f700ff + +/*P2_SMAPCOEF7*/ +#define R0900_P2_SMAPCOEF7 0xf300 +#define F0900_P2_DIS_QSCALE 0xf3000080 +#define F0900_P2_SMAPCOEF_Q_LLR12 0xf300017f + +/*P2_SMAPCOEF6*/ +#define R0900_P2_SMAPCOEF6 0xf301 +#define F0900_P2_DIS_NEWSCALE 0xf3010008 +#define F0900_P2_ADJ_8PSKLLR1 0xf3010004 +#define F0900_P2_OLD_8PSKLLR1 0xf3010002 +#define F0900_P2_DIS_AB8PSK 0xf3010001 + +/*P2_SMAPCOEF5*/ +#define R0900_P2_SMAPCOEF5 0xf302 +#define F0900_P2_DIS_8SCALE 0xf3020080 +#define F0900_P2_SMAPCOEF_8P_LLR23 0xf302017f + +/*P2_DMDPLHSTAT*/ +#define R0900_P2_DMDPLHSTAT 0xf320 +#define F0900_P2_PLH_STATISTIC 0xf32000ff + +/*P2_LOCKTIME3*/ +#define R0900_P2_LOCKTIME3 0xf322 +#define F0900_P2_DEMOD_LOCKTIME3 0xf32200ff + +/*P2_LOCKTIME2*/ +#define R0900_P2_LOCKTIME2 0xf323 +#define F0900_P2_DEMOD_LOCKTIME2 0xf32300ff + +/*P2_LOCKTIME1*/ +#define R0900_P2_LOCKTIME1 0xf324 +#define F0900_P2_DEMOD_LOCKTIME1 0xf32400ff + +/*P2_LOCKTIME0*/ +#define R0900_P2_LOCKTIME0 0xf325 +#define F0900_P2_DEMOD_LOCKTIME0 0xf32500ff + +/*P2_VITSCALE*/ +#define R0900_P2_VITSCALE 0xf332 +#define F0900_P2_NVTH_NOSRANGE 0xf3320080 +#define F0900_P2_VERROR_MAXMODE 0xf3320040 +#define F0900_P2_KDIV_MODE 0xf3320030 +#define F0900_P2_NSLOWSN_LOCKED 0xf3320008 +#define F0900_P2_DELOCK_PRFLOSS 0xf3320004 +#define F0900_P2_DIS_RSFLOCK 0xf3320002 + +/*P2_FECM*/ +#define R0900_P2_FECM 0xf333 +#define F0900_P2_DSS_DVB 0xf3330080 +#define F0900_P2_DEMOD_BYPASS 0xf3330040 +#define F0900_P2_CMP_SLOWMODE 0xf3330020 +#define F0900_P2_DSS_SRCH 0xf3330010 +#define F0900_P2_DIFF_MODEVIT 0xf3330004 +#define F0900_P2_SYNCVIT 0xf3330002 +#define F0900_P2_IQINV 0xf3330001 + +/*P2_VTH12*/ +#define R0900_P2_VTH12 0xf334 +#define F0900_P2_VTH12 0xf33400ff + +/*P2_VTH23*/ +#define R0900_P2_VTH23 0xf335 +#define F0900_P2_VTH23 0xf33500ff + +/*P2_VTH34*/ +#define R0900_P2_VTH34 0xf336 +#define F0900_P2_VTH34 0xf33600ff + +/*P2_VTH56*/ +#define R0900_P2_VTH56 0xf337 +#define F0900_P2_VTH56 0xf33700ff + +/*P2_VTH67*/ +#define R0900_P2_VTH67 0xf338 +#define F0900_P2_VTH67 0xf33800ff + +/*P2_VTH78*/ +#define R0900_P2_VTH78 0xf339 +#define F0900_P2_VTH78 0xf33900ff + +/*P2_VITCURPUN*/ +#define R0900_P2_VITCURPUN 0xf33a +#define F0900_P2_VIT_MAPPING 0xf33a00e0 +#define F0900_P2_VIT_CURPUN 0xf33a001f + +/*P2_VERROR*/ +#define R0900_P2_VERROR 0xf33b +#define F0900_P2_REGERR_VIT 0xf33b00ff + +/*P2_PRVIT*/ +#define R0900_P2_PRVIT 0xf33c +#define F0900_P2_DIS_VTHLOCK 0xf33c0040 +#define F0900_P2_E7_8VIT 0xf33c0020 +#define F0900_P2_E6_7VIT 0xf33c0010 +#define F0900_P2_E5_6VIT 0xf33c0008 +#define F0900_P2_E3_4VIT 0xf33c0004 +#define F0900_P2_E2_3VIT 0xf33c0002 +#define F0900_P2_E1_2VIT 0xf33c0001 + +/*P2_VAVSRVIT*/ +#define R0900_P2_VAVSRVIT 0xf33d +#define F0900_P2_AMVIT 0xf33d0080 +#define F0900_P2_FROZENVIT 0xf33d0040 +#define F0900_P2_SNVIT 0xf33d0030 +#define F0900_P2_TOVVIT 0xf33d000c +#define F0900_P2_HYPVIT 0xf33d0003 + +/*P2_VSTATUSVIT*/ +#define R0900_P2_VSTATUSVIT 0xf33e +#define F0900_P2_VITERBI_ON 0xf33e0080 +#define F0900_P2_END_LOOPVIT 0xf33e0040 +#define F0900_P2_VITERBI_DEPRF 0xf33e0020 +#define F0900_P2_PRFVIT 0xf33e0010 +#define F0900_P2_LOCKEDVIT 0xf33e0008 +#define F0900_P2_VITERBI_DELOCK 0xf33e0004 +#define F0900_P2_VIT_DEMODSEL 0xf33e0002 +#define F0900_P2_VITERBI_COMPOUT 0xf33e0001 + +/*P2_VTHINUSE*/ +#define R0900_P2_VTHINUSE 0xf33f +#define F0900_P2_VIT_INUSE 0xf33f00ff + +/*P2_KDIV12*/ +#define R0900_P2_KDIV12 0xf340 +#define F0900_P2_KDIV12_MANUAL 0xf3400080 +#define F0900_P2_K_DIVIDER_12 0xf340007f + +/*P2_KDIV23*/ +#define R0900_P2_KDIV23 0xf341 +#define F0900_P2_KDIV23_MANUAL 0xf3410080 +#define F0900_P2_K_DIVIDER_23 0xf341007f + +/*P2_KDIV34*/ +#define R0900_P2_KDIV34 0xf342 +#define F0900_P2_KDIV34_MANUAL 0xf3420080 +#define F0900_P2_K_DIVIDER_34 0xf342007f + +/*P2_KDIV56*/ +#define R0900_P2_KDIV56 0xf343 +#define F0900_P2_KDIV56_MANUAL 0xf3430080 +#define F0900_P2_K_DIVIDER_56 0xf343007f + +/*P2_KDIV67*/ +#define R0900_P2_KDIV67 0xf344 +#define F0900_P2_KDIV67_MANUAL 0xf3440080 +#define F0900_P2_K_DIVIDER_67 0xf344007f + +/*P2_KDIV78*/ +#define R0900_P2_KDIV78 0xf345 +#define F0900_P2_KDIV78_MANUAL 0xf3450080 +#define F0900_P2_K_DIVIDER_78 0xf345007f + +/*P2_PDELCTRL1*/ +#define R0900_P2_PDELCTRL1 0xf350 +#define F0900_P2_INV_MISMASK 0xf3500080 +#define F0900_P2_FORCE_ACCEPTED 0xf3500040 +#define F0900_P2_FILTER_EN 0xf3500020 +#define F0900_P2_FORCE_PKTDELINUSE 0xf3500010 +#define F0900_P2_HYSTEN 0xf3500008 +#define F0900_P2_HYSTSWRST 0xf3500004 +#define F0900_P2_EN_MIS00 0xf3500002 +#define F0900_P2_ALGOSWRST 0xf3500001 + +/*P2_PDELCTRL2*/ +#define R0900_P2_PDELCTRL2 0xf351 +#define F0900_P2_FORCE_CONTINUOUS 0xf3510080 +#define F0900_P2_RESET_UPKO_COUNT 0xf3510040 +#define F0900_P2_USER_PKTDELIN_NB 0xf3510020 +#define F0900_P2_FORCE_LOCKED 0xf3510010 +#define F0900_P2_DATA_UNBBSCRAM 0xf3510008 +#define F0900_P2_FORCE_LONGPKT 0xf3510004 +#define F0900_P2_FRAME_MODE 0xf3510002 + +/*P2_HYSTTHRESH*/ +#define R0900_P2_HYSTTHRESH 0xf354 +#define F0900_P2_UNLCK_THRESH 0xf35400f0 +#define F0900_P2_DELIN_LCK_THRESH 0xf354000f + +/*P2_ISIENTRY*/ +#define R0900_P2_ISIENTRY 0xf35e +#define F0900_P2_ISI_ENTRY 0xf35e00ff + +/*P2_ISIBITENA*/ +#define R0900_P2_ISIBITENA 0xf35f +#define F0900_P2_ISI_BIT_EN 0xf35f00ff + +/*P2_MATSTR1*/ +#define R0900_P2_MATSTR1 0xf360 +#define F0900_P2_MATYPE_CURRENT1 0xf36000ff + +/*P2_MATSTR0*/ +#define R0900_P2_MATSTR0 0xf361 +#define F0900_P2_MATYPE_CURRENT0 0xf36100ff + +/*P2_UPLSTR1*/ +#define R0900_P2_UPLSTR1 0xf362 +#define F0900_P2_UPL_CURRENT1 0xf36200ff + +/*P2_UPLSTR0*/ +#define R0900_P2_UPLSTR0 0xf363 +#define F0900_P2_UPL_CURRENT0 0xf36300ff + +/*P2_DFLSTR1*/ +#define R0900_P2_DFLSTR1 0xf364 +#define F0900_P2_DFL_CURRENT1 0xf36400ff + +/*P2_DFLSTR0*/ +#define R0900_P2_DFLSTR0 0xf365 +#define F0900_P2_DFL_CURRENT0 0xf36500ff + +/*P2_SYNCSTR*/ +#define R0900_P2_SYNCSTR 0xf366 +#define F0900_P2_SYNC_CURRENT 0xf36600ff + +/*P2_SYNCDSTR1*/ +#define R0900_P2_SYNCDSTR1 0xf367 +#define F0900_P2_SYNCD_CURRENT1 0xf36700ff + +/*P2_SYNCDSTR0*/ +#define R0900_P2_SYNCDSTR0 0xf368 +#define F0900_P2_SYNCD_CURRENT0 0xf36800ff + +/*P2_PDELSTATUS1*/ +#define R0900_P2_PDELSTATUS1 0xf369 +#define F0900_P2_PKTDELIN_DELOCK 0xf3690080 +#define F0900_P2_SYNCDUPDFL_BADDFL 0xf3690040 +#define F0900_P2_CONTINUOUS_STREAM 0xf3690020 +#define F0900_P2_UNACCEPTED_STREAM 0xf3690010 +#define F0900_P2_BCH_ERROR_FLAG 0xf3690008 +#define F0900_P2_BBHCRCKO 0xf3690004 +#define F0900_P2_PKTDELIN_LOCK 0xf3690002 +#define F0900_P2_FIRST_LOCK 0xf3690001 + +/*P2_PDELSTATUS2*/ +#define R0900_P2_PDELSTATUS2 0xf36a +#define F0900_P2_PKTDEL_DEMODSEL 0xf36a0080 +#define F0900_P2_FRAME_MODCOD 0xf36a007c +#define F0900_P2_FRAME_TYPE 0xf36a0003 + +/*P2_BBFCRCKO1*/ +#define R0900_P2_BBFCRCKO1 0xf36b +#define F0900_P2_BBHCRC_KOCNT1 0xf36b00ff + +/*P2_BBFCRCKO0*/ +#define R0900_P2_BBFCRCKO0 0xf36c +#define F0900_P2_BBHCRC_KOCNT0 0xf36c00ff + +/*P2_UPCRCKO1*/ +#define R0900_P2_UPCRCKO1 0xf36d +#define F0900_P2_PKTCRC_KOCNT1 0xf36d00ff + +/*P2_UPCRCKO0*/ +#define R0900_P2_UPCRCKO0 0xf36e +#define F0900_P2_PKTCRC_KOCNT0 0xf36e00ff + +/*P2_TSSTATEM*/ +#define R0900_P2_TSSTATEM 0xf370 +#define F0900_P2_TSDIL_ON 0xf3700080 +#define F0900_P2_TSSKIPRS_ON 0xf3700040 +#define F0900_P2_TSRS_ON 0xf3700020 +#define F0900_P2_TSDESCRAMB_ON 0xf3700010 +#define F0900_P2_TSFRAME_MODE 0xf3700008 +#define F0900_P2_TS_DISABLE 0xf3700004 +#define F0900_P2_TSACM_MODE 0xf3700002 +#define F0900_P2_TSOUT_NOSYNC 0xf3700001 + +/*P2_TSCFGH*/ +#define R0900_P2_TSCFGH 0xf372 +#define F0900_P2_TSFIFO_DVBCI 0xf3720080 +#define F0900_P2_TSFIFO_SERIAL 0xf3720040 +#define F0900_P2_TSFIFO_TEIUPDATE 0xf3720020 +#define F0900_P2_TSFIFO_DUTY50 0xf3720010 +#define F0900_P2_TSFIFO_HSGNLOUT 0xf3720008 +#define F0900_P2_TSFIFO_ERRMODE 0xf3720006 +#define F0900_P2_RST_HWARE 0xf3720001 + +/*P2_TSCFGM*/ +#define R0900_P2_TSCFGM 0xf373 +#define F0900_P2_TSFIFO_MANSPEED 0xf37300c0 +#define F0900_P2_TSFIFO_PERMDATA 0xf3730020 +#define F0900_P2_TSFIFO_NONEWSGNL 0xf3730010 +#define F0900_P2_TSFIFO_BITSPEED 0xf3730008 +#define F0900_P2_NPD_SPECDVBS2 0xf3730004 +#define F0900_P2_TSFIFO_STOPCKDIS 0xf3730002 +#define F0900_P2_TSFIFO_INVDATA 0xf3730001 + +/*P2_TSCFGL*/ +#define R0900_P2_TSCFGL 0xf374 +#define F0900_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 +#define F0900_P2_BCHERROR_MODE 0xf3740030 +#define F0900_P2_TSFIFO_NSGNL2DATA 0xf3740008 +#define F0900_P2_TSFIFO_EMBINDVB 0xf3740004 +#define F0900_P2_TSFIFO_DPUNACT 0xf3740002 +#define F0900_P2_TSFIFO_NPDOFF 0xf3740001 + +/*P2_TSINSDELH*/ +#define R0900_P2_TSINSDELH 0xf376 +#define F0900_P2_TSDEL_SYNCBYTE 0xf3760080 +#define F0900_P2_TSDEL_XXHEADER 0xf3760040 +#define F0900_P2_TSDEL_BBHEADER 0xf3760020 +#define F0900_P2_TSDEL_DATAFIELD 0xf3760010 +#define F0900_P2_TSINSDEL_ISCR 0xf3760008 +#define F0900_P2_TSINSDEL_NPD 0xf3760004 +#define F0900_P2_TSINSDEL_RSPARITY 0xf3760002 +#define F0900_P2_TSINSDEL_CRC8 0xf3760001 + +/*P2_TSSPEED*/ +#define R0900_P2_TSSPEED 0xf380 +#define F0900_P2_TSFIFO_OUTSPEED 0xf38000ff + +/*P2_TSSTATUS*/ +#define R0900_P2_TSSTATUS 0xf381 +#define F0900_P2_TSFIFO_LINEOK 0xf3810080 +#define F0900_P2_TSFIFO_ERROR 0xf3810040 +#define F0900_P2_TSFIFO_DATA7 0xf3810020 +#define F0900_P2_TSFIFO_NOSYNC 0xf3810010 +#define F0900_P2_ISCR_INITIALIZED 0xf3810008 +#define F0900_P2_ISCR_UPDATED 0xf3810004 +#define F0900_P2_SOFFIFO_UNREGUL 0xf3810002 +#define F0900_P2_DIL_READY 0xf3810001 + +/*P2_TSSTATUS2*/ +#define R0900_P2_TSSTATUS2 0xf382 +#define F0900_P2_TSFIFO_DEMODSEL 0xf3820080 +#define F0900_P2_TSFIFOSPEED_STORE 0xf3820040 +#define F0900_P2_DILXX_RESET 0xf3820020 +#define F0900_P2_TSSERIAL_IMPOS 0xf3820010 +#define F0900_P2_TSFIFO_LINENOK 0xf3820008 +#define F0900_P2_BITSPEED_EVENT 0xf3820004 +#define F0900_P2_SCRAMBDETECT 0xf3820002 +#define F0900_P2_ULDTV67_FALSELOCK 0xf3820001 + +/*P2_TSBITRATE1*/ +#define R0900_P2_TSBITRATE1 0xf383 +#define F0900_P2_TSFIFO_BITRATE1 0xf38300ff + +/*P2_TSBITRATE0*/ +#define R0900_P2_TSBITRATE0 0xf384 +#define F0900_P2_TSFIFO_BITRATE0 0xf38400ff + +/*P2_ERRCTRL1*/ +#define R0900_P2_ERRCTRL1 0xf398 +#define F0900_P2_ERR_SOURCE1 0xf39800f0 +#define F0900_P2_NUM_EVENT1 0xf3980007 + +/*P2_ERRCNT12*/ +#define R0900_P2_ERRCNT12 0xf399 +#define F0900_P2_ERRCNT1_OLDVALUE 0xf3990080 +#define F0900_P2_ERR_CNT12 0xf399007f + +/*P2_ERRCNT11*/ +#define R0900_P2_ERRCNT11 0xf39a +#define F0900_P2_ERR_CNT11 0xf39a00ff + +/*P2_ERRCNT10*/ +#define R0900_P2_ERRCNT10 0xf39b +#define F0900_P2_ERR_CNT10 0xf39b00ff + +/*P2_ERRCTRL2*/ +#define R0900_P2_ERRCTRL2 0xf39c +#define F0900_P2_ERR_SOURCE2 0xf39c00f0 +#define F0900_P2_NUM_EVENT2 0xf39c0007 + +/*P2_ERRCNT22*/ +#define R0900_P2_ERRCNT22 0xf39d +#define F0900_P2_ERRCNT2_OLDVALUE 0xf39d0080 +#define F0900_P2_ERR_CNT22 0xf39d007f + +/*P2_ERRCNT21*/ +#define R0900_P2_ERRCNT21 0xf39e +#define F0900_P2_ERR_CNT21 0xf39e00ff + +/*P2_ERRCNT20*/ +#define R0900_P2_ERRCNT20 0xf39f +#define F0900_P2_ERR_CNT20 0xf39f00ff + +/*P2_FECSPY*/ +#define R0900_P2_FECSPY 0xf3a0 +#define F0900_P2_SPY_ENABLE 0xf3a00080 +#define F0900_P2_NO_SYNCBYTE 0xf3a00040 +#define F0900_P2_SERIAL_MODE 0xf3a00020 +#define F0900_P2_UNUSUAL_PACKET 0xf3a00010 +#define F0900_P2_BER_PACKMODE 0xf3a00008 +#define F0900_P2_BERMETER_LMODE 0xf3a00002 +#define F0900_P2_BERMETER_RESET 0xf3a00001 + +/*P2_FSPYCFG*/ +#define R0900_P2_FSPYCFG 0xf3a1 +#define F0900_P2_FECSPY_INPUT 0xf3a100c0 +#define F0900_P2_RST_ON_ERROR 0xf3a10020 +#define F0900_P2_ONE_SHOT 0xf3a10010 +#define F0900_P2_I2C_MODE 0xf3a1000c +#define F0900_P2_SPY_HYSTERESIS 0xf3a10003 + +/*P2_FSPYDATA*/ +#define R0900_P2_FSPYDATA 0xf3a2 +#define F0900_P2_SPY_STUFFING 0xf3a20080 +#define F0900_P2_NOERROR_PKTJITTER 0xf3a20040 +#define F0900_P2_SPY_CNULLPKT 0xf3a20020 +#define F0900_P2_SPY_OUTDATA_MODE 0xf3a2001f + +/*P2_FSPYOUT*/ +#define R0900_P2_FSPYOUT 0xf3a3 +#define F0900_P2_FSPY_DIRECT 0xf3a30080 +#define F0900_P2_SPY_OUTDATA_BUS 0xf3a30038 +#define F0900_P2_STUFF_MODE 0xf3a30007 + +/*P2_FSTATUS*/ +#define R0900_P2_FSTATUS 0xf3a4 +#define F0900_P2_SPY_ENDSIM 0xf3a40080 +#define F0900_P2_VALID_SIM 0xf3a40040 +#define F0900_P2_FOUND_SIGNAL 0xf3a40020 +#define F0900_P2_DSS_SYNCBYTE 0xf3a40010 +#define F0900_P2_RESULT_STATE 0xf3a4000f + +/*P2_FBERCPT4*/ +#define R0900_P2_FBERCPT4 0xf3a8 +#define F0900_P2_FBERMETER_CPT4 0xf3a800ff + +/*P2_FBERCPT3*/ +#define R0900_P2_FBERCPT3 0xf3a9 +#define F0900_P2_FBERMETER_CPT3 0xf3a900ff + +/*P2_FBERCPT2*/ +#define R0900_P2_FBERCPT2 0xf3aa +#define F0900_P2_FBERMETER_CPT2 0xf3aa00ff + +/*P2_FBERCPT1*/ +#define R0900_P2_FBERCPT1 0xf3ab +#define F0900_P2_FBERMETER_CPT1 0xf3ab00ff + +/*P2_FBERCPT0*/ +#define R0900_P2_FBERCPT0 0xf3ac +#define F0900_P2_FBERMETER_CPT0 0xf3ac00ff + +/*P2_FBERERR2*/ +#define R0900_P2_FBERERR2 0xf3ad +#define F0900_P2_FBERMETER_ERR2 0xf3ad00ff + +/*P2_FBERERR1*/ +#define R0900_P2_FBERERR1 0xf3ae +#define F0900_P2_FBERMETER_ERR1 0xf3ae00ff + +/*P2_FBERERR0*/ +#define R0900_P2_FBERERR0 0xf3af +#define F0900_P2_FBERMETER_ERR0 0xf3af00ff + +/*P2_FSPYBER*/ +#define R0900_P2_FSPYBER 0xf3b2 +#define F0900_P2_FSPYOBS_XORREAD 0xf3b20040 +#define F0900_P2_FSPYBER_OBSMODE 0xf3b20020 +#define F0900_P2_FSPYBER_SYNCBYTE 0xf3b20010 +#define F0900_P2_FSPYBER_UNSYNC 0xf3b20008 +#define F0900_P2_FSPYBER_CTIME 0xf3b20007 + +/*P1_IQCONST*/ +#define R0900_P1_IQCONST 0xf400 +#define F0900_P1_CONSTEL_SELECT 0xf4000060 +#define F0900_P1_IQSYMB_SEL 0xf400001f + +/*P1_NOSCFG*/ +#define R0900_P1_NOSCFG 0xf401 +#define F0900_P1_DUMMYPL_NOSDATA 0xf4010020 +#define F0900_P1_NOSPLH_BETA 0xf4010018 +#define F0900_P1_NOSDATA_BETA 0xf4010007 + +/*P1_ISYMB*/ +#define R0900_P1_ISYMB 0xf402 +#define F0900_P1_I_SYMBOL 0xf40201ff + +/*P1_QSYMB*/ +#define R0900_P1_QSYMB 0xf403 +#define F0900_P1_Q_SYMBOL 0xf40301ff + +/*P1_AGC1CFG*/ +#define R0900_P1_AGC1CFG 0xf404 +#define F0900_P1_DC_FROZEN 0xf4040080 +#define F0900_P1_DC_CORRECT 0xf4040040 +#define F0900_P1_AMM_FROZEN 0xf4040020 +#define F0900_P1_AMM_CORRECT 0xf4040010 +#define F0900_P1_QUAD_FROZEN 0xf4040008 +#define F0900_P1_QUAD_CORRECT 0xf4040004 +#define F0900_P1_DCCOMP_SLOW 0xf4040002 +#define F0900_P1_IQMISM_SLOW 0xf4040001 + +/*P1_AGC1CN*/ +#define R0900_P1_AGC1CN 0xf406 +#define F0900_P1_AGC1_LOCKED 0xf4060080 +#define F0900_P1_AGC1_OVERFLOW 0xf4060040 +#define F0900_P1_AGC1_NOSLOWLK 0xf4060020 +#define F0900_P1_AGC1_MINPOWER 0xf4060010 +#define F0900_P1_AGCOUT_FAST 0xf4060008 +#define F0900_P1_AGCIQ_BETA 0xf4060007 + +/*P1_AGC1REF*/ +#define R0900_P1_AGC1REF 0xf407 +#define F0900_P1_AGCIQ_REF 0xf40700ff + +/*P1_IDCCOMP*/ +#define R0900_P1_IDCCOMP 0xf408 +#define F0900_P1_IAVERAGE_ADJ 0xf40801ff + +/*P1_QDCCOMP*/ +#define R0900_P1_QDCCOMP 0xf409 +#define F0900_P1_QAVERAGE_ADJ 0xf40901ff + +/*P1_POWERI*/ +#define R0900_P1_POWERI 0xf40a +#define F0900_P1_POWER_I 0xf40a00ff + +/*P1_POWERQ*/ +#define R0900_P1_POWERQ 0xf40b +#define F0900_P1_POWER_Q 0xf40b00ff + +/*P1_AGC1AMM*/ +#define R0900_P1_AGC1AMM 0xf40c +#define F0900_P1_AMM_VALUE 0xf40c00ff + +/*P1_AGC1QUAD*/ +#define R0900_P1_AGC1QUAD 0xf40d +#define F0900_P1_QUAD_VALUE 0xf40d01ff + +/*P1_AGCIQIN1*/ +#define R0900_P1_AGCIQIN1 0xf40e +#define F0900_P1_AGCIQ_VALUE1 0xf40e00ff + +/*P1_AGCIQIN0*/ +#define R0900_P1_AGCIQIN0 0xf40f +#define F0900_P1_AGCIQ_VALUE0 0xf40f00ff + +/*P1_DEMOD*/ +#define R0900_P1_DEMOD 0xf410 +#define F0900_P1_DEMOD_STOP 0xf4100040 +#define F0900_P1_SPECINV_CONTROL 0xf4100030 +#define F0900_P1_FORCE_ENASAMP 0xf4100008 +#define F0900_P1_MANUAL_ROLLOFF 0xf4100004 +#define F0900_P1_ROLLOFF_CONTROL 0xf4100003 + +/*P1_DMDMODCOD*/ +#define R0900_P1_DMDMODCOD 0xf411 +#define F0900_P1_MANUAL_MODCOD 0xf4110080 +#define F0900_P1_DEMOD_MODCOD 0xf411007c +#define F0900_P1_DEMOD_TYPE 0xf4110003 + +/*P1_DSTATUS*/ +#define R0900_P1_DSTATUS 0xf412 +#define F0900_P1_CAR_LOCK 0xf4120080 +#define F0900_P1_TMGLOCK_QUALITY 0xf4120060 +#define F0900_P1_SDVBS1_ENABLE 0xf4120010 +#define F0900_P1_LOCK_DEFINITIF 0xf4120008 +#define F0900_P1_TIMING_IS_LOCKED 0xf4120004 +#define F0900_P1_COARSE_TMGLOCK 0xf4120002 +#define F0900_P1_COARSE_CARLOCK 0xf4120001 + +/*P1_DSTATUS2*/ +#define R0900_P1_DSTATUS2 0xf413 +#define F0900_P1_DEMOD_DELOCK 0xf4130080 +#define F0900_P1_DEMOD_TIMEOUT 0xf4130040 +#define F0900_P1_MODCODRQ_SYNCTAG 0xf4130020 +#define F0900_P1_POLYPH_SATEVENT 0xf4130010 +#define F0900_P1_AGC1_NOSIGNALACK 0xf4130008 +#define F0900_P1_AGC2_OVERFLOW 0xf4130004 +#define F0900_P1_CFR_OVERFLOW 0xf4130002 +#define F0900_P1_GAMMA_OVERUNDER 0xf4130001 + +/*P1_DMDCFGMD*/ +#define R0900_P1_DMDCFGMD 0xf414 +#define F0900_P1_DVBS2_ENABLE 0xf4140080 +#define F0900_P1_DVBS1_ENABLE 0xf4140040 +#define F0900_P1_CFR_AUTOSCAN 0xf4140020 +#define F0900_P1_SCAN_ENABLE 0xf4140010 +#define F0900_P1_TUN_AUTOSCAN 0xf4140008 +#define F0900_P1_NOFORCE_RELOCK 0xf4140004 +#define F0900_P1_TUN_RNG 0xf4140003 + +/*P1_DMDCFG2*/ +#define R0900_P1_DMDCFG2 0xf415 +#define F0900_P1_AGC1_WAITLOCK 0xf4150080 +#define F0900_P1_S1S2_SEQUENTIAL 0xf4150040 +#define F0900_P1_OVERFLOW_TIMEOUT 0xf4150020 +#define F0900_P1_SCANFAIL_TIMEOUT 0xf4150010 +#define F0900_P1_DMDTOUT_BACK 0xf4150008 +#define F0900_P1_CARLOCK_S1ENABLE 0xf4150004 +#define F0900_P1_COARSE_LK3MODE 0xf4150002 +#define F0900_P1_COARSE_LK2MODE 0xf4150001 + +/*P1_DMDISTATE*/ +#define R0900_P1_DMDISTATE 0xf416 +#define F0900_P1_I2C_NORESETDMODE 0xf4160080 +#define F0900_P1_FORCE_ETAPED 0xf4160040 +#define F0900_P1_SDMDRST_DIRCLK 0xf4160020 +#define F0900_P1_I2C_DEMOD_MODE 0xf416001f + +/*P1_DMDT0M*/ +#define R0900_P1_DMDT0M 0xf417 +#define F0900_P1_DMDT0_MIN 0xf41700ff + +/*P1_DMDSTATE*/ +#define R0900_P1_DMDSTATE 0xf41b +#define F0900_P1_DEMOD_LOCKED 0xf41b0080 +#define F0900_P1_HEADER_MODE 0xf41b0060 +#define F0900_P1_DEMOD_MODE 0xf41b001f + +/*P1_DMDFLYW*/ +#define R0900_P1_DMDFLYW 0xf41c +#define F0900_P1_I2C_IRQVAL 0xf41c00f0 +#define F0900_P1_FLYWHEEL_CPT 0xf41c000f + +/*P1_DSTATUS3*/ +#define R0900_P1_DSTATUS3 0xf41d +#define F0900_P1_CFR_ZIGZAG 0xf41d0080 +#define F0900_P1_DEMOD_CFGMODE 0xf41d0060 +#define F0900_P1_GAMMA_LOWBAUDRATE 0xf41d0010 +#define F0900_P1_RELOCK_MODE 0xf41d0008 +#define F0900_P1_DEMOD_FAIL 0xf41d0004 +#define F0900_P1_ETAPE1A_DVBXMEM 0xf41d0003 + +/*P1_DMDCFG3*/ +#define R0900_P1_DMDCFG3 0xf41e +#define F0900_P1_DVBS1_TMGWAIT 0xf41e0080 +#define F0900_P1_NO_BWCENTERING 0xf41e0040 +#define F0900_P1_INV_SEQSRCH 0xf41e0020 +#define F0900_P1_DIS_SFRUPLOW_TRK 0xf41e0010 +#define F0900_P1_NOSTOP_FIFOFULL 0xf41e0008 +#define F0900_P1_LOCKTIME_MODE 0xf41e0007 + +/*P1_DMDCFG4*/ +#define R0900_P1_DMDCFG4 0xf41f +#define F0900_P1_TUNER_NRELAUNCH 0xf41f0008 +#define F0900_P1_DIS_CLKENABLE 0xf41f0004 +#define F0900_P1_DIS_HDRDIVLOCK 0xf41f0002 +#define F0900_P1_NO_TNRWBINIT 0xf41f0001 + +/*P1_CORRELMANT*/ +#define R0900_P1_CORRELMANT 0xf420 +#define F0900_P1_CORREL_MANT 0xf42000ff + +/*P1_CORRELABS*/ +#define R0900_P1_CORRELABS 0xf421 +#define F0900_P1_CORREL_ABS 0xf42100ff + +/*P1_CORRELEXP*/ +#define R0900_P1_CORRELEXP 0xf422 +#define F0900_P1_CORREL_ABSEXP 0xf42200f0 +#define F0900_P1_CORREL_EXP 0xf422000f + +/*P1_PLHMODCOD*/ +#define R0900_P1_PLHMODCOD 0xf424 +#define F0900_P1_SPECINV_DEMOD 0xf4240080 +#define F0900_P1_PLH_MODCOD 0xf424007c +#define F0900_P1_PLH_TYPE 0xf4240003 + +/*P1_AGCK32*/ +#define R0900_P1_AGCK32 0xf42b +#define F0900_P1_R3ADJOFF_32APSK 0xf42b0080 +#define F0900_P1_R2ADJOFF_32APSK 0xf42b0040 +#define F0900_P1_R1ADJOFF_32APSK 0xf42b0020 +#define F0900_P1_RADJ_32APSK 0xf42b001f + +/*P1_AGC2O*/ +#define R0900_P1_AGC2O 0xf42c +#define F0900_P1_AGC2REF_ADJUSTING 0xf42c0080 +#define F0900_P1_AGC2_COARSEFAST 0xf42c0040 +#define F0900_P1_AGC2_LKSQRT 0xf42c0020 +#define F0900_P1_AGC2_LKMODE 0xf42c0010 +#define F0900_P1_AGC2_LKEQUA 0xf42c0008 +#define F0900_P1_AGC2_COEF 0xf42c0007 + +/*P1_AGC2REF*/ +#define R0900_P1_AGC2REF 0xf42d +#define F0900_P1_AGC2_REF 0xf42d00ff + +/*P1_AGC1ADJ*/ +#define R0900_P1_AGC1ADJ 0xf42e +#define F0900_P1_AGC1ADJ_MANUAL 0xf42e0080 +#define F0900_P1_AGC1_ADJUSTED 0xf42e017f + +/*P1_AGC2I1*/ +#define R0900_P1_AGC2I1 0xf436 +#define F0900_P1_AGC2_INTEGRATOR1 0xf43600ff + +/*P1_AGC2I0*/ +#define R0900_P1_AGC2I0 0xf437 +#define F0900_P1_AGC2_INTEGRATOR0 0xf43700ff + +/*P1_CARCFG*/ +#define R0900_P1_CARCFG 0xf438 +#define F0900_P1_CFRUPLOW_AUTO 0xf4380080 +#define F0900_P1_CFRUPLOW_TEST 0xf4380040 +#define F0900_P1_EN_CAR2CENTER 0xf4380020 +#define F0900_P1_CARHDR_NODIV8 0xf4380010 +#define F0900_P1_I2C_ROTA 0xf4380008 +#define F0900_P1_ROTAON 0xf4380004 +#define F0900_P1_PH_DET_ALGO 0xf4380003 + +/*P1_ACLC*/ +#define R0900_P1_ACLC 0xf439 +#define F0900_P1_STOP_S2ALPHA 0xf43900c0 +#define F0900_P1_CAR_ALPHA_MANT 0xf4390030 +#define F0900_P1_CAR_ALPHA_EXP 0xf439000f + +/*P1_BCLC*/ +#define R0900_P1_BCLC 0xf43a +#define F0900_P1_STOP_S2BETA 0xf43a00c0 +#define F0900_P1_CAR_BETA_MANT 0xf43a0030 +#define F0900_P1_CAR_BETA_EXP 0xf43a000f + +/*P1_CARFREQ*/ +#define R0900_P1_CARFREQ 0xf43d +#define F0900_P1_KC_COARSE_EXP 0xf43d00f0 +#define F0900_P1_BETA_FREQ 0xf43d000f + +/*P1_CARHDR*/ +#define R0900_P1_CARHDR 0xf43e +#define F0900_P1_K_FREQ_HDR 0xf43e00ff + +/*P1_LDT*/ +#define R0900_P1_LDT 0xf43f +#define F0900_P1_CARLOCK_THRES 0xf43f01ff + +/*P1_LDT2*/ +#define R0900_P1_LDT2 0xf440 +#define F0900_P1_CARLOCK_THRES2 0xf44001ff + +/*P1_CFRICFG*/ +#define R0900_P1_CFRICFG 0xf441 +#define F0900_P1_CFRINIT_UNVALRNG 0xf4410080 +#define F0900_P1_CFRINIT_LUNVALCPT 0xf4410040 +#define F0900_P1_CFRINIT_ABORTDBL 0xf4410020 +#define F0900_P1_CFRINIT_ABORTPRED 0xf4410010 +#define F0900_P1_CFRINIT_UNVALSKIP 0xf4410008 +#define F0900_P1_CFRINIT_CSTINC 0xf4410004 +#define F0900_P1_NEG_CFRSTEP 0xf4410001 + +/*P1_CFRUP1*/ +#define R0900_P1_CFRUP1 0xf442 +#define F0900_P1_CFR_UP1 0xf44201ff + +/*P1_CFRUP0*/ +#define R0900_P1_CFRUP0 0xf443 +#define F0900_P1_CFR_UP0 0xf44300ff + +/*P1_CFRLOW1*/ +#define R0900_P1_CFRLOW1 0xf446 +#define F0900_P1_CFR_LOW1 0xf44601ff + +/*P1_CFRLOW0*/ +#define R0900_P1_CFRLOW0 0xf447 +#define F0900_P1_CFR_LOW0 0xf44700ff + +/*P1_CFRINIT1*/ +#define R0900_P1_CFRINIT1 0xf448 +#define F0900_P1_CFR_INIT1 0xf44801ff + +/*P1_CFRINIT0*/ +#define R0900_P1_CFRINIT0 0xf449 +#define F0900_P1_CFR_INIT0 0xf44900ff + +/*P1_CFRINC1*/ +#define R0900_P1_CFRINC1 0xf44a +#define F0900_P1_MANUAL_CFRINC 0xf44a0080 +#define F0900_P1_CFR_INC1 0xf44a017f + +/*P1_CFRINC0*/ +#define R0900_P1_CFRINC0 0xf44b +#define F0900_P1_CFR_INC0 0xf44b00f0 + +/*P1_CFR2*/ +#define R0900_P1_CFR2 0xf44c +#define F0900_P1_CAR_FREQ2 0xf44c01ff + +/*P1_CFR1*/ +#define R0900_P1_CFR1 0xf44d +#define F0900_P1_CAR_FREQ1 0xf44d00ff + +/*P1_CFR0*/ +#define R0900_P1_CFR0 0xf44e +#define F0900_P1_CAR_FREQ0 0xf44e00ff + +/*P1_LDI*/ +#define R0900_P1_LDI 0xf44f +#define F0900_P1_LOCK_DET_INTEGR 0xf44f01ff + +/*P1_TMGCFG*/ +#define R0900_P1_TMGCFG 0xf450 +#define F0900_P1_TMGLOCK_BETA 0xf45000c0 +#define F0900_P1_NOTMG_GROUPDELAY 0xf4500020 +#define F0900_P1_DO_TIMING_CORR 0xf4500010 +#define F0900_P1_MANUAL_SCAN 0xf450000c +#define F0900_P1_TMG_MINFREQ 0xf4500003 + +/*P1_RTC*/ +#define R0900_P1_RTC 0xf451 +#define F0900_P1_TMGALPHA_EXP 0xf45100f0 +#define F0900_P1_TMGBETA_EXP 0xf451000f + +/*P1_RTCS2*/ +#define R0900_P1_RTCS2 0xf452 +#define F0900_P1_TMGALPHAS2_EXP 0xf45200f0 +#define F0900_P1_TMGBETAS2_EXP 0xf452000f + +/*P1_TMGTHRISE*/ +#define R0900_P1_TMGTHRISE 0xf453 +#define F0900_P1_TMGLOCK_THRISE 0xf45300ff + +/*P1_TMGTHFALL*/ +#define R0900_P1_TMGTHFALL 0xf454 +#define F0900_P1_TMGLOCK_THFALL 0xf45400ff + +/*P1_SFRUPRATIO*/ +#define R0900_P1_SFRUPRATIO 0xf455 +#define F0900_P1_SFR_UPRATIO 0xf45500ff + +/*P1_SFRLOWRATIO*/ +#define R0900_P1_SFRLOWRATIO 0xf456 +#define F0900_P1_SFR_LOWRATIO 0xf45600ff + +/*P1_KREFTMG*/ +#define R0900_P1_KREFTMG 0xf458 +#define F0900_P1_KREF_TMG 0xf45800ff + +/*P1_SFRSTEP*/ +#define R0900_P1_SFRSTEP 0xf459 +#define F0900_P1_SFR_SCANSTEP 0xf45900f0 +#define F0900_P1_SFR_CENTERSTEP 0xf459000f + +/*P1_TMGCFG2*/ +#define R0900_P1_TMGCFG2 0xf45a +#define F0900_P1_DIS_AUTOSAMP 0xf45a0008 +#define F0900_P1_SCANINIT_QUART 0xf45a0004 +#define F0900_P1_NOTMG_DVBS1DERAT 0xf45a0002 +#define F0900_P1_SFRRATIO_FINE 0xf45a0001 + +/*P1_SFRINIT1*/ +#define R0900_P1_SFRINIT1 0xf45e +#define F0900_P1_SFR_INIT1 0xf45e00ff + +/*P1_SFRINIT0*/ +#define R0900_P1_SFRINIT0 0xf45f +#define F0900_P1_SFR_INIT0 0xf45f00ff + +/*P1_SFRUP1*/ +#define R0900_P1_SFRUP1 0xf460 +#define F0900_P1_AUTO_GUP 0xf4600080 +#define F0900_P1_SYMB_FREQ_UP1 0xf460007f + +/*P1_SFRUP0*/ +#define R0900_P1_SFRUP0 0xf461 +#define F0900_P1_SYMB_FREQ_UP0 0xf46100ff + +/*P1_SFRLOW1*/ +#define R0900_P1_SFRLOW1 0xf462 +#define F0900_P1_AUTO_GLOW 0xf4620080 +#define F0900_P1_SYMB_FREQ_LOW1 0xf462007f + +/*P1_SFRLOW0*/ +#define R0900_P1_SFRLOW0 0xf463 +#define F0900_P1_SYMB_FREQ_LOW0 0xf46300ff + +/*P1_SFR3*/ +#define R0900_P1_SFR3 0xf464 +#define F0900_P1_SYMB_FREQ3 0xf46400ff + +/*P1_SFR2*/ +#define R0900_P1_SFR2 0xf465 +#define F0900_P1_SYMB_FREQ2 0xf46500ff + +/*P1_SFR1*/ +#define R0900_P1_SFR1 0xf466 +#define F0900_P1_SYMB_FREQ1 0xf46600ff + +/*P1_SFR0*/ +#define R0900_P1_SFR0 0xf467 +#define F0900_P1_SYMB_FREQ0 0xf46700ff + +/*P1_TMGREG2*/ +#define R0900_P1_TMGREG2 0xf468 +#define F0900_P1_TMGREG2 0xf46800ff + +/*P1_TMGREG1*/ +#define R0900_P1_TMGREG1 0xf469 +#define F0900_P1_TMGREG1 0xf46900ff + +/*P1_TMGREG0*/ +#define R0900_P1_TMGREG0 0xf46a +#define F0900_P1_TMGREG0 0xf46a00ff + +/*P1_TMGLOCK1*/ +#define R0900_P1_TMGLOCK1 0xf46b +#define F0900_P1_TMGLOCK_LEVEL1 0xf46b01ff + +/*P1_TMGLOCK0*/ +#define R0900_P1_TMGLOCK0 0xf46c +#define F0900_P1_TMGLOCK_LEVEL0 0xf46c00ff + +/*P1_TMGOBS*/ +#define R0900_P1_TMGOBS 0xf46d +#define F0900_P1_ROLLOFF_STATUS 0xf46d00c0 +#define F0900_P1_SCAN_SIGN 0xf46d0030 +#define F0900_P1_TMG_SCANNING 0xf46d0008 +#define F0900_P1_CHCENTERING_MODE 0xf46d0004 +#define F0900_P1_TMG_SCANFAIL 0xf46d0002 + +/*P1_EQUALCFG*/ +#define R0900_P1_EQUALCFG 0xf46f +#define F0900_P1_NOTMG_NEGALWAIT 0xf46f0080 +#define F0900_P1_EQUAL_ON 0xf46f0040 +#define F0900_P1_SEL_EQUALCOR 0xf46f0038 +#define F0900_P1_MU_EQUALDFE 0xf46f0007 + +/*P1_EQUAI1*/ +#define R0900_P1_EQUAI1 0xf470 +#define F0900_P1_EQUA_ACCI1 0xf47001ff + +/*P1_EQUAQ1*/ +#define R0900_P1_EQUAQ1 0xf471 +#define F0900_P1_EQUA_ACCQ1 0xf47101ff + +/*P1_EQUAI2*/ +#define R0900_P1_EQUAI2 0xf472 +#define F0900_P1_EQUA_ACCI2 0xf47201ff + +/*P1_EQUAQ2*/ +#define R0900_P1_EQUAQ2 0xf473 +#define F0900_P1_EQUA_ACCQ2 0xf47301ff + +/*P1_EQUAI3*/ +#define R0900_P1_EQUAI3 0xf474 +#define F0900_P1_EQUA_ACCI3 0xf47401ff + +/*P1_EQUAQ3*/ +#define R0900_P1_EQUAQ3 0xf475 +#define F0900_P1_EQUA_ACCQ3 0xf47501ff + +/*P1_EQUAI4*/ +#define R0900_P1_EQUAI4 0xf476 +#define F0900_P1_EQUA_ACCI4 0xf47601ff + +/*P1_EQUAQ4*/ +#define R0900_P1_EQUAQ4 0xf477 +#define F0900_P1_EQUA_ACCQ4 0xf47701ff + +/*P1_EQUAI5*/ +#define R0900_P1_EQUAI5 0xf478 +#define F0900_P1_EQUA_ACCI5 0xf47801ff + +/*P1_EQUAQ5*/ +#define R0900_P1_EQUAQ5 0xf479 +#define F0900_P1_EQUA_ACCQ5 0xf47901ff + +/*P1_EQUAI6*/ +#define R0900_P1_EQUAI6 0xf47a +#define F0900_P1_EQUA_ACCI6 0xf47a01ff + +/*P1_EQUAQ6*/ +#define R0900_P1_EQUAQ6 0xf47b +#define F0900_P1_EQUA_ACCQ6 0xf47b01ff + +/*P1_EQUAI7*/ +#define R0900_P1_EQUAI7 0xf47c +#define F0900_P1_EQUA_ACCI7 0xf47c01ff + +/*P1_EQUAQ7*/ +#define R0900_P1_EQUAQ7 0xf47d +#define F0900_P1_EQUA_ACCQ7 0xf47d01ff + +/*P1_EQUAI8*/ +#define R0900_P1_EQUAI8 0xf47e +#define F0900_P1_EQUA_ACCI8 0xf47e01ff + +/*P1_EQUAQ8*/ +#define R0900_P1_EQUAQ8 0xf47f +#define F0900_P1_EQUA_ACCQ8 0xf47f01ff + +/*P1_NNOSDATAT1*/ +#define R0900_P1_NNOSDATAT1 0xf480 +#define F0900_P1_NOSDATAT_NORMED1 0xf48000ff + +/*P1_NNOSDATAT0*/ +#define R0900_P1_NNOSDATAT0 0xf481 +#define F0900_P1_NOSDATAT_NORMED0 0xf48100ff + +/*P1_NNOSDATA1*/ +#define R0900_P1_NNOSDATA1 0xf482 +#define F0900_P1_NOSDATA_NORMED1 0xf48200ff + +/*P1_NNOSDATA0*/ +#define R0900_P1_NNOSDATA0 0xf483 +#define F0900_P1_NOSDATA_NORMED0 0xf48300ff + +/*P1_NNOSPLHT1*/ +#define R0900_P1_NNOSPLHT1 0xf484 +#define F0900_P1_NOSPLHT_NORMED1 0xf48400ff + +/*P1_NNOSPLHT0*/ +#define R0900_P1_NNOSPLHT0 0xf485 +#define F0900_P1_NOSPLHT_NORMED0 0xf48500ff + +/*P1_NNOSPLH1*/ +#define R0900_P1_NNOSPLH1 0xf486 +#define F0900_P1_NOSPLH_NORMED1 0xf48600ff + +/*P1_NNOSPLH0*/ +#define R0900_P1_NNOSPLH0 0xf487 +#define F0900_P1_NOSPLH_NORMED0 0xf48700ff + +/*P1_NOSDATAT1*/ +#define R0900_P1_NOSDATAT1 0xf488 +#define F0900_P1_NOSDATAT_UNNORMED1 0xf48800ff + +/*P1_NOSDATAT0*/ +#define R0900_P1_NOSDATAT0 0xf489 +#define F0900_P1_NOSDATAT_UNNORMED0 0xf48900ff + +/*P1_NOSDATA1*/ +#define R0900_P1_NOSDATA1 0xf48a +#define F0900_P1_NOSDATA_UNNORMED1 0xf48a00ff + +/*P1_NOSDATA0*/ +#define R0900_P1_NOSDATA0 0xf48b +#define F0900_P1_NOSDATA_UNNORMED0 0xf48b00ff + +/*P1_NOSPLHT1*/ +#define R0900_P1_NOSPLHT1 0xf48c +#define F0900_P1_NOSPLHT_UNNORMED1 0xf48c00ff + +/*P1_NOSPLHT0*/ +#define R0900_P1_NOSPLHT0 0xf48d +#define F0900_P1_NOSPLHT_UNNORMED0 0xf48d00ff + +/*P1_NOSPLH1*/ +#define R0900_P1_NOSPLH1 0xf48e +#define F0900_P1_NOSPLH_UNNORMED1 0xf48e00ff + +/*P1_NOSPLH0*/ +#define R0900_P1_NOSPLH0 0xf48f +#define F0900_P1_NOSPLH_UNNORMED0 0xf48f00ff + +/*P1_CAR2CFG*/ +#define R0900_P1_CAR2CFG 0xf490 +#define F0900_P1_DESCRAMB_OFF 0xf4900080 +#define F0900_P1_PN4_SELECT 0xf4900040 +#define F0900_P1_CFR2_STOPDVBS1 0xf4900020 +#define F0900_P1_STOP_CFR2UPDATE 0xf4900010 +#define F0900_P1_STOP_NCO2UPDATE 0xf4900008 +#define F0900_P1_ROTA2ON 0xf4900004 +#define F0900_P1_PH_DET_ALGO2 0xf4900003 + +/*P1_ACLC2*/ +#define R0900_P1_ACLC2 0xf491 +#define F0900_P1_CAR2_PUNCT_ADERAT 0xf4910040 +#define F0900_P1_CAR2_ALPHA_MANT 0xf4910030 +#define F0900_P1_CAR2_ALPHA_EXP 0xf491000f + +/*P1_BCLC2*/ +#define R0900_P1_BCLC2 0xf492 +#define F0900_P1_DVBS2_NIP 0xf4920080 +#define F0900_P1_CAR2_PUNCT_BDERAT 0xf4920040 +#define F0900_P1_CAR2_BETA_MANT 0xf4920030 +#define F0900_P1_CAR2_BETA_EXP 0xf492000f + +/*P1_CFR22*/ +#define R0900_P1_CFR22 0xf493 +#define F0900_P1_CAR2_FREQ2 0xf49301ff + +/*P1_CFR21*/ +#define R0900_P1_CFR21 0xf494 +#define F0900_P1_CAR2_FREQ1 0xf49400ff + +/*P1_CFR20*/ +#define R0900_P1_CFR20 0xf495 +#define F0900_P1_CAR2_FREQ0 0xf49500ff + +/*P1_ACLC2S2Q*/ +#define R0900_P1_ACLC2S2Q 0xf497 +#define F0900_P1_ENAB_SPSKSYMB 0xf4970080 +#define F0900_P1_CAR2S2_QADERAT 0xf4970040 +#define F0900_P1_CAR2S2_Q_ALPH_M 0xf4970030 +#define F0900_P1_CAR2S2_Q_ALPH_E 0xf497000f + +/*P1_ACLC2S28*/ +#define R0900_P1_ACLC2S28 0xf498 +#define F0900_P1_OLDI3Q_MODE 0xf4980080 +#define F0900_P1_CAR2S2_8ADERAT 0xf4980040 +#define F0900_P1_CAR2S2_8_ALPH_M 0xf4980030 +#define F0900_P1_CAR2S2_8_ALPH_E 0xf498000f + +/*P1_ACLC2S216A*/ +#define R0900_P1_ACLC2S216A 0xf499 +#define F0900_P1_CAR2S2_16ADERAT 0xf4990040 +#define F0900_P1_CAR2S2_16A_ALPH_M 0xf4990030 +#define F0900_P1_CAR2S2_16A_ALPH_E 0xf499000f + +/*P1_ACLC2S232A*/ +#define R0900_P1_ACLC2S232A 0xf49a +#define F0900_P1_CAR2S2_32ADERAT 0xf49a0040 +#define F0900_P1_CAR2S2_32A_ALPH_M 0xf49a0030 +#define F0900_P1_CAR2S2_32A_ALPH_E 0xf49a000f + +/*P1_BCLC2S2Q*/ +#define R0900_P1_BCLC2S2Q 0xf49c +#define F0900_P1_DVBS2S2Q_NIP 0xf49c0080 +#define F0900_P1_CAR2S2_QBDERAT 0xf49c0040 +#define F0900_P1_CAR2S2_Q_BETA_M 0xf49c0030 +#define F0900_P1_CAR2S2_Q_BETA_E 0xf49c000f + +/*P1_BCLC2S28*/ +#define R0900_P1_BCLC2S28 0xf49d +#define F0900_P1_DVBS2S28_NIP 0xf49d0080 +#define F0900_P1_CAR2S2_8BDERAT 0xf49d0040 +#define F0900_P1_CAR2S2_8_BETA_M 0xf49d0030 +#define F0900_P1_CAR2S2_8_BETA_E 0xf49d000f + +/*P1_BCLC2S216A*/ +#define R0900_P1_BCLC2S216A 0xf49e +#define F0900_P1_DVBS2S216A_NIP 0xf49e0080 +#define F0900_P1_CAR2S2_16BDERAT 0xf49e0040 +#define F0900_P1_CAR2S2_16A_BETA_M 0xf49e0030 +#define F0900_P1_CAR2S2_16A_BETA_E 0xf49e000f + +/*P1_BCLC2S232A*/ +#define R0900_P1_BCLC2S232A 0xf49f +#define F0900_P1_DVBS2S232A_NIP 0xf49f0080 +#define F0900_P1_CAR2S2_32BDERAT 0xf49f0040 +#define F0900_P1_CAR2S2_32A_BETA_M 0xf49f0030 +#define F0900_P1_CAR2S2_32A_BETA_E 0xf49f000f + +/*P1_PLROOT2*/ +#define R0900_P1_PLROOT2 0xf4ac +#define F0900_P1_SHORTFR_DISABLE 0xf4ac0080 +#define F0900_P1_LONGFR_DISABLE 0xf4ac0040 +#define F0900_P1_DUMMYPL_DISABLE 0xf4ac0020 +#define F0900_P1_SHORTFR_AVOID 0xf4ac0010 +#define F0900_P1_PLSCRAMB_MODE 0xf4ac000c +#define F0900_P1_PLSCRAMB_ROOT2 0xf4ac0003 + +/*P1_PLROOT1*/ +#define R0900_P1_PLROOT1 0xf4ad +#define F0900_P1_PLSCRAMB_ROOT1 0xf4ad00ff + +/*P1_PLROOT0*/ +#define R0900_P1_PLROOT0 0xf4ae +#define F0900_P1_PLSCRAMB_ROOT0 0xf4ae00ff + +/*P1_MODCODLST0*/ +#define R0900_P1_MODCODLST0 0xf4b0 +#define F0900_P1_EN_TOKEN31 0xf4b00080 +#define F0900_P1_SYNCTAG_SELECT 0xf4b00040 +#define F0900_P1_MODCODRQ_MODE 0xf4b00030 + +/*P1_MODCODLST1*/ +#define R0900_P1_MODCODLST1 0xf4b1 +#define F0900_P1_DIS_MODCOD29 0xf4b100f0 +#define F0900_P1_DIS_32PSK_9_10 0xf4b1000f + +/*P1_MODCODLST2*/ +#define R0900_P1_MODCODLST2 0xf4b2 +#define F0900_P1_DIS_32PSK_8_9 0xf4b200f0 +#define F0900_P1_DIS_32PSK_5_6 0xf4b2000f + +/*P1_MODCODLST3*/ +#define R0900_P1_MODCODLST3 0xf4b3 +#define F0900_P1_DIS_32PSK_4_5 0xf4b300f0 +#define F0900_P1_DIS_32PSK_3_4 0xf4b3000f + +/*P1_MODCODLST4*/ +#define R0900_P1_MODCODLST4 0xf4b4 +#define F0900_P1_DIS_16PSK_9_10 0xf4b400f0 +#define F0900_P1_DIS_16PSK_8_9 0xf4b4000f + +/*P1_MODCODLST5*/ +#define R0900_P1_MODCODLST5 0xf4b5 +#define F0900_P1_DIS_16PSK_5_6 0xf4b500f0 +#define F0900_P1_DIS_16PSK_4_5 0xf4b5000f + +/*P1_MODCODLST6*/ +#define R0900_P1_MODCODLST6 0xf4b6 +#define F0900_P1_DIS_16PSK_3_4 0xf4b600f0 +#define F0900_P1_DIS_16PSK_2_3 0xf4b6000f + +/*P1_MODCODLST7*/ +#define R0900_P1_MODCODLST7 0xf4b7 +#define F0900_P1_DIS_8P_9_10 0xf4b700f0 +#define F0900_P1_DIS_8P_8_9 0xf4b7000f + +/*P1_MODCODLST8*/ +#define R0900_P1_MODCODLST8 0xf4b8 +#define F0900_P1_DIS_8P_5_6 0xf4b800f0 +#define F0900_P1_DIS_8P_3_4 0xf4b8000f + +/*P1_MODCODLST9*/ +#define R0900_P1_MODCODLST9 0xf4b9 +#define F0900_P1_DIS_8P_2_3 0xf4b900f0 +#define F0900_P1_DIS_8P_3_5 0xf4b9000f + +/*P1_MODCODLSTA*/ +#define R0900_P1_MODCODLSTA 0xf4ba +#define F0900_P1_DIS_QP_9_10 0xf4ba00f0 +#define F0900_P1_DIS_QP_8_9 0xf4ba000f + +/*P1_MODCODLSTB*/ +#define R0900_P1_MODCODLSTB 0xf4bb +#define F0900_P1_DIS_QP_5_6 0xf4bb00f0 +#define F0900_P1_DIS_QP_4_5 0xf4bb000f + +/*P1_MODCODLSTC*/ +#define R0900_P1_MODCODLSTC 0xf4bc +#define F0900_P1_DIS_QP_3_4 0xf4bc00f0 +#define F0900_P1_DIS_QP_2_3 0xf4bc000f + +/*P1_MODCODLSTD*/ +#define R0900_P1_MODCODLSTD 0xf4bd +#define F0900_P1_DIS_QP_3_5 0xf4bd00f0 +#define F0900_P1_DIS_QP_1_2 0xf4bd000f + +/*P1_MODCODLSTE*/ +#define R0900_P1_MODCODLSTE 0xf4be +#define F0900_P1_DIS_QP_2_5 0xf4be00f0 +#define F0900_P1_DIS_QP_1_3 0xf4be000f + +/*P1_MODCODLSTF*/ +#define R0900_P1_MODCODLSTF 0xf4bf +#define F0900_P1_DIS_QP_1_4 0xf4bf00f0 +#define F0900_P1_DDEMOD_SET 0xf4bf0002 +#define F0900_P1_DDEMOD_MASK 0xf4bf0001 + +/*P1_DMDRESCFG*/ +#define R0900_P1_DMDRESCFG 0xf4c6 +#define F0900_P1_DMDRES_RESET 0xf4c60080 +#define F0900_P1_DMDRES_NOISESQR 0xf4c60010 +#define F0900_P1_DMDRES_STRALL 0xf4c60008 +#define F0900_P1_DMDRES_NEWONLY 0xf4c60004 +#define F0900_P1_DMDRES_NOSTORE 0xf4c60002 +#define F0900_P1_DMDRES_AGC2MEM 0xf4c60001 + +/*P1_DMDRESADR*/ +#define R0900_P1_DMDRESADR 0xf4c7 +#define F0900_P1_SUSP_PREDCANAL 0xf4c70080 +#define F0900_P1_DMDRES_VALIDCFR 0xf4c70040 +#define F0900_P1_DMDRES_MEMFULL 0xf4c70030 +#define F0900_P1_DMDRES_RESNBR 0xf4c7000f + +/*P1_DMDRESDATA7*/ +#define R0900_P1_DMDRESDATA7 0xf4c8 +#define F0900_P1_DMDRES_DATA7 0xf4c800ff + +/*P1_DMDRESDATA6*/ +#define R0900_P1_DMDRESDATA6 0xf4c9 +#define F0900_P1_DMDRES_DATA6 0xf4c900ff + +/*P1_DMDRESDATA5*/ +#define R0900_P1_DMDRESDATA5 0xf4ca +#define F0900_P1_DMDRES_DATA5 0xf4ca00ff + +/*P1_DMDRESDATA4*/ +#define R0900_P1_DMDRESDATA4 0xf4cb +#define F0900_P1_DMDRES_DATA4 0xf4cb00ff + +/*P1_DMDRESDATA3*/ +#define R0900_P1_DMDRESDATA3 0xf4cc +#define F0900_P1_DMDRES_DATA3 0xf4cc00ff + +/*P1_DMDRESDATA2*/ +#define R0900_P1_DMDRESDATA2 0xf4cd +#define F0900_P1_DMDRES_DATA2 0xf4cd00ff + +/*P1_DMDRESDATA1*/ +#define R0900_P1_DMDRESDATA1 0xf4ce +#define F0900_P1_DMDRES_DATA1 0xf4ce00ff + +/*P1_DMDRESDATA0*/ +#define R0900_P1_DMDRESDATA0 0xf4cf +#define F0900_P1_DMDRES_DATA0 0xf4cf00ff + +/*P1_FFEI1*/ +#define R0900_P1_FFEI1 0xf4d0 +#define F0900_P1_FFE_ACCI1 0xf4d001ff + +/*P1_FFEQ1*/ +#define R0900_P1_FFEQ1 0xf4d1 +#define F0900_P1_FFE_ACCQ1 0xf4d101ff + +/*P1_FFEI2*/ +#define R0900_P1_FFEI2 0xf4d2 +#define F0900_P1_FFE_ACCI2 0xf4d201ff + +/*P1_FFEQ2*/ +#define R0900_P1_FFEQ2 0xf4d3 +#define F0900_P1_FFE_ACCQ2 0xf4d301ff + +/*P1_FFEI3*/ +#define R0900_P1_FFEI3 0xf4d4 +#define F0900_P1_FFE_ACCI3 0xf4d401ff + +/*P1_FFEQ3*/ +#define R0900_P1_FFEQ3 0xf4d5 +#define F0900_P1_FFE_ACCQ3 0xf4d501ff + +/*P1_FFEI4*/ +#define R0900_P1_FFEI4 0xf4d6 +#define F0900_P1_FFE_ACCI4 0xf4d601ff + +/*P1_FFEQ4*/ +#define R0900_P1_FFEQ4 0xf4d7 +#define F0900_P1_FFE_ACCQ4 0xf4d701ff + +/*P1_FFECFG*/ +#define R0900_P1_FFECFG 0xf4d8 +#define F0900_P1_EQUALFFE_ON 0xf4d80040 +#define F0900_P1_EQUAL_USEDSYMB 0xf4d80030 +#define F0900_P1_MU_EQUALFFE 0xf4d80007 + +/*P1_TNRCFG*/ +#define R0900_P1_TNRCFG 0xf4e0 +#define F0900_P1_TUN_ACKFAIL 0xf4e00080 +#define F0900_P1_TUN_TYPE 0xf4e00070 +#define F0900_P1_TUN_SECSTOP 0xf4e00008 +#define F0900_P1_TUN_VCOSRCH 0xf4e00004 +#define F0900_P1_TUN_MADDRESS 0xf4e00003 + +/*P1_TNRCFG2*/ +#define R0900_P1_TNRCFG2 0xf4e1 +#define F0900_P1_TUN_IQSWAP 0xf4e10080 +#define F0900_P1_STB6110_STEP2MHZ 0xf4e10040 +#define F0900_P1_STB6120_DBLI2C 0xf4e10020 +#define F0900_P1_DIS_FCCK 0xf4e10010 +#define F0900_P1_DIS_LPEN 0xf4e10008 +#define F0900_P1_DIS_BWCALC 0xf4e10004 +#define F0900_P1_SHORT_WAITSTATES 0xf4e10002 +#define F0900_P1_DIS_2BWAGC1 0xf4e10001 + +/*P1_TNRXTAL*/ +#define R0900_P1_TNRXTAL 0xf4e4 +#define F0900_P1_TUN_MCLKDECIMAL 0xf4e400e0 +#define F0900_P1_TUN_XTALFREQ 0xf4e4001f + +/*P1_TNRSTEPS*/ +#define R0900_P1_TNRSTEPS 0xf4e7 +#define F0900_P1_TUNER_BW1P6 0xf4e70080 +#define F0900_P1_BWINC_OFFSET 0xf4e70070 +#define F0900_P1_SOFTSTEP_RNG 0xf4e70008 +#define F0900_P1_TUN_BWOFFSET 0xf4e70107 + +/*P1_TNRGAIN*/ +#define R0900_P1_TNRGAIN 0xf4e8 +#define F0900_P1_TUN_KDIVEN 0xf4e800c0 +#define F0900_P1_STB6X00_OCK 0xf4e80030 +#define F0900_P1_TUN_GAIN 0xf4e8000f + +/*P1_TNRRF1*/ +#define R0900_P1_TNRRF1 0xf4e9 +#define F0900_P1_TUN_RFFREQ2 0xf4e900ff + +/*P1_TNRRF0*/ +#define R0900_P1_TNRRF0 0xf4ea +#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff + +/*P1_TNRBW*/ +#define R0900_P1_TNRBW 0xf4eb +#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 +#define F0900_P1_TUN_BW 0xf4eb003f + +/*P1_TNRADJ*/ +#define R0900_P1_TNRADJ 0xf4ec +#define F0900_P1_STB61X0_RCLK 0xf4ec0080 +#define F0900_P1_STB61X0_CALTIME 0xf4ec0040 +#define F0900_P1_STB6X00_DLB 0xf4ec0038 +#define F0900_P1_STB6000_FCL 0xf4ec0007 + +/*P1_TNRCTL2*/ +#define R0900_P1_TNRCTL2 0xf4ed +#define F0900_P1_STB61X0_LCP1_RCCKOFF 0xf4ed0080 +#define F0900_P1_STB61X0_LCP0 0xf4ed0040 +#define F0900_P1_STB61X0_XTOUT_RFOUTS 0xf4ed0020 +#define F0900_P1_STB61X0_XTON_MCKDV 0xf4ed0010 +#define F0900_P1_STB61X0_CALOFF_DCOFF 0xf4ed0008 +#define F0900_P1_STB6110_LPT 0xf4ed0004 +#define F0900_P1_STB6110_RX 0xf4ed0002 +#define F0900_P1_STB6110_SYN 0xf4ed0001 + +/*P1_TNRCFG3*/ +#define R0900_P1_TNRCFG3 0xf4ee +#define F0900_P1_STB6120_DISCTRL1 0xf4ee0080 +#define F0900_P1_STB6120_INVORDER 0xf4ee0040 +#define F0900_P1_STB6120_ENCTRL6 0xf4ee0020 +#define F0900_P1_TUN_PLLFREQ 0xf4ee001c +#define F0900_P1_TUN_I2CFREQ_MODE 0xf4ee0003 + +/*P1_TNRLAUNCH*/ +#define R0900_P1_TNRLAUNCH 0xf4f0 + +/*P1_TNRLD*/ +#define R0900_P1_TNRLD 0xf4f0 +#define F0900_P1_TUNLD_VCOING 0xf4f00080 +#define F0900_P1_TUN_REG1FAIL 0xf4f00040 +#define F0900_P1_TUN_REG2FAIL 0xf4f00020 +#define F0900_P1_TUN_REG3FAIL 0xf4f00010 +#define F0900_P1_TUN_REG4FAIL 0xf4f00008 +#define F0900_P1_TUN_REG5FAIL 0xf4f00004 +#define F0900_P1_TUN_BWING 0xf4f00002 +#define F0900_P1_TUN_LOCKED 0xf4f00001 + +/*P1_TNROBSL*/ +#define R0900_P1_TNROBSL 0xf4f6 +#define F0900_P1_TUN_I2CABORTED 0xf4f60080 +#define F0900_P1_TUN_LPEN 0xf4f60040 +#define F0900_P1_TUN_FCCK 0xf4f60020 +#define F0900_P1_TUN_I2CLOCKED 0xf4f60010 +#define F0900_P1_TUN_PROGDONE 0xf4f6000c +#define F0900_P1_TUN_RFRESTE1 0xf4f60003 + +/*P1_TNRRESTE*/ +#define R0900_P1_TNRRESTE 0xf4f7 +#define F0900_P1_TUN_RFRESTE0 0xf4f700ff + +/*P1_SMAPCOEF7*/ +#define R0900_P1_SMAPCOEF7 0xf500 +#define F0900_P1_DIS_QSCALE 0xf5000080 +#define F0900_P1_SMAPCOEF_Q_LLR12 0xf500017f + +/*P1_SMAPCOEF6*/ +#define R0900_P1_SMAPCOEF6 0xf501 +#define F0900_P1_DIS_NEWSCALE 0xf5010008 +#define F0900_P1_ADJ_8PSKLLR1 0xf5010004 +#define F0900_P1_OLD_8PSKLLR1 0xf5010002 +#define F0900_P1_DIS_AB8PSK 0xf5010001 + +/*P1_SMAPCOEF5*/ +#define R0900_P1_SMAPCOEF5 0xf502 +#define F0900_P1_DIS_8SCALE 0xf5020080 +#define F0900_P1_SMAPCOEF_8P_LLR23 0xf502017f + +/*P1_DMDPLHSTAT*/ +#define R0900_P1_DMDPLHSTAT 0xf520 +#define F0900_P1_PLH_STATISTIC 0xf52000ff + +/*P1_LOCKTIME3*/ +#define R0900_P1_LOCKTIME3 0xf522 +#define F0900_P1_DEMOD_LOCKTIME3 0xf52200ff + +/*P1_LOCKTIME2*/ +#define R0900_P1_LOCKTIME2 0xf523 +#define F0900_P1_DEMOD_LOCKTIME2 0xf52300ff + +/*P1_LOCKTIME1*/ +#define R0900_P1_LOCKTIME1 0xf524 +#define F0900_P1_DEMOD_LOCKTIME1 0xf52400ff + +/*P1_LOCKTIME0*/ +#define R0900_P1_LOCKTIME0 0xf525 +#define F0900_P1_DEMOD_LOCKTIME0 0xf52500ff + +/*P1_VITSCALE*/ +#define R0900_P1_VITSCALE 0xf532 +#define F0900_P1_NVTH_NOSRANGE 0xf5320080 +#define F0900_P1_VERROR_MAXMODE 0xf5320040 +#define F0900_P1_KDIV_MODE 0xf5320030 +#define F0900_P1_NSLOWSN_LOCKED 0xf5320008 +#define F0900_P1_DELOCK_PRFLOSS 0xf5320004 +#define F0900_P1_DIS_RSFLOCK 0xf5320002 + +/*P1_FECM*/ +#define R0900_P1_FECM 0xf533 +#define F0900_P1_DSS_DVB 0xf5330080 +#define F0900_P1_DEMOD_BYPASS 0xf5330040 +#define F0900_P1_CMP_SLOWMODE 0xf5330020 +#define F0900_P1_DSS_SRCH 0xf5330010 +#define F0900_P1_DIFF_MODEVIT 0xf5330004 +#define F0900_P1_SYNCVIT 0xf5330002 +#define F0900_P1_IQINV 0xf5330001 + +/*P1_VTH12*/ +#define R0900_P1_VTH12 0xf534 +#define F0900_P1_VTH12 0xf53400ff + +/*P1_VTH23*/ +#define R0900_P1_VTH23 0xf535 +#define F0900_P1_VTH23 0xf53500ff + +/*P1_VTH34*/ +#define R0900_P1_VTH34 0xf536 +#define F0900_P1_VTH34 0xf53600ff + +/*P1_VTH56*/ +#define R0900_P1_VTH56 0xf537 +#define F0900_P1_VTH56 0xf53700ff + +/*P1_VTH67*/ +#define R0900_P1_VTH67 0xf538 +#define F0900_P1_VTH67 0xf53800ff + +/*P1_VTH78*/ +#define R0900_P1_VTH78 0xf539 +#define F0900_P1_VTH78 0xf53900ff + +/*P1_VITCURPUN*/ +#define R0900_P1_VITCURPUN 0xf53a +#define F0900_P1_VIT_MAPPING 0xf53a00e0 +#define F0900_P1_VIT_CURPUN 0xf53a001f + +/*P1_VERROR*/ +#define R0900_P1_VERROR 0xf53b +#define F0900_P1_REGERR_VIT 0xf53b00ff + +/*P1_PRVIT*/ +#define R0900_P1_PRVIT 0xf53c +#define F0900_P1_DIS_VTHLOCK 0xf53c0040 +#define F0900_P1_E7_8VIT 0xf53c0020 +#define F0900_P1_E6_7VIT 0xf53c0010 +#define F0900_P1_E5_6VIT 0xf53c0008 +#define F0900_P1_E3_4VIT 0xf53c0004 +#define F0900_P1_E2_3VIT 0xf53c0002 +#define F0900_P1_E1_2VIT 0xf53c0001 + +/*P1_VAVSRVIT*/ +#define R0900_P1_VAVSRVIT 0xf53d +#define F0900_P1_AMVIT 0xf53d0080 +#define F0900_P1_FROZENVIT 0xf53d0040 +#define F0900_P1_SNVIT 0xf53d0030 +#define F0900_P1_TOVVIT 0xf53d000c +#define F0900_P1_HYPVIT 0xf53d0003 + +/*P1_VSTATUSVIT*/ +#define R0900_P1_VSTATUSVIT 0xf53e +#define F0900_P1_VITERBI_ON 0xf53e0080 +#define F0900_P1_END_LOOPVIT 0xf53e0040 +#define F0900_P1_VITERBI_DEPRF 0xf53e0020 +#define F0900_P1_PRFVIT 0xf53e0010 +#define F0900_P1_LOCKEDVIT 0xf53e0008 +#define F0900_P1_VITERBI_DELOCK 0xf53e0004 +#define F0900_P1_VIT_DEMODSEL 0xf53e0002 +#define F0900_P1_VITERBI_COMPOUT 0xf53e0001 + +/*P1_VTHINUSE*/ +#define R0900_P1_VTHINUSE 0xf53f +#define F0900_P1_VIT_INUSE 0xf53f00ff + +/*P1_KDIV12*/ +#define R0900_P1_KDIV12 0xf540 +#define F0900_P1_KDIV12_MANUAL 0xf5400080 +#define F0900_P1_K_DIVIDER_12 0xf540007f + +/*P1_KDIV23*/ +#define R0900_P1_KDIV23 0xf541 +#define F0900_P1_KDIV23_MANUAL 0xf5410080 +#define F0900_P1_K_DIVIDER_23 0xf541007f + +/*P1_KDIV34*/ +#define R0900_P1_KDIV34 0xf542 +#define F0900_P1_KDIV34_MANUAL 0xf5420080 +#define F0900_P1_K_DIVIDER_34 0xf542007f + +/*P1_KDIV56*/ +#define R0900_P1_KDIV56 0xf543 +#define F0900_P1_KDIV56_MANUAL 0xf5430080 +#define F0900_P1_K_DIVIDER_56 0xf543007f + +/*P1_KDIV67*/ +#define R0900_P1_KDIV67 0xf544 +#define F0900_P1_KDIV67_MANUAL 0xf5440080 +#define F0900_P1_K_DIVIDER_67 0xf544007f + +/*P1_KDIV78*/ +#define R0900_P1_KDIV78 0xf545 +#define F0900_P1_KDIV78_MANUAL 0xf5450080 +#define F0900_P1_K_DIVIDER_78 0xf545007f + +/*P1_PDELCTRL1*/ +#define R0900_P1_PDELCTRL1 0xf550 +#define F0900_P1_INV_MISMASK 0xf5500080 +#define F0900_P1_FORCE_ACCEPTED 0xf5500040 +#define F0900_P1_FILTER_EN 0xf5500020 +#define F0900_P1_FORCE_PKTDELINUSE 0xf5500010 +#define F0900_P1_HYSTEN 0xf5500008 +#define F0900_P1_HYSTSWRST 0xf5500004 +#define F0900_P1_EN_MIS00 0xf5500002 +#define F0900_P1_ALGOSWRST 0xf5500001 + +/*P1_PDELCTRL2*/ +#define R0900_P1_PDELCTRL2 0xf551 +#define F0900_P1_FORCE_CONTINUOUS 0xf5510080 +#define F0900_P1_RESET_UPKO_COUNT 0xf5510040 +#define F0900_P1_USER_PKTDELIN_NB 0xf5510020 +#define F0900_P1_FORCE_LOCKED 0xf5510010 +#define F0900_P1_DATA_UNBBSCRAM 0xf5510008 +#define F0900_P1_FORCE_LONGPKT 0xf5510004 +#define F0900_P1_FRAME_MODE 0xf5510002 + +/*P1_HYSTTHRESH*/ +#define R0900_P1_HYSTTHRESH 0xf554 +#define F0900_P1_UNLCK_THRESH 0xf55400f0 +#define F0900_P1_DELIN_LCK_THRESH 0xf554000f + +/*P1_ISIENTRY*/ +#define R0900_P1_ISIENTRY 0xf55e +#define F0900_P1_ISI_ENTRY 0xf55e00ff + +/*P1_ISIBITENA*/ +#define R0900_P1_ISIBITENA 0xf55f +#define F0900_P1_ISI_BIT_EN 0xf55f00ff + +/*P1_MATSTR1*/ +#define R0900_P1_MATSTR1 0xf560 +#define F0900_P1_MATYPE_CURRENT1 0xf56000ff + +/*P1_MATSTR0*/ +#define R0900_P1_MATSTR0 0xf561 +#define F0900_P1_MATYPE_CURRENT0 0xf56100ff + +/*P1_UPLSTR1*/ +#define R0900_P1_UPLSTR1 0xf562 +#define F0900_P1_UPL_CURRENT1 0xf56200ff + +/*P1_UPLSTR0*/ +#define R0900_P1_UPLSTR0 0xf563 +#define F0900_P1_UPL_CURRENT0 0xf56300ff + +/*P1_DFLSTR1*/ +#define R0900_P1_DFLSTR1 0xf564 +#define F0900_P1_DFL_CURRENT1 0xf56400ff + +/*P1_DFLSTR0*/ +#define R0900_P1_DFLSTR0 0xf565 +#define F0900_P1_DFL_CURRENT0 0xf56500ff + +/*P1_SYNCSTR*/ +#define R0900_P1_SYNCSTR 0xf566 +#define F0900_P1_SYNC_CURRENT 0xf56600ff + +/*P1_SYNCDSTR1*/ +#define R0900_P1_SYNCDSTR1 0xf567 +#define F0900_P1_SYNCD_CURRENT1 0xf56700ff + +/*P1_SYNCDSTR0*/ +#define R0900_P1_SYNCDSTR0 0xf568 +#define F0900_P1_SYNCD_CURRENT0 0xf56800ff + +/*P1_PDELSTATUS1*/ +#define R0900_P1_PDELSTATUS1 0xf569 +#define F0900_P1_PKTDELIN_DELOCK 0xf5690080 +#define F0900_P1_SYNCDUPDFL_BADDFL 0xf5690040 +#define F0900_P1_CONTINUOUS_STREAM 0xf5690020 +#define F0900_P1_UNACCEPTED_STREAM 0xf5690010 +#define F0900_P1_BCH_ERROR_FLAG 0xf5690008 +#define F0900_P1_BBHCRCKO 0xf5690004 +#define F0900_P1_PKTDELIN_LOCK 0xf5690002 +#define F0900_P1_FIRST_LOCK 0xf5690001 + +/*P1_PDELSTATUS2*/ +#define R0900_P1_PDELSTATUS2 0xf56a +#define F0900_P1_PKTDEL_DEMODSEL 0xf56a0080 +#define F0900_P1_FRAME_MODCOD 0xf56a007c +#define F0900_P1_FRAME_TYPE 0xf56a0003 + +/*P1_BBFCRCKO1*/ +#define R0900_P1_BBFCRCKO1 0xf56b +#define F0900_P1_BBHCRC_KOCNT1 0xf56b00ff + +/*P1_BBFCRCKO0*/ +#define R0900_P1_BBFCRCKO0 0xf56c +#define F0900_P1_BBHCRC_KOCNT0 0xf56c00ff + +/*P1_UPCRCKO1*/ +#define R0900_P1_UPCRCKO1 0xf56d +#define F0900_P1_PKTCRC_KOCNT1 0xf56d00ff + +/*P1_UPCRCKO0*/ +#define R0900_P1_UPCRCKO0 0xf56e +#define F0900_P1_PKTCRC_KOCNT0 0xf56e00ff + +/*P1_TSSTATEM*/ +#define R0900_P1_TSSTATEM 0xf570 +#define F0900_P1_TSDIL_ON 0xf5700080 +#define F0900_P1_TSSKIPRS_ON 0xf5700040 +#define F0900_P1_TSRS_ON 0xf5700020 +#define F0900_P1_TSDESCRAMB_ON 0xf5700010 +#define F0900_P1_TSFRAME_MODE 0xf5700008 +#define F0900_P1_TS_DISABLE 0xf5700004 +#define F0900_P1_TSACM_MODE 0xf5700002 +#define F0900_P1_TSOUT_NOSYNC 0xf5700001 + +/*P1_TSCFGH*/ +#define R0900_P1_TSCFGH 0xf572 +#define F0900_P1_TSFIFO_DVBCI 0xf5720080 +#define F0900_P1_TSFIFO_SERIAL 0xf5720040 +#define F0900_P1_TSFIFO_TEIUPDATE 0xf5720020 +#define F0900_P1_TSFIFO_DUTY50 0xf5720010 +#define F0900_P1_TSFIFO_HSGNLOUT 0xf5720008 +#define F0900_P1_TSFIFO_ERRMODE 0xf5720006 +#define F0900_P1_RST_HWARE 0xf5720001 + +/*P1_TSCFGM*/ +#define R0900_P1_TSCFGM 0xf573 +#define F0900_P1_TSFIFO_MANSPEED 0xf57300c0 +#define F0900_P1_TSFIFO_PERMDATA 0xf5730020 +#define F0900_P1_TSFIFO_NONEWSGNL 0xf5730010 +#define F0900_P1_TSFIFO_BITSPEED 0xf5730008 +#define F0900_P1_NPD_SPECDVBS2 0xf5730004 +#define F0900_P1_TSFIFO_STOPCKDIS 0xf5730002 +#define F0900_P1_TSFIFO_INVDATA 0xf5730001 + +/*P1_TSCFGL*/ +#define R0900_P1_TSCFGL 0xf574 +#define F0900_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 +#define F0900_P1_BCHERROR_MODE 0xf5740030 +#define F0900_P1_TSFIFO_NSGNL2DATA 0xf5740008 +#define F0900_P1_TSFIFO_EMBINDVB 0xf5740004 +#define F0900_P1_TSFIFO_DPUNACT 0xf5740002 +#define F0900_P1_TSFIFO_NPDOFF 0xf5740001 + +/*P1_TSINSDELH*/ +#define R0900_P1_TSINSDELH 0xf576 +#define F0900_P1_TSDEL_SYNCBYTE 0xf5760080 +#define F0900_P1_TSDEL_XXHEADER 0xf5760040 +#define F0900_P1_TSDEL_BBHEADER 0xf5760020 +#define F0900_P1_TSDEL_DATAFIELD 0xf5760010 +#define F0900_P1_TSINSDEL_ISCR 0xf5760008 +#define F0900_P1_TSINSDEL_NPD 0xf5760004 +#define F0900_P1_TSINSDEL_RSPARITY 0xf5760002 +#define F0900_P1_TSINSDEL_CRC8 0xf5760001 + +/*P1_TSSPEED*/ +#define R0900_P1_TSSPEED 0xf580 +#define F0900_P1_TSFIFO_OUTSPEED 0xf58000ff + +/*P1_TSSTATUS*/ +#define R0900_P1_TSSTATUS 0xf581 +#define F0900_P1_TSFIFO_LINEOK 0xf5810080 +#define F0900_P1_TSFIFO_ERROR 0xf5810040 +#define F0900_P1_TSFIFO_DATA7 0xf5810020 +#define F0900_P1_TSFIFO_NOSYNC 0xf5810010 +#define F0900_P1_ISCR_INITIALIZED 0xf5810008 +#define F0900_P1_ISCR_UPDATED 0xf5810004 +#define F0900_P1_SOFFIFO_UNREGUL 0xf5810002 +#define F0900_P1_DIL_READY 0xf5810001 + +/*P1_TSSTATUS2*/ +#define R0900_P1_TSSTATUS2 0xf582 +#define F0900_P1_TSFIFO_DEMODSEL 0xf5820080 +#define F0900_P1_TSFIFOSPEED_STORE 0xf5820040 +#define F0900_P1_DILXX_RESET 0xf5820020 +#define F0900_P1_TSSERIAL_IMPOS 0xf5820010 +#define F0900_P1_TSFIFO_LINENOK 0xf5820008 +#define F0900_P1_BITSPEED_EVENT 0xf5820004 +#define F0900_P1_SCRAMBDETECT 0xf5820002 +#define F0900_P1_ULDTV67_FALSELOCK 0xf5820001 + +/*P1_TSBITRATE1*/ +#define R0900_P1_TSBITRATE1 0xf583 +#define F0900_P1_TSFIFO_BITRATE1 0xf58300ff + +/*P1_TSBITRATE0*/ +#define R0900_P1_TSBITRATE0 0xf584 +#define F0900_P1_TSFIFO_BITRATE0 0xf58400ff + +/*P1_ERRCTRL1*/ +#define R0900_P1_ERRCTRL1 0xf598 +#define F0900_P1_ERR_SOURCE1 0xf59800f0 +#define F0900_P1_NUM_EVENT1 0xf5980007 + +/*P1_ERRCNT12*/ +#define R0900_P1_ERRCNT12 0xf599 +#define F0900_P1_ERRCNT1_OLDVALUE 0xf5990080 +#define F0900_P1_ERR_CNT12 0xf599007f + +/*P1_ERRCNT11*/ +#define R0900_P1_ERRCNT11 0xf59a +#define F0900_P1_ERR_CNT11 0xf59a00ff + +/*P1_ERRCNT10*/ +#define R0900_P1_ERRCNT10 0xf59b +#define F0900_P1_ERR_CNT10 0xf59b00ff + +/*P1_ERRCTRL2*/ +#define R0900_P1_ERRCTRL2 0xf59c +#define F0900_P1_ERR_SOURCE2 0xf59c00f0 +#define F0900_P1_NUM_EVENT2 0xf59c0007 + +/*P1_ERRCNT22*/ +#define R0900_P1_ERRCNT22 0xf59d +#define F0900_P1_ERRCNT2_OLDVALUE 0xf59d0080 +#define F0900_P1_ERR_CNT22 0xf59d007f + +/*P1_ERRCNT21*/ +#define R0900_P1_ERRCNT21 0xf59e +#define F0900_P1_ERR_CNT21 0xf59e00ff + +/*P1_ERRCNT20*/ +#define R0900_P1_ERRCNT20 0xf59f +#define F0900_P1_ERR_CNT20 0xf59f00ff + +/*P1_FECSPY*/ +#define R0900_P1_FECSPY 0xf5a0 +#define F0900_P1_SPY_ENABLE 0xf5a00080 +#define F0900_P1_NO_SYNCBYTE 0xf5a00040 +#define F0900_P1_SERIAL_MODE 0xf5a00020 +#define F0900_P1_UNUSUAL_PACKET 0xf5a00010 +#define F0900_P1_BER_PACKMODE 0xf5a00008 +#define F0900_P1_BERMETER_LMODE 0xf5a00002 +#define F0900_P1_BERMETER_RESET 0xf5a00001 + +/*P1_FSPYCFG*/ +#define R0900_P1_FSPYCFG 0xf5a1 +#define F0900_P1_FECSPY_INPUT 0xf5a100c0 +#define F0900_P1_RST_ON_ERROR 0xf5a10020 +#define F0900_P1_ONE_SHOT 0xf5a10010 +#define F0900_P1_I2C_MODE 0xf5a1000c +#define F0900_P1_SPY_HYSTERESIS 0xf5a10003 + +/*P1_FSPYDATA*/ +#define R0900_P1_FSPYDATA 0xf5a2 +#define F0900_P1_SPY_STUFFING 0xf5a20080 +#define F0900_P1_NOERROR_PKTJITTER 0xf5a20040 +#define F0900_P1_SPY_CNULLPKT 0xf5a20020 +#define F0900_P1_SPY_OUTDATA_MODE 0xf5a2001f + +/*P1_FSPYOUT*/ +#define R0900_P1_FSPYOUT 0xf5a3 +#define F0900_P1_FSPY_DIRECT 0xf5a30080 +#define F0900_P1_SPY_OUTDATA_BUS 0xf5a30038 +#define F0900_P1_STUFF_MODE 0xf5a30007 + +/*P1_FSTATUS*/ +#define R0900_P1_FSTATUS 0xf5a4 +#define F0900_P1_SPY_ENDSIM 0xf5a40080 +#define F0900_P1_VALID_SIM 0xf5a40040 +#define F0900_P1_FOUND_SIGNAL 0xf5a40020 +#define F0900_P1_DSS_SYNCBYTE 0xf5a40010 +#define F0900_P1_RESULT_STATE 0xf5a4000f + +/*P1_FBERCPT4*/ +#define R0900_P1_FBERCPT4 0xf5a8 +#define F0900_P1_FBERMETER_CPT4 0xf5a800ff + +/*P1_FBERCPT3*/ +#define R0900_P1_FBERCPT3 0xf5a9 +#define F0900_P1_FBERMETER_CPT3 0xf5a900ff + +/*P1_FBERCPT2*/ +#define R0900_P1_FBERCPT2 0xf5aa +#define F0900_P1_FBERMETER_CPT2 0xf5aa00ff + +/*P1_FBERCPT1*/ +#define R0900_P1_FBERCPT1 0xf5ab +#define F0900_P1_FBERMETER_CPT1 0xf5ab00ff + +/*P1_FBERCPT0*/ +#define R0900_P1_FBERCPT0 0xf5ac +#define F0900_P1_FBERMETER_CPT0 0xf5ac00ff + +/*P1_FBERERR2*/ +#define R0900_P1_FBERERR2 0xf5ad +#define F0900_P1_FBERMETER_ERR2 0xf5ad00ff + +/*P1_FBERERR1*/ +#define R0900_P1_FBERERR1 0xf5ae +#define F0900_P1_FBERMETER_ERR1 0xf5ae00ff + +/*P1_FBERERR0*/ +#define R0900_P1_FBERERR0 0xf5af +#define F0900_P1_FBERMETER_ERR0 0xf5af00ff + +/*P1_FSPYBER*/ +#define R0900_P1_FSPYBER 0xf5b2 +#define F0900_P1_FSPYOBS_XORREAD 0xf5b20040 +#define F0900_P1_FSPYBER_OBSMODE 0xf5b20020 +#define F0900_P1_FSPYBER_SYNCBYTE 0xf5b20010 +#define F0900_P1_FSPYBER_UNSYNC 0xf5b20008 +#define F0900_P1_FSPYBER_CTIME 0xf5b20007 + +/*RCCFGH*/ +#define R0900_RCCFGH 0xf600 +#define F0900_TSRCFIFO_DVBCI 0xf6000080 +#define F0900_TSRCFIFO_SERIAL 0xf6000040 +#define F0900_TSRCFIFO_DISABLE 0xf6000020 +#define F0900_TSFIFO_2TORC 0xf6000010 +#define F0900_TSRCFIFO_HSGNLOUT 0xf6000008 +#define F0900_TSRCFIFO_ERRMODE 0xf6000006 + +/*TSGENERAL*/ +#define R0900_TSGENERAL 0xf630 +#define F0900_TSFIFO_BCLK1ALL 0xf6300020 +#define F0900_MUXSTREAM_OUTMODE 0xf6300008 +#define F0900_TSFIFO_PERMPARAL 0xf6300006 +#define F0900_RST_REEDSOLO 0xf6300001 + +/*TSGENERAL1X*/ +#define R0900_TSGENERAL1X 0xf670 +#define F0900_TSFIFO1X_BCLK1ALL 0xf6700020 +#define F0900_MUXSTREAM1X_OUTMODE 0xf6700008 +#define F0900_TSFIFO1X_PERMPARAL 0xf6700006 +#define F0900_RST1X_REEDSOLO 0xf6700001 + +/*NBITER_NF4*/ +#define R0900_NBITER_NF4 0xfa03 +#define F0900_NBITER_NF_QP_1_2 0xfa0300ff + +/*NBITER_NF5*/ +#define R0900_NBITER_NF5 0xfa04 +#define F0900_NBITER_NF_QP_3_5 0xfa0400ff + +/*NBITER_NF6*/ +#define R0900_NBITER_NF6 0xfa05 +#define F0900_NBITER_NF_QP_2_3 0xfa0500ff + +/*NBITER_NF7*/ +#define R0900_NBITER_NF7 0xfa06 +#define F0900_NBITER_NF_QP_3_4 0xfa0600ff + +/*NBITER_NF8*/ +#define R0900_NBITER_NF8 0xfa07 +#define F0900_NBITER_NF_QP_4_5 0xfa0700ff + +/*NBITER_NF9*/ +#define R0900_NBITER_NF9 0xfa08 +#define F0900_NBITER_NF_QP_5_6 0xfa0800ff + +/*NBITER_NF10*/ +#define R0900_NBITER_NF10 0xfa09 +#define F0900_NBITER_NF_QP_8_9 0xfa0900ff + +/*NBITER_NF11*/ +#define R0900_NBITER_NF11 0xfa0a +#define F0900_NBITER_NF_QP_9_10 0xfa0a00ff + +/*NBITER_NF12*/ +#define R0900_NBITER_NF12 0xfa0b +#define F0900_NBITER_NF_8P_3_5 0xfa0b00ff + +/*NBITER_NF13*/ +#define R0900_NBITER_NF13 0xfa0c +#define F0900_NBITER_NF_8P_2_3 0xfa0c00ff + +/*NBITER_NF14*/ +#define R0900_NBITER_NF14 0xfa0d +#define F0900_NBITER_NF_8P_3_4 0xfa0d00ff + +/*NBITER_NF15*/ +#define R0900_NBITER_NF15 0xfa0e +#define F0900_NBITER_NF_8P_5_6 0xfa0e00ff + +/*NBITER_NF16*/ +#define R0900_NBITER_NF16 0xfa0f +#define F0900_NBITER_NF_8P_8_9 0xfa0f00ff + +/*NBITER_NF17*/ +#define R0900_NBITER_NF17 0xfa10 +#define F0900_NBITER_NF_8P_9_10 0xfa1000ff + +/*NBITERNOERR*/ +#define R0900_NBITERNOERR 0xfa3f +#define F0900_NBITER_STOP_CRIT 0xfa3f000f + +/*GAINLLR_NF4*/ +#define R0900_GAINLLR_NF4 0xfa43 +#define F0900_GAINLLR_NF_QP_1_2 0xfa43007f + +/*GAINLLR_NF5*/ +#define R0900_GAINLLR_NF5 0xfa44 +#define F0900_GAINLLR_NF_QP_3_5 0xfa44007f + +/*GAINLLR_NF6*/ +#define R0900_GAINLLR_NF6 0xfa45 +#define F0900_GAINLLR_NF_QP_2_3 0xfa45007f + +/*GAINLLR_NF7*/ +#define R0900_GAINLLR_NF7 0xfa46 +#define F0900_GAINLLR_NF_QP_3_4 0xfa46007f + +/*GAINLLR_NF8*/ +#define R0900_GAINLLR_NF8 0xfa47 +#define F0900_GAINLLR_NF_QP_4_5 0xfa47007f + +/*GAINLLR_NF9*/ +#define R0900_GAINLLR_NF9 0xfa48 +#define F0900_GAINLLR_NF_QP_5_6 0xfa48007f + +/*GAINLLR_NF10*/ +#define R0900_GAINLLR_NF10 0xfa49 +#define F0900_GAINLLR_NF_QP_8_9 0xfa49007f + +/*GAINLLR_NF11*/ +#define R0900_GAINLLR_NF11 0xfa4a +#define F0900_GAINLLR_NF_QP_9_10 0xfa4a007f + +/*GAINLLR_NF12*/ +#define R0900_GAINLLR_NF12 0xfa4b +#define F0900_GAINLLR_NF_8P_3_5 0xfa4b007f + +/*GAINLLR_NF13*/ +#define R0900_GAINLLR_NF13 0xfa4c +#define F0900_GAINLLR_NF_8P_2_3 0xfa4c007f + +/*GAINLLR_NF14*/ +#define R0900_GAINLLR_NF14 0xfa4d +#define F0900_GAINLLR_NF_8P_3_4 0xfa4d007f + +/*GAINLLR_NF15*/ +#define R0900_GAINLLR_NF15 0xfa4e +#define F0900_GAINLLR_NF_8P_5_6 0xfa4e007f + +/*GAINLLR_NF16*/ +#define R0900_GAINLLR_NF16 0xfa4f +#define F0900_GAINLLR_NF_8P_8_9 0xfa4f007f + +/*GAINLLR_NF17*/ +#define R0900_GAINLLR_NF17 0xfa50 +#define F0900_GAINLLR_NF_8P_9_10 0xfa50007f + +/*CFGEXT*/ +#define R0900_CFGEXT 0xfa80 +#define F0900_STAGMODE 0xfa800080 +#define F0900_BYPBCH 0xfa800040 +#define F0900_BYPLDPC 0xfa800020 +#define F0900_LDPCMODE 0xfa800010 +#define F0900_INVLLRSIGN 0xfa800008 +#define F0900_SHORTMULT 0xfa800004 +#define F0900_EXTERNTX 0xfa800001 + +/*GENCFG*/ +#define R0900_GENCFG 0xfa86 +#define F0900_BROADCAST 0xfa860010 +#define F0900_NOSHFRD2 0xfa860008 +#define F0900_BCHERRFLAG 0xfa860004 +#define F0900_PRIORITY 0xfa860002 +#define F0900_DDEMOD 0xfa860001 + +/*LDPCERR1*/ +#define R0900_LDPCERR1 0xfa96 +#define F0900_LDPC_ERRORS_COUNTER1 0xfa9600ff + +/*LDPCERR0*/ +#define R0900_LDPCERR0 0xfa97 +#define F0900_LDPC_ERRORS_COUNTER0 0xfa9700ff + +/*BCHERR*/ +#define R0900_BCHERR 0xfa98 +#define F0900_ERRORFLAG 0xfa980010 +#define F0900_BCH_ERRORS_COUNTER 0xfa98000f + +/*TSTRES0*/ +#define R0900_TSTRES0 0xff11 +#define F0900_FRESFEC 0xff110080 +#define F0900_FRESTS 0xff110040 +#define F0900_FRESVIT1 0xff110020 +#define F0900_FRESVIT2 0xff110010 +#define F0900_FRESSYM1 0xff110008 +#define F0900_FRESSYM2 0xff110004 +#define F0900_FRESMAS 0xff110002 +#define F0900_FRESINT 0xff110001 + +/*P2_TSTDISRX*/ +#define R0900_P2_TSTDISRX 0xff65 +#define F0900_P2_EN_DISRX 0xff650080 +#define F0900_P2_TST_CURRSRC 0xff650040 +#define F0900_P2_IN_DIGSIGNAL 0xff650020 +#define F0900_P2_HIZ_CURRENTSRC 0xff650010 +#define F0900_TST_P2_PIN_SELECT 0xff650008 +#define F0900_P2_TST_DISRX 0xff650007 + +/*P1_TSTDISRX*/ +#define R0900_P1_TSTDISRX 0xff67 +#define F0900_P1_EN_DISRX 0xff670080 +#define F0900_P1_TST_CURRSRC 0xff670040 +#define F0900_P1_IN_DIGSIGNAL 0xff670020 +#define F0900_P1_HIZ_CURRENTSRC 0xff670010 +#define F0900_TST_P1_PIN_SELECT 0xff670008 +#define F0900_P1_TST_DISRX 0xff670007 + +#define STV0900_NBREGS 684 +#define STV0900_NBFIELDS 1702 + +#endif + -- cgit v1.2.3 From 4302d8c9c1a57ff34416e9ac9402a25c74ef9b24 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:41:39 +0200 Subject: Add more headers for ST STV0900 dual demodulator. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900_init.h | 439 +++++++++++++++++++++++ linux/drivers/media/dvb/frontends/stv0900_priv.h | 430 ++++++++++++++++++++++ 2 files changed, 869 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/stv0900_init.h create mode 100644 linux/drivers/media/dvb/frontends/stv0900_priv.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_init.h b/linux/drivers/media/dvb/frontends/stv0900_init.h new file mode 100644 index 000000000..fa8dbe197 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv0900_init.h @@ -0,0 +1,439 @@ +/* + * stv0900_init.h + * + * Driver for ST STV0900 satellite demodulator IC. + * + * Copyright (C) ST Microelectronics. + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef STV0900_INIT_H +#define STV0900_INIT_H + +#include "stv0900_priv.h" + +/* DVBS2 C/N Look-Up table */ +static const struct stv0900_table stv0900_s2_cn = { + 55, + { + { -30, 13348 }, /*C/N=-3dB*/ + { -20, 12640 }, /*C/N=-2dB*/ + { -10, 11883 }, /*C/N=-1dB*/ + { 0, 11101 }, /*C/N=-0dB*/ + { 5, 10718 }, /*C/N=0.5dB*/ + { 10, 10339 }, /*C/N=1.0dB*/ + { 15, 9947 }, /*C/N=1.5dB*/ + { 20, 9552 }, /*C/N=2.0dB*/ + { 25, 9183 }, /*C/N=2.5dB*/ + { 30, 8799 }, /*C/N=3.0dB*/ + { 35, 8422 }, /*C/N=3.5dB*/ + { 40, 8062 }, /*C/N=4.0dB*/ + { 45, 7707 }, /*C/N=4.5dB*/ + { 50, 7353 }, /*C/N=5.0dB*/ + { 55, 7025 }, /*C/N=5.5dB*/ + { 60, 6684 }, /*C/N=6.0dB*/ + { 65, 6331 }, /*C/N=6.5dB*/ + { 70, 6036 }, /*C/N=7.0dB*/ + { 75, 5727 }, /*C/N=7.5dB*/ + { 80, 5437 }, /*C/N=8.0dB*/ + { 85, 5164 }, /*C/N=8.5dB*/ + { 90, 4902 }, /*C/N=9.0dB*/ + { 95, 4653 }, /*C/N=9.5dB*/ + { 100, 4408 }, /*C/N=10.0dB*/ + { 105, 4187 }, /*C/N=10.5dB*/ + { 110, 3961 }, /*C/N=11.0dB*/ + { 115, 3751 }, /*C/N=11.5dB*/ + { 120, 3558 }, /*C/N=12.0dB*/ + { 125, 3368 }, /*C/N=12.5dB*/ + { 130, 3191 }, /*C/N=13.0dB*/ + { 135, 3017 }, /*C/N=13.5dB*/ + { 140, 2862 }, /*C/N=14.0dB*/ + { 145, 2710 }, /*C/N=14.5dB*/ + { 150, 2565 }, /*C/N=15.0dB*/ + { 160, 2300 }, /*C/N=16.0dB*/ + { 170, 2058 }, /*C/N=17.0dB*/ + { 180, 1849 }, /*C/N=18.0dB*/ + { 190, 1663 }, /*C/N=19.0dB*/ + { 200, 1495 }, /*C/N=20.0dB*/ + { 210, 1349 }, /*C/N=21.0dB*/ + { 220, 1222 }, /*C/N=22.0dB*/ + { 230, 1110 }, /*C/N=23.0dB*/ + { 240, 1011 }, /*C/N=24.0dB*/ + { 250, 925 }, /*C/N=25.0dB*/ + { 260, 853 }, /*C/N=26.0dB*/ + { 270, 789 }, /*C/N=27.0dB*/ + { 280, 734 }, /*C/N=28.0dB*/ + { 290, 690 }, /*C/N=29.0dB*/ + { 300, 650 }, /*C/N=30.0dB*/ + { 310, 619 }, /*C/N=31.0dB*/ + { 320, 593 }, /*C/N=32.0dB*/ + { 330, 571 }, /*C/N=33.0dB*/ + { 400, 498 }, /*C/N=40.0dB*/ + { 450, 484 }, /*C/N=45.0dB*/ + { 500, 481 } /*C/N=50.0dB*/ + } +}; + +/* RF level C/N Look-Up table */ +static const struct stv0900_table stv0900_rf = { + 14, + { + { -5, 0xCAA1 }, /*-5dBm*/ + { -10, 0xC229 }, /*-10dBm*/ + { -15, 0xBB08 }, /*-15dBm*/ + { -20, 0xB4BC }, /*-20dBm*/ + { -25, 0xAD5A }, /*-25dBm*/ + { -30, 0xA298 }, /*-30dBm*/ + { -35, 0x98A8 }, /*-35dBm*/ + { -40, 0x8389 }, /*-40dBm*/ + { -45, 0x59BE }, /*-45dBm*/ + { -50, 0x3A14 }, /*-50dBm*/ + { -55, 0x2D11 }, /*-55dBm*/ + { -60, 0x210D }, /*-60dBm*/ + { -65, 0xA14F }, /*-65dBm*/ + { -70, 0x7AA } /*-70dBm*/ + } +}; + +struct stv0900_car_loop_optim { + enum fe_stv0900_modcode modcode; + u8 car_loop_pilots_on_2; + u8 car_loop_pilots_off_2; + u8 car_loop_pilots_on_5; + u8 car_loop_pilots_off_5; + u8 car_loop_pilots_on_10; + u8 car_loop_pilots_off_10; + u8 car_loop_pilots_on_20; + u8 car_loop_pilots_off_20; + u8 car_loop_pilots_on_30; + u8 car_loop_pilots_off_30; + +}; + +struct stv0900_short_frames_car_loop_optim { + enum fe_stv0900_modulation modulation; + u8 car_loop_cut12_2; /* Cut 1.2, SR<=3msps */ + u8 car_loop_cut20_2; /* Cut 2.0, SR<3msps */ + u8 car_loop_cut12_5; /* Cut 1.2, 3 + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef STV0900_PRIV_H +#define STV0900_PRIV_H + +#include + +#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X)) +#define INRANGE(X, Y, Z) ((((X) <= (Y)) && ((Y) <= (Z))) \ + || (((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0) + +#ifndef MAKEWORD +#define MAKEWORD(X, Y) (((X) << 8) + (Y)) +#endif + +#define LSB(X) (((X) & 0xFF)) +#define MSB(Y) (((Y) >> 8) & 0xFF) + +#ifndef TRUE +#define TRUE (1 == 1) +#endif +#ifndef FALSE +#define FALSE (!TRUE) +#endif + +#define dmd_reg(a, b, c) \ + do { \ + a = 0; \ + switch (demod) { \ + case STV0900_DEMOD_1: \ + default: \ + a = b; \ + break; \ + case STV0900_DEMOD_2: \ + a = c; \ + break; \ + } \ + } while (0) + +#define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a)) + +extern int debug; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG args); \ + } while (0) + +#define STV0900_MAXLOOKUPSIZE 500 +#define STV0900_BLIND_SEARCH_AGC2_TH 700 + +/* One point of the lookup table */ +struct stv000_lookpoint { + s32 realval;/* real value */ + s32 regval;/* binary value */ +}; + +/* Lookup table definition */ +struct stv0900_table{ + s32 size;/* Size of the lookup table */ + struct stv000_lookpoint table[STV0900_MAXLOOKUPSIZE];/* Lookup table */ +}; + +enum fe_stv0900_error { + STV0900_NO_ERROR = 0, + STV0900_INVALID_HANDLE, + STV0900_BAD_PARAMETER, + STV0900_I2C_ERROR, + STV0900_SEARCH_FAILED, +}; + +enum fe_stv0900_clock_type { + STV0900_USE_REGISTERS_DEFAULT, + STV0900_SERIAL_PUNCT_CLOCK,/*Serial punctured clock */ + STV0900_SERIAL_CONT_CLOCK,/*Serial continues clock */ + STV0900_PARALLEL_PUNCT_CLOCK,/*Parallel punctured clock */ + STV0900_DVBCI_CLOCK/*Parallel continues clock : DVBCI */ +}; + +enum fe_stv0900_search_state { + STV0900_SEARCH = 0, + STV0900_PLH_DETECTED, + STV0900_DVBS2_FOUND, + STV0900_DVBS_FOUND + +}; + +enum fe_stv0900_ldpc_state { + STV0900_PATH1_OFF_PATH2_OFF = 0, + STV0900_PATH1_ON_PATH2_OFF = 1, + STV0900_PATH1_OFF_PATH2_ON = 2, + STV0900_PATH1_ON_PATH2_ON = 3 +}; + +enum fe_stv0900_signal_type { + STV0900_NOAGC1 = 0, + STV0900_AGC1OK, + STV0900_NOTIMING, + STV0900_ANALOGCARRIER, + STV0900_TIMINGOK, + STV0900_NOAGC2, + STV0900_AGC2OK, + STV0900_NOCARRIER, + STV0900_CARRIEROK, + STV0900_NODATA, + STV0900_DATAOK, + STV0900_OUTOFRANGE, + STV0900_RANGEOK +}; + +enum fe_stv0900_demod_num { + STV0900_DEMOD_1, + STV0900_DEMOD_2 +}; + +enum fe_stv0900_tracking_standard { + STV0900_DVBS1_STANDARD,/* Found Standard*/ + STV0900_DVBS2_STANDARD, + STV0900_DSS_STANDARD, + STV0900_TURBOCODE_STANDARD, + STV0900_UNKNOWN_STANDARD +}; + +enum fe_stv0900_search_standard { + STV0900_AUTO_SEARCH, + STV0900_SEARCH_DVBS1,/* Search Standard*/ + STV0900_SEARCH_DVBS2, + STV0900_SEARCH_DSS, + STV0900_SEARCH_TURBOCODE +}; + +enum fe_stv0900_search_algo { + STV0900_BLIND_SEARCH,/* offset freq and SR are Unknown */ + STV0900_COLD_START,/* only the SR is known */ + STV0900_WARM_START/* offset freq and SR are known */ +}; + +enum fe_stv0900_modulation { + STV0900_QPSK, + STV0900_8PSK, + STV0900_16APSK, + STV0900_32APSK, + STV0900_UNKNOWN +}; + +enum fe_stv0900_modcode { + STV0900_DUMMY_PLF, + STV0900_QPSK_14, + STV0900_QPSK_13, + STV0900_QPSK_25, + STV0900_QPSK_12, + STV0900_QPSK_35, + STV0900_QPSK_23, + STV0900_QPSK_34, + STV0900_QPSK_45, + STV0900_QPSK_56, + STV0900_QPSK_89, + STV0900_QPSK_910, + STV0900_8PSK_35, + STV0900_8PSK_23, + STV0900_8PSK_34, + STV0900_8PSK_56, + STV0900_8PSK_89, + STV0900_8PSK_910, + STV0900_16APSK_23, + STV0900_16APSK_34, + STV0900_16APSK_45, + STV0900_16APSK_56, + STV0900_16APSK_89, + STV0900_16APSK_910, + STV0900_32APSK_34, + STV0900_32APSK_45, + STV0900_32APSK_56, + STV0900_32APSK_89, + STV0900_32APSK_910, + STV0900_MODCODE_UNKNOWN +}; + +enum fe_stv0900_fec {/*DVBS1, DSS and turbo code puncture rate*/ + STV0900_FEC_1_2 = 0, + STV0900_FEC_2_3, + STV0900_FEC_3_4, + STV0900_FEC_4_5,/*for turbo code only*/ + STV0900_FEC_5_6, + STV0900_FEC_6_7,/*for DSS only */ + STV0900_FEC_7_8, + STV0900_FEC_8_9,/*for turbo code only*/ + STV0900_FEC_UNKNOWN +}; + +enum fe_stv0900_frame_length { + STV0900_LONG_FRAME, + STV0900_SHORT_FRAME +}; + +enum fe_stv0900_pilot { + STV0900_PILOTS_OFF, + STV0900_PILOTS_ON +}; + +enum fe_stv0900_rolloff { + STV0900_35, + STV0900_25, + STV0900_20 +}; + +enum fe_stv0900_search_iq { + STV0900_IQ_AUTO, + STV0900_IQ_AUTO_NORMAL_FIRST, + STV0900_IQ_FORCE_NORMAL, + STV0900_IQ_FORCE_SWAPPED +}; + +enum stv0900_iq_inversion { + STV0900_IQ_NORMAL, + STV0900_IQ_SWAPPED +}; + +enum fe_stv0900_diseqc_mode { + STV0900_22KHZ_Continues = 0, + STV0900_DISEQC_2_3_PWM = 2, + STV0900_DISEQC_3_3_PWM = 3, + STV0900_DISEQC_2_3_ENVELOP = 4, + STV0900_DISEQC_3_3_ENVELOP = 5 +}; + +enum fe_stv0900_demod_mode { + STV0900_SINGLE = 0, + STV0900_DUAL +}; + +struct stv0900_init_params{ + u32 dmd_ref_clk;/* Refrence,Input clock for the demod in Hz */ + + /* Demodulator Type (single demod or dual demod) */ + enum fe_stv0900_demod_mode demod_mode; + enum fe_stv0900_rolloff rolloff; + enum fe_stv0900_clock_type path1_ts_clock; + + u8 tun1_maddress; + int tuner1_adc; + + /* IQ from the tuner1 to the demod */ + enum stv0900_iq_inversion tun1_iq_inversion; + enum fe_stv0900_clock_type path2_ts_clock; + + u8 tun2_maddress; + int tuner2_adc; + + /* IQ from the tuner2 to the demod */ + enum stv0900_iq_inversion tun2_iq_inversion; +}; + +struct stv0900_search_params { + enum fe_stv0900_demod_num path;/* Path Used demod1 or 2 */ + + u32 frequency;/* Transponder frequency (in KHz) */ + u32 symbol_rate;/* Transponder symbol rate (in bds)*/ + u32 search_range;/* Range of the search (in Hz) */ + + enum fe_stv0900_search_standard standard; + enum fe_stv0900_modulation modulation; + enum fe_stv0900_fec fec; + enum fe_stv0900_modcode modcode; + enum fe_stv0900_search_iq iq_inversion; + enum fe_stv0900_search_algo search_algo; + +}; + +struct stv0900_signal_info { + int locked;/* Transponder locked */ + u32 frequency;/* Transponder frequency (in KHz) */ + u32 symbol_rate;/* Transponder symbol rate (in Mbds) */ + + enum fe_stv0900_tracking_standard standard; + enum fe_stv0900_fec fec; + enum fe_stv0900_modcode modcode; + enum fe_stv0900_modulation modulation; + enum fe_stv0900_pilot pilot; + enum fe_stv0900_frame_length frame_length; + enum stv0900_iq_inversion spectrum; + enum fe_stv0900_rolloff rolloff; + + s32 Power;/* Power of the RF signal (dBm) */ + s32 C_N;/* Carrier to noise ratio (dB x10)*/ + u32 BER;/* Bit error rate (x10^7) */ + +}; + +struct stv0900_internal{ + s32 quartz; + s32 mclk; + /* manual RollOff for DVBS1/DSS only */ + enum fe_stv0900_rolloff rolloff; + /* Demodulator use for single demod or for dual demod) */ + enum fe_stv0900_demod_mode demod_mode; + + /*Demod 1*/ + s32 tuner1_freq; + s32 tuner1_bw; + s32 dmd1_symbol_rate; + s32 dmd1_srch_range; + + /* algorithm for search Blind, Cold or Warm*/ + enum fe_stv0900_search_algo dmd1_srch_algo; + /* search standard: Auto, DVBS1/DSS only or DVBS2 only*/ + enum fe_stv0900_search_standard dmd1_srch_standard; + /* inversion search : auto, auto norma first, normal or inverted */ + enum fe_stv0900_search_iq dmd1_srch_iq_inv; + enum fe_stv0900_modcode dmd1_modcode; + enum fe_stv0900_modulation dmd1_modulation; + enum fe_stv0900_fec dmd1_fec; + + struct stv0900_signal_info dmd1_rslts; + enum fe_stv0900_signal_type dmd1_state; + + enum fe_stv0900_error dmd1_err; + + /*Demod 2*/ + s32 tuner2_freq; + s32 tuner2_bw; + s32 dmd2_symbol_rate; + s32 dmd2_srch_range; + + enum fe_stv0900_search_algo dmd2_srch_algo; + enum fe_stv0900_search_standard dmd2_srch_stndrd; + /* inversion search : auto, auto normal first, normal or inverted */ + enum fe_stv0900_search_iq dmd2_srch_iq_inv; + enum fe_stv0900_modcode dmd2_modcode; + enum fe_stv0900_modulation dmd2_modulation; + enum fe_stv0900_fec dmd2_fec; + + /* results of the search*/ + struct stv0900_signal_info dmd2_rslts; + /* current state of the search algorithm */ + enum fe_stv0900_signal_type dmd2_state; + + enum fe_stv0900_error dmd2_err; + + struct i2c_adapter *i2c_adap; + u8 i2c_addr; + u8 clkmode;/* 0 for CLKI, 2 for XTALI */ + u8 chip_id; + enum fe_stv0900_error errs; + int dmds_used; +}; + +/* state for each demod */ +struct stv0900_state { + /* pointer for internal params, one for each pair of demods */ + struct stv0900_internal *internal; + struct i2c_adapter *i2c_adap; + const struct stv0900_config *config; + struct dvb_frontend frontend; + int demod; +}; + +extern s32 ge2comp(s32 a, s32 width); + +extern void stv0900_write_reg(struct stv0900_internal *i_params, + u16 reg_addr, u8 reg_data); + +extern u8 stv0900_read_reg(struct stv0900_internal *i_params, + u16 reg_addr); + +extern void stv0900_write_bits(struct stv0900_internal *i_params, + u32 label, u8 val); + +extern u8 stv0900_get_bits(struct stv0900_internal *i_params, + u32 label); + +extern int stv0900_get_demod_lock(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod, s32 time_out); +extern int stv0900_check_signal_presence(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod); + +extern enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe); + +extern void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency, + u32 bandwidth); +extern void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth); + +extern void stv0900_start_search(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod); + +extern u8 stv0900_get_optim_carr_loop(s32 srate, + enum fe_stv0900_modcode modcode, + s32 pilot, u8 chip_id); + +extern u8 stv0900_get_optim_short_carr_loop(s32 srate, + enum fe_stv0900_modulation modulation, + u8 chip_id); + +extern void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod); + +extern void stv0900_activate_s2_modcode(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod); + +extern void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod); + +extern enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, + enum fe_stv0900_demod_num demod); + +#endif -- cgit v1.2.3 From eb4eb1c9135ee4c35f958c5bb7c8ed71a8654e44 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:45:49 +0200 Subject: Add core code for ST STV0900 dual demodulator. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900_core.c | 1961 ++++++++++++++++++++++ 1 file changed, 1961 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/stv0900_core.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c new file mode 100644 index 000000000..c86c3017e --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -0,0 +1,1961 @@ +/* + * stv0900_core.c + * + * Driver for ST STV0900 satellite demodulator IC. + * + * Copyright (C) ST Microelectronics. + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "stv0900.h" +#include "stv0900_reg.h" +#include "stv0900_priv.h" +#include "stv0900_init.h" + +int debug = 1; +module_param(debug, int, 0644); + +/* internal params node */ +struct stv0900_inode { + /* pointer for internal params, one for each pair of demods */ + struct stv0900_internal *internal; + struct stv0900_inode *next_inode; +}; + +/* first internal params */ +static struct stv0900_inode *stv0900_first_inode; + +/* find chip by i2c adapter and i2c address */ +static struct stv0900_inode *find_inode(struct i2c_adapter *i2c_adap, + u8 i2c_addr) +{ + struct stv0900_inode *temp_chip = stv0900_first_inode; + + if (temp_chip != NULL) { + /* + Search of the last stv0900 chip or + find it by i2c adapter and i2c address */ + while ((temp_chip != NULL) && + ((temp_chip->internal->i2c_adap != i2c_adap) || + (temp_chip->internal->i2c_addr != i2c_addr))) { + + temp_chip = temp_chip->next_inode; + dprintk(KERN_INFO "%s: store.adap %x\n", __func__, + (int)&(*temp_chip->internal->i2c_adap)); + dprintk(KERN_INFO "%s: init.adap %x\n", __func__, + (int)&(*i2c_adap)); + } + if (temp_chip != NULL) {/* find by i2c adapter & address */ + dprintk(KERN_INFO "%s: store.adap %x\n", __func__, + (int)temp_chip->internal->i2c_adap); + dprintk(KERN_INFO "%s: init.adap %x\n", __func__, + (int)i2c_adap); + } + } + + return temp_chip; +} + +/* deallocating chip */ +static void remove_inode(struct stv0900_internal *internal) +{ + struct stv0900_inode *prev_node = stv0900_first_inode; + struct stv0900_inode *del_node = find_inode(internal->i2c_adap, + internal->i2c_addr); + + if (del_node != NULL) { + if (del_node == stv0900_first_inode) { + stv0900_first_inode = del_node->next_inode; + } else { + while (prev_node->next_inode != del_node) + prev_node = prev_node->next_inode; + + if (del_node->next_inode == NULL) + prev_node->next_inode = NULL; + else + prev_node->next_inode = + prev_node->next_inode->next_inode; + } + + kfree(del_node); + } +} + +/* allocating new chip */ +static struct stv0900_inode *append_internal(struct stv0900_internal *internal) +{ + struct stv0900_inode *new_node = stv0900_first_inode; + + if (new_node == NULL) { + new_node = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL); + stv0900_first_inode = new_node; + } else { + while (new_node->next_inode != NULL) + new_node = new_node->next_inode; + + new_node->next_inode = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL); + if (new_node->next_inode != NULL) + new_node = new_node->next_inode; + else + new_node = NULL; + } + + if (new_node != NULL) { + new_node->internal = internal; + new_node->next_inode = NULL; + } + + return new_node; +} + +s32 ge2comp(s32 a, s32 width) +{ + if (width == 32) + return a; + else + return (a >= (1 << (width - 1))) ? (a - (1 << width)) : a; +} + +void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr, + u8 reg_data) +{ + u8 data[3]; + int ret; + struct i2c_msg i2cmsg = { + .addr = i_params->i2c_addr, + .flags = 0, + .len = 3, + .buf = data, + }; + + data[0] = MSB(reg_addr); + data[1] = LSB(reg_addr); + data[2] = reg_data; + + ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); + if (ret != 1) + dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); +} + +u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr) +{ + u8 data[2]; + int ret; + struct i2c_msg i2cmsg = { + .addr = i_params->i2c_addr, + .flags = 0, + .len = 2, + .buf = data, + }; + + data[0] = MSB(reg_addr); + data[1] = LSB(reg_addr); + + ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); + if (ret != 1) + dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); + + i2cmsg.flags = I2C_M_RD; + i2cmsg.len = 1; + ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); + if (ret != 1) + dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); + + return data[0]; +} + +void extract_mask_pos(u32 label, u8 *mask, u8 *pos) +{ + u8 position = 0, i = 0; + + (*mask) = label & 0xff; + + while ((position == 0) && (i < 8)) { + position = ((*mask) >> i) & 0x01; + i++; + } + + (*pos) = (i - 1); +} + +void stv0900_write_bits(struct stv0900_internal *i_params, u32 label, u8 val) +{ + u8 reg, mask, pos; + + reg = stv0900_read_reg(i_params, (label >> 16) & 0xffff); + extract_mask_pos(label, &mask, &pos); + + val = mask & (val << pos); + + reg = (reg & (~mask)) | val; + stv0900_write_reg(i_params, (label >> 16) & 0xffff, reg); + +} + +u8 stv0900_get_bits(struct stv0900_internal *i_params, u32 label) +{ + u8 val = 0xff; + u8 mask, pos; + + extract_mask_pos(label, &mask, &pos); + + val = stv0900_read_reg(i_params, label >> 16); + val = (val & mask) >> pos; + + return val; +} + +enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params) +{ + s32 i; + enum fe_stv0900_error error; + + if (i_params != NULL) { + i_params->chip_id = stv0900_read_reg(i_params, R0900_MID); + if (i_params->errs == STV0900_NO_ERROR) { + /*Startup sequence*/ + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5c); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5c); +#if 0 + msleep(3);/* wait for demod stop + (i.e. no more tuner I2C transactions) */ +#endif + stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c); + stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f); + stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x24); + stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x24); + stv0900_write_reg(i_params, R0900_NCOARSE, 0x13); + msleep(3); + stv0900_write_reg(i_params, R0900_I2CCFG, 0x08); + + switch (i_params->clkmode) { + case 0: + case 2: + stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20 + | i_params->clkmode); + break; + default: + /* preserve SELOSCI bit */ + i = 0x02 & stv0900_read_reg(i_params, R0900_SYNTCTRL); + stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20 | i); + break; + } + + msleep(3); + for (i = 0; i < 180; i++) + stv0900_write_reg(i_params, STV0900_InitVal[i][0], STV0900_InitVal[i][1]); + + if (stv0900_read_reg(i_params, R0900_MID) >= 0x20) { + stv0900_write_reg(i_params, R0900_TSGENERAL, 0x0c); + for (i = 0; i < 32; i++) + stv0900_write_reg(i_params, STV0900_Cut20_AddOnVal[i][0], STV0900_Cut20_AddOnVal[i][1]); + } + + stv0900_write_reg(i_params, R0900_P1_FSPYCFG, 0x6c); + stv0900_write_reg(i_params, R0900_P2_FSPYCFG, 0x6c); + stv0900_write_reg(i_params, R0900_TSTRES0, 0x80); + stv0900_write_reg(i_params, R0900_TSTRES0, 0x00); + } + error = i_params->errs; + } else + error = STV0900_INVALID_HANDLE; + + return error; + +} + +u32 stv0900_get_mclk_freq(struct stv0900_internal *i_params, u32 ext_clk) +{ + u32 mclk = 90000000, div = 0, ad_div = 0; + + div = stv0900_get_bits(i_params, F0900_M_DIV); + ad_div = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6); + + mclk = (div + 1) * ext_clk / ad_div; + + dprintk(KERN_INFO "%s: Calculated Mclk = %d\n", __func__, mclk); + + return mclk; +} + +enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *i_params, u32 mclk) +{ + enum fe_stv0900_error error = STV0900_NO_ERROR; + u32 m_div, clk_sel; + + dprintk(KERN_INFO "%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, + i_params->quartz); + + if (i_params == NULL) + error = STV0900_INVALID_HANDLE; + else { + if (i_params->errs) + error = STV0900_I2C_ERROR; + else { + clk_sel = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6); + m_div = ((clk_sel * mclk) / i_params->quartz) - 1; + stv0900_write_bits(i_params, F0900_M_DIV, m_div); + i_params->mclk = stv0900_get_mclk_freq(i_params, + i_params->quartz); + + /*Set the DiseqC frequency to 22KHz */ + /* + Formula: + DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg) + DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg) + */ + m_div = i_params->mclk / 704000; + stv0900_write_reg(i_params, R0900_P1_F22TX, m_div); + stv0900_write_reg(i_params, R0900_P1_F22RX, m_div); + + stv0900_write_reg(i_params, R0900_P2_F22TX, m_div); + stv0900_write_reg(i_params, R0900_P2_F22RX, m_div); + + if ((i_params->errs)) + error = STV0900_I2C_ERROR; + } + } + + return error; +} + +u32 stv0900_get_err_count(struct stv0900_internal *i_params, int cntr, + enum fe_stv0900_demod_num demod) +{ + u32 lsb, msb, hsb, err_val; + s32 err1field_hsb, err1field_msb, err1field_lsb; + s32 err2field_hsb, err2field_msb, err2field_lsb; + + dmd_reg(err1field_hsb, F0900_P1_ERR_CNT12, F0900_P2_ERR_CNT12); + dmd_reg(err1field_msb, F0900_P1_ERR_CNT11, F0900_P2_ERR_CNT11); + dmd_reg(err1field_lsb, F0900_P1_ERR_CNT10, F0900_P2_ERR_CNT10); + + dmd_reg(err2field_hsb, F0900_P1_ERR_CNT22, F0900_P2_ERR_CNT22); + dmd_reg(err2field_msb, F0900_P1_ERR_CNT21, F0900_P2_ERR_CNT21); + dmd_reg(err2field_lsb, F0900_P1_ERR_CNT20, F0900_P2_ERR_CNT20); + + switch (cntr) { + case 0: + default: + hsb = stv0900_get_bits(i_params, err1field_hsb); + msb = stv0900_get_bits(i_params, err1field_msb); + lsb = stv0900_get_bits(i_params, err1field_lsb); + break; + case 1: + hsb = stv0900_get_bits(i_params, err2field_hsb); + msb = stv0900_get_bits(i_params, err2field_msb); + lsb = stv0900_get_bits(i_params, err2field_lsb); + break; + } + + err_val = (hsb << 16) + (msb << 8) + (lsb); + + return err_val; +} + +static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + u32 fi2c; + + dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON); + if (enable) + stv0900_write_bits(i_params, fi2c, 1); + + return 0; +} + +static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, + enum fe_stv0900_clock_type path1_ts, + enum fe_stv0900_clock_type path2_ts) +{ + + dprintk(KERN_INFO "%s\n", __func__); + + if (i_params->chip_id >= 0x20) { + switch (path1_ts) { + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + switch (path2_ts) { + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + stv0900_write_reg(i_params, R0900_TSGENERAL, + 0x00); + break; + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + stv0900_write_reg(i_params, R0900_TSGENERAL, + 0x06); + stv0900_write_bits(i_params, + F0900_P1_TSFIFO_MANSPEED, 3); + stv0900_write_bits(i_params, + F0900_P2_TSFIFO_MANSPEED, 0); + stv0900_write_reg(i_params, + R0900_P1_TSSPEED, 0x14); + stv0900_write_reg(i_params, + R0900_P2_TSSPEED, 0x28); + break; + } + break; + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + switch (path2_ts) { + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + stv0900_write_reg(i_params, + R0900_TSGENERAL, 0x0C); + break; + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + stv0900_write_reg(i_params, + R0900_TSGENERAL, 0x0A); + dprintk(KERN_INFO "%s: 0x0a\n", __func__); + break; + } + break; + } + } else { + switch (path1_ts) { + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + switch (path2_ts) { + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + stv0900_write_reg(i_params, R0900_TSGENERAL1X, + 0x10); + break; + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + stv0900_write_reg(i_params, R0900_TSGENERAL1X, + 0x16); + stv0900_write_bits(i_params, + F0900_P1_TSFIFO_MANSPEED, 3); + stv0900_write_bits(i_params, + F0900_P2_TSFIFO_MANSPEED, 0); + stv0900_write_reg(i_params, R0900_P1_TSSPEED, + 0x14); + stv0900_write_reg(i_params, R0900_P2_TSSPEED, + 0x28); + break; + } + + break; + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + switch (path2_ts) { + case STV0900_SERIAL_PUNCT_CLOCK: + case STV0900_SERIAL_CONT_CLOCK: + default: + stv0900_write_reg(i_params, R0900_TSGENERAL1X, + 0x14); + break; + case STV0900_PARALLEL_PUNCT_CLOCK: + case STV0900_DVBCI_CLOCK: + stv0900_write_reg(i_params, R0900_TSGENERAL1X, + 0x12); + dprintk(KERN_INFO "%s: 0x12\n", __func__); + break; + } + + break; + } + } + + switch (path1_ts) { + case STV0900_PARALLEL_PUNCT_CLOCK: + stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00); + break; + case STV0900_DVBCI_CLOCK: + stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01); + break; + case STV0900_SERIAL_PUNCT_CLOCK: + stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00); + break; + case STV0900_SERIAL_CONT_CLOCK: + stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01); + break; + default: + break; + } + + switch (path2_ts) { + case STV0900_PARALLEL_PUNCT_CLOCK: + stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00); + break; + case STV0900_DVBCI_CLOCK: + stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01); + break; + case STV0900_SERIAL_PUNCT_CLOCK: + stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00); + break; + case STV0900_SERIAL_CONT_CLOCK: + stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01); + break; + default: + break; + } + + stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1); + stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 0); + stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1); + stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 0); +} + +void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency, + u32 bandwidth) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + + if (&fe->ops) + frontend_ops = &fe->ops; + + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + + if (tuner_ops->set_frequency) { + if ((tuner_ops->set_frequency(fe, frequency)) < 0) + dprintk("%s: Invalid parameter\n", __func__); + else + dprintk("%s: Frequency=%d\n", __func__, frequency); + + } + + if (tuner_ops->set_bandwidth) { + if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0) + dprintk("%s: Invalid parameter\n", __func__); + else + dprintk("%s: Bandwidth=%d\n", __func__, bandwidth); + + } +} + +void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + + if (&fe->ops) + frontend_ops = &fe->ops; + + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + + if (tuner_ops->set_bandwidth) { + if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0) + dprintk("%s: Invalid parameter\n", __func__); + else + dprintk("%s: Bandwidth=%d\n", __func__, bandwidth); + + } +} + +static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, + const struct stv0900_table *lookup, + enum fe_stv0900_demod_num demod) +{ + s32 agc_gain = 0, + imin, + imax, + i, + rf_lvl = 0; + + dprintk(KERN_INFO "%s\n", __func__); + + if ((lookup != NULL) && lookup->size) { + switch (demod) { + case STV0900_DEMOD_1: + default: + agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE1), + stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE0)); + break; + case STV0900_DEMOD_2: + agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE1), + stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE0)); + break; + } + + imin = 0; + imax = lookup->size - 1; + if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[imax].regval)) { + while ((imax - imin) > 1) { + i = (imax + imin) >> 1; + + if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[i].regval)) + imax = i; + else + imin = i; + } + + rf_lvl = (((s32)agc_gain - lookup->table[imin].regval) + * (lookup->table[imax].realval - lookup->table[imin].realval) + / (lookup->table[imax].regval - lookup->table[imin].regval)) + + lookup->table[imin].realval; + } else if (agc_gain > lookup->table[0].regval) + rf_lvl = 5; + else if (agc_gain < lookup->table[lookup->size-1].regval) + rf_lvl = -100; + + } + + dprintk(KERN_INFO "%s: RFLevel = %d\n", __func__, rf_lvl); + + return rf_lvl; +} + +static int stv0900_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *internal = state->internal; + s32 rflevel = stv0900_get_rf_level(internal, &stv0900_rf, + state->demod); + + *strength = (rflevel + 100) * (16383 / 105); + + return 0; +} + + +static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, + const struct stv0900_table *lookup) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + s32 c_n = -100, + regval, imin, imax, + i, + lock_flag_field, + noise_field1, + noise_field0; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); + if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { + dmd_reg(noise_field1, F0900_P1_NOSPLHT_NORMED1, F0900_P2_NOSPLHT_NORMED1); + dmd_reg(noise_field0, F0900_P1_NOSPLHT_NORMED0, F0900_P2_NOSPLHT_NORMED0); + } else { + dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1, F0900_P2_NOSDATAT_NORMED1); + dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0, F0900_P1_NOSDATAT_NORMED0); + } + + if (stv0900_get_bits(i_params, lock_flag_field)) { + if ((lookup != NULL) && lookup->size) { + regval = 0; + msleep(5); + for (i = 0; i < 16; i++) { + regval += MAKEWORD(stv0900_get_bits(i_params, noise_field1), + stv0900_get_bits(i_params, noise_field0)); + msleep(1); + } + + regval /= 16; + imin = 0; + imax = lookup->size - 1; + if (INRANGE(lookup->table[imin].regval, regval, lookup->table[imax].regval)) { + while ((imax - imin) > 1) { + i = (imax + imin) >> 1; + + if (INRANGE(lookup->table[imin].regval, regval, lookup->table[i].regval)) + imax = i; + else + imin = i; + } + + c_n = ((regval - lookup->table[imin].regval) + * (lookup->table[imax].realval - lookup->table[imin].realval) + / (lookup->table[imax].regval - lookup->table[imin].regval)) + + lookup->table[imin].realval; + } else if (regval < lookup->table[imin].regval) + c_n = 1000; + } + } + + return c_n; +} + +static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + *snr = (16383 / 1030) * (30 + stv0900_carr_get_quality(fe, (const struct stv0900_table *)&stv0900_s2_cn)); + + return 0; +} + +static u32 stv0900_get_ber(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + u32 ber = 10000000, i; + s32 dmd_state_reg; + s32 demod_state; + s32 vstatus_reg; + s32 prvit_field; + s32 pdel_status_reg; + s32 pdel_lock_field; + + dmd_reg(dmd_state_reg, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); + dmd_reg(vstatus_reg, R0900_P1_VSTATUSVIT, R0900_P2_VSTATUSVIT); + dmd_reg(prvit_field, F0900_P1_PRFVIT, F0900_P2_PRFVIT); + dmd_reg(pdel_status_reg, R0900_P1_PDELSTATUS1, R0900_P2_PDELSTATUS1); + dmd_reg(pdel_lock_field, F0900_P1_PKTDELIN_LOCK, + F0900_P2_PKTDELIN_LOCK); + + demod_state = stv0900_get_bits(i_params, dmd_state_reg); + + switch (demod_state) { + case STV0900_SEARCH: + case STV0900_PLH_DETECTED: + default: + ber = 10000000; + break; + case STV0900_DVBS_FOUND: + ber = 0; + for (i = 0; i < 5; i++) { + msleep(5); + ber += stv0900_get_err_count(i_params, 0, demod); + } + + ber /= 5; + if (stv0900_get_bits(i_params, prvit_field)) { + ber *= 9766; + ber = ber >> 13; + } + + break; + case STV0900_DVBS2_FOUND: + ber = 0; + for (i = 0; i < 5; i++) { + msleep(5); + ber += stv0900_get_err_count(i_params, 0, demod); + } + + ber /= 5; + if (stv0900_get_bits(i_params, pdel_lock_field)) { + ber *= 9766; + ber = ber >> 13; + } + + break; + } + + return ber; +} + +static int stv0900_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *internal = state->internal; + + *ber = stv0900_get_ber(internal, state->demod); + + return 0; +} + +int stv0900_get_demod_lock(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod, s32 time_out) +{ + s32 timer = 0, + lock = 0, + header_field, + lock_field; + + enum fe_stv0900_search_state dmd_state; + + dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); + dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); + while ((timer < time_out) && (lock == 0)) { + dmd_state = stv0900_get_bits(i_params, header_field); + dprintk("Demod State = %d\n", dmd_state); + switch (dmd_state) { + case STV0900_SEARCH: + case STV0900_PLH_DETECTED: + default: + lock = 0; + break; + case STV0900_DVBS2_FOUND: + case STV0900_DVBS_FOUND: + lock = stv0900_get_bits(i_params, lock_field); + break; + } + + if (lock == 0) + msleep(10); + + timer += 10; + } + + if (lock) + dprintk("DEMOD LOCK OK\n"); + else + dprintk("DEMOD LOCK FAIL\n"); + + return lock; +} + +void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + s32 regflist, + i; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(regflist, R0900_P1_MODCODLST0, R0900_P2_MODCODLST0); + + for (i = 0; i < 16; i++) + stv0900_write_reg(i_params, regflist + i, 0xff); +} + +void stv0900_activate_s2_modcode(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + u32 matype, + mod_code, + fmod, + reg_index, + field_index; + + dprintk(KERN_INFO "%s\n", __func__); + + if (i_params->chip_id <= 0x11) { + msleep(5); + + switch (demod) { + case STV0900_DEMOD_1: + default: + mod_code = stv0900_read_reg(i_params, + R0900_P1_PLHMODCOD); + matype = mod_code & 0x3; + mod_code = (mod_code & 0x7f) >> 2; + + reg_index = R0900_P1_MODCODLSTF - mod_code / 2; + field_index = mod_code % 2; + break; + case STV0900_DEMOD_2: + mod_code = stv0900_read_reg(i_params, + R0900_P2_PLHMODCOD); + matype = mod_code & 0x3; + mod_code = (mod_code & 0x7f) >> 2; + + reg_index = R0900_P2_MODCODLSTF - mod_code / 2; + field_index = mod_code % 2; + break; + } + + + switch (matype) { + case 0: + default: + fmod = 14; + break; + case 1: + fmod = 13; + break; + case 2: + fmod = 11; + break; + case 3: + fmod = 7; + break; + } + + if ((INRANGE(STV0900_QPSK_12, mod_code, STV0900_8PSK_910)) + && (matype <= 1)) { + if (field_index == 0) + stv0900_write_reg(i_params, reg_index, + 0xf0 | fmod); + else + stv0900_write_reg(i_params, reg_index, + (fmod << 4) | 0xf); + } + } else if (i_params->chip_id >= 0x12) { + switch (demod) { + case STV0900_DEMOD_1: + default: + for (reg_index = 0; reg_index < 7; reg_index++) + stv0900_write_reg(i_params, R0900_P1_MODCODLST0 + reg_index, 0xff); + + stv0900_write_reg(i_params, R0900_P1_MODCODLSTE, 0xff); + stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0xcf); + for (reg_index = 0; reg_index < 8; reg_index++) + stv0900_write_reg(i_params, R0900_P1_MODCODLST7 + reg_index, 0xcc); + + break; + case STV0900_DEMOD_2: + for (reg_index = 0; reg_index < 7; reg_index++) + stv0900_write_reg(i_params, R0900_P2_MODCODLST0 + reg_index, 0xff); + + stv0900_write_reg(i_params, R0900_P2_MODCODLSTE, 0xff); + stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0xcf); + for (reg_index = 0; reg_index < 8; reg_index++) + stv0900_write_reg(i_params, R0900_P2_MODCODLST7 + reg_index, 0xcc); + + break; + } + + } +} + +void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + u32 reg_index; + + dprintk(KERN_INFO "%s\n", __func__); + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_reg(i_params, R0900_P1_MODCODLST0, 0xff); + stv0900_write_reg(i_params, R0900_P1_MODCODLST1, 0xf0); + stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0x0f); + for (reg_index = 0; reg_index < 13; reg_index++) + stv0900_write_reg(i_params, + R0900_P1_MODCODLST2 + reg_index, 0); + + break; + case STV0900_DEMOD_2: + stv0900_write_reg(i_params, R0900_P2_MODCODLST0, 0xff); + stv0900_write_reg(i_params, R0900_P2_MODCODLST1, 0xf0); + stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0x0f); + for (reg_index = 0; reg_index < 13; reg_index++) + stv0900_write_reg(i_params, + R0900_P2_MODCODLST2 + reg_index, 0); + + break; + } +} + +static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_CUSTOM; +} + +static int stb0900_set_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + dprintk(KERN_INFO "%s(..)\n", __func__); + + return 0; +} + +static int stb0900_get_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + dprintk(KERN_INFO "%s(..)\n", __func__); + + return 0; +} + +void stv0900_start_search(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1f); + + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xaa); + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55); + + if (i_params->dmd1_symbol_rate <= 5000000) { + stv0900_write_reg(i_params, R0900_P1_CARCFG, 0x44); + stv0900_write_reg(i_params, R0900_P1_CFRUP1, 0x0f); + stv0900_write_reg(i_params, R0900_P1_CFRUP0, 0xff); + stv0900_write_reg(i_params, R0900_P1_CFRLOW1, 0xf0); + stv0900_write_reg(i_params, R0900_P1_CFRLOW0, 0x00); + stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68); + } else { + stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xc4); + stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44); + } + + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41); + stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41); + + if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) { + stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82); + stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0); + } + } + + stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00); + stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xe0); + stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xc0); + stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + stv0900_write_bits(i_params, F0900_P1_S1S2_SEQUENTIAL, 0); + stv0900_write_reg(i_params, R0900_P1_RTC, 0x88); + if (i_params->chip_id >= 0x20) { + if (i_params->dmd1_symbol_rate < 2000000) { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x39); + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x40); + } + + if (i_params->dmd1_symbol_rate < 10000000) { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4c); + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20); + } else { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4b); + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20); + } + + } else { + if (i_params->dmd1_symbol_rate < 10000000) + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xef); + else + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); + } + + switch (i_params->dmd1_srch_algo) { + case STV0900_WARM_START: + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + break; + case STV0900_COLD_START: + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); + break; + default: + break; + } + + break; + case STV0900_DEMOD_2: + stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1f); + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xaa); + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55); + + if (i_params->dmd2_symbol_rate <= 5000000) { + stv0900_write_reg(i_params, R0900_P2_CARCFG, 0x44); + stv0900_write_reg(i_params, R0900_P2_CFRUP1, 0x0f); + stv0900_write_reg(i_params, R0900_P2_CFRUP0, 0xff); + stv0900_write_reg(i_params, R0900_P2_CFRLOW1, 0xf0); + stv0900_write_reg(i_params, R0900_P2_CFRLOW0, 0x00); + stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68); + } else { + stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xc4); + stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44); + } + + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41); + stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41); + if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) { + stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82); + stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0); + } + } + + stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00); + stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xe0); + stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xc0); + stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); + stv0900_write_bits(i_params, F0900_P2_S1S2_SEQUENTIAL, 0); + stv0900_write_reg(i_params, R0900_P2_RTC, 0x88); + if (i_params->chip_id >= 0x20) { + if (i_params->dmd2_symbol_rate < 2000000) { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x39); + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x40); + } + + if (i_params->dmd2_symbol_rate < 10000000) { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4c); + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20); + } else { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4b); + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20); + } + + } else { + if (i_params->dmd2_symbol_rate < 10000000) + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xef); + else + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); + } + + switch (i_params->dmd2_srch_algo) { + case STV0900_WARM_START: + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + break; + case STV0900_COLD_START: + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); + break; + default: + break; + } + + break; + } +} + +u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode, + s32 pilot, u8 chip_id) +{ + u8 aclc_value = 0x29; + s32 i; + const struct stv0900_car_loop_optim *car_loop_s2; + + dprintk(KERN_INFO "%s\n", __func__); + + if (chip_id <= 0x12) + car_loop_s2 = FE_STV0900_S2CarLoop; + else if (chip_id == 0x20) + car_loop_s2 = FE_STV0900_S2CarLoopCut20; + else + car_loop_s2 = FE_STV0900_S2CarLoop; + + if (modcode < STV0900_QPSK_12) { + i = 0; + while ((i < 3) && (modcode != FE_STV0900_S2LowQPCarLoopCut20[i].modcode)) + i++; + + if (i >= 3) + i = 2; + } else { + i = 0; + while ((i < 14) && (modcode != car_loop_s2[i].modcode)) + i++; + + if (i >= 14) { + i = 0; + while ((i < 11) && (modcode != FE_STV0900_S2APSKCarLoopCut20[i].modcode)) + i++; + + if (i >= 11) + i = 10; + } + } + + if (modcode <= STV0900_QPSK_25) { + if (pilot) { + if (srate <= 3000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_2; + else if (srate <= 7000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_5; + else if (srate <= 15000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_10; + else if (srate <= 25000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_20; + else + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_30; + } else { + if (srate <= 3000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_2; + else if (srate <= 7000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_5; + else if (srate <= 15000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_10; + else if (srate <= 25000000) + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_20; + else + aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_30; + } + + } else if (modcode <= STV0900_8PSK_910) { + if (pilot) { + if (srate <= 3000000) + aclc_value = car_loop_s2[i].car_loop_pilots_on_2; + else if (srate <= 7000000) + aclc_value = car_loop_s2[i].car_loop_pilots_on_5; + else if (srate <= 15000000) + aclc_value = car_loop_s2[i].car_loop_pilots_on_10; + else if (srate <= 25000000) + aclc_value = car_loop_s2[i].car_loop_pilots_on_20; + else + aclc_value = car_loop_s2[i].car_loop_pilots_on_30; + } else { + if (srate <= 3000000) + aclc_value = car_loop_s2[i].car_loop_pilots_off_2; + else if (srate <= 7000000) + aclc_value = car_loop_s2[i].car_loop_pilots_off_5; + else if (srate <= 15000000) + aclc_value = car_loop_s2[i].car_loop_pilots_off_10; + else if (srate <= 25000000) + aclc_value = car_loop_s2[i].car_loop_pilots_off_20; + else + aclc_value = car_loop_s2[i].car_loop_pilots_off_30; + } + + } else { + if (srate <= 3000000) + aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_2; + else if (srate <= 7000000) + aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_5; + else if (srate <= 15000000) + aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_10; + else if (srate <= 25000000) + aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_20; + else + aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_30; + } + + return aclc_value; +} + +u8 stv0900_get_optim_short_carr_loop(s32 srate, enum fe_stv0900_modulation modulation, u8 chip_id) +{ + s32 mod_index = 0; + + u8 aclc_value = 0x0b; + + dprintk(KERN_INFO "%s\n", __func__); + + switch (modulation) { + case STV0900_QPSK: + default: + mod_index = 0; + break; + case STV0900_8PSK: + mod_index = 1; + break; + case STV0900_16APSK: + mod_index = 2; + break; + case STV0900_32APSK: + mod_index = 3; + break; + } + + switch (chip_id) { + case 0x20: + if (srate <= 3000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_2; + else if (srate <= 7000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_5; + else if (srate <= 15000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_10; + else if (srate <= 25000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_20; + else + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_30; + + break; + case 0x12: + default: + if (srate <= 3000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_2; + else if (srate <= 7000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_5; + else if (srate <= 15000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_10; + else if (srate <= 25000000) + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_20; + else + aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_30; + + break; + } + + return aclc_value; +} + +static enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *i_params, + enum fe_stv0900_demod_mode LDPC_Mode, + enum fe_stv0900_demod_num demod) +{ + enum fe_stv0900_error error = STV0900_NO_ERROR; + + dprintk(KERN_INFO "%s\n", __func__); + + switch (LDPC_Mode) { + case STV0900_DUAL: + default: + if ((i_params->demod_mode != STV0900_DUAL) + || (stv0900_get_bits(i_params, F0900_DDEMOD) != 1)) { + stv0900_write_reg(i_params, R0900_GENCFG, 0x1d); + + i_params->demod_mode = STV0900_DUAL; + + stv0900_write_bits(i_params, F0900_FRESFEC, 1); + stv0900_write_bits(i_params, F0900_FRESFEC, 0); + } + + break; + case STV0900_SINGLE: + if (demod == STV0900_DEMOD_2) + stv0900_write_reg(i_params, R0900_GENCFG, 0x06); + else + stv0900_write_reg(i_params, R0900_GENCFG, 0x04); + + i_params->demod_mode = STV0900_SINGLE; + + stv0900_write_bits(i_params, F0900_FRESFEC, 1); + stv0900_write_bits(i_params, F0900_FRESFEC, 0); + stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1); + stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0); + stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1); + stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0); + break; + } + + return error; +} + +static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, + struct stv0900_init_params *p_init) +{ + struct stv0900_state *state = fe->demodulator_priv; + enum fe_stv0900_error error = STV0900_NO_ERROR; + enum fe_stv0900_error demodError = STV0900_NO_ERROR; + int selosci; + + struct stv0900_inode *temp_int = find_inode(state->i2c_adap, + state->config->demod_address); + + dprintk(KERN_INFO "%s\n", __func__); + + if (temp_int != NULL) { + state->internal = temp_int->internal; + (state->internal->dmds_used)++; + dprintk(KERN_INFO "%s: Find Internal Structure!\n", __func__); + return STV0900_NO_ERROR; + } else { + state->internal = kmalloc(sizeof(struct stv0900_internal), GFP_KERNEL); + temp_int = append_internal(state->internal); + state->internal->dmds_used = 1; + state->internal->i2c_adap = state->i2c_adap; + state->internal->i2c_addr = state->config->demod_address; + state->internal->clkmode = state->config->clkmode; + state->internal->errs = STV0900_NO_ERROR; + dprintk(KERN_INFO "%s: Create New Internal Structure!\n", __func__); + } + + if (state->internal != NULL) { + demodError = stv0900_initialize(state->internal); + if (demodError == STV0900_NO_ERROR) { + error = STV0900_NO_ERROR; + } else { + if (demodError == STV0900_INVALID_HANDLE) + error = STV0900_INVALID_HANDLE; + else + error = STV0900_I2C_ERROR; + } + + if (state->internal != NULL) { + if (error == STV0900_NO_ERROR) { + state->internal->demod_mode = p_init->demod_mode; + + stv0900_st_dvbs2_single(state->internal, state->internal->demod_mode, STV0900_DEMOD_1); + + state->internal->chip_id = stv0900_read_reg(state->internal, R0900_MID); + state->internal->rolloff = p_init->rolloff; + state->internal->quartz = p_init->dmd_ref_clk; + + stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff); + stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff); + + stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock); + stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); + switch (p_init->tuner1_adc) { + case 1: + stv0900_write_reg(state->internal, R0900_TSTTNR1, 0x26); + break; + default: + break; + } + + stv0900_write_bits(state->internal, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); + switch (p_init->tuner2_adc) { + case 1: + stv0900_write_reg(state->internal, R0900_TSTTNR3, 0x26); + break; + default: + break; + } + + stv0900_write_bits(state->internal, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inversion); + stv0900_write_bits(state->internal, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inversion); + stv0900_set_mclk(state->internal, 135000000); + msleep(3); + + switch (state->internal->clkmode) { + case 0: + case 2: + stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | state->internal->clkmode); + break; + default: + selosci = 0x02 & stv0900_read_reg(state->internal, R0900_SYNTCTRL); + stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | selosci); + break; + } + msleep(3); + + state->internal->mclk = stv0900_get_mclk_freq(state->internal, state->internal->quartz); + if (state->internal->errs) + error = STV0900_I2C_ERROR; + } + } else { + error = STV0900_INVALID_HANDLE; + } + } + + return error; +} + +static int stv0900_status(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + enum fe_stv0900_search_state demod_state; + s32 mode_field, delin_field, lock_field, fifo_field, lockedvit_field; + int locked = FALSE; + + dmd_reg(mode_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); + dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); + dmd_reg(delin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK); + dmd_reg(fifo_field, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK); + dmd_reg(lockedvit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT); + + demod_state = stv0900_get_bits(i_params, mode_field); + switch (demod_state) { + case STV0900_SEARCH: + case STV0900_PLH_DETECTED: + default: + locked = FALSE; + break; + case STV0900_DVBS2_FOUND: + locked = stv0900_get_bits(i_params, lock_field) && + stv0900_get_bits(i_params, delin_field) && + stv0900_get_bits(i_params, fifo_field); + break; + case STV0900_DVBS_FOUND: + locked = stv0900_get_bits(i_params, lock_field) && + stv0900_get_bits(i_params, lockedvit_field) && + stv0900_get_bits(i_params, fifo_field); + break; + } + + return locked; +} + +static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + struct stv0900_search_params p_search; + struct stv0900_signal_info p_result; + + enum fe_stv0900_error error = STV0900_NO_ERROR; + + dprintk(KERN_INFO "%s: Internal = %x\n", __func__, (u32)i_params); + + p_result.locked = FALSE; + p_search.path = state->demod; + p_search.frequency = c->frequency; + p_search.symbol_rate = c->symbol_rate; + p_search.search_range = 10000000; + p_search.fec = STV0900_FEC_UNKNOWN; + p_search.standard = STV0900_AUTO_SEARCH; + p_search.iq_inversion = STV0900_IQ_AUTO; + p_search.search_algo = STV0900_BLIND_SEARCH; + + if ((INRANGE(100000, p_search.symbol_rate, 70000000)) && + (INRANGE(100000, p_search.search_range, 50000000))) { + switch (p_search.path) { + case STV0900_DEMOD_1: + default: + i_params->dmd1_srch_standard = p_search.standard; + i_params->dmd1_symbol_rate = p_search.symbol_rate; + i_params->dmd1_srch_range = p_search.search_range; + i_params->tuner1_freq = p_search.frequency; + i_params->dmd1_srch_algo = p_search.search_algo; + i_params->dmd1_srch_iq_inv = p_search.iq_inversion; + i_params->dmd1_fec = p_search.fec; +#if 0 + i_params->dmd1_modulation = p_search.modulation; + i_params->dmd1_modcode = p_search.modcode; +#endif + break; + + case STV0900_DEMOD_2: + i_params->dmd2_srch_stndrd = p_search.standard; + i_params->dmd2_symbol_rate = p_search.symbol_rate; + i_params->dmd2_srch_range = p_search.search_range; + i_params->tuner2_freq = p_search.frequency; + i_params->dmd2_srch_algo = p_search.search_algo; + i_params->dmd2_srch_iq_inv = p_search.iq_inversion; + i_params->dmd2_fec = p_search.fec; +#if 0 + i_params->dmd2_modulation = p_search.modulation; + i_params->dmd2_modcode = p_search.modcode; +#endif + break; + } + + if ((stv0900_algo(fe) == STV0900_RANGEOK) && + (i_params->errs == STV0900_NO_ERROR)) { + switch (p_search.path) { + case STV0900_DEMOD_1: + default: + p_result.locked = i_params->dmd1_rslts.locked; + p_result.standard = i_params->dmd1_rslts.standard; + p_result.frequency = i_params->dmd1_rslts.frequency; + p_result.symbol_rate = i_params->dmd1_rslts.symbol_rate; + p_result.fec = i_params->dmd1_rslts.fec; + p_result.modcode = i_params->dmd1_rslts.modcode; + p_result.pilot = i_params->dmd1_rslts.pilot; + p_result.frame_length = i_params->dmd1_rslts.frame_length; + p_result.spectrum = i_params->dmd1_rslts.spectrum; + p_result.rolloff = i_params->dmd1_rslts.rolloff; + p_result.modulation = i_params->dmd1_rslts.modulation; + break; + case STV0900_DEMOD_2: + p_result.locked = i_params->dmd2_rslts.locked; + p_result.standard = i_params->dmd2_rslts.standard; + p_result.frequency = i_params->dmd2_rslts.frequency; + p_result.symbol_rate = i_params->dmd2_rslts.symbol_rate; + p_result.fec = i_params->dmd2_rslts.fec; + p_result.modcode = i_params->dmd2_rslts.modcode; + p_result.pilot = i_params->dmd2_rslts.pilot; + p_result.frame_length = i_params->dmd2_rslts.frame_length; + p_result.spectrum = i_params->dmd2_rslts.spectrum; + p_result.rolloff = i_params->dmd2_rslts.rolloff; + p_result.modulation = i_params->dmd2_rslts.modulation; + break; + } + + } else { + p_result.locked = FALSE; + switch (p_search.path) { + case STV0900_DEMOD_1: + switch (i_params->dmd1_err) { + case STV0900_I2C_ERROR: + error = STV0900_I2C_ERROR; + break; + case STV0900_NO_ERROR: + default: + error = STV0900_SEARCH_FAILED; + break; + } + break; + case STV0900_DEMOD_2: + switch (i_params->dmd2_err) { + case STV0900_I2C_ERROR: + error = STV0900_I2C_ERROR; + break; + case STV0900_NO_ERROR: + default: + error = STV0900_SEARCH_FAILED; + break; + } + break; + } + } + + } else + error = STV0900_BAD_PARAMETER; + + if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) { + dprintk(KERN_INFO "Search Success\n"); + return DVBFE_ALGO_SEARCH_SUCCESS; + } else { + dprintk(KERN_INFO "Search Fail\n"); + return DVBFE_ALGO_SEARCH_FAILED; + } + + return DVBFE_ALGO_SEARCH_ERROR; +} + +static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status) +{ + struct stv0900_state *state = fe->demodulator_priv; + + dprintk("%s: Internal = %x\n", __func__, (unsigned int)state->internal); + + if ((stv0900_status(state->internal, state->demod)) == TRUE) { + dprintk("DEMOD LOCK OK\n"); + *status = FE_HAS_CARRIER + | FE_HAS_VITERBI + | FE_HAS_SYNC + | FE_HAS_LOCK; + } else + dprintk("DEMOD LOCK FAIL\n"); + + return 0; +} + +static int stv0900_track(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + return 0; +} + +static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts) +{ + + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + s32 rst_field; + + dmd_reg(rst_field, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE); + + if (stop_ts == TRUE) + stv0900_write_bits(i_params, rst_field, 1); + else + stv0900_write_bits(i_params, rst_field, 0); + + return 0; +} + +static int stv0900_diseqc_init(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + s32 mode_field, reset_field; + + dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); + dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); + + stv0900_write_bits(i_params, mode_field, state->config->diseqc_mode); + stv0900_write_bits(i_params, reset_field, 1); + stv0900_write_bits(i_params, reset_field, 0); + + return 0; +} + +static int stv0900_init(struct dvb_frontend *fe) +{ + dprintk(KERN_INFO "%s\n", __func__); + + stv0900_stop_ts(fe, 1); + stv0900_diseqc_init(fe); + + return 0; +} + +static int stv0900_diseqc_send(struct stv0900_internal *i_params , u8 *Data, + u32 NbData, enum fe_stv0900_demod_num demod) +{ + s32 i = 0; + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 1); + while (i < NbData) { + while (stv0900_get_bits(i_params, F0900_P1_FIFO_FULL)) + ;/* checkpatch complains */ + stv0900_write_reg(i_params, R0900_P1_DISTXDATA, Data[i]); + i++; + } + + stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 0); + i = 0; + while ((stv0900_get_bits(i_params, F0900_P1_TX_IDLE) != 1) && (i < 10)) { + msleep(10); + i++; + } + + break; + case STV0900_DEMOD_2: + stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 1); + + while (i < NbData) { + while (stv0900_get_bits(i_params, F0900_P2_FIFO_FULL)) + ;/* checkpatch complains */ + stv0900_write_reg(i_params, R0900_P2_DISTXDATA, Data[i]); + i++; + } + + stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 0); + i = 0; + while ((stv0900_get_bits(i_params, F0900_P2_TX_IDLE) != 1) && (i < 10)) { + msleep(10); + i++; + } + + break; + } + + return 0; +} + +static int stv0900_send_master_cmd(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) +{ + struct stv0900_state *state = fe->demodulator_priv; + + return stv0900_diseqc_send(state->internal, + cmd->msg, + cmd->msg_len, + state->demod); +} + +static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + s32 mode_field; + u32 diseqc_fifo; + + dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); + dmd_reg(diseqc_fifo, R0900_P1_DISTXDATA, R0900_P2_DISTXDATA); + + switch (burst) { + case SEC_MINI_A: + stv0900_write_bits(i_params, mode_field, 3);/* Unmodulated */ + stv0900_write_reg(i_params, diseqc_fifo, 0x00); + break; + case SEC_MINI_B: + stv0900_write_bits(i_params, mode_field, 2);/* Modulated */ + stv0900_write_reg(i_params, diseqc_fifo, 0xff); + break; + } + + return 0; +} + +static int stv0900_recv_slave_reply(struct dvb_frontend *fe, + struct dvb_diseqc_slave_reply *reply) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + s32 i = 0; + + switch (state->demod) { + case STV0900_DEMOD_1: + default: + reply->msg_len = 0; + + while ((stv0900_get_bits(i_params, F0900_P1_RX_END) != 1) && (i < 10)) { + msleep(10); + i++; + } + + if (stv0900_get_bits(i_params, F0900_P1_RX_END)) { + reply->msg_len = stv0900_get_bits(i_params, F0900_P1_FIFO_BYTENBR); + + for (i = 0; i < reply->msg_len; i++) + reply->msg[i] = stv0900_read_reg(i_params, R0900_P1_DISRXDATA); + } + break; + case STV0900_DEMOD_2: + reply->msg_len = 0; + + while ((stv0900_get_bits(i_params, F0900_P2_RX_END) != 1) && (i < 10)) { + msleep(10); + i++; + } + + if (stv0900_get_bits(i_params, F0900_P2_RX_END)) { + reply->msg_len = stv0900_get_bits(i_params, F0900_P2_FIFO_BYTENBR); + + for (i = 0; i < reply->msg_len; i++) + reply->msg[i] = stv0900_read_reg(i_params, R0900_P2_DISRXDATA); + } + break; + } + + return 0; +} + +static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + s32 mode_field, reset_field; + + dprintk(KERN_INFO "%s: %s\n", __func__, ((tone == 0) ? "Off" : "On")); + + dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); + dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); + + if (tone) { + /*Set the DiseqC mode to 22Khz continues tone*/ + stv0900_write_bits(i_params, mode_field, 0); + stv0900_write_bits(i_params, reset_field, 1); + /*release DiseqC reset to enable the 22KHz tone*/ + stv0900_write_bits(i_params, reset_field, 0); + } else { + stv0900_write_bits(i_params, mode_field, 0); + /*maintain the DiseqC reset to disable the 22KHz tone*/ + stv0900_write_bits(i_params, reset_field, 1); + } + + return 0; +} + +static void stv0900_release(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + + dprintk(KERN_INFO "%s\n", __func__); + + if ((--(state->internal->dmds_used)) <= 0) { + + dprintk(KERN_INFO "%s: Actually removing\n", __func__); + + remove_inode(state->internal); + kfree(state->internal); + } + + kfree(state); +} + +static struct dvb_frontend_ops stv0900_ops = { + + .info = { + .name = "STV0900 frontend", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | FE_CAN_QPSK | + FE_CAN_2G_MODULATION | + FE_CAN_FEC_AUTO + }, + .release = stv0900_release, + .init = stv0900_init, +#if 0 + .sleep = stv0900_sleep, +#endif + .get_frontend_algo = stv0900_frontend_algo, + .i2c_gate_ctrl = stv0900_i2c_gate_ctrl, + .diseqc_send_master_cmd = stv0900_send_master_cmd, + .diseqc_send_burst = stv0900_send_burst, + .diseqc_recv_slave_reply = stv0900_recv_slave_reply, + .set_tone = stv0900_set_tone, + .set_property = stb0900_set_property, + .get_property = stb0900_get_property, + .search = stv0900_search, + .track = stv0900_track, + .read_status = stv0900_read_status, + .read_ber = stv0900_read_ber, + .read_signal_strength = stv0900_read_signal_strength, + .read_snr = stv0900_read_snr, +}; + +struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, + struct i2c_adapter *i2c, + int demod) +{ + struct stv0900_state *state = NULL; + struct stv0900_init_params init_params; + enum fe_stv0900_error err_stv0900; + + state = kzalloc(sizeof(struct stv0900_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->demod = demod; + state->config = config; + state->i2c_adap = i2c; + + memcpy(&state->frontend.ops, &stv0900_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + switch (demod) { + case 0: + case 1: + init_params.dmd_ref_clk = config->xtal; + init_params.demod_mode = STV0900_DUAL; + init_params.rolloff = STV0900_35; + init_params.path1_ts_clock = config->path1_mode; + init_params.tun1_maddress = config->tun1_maddress; + init_params.tun1_iq_inversion = STV0900_IQ_NORMAL; + init_params.tuner1_adc = config->tun1_adc; + init_params.path2_ts_clock = config->path2_mode; + init_params.tun2_maddress = config->tun2_maddress; + init_params.tuner2_adc = config->tun2_adc; + init_params.tun2_iq_inversion = STV0900_IQ_SWAPPED; + + err_stv0900 = stv0900_init_internal(&state->frontend, + &init_params); + + if (err_stv0900) + goto error; + + dprintk(KERN_INFO "%s: Init Result = %d, handle_stv0900 = %x\n", + __func__, err_stv0900, (unsigned int)state->internal); + break; + default: + goto error; + break; + } + + dprintk("%s: Attaching STV0900 demodulator(%d) \n", __func__, demod); + return &state->frontend; + +error: + dprintk("%s: Failed to attach STV0900 demodulator(%d) \n", + __func__, demod); + kfree(state); + return NULL; +} +EXPORT_SYMBOL(stv0900_attach); + +MODULE_PARM_DESC(debug, "Set debug"); + +MODULE_AUTHOR("Igor M. Liplianin"); +MODULE_DESCRIPTION("ST STV0900 frontend"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From bb78046027a41288aaf2341c0e51f62e5fa8d143 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 16:55:20 +0200 Subject: Add support for ST STV0900 dual demodulator. From: Igor M. Liplianin Add last piece of code to support ST STV0900 dual demodulator. The IC consist of two dependent parts. It may use single or dual mode. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 2 + linux/drivers/media/dvb/frontends/stv0900_sw.c | 2847 ++++++++++++++++++++++++ 3 files changed, 2856 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/stv0900_sw.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index d3cfced2c..a7ea35590 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -90,6 +90,13 @@ config DVB_STV6110 help A DVB-S silicon tuner module. Say Y when you want to support this tuner. +config DVB_STV0900 + tristate "ST STV0900 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S/S2 demodulator. Say Y when you want to support this frontend. + config DVB_TDA8083 tristate "Philips TDA8083 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 1d180fc71..2231c6829 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -7,6 +7,7 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ s921-objs := s921_module.o s921_core.o stb0899-objs = stb0899_drv.o stb0899_algo.o +stv0900-objs = stv0900_core.o stv0900_sw.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o @@ -65,4 +66,5 @@ obj-$(CONFIG_DVB_STV0288) += stv0288.o obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_S921) += s921.o obj-$(CONFIG_DVB_STV6110) += stv6110.o +obj-$(CONFIG_DVB_STV0900) += stv0900.o diff --git a/linux/drivers/media/dvb/frontends/stv0900_sw.c b/linux/drivers/media/dvb/frontends/stv0900_sw.c new file mode 100644 index 000000000..a5a31536c --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv0900_sw.c @@ -0,0 +1,2847 @@ +/* + * stv0900_sw.c + * + * Driver for ST STV0900 satellite demodulator IC. + * + * Copyright (C) ST Microelectronics. + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * + * 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, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "stv0900.h" +#include "stv0900_reg.h" +#include "stv0900_priv.h" + +int stv0900_check_signal_presence(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + s32 carr_offset, + agc2_integr, + max_carrier; + + int no_signal; + + switch (demod) { + case STV0900_DEMOD_1: + default: + carr_offset = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8) + | stv0900_read_reg(i_params, + R0900_P1_CFR1); + carr_offset = ge2comp(carr_offset, 16); + agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) + | stv0900_read_reg(i_params, + R0900_P1_AGC2I0); + max_carrier = i_params->dmd1_srch_range / 1000; + break; + case STV0900_DEMOD_2: + carr_offset = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8) + | stv0900_read_reg(i_params, + R0900_P2_CFR1); + carr_offset = ge2comp(carr_offset, 16); + agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) + | stv0900_read_reg(i_params, + R0900_P2_AGC2I0); + max_carrier = i_params->dmd2_srch_range / 1000; + break; + } + + max_carrier += (max_carrier / 10); + max_carrier = 65536 * (max_carrier / 2); + max_carrier /= i_params->mclk / 1000; + if (max_carrier > 0x4000) + max_carrier = 0x4000; + + if ((agc2_integr > 0x2000) + || (carr_offset > + 2*max_carrier) + || (carr_offset < -2*max_carrier)) + no_signal = TRUE; + else + no_signal = FALSE; + + return no_signal; +} + +static void stv0900_get_sw_loop_params(struct stv0900_internal *i_params, + s32 *frequency_inc, s32 *sw_timeout, + s32 *steps, + enum fe_stv0900_demod_num demod) +{ + s32 timeout, freq_inc, max_steps, srate, max_carrier; + + enum fe_stv0900_search_standard standard; + + switch (demod) { + case STV0900_DEMOD_1: + default: + srate = i_params->dmd1_symbol_rate; + max_carrier = i_params->dmd1_srch_range / 1000; + max_carrier += max_carrier / 10; + standard = i_params->dmd1_srch_standard; + break; + case STV0900_DEMOD_2: + srate = i_params->dmd2_symbol_rate; + max_carrier = i_params->dmd2_srch_range / 1000; + max_carrier += max_carrier / 10; + standard = i_params->dmd2_srch_stndrd; + break; + } + + max_carrier = 65536 * (max_carrier / 2); + max_carrier /= i_params->mclk / 1000; + + if (max_carrier > 0x4000) + max_carrier = 0x4000; + + freq_inc = srate; + freq_inc /= i_params->mclk >> 10; + freq_inc = freq_inc << 6; + + switch (standard) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + freq_inc *= 3; + timeout = 20; + break; + case STV0900_SEARCH_DVBS2: + freq_inc *= 4; + timeout = 25; + break; + case STV0900_AUTO_SEARCH: + default: + freq_inc *= 3; + timeout = 25; + break; + } + + freq_inc /= 100; + + if ((freq_inc > max_carrier) || (freq_inc < 0)) + freq_inc = max_carrier / 2; + + timeout *= 27500; + + if (srate > 0) + timeout /= srate / 1000; + + if ((timeout > 100) || (timeout < 0)) + timeout = 100; + + max_steps = (max_carrier / freq_inc) + 1; + + if ((max_steps > 100) || (max_steps < 0)) { + max_steps = 100; + freq_inc = max_carrier / max_steps; + } + + *frequency_inc = freq_inc; + *sw_timeout = timeout; + *steps = max_steps; + +} + +static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, + s32 FreqIncr, s32 Timeout, int zigzag, + s32 MaxStep, enum fe_stv0900_demod_num demod) +{ + int no_signal, + lock = FALSE; + s32 stepCpt, + freqOffset, + max_carrier; + + switch (demod) { + case STV0900_DEMOD_1: + default: + max_carrier = i_params->dmd1_srch_range / 1000; + max_carrier += (max_carrier / 10); + break; + case STV0900_DEMOD_2: + max_carrier = i_params->dmd2_srch_range / 1000; + max_carrier += (max_carrier / 10); + break; + } + + max_carrier = 65536 * (max_carrier / 2); + max_carrier /= i_params->mclk / 1000; + + if (max_carrier > 0x4000) + max_carrier = 0x4000; + + if (zigzag == TRUE) + freqOffset = 0; + else + freqOffset = -max_carrier + FreqIncr; + + stepCpt = 0; + + do { + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, + (freqOffset / 256) & 0xFF); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, + freqOffset & 0xFF); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1); + + if (i_params->chip_id == 0x12) { + stv0900_write_bits(i_params, + F0900_P1_RST_HWARE, 1); + stv0900_write_bits(i_params, + F0900_P1_RST_HWARE, 0); + } + break; + case STV0900_DEMOD_2: + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, + (freqOffset / 256) & 0xFF); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, + freqOffset & 0xFF); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1); + + if (i_params->chip_id == 0x12) { + stv0900_write_bits(i_params, + F0900_P2_RST_HWARE, 1); + stv0900_write_bits(i_params, + F0900_P2_RST_HWARE, 0); + } + break; + } + + if (zigzag == TRUE) { + if (freqOffset >= 0) + freqOffset = -freqOffset - 2 * FreqIncr; + else + freqOffset = -freqOffset; + } else + freqOffset += + 2 * FreqIncr; + + stepCpt++; + lock = stv0900_get_demod_lock(i_params, demod, Timeout); + no_signal = stv0900_check_signal_presence(i_params, demod); + + } while ((lock == FALSE) + && (no_signal == FALSE) + && ((freqOffset - FreqIncr) < max_carrier) + && ((freqOffset + FreqIncr) > -max_carrier) + && (stepCpt < MaxStep)); + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0); + break; + case STV0900_DEMOD_2: + stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0); + break; + } + + return lock; +} + +int stv0900_sw_algo(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + int lock = FALSE; + + int no_signal, + zigzag; + s32 dvbs2_fly_wheel; + + s32 freqIncrement, softStepTimeout, trialCounter, max_steps; + + stv0900_get_sw_loop_params(i_params, &freqIncrement, &softStepTimeout, + &max_steps, demod); + switch (demod) { + case STV0900_DEMOD_1: + default: + switch (i_params->dmd1_srch_standard) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CARFREQ, + 0x3B); + else + stv0900_write_reg(i_params, R0900_P1_CARFREQ, + 0xef); + + stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x49); + zigzag = FALSE; + break; + case STV0900_SEARCH_DVBS2: + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CORRELABS, + 0x79); + else + stv0900_write_reg(i_params, R0900_P1_CORRELABS, + 0x68); + + stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, + 0x89); + + zigzag = TRUE; + break; + case STV0900_AUTO_SEARCH: + default: + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, + 0x3B); + stv0900_write_reg(i_params, R0900_P1_CORRELABS, + 0x79); + } else { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, + 0xef); + stv0900_write_reg(i_params, R0900_P1_CORRELABS, + 0x68); + } + + stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, + 0xc9); + zigzag = FALSE; + break; + } + + trialCounter = 0; + do { + lock = stv0900_search_carr_sw_loop(i_params, + freqIncrement, + softStepTimeout, + zigzag, + max_steps, + demod); + no_signal = stv0900_check_signal_presence(i_params, + demod); + trialCounter++; + if ((lock == TRUE) + || (no_signal == TRUE) + || (trialCounter == 2)) { + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, + R0900_P1_CARFREQ, + 0x49); + stv0900_write_reg(i_params, + R0900_P1_CORRELABS, + 0x9e); + } else { + stv0900_write_reg(i_params, + R0900_P1_CARFREQ, + 0xed); + stv0900_write_reg(i_params, + R0900_P1_CORRELABS, + 0x88); + } + + if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS2_FOUND)) { + msleep(softStepTimeout); + dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT); + + if (dvbs2_fly_wheel < 0xd) { + msleep(softStepTimeout); + dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT); + } + + if (dvbs2_fly_wheel < 0xd) { + lock = FALSE; + + if (trialCounter < 2) { + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x79); + else + stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x68); + + stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x89); + } + } + } + } + + } while ((lock == FALSE) + && (trialCounter < 2) + && (no_signal == FALSE)); + + break; + case STV0900_DEMOD_2: + switch (i_params->dmd2_srch_stndrd) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CARFREQ, + 0x3b); + else + stv0900_write_reg(i_params, R0900_P2_CARFREQ, + 0xef); + + stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, + 0x49); + zigzag = FALSE; + break; + case STV0900_SEARCH_DVBS2: + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CORRELABS, + 0x79); + else + stv0900_write_reg(i_params, R0900_P2_CORRELABS, + 0x68); + + stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89); + zigzag = TRUE; + break; + case STV0900_AUTO_SEARCH: + default: + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, + 0x3b); + stv0900_write_reg(i_params, R0900_P2_CORRELABS, + 0x79); + } else { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, + 0xef); + stv0900_write_reg(i_params, R0900_P2_CORRELABS, + 0x68); + } + + stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0xc9); + + zigzag = FALSE; + break; + } + + trialCounter = 0; + + do { + lock = stv0900_search_carr_sw_loop(i_params, + freqIncrement, + softStepTimeout, + zigzag, + max_steps, + demod); + no_signal = stv0900_check_signal_presence(i_params, + demod); + trialCounter++; + if ((lock == TRUE) + || (no_signal == TRUE) + || (trialCounter == 2)) { + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, + R0900_P2_CARFREQ, + 0x49); + stv0900_write_reg(i_params, + R0900_P2_CORRELABS, + 0x9e); + } else { + stv0900_write_reg(i_params, + R0900_P2_CARFREQ, + 0xed); + stv0900_write_reg(i_params, + R0900_P2_CORRELABS, + 0x88); + } + + if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS2_FOUND)) { + msleep(softStepTimeout); + dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT); + if (dvbs2_fly_wheel < 0xd) { + msleep(softStepTimeout); + dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT); + } + + if (dvbs2_fly_wheel < 0xd) { + lock = FALSE; + if (trialCounter < 2) { + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x79); + else + stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x68); + + stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89); + } + } + } + } + + } while ((lock == FALSE) && (trialCounter < 2) && (no_signal == FALSE)); + + break; + } + + return lock; +} + +static u32 stv0900_get_symbol_rate(struct stv0900_internal *i_params, + u32 mclk, + enum fe_stv0900_demod_num demod) +{ + s32 sfr_field3, sfr_field2, sfr_field1, sfr_field0, + rem1, rem2, intval1, intval2, srate; + + dmd_reg(sfr_field3, F0900_P1_SYMB_FREQ3, F0900_P2_SYMB_FREQ3); + dmd_reg(sfr_field2, F0900_P1_SYMB_FREQ2, F0900_P2_SYMB_FREQ2); + dmd_reg(sfr_field1, F0900_P1_SYMB_FREQ1, F0900_P2_SYMB_FREQ1); + dmd_reg(sfr_field0, F0900_P1_SYMB_FREQ0, F0900_P2_SYMB_FREQ0); + + srate = (stv0900_get_bits(i_params, sfr_field3) << 24) + + (stv0900_get_bits(i_params, sfr_field2) << 16) + + (stv0900_get_bits(i_params, sfr_field1) << 8) + + (stv0900_get_bits(i_params, sfr_field0)); + dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n", + srate, stv0900_get_bits(i_params, sfr_field0), + stv0900_get_bits(i_params, sfr_field1), + stv0900_get_bits(i_params, sfr_field2), + stv0900_get_bits(i_params, sfr_field3)); + + intval1 = (mclk) >> 16; + intval2 = (srate) >> 16; + + rem1 = (mclk) % 0x10000; + rem2 = (srate) % 0x10000; + srate = (intval1 * intval2) + + ((intval1 * rem2) >> 16) + + ((intval2 * rem1) >> 16); + + return srate; +} + +static void stv0900_set_symbol_rate(struct stv0900_internal *i_params, + u32 mclk, u32 srate, + enum fe_stv0900_demod_num demod) +{ + s32 sfr_init_reg; + u32 symb; + + dprintk(KERN_INFO "%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk, + srate, demod); + + dmd_reg(sfr_init_reg, R0900_P1_SFRINIT1, R0900_P2_SFRINIT1); + + if (srate > 60000000) { + symb = srate << 4; + symb /= (mclk >> 12); + } else if (srate > 6000000) { + symb = srate << 6; + symb /= (mclk >> 10); + } else { + symb = srate << 9; + symb /= (mclk >> 7); + } + + stv0900_write_reg(i_params, sfr_init_reg, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, sfr_init_reg + 1, (symb & 0xFF)); +} + +static void stv0900_set_max_symbol_rate(struct stv0900_internal *i_params, + u32 mclk, u32 srate, + enum fe_stv0900_demod_num demod) +{ + s32 sfr_max_reg; + u32 symb; + + dmd_reg(sfr_max_reg, R0900_P1_SFRUP1, R0900_P2_SFRUP1); + + srate = 105 * (srate / 100); + + if (srate > 60000000) { + symb = srate << 4; + symb /= (mclk >> 12); + } else if (srate > 6000000) { + symb = srate << 6; + symb /= (mclk >> 10); + } else { + symb = srate << 9; + symb /= (mclk >> 7); + } + + if (symb < 0x7fff) { + stv0900_write_reg(i_params, sfr_max_reg, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, sfr_max_reg + 1, (symb & 0xFF)); + } else { + stv0900_write_reg(i_params, sfr_max_reg, 0x7F); + stv0900_write_reg(i_params, sfr_max_reg + 1, 0xFF); + } +} + +static void stv0900_set_min_symbol_rate(struct stv0900_internal *i_params, + u32 mclk, u32 srate, + enum fe_stv0900_demod_num demod) +{ + s32 sfr_min_reg; + u32 symb; + + dmd_reg(sfr_min_reg, R0900_P1_SFRLOW1, R0900_P2_SFRLOW1); + + srate = 95 * (srate / 100); + if (srate > 60000000) { + symb = srate << 4; + symb /= (mclk >> 12); + + } else if (srate > 6000000) { + symb = srate << 6; + symb /= (mclk >> 10); + + } else { + symb = srate << 9; + symb /= (mclk >> 7); + } + + stv0900_write_reg(i_params, sfr_min_reg, (symb >> 8) & 0xFF); + stv0900_write_reg(i_params, sfr_min_reg + 1, (symb & 0xFF)); +} + +static s32 stv0900_get_timing_offst(struct stv0900_internal *i_params, + u32 srate, + enum fe_stv0900_demod_num demod) +{ + s32 tmgreg, + timingoffset; + + dmd_reg(tmgreg, R0900_P1_TMGREG2, R0900_P2_TMGREG2); + + timingoffset = (stv0900_read_reg(i_params, tmgreg) << 16) + + (stv0900_read_reg(i_params, tmgreg + 1) << 8) + + (stv0900_read_reg(i_params, tmgreg + 2)); + + timingoffset = ge2comp(timingoffset, 24); + + + if (timingoffset == 0) + timingoffset = 1; + + timingoffset = ((s32)srate * 10) / ((s32)0x1000000 / timingoffset); + timingoffset /= 320; + + return timingoffset; +} + +static void stv0900_set_dvbs2_rolloff(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + s32 rolloff, man_fld, matstr_reg, rolloff_ctl_fld; + + dmd_reg(man_fld, F0900_P1_MANUAL_ROLLOFF, F0900_P2_MANUAL_ROLLOFF); + dmd_reg(matstr_reg, R0900_P1_MATSTR1, R0900_P2_MATSTR1); + dmd_reg(rolloff_ctl_fld, F0900_P1_ROLLOFF_CONTROL, + F0900_P2_ROLLOFF_CONTROL); + + if (i_params->chip_id == 0x10) { + stv0900_write_bits(i_params, man_fld, 1); + rolloff = stv0900_read_reg(i_params, matstr_reg) & 0x03; + stv0900_write_bits(i_params, rolloff_ctl_fld, rolloff); + } else + stv0900_write_bits(i_params, man_fld, 0); +} + +static u32 stv0900_carrier_width(u32 srate, enum fe_stv0900_rolloff ro) +{ + u32 rolloff; + + switch (ro) { + case STV0900_20: + rolloff = 20; + break; + case STV0900_25: + rolloff = 25; + break; + case STV0900_35: + default: + rolloff = 35; + break; + } + + return srate + (srate * rolloff) / 100; +} + +static int stv0900_check_timing_lock(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + int timingLock = FALSE; + s32 i, + timingcpt = 0; + u8 carFreq, + tmgTHhigh, + tmgTHLow; + + switch (demod) { + case STV0900_DEMOD_1: + default: + carFreq = stv0900_read_reg(i_params, R0900_P1_CARFREQ); + tmgTHhigh = stv0900_read_reg(i_params, R0900_P1_TMGTHRISE); + tmgTHLow = stv0900_read_reg(i_params, R0900_P1_TMGTHFALL); + stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20); + stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x0); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + stv0900_write_reg(i_params, R0900_P1_RTC, 0x80); + stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x40); + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x0); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0x0); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0x0); + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x65); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + msleep(7); + + for (i = 0; i < 10; i++) { + if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2) + timingcpt++; + + msleep(1); + } + + if (timingcpt >= 3) + timingLock = TRUE; + + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); + stv0900_write_reg(i_params, R0900_P1_RTC, 0x88); + stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68); + stv0900_write_reg(i_params, R0900_P1_CARFREQ, carFreq); + stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, tmgTHhigh); + stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, tmgTHLow); + break; + case STV0900_DEMOD_2: + carFreq = stv0900_read_reg(i_params, R0900_P2_CARFREQ); + tmgTHhigh = stv0900_read_reg(i_params, R0900_P2_TMGTHRISE); + tmgTHLow = stv0900_read_reg(i_params, R0900_P2_TMGTHFALL); + stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20); + stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); + stv0900_write_reg(i_params, R0900_P2_RTC, 0x80); + stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x40); + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x0); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0x0); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0x0); + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x65); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + msleep(5); + for (i = 0; i < 10; i++) { + if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2) + timingcpt++; + + msleep(1); + } + + if (timingcpt >= 3) + timingLock = TRUE; + + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); + stv0900_write_reg(i_params, R0900_P2_RTC, 0x88); + stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68); + stv0900_write_reg(i_params, R0900_P2_CARFREQ, carFreq); + stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, tmgTHhigh); + stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, tmgTHLow); + break; + } + + return timingLock; +} + +static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, + s32 demod_timeout) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + int lock = FALSE; + s32 srate, search_range, locktimeout, + currier_step, nb_steps, current_step, + direction, tuner_freq, timeout; + + switch (demod) { + case STV0900_DEMOD_1: + default: + srate = i_params->dmd1_symbol_rate; + search_range = i_params->dmd1_srch_range; + break; + + case STV0900_DEMOD_2: + srate = i_params->dmd2_symbol_rate; + search_range = i_params->dmd2_srch_range; + break; + } + + if (srate >= 10000000) + locktimeout = demod_timeout / 3; + else + locktimeout = demod_timeout / 2; + + lock = stv0900_get_demod_lock(i_params, demod, locktimeout); + + if (lock == FALSE) { + if (srate >= 10000000) { + if (stv0900_check_timing_lock(i_params, demod) == TRUE) { + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); + break; + case STV0900_DEMOD_2: + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); + break; + } + + lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); + } else + lock = FALSE; + } else { + if (srate <= 4000000) + currier_step = 1000; + else if (srate <= 7000000) + currier_step = 2000; + else if (srate <= 10000000) + currier_step = 3000; + else + currier_step = 5000; + + nb_steps = ((search_range / 1000) / currier_step); + nb_steps /= 2; + nb_steps = (2 * (nb_steps + 1)); + if (nb_steps < 0) + nb_steps = 2; + else if (nb_steps > 12) + nb_steps = 12; + + current_step = 1; + direction = 1; + timeout = (demod_timeout / 3); + if (timeout > 1000) + timeout = 1000; + + switch (demod) { + case STV0900_DEMOD_1: + default: + if (lock == FALSE) { + tuner_freq = i_params->tuner1_freq; + i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + i_params->dmd1_symbol_rate; + + while ((current_step <= nb_steps) && (lock == FALSE)) { + + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); + + stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); + if (i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS2) { + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); + } + + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); + lock = stv0900_get_demod_lock(i_params, demod, timeout); + direction *= -1; + current_step++; + } + } + break; + case STV0900_DEMOD_2: + if (lock == FALSE) { + tuner_freq = i_params->tuner2_freq; + i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + srate; + + while ((current_step <= nb_steps) && (lock == FALSE)) { + + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); + + stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); + if (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS2) { + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); + } + + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); + lock = stv0900_get_demod_lock(i_params, demod, timeout); + direction *= -1; + current_step++; + } + } + break; + } + } + } + + return lock; +} + +static void stv0900_get_lock_timeout(s32 *demod_timeout, s32 *fec_timeout, + s32 srate, + enum fe_stv0900_search_algo algo) +{ + switch (algo) { + case STV0900_BLIND_SEARCH: + if (srate <= 1500000) { + (*demod_timeout) = 1500; + (*fec_timeout) = 400; + } else if (srate <= 5000000) { + (*demod_timeout) = 1000; + (*fec_timeout) = 300; + } else { + (*demod_timeout) = 700; + (*fec_timeout) = 100; + } + + break; + case STV0900_COLD_START: + case STV0900_WARM_START: + default: + if (srate <= 1000000) { + (*demod_timeout) = 3000; + (*fec_timeout) = 1700; + } else if (srate <= 2000000) { + (*demod_timeout) = 2500; + (*fec_timeout) = 1100; + } else if (srate <= 5000000) { + (*demod_timeout) = 1000; + (*fec_timeout) = 550; + } else if (srate <= 10000000) { + (*demod_timeout) = 700; + (*fec_timeout) = 250; + } else if (srate <= 20000000) { + (*demod_timeout) = 400; + (*fec_timeout) = 130; + } + + else { + (*demod_timeout) = 300; + (*fec_timeout) = 100; + } + + break; + + } + + if (algo == STV0900_WARM_START) + (*demod_timeout) /= 2; +} + +static void stv0900_set_viterbi_tracq(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + + s32 vth_reg; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); + + stv0900_write_reg(i_params, vth_reg++, 0xd0); + stv0900_write_reg(i_params, vth_reg++, 0x7d); + stv0900_write_reg(i_params, vth_reg++, 0x53); + stv0900_write_reg(i_params, vth_reg++, 0x2F); + stv0900_write_reg(i_params, vth_reg++, 0x24); + stv0900_write_reg(i_params, vth_reg++, 0x1F); +} + +static void stv0900_set_viterbi_standard(struct stv0900_internal *i_params, + enum fe_stv0900_search_standard Standard, + enum fe_stv0900_fec PunctureRate, + enum fe_stv0900_demod_num demod) +{ + + s32 fecmReg, + prvitReg; + + dprintk(KERN_INFO "%s: ViterbiStandard = ", __func__); + + switch (demod) { + case STV0900_DEMOD_1: + default: + fecmReg = R0900_P1_FECM; + prvitReg = R0900_P1_PRVIT; + break; + case STV0900_DEMOD_2: + fecmReg = R0900_P2_FECM; + prvitReg = R0900_P2_PRVIT; + break; + } + + switch (Standard) { + case STV0900_AUTO_SEARCH: + dprintk("Auto\n"); + stv0900_write_reg(i_params, fecmReg, 0x10); + stv0900_write_reg(i_params, prvitReg, 0x3F); + break; + case STV0900_SEARCH_DVBS1: + dprintk("DVBS1\n"); + stv0900_write_reg(i_params, fecmReg, 0x00); + switch (PunctureRate) { + case STV0900_FEC_UNKNOWN: + default: + stv0900_write_reg(i_params, prvitReg, 0x2F); + break; + case STV0900_FEC_1_2: + stv0900_write_reg(i_params, prvitReg, 0x01); + break; + case STV0900_FEC_2_3: + stv0900_write_reg(i_params, prvitReg, 0x02); + break; + case STV0900_FEC_3_4: + stv0900_write_reg(i_params, prvitReg, 0x04); + break; + case STV0900_FEC_5_6: + stv0900_write_reg(i_params, prvitReg, 0x08); + break; + case STV0900_FEC_7_8: + stv0900_write_reg(i_params, prvitReg, 0x20); + break; + } + + break; + case STV0900_SEARCH_DSS: + dprintk("DSS\n"); + stv0900_write_reg(i_params, fecmReg, 0x80); + switch (PunctureRate) { + case STV0900_FEC_UNKNOWN: + default: + stv0900_write_reg(i_params, prvitReg, 0x13); + break; + case STV0900_FEC_1_2: + stv0900_write_reg(i_params, prvitReg, 0x01); + break; + case STV0900_FEC_2_3: + stv0900_write_reg(i_params, prvitReg, 0x02); + break; + case STV0900_FEC_6_7: + stv0900_write_reg(i_params, prvitReg, 0x10); + break; + } + break; + default: + break; + } +} + +static void stv0900_track_optimization(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + s32 srate, pilots, aclc, freq1, freq0, + i = 0, timed, timef, blindTunSw = 0; + + enum fe_stv0900_rolloff rolloff; + enum fe_stv0900_modcode foundModcod; + + dprintk(KERN_INFO "%s\n", __func__); + + srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + srate += stv0900_get_timing_offst(i_params, srate, demod); + + switch (demod) { + case STV0900_DEMOD_1: + default: + switch (i_params->dmd1_rslts.standard) { + case STV0900_DVBS1_STANDARD: + if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) { + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + } + + stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff); + stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); + stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); + break; + case STV0900_DSS_STANDARD: + if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) { + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + } + + stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff); + stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); + stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); + break; + case STV0900_DVBS2_STANDARD: + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); + stv0900_write_reg(i_params, R0900_P1_ACLC, 0); + stv0900_write_reg(i_params, R0900_P1_BCLC, 0); + if (i_params->dmd1_rslts.frame_length == STV0900_LONG_FRAME) { + foundModcod = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD); + pilots = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01; + aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id); + if (foundModcod <= STV0900_QPSK_910) + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc); + else if (foundModcod <= STV0900_8PSK_910) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc); + } + + if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) { + if (foundModcod <= STV0900_16APSK_910) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc); + } else if (foundModcod <= STV0900_32APSK_910) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc); + } + } + + } else { + aclc = stv0900_get_optim_short_carr_loop(srate, i_params->dmd1_rslts.modulation, i_params->chip_id); + if (i_params->dmd1_rslts.modulation == STV0900_QPSK) + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc); + + else if (i_params->dmd1_rslts.modulation == STV0900_8PSK) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc); + } else if (i_params->dmd1_rslts.modulation == STV0900_16APSK) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc); + } else if (i_params->dmd1_rslts.modulation == STV0900_32APSK) { + stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc); + } + + } + + if (i_params->chip_id <= 0x11) { + if (i_params->demod_mode != STV0900_SINGLE) + stv0900_activate_s2_modcode(i_params, demod); + + } + + stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67); + break; + case STV0900_UNKNOWN_STANDARD: + default: + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); + break; + } + + freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2); + freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1); + rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS); + if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { + stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00); + stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); + stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); + stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod); + stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod); + blindTunSw = 1; + } + + if (i_params->chip_id >= 0x20) { + if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) { + stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0a); + stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x0); + } + } + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x08); + + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0x0A); + + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); + + if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd1_symbol_rate < 10000000)) { + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); + i_params->tuner1_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000; + + if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) { + if (i_params->dmd1_srch_algo != STV0900_WARM_START) + stv0900_set_bandwidth(fe, i_params->tuner1_bw); + } + + if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000)) + msleep(50); + else + msleep(5); + + stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START); + + if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) { + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + i = 0; + while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) { + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + i++; + } + } + + } + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49); + + if ((i_params->dmd1_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd1_rslts.standard == STV0900_DSS_STANDARD)) + stv0900_set_viterbi_tracq(i_params, demod); + + break; + + case STV0900_DEMOD_2: + switch (i_params->dmd2_rslts.standard) { + case STV0900_DVBS1_STANDARD: + + if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) { + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + } + + stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff); + stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); + stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); + break; + case STV0900_DSS_STANDARD: + if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) { + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + } + + stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff); + stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); + stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); + break; + case STV0900_DVBS2_STANDARD: + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); + stv0900_write_reg(i_params, R0900_P2_ACLC, 0); + stv0900_write_reg(i_params, R0900_P2_BCLC, 0); + if (i_params->dmd2_rslts.frame_length == STV0900_LONG_FRAME) { + foundModcod = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD); + pilots = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01; + aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id); + if (foundModcod <= STV0900_QPSK_910) + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc); + else if (foundModcod <= STV0900_8PSK_910) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc); + } + + if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) { + if (foundModcod <= STV0900_16APSK_910) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc); + } else if (foundModcod <= STV0900_32APSK_910) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc); + } + + } + + } else { + aclc = stv0900_get_optim_short_carr_loop(srate, + i_params->dmd2_rslts.modulation, + i_params->chip_id); + + if (i_params->dmd2_rslts.modulation == STV0900_QPSK) + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc); + + else if (i_params->dmd2_rslts.modulation == STV0900_8PSK) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc); + } else if (i_params->dmd2_rslts.modulation == STV0900_16APSK) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc); + } else if (i_params->dmd2_rslts.modulation == STV0900_32APSK) { + stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); + stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc); + } + } + + stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67); + + break; + case STV0900_UNKNOWN_STANDARD: + default: + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); + break; + } + + freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2); + freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1); + rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS); + if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { + stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00); + stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); + stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); + stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); + stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod); + stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod); + blindTunSw = 1; + } + + if (i_params->chip_id >= 0x20) { + if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) { + stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0a); + stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x0); + } + } + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x08); + + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0x0a); + + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); + if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd2_symbol_rate < 10000000)) { + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); + i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000; + + if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) { + if (i_params->dmd2_srch_algo != STV0900_WARM_START) + stv0900_set_bandwidth(fe, i_params->tuner2_bw); + } + + if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000)) + msleep(50); + else + msleep(5); + + stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START); + if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) { + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + i = 0; + while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) { + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + i++; + } + } + } + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49); + + if ((i_params->dmd2_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd2_rslts.standard == STV0900_DSS_STANDARD)) + stv0900_set_viterbi_tracq(i_params, demod); + + break; + } +} + +static int stv0900_get_fec_lock(struct stv0900_internal *i_params, enum fe_stv0900_demod_num demod, s32 time_out) +{ + s32 timer = 0, lock = 0, header_field, pktdelin_field, lock_vit_field; + + enum fe_stv0900_search_state dmd_state; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); + dmd_reg(pktdelin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK); + dmd_reg(lock_vit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT); + + dmd_state = stv0900_get_bits(i_params, header_field); + + while ((timer < time_out) && (lock == 0)) { + switch (dmd_state) { + case STV0900_SEARCH: + case STV0900_PLH_DETECTED: + default: + lock = 0; + break; + case STV0900_DVBS2_FOUND: + lock = stv0900_get_bits(i_params, pktdelin_field); + break; + case STV0900_DVBS_FOUND: + lock = stv0900_get_bits(i_params, lock_vit_field); + break; + } + + if (lock == 0) { + msleep(10); + timer += 10; + } + } + + if (lock) + dprintk("DEMOD FEC LOCK OK\n"); + else + dprintk("DEMOD FEC LOCK FAIL\n"); + + return lock; +} + +static int stv0900_wait_for_lock(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod, + s32 dmd_timeout, s32 fec_timeout) +{ + + s32 timer = 0, lock = 0, str_merg_rst_fld, str_merg_lock_fld; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(str_merg_rst_fld, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE); + dmd_reg(str_merg_lock_fld, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK); + + lock = stv0900_get_demod_lock(i_params, demod, dmd_timeout); + + if (lock) + lock = lock && stv0900_get_fec_lock(i_params, demod, fec_timeout); + + if (lock) { + lock = 0; + + dprintk(KERN_INFO "%s: Timer = %d, time_out = %d\n", __func__, timer, fec_timeout); + + while ((timer < fec_timeout) && (lock == 0)) { + lock = stv0900_get_bits(i_params, str_merg_lock_fld); + msleep(1); + timer++; + } + } + + if (lock) + dprintk(KERN_INFO "%s: DEMOD LOCK OK\n", __func__); + else + dprintk(KERN_INFO "%s: DEMOD LOCK FAIL\n", __func__); + + if (lock) + return TRUE; + else + return FALSE; +} + +enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, + enum fe_stv0900_demod_num demod) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_tracking_standard fnd_standard; + s32 state_field, + dss_dvb_field; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(state_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); + dmd_reg(dss_dvb_field, F0900_P1_DSS_DVB, F0900_P2_DSS_DVB); + + if (stv0900_get_bits(i_params, state_field) == 2) + fnd_standard = STV0900_DVBS2_STANDARD; + + else if (stv0900_get_bits(i_params, state_field) == 3) { + if (stv0900_get_bits(i_params, dss_dvb_field) == 1) + fnd_standard = STV0900_DSS_STANDARD; + else + fnd_standard = STV0900_DVBS1_STANDARD; + } else + fnd_standard = STV0900_UNKNOWN_STANDARD; + + return fnd_standard; +} + +static s32 stv0900_get_carr_freq(struct stv0900_internal *i_params, u32 mclk, + enum fe_stv0900_demod_num demod) +{ + s32 cfr_field2, cfr_field1, cfr_field0, + derot, rem1, rem2, intval1, intval2; + + dmd_reg(cfr_field2, F0900_P1_CAR_FREQ2, F0900_P2_CAR_FREQ2); + dmd_reg(cfr_field1, F0900_P1_CAR_FREQ1, F0900_P2_CAR_FREQ1); + dmd_reg(cfr_field0, F0900_P1_CAR_FREQ0, F0900_P2_CAR_FREQ0); + + derot = (stv0900_get_bits(i_params, cfr_field2) << 16) + + (stv0900_get_bits(i_params, cfr_field1) << 8) + + (stv0900_get_bits(i_params, cfr_field0)); + + derot = ge2comp(derot, 24); + intval1 = mclk >> 12; + intval2 = derot >> 12; + rem1 = mclk % 0x1000; + rem2 = derot % 0x1000; + derot = (intval1 * intval2) + + ((intval1 * rem2) >> 12) + + ((intval2 * rem1) >> 12); + + return derot; +} + +static u32 stv0900_get_tuner_freq(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + u32 frequency = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + + if (tuner_ops->get_frequency) { + if ((tuner_ops->get_frequency(fe, &frequency)) < 0) + dprintk("%s: Invalid parameter\n", __func__); + else + dprintk("%s: Frequency=%d\n", __func__, frequency); + + } + + return frequency; +} + +static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + s32 rate_fld, vit_curpun_fld; + enum fe_stv0900_fec prate; + + dmd_reg(vit_curpun_fld, F0900_P1_VIT_CURPUN, F0900_P2_VIT_CURPUN); + rate_fld = stv0900_get_bits(i_params, vit_curpun_fld); + + switch (rate_fld) { + case 13: + prate = STV0900_FEC_1_2; + break; + case 18: + prate = STV0900_FEC_2_3; + break; + case 21: + prate = STV0900_FEC_3_4; + break; + case 24: + prate = STV0900_FEC_5_6; + break; + case 25: + prate = STV0900_FEC_6_7; + break; + case 26: + prate = STV0900_FEC_7_8; + break; + default: + prate = STV0900_FEC_UNKNOWN; + break; + } + + return prate; +} + +static enum fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE; + s32 offsetFreq, + srate_offset, + i = 0; + + u8 timing; + + msleep(5); + switch (demod) { + case STV0900_DEMOD_1: + default: + if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { + timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2); + i = 0; + stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x5c); + + while ((i <= 50) && (timing != 0) && (timing != 0xFF)) { + timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2); + msleep(5); + i += 5; + } + } + + i_params->dmd1_rslts.standard = stv0900_get_standard(fe, demod); + i_params->dmd1_rslts.frequency = stv0900_get_tuner_freq(fe); + offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000; + i_params->dmd1_rslts.frequency += offsetFreq; + i_params->dmd1_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd1_rslts.symbol_rate, demod); + i_params->dmd1_rslts.symbol_rate += srate_offset; + i_params->dmd1_rslts.fec = stv0900_get_vit_fec(i_params, demod); + i_params->dmd1_rslts.modcode = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD); + i_params->dmd1_rslts.pilot = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01; + i_params->dmd1_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE)) >> 1; + i_params->dmd1_rslts.rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS); + switch (i_params->dmd1_rslts.standard) { + case STV0900_DVBS2_STANDARD: + i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_SPECINV_DEMOD); + if (i_params->dmd1_rslts.modcode <= STV0900_QPSK_910) + i_params->dmd1_rslts.modulation = STV0900_QPSK; + else if (i_params->dmd1_rslts.modcode <= STV0900_8PSK_910) + i_params->dmd1_rslts.modulation = STV0900_8PSK; + else if (i_params->dmd1_rslts.modcode <= STV0900_16APSK_910) + i_params->dmd1_rslts.modulation = STV0900_16APSK; + else if (i_params->dmd1_rslts.modcode <= STV0900_32APSK_910) + i_params->dmd1_rslts.modulation = STV0900_32APSK; + else + i_params->dmd1_rslts.modulation = STV0900_UNKNOWN; + break; + case STV0900_DVBS1_STANDARD: + case STV0900_DSS_STANDARD: + i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_IQINV); + i_params->dmd1_rslts.modulation = STV0900_QPSK; + break; + default: + break; + } + + if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000)) { + offsetFreq = i_params->dmd1_rslts.frequency - i_params->tuner1_freq; + i_params->tuner1_freq = stv0900_get_tuner_freq(fe); + if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500)) + range = STV0900_RANGEOK; + else + if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd1_rslts.symbol_rate, i_params->dmd1_rslts.rolloff) / 2000)) + range = STV0900_RANGEOK; + else + range = STV0900_OUTOFRANGE; + + } else { + if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500)) + range = STV0900_RANGEOK; + else + range = STV0900_OUTOFRANGE; + } + break; + case STV0900_DEMOD_2: + if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { + timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2); + i = 0; + stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x5c); + + while ((i <= 50) && (timing != 0) && (timing != 0xff)) { + timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2); + msleep(5); + i += 5; + } + } + + i_params->dmd2_rslts.standard = stv0900_get_standard(fe, demod); + i_params->dmd2_rslts.frequency = stv0900_get_tuner_freq(fe); + offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000; + i_params->dmd2_rslts.frequency += offsetFreq; + i_params->dmd2_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd2_rslts.symbol_rate, demod); + i_params->dmd2_rslts.symbol_rate += srate_offset; + i_params->dmd2_rslts.fec = stv0900_get_vit_fec(i_params, demod); + i_params->dmd2_rslts.modcode = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD); + i_params->dmd2_rslts.pilot = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01; + i_params->dmd2_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE)) >> 1; + i_params->dmd2_rslts.rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS); + switch (i_params->dmd2_rslts.standard) { + case STV0900_DVBS2_STANDARD: + i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_SPECINV_DEMOD); + if (i_params->dmd2_rslts.modcode <= STV0900_QPSK_910) + i_params->dmd2_rslts.modulation = STV0900_QPSK; + else if (i_params->dmd2_rslts.modcode <= STV0900_8PSK_910) + i_params->dmd2_rslts.modulation = STV0900_8PSK; + else if (i_params->dmd2_rslts.modcode <= STV0900_16APSK_910) + i_params->dmd2_rslts.modulation = STV0900_16APSK; + else if (i_params->dmd2_rslts.modcode <= STV0900_32APSK_910) + i_params->dmd2_rslts.modulation = STV0900_32APSK; + else + i_params->dmd2_rslts.modulation = STV0900_UNKNOWN; + break; + case STV0900_DVBS1_STANDARD: + case STV0900_DSS_STANDARD: + i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_IQINV); + i_params->dmd2_rslts.modulation = STV0900_QPSK; + break; + default: + break; + } + + if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000)) { + offsetFreq = i_params->dmd2_rslts.frequency - i_params->tuner2_freq; + i_params->tuner2_freq = stv0900_get_tuner_freq(fe); + + if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500)) + range = STV0900_RANGEOK; + else + if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd2_rslts.symbol_rate, i_params->dmd2_rslts.rolloff) / 2000)) + range = STV0900_RANGEOK; + else + range = STV0900_OUTOFRANGE; + } else { + if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500)) + range = STV0900_RANGEOK; + else + range = STV0900_OUTOFRANGE; + } + + break; + } + + return range; +} + +static enum fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + s32 srate, demod_timeout, + fec_timeout, freq1, freq0; + enum fe_stv0900_signal_type signal_type = STV0900_NODATA;; + + switch (demod) { + case STV0900_DEMOD_1: + default: + i_params->dmd1_rslts.locked = FALSE; + if (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) { + srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + srate += stv0900_get_timing_offst(i_params, srate, demod); + if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) + stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); + + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START); + freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2); + freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { + i_params->dmd1_rslts.locked = TRUE; + signal_type = stv0900_get_signal_params(fe); + stv0900_track_optimization(fe); + } else { + stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1c); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); + if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { + i_params->dmd1_rslts.locked = TRUE; + signal_type = stv0900_get_signal_params(fe); + stv0900_track_optimization(fe); + } + + } + + } else + i_params->dmd1_rslts.locked = FALSE; + + break; + case STV0900_DEMOD_2: + i_params->dmd2_rslts.locked = FALSE; + if (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) { + srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + srate += stv0900_get_timing_offst(i_params, srate, demod); + + if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) + stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); + + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START); + freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2); + freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); + stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + + if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { + i_params->dmd2_rslts.locked = TRUE; + signal_type = stv0900_get_signal_params(fe); + stv0900_track_optimization(fe); + } else { + stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1c); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); + + if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { + i_params->dmd2_rslts.locked = TRUE; + signal_type = stv0900_get_signal_params(fe); + stv0900_track_optimization(fe); + } + + } + + } else + i_params->dmd1_rslts.locked = FALSE; + + break; + } + + return signal_type; +} + +static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + u32 minagc2level = 0xffff, + agc2level, + init_freq, freq_step; + + s32 i, j, nb_steps, direction; + + dprintk(KERN_INFO "%s\n", __func__); + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); + stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1); + + stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83); + stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0); + + stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82); + stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0); + stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0); + + stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); + nb_steps = -1 + (i_params->dmd1_srch_range / 1000000); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; + + if (nb_steps < 0) + nb_steps = 1; + + direction = 1; + + freq_step = (1000000 << 8) / (i_params->mclk >> 8); + + init_freq = 0; + + for (i = 0; i < nb_steps; i++) { + if (direction > 0) + init_freq = init_freq + (freq_step * i); + else + init_freq = init_freq - (freq_step * i); + + direction *= -1; + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (init_freq >> 8) & 0xff); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, init_freq & 0xff); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x58); + msleep(10); + agc2level = 0; + + for (j = 0; j < 10; j++) + agc2level += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) + | stv0900_read_reg(i_params, R0900_P1_AGC2I0); + + agc2level /= 10; + + if (agc2level < minagc2level) + minagc2level = agc2level; + } + break; + case STV0900_DEMOD_2: + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); + stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1); + stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83); + stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0); + stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82); + stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0); + stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0); + stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); + nb_steps = -1 + (i_params->dmd2_srch_range / 1000000); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; + + if (nb_steps < 0) + nb_steps = 1; + + direction = 1; + freq_step = (1000000 << 8) / (i_params->mclk >> 8); + init_freq = 0; + for (i = 0; i < nb_steps; i++) { + if (direction > 0) + init_freq = init_freq + (freq_step * i); + else + init_freq = init_freq - (freq_step * i); + + direction *= -1; + + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (init_freq >> 8) & 0xff); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, init_freq & 0xff); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x58); + + msleep(10); + agc2level = 0; + for (j = 0; j < 10; j++) + agc2level += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) + | stv0900_read_reg(i_params, R0900_P2_AGC2I0); + + agc2level /= 10; + + if (agc2level < minagc2level) + minagc2level = agc2level; + } + break; + } + + return (u16)minagc2level; +} + +static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + int timingLock = FALSE; + s32 i, timingcpt = 0, + direction = 1, + nb_steps, + current_step = 0, + tuner_freq; + + u32 coarse_srate = 0, agc2_integr = 0, currier_step = 1200; + + switch (demod) { + case STV0900_DEMOD_1: + default: + stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1F); + stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0x12); + stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xf0); + stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xe0); + stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1); + stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83); + stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0); + stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82); + stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0); + stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0); + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x50); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x6a); + stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x95); + } else { + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); + stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x73); + } + + if (i_params->dmd1_symbol_rate <= 2000000) + currier_step = 1000; + else if (i_params->dmd1_symbol_rate <= 5000000) + currier_step = 2000; + else if (i_params->dmd1_symbol_rate <= 12000000) + currier_step = 3000; + else + currier_step = 5000; + + nb_steps = -1 + ((i_params->dmd1_srch_range / 1000) / currier_step); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; + + if (nb_steps < 0) + nb_steps = 1; + + else if (nb_steps > 10) { + nb_steps = 11; + currier_step = (i_params->dmd1_srch_range / 1000) / 10; + } + + current_step = 0; + + direction = 1; + tuner_freq = i_params->tuner1_freq; + + while ((timingLock == FALSE) && (current_step < nb_steps)) { + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5F); + stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x0); + + msleep(50); + + for (i = 0; i < 10; i++) { + if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2) + timingcpt++; + + agc2_integr += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) | stv0900_read_reg(i_params, R0900_P1_AGC2I0); + + } + + agc2_integr /= 10; + coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + current_step++; + direction *= -1; + + dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started. tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n", tuner_freq, agc2_integr, coarse_srate, timingcpt); + + if ((timingcpt >= 5) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000)) { + timingLock = TRUE; + } + + else if (current_step < nb_steps) { + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); + + stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw); + } + } + + if (timingLock == FALSE) + coarse_srate = 0; + else + coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + break; + case STV0900_DEMOD_2: + stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1F); + stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0x12); + stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xf0); + stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xe0); + stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1); + stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83); + stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0); + stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82); + stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0); + stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0); + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x50); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x6a); + stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x95); + } else { + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); + stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x73); + } + + if (i_params->dmd2_symbol_rate <= 2000000) + currier_step = 1000; + else if (i_params->dmd2_symbol_rate <= 5000000) + currier_step = 2000; + else if (i_params->dmd2_symbol_rate <= 12000000) + currier_step = 3000; + else + currier_step = 5000; + + + nb_steps = -1 + ((i_params->dmd2_srch_range / 1000) / currier_step); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; + + if (nb_steps < 0) + nb_steps = 1; + else if (nb_steps > 10) { + nb_steps = 11; + currier_step = (i_params->dmd2_srch_range / 1000) / 10; + } + + current_step = 0; + direction = 1; + tuner_freq = i_params->tuner2_freq; + + while ((timingLock == FALSE) && (current_step < nb_steps)) { + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5F); + stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x0); + + msleep(50); + timingcpt = 0; + + for (i = 0; i < 20; i++) { + if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2) + timingcpt++; + agc2_integr += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) + | stv0900_read_reg(i_params, R0900_P2_AGC2I0); + } + + agc2_integr /= 20; + coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + if ((timingcpt >= 10) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000)) + timingLock = TRUE; + else { + current_step++; + direction *= -1; + + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); + + stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw); + } + } + + if (timingLock == FALSE) + coarse_srate = 0; + else + coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + break; + } + + return coarse_srate; +} + +static u32 stv0900_search_srate_fine(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + u32 coarse_srate, + coarse_freq, + symb; + + coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + + switch (demod) { + case STV0900_DEMOD_1: + default: + coarse_freq = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8) + | stv0900_read_reg(i_params, R0900_P1_CFR1); + symb = 13 * (coarse_srate / 10); + + if (symb < i_params->dmd1_symbol_rate) + coarse_srate = 0; + else { + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); + stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20); + stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x00); + stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2); + stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49); + else + stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); + + if (coarse_srate > 3000000) { + symb = 13 * (coarse_srate / 10); + symb = (symb / 1000) * 65536; + symb /= (i_params->mclk / 1000); + stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF)); + + symb = 10 * (coarse_srate / 13); + symb = (symb / 1000) * 65536; + symb /= (i_params->mclk / 1000); + + stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF)); + + symb = (coarse_srate / 1000) * 65536; + symb /= (i_params->mclk / 1000); + stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF); + stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF)); + } else { + symb = 13 * (coarse_srate / 10); + symb = (symb / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF)); + + symb = 10 * (coarse_srate / 14); + symb = (symb / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF)); + + symb = (coarse_srate / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF); + stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF)); + } + + stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20); + stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (coarse_freq >> 8) & 0xff); + stv0900_write_reg(i_params, R0900_P1_CFRINIT0, coarse_freq & 0xff); + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); + } + break; + case STV0900_DEMOD_2: + coarse_freq = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8) + | stv0900_read_reg(i_params, R0900_P2_CFR1); + + symb = 13 * (coarse_srate / 10); + + if (symb < i_params->dmd2_symbol_rate) + coarse_srate = 0; + else { + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); + stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); + stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20); + stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0x00); + stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2); + stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49); + else + stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); + + if (coarse_srate > 3000000) { + symb = 13 * (coarse_srate / 10); + symb = (symb / 1000) * 65536; + symb /= (i_params->mclk / 1000); + stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF)); + + symb = 10 * (coarse_srate / 13); + symb = (symb / 1000) * 65536; + symb /= (i_params->mclk / 1000); + + stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF)); + + symb = (coarse_srate / 1000) * 65536; + symb /= (i_params->mclk / 1000); + stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF); + stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF)); + } else { + symb = 13 * (coarse_srate / 10); + symb = (symb / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF)); + + symb = 10 * (coarse_srate / 14); + symb = (symb / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F); + stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF)); + + symb = (coarse_srate / 100) * 65536; + symb /= (i_params->mclk / 100); + stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF); + stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF)); + } + + stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20); + stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (coarse_freq >> 8) & 0xff); + stv0900_write_reg(i_params, R0900_P2_CFRINIT0, coarse_freq & 0xff); + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); + } + + break; + } + + return coarse_srate; +} + +static int stv0900_blind_search_algo(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + u8 k_ref_tmg, k_ref_tmg_max, k_ref_tmg_min; + u32 coarse_srate; + int lock = FALSE, coarse_fail = FALSE; + s32 demod_timeout = 500, fec_timeout = 50, kref_tmg_reg, fail_cpt, i, agc2_overflow; + u16 agc2_integr; + u8 dstatus2; + + dprintk(KERN_INFO "%s\n", __func__); + + if (i_params->chip_id < 0x20) { + k_ref_tmg_max = 233; + k_ref_tmg_min = 143; + } else { + k_ref_tmg_max = 120; + k_ref_tmg_min = 30; + } + + agc2_integr = stv0900_blind_check_agc2_min_level(i_params, demod); + + if (agc2_integr > STV0900_BLIND_SEARCH_AGC2_TH) { + lock = FALSE; + + } else { + switch (demod) { + case STV0900_DEMOD_1: + default: + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xAA); + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55); + + stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xC4); + stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41); + stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41); + stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82); + stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0); + } + + kref_tmg_reg = R0900_P1_KREFTMG; + break; + case STV0900_DEMOD_2: + if (i_params->chip_id == 0x10) + stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xAA); + + if (i_params->chip_id < 0x20) + stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55); + + stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xC4); + stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41); + stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41); + stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82); + stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0); + } + + kref_tmg_reg = R0900_P2_KREFTMG; + break; + } + + k_ref_tmg = k_ref_tmg_max; + + do { + stv0900_write_reg(i_params, kref_tmg_reg, k_ref_tmg); + if (stv0900_search_srate_coarse(fe) != 0) { + coarse_srate = stv0900_search_srate_fine(fe); + + if (coarse_srate != 0) { + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, coarse_srate, STV0900_BLIND_SEARCH); + lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); + } else + lock = FALSE; + } else { + fail_cpt = 0; + agc2_overflow = 0; + + switch (demod) { + case STV0900_DEMOD_1: + default: + for (i = 0; i < 10; i++) { + agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) + | stv0900_read_reg(i_params, R0900_P1_AGC2I0); + + if (agc2_integr >= 0xff00) + agc2_overflow++; + + dstatus2 = stv0900_read_reg(i_params, R0900_P1_DSTATUS2); + + if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1)) + fail_cpt++; + } + break; + case STV0900_DEMOD_2: + for (i = 0; i < 10; i++) { + agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) + | stv0900_read_reg(i_params, R0900_P2_AGC2I0); + + if (agc2_integr >= 0xff00) + agc2_overflow++; + + dstatus2 = stv0900_read_reg(i_params, R0900_P2_DSTATUS2); + + if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1)) + fail_cpt++; + } + break; + } + + if ((fail_cpt > 7) || (agc2_overflow > 7)) + coarse_fail = TRUE; + + lock = FALSE; + } + k_ref_tmg -= 30; + } while ((k_ref_tmg >= k_ref_tmg_min) && (lock == FALSE) && (coarse_fail == FALSE)); + } + + return lock; +} + +static void stv0900_set_viterbi_acq(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + s32 vth_reg; + + dprintk(KERN_INFO "%s\n", __func__); + + dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); + + stv0900_write_reg(i_params, vth_reg++, 0x96); + stv0900_write_reg(i_params, vth_reg++, 0x64); + stv0900_write_reg(i_params, vth_reg++, 0x36); + stv0900_write_reg(i_params, vth_reg++, 0x23); + stv0900_write_reg(i_params, vth_reg++, 0x1E); + stv0900_write_reg(i_params, vth_reg++, 0x19); +} + +static void stv0900_set_search_standard(struct stv0900_internal *i_params, + enum fe_stv0900_demod_num demod) +{ + + int sstndrd; + + dprintk(KERN_INFO "%s\n", __func__); + + sstndrd = i_params->dmd1_srch_standard; + if (demod == 1) + sstndrd = i_params->dmd2_srch_stndrd; + + switch (sstndrd) { + case STV0900_SEARCH_DVBS1: + dprintk("Search Standard = DVBS1\n"); + break; + case STV0900_SEARCH_DSS: + dprintk("Search Standard = DSS\n"); + case STV0900_SEARCH_DVBS2: + break; + dprintk("Search Standard = DVBS2\n"); + case STV0900_AUTO_SEARCH: + default: + dprintk("Search Standard = AUTO\n"); + break; + } + + switch (demod) { + case STV0900_DEMOD_1: + default: + switch (i_params->dmd1_srch_standard) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + + stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0); + stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x22); + + stv0900_set_viterbi_acq(i_params, demod); + stv0900_set_viterbi_standard(i_params, + i_params->dmd1_srch_standard, + i_params->dmd1_fec, demod); + + break; + case STV0900_SEARCH_DVBS2: + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); + stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 1); + stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26); + if (i_params->demod_mode != STV0900_SINGLE) { + if (i_params->chip_id <= 0x11) + stv0900_stop_all_s2_modcod(i_params, demod); + else + stv0900_activate_s2_modcode(i_params, demod); + + } else + stv0900_activate_s2_modcode_single(i_params, demod); + + stv0900_set_viterbi_tracq(i_params, demod); + + break; + case STV0900_AUTO_SEARCH: + default: + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); + stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0); + stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26); + if (i_params->demod_mode != STV0900_SINGLE) { + if (i_params->chip_id <= 0x11) + stv0900_stop_all_s2_modcod(i_params, demod); + else + stv0900_activate_s2_modcode(i_params, demod); + + } else + stv0900_activate_s2_modcode_single(i_params, demod); + + if (i_params->dmd1_symbol_rate >= 2000000) + stv0900_set_viterbi_acq(i_params, demod); + else + stv0900_set_viterbi_tracq(i_params, demod); + + stv0900_set_viterbi_standard(i_params, i_params->dmd1_srch_standard, i_params->dmd1_fec, demod); + + break; + } + break; + case STV0900_DEMOD_2: + switch (i_params->dmd2_srch_stndrd) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0); + stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x22); + stv0900_set_viterbi_acq(i_params, demod); + stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod); + break; + case STV0900_SEARCH_DVBS2: + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); + stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 1); + stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26); + if (i_params->demod_mode != STV0900_SINGLE) + stv0900_activate_s2_modcode(i_params, demod); + else + stv0900_activate_s2_modcode_single(i_params, demod); + + stv0900_set_viterbi_tracq(i_params, demod); + break; + case STV0900_AUTO_SEARCH: + default: + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); + stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); + stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); + stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0); + stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); + stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); + stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26); + if (i_params->demod_mode != STV0900_SINGLE) + stv0900_activate_s2_modcode(i_params, demod); + else + stv0900_activate_s2_modcode_single(i_params, demod); + + if (i_params->dmd2_symbol_rate >= 2000000) + stv0900_set_viterbi_acq(i_params, demod); + else + stv0900_set_viterbi_tracq(i_params, demod); + + stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod); + + break; + } + + break; + } +} + +enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + s32 demod_timeout = 500, fec_timeout = 50, stream_merger_field; + + int lock = FALSE, low_sr = FALSE; + + enum fe_stv0900_signal_type signal_type = STV0900_NOCARRIER; + enum fe_stv0900_search_algo algo; + int no_signal = FALSE; + + dprintk(KERN_INFO "%s\n", __func__); + + switch (demod) { + case STV0900_DEMOD_1: + default: + algo = i_params->dmd1_srch_algo; + + stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1); + stream_merger_field = F0900_P1_RST_HWARE; + + stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C); + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x9e); + else + stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x88); + + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd1_symbol_rate, i_params->dmd1_srch_algo); + + if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { + i_params->tuner1_bw = 2 * 36000000; + + stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x00); + stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70); + + stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); + } else { + stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20); + stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2); + + if (i_params->dmd1_symbol_rate < 2000000) + stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x63); + else + stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70); + + stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0x5a); + + if (i_params->dmd1_srch_algo == STV0900_COLD_START) + i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10; + else if (i_params->dmd1_srch_algo == STV0900_WARM_START) + i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000; + } else { + stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0xc1); + i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10; + } + + stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); + + stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); + stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); + stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); + if (i_params->dmd1_symbol_rate >= 10000000) + low_sr = FALSE; + else + low_sr = TRUE; + + } + + stv0900_set_tuner(fe, i_params->tuner1_freq, i_params->tuner1_bw); + + stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, i_params->dmd1_srch_iq_inv); + stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); + + stv0900_set_search_standard(i_params, demod); + + if (i_params->dmd1_srch_algo != STV0900_BLIND_SEARCH) + stv0900_start_search(i_params, demod); + break; + case STV0900_DEMOD_2: + algo = i_params->dmd2_srch_algo; + + stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1); + + stream_merger_field = F0900_P2_RST_HWARE; + + stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C); + + if (i_params->chip_id >= 0x20) + stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x9e); + else + stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x88); + + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd2_symbol_rate, i_params->dmd2_srch_algo); + + if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { + i_params->tuner2_bw = 2 * 36000000; + + stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x00); + stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70); + + stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); + } else { + stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20); + stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2); + + if (i_params->dmd2_symbol_rate < 2000000) + stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x63); + else + stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70); + + if (i_params->dmd2_symbol_rate >= 10000000) + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); + else + stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x60); + + if (i_params->chip_id >= 0x20) { + stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0x5a); + + if (i_params->dmd2_srch_algo == STV0900_COLD_START) + i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate, + i_params->rolloff) + 10000000)) / 10; + else if (i_params->dmd2_srch_algo == STV0900_WARM_START) + i_params->tuner2_bw = stv0900_carrier_width(i_params->dmd2_symbol_rate, + i_params->rolloff) + 10000000; + } else { + stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0xc1); + i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate, + i_params->rolloff) + 10000000)) / 10; + } + + stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); + + stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); + stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); + stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); + if (i_params->dmd2_symbol_rate >= 10000000) + low_sr = FALSE; + else + low_sr = TRUE; + + } + + stv0900_set_tuner(fe, i_params->tuner2_freq, i_params->tuner2_bw); + + stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, i_params->dmd2_srch_iq_inv); + stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); + + stv0900_set_search_standard(i_params, demod); + + if (i_params->dmd2_srch_algo != STV0900_BLIND_SEARCH) + stv0900_start_search(i_params, demod); + break; + } + + if (i_params->chip_id == 0x12) { + stv0900_write_bits(i_params, stream_merger_field, 0); + msleep(3); + stv0900_write_bits(i_params, stream_merger_field, 1); + stv0900_write_bits(i_params, stream_merger_field, 0); + } + + if (algo == STV0900_BLIND_SEARCH) + lock = stv0900_blind_search_algo(fe); + else if (algo == STV0900_COLD_START) + lock = stv0900_get_demod_cold_lock(fe, demod_timeout); + else if (algo == STV0900_WARM_START) + lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); + + if ((lock == FALSE) && (algo == STV0900_COLD_START)) { + if (low_sr == FALSE) { + if (stv0900_check_timing_lock(i_params, demod) == TRUE) + lock = stv0900_sw_algo(i_params, demod); + } + } + + if (lock == TRUE) + signal_type = stv0900_get_signal_params(fe); + + if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) { + stv0900_track_optimization(fe); + if (i_params->chip_id <= 0x11) { + if ((stv0900_get_standard(fe, STV0900_DEMOD_1) == STV0900_DVBS1_STANDARD) && (stv0900_get_standard(fe, STV0900_DEMOD_2) == STV0900_DVBS1_STANDARD)) { + msleep(20); + stv0900_write_bits(i_params, stream_merger_field, 0); + } else { + stv0900_write_bits(i_params, stream_merger_field, 0); + msleep(3); + stv0900_write_bits(i_params, stream_merger_field, 1); + stv0900_write_bits(i_params, stream_merger_field, 0); + } + } else if (i_params->chip_id == 0x20) { + stv0900_write_bits(i_params, stream_merger_field, 0); + msleep(3); + stv0900_write_bits(i_params, stream_merger_field, 1); + stv0900_write_bits(i_params, stream_merger_field, 0); + } + + if (stv0900_wait_for_lock(i_params, demod, fec_timeout, fec_timeout) == TRUE) { + lock = TRUE; + switch (demod) { + case STV0900_DEMOD_1: + default: + i_params->dmd1_rslts.locked = TRUE; + if (i_params->dmd1_rslts.standard == STV0900_DVBS2_STANDARD) { + stv0900_set_dvbs2_rolloff(i_params, demod); + stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0x40); + stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0); + stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67); + } else { + stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); + } + + stv0900_write_reg(i_params, R0900_P1_FBERCPT4, 0); + stv0900_write_reg(i_params, R0900_P1_ERRCTRL2, 0xc1); + break; + case STV0900_DEMOD_2: + i_params->dmd2_rslts.locked = TRUE; + + if (i_params->dmd2_rslts.standard == STV0900_DVBS2_STANDARD) { + stv0900_set_dvbs2_rolloff(i_params, demod); + stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x60); + stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x20); + stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67); + } else { + stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); + } + + stv0900_write_reg(i_params, R0900_P2_FBERCPT4, 0); + + stv0900_write_reg(i_params, R0900_P2_ERRCTRL2, 0xc1); + break; + } + } else { + lock = FALSE; + signal_type = STV0900_NODATA; + no_signal = stv0900_check_signal_presence(i_params, demod); + + switch (demod) { + case STV0900_DEMOD_1: + default: + i_params->dmd1_rslts.locked = FALSE; + break; + case STV0900_DEMOD_2: + i_params->dmd2_rslts.locked = FALSE; + break; + } + } + } + + if ((signal_type == STV0900_NODATA) && (no_signal == FALSE)) { + switch (demod) { + case STV0900_DEMOD_1: + default: + if (i_params->chip_id <= 0x11) { + if ((stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) && + (i_params->dmd1_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST)) + signal_type = stv0900_dvbs1_acq_workaround(fe); + } else + i_params->dmd1_rslts.locked = FALSE; + + break; + case STV0900_DEMOD_2: + if (i_params->chip_id <= 0x11) { + if ((stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) && + (i_params->dmd2_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST)) + signal_type = stv0900_dvbs1_acq_workaround(fe); + } else + i_params->dmd2_rslts.locked = FALSE; + break; + } + } + + return signal_type; +} + -- cgit v1.2.3 From ef1ebf00be0fc71da604ae83054e10a99141adf7 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 17:06:09 +0200 Subject: Add support for NetUP Dual DVB-S2 CI card From: Igor M. Liplianin Add support for NetUP Dual DVB-S2 CI card The card based on cx23885 PCI-e bridge, CiMax SP2 Common Interface chips, STM lnbh24 LNB power chip, stv6110 tuners and stv0900 demodulator. http://www.linuxtv.org/wiki/index.php/NetUP_Dual_DVB_S2_CI Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/Kconfig | 1 + linux/drivers/media/video/cx23885/Makefile | 4 +- linux/drivers/media/video/cx23885/cx23885-cards.c | 53 +++++++++++ linux/drivers/media/video/cx23885/cx23885-core.c | 20 +++- linux/drivers/media/video/cx23885/cx23885-dvb.c | 106 +++++++++++++++++++++- linux/drivers/media/video/cx23885/cx23885-reg.h | 2 + linux/drivers/media/video/cx23885/cx23885.h | 3 + 7 files changed, 186 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 00f1e2e88..b62f16d50 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -16,6 +16,7 @@ config VIDEO_CX23885 select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select DVB_LNBP21 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/linux/drivers/media/video/cx23885/Makefile b/linux/drivers/media/video/cx23885/Makefile index 29c23b44c..ab8ea35c9 100644 --- a/linux/drivers/media/video/cx23885/Makefile +++ b/linux/drivers/media/video/cx23885/Makefile @@ -1,4 +1,6 @@ -cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o +cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ + cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ + netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index a8201ceaa..e6db78f8b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -28,6 +28,7 @@ #include "compat.h" #include "cx23885.h" #include "tuner-xc2028.h" +#include "netup-init.h" /* ------------------------------------------------------------------ */ /* board config info */ @@ -175,6 +176,12 @@ struct cx23885_board cx23885_boards[] = { .name = "DVBWorld DVB-S2 2005", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = { + .cimax = 1, + .name = "NetUP Dual DVB-S2 CI", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -270,6 +277,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0001, .subdevice = 0x2005, .card = CX23885_BOARD_DVBWORLD_2005, + }, { + .subvendor = 0x1b55, + .subdevice = 0x2a2c, + .card = CX23885_BOARD_NETUP_DUAL_DVBS2_CI, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -583,6 +594,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_write(MC417_OEN, 0x00001000); cx_write(MC417_RWD, 0x00001800); break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + /* GPIO-0 INTA from CiMax1 + GPIO-1 INTB from CiMax2 + GPIO-2 reset chips + GPIO-3 to GPIO-10 data/addr for CA + GPIO-11 ~CS0 to CiMax1 + GPIO-12 ~CS1 to CiMax2 + GPIO-13 ADL0 load LSB addr + GPIO-14 ADL1 load MSB addr + GPIO-15 ~RDY from CiMax + GPIO-17 ~RD to CiMax + GPIO-18 ~WR to CiMax + */ + cx_set(GP0_IO, 0x00040000); /* GPIO as out */ + /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */ + cx_clear(GP0_IO, 0x00030004); + mdelay(100);/* reset delay */ + cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */ + cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ + /* GPIO-15 IN as ~ACK, rest as OUT */ + cx_write(MC417_OEN, 0x00001000); + /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ + cx_write(MC417_RWD, 0x0000c300); + /* enable irq */ + cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ + break; } } @@ -670,6 +707,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: @@ -694,9 +739,17 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: request_module("cx25840"); break; } + + /* AUX-PLL 27MHz CLK */ + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + netup_initialize(dev); + break; + } } /* ------------------------------------------------------------------ */ diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 4f68156d2..6ae7ee247 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -32,6 +32,7 @@ #include #include "cx23885.h" +#include "cimax2.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -792,6 +793,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->pci_bus = dev->pci->bus->number; dev->pci_slot = PCI_SLOT(dev->pci->devfn); dev->pci_irqmask = 0x001f00; + if (cx23885_boards[dev->board].cimax > 0) + dev->pci_irqmask |= 0x01800000; /* for CiMaxes */ /* External Master 1 Bus */ dev->i2c_bus[0].nr = 0; @@ -1654,7 +1657,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) (pci_status & PCI_MSK_VID_B) || (pci_status & PCI_MSK_VID_A) || (pci_status & PCI_MSK_AUD_INT) || - (pci_status & PCI_MSK_AUD_EXT)) { + (pci_status & PCI_MSK_AUD_EXT) || + (pci_status & PCI_MSK_GPIO0) || + (pci_status & PCI_MSK_GPIO1)) { if (pci_status & PCI_MSK_RISC_RD) dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", @@ -1696,8 +1701,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n", PCI_MSK_AUD_EXT); + if (pci_status & PCI_MSK_GPIO0) + dprintk(7, " (PCI_MSK_GPIO0 0x%08x)\n", + PCI_MSK_GPIO0); + + if (pci_status & PCI_MSK_GPIO1) + dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", + PCI_MSK_GPIO1); } + if ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)) + /* handled += cx23885_irq_gpio(dev, pci_status); */ + handled += netup_ci_slot_status(dev, pci_status); + if (ts1_status) { if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) handled += cx23885_irq_ts(ts1, ts1_status); @@ -1770,6 +1786,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, } pci_set_drvdata(pci_dev, dev); + cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + return 0; fail_irq: diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 90dbf49ea..5529dcf6a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -31,6 +31,7 @@ #include "cx23885.h" #include +#include "dvb_ca_en50221.h" #include "s5h1409.h" #include "s5h1411.h" #include "mt2131.h" @@ -44,7 +45,13 @@ #include "dib7000p.h" #include "dibx000_common.h" #include "zl10353.h" +#include "stv0900.h" +#include "stv6110.h" +#include "lnbh24.h" #include "cx24116.h" +#include "cimax2.h" +#include "netup-eeprom.h" +#include "netup-init.h" static unsigned int debug; @@ -310,6 +317,31 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .no_tuner = 1, }; +static struct stv0900_config netup_stv0900_config = { + .demod_address = 0x68, + .xtal = 27000000, + .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ + .diseqc_mode = 2,/* 2/3 PWM */ + .path1_mode = 2,/*Serial continues clock */ + .path2_mode = 2,/*Serial continues clock */ + .tun1_maddress = 0,/* 0x60 */ + .tun2_maddress = 3,/* 0x63 */ + .tun1_adc = 1,/* 1 Vpp */ + .tun2_adc = 1,/* 1 Vpp */ +}; + +static struct stv6110_config netup_stv6110_tunerconfig_a = { + .i2c_address = 0x60, + .mclk = 27000000, + .iq_wiring = 0, +}; + +static struct stv6110_config netup_stv6110_tunerconfig_b = { + .i2c_address = 0x63, + .mclk = 27000000, + .iq_wiring = 1, +}; + static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct cx23885_tsport *port = fe->dvb->priv; @@ -341,6 +373,7 @@ static int dvb_register(struct cx23885_tsport *port) struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL; struct videobuf_dvb_frontend *fe0; + int ret; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); @@ -581,6 +614,51 @@ static int dvb_register(struct cx23885_tsport *port) &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + i2c_bus = &dev->i2c_bus[0]; + switch (port->nr) { + /* port B */ + case 1: + fe0->dvb.frontend = dvb_attach(stv0900_attach, + &netup_stv0900_config, + &i2c_bus->i2c_adap, 0); + if (fe0->dvb.frontend != NULL) { + if (dvb_attach(stv6110_attach, + fe0->dvb.frontend, + &netup_stv6110_tunerconfig_a, + &i2c_bus->i2c_adap)) { + if (!dvb_attach(lnbh24_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + LNBH24_PCL, 0, 0x09)) + printk(KERN_ERR + "No LNBH24 found!\n"); + + } + } + break; + /* port C */ + case 2: + fe0->dvb.frontend = dvb_attach(stv0900_attach, + &netup_stv0900_config, + &i2c_bus->i2c_adap, 1); + if (fe0->dvb.frontend != NULL) { + if (dvb_attach(stv6110_attach, + fe0->dvb.frontend, + &netup_stv6110_tunerconfig_b, + &i2c_bus->i2c_adap)) { + if (!dvb_attach(lnbh24_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + LNBH24_PCL, 0, 0x0a)) + printk(KERN_ERR + "No LNBH24 found!\n"); + + } + } + break; + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", @@ -602,9 +680,33 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ - return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, + ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0); + /* init CI & MAC */ + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { + static struct netup_card_info cinfo; + + netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); + memcpy(port->frontends.adapter.proposed_mac, + cinfo.port[port->nr - 1].mac, 6); + printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" + "%02X:%02X:%02X:%02X:%02X:%02X\n", + port->nr, + port->frontends.adapter.proposed_mac[0], + port->frontends.adapter.proposed_mac[1], + port->frontends.adapter.proposed_mac[2], + port->frontends.adapter.proposed_mac[3], + port->frontends.adapter.proposed_mac[4], + port->frontends.adapter.proposed_mac[5]); + + netup_ci_init(port); + break; + } + } + + return ret; } int cx23885_dvb_register(struct cx23885_tsport *port) @@ -677,6 +779,8 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port) if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); + netup_ci_exit(port); + return 0; } diff --git a/linux/drivers/media/video/cx23885/cx23885-reg.h b/linux/drivers/media/video/cx23885/cx23885-reg.h index 20b68a236..eafbe5226 100644 --- a/linux/drivers/media/video/cx23885/cx23885-reg.h +++ b/linux/drivers/media/video/cx23885/cx23885-reg.h @@ -212,6 +212,8 @@ Channel manager Data Structure entry = 20 DWORD #define DEV_CNTRL2 0x00040000 +#define PCI_MSK_GPIO1 (1 << 24) +#define PCI_MSK_GPIO0 (1 << 23) #define PCI_MSK_APB_DMA (1 << 12) #define PCI_MSK_AL_WR (1 << 11) #define PCI_MSK_AL_RD (1 << 10) diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index cae0a74bd..e8118c6bd 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -71,6 +71,7 @@ #define CX23885_BOARD_TBS_6920 14 #define CX23885_BOARD_TEVII_S470 15 #define CX23885_BOARD_DVBWORLD_2005 16 +#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ @@ -188,6 +189,7 @@ struct cx23885_board { */ u32 clk_freq; struct cx23885_input input[MAX_CX23885_INPUT]; + int cimax; /* for NetUP */ }; struct cx23885_subid { @@ -270,6 +272,7 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; + void *port_priv; }; struct cx23885_dev { -- cgit v1.2.3 From 831376e2cfb73403a9bba2be23e9c8ce1ec20c3b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 13:51:52 -0800 Subject: videodev: not possible to register NULL video_device From: Trent Piepho video_register_device_index() checks if it was passed a NULL video_device pointer (which isn't allowed) _after_ it has already dereferenced it with video_get_drvdata(vdev). The checks are clearly pointless and can be removed, as the function would have crashed before reaching them if vdev ever was NULL. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-dev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index e6dc1279a..861e3194f 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -404,12 +404,11 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, /* A minor value of -1 marks this video device as never having been registered */ - if (vdev) - vdev->minor = -1; + vdev->minor = -1; /* the release callback MUST be present */ - WARN_ON(!vdev || !vdev->release); - if (!vdev || !vdev->release) + WARN_ON(!vdev->release); + if (!vdev->release) return -EINVAL; /* Part 1: check device type */ -- cgit v1.2.3 From aaac79924970a2c688fa7cf89dc75fc3822460bc Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 13:52:57 -0800 Subject: cx88: remove unnecessary forward declaration of cx88_core From: Trent Piepho A recent patch added a forward declaration of cx88_core right before the main definition of that structure, which is obviously unneeded. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx88/cx88.h | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index d641c24c3..2227d93c7 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -306,7 +306,6 @@ struct cx88_dmaqueue { struct btcx_riscmem stopper; u32 count; }; -struct cx88_core; struct cx88_core { struct list_head devlist; -- cgit v1.2.3 From 66457790914e610bc7f372d47794cee4304ba959 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 13:53:13 -0800 Subject: compat: rename struct delayed_work to work_struct on pre-2.6.20 From: Trent Piepho In v2.6.19-rc6-118-g52bad64 struct work_struct was changed to be only for non-delayed work and struct delayed_work was created for delayed work. Instead of putting ifdefs in the drivers, we use compat.h to rename delayed_work to work_struct on pre-2.6.20 kernels. This will only be a problem if some driver decides to create identifiers named both work_struct and delayed_work in the same scope. There is one driver that has something named work_struct and none with anything named delayed_work, so I don't think will be a problem for as long as this compat code sticks around. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/b2c2/flexcop-pci.c | 4 ---- linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 4 ---- linux/drivers/media/radio/radio-si470x.c | 4 ---- linux/drivers/media/video/em28xx/em28xx.h | 4 ---- 4 files changed, 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index 5baf9ded9..2905ffccf 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -67,11 +67,7 @@ struct flexcop_pci { unsigned long last_irq; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct irq_check_work; -#else struct delayed_work irq_check_work; -#endif struct flexcop_device *fc_dev; }; diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index 72503e2da..1279046e0 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -364,11 +364,7 @@ struct dvb_usb_device { /* remote control */ struct input_dev *rc_input_dev; char rc_phys[64]; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct rc_query_work; -#else struct delayed_work rc_query_work; -#endif u32 last_event; int last_state; diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index b0a1e5832..a5ba4bf21 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -459,11 +459,7 @@ struct si470x_device { unsigned short registers[RADIO_REGISTER_NUM]; /* RDS receive buffer */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - struct work_struct work; -#else struct delayed_work work; -#endif wait_queue_head_t read_queue; struct mutex lock; /* buffer locking */ unsigned char *buffer; /* size is always multiple of three */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 235b63499..43c537e66 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -571,11 +571,7 @@ struct em28xx { /* Snapshot button */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - struct work_struct sbutton_query_work; -#else struct delayed_work sbutton_query_work; -#endif struct em28xx_dvb *dvb; }; -- cgit v1.2.3 From 076025d4e103147cbc6a8ad177824e15ff0143d9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 15:44:45 -0800 Subject: v4l2: Move code to zero querybuf output struct to v4l2_ioctl From: Trent Piepho For VIDIOC_QUERYBUF only the first two fields, size and type, are used as input. The rest can be filled in by the driver as output. Most drivers do not actually use all the field and unused ones should be zeroed out. Some drivers have code to do this and some drivers should but don't. So put some zero out code in v4l2_ioctl so that all drivers using that system get it. The drivers that have zeroing code get that code removed. Some drivers checked that the type field was valid, but v4l2_ioctl already does this so those checks can be removed as well. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/meye.c | 4 ---- linux/drivers/media/video/stk-webcam.c | 8 +------- linux/drivers/media/video/usbvision/usbvision-video.c | 3 --- linux/drivers/media/video/v4l2-ioctl.c | 5 +++++ linux/drivers/media/video/zoran/zoran_driver.c | 7 +------ 5 files changed, 7 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 323aa378b..0fd646f7c 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -1451,10 +1451,6 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) if (index < 0 || index >= gbuffers) return -EINVAL; - memset(buf, 0, sizeof(*buf)); - - buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->index = index; buf->bytesused = meye.grab_buffer[index].size; buf->flags = V4L2_BUF_FLAG_MAPPED; diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 3af084640..52bf877bf 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1140,16 +1140,10 @@ static int stk_vidioc_reqbufs(struct file *filp, static int stk_vidioc_querybuf(struct file *filp, void *priv, struct v4l2_buffer *buf) { - int index; struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - index = buf->index; - - if (index < 0 || index >= dev->n_sbufs) + if (buf->index < 0 || buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; *buf = sbuf->v4lbuf; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 33d79a5da..863fcb316 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -788,9 +788,6 @@ static int vidioc_querybuf (struct file *file, /* FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) */ - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } if(vb->index>=usbvision->num_frames) { return -EINVAL; } diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index ec139df5c..f2d74fedf 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -970,6 +970,11 @@ static long __video_do_ioctl(struct file *file, if (ret) break; + /* Zero out all fields starting with bytesysed, which is + * everything but index and type. */ + memset(0, &p->bytesused, + sizeof(*p) - offsetof(typeof(*p), bytesused)); + ret = ops->vidioc_querybuf(file, fh, p); if (!ret) dbgbuf(cmd, vfd, p); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 7ddbdf37d..8eda83b06 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2499,12 +2499,7 @@ static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - __u32 type = buf->type; - int index = buf->index, res; - - memset(buf, 0, sizeof(*buf)); - buf->type = type; - buf->index = index; + int res; mutex_lock(&zr->resource_lock); res = zoran_v4l2_buffer_status(file, buf, buf->index); -- cgit v1.2.3 From 5d9793798969b6929cf0f80edb77d8845b72f9ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 23:05:45 -0300 Subject: stv6110: remove a wrong include file From: Mauro Carvalho Chehab For sure a frontend doesn't need to include cx23885.h header. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stv6110.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv6110.c b/linux/drivers/media/dvb/frontends/stv6110.c index 94fd0fdae..70efac869 100644 --- a/linux/drivers/media/dvb/frontends/stv6110.c +++ b/linux/drivers/media/dvb/frontends/stv6110.c @@ -28,7 +28,6 @@ #include #include "stv6110.h" -#include "cx23885.h" static int debug; -- cgit v1.2.3 From 4f05fe5a173aafe4fd81efaa5a3288f2ab482ca1 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:02 -0800 Subject: videodev: only copy needed part of RW ioctl's parameter From: Trent Piepho There are many RW ioctls() in v4l2 where userspace only supplies one or two of the first fields in the structure passed to the ioctl. The driver then fills in the rest of the fields. Instead of copying the entire structure from userspace to the kernel we only need to copy those fields that userspace is actually supposed to supply. What's more, the fields that are meant to be only be output from the driver can be zeroed out in the videodev code, in case the driver doesn't fill them all in. Many of the ioctl handlers in v4l2_ioctl do this already, but my patch does this at one common point and so all the memsets for each ioctl can be deleted. For VIDIOC_G_SLICED_VBI_CAP, which has one input field ('type') and other output-only fields, the input field is near the end of the structure instead of at the beginning. So there is still a memset in it's ioctl handler to zero out the beginning of the struct. There were a couple mistakes with the existing code: For VIDIOC_G_AUDIO the index field was preserved, but G_AUDIO is a read only ioctl so nothing is copied from userspace to preserve. For VIDIOC_G_FREQUENCY the tuner field was not preserved like it should have been. This would be a problem if there was any hardware with more than one tuner/modulator. For VIDIOC_ENUM_FRAMESIZES and VIDIOC_ENUM_FRAMEINTERVALS, none of the fields were preserved even though each ioctl has several field that are supposed to be inputs to the driver! Obviously these ioctls don't get used much. The index field is needed if the driver has multiple discrete sizes/rates and other fields can be used too, e.g. if the size depends on pixel format or frame rate depends on image size for example. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-ioctl.c | 107 ++++++++++++++++----------------- 1 file changed, 52 insertions(+), 55 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index f2d74fedf..71e7633b5 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -727,16 +727,8 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *f = arg; - enum v4l2_buf_type type; - unsigned int index; - index = f->index; - type = f->type; - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = type; - - switch (type) { + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (ops->vidioc_enum_fmt_vid_cap) ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); @@ -773,8 +765,6 @@ static long __video_do_ioctl(struct file *file, { struct v4l2_format *f = (struct v4l2_format *)arg; - memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data)); - /* FIXME: Should be one dump per type */ dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); @@ -970,11 +960,6 @@ static long __video_do_ioctl(struct file *file, if (ret) break; - /* Zero out all fields starting with bytesysed, which is - * everything but index and type. */ - memset(0, &p->bytesused, - sizeof(*p) - offsetof(typeof(*p), bytesused)); - ret = ops->vidioc_querybuf(file, fh, p); if (!ret) dbgbuf(cmd, vfd, p); @@ -1160,12 +1145,9 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUMINPUT: { struct v4l2_input *p = arg; - int i = p->index; if (!ops->vidioc_enum_input) break; - memset(p, 0, sizeof(*p)); - p->index = i; ret = ops->vidioc_enum_input(file, fh, p); if (!ret) @@ -1204,12 +1186,9 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUMOUTPUT: { struct v4l2_output *p = arg; - int i = p->index; if (!ops->vidioc_enum_output) break; - memset(p, 0, sizeof(*p)); - p->index = i; ret = ops->vidioc_enum_output(file, fh, p); if (!ret) @@ -1385,13 +1364,11 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_AUDIO: { struct v4l2_audio *p = arg; - __u32 index = p->index; if (!ops->vidioc_g_audio) break; memset(p, 0, sizeof(*p)); - p->index = index; ret = ops->vidioc_g_audio(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " @@ -1486,15 +1463,10 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_CROP: { struct v4l2_crop *p = arg; - __u32 type; if (!ops->vidioc_g_crop) break; - type = p->type; - memset(p, 0, sizeof(*p)); - p->type = type; - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_g_crop(file, fh, p); if (!ret) @@ -1515,16 +1487,11 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_CROPCAP: { struct v4l2_cropcap *p = arg; - __u32 type; /*FIXME: Should also show v4l2_fract pixelaspect */ if (!ops->vidioc_cropcap) break; - type = p->type; - memset(p, 0, sizeof(*p)); - p->type = type; - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_cropcap(file, fh, p); if (!ret) { @@ -1582,7 +1549,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_encoder_cmd) break; - memset(&p->raw, 0, sizeof(p->raw)); ret = ops->vidioc_encoder_cmd(file, fh, p); if (!ret) dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); @@ -1594,7 +1560,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_try_encoder_cmd) break; - memset(&p->raw, 0, sizeof(p->raw)); ret = ops->vidioc_try_encoder_cmd(file, fh, p); if (!ret) dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); @@ -1603,10 +1568,6 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_PARM: { struct v4l2_streamparm *p = arg; - __u32 type = p->type; - - memset(p, 0, sizeof(*p)); - p->type = type; if (ops->vidioc_g_parm) { ret = ops->vidioc_g_parm(file, fh, p); @@ -1639,14 +1600,10 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *p = arg; - __u32 index = p->index; if (!ops->vidioc_g_tuner) break; - memset(p, 0, sizeof(*p)); - p->index = index; - ret = ops->vidioc_g_tuner(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, type=%d, " @@ -1683,8 +1640,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_frequency) break; - memset(p->reserved, 0, sizeof(p->reserved)); - ret = ops->vidioc_g_frequency(file, fh, p); if (!ret) dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", @@ -1705,12 +1660,13 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p = arg; - __u32 type = p->type; if (!ops->vidioc_g_sliced_vbi_cap) break; - memset(p, 0, sizeof(*p)); - p->type = type; + + /* Clear up to type, everything after type is zerod already */ + memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p); if (!ret) @@ -1783,8 +1739,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_enum_framesizes) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_enum_framesizes(file, fh, p); dbgarg(cmd, "index=%d, pixelformat=%d, type=%d ", @@ -1816,8 +1770,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_enum_frameintervals) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_enum_frameintervals(file, fh, p); dbgarg(cmd, "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ", @@ -1866,6 +1818,44 @@ static long __video_do_ioctl(struct file *file, return ret; } +/* In some cases, only a few fields are used as input, i.e. when the app sets + * "index" and then the driver fills in the rest of the structure for the thing + * with that index. We only need to copy up the first non-input field. */ +static unsigned long cmd_input_size(unsigned int cmd) +{ + /* Size of structure up to and including 'field' */ +#define CMDINSIZE(cmd, type, field) case _IOC_NR(VIDIOC_##cmd): return \ + offsetof(struct v4l2_##type, field) + \ + sizeof(((struct v4l2_##type *)0)->field); + + switch (_IOC_NR(cmd)) { + CMDINSIZE(ENUM_FMT, fmtdesc, type); + CMDINSIZE(G_FMT, format, type); + CMDINSIZE(QUERYBUF, buffer, type); + CMDINSIZE(G_PARM, streamparm, type); + CMDINSIZE(ENUMSTD, standard, index); + CMDINSIZE(ENUMINPUT, input, index); + CMDINSIZE(G_CTRL, control, id); + CMDINSIZE(G_TUNER, tuner, index); + CMDINSIZE(QUERYCTRL, queryctrl, id); + CMDINSIZE(QUERYMENU, querymenu, index); + CMDINSIZE(ENUMOUTPUT, output, index); + CMDINSIZE(G_MODULATOR, modulator, index); + CMDINSIZE(G_FREQUENCY, frequency, tuner); + CMDINSIZE(CROPCAP, cropcap, type); + CMDINSIZE(G_CROP, crop, type); + CMDINSIZE(ENUMAUDIO, audio, index); + CMDINSIZE(ENUMAUDOUT, audioout, index); + CMDINSIZE(ENCODER_CMD, encoder_cmd, flags); + CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags); + CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type); + CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format); + CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height); + default: + return _IOC_SIZE(cmd); + } +} + long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1902,9 +1892,16 @@ long video_ioctl2(struct file *file, } err = -EFAULT; - if (_IOC_DIR(cmd) & _IOC_WRITE) - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + if (_IOC_DIR(cmd) & _IOC_WRITE) { + unsigned long n = cmd_input_size(cmd); + + if (copy_from_user(parg, (void __user *)arg, n)) goto out; + + /* zero out anything we don't copy from userspace */ + if (n < _IOC_SIZE(cmd)) + memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); + } break; } -- cgit v1.2.3 From f848a016635d7ec5b7624ef9235b5a39ca0afee7 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:02 -0800 Subject: v4l2: Zero out read-only ioctls in one place From: Trent Piepho If an ioctl is read-only then the driver fills in all the fields. Lots of times drivers only care about some fields so it's best if video_ioctl2 takes care of zeroing out the entire structure before handing it to the driver. This saves code in each driver to do it and driver authors often forget. The existing memset code in some of the read-only ioctl handlers can be deleted. Convert a case statement to a single if statement. Deleted a debug line from ENUMAUDOUT that was copy-and-pasted to G_AUDOUT by mistake. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-ioctl.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 71e7633b5..90a58523b 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -656,8 +656,6 @@ static long __video_do_ioctl(struct file *file, if (cmd == VIDIOCGMBUF) { struct video_mbuf *p = arg; - memset(p, 0, sizeof(*p)); - if (!ops->vidiocgmbuf) return ret; ret = ops->vidiocgmbuf(file, fh, p); @@ -684,7 +682,6 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = (struct v4l2_capability *)arg; - memset(cap, 0, sizeof(*cap)); if (!ops->vidioc_querycap) break; @@ -1368,7 +1365,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_audio) break; - memset(p, 0, sizeof(*p)); ret = ops->vidioc_g_audio(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " @@ -1410,7 +1406,7 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_audout) break; - dbgarg(cmd, "Enum for index=%d\n", p->index); + ret = ops->vidioc_g_audout(file, fh, p); if (!ret) dbgarg2("index=%d, name=%s, capability=%d, " @@ -1507,8 +1503,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_jpegcomp) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_g_jpegcomp(file, fh, p); if (!ret) dbgarg(cmd, "quality=%d, APPn=%d, " @@ -1874,13 +1868,7 @@ long video_ioctl2(struct file *file, cmd == VIDIOC_TRY_EXT_CTRLS); /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = NULL; - break; - case _IOC_READ: - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): + if (_IOC_DIR(cmd) != _IOC_NONE) { if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { parg = sbuf; } else { @@ -1901,8 +1889,10 @@ long video_ioctl2(struct file *file, /* zero out anything we don't copy from userspace */ if (n < _IOC_SIZE(cmd)) memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); + } else { + /* read-only ioctl */ + memset(parg, 0, _IOC_SIZE(cmd)); } - break; } if (is_ext_ctrl) { -- cgit v1.2.3 From 524c72c90e185f6d07719ce31db5507dcf6bf85c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:02 -0800 Subject: v4l2: New function v4l2_video_std_frame_period From: Trent Piepho Some code was calling v4l2_video_std_construct() when all it cared about was the frame period. So make a function that just returns that and have v4l2_video_std_construct() use it. At this point there are no users of v4l2_video_std_construct() left outside of v4l2-ioctl, so it could be un-exported and made static. Change v4l2_video_std_construct() so that it doesn't zero out the struct v4l2_standard passed in. It's already been zeroed out in the common ioctl code. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/bt8xx/bttv-driver.c | 6 ++--- linux/drivers/media/video/v4l2-ioctl.c | 39 +++++++++++++-------------- 2 files changed, 20 insertions(+), 25 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index ab202761b..f95a4f811 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -2960,13 +2960,11 @@ static int bttv_g_parm(struct file *file, void *f, { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - struct v4l2_standard s; if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, - bttv_tvnorms[btv->tvnorm].name); - parm->parm.capture.timeperframe = s.frameperiod; + v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, + &parm->parm.capture.timeperframe); return 0; } diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 90a58523b..e079a343a 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -102,25 +102,27 @@ const char *v4l2_norm_to_name(v4l2_std_id id) } EXPORT_SYMBOL(v4l2_norm_to_name); +/* Returns frame period for the given standard */ +void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod) +{ + if (id & V4L2_STD_525_60) { + frameperiod->numerator = 1001; + frameperiod->denominator = 30000; + } else { + frameperiod->numerator = 1; + frameperiod->denominator = 25; + } +} +EXPORT_SYMBOL(v4l2_video_std_frame_period); + /* Fill in the fields of a v4l2_standard structure according to the 'id' and 'transmission' parameters. Returns negative on error. */ int v4l2_video_std_construct(struct v4l2_standard *vs, int id, const char *name) { - u32 index = vs->index; - - memset(vs, 0, sizeof(struct v4l2_standard)); - vs->index = index; - vs->id = id; - if (id & V4L2_STD_525_60) { - vs->frameperiod.numerator = 1001; - vs->frameperiod.denominator = 30000; - vs->framelines = 525; - } else { - vs->frameperiod.numerator = 1; - vs->frameperiod.denominator = 25; - vs->framelines = 625; - } + vs->id = id; + v4l2_video_std_frame_period(id, &vs->frameperiod); + vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625; strlcpy(vs->name, name, sizeof(vs->name)); return 0; } @@ -1077,7 +1079,6 @@ static long __video_do_ioctl(struct file *file, return -EINVAL; v4l2_video_std_construct(p, curr_id, descr); - p->index = index; dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, " "framelines=%d\n", p->index, @@ -1566,15 +1567,11 @@ static long __video_do_ioctl(struct file *file, if (ops->vidioc_g_parm) { ret = ops->vidioc_g_parm(file, fh, p); } else { - struct v4l2_standard s; - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_construct(&s, vfd->current_norm, - v4l2_norm_to_name(vfd->current_norm)); - - p->parm.capture.timeperframe = s.frameperiod; + v4l2_video_std_frame_period(vfd->current_norm, + &p->parm.capture.timeperframe); ret = 0; } -- cgit v1.2.3 From 32096c8cae65c6bb6388033e00b0d5e14c99d934 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: saa7146: some small fixes From: Trent Piepho vidioc_enum_fmt_vid_overlay() did nothing but call vidioc_enum_fmt_vid_cap(), so just make saa7146_video_ioctl_ops.vidioc_enum_fmt_vid_overlay point to vidioc_enum_fmt_vid_cap() and get ride of vidioc_enum_fmt_vid_overlay(). Have gparm use v4l2_video_std_frame_period to fill in the frame period instead of just assuming PAL. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/common/saa7146_video.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index b7d73b7fd..ace925134 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -577,11 +577,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd return 0; } -static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_fmtdesc *f) -{ - return vidioc_enum_fmt_vid_cap(file, fh, f); -} - static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) { const struct v4l2_queryctrl *ctrl; @@ -726,12 +721,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) static int vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm) { + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; parm->parm.capture.readbuffers = 1; - /* fixme: only for PAL! */ - parm->parm.capture.timeperframe.numerator = 1; - parm->parm.capture.timeperframe.denominator = 25; + v4l2_video_std_frame_period(vv->standard->id, + &parm->parm.capture.timeperframe); return 0; } @@ -1165,7 +1162,7 @@ static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -- cgit v1.2.3 From b8a69a37f416564efc1f148e4cfb3f5f95f30abb Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: bttv: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input and g_tuner. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/bt8xx/bttv-driver.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index f95a4f811..d34898f95 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1922,16 +1922,11 @@ static int bttv_enum_input(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - unsigned int n; + int n; - n = i->index; - - if (n >= bttv_tvcards[btv->c.type].video_inputs) + if (i->index >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - memset(i, 0, sizeof(*i)); - - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 1; @@ -2980,7 +2975,6 @@ static int bttv_g_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); - memset(t, 0, sizeof(*t)); t->rxsubchans = V4L2_TUNER_SUB_MONO; bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); strcpy(t->name, "Television"); @@ -3523,7 +3517,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (0 != t->index) return -EINVAL; mutex_lock(&btv->lock); - memset(t, 0, sizeof(*t)); strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; -- cgit v1.2.3 From 0b880887bafe743d82aa67082ad82110920fb23c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: cx88: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input and g_tuner. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx88/cx88-video.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index c8870cf06..005a78aab 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1514,15 +1514,12 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) [ CX88_VMUX_DVB ] = "DVB", [ CX88_VMUX_DEBUG ] = "for debug only", }; - unsigned int n; + unsigned int n = i->index; - n = i->index; if (n >= 4) return -EINVAL; if (0 == INPUT(n).type) return -EINVAL; - memset(i,0,sizeof(*i)); - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name,iname[INPUT(n).type]); if ((CX88_VMUX_TELEVISION == INPUT(n).type) || @@ -1787,7 +1784,6 @@ static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a) if (unlikely(a->index)) return -EINVAL; - memset(a,0,sizeof(*a)); strcpy(a->name,"Radio"); return 0; } -- cgit v1.2.3 From 50084efb689cde7d08726a091b683d97dd12ed75 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: stkwebcam: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_fmt_vid_cap, g_fmt_vid_cap, and g_parm. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/stk-webcam.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 52bf877bf..54efa2cc0 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -934,8 +934,6 @@ static int stk_vidioc_s_ctrl(struct file *filp, static int stk_vidioc_enum_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_fmtdesc *fmtd) { - fmtd->flags = 0; - switch (fmtd->index) { case 0: fmtd->pixelformat = V4L2_PIX_FMT_RGB565; @@ -993,7 +991,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp, pix_format->height = stk_sizes[i].h; pix_format->field = V4L2_FIELD_NONE; pix_format->colorspace = V4L2_COLORSPACE_SRGB; - pix_format->priv = 0; pix_format->pixelformat = dev->vsettings.palette; if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) pix_format->bytesperline = pix_format->width; @@ -1247,13 +1244,10 @@ static int stk_vidioc_g_parm(struct file *filp, if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - sp->parm.capture.capability = 0; - sp->parm.capture.capturemode = 0; /*FIXME This is not correct */ sp->parm.capture.timeperframe.numerator = 1; sp->parm.capture.timeperframe.denominator = 30; sp->parm.capture.readbuffers = 2; - sp->parm.capture.extendedmode = 0; return 0; } -- cgit v1.2.3 From 28109ada8c6cdc6b8fb51da8cbbb7506b9da0400 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: usbvision: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from g_audio, queryctrl, and enum_fmt_vid_cap. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/usbvision/usbvision-video.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 863fcb316..3d400e4b7 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -697,7 +697,6 @@ static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) { struct usb_usbvision *usbvision = video_drvdata(file); - memset(a,0,sizeof(*a)); if(usbvision->radio) { strcpy(a->name,"Radio"); } else { @@ -721,10 +720,6 @@ static int vidioc_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; call_all(usbvision, core, queryctrl, ctrl); @@ -926,11 +921,9 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { return -EINVAL; } - vfd->flags = 0; vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - memset(vfd->reserved, 0, sizeof(vfd->reserved)); return 0; } -- cgit v1.2.3 From 30469c2aeab5614b28a4de2d080481dc84f130da Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: gspca: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from g_audio, enum_input, g_parm and gmbuf. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/gspca/gspca.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 8d78b9287..d629ce1dc 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1111,7 +1111,6 @@ static int vidioc_s_audio(struct file *file, void *priv, static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *audio) { - memset(audio, 0, sizeof *audio); strcpy(audio->name, "Microphone"); return 0; } @@ -1145,7 +1144,6 @@ static int vidioc_enum_input(struct file *file, void *priv, if (input->index != 0) return -EINVAL; - memset(input, 0, sizeof *input); input->type = V4L2_INPUT_TYPE_CAMERA; strncpy(input->name, gspca_dev->sd_desc->name, sizeof input->name); @@ -1353,7 +1351,6 @@ static int vidioc_g_parm(struct file *filp, void *priv, { struct gspca_dev *gspca_dev = priv; - memset(parm, 0, sizeof *parm); parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm->parm.capture.readbuffers = gspca_dev->nbufread; @@ -1423,7 +1420,6 @@ static int vidiocgmbuf(struct file *file, void *priv, { struct v4l2_format fmt; - memset(&fmt, 0, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; i = gspca_dev->cam.nmodes - 1; /* highest mode */ fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width; -- cgit v1.2.3 From 0b0807ef7ebec0bda5074e9bb79aba86486ea728 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:21:03 -0800 Subject: meye: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from querycap, enum_input, enum_fmt_vid_cap, and g_fmt_vid_cap. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/meye.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 0fd646f7c..85b2cff1a 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -1022,7 +1022,6 @@ static int meyeioc_stilljcapt(int *len) static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, "meye"); strcpy(cap->card, "meye"); sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev)); @@ -1041,8 +1040,6 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) if (i->index != 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = 0; strcpy(i->name, "Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; @@ -1269,16 +1266,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index == 0) { /* standard YUV 422 capture */ - memset(f, 0, sizeof(*f)); - f->index = 0; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = 0; strcpy(f->description, "YUV422"); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ - memset(f, 0, sizeof(*f)); - f->index = 1; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "MJPEG"); @@ -1327,9 +1320,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: default: @@ -1346,8 +1336,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; return 0; } -- cgit v1.2.3 From 210d9c6ba2efaade3b8705c60b5fc7cbb01b513b Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 4 Mar 2009 16:40:31 +0300 Subject: Fix typo in lnbp21.c From: Igor M. Liplianin It was a typo in the function name, it should be lnbh24_attach, and not lnbp24_attach. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/lnbp21.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c index 772a0bbb0..1dcc56f32 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.c +++ b/linux/drivers/media/dvb/frontends/lnbp21.c @@ -138,7 +138,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, return fe; } -struct dvb_frontend *lnbp24_attach(struct dvb_frontend *fe, +struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear, u8 i2c_addr) { -- cgit v1.2.3 From 0fa648efd2bf50691105bf1ab24e4f1e20f12d5f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Feb 2009 15:35:15 +0000 Subject: Add support for Zarlink ZL10036 DVB-S tuner. From: Matthias Schwarzott This driver is based on initial work by Tino Reichardt and was heavily changed. The datasheet of the zl10036 can be found here and on other places on the net: http://www.mcmilk.de/projects/dvb-card/datasheets/ZL10036.pdf The zl10038 is similar to the zl10036, so it is maybe possible to write a common driver of necessary. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/zl10036.c | 519 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/zl10036.h | 53 +++ 4 files changed, 580 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/zl10036.c create mode 100644 linux/drivers/media/dvb/frontends/zl10036.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index a7ea35590..4059d22a1 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -55,6 +55,13 @@ config DVB_MT312 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_ZL10036 + tristate "Zarlink ZL10036 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 2231c6829..1e3866b2f 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o +obj-$(CONFIG_DVB_ZL10036) += zl10036.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o diff --git a/linux/drivers/media/dvb/frontends/zl10036.c b/linux/drivers/media/dvb/frontends/zl10036.c new file mode 100644 index 000000000..e22a0b381 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10036.c @@ -0,0 +1,519 @@ +/** + * Driver for Zarlink zl10036 DVB-S silicon tuner + * + * Copyright (C) 2006 Tino Reichardt + * Copyright (C) 2007-2009 Matthias Schwarzott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2, as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ** + * The data sheet for this tuner can be found at: + * http://www.mcmilk.de/projects/dvb-card/datasheets/ZL10036.pdf + * + * This one is working: (at my Avermedia DVB-S Pro) + * - zl10036 (40pin, FTA) + * + * A driver for zl10038 should be very similar. + */ + +#include +#include +#include + +#include "zl10036.h" + +static int zl10036_debug; +#define dprintk(level, args...) \ + do { if (zl10036_debug & level) printk(KERN_DEBUG "zl10036: " args); \ + } while (0) + +#define deb_info(args...) dprintk(0x01, args) +#define deb_i2c(args...) dprintk(0x02, args) + +struct zl10036_state { + struct i2c_adapter *i2c; + const struct zl10036_config *config; + u32 frequency; + u8 br, bf; +}; + + +/* This driver assumes the tuner is driven by a 10.111MHz Cristal */ +#define _XTAL 10111 + +/* Some of the possible dividers: + * 64, (write 0x05 to reg), freq step size 158kHz + * 10, (write 0x0a to reg), freq step size 1.011kHz (used here) + * 5, (write 0x09 to reg), freq step size 2.022kHz + */ + +#define _RDIV 10 +#define _RDIV_REG 0x0a +#define _FR (_XTAL/_RDIV) + +#define STATUS_POR 0x80 /* Power on Reset */ +#define STATUS_FL 0x40 /* Frequency & Phase Lock */ + +/* read/write for zl10036 and zl10038 */ + +static int zl10036_read_status_reg(struct zl10036_state *state) +{ + u8 status; + struct i2c_msg msg[1] = { + { .addr = state->config->tuner_address, .flags = I2C_M_RD, + .buf = &status, .len = sizeof(status) }, + }; + + if (i2c_transfer(state->i2c, msg, 1) != 1) { + printk(KERN_ERR "%s: i2c read failed at addr=%02x\n", + __func__, state->config->tuner_address); + return -EIO; + } + + deb_i2c("R(status): %02x [FL=%d]\n", status, + (status & STATUS_FL) ? 1 : 0); + if (status & STATUS_POR) + deb_info("%s: Power-On-Reset bit enabled - " + "need to initialize the tuner\n", __func__); + + return status; +} + +static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count) +{ + struct i2c_msg msg[1] = { + { .addr = state->config->tuner_address, .flags = 0, + .buf = buf, .len = count }, + }; + u8 reg = 0; + int ret; + + if (zl10036_debug & 0x02) { + /* every 8bit-value satisifes this! + * so only check for debug log */ + if ((buf[0] & 0x80) == 0x00) + reg = 2; + else if ((buf[0] & 0xc0) == 0x80) + reg = 4; + else if ((buf[0] & 0xf0) == 0xc0) + reg = 6; + else if ((buf[0] & 0xf0) == 0xd0) + reg = 8; + else if ((buf[0] & 0xf0) == 0xe0) + reg = 10; + else if ((buf[0] & 0xf0) == 0xf0) + reg = 12; + + deb_i2c("W(%d):", reg); + { + int i; + for (i = 0; i < count; i++) + printk(KERN_CONT " %02x", buf[i]); + printk(KERN_CONT "\n"); + } + } + + ret = i2c_transfer(state->i2c, msg, 1); + if (ret != 1) { + printk(KERN_ERR "%s: i2c error, ret=%d\n", __func__, ret); + return -EIO; + } + + return 0; +} + +static int zl10036_release(struct dvb_frontend *fe) +{ + struct zl10036_state *state = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(state); + + return 0; +} + +static int zl10036_sleep(struct dvb_frontend *fe) +{ + struct zl10036_state *state = fe->tuner_priv; + u8 buf[] = { 0xf0, 0x80 }; /* regs 12/13 */ + int ret; + + deb_info("%s\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = zl10036_write(state, buf, sizeof(buf)); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return ret; +} + +/** + * register map of the ZL10036/ZL10038 + * + * reg[default] content + * 2[0x00]: 0 | N14 | N13 | N12 | N11 | N10 | N9 | N8 + * 3[0x00]: N7 | N6 | N5 | N4 | N3 | N2 | N1 | N0 + * 4[0x80]: 1 | 0 | RFG | BA1 | BA0 | BG1 | BG0 | LEN + * 5[0x00]: P0 | C1 | C0 | R4 | R3 | R2 | R1 | R0 + * 6[0xc0]: 1 | 1 | 0 | 0 | RSD | 0 | 0 | 0 + * 7[0x20]: P1 | BF6 | BF5 | BF4 | BF3 | BF2 | BF1 | 0 + * 8[0xdb]: 1 | 1 | 0 | 1 | 0 | CC | 1 | 1 + * 9[0x30]: VSD | V2 | V1 | V0 | S3 | S2 | S1 | S0 + * 10[0xe1]: 1 | 1 | 1 | 0 | 0 | LS2 | LS1 | LS0 + * 11[0xf5]: WS | WH2 | WH1 | WH0 | WL2 | WL1 | WL0 | WRE + * 12[0xf0]: 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 + * 13[0x28]: PD | BR4 | BR3 | BR2 | BR1 | BR0 | CLR | TL + */ + +static int zl10036_set_frequency(struct zl10036_state *state, u32 frequency) +{ + u8 buf[2]; + u32 div, foffset; + + div = (frequency + _FR/2) / _FR; + state->frequency = div * _FR; + + foffset = frequency - state->frequency; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + + deb_info("%s: ftodo=%u fpriv=%u ferr=%d div=%u\n", __func__, + frequency, state->frequency, foffset, div); + + return zl10036_write(state, buf, sizeof(buf)); +} + +static int zl10036_set_bandwidth(struct zl10036_state *state, u32 fbw) +{ + /* fbw is measured in kHz */ + u8 br, bf; + int ret; + u8 buf_bf[] = { + 0xc0, 0x00, /* 6/7: rsd=0 bf=0 */ + }; + u8 buf_br[] = { + 0xf0, 0x00, /* 12/13: br=0xa clr=0 tl=0*/ + }; + u8 zl10036_rsd_off[] = { 0xc8 }; /* set RSD=1 */ + + /* ensure correct values */ + if (fbw > 35000) + fbw = 35000; + if (fbw < 8000) + fbw = 8000; + +#define _BR_MAXIMUM (_XTAL/575) /* _XTAL / 575kHz = 17 */ + + /* <= 28,82 MHz */ + if (fbw <= 28820) { + br = _BR_MAXIMUM; + } else { + /** + * f(bw)=34,6MHz f(xtal)=10.111MHz + * br = (10111/34600) * 63 * 1/K = 14; + */ + br = ((_XTAL * 21 * 1000) / (fbw * 419)); + } + + /* ensure correct values */ + if (br < 4) + br = 4; + if (br > _BR_MAXIMUM) + br = _BR_MAXIMUM; + + /* + * k = 1.257 + * bf = fbw/_XTAL * br * k - 1 */ + + bf = (fbw * br * 1257) / (_XTAL * 1000) - 1; + + /* ensure correct values */ + if (bf > 62) + bf = 62; + + buf_bf[1] = (bf << 1) & 0x7e; + buf_br[1] = (br << 2) & 0x7c; + deb_info("%s: BW=%d br=%u bf=%u\n", __func__, fbw, br, bf); + + if (br != state->br) { + ret = zl10036_write(state, buf_br, sizeof(buf_br)); + if (ret < 0) + return ret; + } + + if (bf != state->bf) { + ret = zl10036_write(state, buf_bf, sizeof(buf_bf)); + if (ret < 0) + return ret; + + /* time = br/(32* fxtal) */ + /* minimal sleep time to be calculated + * maximum br is 63 -> max time = 2 /10 MHz = 2e-7 */ + msleep(1); + + ret = zl10036_write(state, zl10036_rsd_off, + sizeof(zl10036_rsd_off)); + if (ret < 0) + return ret; + } + + state->br = br; + state->bf = bf; + + return 0; +} + +static int zl10036_set_gain_params(struct zl10036_state *state, + int c) +{ + u8 buf[2]; + u8 rfg, ba, bg; + + /* default values */ + rfg = 0; /* enable when using an lna */ + ba = 1; + bg = 1; + + /* reg 4 */ + buf[0] = 0x80 | ((rfg << 5) & 0x20) + | ((ba << 3) & 0x18) | ((bg << 1) & 0x06); + + if (!state->config->rf_loop_enable) + buf[0] |= 0x01; + + /* P0=0 */ + buf[1] = _RDIV_REG | ((c << 5) & 0x60); + + deb_info("%s: c=%u rfg=%u ba=%u bg=%u\n", __func__, c, rfg, ba, bg); + return zl10036_write(state, buf, sizeof(buf)); +} + +static int zl10036_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct zl10036_state *state = fe->tuner_priv; + int ret = 0; + u32 frequency = params->frequency; + u32 fbw; + int i; + u8 c; + + /* ensure correct values + * maybe redundant as core already checks this */ + if ((frequency < fe->ops.info.frequency_min) + || (frequency > fe->ops.info.frequency_max)) + return -EINVAL; + + /** + * alpha = 1.35 for dvb-s + * fBW = (alpha*symbolrate)/(2*0.8) + * 1.35 / (2*0.8) = 27 / 32 + */ + fbw = (27 * params->u.qpsk.symbol_rate) / 32; + + /* scale to kHz */ + fbw /= 1000; + + /* Add safe margin of 3MHz */ + fbw += 3000; + + /* setting the charge pump - guessed values */ + if (frequency < 950000) + return -EINVAL; + else if (frequency < 1250000) + c = 0; + else if (frequency < 1750000) + c = 1; + else if (frequency < 2175000) + c = 2; + else + return -EINVAL; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = zl10036_set_gain_params(state, c); + if (ret < 0) + goto error; + + ret = zl10036_set_frequency(state, params->frequency); + if (ret < 0) + goto error; + + ret = zl10036_set_bandwidth(state, fbw); + if (ret < 0) + goto error; + + /* wait for tuner lock - no idea if this is really needed */ + for (i = 0; i < 20; i++) { + ret = zl10036_read_status_reg(state); + if (ret < 0) + goto error; + + /* check Frequency & Phase Lock Bit */ + if (ret & STATUS_FL) + break; + + msleep(10); + } + +error: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return ret; +} + +static int zl10036_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct zl10036_state *state = fe->tuner_priv; + + *frequency = state->frequency; + + return 0; +} + +static int zl10036_init_regs(struct zl10036_state *state) +{ + int ret; + int i; + + /* could also be one block from reg 2 to 13 and additional 10/11 */ + u8 zl10036_init_tab[][2] = { + { 0x04, 0x00 }, /* 2/3: div=0x400 - arbitrary value */ + { 0x8b, _RDIV_REG }, /* 4/5: rfg=0 ba=1 bg=1 len=? */ + /* p0=0 c=0 r=_RDIV_REG */ + { 0xc0, 0x20 }, /* 6/7: rsd=0 bf=0x10 */ + { 0xd3, 0x40 }, /* 8/9: from datasheet */ + { 0xe3, 0x5b }, /* 10/11: lock window level */ + { 0xf0, 0x28 }, /* 12/13: br=0xa clr=0 tl=0*/ + { 0xe3, 0xf9 }, /* 10/11: unlock window level */ + }; + + /* invalid values to trigger writing */ + state->br = 0xff; + state->bf = 0xff; + + if (!state->config->rf_loop_enable) + zl10036_init_tab[1][2] |= 0x01; + + deb_info("%s\n", __func__); + + for (i = 0; i < ARRAY_SIZE(zl10036_init_tab); i++) { + ret = zl10036_write(state, zl10036_init_tab[i], 2); + if (ret < 0) + return ret; + } + + return 0; +} + +static int zl10036_init(struct dvb_frontend *fe) +{ + struct zl10036_state *state = fe->tuner_priv; + int ret = 0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = zl10036_read_status_reg(state); + if (ret < 0) + return ret; + + /* Only init if Power-on-Reset bit is set? */ + ret = zl10036_init_regs(state); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return ret; +} + +static struct dvb_tuner_ops zl10036_tuner_ops = { + .info = { + .name = "Zarlink ZL10036", + .frequency_min = 950000, + .frequency_max = 2175000 + }, + .init = zl10036_init, + .release = zl10036_release, + .sleep = zl10036_sleep, + .set_params = zl10036_set_params, + .get_frequency = zl10036_get_frequency, +}; + +struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, + const struct zl10036_config *config, + struct i2c_adapter *i2c) +{ + struct zl10036_state *state = NULL; + int ret; + + if (NULL == config) { + printk(KERN_ERR "%s: no config specified", __func__); + goto error; + } + + state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL); + if (NULL == state) + return NULL; + + state->config = config; + state->i2c = i2c; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = zl10036_read_status_reg(state); + if (ret < 0) { + printk(KERN_ERR "%s: No zl10036 found\n", __func__); + goto error; + } + + ret = zl10036_init_regs(state); + if (ret < 0) { + printk(KERN_ERR "%s: tuner initialization failed\n", + __func__); + goto error; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + fe->tuner_priv = state; + + memcpy(&fe->ops.tuner_ops, &zl10036_tuner_ops, + sizeof(struct dvb_tuner_ops)); + printk(KERN_INFO "%s: tuner initialization (%s addr=0x%02x) ok\n", + __func__, fe->ops.tuner_ops.info.name, config->tuner_address); + + return fe; + +error: + zl10036_release(fe); + return NULL; +} +EXPORT_SYMBOL(zl10036_attach); + +module_param_named(debug, zl10036_debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_DESCRIPTION("DVB ZL10036 driver"); +MODULE_AUTHOR("Tino Reichardt"); +MODULE_AUTHOR("Matthias Schwarzott"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/zl10036.h b/linux/drivers/media/dvb/frontends/zl10036.h new file mode 100644 index 000000000..d84b8f821 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10036.h @@ -0,0 +1,53 @@ +/** + * Driver for Zarlink ZL10036 DVB-S silicon tuner + * + * Copyright (C) 2006 Tino Reichardt + * Copyright (C) 2007-2009 Matthias Schwarzott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2, as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef DVB_ZL10036_H +#define DVB_ZL10036_H + +#include +#include "dvb_frontend.h" + +/** + * Attach a zl10036 tuner to the supplied frontend structure. + * + * @param fe Frontend to attach to. + * @param config zl10036_config structure + * @return FE pointer on success, NULL on failure. + */ + +struct zl10036_config { + u8 tuner_address; + int rf_loop_enable; +}; + +#if defined(CONFIG_DVB_ZL10036) || \ + (defined(CONFIG_DVB_ZL10036_MODULE) && defined(MODULE)) +extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, + const struct zl10036_config *config, struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, + const struct zl10036_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* DVB_ZL10036_H */ -- cgit v1.2.3 From 5fae8b27610dafee725094ed65fe0d6d7b455c77 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Feb 2009 15:35:16 +0000 Subject: saa7134: add DVB support for Avermedia A700 cards From: Matthias Schwarzott Add DVB support for Avermedia DVB-S Pro and Avermedia DVB-S Hybrid+FM card both labled A700. They use zl10313 demod (driver mt312) and zl10036 tuner. Signed-off-by: Matthias Schwarzott [mchehab@redhat.com: change __FUNCTION__ into __func__] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/Kconfig | 2 ++ linux/drivers/media/video/saa7134/saa7134-cards.c | 16 ++++++-------- linux/drivers/media/video/saa7134/saa7134-dvb.c | 27 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index fc2164e28..a3470ebad 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -37,6 +37,8 @@ config VIDEO_SAA7134_DVB select DVB_ISL6421 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select DVB_ZL10036 if !DVB_FE_CUSTOMISE + select DVB_MT312 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 9db045cf5..4697a6e48 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4460,8 +4460,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - /* no DVB support for now */ - /* .mpeg = SAA7134_MPEG_DVB, */ + .mpeg = SAA7134_MPEG_DVB, .inputs = { { .name = name_comp, .vmux = 1, @@ -4480,8 +4479,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - /* no DVB support for now */ - /* .mpeg = SAA7134_MPEG_DVB, */ + .mpeg = SAA7134_MPEG_DVB, .inputs = { { .name = name_comp, .vmux = 1, @@ -6187,15 +6185,15 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x8c040007, 0x8c040007); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); break; - case SAA7134_BOARD_AVERMEDIA_A700_PRO: case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: - /* write windows gpio values */ - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); printk("%s: %s: hybrid analog/dvb card\n" - "%s: Sorry, only analog s-video and composite input " + "%s: Sorry, of the analog inputs, only analog s-video and composite " "are supported for now.\n", dev->name, card(dev).name, dev->name); + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + /* write windows gpio values */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); break; } return 0; diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 27a4d9c83..7745cad95 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -51,6 +51,9 @@ #include "zl10353.h" +#include "zl10036.h" +#include "mt312.h" + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -949,6 +952,17 @@ static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, }; +/* ------------------------------------------------------------------ */ + +static struct mt312_config avertv_a700_mt312 = { + .demod_address = 0x0e, + .voltage_inverted = 1, +}; + +static struct zl10036_config avertv_a700_tuner = { + .tuner_address = 0x60, +}; + /* ================================================================== * Core code */ @@ -1379,6 +1393,19 @@ static int dvb_init(struct saa7134_dev *dev) TUNER_PHILIPS_FMD1216ME_MK3); } break; + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: + /* Zarlink ZL10313 */ + fe0->dvb.frontend = dvb_attach(mt312_attach, + &avertv_a700_mt312, &dev->i2c_adap); + if (fe0->dvb.frontend) { + if (dvb_attach(zl10036_attach, fe0->dvb.frontend, + &avertv_a700_tuner, &dev->i2c_adap) == NULL) { + wprintk("%s: No zl10036 found!\n", + __func__); + } + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; -- cgit v1.2.3 From f4bd480875638f4aaf6bc024079544e5b281e68b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Feb 2009 17:51:43 +0000 Subject: Add "Sony PlayTV" to dibcom driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: sebastian.blanes@gmail.com This patch introduces support for DVB-T for the following dibcom based card: Sony PlayTV (USB-ID: 1415:0003) Signed-off-by: Sebastián Blanes CC: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index f291fb55f..95582aeaf 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1419,6 +1419,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, + { USB_DEVICE(USB_VID_SONY, USB_PID_SONY_PLAYTV) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1684,7 +1685,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { } }, - .num_device_descs = 5, + .num_device_descs = 6, .devices = { { "DiBcom STK7070PD reference design", { &dib0700_usb_id_table[17], NULL }, @@ -1705,6 +1706,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Terratec Cinergy DT USB XS Diversity", { &dib0700_usb_id_table[43], NULL }, { NULL }, + }, + { "Sony PlayTV", + { &dib0700_usb_id_table[44], NULL }, + { NULL }, } }, .rc_interval = DEFAULT_RC_INTERVAL, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4ab5ec9a0..748d8dc38 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -55,6 +55,7 @@ #define USB_VID_GIGABYTE 0x1044 #define USB_VID_YUAN 0x1164 #define USB_VID_XTENSIONS 0x1ae7 +#define USB_VID_SONY 0x1415 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -237,5 +238,6 @@ #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 +#define USB_PID_SONY_PLAYTV 0x0003 #endif -- cgit v1.2.3 From d9886b0adc863fecca0c9fb09961cf056a0aa205 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Feb 2009 13:31:41 +0000 Subject: Add ids for Yuan PD378S DVB adapter From: Pascal Terjan Signed-off-by: Arnaud Patard Signed-off-by: Pascal Terjan CC: Patrick Boettcher [mchehab@redhat.com: Fixed a small merge conflict] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 95582aeaf..80744f44e 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1420,6 +1420,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, { USB_DEVICE(USB_VID_SONY, USB_PID_SONY_PLAYTV) }, +/* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1619,7 +1620,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 9, + .num_device_descs = 10, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1657,6 +1658,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[33], NULL }, { NULL }, }, + { "Yuan PD378S", + { &dib0700_usb_id_table[44], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 748d8dc38..6d70576ad 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -234,6 +234,7 @@ #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_YUAN_STK7700PH 0x1f08 +#define USB_PID_YUAN_PD378S 0x2edc #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index 1279046e0..081550761 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -224,7 +224,7 @@ struct dvb_usb_device_properties { int generic_bulk_ctrl_endpoint; int num_device_descs; - struct dvb_usb_device_description devices[9]; + struct dvb_usb_device_description devices[10]; }; /** -- cgit v1.2.3 From 0f150356bedfcbfe38b12f5f70c01c3daff98ed0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 08:02:53 -0300 Subject: get rid of the other occurrences of DVB_FE_CUSTOMIZE typo From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/Kconfig | 6 +++--- linux/drivers/media/video/cx23885/Kconfig | 8 ++++---- linux/drivers/media/video/pvrusb2/Kconfig | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 621ec043f..deb00e4ac 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 4066ca69c..28896aa31 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 7f7b05c40..bb4271393 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE ---help--- This option enables a DVB interface for the pvrusb2 driver. -- cgit v1.2.3 From 14930d48b7b561c2900d1487500bec01d090d55b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 12:55:29 -0300 Subject: em28xx-dvb: Remove an unused header From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index c76dbc029..edafe9bde 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -30,9 +30,6 @@ #include "lgdt330x.h" #include "zl10353.h" #include "s5h1409.h" -#ifdef EM28XX_DRX397XD_SUPPORT -#include "drx397xD.h" -#endif MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); -- cgit v1.2.3 From 33fa4d14a6a7b604b8fc146401a102a08dfce1be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 13:11:31 -0300 Subject: Adds some missing frontend select for saa7134 and dvb-usb From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/Kconfig | 1 + linux/drivers/media/video/saa7134/Kconfig | 2 ++ 2 files changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 3e581409f..3763a9c68 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -96,6 +96,7 @@ config DVB_USB_UMT_010 select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index e69d504ac..51f17c82b 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -40,6 +40,8 @@ config VIDEO_SAA7134_DVB select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select DVB_ZL10036 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From 2168a4a14827fc1411174452333f19456cf0ae2a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 28 Feb 2009 14:35:48 +0100 Subject: saa7146: Clean-up i2c error handling From: Oliver Endriss saa7146: Clean-up i2c error handling Simplify i2c error handling and fix incorrect handling of address errors in poll mode. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/saa7146_i2c.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index 68674799b..fa9d4f90a 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -294,7 +294,6 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m int i = 0, count = 0; __le32 *buffer = dev->d_i2c.cpu_addr; int err = 0; - int address_err = 0; int short_delay = 0; if (mutex_lock_interruptible(&dev->i2c_lock)) @@ -334,17 +333,10 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m i2c address probing, however, and address errors indicate that a device is really *not* there. retrying in that case increases the time the device needs to probe greatly, so - it should be avoided. because of the fact, that only - analog based cards use irq based i2c transactions (for dvb - cards, this screwes up other interrupt sources), we bail out - completely for analog cards after an address error and trust - the saa7146 address error detection. */ - if ( -EREMOTEIO == err ) { - if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { - goto out; - } - address_err++; - } + it should be avoided. So we bail out in irq mode after an + address error and trust the saa7146 address error detection. */ + if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) + goto out; DEB_I2C(("error while sending message(s). starting again.\n")); break; } @@ -359,10 +351,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m } while (err != num && retries--); - /* if every retry had an address error, exit right away */ - if (address_err == retries) { + /* quit if any error occurred */ + if (err != num) goto out; - } /* if any things had to be read, get the results */ if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) { -- cgit v1.2.3 From d0d7f86bddbb6e03debcd8c07cce1d710fd8a870 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 11:19:45 -0500 Subject: cx18: Use strlcpy() instead of strncpy() for temp eeprom i2c_client setup From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 8f294f436..f688ec7db 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -273,8 +273,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) u8 eedata[256]; memset(&c, 0, sizeof(c)); - strncpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); - c.name[sizeof(c.name)-1] = '\0'; + strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); c.adapter = &cx->i2c_adap[0]; c.addr = 0xA0 >> 1; -- cgit v1.2.3 From dab02fd6f0416a4ac1e76213a63b9900ee7b5133 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 12:51:47 -0500 Subject: cx18: Fix a video scaling check problem introduced by sliced VBI changes From: Andy Walls Fix a scaling check that was failing, due to a magic number I missed fixing during previous slice VBI changes. Now $ v4l2-ctl -v width=480,height=480,pixelformat=MPEG yields proper visual results again. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index cf256a999..aeeb3cfa3 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -867,8 +867,22 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_50Hz ? 4 : 7); + /* + * This adjustment reflects the excess of vactive, set in + * cx18_av_std_setup(), above standard values: + * + * 480 + 1 for 60 Hz systems + * 576 + 4 for 50 Hz systems + */ + Vlines = pix->height + (is_50Hz ? 4 : 1); + /* + * Invalid height and width scaling requests are: + * 1. width less than 1/16 of the source width + * 2. width greater than the source width + * 3. height less than 1/8 of the source height + * 4. height greater than the source height + */ if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", -- cgit v1.2.3 From 6027e12e8c84fefb63c5e8a3cfcf1e672629a439 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 14:42:51 -0500 Subject: cx18: Include cx18-audio.h in cx18-audio.c to eliminate s-parse warning From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-audio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index ccd170887..bb5c5165d 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -24,6 +24,7 @@ #include "cx18-driver.h" #include "cx18-io.h" #include "cx18-cards.h" +#include "cx18-audio.h" #define CX18_AUDIO_ENABLE 0xc72014 -- cgit v1.2.3 From bf1357c00949c25ceaef64b2127f022a870491ca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 4 Mar 2009 17:42:06 -0500 Subject: tda18271: add support for AGC configuration via tuner callback From: Michael Krufky The tda827x driver supports a feature that the tda18271 driver was lacking until now. This patch adds support for device-level configuration via the tuner callback configuration interface. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/tda18271-fe.c | 37 +++++++++++++++++++++++ linux/drivers/media/common/tuners/tda18271-priv.h | 6 +--- linux/drivers/media/common/tuners/tda18271.h | 10 ++++++ linux/drivers/media/common/tuners/tda8290.c | 1 + 4 files changed, 49 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tda18271-fe.c b/linux/drivers/media/common/tuners/tda18271-fe.c index 33bc96ea6..85e30af31 100644 --- a/linux/drivers/media/common/tuners/tda18271-fe.c +++ b/linux/drivers/media/common/tuners/tda18271-fe.c @@ -819,6 +819,38 @@ fail: return ret; } +/* ------------------------------------------------------------------ */ + +static int tda18271_agc(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + int ret = 0; + + switch (priv->config) { + case 0: + /* no LNA */ + tda_dbg("no agc configuration provided\n"); + break; + case 3: + /* switch with GPIO of saa713x */ + tda_dbg("invoking callback\n"); + if (fe->callback) + ret = fe->callback(priv->i2c_props.adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, + TDA18271_CALLBACK_CMD_AGC_ENABLE, + priv->mode); + break; + case 1: + case 2: + default: + /* n/a - currently not supported */ + tda_err("unsupported configuration: %d\n", priv->config); + ret = -EINVAL; + break; + } + return ret; +} + static int tda18271_tune(struct dvb_frontend *fe, struct tda18271_std_map_item *map, u32 freq, u32 bw) { @@ -828,6 +860,10 @@ static int tda18271_tune(struct dvb_frontend *fe, tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n", freq, map->if_freq, bw, map->agc_mode, map->std); + ret = tda18271_agc(fe); + if (tda_fail(ret)) + tda_warn("failed to configure agc\n"); + ret = tda18271_init(fe); if (tda_fail(ret)) goto fail; @@ -1160,6 +1196,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->role = (cfg) ? cfg->role : TDA18271_MASTER; + priv->config = (cfg) ? cfg->config : 0; priv->cal_initialized = false; mutex_init(&priv->lock); diff --git a/linux/drivers/media/common/tuners/tda18271-priv.h b/linux/drivers/media/common/tuners/tda18271-priv.h index 78417b7c1..f3adbb212 100644 --- a/linux/drivers/media/common/tuners/tda18271-priv.h +++ b/linux/drivers/media/common/tuners/tda18271-priv.h @@ -92,11 +92,6 @@ enum tda18271_pll { TDA18271_CAL_PLL, }; -enum tda18271_mode { - TDA18271_ANALOG, - TDA18271_DIGITAL, -}; - struct tda18271_map_layout; enum tda18271_ver { @@ -115,6 +110,7 @@ struct tda18271_priv { enum tda18271_i2c_gate gate; enum tda18271_ver id; + unsigned int config; /* interface to saa713x / tda829x */ unsigned int tm_rfcal; unsigned int cal_initialized:1; unsigned int small_i2c:1; diff --git a/linux/drivers/media/common/tuners/tda18271.h b/linux/drivers/media/common/tuners/tda18271.h index 7db9831c0..53a9892a1 100644 --- a/linux/drivers/media/common/tuners/tda18271.h +++ b/linux/drivers/media/common/tuners/tda18271.h @@ -79,6 +79,16 @@ struct tda18271_config { /* some i2c providers cant write all 39 registers at once */ unsigned int small_i2c:1; + + /* interface to saa713x / tda829x */ + unsigned int config; +}; + +#define TDA18271_CALLBACK_CMD_AGC_ENABLE 0 + +enum tda18271_mode { + TDA18271_ANALOG = 0, + TDA18271_DIGITAL, }; #if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE)) diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c index b1ef5f1e4..02ebc22a9 100644 --- a/linux/drivers/media/common/tuners/tda8290.c +++ b/linux/drivers/media/common/tuners/tda8290.c @@ -647,6 +647,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) if ((data == 0x83) || (data == 0x84)) { priv->ver |= TDA18271; + tda829x_tda18271_config.config = priv->cfg.config; dvb_attach(tda18271_attach, fe, priv->tda827x_addr, priv->i2c_props.adap, &tda829x_tda18271_config); } else { -- cgit v1.2.3 From 2af26e6a68740096134e432bc8b0fbf46cbd0a27 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 28 Feb 2009 15:45:17 -0500 Subject: saa7134: add analog support for Hauppauge HVR1110r3 boards From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-cards.c | 173 +++++++++++++++++++++- linux/drivers/media/video/saa7134/saa7134.h | 2 + 2 files changed, 173 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 9db045cf5..c912ab3d7 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -31,6 +31,7 @@ #include #include #include "tea5767.h" +#include "tda18271.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -3330,6 +3331,66 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200100, }, }, + [SAA7134_BOARD_HAUPPAUGE_HVR1150] = { + .name = "Hauppauge WinTV-HVR1150", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 3, + .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0800100, /* GPIO 23 HI for FM */ + }, + }, + [SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = { + .name = "Hauppauge WinTV-HVR1110r3", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 3, + .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0800100, /* GPIO 23 HI for FM */ + }, + }, [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { .name = "Terratec Cinergy HT PCMCIA", .audio_clock = 0x00187de7, @@ -5441,6 +5502,36 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0070, .subdevice = 0x6705, .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6706, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6707, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6708, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6709, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x670a, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5916,8 +6007,8 @@ static int saa7134_xc5000_callback(struct saa7134_dev *dev, } #endif -static int saa7134_tda8290_callback(struct saa7134_dev *dev, - int command, int arg) +static int saa7134_tda8290_827x_callback(struct saa7134_dev *dev, + int command, int arg) { u8 sync_control; @@ -5943,6 +6034,65 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, return 0; } +static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev, + enum tda18271_mode mode) +{ + /* toggle AGC switch through GPIO 26 */ + switch (mode) { + case TDA18271_ANALOG: + saa7134_set_gpio(dev, 26, 0); + break; + case TDA18271_DIGITAL: + saa7134_set_gpio(dev, 26, 1); + break; + default: + return -EINVAL; + } + return 0; +} + +static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, + int command, int arg) +{ + int ret = 0; + + switch (command) { + case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ + switch (dev->board) { + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); + break; + default: + break; + } + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int saa7134_tda8290_callback(struct saa7134_dev *dev, + int command, int arg) +{ + int ret; + + switch (dev->board) { + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + /* tda8290 + tda18271 */ + ret = saa7134_tda8290_18271_callback(dev, command, arg); + break; + default: + /* tda8290 + tda827x */ + ret = saa7134_tda8290_827x_callback(dev, command, arg); + break; + } + return ret; +} + int saa7134_tuner_callback(void *priv, int component, int command, int arg) { struct saa7134_dev *dev = priv; @@ -5977,11 +6127,16 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) switch (tv.model) { case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ + case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ + case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ + case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ case 67569: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM) */ case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */ case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ + case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ + case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ break; default: printk(KERN_WARNING "%s: warning: " @@ -6162,6 +6317,16 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + /* GPIO 26 high for digital, low for analog */ + saa7134_set_gpio(dev, 26, 0); + msleep(1); + + saa7134_set_gpio(dev, 22, 0); + msleep(10); + saa7134_set_gpio(dev, 22, 1); + break; /* i2c remotes */ case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: @@ -6414,6 +6579,10 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); } break; + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + hauppauge_eeprom(dev, dev->eedata+0x80); + break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: hauppauge_eeprom(dev, dev->eedata+0x80); /* break intentionally omitted */ diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index c9d4d4354..0e45c0931 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -279,6 +279,8 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 +#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 +#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 6f74c341a7b249eb9d00d02c979b5b646f6838f3 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 16:48:27 -0500 Subject: cx18: Fix s-parse warnings and a logic error about extracting the VBI PTS From: Andy Walls My s-parse builds never griped about be32_to_cpu() casting to __be32, but Hans' builds did. This change explictly declares the pointer into the VBI buffer header as __be32, which is the correct thing to do as the data is always big endian when we go to fetch it. Hopefully this will quiet s-parse warnings. Also corrected a misplaced parenthesis logic error in checking for the VBI header magic number. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-vbi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index a81fe2e98..355737bff 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -169,7 +169,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, int streamtype) { u8 *p = (u8 *) buf->buf; - u32 *q = (u32 *) buf->buf; + __be32 *q = (__be32 *) buf->buf; u32 size = buf->bytesused; u32 pts; int lines; @@ -178,8 +178,9 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, return; /* - * The CX23418 sends us data that is 32 bit LE swapped, but we want - * the raw VBI bytes in the order they were in the raster line + * The CX23418 sends us data that is 32 bit little-endian swapped, + * but we want the raw VBI bytes in the order they were in the raster + * line. This has a side effect of making the 12 byte header big endian */ cx18_buf_swap(buf); @@ -218,7 +219,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; + pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; /* * For calls to compress_sliced_buf(), ensure there are an integral -- cgit v1.2.3 From 597bd5dbc2ff24bbdd148fb698bc9a3d9daad61c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 18:13:50 -0500 Subject: cx18: Correct comments about vertical and horizontal blanking timings From: Andy Walls This change only affects comments. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 26 ++++++++++++++++---------- linux/drivers/media/video/cx18/cx18-av-core.h | 19 ++++++++++++------- linux/drivers/media/video/cx18/cx18-streams.c | 5 ++--- 3 files changed, 30 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index aeeb3cfa3..21f4be839 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -292,23 +292,29 @@ void cx18_av_std_setup(struct cx18 *cx) * * vsync: always 6 half-lines of vsync pulses * vactive: half lines of active video - * vblank656: half lines, after line 3, of blanked video - * vblank: half lines, after line 9, of blanked video + * vblank656: half lines, after line 3/mid-266, of blanked video + * vblank: half lines, after line 9/272, of blanked video * + * As far as I can tell: * vblank656 starts counting from the falling edge of the first - * vsync pulse (start of line 4) + * vsync pulse (start of line 4 or mid-266) * vblank starts counting from the after the 6 vsync pulses and - * 6 equalization pulses (start of line 10) + * 6 or 5 equalization pulses (start of line 10 or 272) * * For 525 line systems the driver will extract VBI information - * from lines 10 through 21. To avoid the EAV RP code from - * toggling at the start of hblank at line 22, where sliced VBI - * data from line 21 is stuffed, also treat line 22 as blanked. + * from lines 10-21 and lines 273-284. */ - vblank656 = 38; /* lines 4 through 22 */ - vblank = 26; /* lines 10 through 22 */ - vactive = 481; /* lines 23 through 262.5 */ + vblank656 = 38; /* lines 4 - 22 & 266 - 284 */ + vblank = 26; /* lines 10 - 22 & 272 - 284 */ + vactive = 481; /* lines 23 - 263 & 285 - 525 */ + /* + * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is + * is 858 pixels = 720 active + 138 blanking. The Hsync leading + * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the + * end of active video, leaving 122 pixels of hblank to ignore + * before active video starts. + */ hactive = 720; hblank = 122; luma_lpf = 1; diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h index fd0df4151..2687a2c91 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.h +++ b/linux/drivers/media/video/cx18/cx18-av-core.h @@ -89,16 +89,21 @@ struct cx18_av_state { /* * The VBI slicer starts operating and counting lines, begining at - * slicer line count of 1, at D lines after the deassertion of VRESET - * This staring field line, S, is 6 or 10 for 625 or 525 line systems. - * Sliced ancillary data captured on VBI slicer line M is sent at the - * beginning of the next VBI slicer line, VBI slicer line count N = M+1. - * Thus when the VBI slicer reports a VBI slicer line number with - * ancillary data, the IDID0 byte indicates VBI slicer line N. - * The actual field line that the captured data comes from is + * slicer line count of 1, at D lines after the deassertion of VRESET. + * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525 + * line systems respectively. Sliced ancillary data captured on VBI + * slicer line M is inserted after the VBI slicer is done with line M, + * when VBI slicer line count is N = M+1. Thus when the VBI slicer + * reports a VBI slicer line number with ancillary data, the IDID0 byte + * indicates VBI slicer line N. The actual field line that the captured + * data comes from is + * * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). * + * L is the line in the field, not frame, from which the VBI data came. + * N is the line reported by the slicer in the ancillary data. * D is the slicer_line_delay value programmed into register 0x47f. + * S is 6 for 625 line systems or 10 for 525 line systems * (S+D-2) is the slicer_line_offset used to convert slicer reported * line counts to actual field lines. */ diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 0605c2d83..7c1db9c18 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -413,9 +413,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) * 0x90 (Task HorizontalBlank) * 0xd0 (Task EvenField HorizontalBlank) * - * We have set the digitzer to consider the first active line - * as part of VerticalBlank as well so we don't have to look for - * these problem codes nor lose the last line of sliced data. + * We have set the digitzer such that we don't have to worry + * about these problem codes. */ data[4] = 0xB0F0B0F0; /* -- cgit v1.2.3 From 9f4b271dd3b4ae44e09437c3826a763e5d1adfb5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 1 Mar 2009 01:29:20 +0000 Subject: cx88: Add IR support to pcHDTV HD3000 & HD5500 From: Erik S. Beiser cx88: Add IR support to pcHDTV HD3000 & HD5500 Signed-off-by: Erik S. Beiser Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index bcecb5bbd..dbb6ee2d9 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -239,6 +239,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -483,6 +485,8 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); /* -- cgit v1.2.3 From 85609544aa42593842578f8281caaa4c1c5ca7c5 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 21:06:08 -0500 Subject: cx18: Fix VPS service register codes From: Andy Walls Based on a documentation clarification from Conexant, fix the register code used for sliced VBI VPS service. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-vbi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 43267d1af..27699839b 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -142,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ - V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 0, 0, 0, 0 }; int is_pal = !(state->std & V4L2_STD_525_60); @@ -243,7 +243,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) lcr[i] |= 6 << (4 * x); break; case V4L2_SLICED_VPS: - lcr[i] |= 7 << (4 * x); /*'840 differs*/ + lcr[i] |= 9 << (4 * x); break; } } @@ -301,7 +301,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) sdid = V4L2_SLICED_CAPTION_525; err = !odd_parity(p[0]) || !odd_parity(p[1]); break; - case 7: /* Differs from cx25840 */ + case 9: sdid = V4L2_SLICED_VPS; if (decode_vps(p, p) != 0) err = 1; -- cgit v1.2.3 From 8b42cd040a582268bae8f59db2fa336d21e8a5a6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Mar 2009 21:10:07 -0500 Subject: cx18: Add interlock so sliced VBI insertion only happens for an MPEG PS From: Andy Walls The cx18 private packet insertion code only expects to operate on an MPEG PS when inserting private packets of sliced VBI data. This patch keeps the cx18 driver from corrupting the MPEG TS or other non-PS stream types, in case the user enables sliced VBI insertion for these MPEG stream types. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-controls.c | 40 ++++++++++++++++++++------ 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 925e01fdb..82fc2f9d4 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -166,15 +166,26 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) return 0; } -static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt) +static int cx18_setup_vbi_fmt(struct cx18 *cx, + enum v4l2_mpeg_stream_vbi_fmt fmt, + enum v4l2_mpeg_stream_type type) { if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) return -EINVAL; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; - /* First try to allocate sliced VBI buffers if needed. */ - if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) { + if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || + type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + /* We don't do VBI insertion aside from IVTV format in a PS */ + cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " + "the MPEG stream\n"); + return 0; + } + + /* Allocate sliced VBI buffers if needed. */ + if (cx->vbi.sliced_mpeg_data[0] == NULL) { int i; for (i = 0; i < CX18_VBI_FRAMES; i++) { @@ -185,19 +196,27 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt kfree(cx->vbi.sliced_mpeg_data[i]); cx->vbi.sliced_mpeg_data[i] = NULL; } + cx->vbi.insert_mpeg = + V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_WARN("Unable to allocate buffers for " + "sliced VBI data insertion\n"); return -ENOMEM; } } } cx->vbi.insert_mpeg = fmt; + CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS," + "when sliced VBI is enabled\n"); - if (cx->vbi.insert_mpeg == 0) - return 0; - /* Need sliced data for mpeg insertion */ + /* + * If our current settings have no lines set for capture, store a valid, + * default set of service lines to capture, in our current settings. + */ if (cx18_get_service_set(cx->vbi.sliced_in) == 0) { if (cx->is_60hz) - cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; + cx->vbi.sliced_in->service_set = + V4L2_SLICED_CAPTION_525; else cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz); @@ -284,8 +303,11 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) priv.cx = cx; priv.s = &cx->streams[id->type]; err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); - if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt) - err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); + if (!err && + (cx->params.stream_vbi_fmt != p.stream_vbi_fmt || + cx->params.stream_type != p.stream_type)) + err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt, + p.stream_type); cx->params = p; cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; idx = p.audio_properties & 0x03; -- cgit v1.2.3 From 1bf54ffc543bd87a7e01c3163b3bfc64191a432e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 01:38:59 +0000 Subject: Add support for GeoVision GV-800(S) From: Bruno Christo Signed-off-by: Bruno Christo Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-cards.c | 181 ++++++++++++++++++++++++++- linux/drivers/media/video/bt8xx/bttv.h | 2 + 2 files changed, 182 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index a2719c6bd..aed55398d 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -76,6 +76,9 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input); static void phytec_muxsel(struct bttv *btv, unsigned int input); +static void gv800s_muxsel(struct bttv *btv, unsigned int input); +static void gv800s_init(struct bttv *btv); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -312,6 +315,10 @@ static struct CARD { { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" }, + { 0x763d800a, BTTV_BOARD_GEOVISION_GV800S, "GeoVision GV-800(S) (master)" }, + { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0, -1, NULL } }; @@ -2847,7 +2854,60 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - } + }, + [BTTV_BOARD_GEOVISION_GV800S] = { + /* Bruno Christo + * + * GeoVision GV-800(S) has 4 Conexant Fusion 878A: + * 1 audio input per BT878A = 4 audio inputs + * 4 video inputs per BT878A = 16 video inputs + * This is the first BT878A chip of the GV-800(S). It's the + * "master" chip and it controls the video inputs through an + * analog multiplexer (a CD22M3494) via some GPIO pins. The + * slaves should use card type 0x9e (following this one). + * There is a EEPROM on the card which is currently not handled. + * The audio input is not working yet. + */ + .name = "Geovision GV-800(S) (master)", + .video_inputs = 4, + /* .audio_inputs= 1, */ + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .svhs = NO_SVHS, + .gpiomask = 0xf107f, + .no_gpioirq = 1, + .muxsel = MUXSEL(2, 2, 2, 2), + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = gv800s_muxsel, + }, + [BTTV_BOARD_GEOVISION_GV800S_SL] = { + /* Bruno Christo + * + * GeoVision GV-800(S) has 4 Conexant Fusion 878A: + * 1 audio input per BT878A = 4 audio inputs + * 4 video inputs per BT878A = 16 video inputs + * The 3 other BT878A chips are "slave" chips of the GV-800(S) + * and should use this card type. + * The audio input is not working yet. + */ + .name = "Geovision GV-800(S) (slave)", + .video_inputs = 4, + /* .audio_inputs= 1, */ + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .svhs = NO_SVHS, + .gpiomask = 0x00, + .no_gpioirq = 1, + .muxsel = MUXSEL(2, 2, 2, 2), + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = gv800s_muxsel, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3376,6 +3436,9 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_KODICOM_4400R: kodicom4400r_init(btv); break; + case BTTV_BOARD_GEOVISION_GV800S: + gv800s_init(btv); + break; } /* pll configuration */ @@ -4595,6 +4658,122 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input) gpio_bits(0x3, mux); } +/* + * GeoVision GV-800(S) functions + * Bruno Christo +*/ + +/* This is a function to control the analog switch, which determines which + * camera is routed to which controller. The switch comprises an X-address + * (gpio bits 0-3, representing the camera, ranging from 0-15), and a + * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). + * A data value (gpio bit 18) of '1' enables the switch, and '0' disables + * the switch. A STROBE bit (gpio bit 17) latches the data value into the + * specified address. There is also a chip select (gpio bit 16). + * The idea is to set the address and chip select together, bring + * STROBE high, write the data, and finally bring STROBE back to low. + */ +static void gv800s_write(struct bttv *btv, + unsigned char xaddr, + unsigned char yaddr, + unsigned char data) { + /* On the "master" 878A: + * GPIO bits 0-9 are used for the analog switch: + * 00 - 03: camera selector + * 04 - 06: 878A (controller) selector + * 16: cselect + * 17: strobe + * 18: data (1->on, 0->off) + * 19: reset + */ + const u32 ADDRESS = ((xaddr&0xf) | (yaddr&3)<<4); + const u32 CSELECT = 1<<16; + const u32 STROBE = 1<<17; + const u32 DATA = data<<18; + + gpio_bits(0x1007f, ADDRESS | CSELECT); /* write ADDRESS and CSELECT */ + gpio_bits(0x20000, STROBE); /* STROBE high */ + gpio_bits(0x40000, DATA); /* write DATA */ + gpio_bits(0x20000, ~STROBE); /* STROBE low */ +} + +/* + * GeoVision GV-800(S) muxsel + * + * Each of the 4 cards (controllers) use this function. + * The controller using this function selects the input through the GPIO pins + * of the "master" card. A pointer to this card is stored in master[btv->c.nr]. + * + * The parameter 'input' is the requested camera number (0-4) on the controller. + * The map array has the address of each input. Note that the addresses in the + * array are in the sequence the original GeoVision driver uses, that is, set + * every controller to input 0, then to input 1, 2, 3, repeat. This means that + * the physical "camera 1" connector corresponds to controller 0 input 0, + * "camera 2" corresponds to controller 1 input 0, and so on. + * + * After getting the input address, the function then writes the appropriate + * data to the analog switch, and housekeeps the local copy of the switch + * information. + */ +static void gv800s_muxsel(struct bttv *btv, unsigned int input) +{ + struct bttv *mctlr; + char *sw_status; + int xaddr, yaddr; + static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, + { 0x1, 0x5, 0xb, 0x7 }, + { 0x2, 0x8, 0xc, 0xe }, + { 0x3, 0x9, 0xd, 0xf } }; + input = input%4; + mctlr = master[btv->c.nr]; + if (mctlr == NULL) { + /* do nothing until the "master" is detected */ + return; + } + yaddr = (btv->c.nr - mctlr->c.nr) & 3; + sw_status = (char *)(&mctlr->mbox_we); + xaddr = map[yaddr][input] & 0xf; + + /* Check if the controller/camera pair has changed, ignore otherwise */ + if (sw_status[yaddr] != xaddr) { + /* disable the old switch, enable the new one and save status */ + gv800s_write(mctlr, sw_status[yaddr], yaddr, 0); + sw_status[yaddr] = xaddr; + gv800s_write(mctlr, xaddr, yaddr, 1); + } +} + +/* GeoVision GV-800(S) "master" chip init */ +static void gv800s_init(struct bttv *btv) +{ + char *sw_status = (char *)(&btv->mbox_we); + int ix; + + gpio_inout(0xf107f, 0xf107f); + gpio_write(1<<19); /* reset the analog MUX */ + gpio_write(0); + + /* Preset camera 0 to the 4 controllers */ + for (ix = 0; ix < 4; ix++) { + sw_status[ix] = ix; + gv800s_write(btv, ix, ix, 1); + } + + /* Inputs on the "master" controller need this brightness fix */ + bttv_I2CWrite(btv, 0x18, 0x5, 0x90, 1); + + if (btv->c.nr > BTTV_MAX-4) + return; + /* + * Store the "master" controller pointer in the master + * array for later use in the muxsel function. + */ + master[btv->c.nr] = btv; + master[btv->c.nr+1] = btv; + master[btv->c.nr+2] = btv; + master[btv->c.nr+3] = btv; +} + /* ----------------------------------------------------------------------- */ /* motherboard chipset specific stuff */ diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 3a065b8a4..35f943337 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -182,6 +182,8 @@ #define BTTV_BOARD_VD012_X1 0x9a #define BTTV_BOARD_VD012_X2 0x9b #define BTTV_BOARD_IVCE8784 0x9c +#define BTTV_BOARD_GEOVISION_GV800S 0x9d +#define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e /* more card-specific defines */ -- cgit v1.2.3 From 9471f09f98982fcbf6ad0e3411af405c1d5d4588 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 16:25:19 +0300 Subject: tvaudio: remove bogus check From: Vitaly Wool The 'bytes' array is 64 bytes large but the easy standard programming (TDA9874A_ESP) has a number of 255, outside the shadow array size. This patch increases the size of the shadow array in order to accomodate this register. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 755418a31..d630dca83 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -57,7 +57,7 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ /* our structs */ -#define MAXREGS 64 +#define MAXREGS 256 struct CHIPSTATE; typedef int (*getvalue)(int); -- cgit v1.2.3 From 71f4cd372a2afd40df0d75bb5276add07ce8edb5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 23:20:47 +0000 Subject: Support alternate resolutions for sq905 From: Adam Baker Add support for the alternate resolutions offered by SQ-905 based cameras. As well as 320x240 all cameras can do 160x120 and some can do 640x480. Signed-off-by: Adam Baker Signed-off-by: Theodore Kilgore Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/sq905.c | 100 +++++++++++++++++++------------- 1 file changed, 59 insertions(+), 41 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index dafaed69e..da60eea51 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -60,23 +60,29 @@ MODULE_LICENSE("GPL"); #define SQ905_PING 0x07 /* when reading an "idling" command */ #define SQ905_READ_DONE 0xc0 /* ack bulk read completed */ +/* Any non-zero value in the bottom 2 bits of the 2nd byte of + * the ID appears to indicate the camera can do 640*480. If the + * LSB of that byte is set the image is just upside down, otherwise + * it is rotated 180 degrees. */ +#define SQ905_HIRES_MASK 0x00000300 +#define SQ905_ORIENTATION_MASK 0x00000100 + /* Some command codes. These go in the "index" slot. */ #define SQ905_ID 0xf0 /* asks for model string */ #define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */ #define SQ905_DATA 0x30 /* accesses photo data, not used here */ #define SQ905_CLEAR 0xa0 /* clear everything */ -#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ -#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ +#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +#define SQ905_CAPTURE_HIGH 0x62 /* Starts capture at 640x480 (some cams only) */ /* note that the capture command also controls the output dimensions */ -/* 0x60 -> 160x120, 0x61 -> 320x240 0x62 -> 640x480 depends on camera */ -/* 0x62 is not correct, at least for some cams. Should be 0x63 ? */ /* Structure to hold all of our device specific stuff */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 cam_type; + const struct v4l2_pix_format *cap_mode; /* * Driver stuff @@ -85,33 +91,24 @@ struct sd { struct workqueue_struct *work_thread; }; -/* The driver only supports 320x240 so far. */ -static struct v4l2_pix_format sq905_mode[1] = { +static struct v4l2_pix_format sq905_mode[] = { + { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240, .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0} }; -struct cam_type { - u32 ident_word; - char *name; - struct v4l2_pix_format *min_mode; - u8 num_modes; - u8 sensor_flags; -}; - -#define SQ905_FLIP_HORIZ (1 << 0) -#define SQ905_FLIP_VERT (1 << 1) - -/* Last entry is default if nothing else matches */ -static struct cam_type cam_types[] = { - { 0x19010509, "PocketCam", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, - { 0x32010509, "Magpix", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, - { 0, "Default", &sq905_mode[0], 1, SQ905_FLIP_HORIZ | SQ905_FLIP_VERT } -}; - /* * Send a command to the camera. */ @@ -240,7 +237,7 @@ static void sq905_dostream(struct work_struct *work) /* request some data and then read it until we have * a complete frame. */ - bytes_left = sq905_mode[0].sizeimage + FRAME_HEADER_LEN; + bytes_left = dev->cap_mode->sizeimage + FRAME_HEADER_LEN; header_read = 0; discarding = 0; @@ -272,11 +269,18 @@ static void sq905_dostream(struct work_struct *work) packet_type = INTER_PACKET; } frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) + if (frame && !discarding) { gspca_frame_add(gspca_dev, packet_type, frame, data, data_len); - else + /* If entire frame fits in one packet we still + need to add a LAST_PACKET */ + if ((packet_type == FIRST_PACKET) && + (bytes_left == 0)) + gspca_frame_add(gspca_dev, LAST_PACKET, + frame, data, 0); + } else { discarding = 1; + } } /* acknowledge the frame */ mutex_lock(&gspca_dev->usb_lock); @@ -301,8 +305,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam = &gspca_dev->cam; struct sd *dev = (struct sd *) gspca_dev; - cam->cam_mode = sq905_mode; - cam->nmodes = 1; /* We don't use the buffer gspca allocates so make it small. */ cam->bulk_size = 64; @@ -328,7 +330,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct sd *dev = (struct sd *) gspca_dev; u32 ident; int ret; @@ -344,17 +345,18 @@ static int sd_init(struct gspca_dev *gspca_dev) ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); if (ret < 0) return ret; - /* usb_buf is allocated with kmalloc so is aligned. */ - ident = le32_to_cpup((u32 *)gspca_dev->usb_buf); + /* usb_buf is allocated with kmalloc so is aligned. + * Camera model number is the right way round if we assume this + * reverse engineered ID is supposed to be big endian. */ + ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf); ret = sq905_command(gspca_dev, SQ905_CLEAR); if (ret < 0) return ret; - dev->cam_type = 0; - while (dev->cam_type < ARRAY_SIZE(cam_types) - 1 && - ident != cam_types[dev->cam_type].ident_word) - dev->cam_type++; - PDEBUG(D_CONF, "SQ905 camera %s, ID %08x detected", - cam_types[dev->cam_type].name, ident); + PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident); + gspca_dev->cam.cam_mode = sq905_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode); + if (!(ident & SQ905_HIRES_MASK)) + gspca_dev->cam.nmodes--; return 0; } @@ -364,13 +366,29 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *dev = (struct sd *) gspca_dev; int ret; + /* Set capture mode based on selected resolution. */ + dev->cap_mode = gspca_dev->cam.cam_mode; /* "Open the shutter" and set size, to start capture */ - ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at high resolution"); + dev->cap_mode += 2; + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH); + break; + case 320: + PDEBUG(D_STREAM, "Start streaming at medium resolution"); + dev->cap_mode++; + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + break; + default: + PDEBUG(D_STREAM, "Start streaming at low resolution"); + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW); + } + if (ret < 0) { PDEBUG(D_ERR, "Start streaming command failed"); return ret; } - /* Start the workqueue function to do the streaming */ dev->work_thread = create_singlethread_workqueue(MODULE_NAME); queue_work(dev->work_thread, &dev->work_struct); -- cgit v1.2.3 From 49e8c2b4c9396a7d75bde724d497fdddd09f0ab2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 4 Mar 2009 14:27:52 +0300 Subject: em28xx: enable Compro VideoMate ForYou sound From: Vitaly Wool Compro VideoMate uses an external audio DSP chip, controlled via tvaudio module (tda9874a). This patch improves em28xx infrastructure to support an external audio processor and fixes the Compro VideoMate entry to work with it. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 21 ++++++++++++++++++++- linux/drivers/media/video/em28xx/em28xx-core.c | 5 +++++ linux/drivers/media/video/em28xx/em28xx-i2c.c | 6 ++++++ linux/drivers/media/video/em28xx/em28xx-video.c | 7 +++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 74f35b6d6..fcb8131e6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -135,6 +135,22 @@ static struct em28xx_reg_seq default_tuner_gpio[] = { { -1, -1, -1, -1}, }; +/* Mute/unmute */ +static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { + {EM28XX_R08_GPIO, 5, 7, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { + {EM28XX_R08_GPIO, 4, 7, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq compro_mute_gpio[] = { + {EM28XX_R08_GPIO, 6, 7, 10}, + { -1, -1, -1, -1}, +}; + /* * Board definitions */ @@ -1290,14 +1306,17 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, .adecoder = EM28XX_TVAUDIO, + .mute_gpio = compro_mute_gpio, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, + .amux = EM28XX_AMUX_VIDEO, + .gpio = compro_unmute_tv_gpio, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = compro_unmute_svid_gpio, } }, }, [EM2860_BOARD_KAIOMY_TVNPC_U2] = { diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index f10abc5b4..0d4c9fcc2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -378,6 +378,11 @@ static int em28xx_set_audio_source(struct em28xx *dev) } } + if (dev->board.mute_gpio && dev->mute) + em28xx_gpio_set(dev, dev->board.mute_gpio); + else + em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); + ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0); if (ret < 0) return ret; diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 1bdcf2500..e9abb2769 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -510,12 +510,17 @@ static int attach_inform(struct i2c_client *client) dprintk1(1, "attach_inform: tvp5150 detected.\n"); break; + case 0xb0: + dprintk1(1, "attach_inform: tda9874 detected\n"); + break; + default: if (!dev->tuner_addr) dev->tuner_addr = client->addr; dprintk1(1, "attach inform: detected I2C address %x\n", client->addr << 1); + dprintk1(1, "driver id %d\n", client->driver->id); } @@ -557,6 +562,7 @@ static char *i2c_devs[128] = { [0x80 >> 1] = "msp34xx", [0x88 >> 1] = "msp34xx", [0xa0 >> 1] = "eeprom", + [0xb0 >> 1] = "tda9874", [0xb8 >> 1] = "tvp5150a", [0xba >> 1] = "tvp5150a", [0xc0 >> 1] = "tuner (analog)", diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 448a02b04..ef02999ec 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -544,6 +544,13 @@ static void video_mux(struct em28xx *dev, int index) &route); } + if (dev->board.adecoder != EM28XX_NOADECODER) { + route.input = dev->ctl_ainput; + route.output = dev->ctl_aoutput; + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, + &route); + } + em28xx_audio_analog_set(dev); } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 43c537e66..c9be33aba 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -375,6 +375,7 @@ struct em28xx_board { struct em28xx_reg_seq *dvb_gpio; struct em28xx_reg_seq *suspend_gpio; struct em28xx_reg_seq *tuner_gpio; + struct em28xx_reg_seq *mute_gpio; unsigned int is_em2800:1; unsigned int has_msp34xx:1; -- cgit v1.2.3 From b6fa6a4b2489d8599ce71ae8bc9075cbd144caaa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 4 Mar 2009 16:57:04 +0000 Subject: dm1105: uses ir_* functions, select VIDEO_IR From: Randy Dunlap dm1105 uses the ir_*() functions, so it needs to select VIDEO_IR to avoid build errors: dm1105.c:(.text+0x26b7ac): undefined reference to `ir_input_keydown' dm1105.c:(.text+0x26b7bc): undefined reference to `ir_input_nokey' (.devinit.text+0x29982): undefined reference to `ir_codes_dm1105_nec' (.devinit.text+0x2998a): undefined reference to `ir_input_init' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dm1105/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dm1105/Kconfig b/linux/drivers/media/dvb/dm1105/Kconfig index 43f4d44ed..de3eeb0a8 100644 --- a/linux/drivers/media/dvb/dm1105/Kconfig +++ b/linux/drivers/media/dvb/dm1105/Kconfig @@ -8,6 +8,7 @@ config DVB_DM1105 select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE + select VIDEO_IR help Support for cards based on the SDMC DM1105 PCI chip like DvbWorld 2002 -- cgit v1.2.3 From 9892238b5ecfef471cd6a203d3f9865afdebafb3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 4 Mar 2009 18:12:38 -0300 Subject: dib0700: Fixes the usb_id_table From: Mauro Carvalho Chehab As noticed by Pascal Terjan : The merge seems wrong: > +/* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) }, > + { &dib0700_usb_id_table[44], NULL }, Should be 45 Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 80744f44e..8877215cb 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1659,7 +1659,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { { NULL }, }, { "Yuan PD378S", - { &dib0700_usb_id_table[44], NULL }, + { &dib0700_usb_id_table[45], NULL }, { NULL }, }, }, -- cgit v1.2.3 From 798185861c11b8c26c0494e459d1b7811d2c228e Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 5 Mar 2009 03:02:05 -0800 Subject: zoran: Change first argument to zoran_v4l2_buffer_status From: Trent Piepho It was a struct file *, but all that function wants is the struct zoran_fh from the file's private data. Since every caller already has this, just pass the zoran_fh instead. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran_driver.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 8eda83b06..1560c1e4c 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1378,11 +1378,10 @@ setup_overlay (struct file *file, /* get the status of a buffer in the clients buffer queue */ static int -zoran_v4l2_buffer_status (struct file *file, +zoran_v4l2_buffer_status (struct zoran_fh *fh, struct v4l2_buffer *buf, int num) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; buf->flags = V4L2_BUF_FLAG_MAPPED; @@ -2502,7 +2501,7 @@ static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf int res; mutex_lock(&zr->resource_lock); - res = zoran_v4l2_buffer_status(file, buf, buf->index); + res = zoran_v4l2_buffer_status(fh, buf, buf->index); mutex_unlock(&zr->resource_lock); return res; @@ -2603,7 +2602,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) if (res) goto dqbuf_unlock_and_return; zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(file, buf, num); + res = zoran_v4l2_buffer_status(fh, buf, num); break; case ZORAN_MAP_MODE_JPG_REC: @@ -2634,7 +2633,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = jpg_sync(file, &bs); if (res) goto dqbuf_unlock_and_return; - res = zoran_v4l2_buffer_status(file, buf, bs.frame); + res = zoran_v4l2_buffer_status(fh, buf, bs.frame); break; } -- cgit v1.2.3 From f217e9ebf0be52ccca5d5c93e6d25cfb7609e74f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 16:19:14 -0300 Subject: zoran: auto-select bt866 for AverMedia 6 Eyes From: Mauro Carvalho Chehab AFAIK, the bt866 is only seen on AverMedia 6 Eyes. However, no module selects it. Adds a proper select for this driver. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/Kconfig b/linux/drivers/media/video/zoran/Kconfig index 925fb5159..fd4120e4c 100644 --- a/linux/drivers/media/video/zoran/Kconfig +++ b/linux/drivers/media/video/zoran/Kconfig @@ -68,6 +68,7 @@ config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help Support for the AverMedia 6 Eyes video surveillance card. -- cgit v1.2.3 From 100a1887717fba257eb5ad9fd716e4aa4da7187b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2009 08:06:24 -0300 Subject: Kconfig: Add some missing selects for a required frontends From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/Kconfig | 1 + linux/drivers/media/video/cx23885/Kconfig | 2 ++ linux/drivers/media/video/saa7134/Kconfig | 1 + 3 files changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index bbddc9fb6..3e581409f 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -108,6 +108,7 @@ config DVB_USB_CXUSB select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE + select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index b62f16d50..bbd990ff7 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -17,6 +17,8 @@ config VIDEO_CX23885 select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE select DVB_LNBP21 if !DVB_FE_CUSTOMIZE + select DVB_STV6110 if !DVB_FE_CUSTOMIZE + select DVB_STV0900 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index a3470ebad..e69d504ac 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -35,6 +35,7 @@ config VIDEO_SAA7134_DVB select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select DVB_ISL6405 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select DVB_ZL10036 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From 3ab3e879ca4a6d8a00f98d751af7890688b4aee4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2009 08:25:35 -0300 Subject: Kconfig: replace DVB_FE_CUSTOMIZE to DVB_FE_CUSTOMISE From: Mauro Carvalho Chehab The name of the option is DVB_FE_CUSTOMISE. However, on a few places, a wrong name were used, due to a typo (DVB_FE_CUSTOMIZE). Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 8 ++++---- linux/drivers/media/video/pvrusb2/Kconfig | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 018f72b8e..621ec043f 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -4,7 +4,7 @@ config VIDEO_AU0828 depends on I2C && INPUT && DVB_CORE && USB select I2C_ALGOBIT select VIDEO_TVEEPROM - select DVB_AU8522 if !DVB_FE_CUSTOMIZE + select DVB_AU8522 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index bbd990ff7..4066ca69c 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -15,10 +15,10 @@ config VIDEO_CX23885 select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE - select DVB_LNBP21 if !DVB_FE_CUSTOMIZE - select DVB_STV6110 if !DVB_FE_CUSTOMIZE - select DVB_STV0900 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_STV6110 if !DVB_FE_CUSTOMISE + select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 854c2a885..7f7b05c40 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -40,7 +40,7 @@ config VIDEO_PVRUSB2_DVB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE -- cgit v1.2.3 From 706b9e26b99f3461c34fd3a397d73e0a0d60aafb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2009 08:31:39 -0300 Subject: Kconfig: only open the customise menu if selected From: Mauro Carvalho Chehab Instead of asking a lot of questions for the poor users, let's just hide the frontend customise menu, if the user doesn't want to customise. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 4059d22a1..3205e302d 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -1,17 +1,21 @@ -menu "Customise DVB Frontends" - depends on DVB_CORE - config DVB_FE_CUSTOMISE bool "Customise the frontend modules to build" + depends on DVB_CORE default N help - This allows the user to deselect frontend drivers unnecessary - for their hardware from the build. Use this option with care - as deselecting frontends which are in fact necessary will result - in DVB devices which cannot be tuned due to lack of driver support. + This allows the user to select/deselect frontend drivers for their + hardware from the build. + + Use this option with care as deselecting frontends which are in fact + necessary will result in DVB devices which cannot be tuned due to lack + of driver support. If unsure say N. +if DVB_FE_CUSTOMISE + +menu "Customise DVB Frontends" + comment "Multistandard (satellite) frontends" depends on DVB_CORE @@ -507,3 +511,5 @@ config DVB_AF9013 help Say Y when you want to support this frontend. endmenu + +endif -- cgit v1.2.3 From d656238607307dba3176cbca78c0dc80ac54948c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 16:05:43 +0100 Subject: vino: fold i2c-algo-sgi code into vino. From: Jean Delvare Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 1 - linux/drivers/media/video/vino.c | 247 ++++++++++++++++++++++++++++++-------- 2 files changed, 194 insertions(+), 54 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 6c26618b8..534a022c4 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -582,7 +582,6 @@ config VIDEO_SAA5249 config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 - select I2C_ALGO_SGI select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO help Say Y here to build in support for the Vino video input system found diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 8a96ee7db..20743721b 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -33,7 +33,6 @@ #include #include -#include #include #include @@ -141,6 +140,20 @@ MODULE_LICENSE("GPL"); #define VINO_DATA_NORM_COUNT 4 +/* I2C controller flags */ +#define SGI_I2C_FORCE_IDLE (0 << 0) +#define SGI_I2C_NOT_IDLE (1 << 0) +#define SGI_I2C_WRITE (0 << 1) +#define SGI_I2C_READ (1 << 1) +#define SGI_I2C_RELEASE_BUS (0 << 2) +#define SGI_I2C_HOLD_BUS (1 << 2) +#define SGI_I2C_XFER_DONE (0 << 4) +#define SGI_I2C_XFER_BUSY (1 << 4) +#define SGI_I2C_ACK (0 << 5) +#define SGI_I2C_NACK (1 << 5) +#define SGI_I2C_BUS_OK (0 << 7) +#define SGI_I2C_BUS_ERR (1 << 7) + /* Internal data structure definitions */ struct vino_input { @@ -640,56 +653,6 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { } }; -/* VINO I2C bus functions */ - -unsigned i2c_vino_getctrl(void *data) -{ - return vino->i2c_control; -} - -void i2c_vino_setctrl(void *data, unsigned val) -{ - vino->i2c_control = val; -} - -unsigned i2c_vino_rdata(void *data) -{ - return vino->i2c_data; -} - -void i2c_vino_wdata(void *data, unsigned val) -{ - vino->i2c_data = val; -} - -static struct i2c_algo_sgi_data i2c_sgi_vino_data = -{ - .getctrl = &i2c_vino_getctrl, - .setctrl = &i2c_vino_setctrl, - .rdata = &i2c_vino_rdata, - .wdata = &i2c_vino_wdata, - .xfer_timeout = 200, - .ack_timeout = 1000, -}; - -static struct i2c_adapter vino_i2c_adapter = -{ - .name = "VINO I2C bus", - .id = I2C_HW_SGI_VINO, - .algo_data = &i2c_sgi_vino_data, - .owner = THIS_MODULE, -}; - -static int vino_i2c_add_bus(void) -{ - return i2c_sgi_add_bus(&vino_i2c_adapter); -} - -static int vino_i2c_del_bus(void) -{ - return i2c_del_adapter(&vino_i2c_adapter); -} - /* VINO framebuffer/DMA descriptor management */ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, @@ -1635,6 +1598,184 @@ static inline void vino_set_default_framerate(struct vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); } +/* VINO I2C bus functions */ + +struct i2c_algo_sgi_data { + void *data; /* private data for lowlevel routines */ + unsigned (*getctrl)(void *data); + void (*setctrl)(void *data, unsigned val); + unsigned (*rdata)(void *data); + void (*wdata)(void *data, unsigned val); + + int xfer_timeout; + int ack_timeout; +}; + +static int wait_xfer_done(struct i2c_algo_sgi_data *adap) +{ + int i; + + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int wait_ack(struct i2c_algo_sgi_data *adap) +{ + int i; + + if (wait_xfer_done(adap)) + return -ETIMEDOUT; + for (i = 0; i < adap->ack_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int force_idle(struct i2c_algo_sgi_data *adap) +{ + int i; + + adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE); + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0) + goto out; + udelay(1); + } + return -ETIMEDOUT; +out: + if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR) + return -EIO; + return 0; +} + +static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr, + int rd) +{ + if (rd) + adap->setctrl(adap->data, SGI_I2C_NOT_IDLE); + /* Check if bus is idle, eventually force it to do so */ + if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) + if (force_idle(adap)) + return -EIO; + /* Write out the i2c chip address and specify operation */ + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE); + if (rd) + addr |= 1; + adap->wdata(adap->data, addr); + if (wait_ack(adap)) + return -EIO; + return 0; +} + +static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE); + for (i = 0; i < len; i++) { + if (wait_xfer_done(adap)) + return -EIO; + buf[i] = adap->rdata(adap->data); + } + adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE); + + return 0; + +} + +static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + /* We are already in write state */ + for (i = 0; i < len; i++) { + adap->wdata(adap->data, buf[i]); + if (wait_ack(adap)) + return -EIO; + } + return 0; +} + +static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_sgi_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = do_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = i2c_read(adap, p->buf, p->len); + else + err = i2c_write(adap, p->buf, p->len); + } + + return (err < 0) ? err : i; +} + +static u32 sgi_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sgi_algo = { + .master_xfer = sgi_xfer, + .functionality = sgi_func, +}; + +static unsigned i2c_vino_getctrl(void *data) +{ + return vino->i2c_control; +} + +static void i2c_vino_setctrl(void *data, unsigned val) +{ + vino->i2c_control = val; +} + +static unsigned i2c_vino_rdata(void *data) +{ + return vino->i2c_data; +} + +static void i2c_vino_wdata(void *data, unsigned val) +{ + vino->i2c_data = val; +} + +static struct i2c_algo_sgi_data i2c_sgi_vino_data = { + .getctrl = &i2c_vino_getctrl, + .setctrl = &i2c_vino_setctrl, + .rdata = &i2c_vino_rdata, + .wdata = &i2c_vino_wdata, + .xfer_timeout = 200, + .ack_timeout = 1000, +}; + +static struct i2c_adapter vino_i2c_adapter = { + .name = "VINO I2C bus", + .id = I2C_HW_SGI_VINO, + .algo = &sgi_algo, + .algo_data = &i2c_sgi_vino_data, + .owner = THIS_MODULE, +}; + /* * Prepare VINO for DMA transfer... * (execute only with vino_lock and input_lock locked) @@ -4003,7 +4144,7 @@ static void vino_module_cleanup(int stage) video_unregister_device(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; case 9: - vino_i2c_del_bus(); + i2c_del_adapter(&vino_i2c_adapter); case 8: free_irq(SGI_VINO_IRQ, NULL); case 7: @@ -4226,7 +4367,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = vino_i2c_add_bus(); + ret = i2c_add_adapter(&vino_i2c_adapter); if (ret) { printk(KERN_ERR "VINO I2C bus registration failed\n"); vino_module_cleanup(vino_init_stage); -- cgit v1.2.3 From 065193c75af7a295d98a8cad617537d45f69a23a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 16:15:08 +0100 Subject: vino: add note that this conversion is untested. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 20743721b..ba4e8b97d 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -8,6 +8,12 @@ * * Based on the previous version of the driver for 2.4 kernels by: * Copyright (C) 2003 Ladislav Michl + * + * v4l2_device/v4l2_subdev conversion by: + * Copyright (C) 2009 Hans Verkuil + * + * Note: this conversion is untested! Please contact the linux-media + * mailinglist if you can test this, together with the test results. */ /* -- cgit v1.2.3 From 7c7af993cc14112fbcb88c86c94ec1a546a2263b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:45:27 +0100 Subject: radio-aimslab: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 350 ++++++++++++++---------------- 1 file changed, 168 insertions(+), 182 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 384aa928f..57b896968 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -32,15 +32,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("M.Kirkwood"); +MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK_PORT #define CONFIG_RADIO_RTRACK_PORT -1 @@ -48,86 +50,95 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; -static struct mutex lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; int port; int curvol; unsigned long curfreq; int muted; + int io; + struct mutex lock; }; +static struct rtrack rtrack_card; /* local things */ static void sleep_delay(long n) { /* Sleep nicely for 'n' uS */ - int d=n/msecs_to_jiffies(1000); - if(!d) + int d = n / msecs_to_jiffies(1000); + if (!d) udelay(n); else msleep(jiffies_to_msecs(d)); } -static void rt_decvol(void) +static void rt_decvol(struct rtrack *rt) { - outb(0x58, io); /* volume down + sigstr + on */ + outb(0x58, rt->io); /* volume down + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_incvol(void) +static void rt_incvol(struct rtrack *rt) { - outb(0x98, io); /* volume up + sigstr + on */ + outb(0x98, rt->io); /* volume up + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack *rt) { - dev->muted = 1; - mutex_lock(&lock); - outb(0xd0, io); /* volume steady, off */ - mutex_unlock(&lock); + rt->muted = 1; + mutex_lock(&rt->lock); + outb(0xd0, rt->io); /* volume steady, off */ + mutex_unlock(&rt->lock); } -static int rt_setvol(struct rt_device *dev, int vol) +static int rt_setvol(struct rtrack *rt, int vol) { int i; - mutex_lock(&lock); + mutex_lock(&rt->lock); - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - outb (0xd8, io); /* enable card */ + if (vol == rt->curvol) { /* requested volume = current */ + if (rt->muted) { /* user is unmuting the card */ + rt->muted = 0; + outb(0xd8, rt->io); /* enable card */ } - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } - if(vol == 0) { /* volume = 0 means mute the card */ - outb(0x48, io); /* volume down but still "on" */ + if (vol == 0) { /* volume = 0 means mute the card */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xd0, io); /* volume steady, off */ - dev->curvol = 0; /* track the volume state! */ - mutex_unlock(&lock); + outb(0xd0, rt->io); /* volume steady, off */ + rt->curvol = 0; /* track the volume state! */ + mutex_unlock(&rt->lock); return 0; } - dev->muted = 0; - if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) - rt_incvol(); + rt->muted = 0; + if (vol > rt->curvol) + for (i = rt->curvol; i < vol; i++) + rt_incvol(rt); else - for(i = dev->curvol; i > vol; i--) - rt_decvol(); + for (i = rt->curvol; i > vol; i--) + rt_decvol(rt); - dev->curvol = vol; - mutex_unlock(&lock); + rt->curvol = vol; + mutex_unlock(&rt->lock); return 0; } @@ -136,155 +147,137 @@ static int rt_setvol(struct rt_device *dev, int vol) * and bit 4 (+16) is to keep the signal strength meter enabled */ -static void send_0_byte(int port, struct rt_device *dev) +static void send_0_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+ 1, port); /* wr-enable + data low */ - outb_p(128+64+16+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ + outb_p(128+64+16+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ - outb_p(128+64+16+8+2+1, port); /* clock */ + outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ + outb_p(128+64+16+8+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static void send_1_byte(int port, struct rt_device *dev) +static void send_1_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ - outb_p(128+64+16+4+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ + outb_p(128+64+16+4+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ - outb_p(128+64+16+8+4+2+1, port); /* clock */ + outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ + outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack *rt, unsigned long freq) { int i; - /* adapted from radio-aztech.c */ + mutex_lock(&rt->lock); /* Stop other ops interfering */ + + rt->curfreq = freq; /* now uses VIDEO_TUNER_LOW for fine tuning */ freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); /* Stop other ops interfering */ - - send_0_byte (io, dev); /* 0: LSB of frequency */ + send_0_byte(rt); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (freq & (1 << i)) - send_1_byte (io, dev); + send_1_byte(rt); else - send_0_byte (io, dev); + send_0_byte(rt); - send_0_byte (io, dev); /* 14: test bit - always 0 */ - send_0_byte (io, dev); /* 15: test bit - always 0 */ + send_0_byte(rt); /* 14: test bit - always 0 */ + send_0_byte(rt); /* 15: test bit - always 0 */ - send_0_byte (io, dev); /* 16: band data 0 - always 0 */ - send_0_byte (io, dev); /* 17: band data 1 - always 0 */ - send_0_byte (io, dev); /* 18: band data 2 - always 0 */ - send_0_byte (io, dev); /* 19: time base - always 0 */ + send_0_byte(rt); /* 16: band data 0 - always 0 */ + send_0_byte(rt); /* 17: band data 1 - always 0 */ + send_0_byte(rt); /* 18: band data 2 - always 0 */ + send_0_byte(rt); /* 19: time base - always 0 */ - send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */ + send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ - if ((dev->curvol == 0) || (dev->muted)) - outb (0xd0, io); /* volume steady + sigstr */ + if (rt->curvol == 0 || rt->muted) + outb(0xd0, rt->io); /* volume steady + sigstr */ else - outb (0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } -static int rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack *rt) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} + int sig = 1; -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; + mutex_lock(&rt->lock); + if (inb(rt->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&rt->lock); + return sig; +} static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); strlcpy(v->card, "RadioTrack", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87*16000); - v->rangehigh = (108*16000); + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xffff*rt_getsigstr(rt); + v->signal = 0xffff * rt_getsigstr(rt); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -294,14 +287,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } @@ -309,14 +299,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = rt->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = rt->curvol * 6554; + ctrl->value = rt->curvol; return 0; } return -EINVAL; @@ -325,33 +315,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) rt_mute(rt); else - rt_setvol(rt,rt->curvol); + rt_setvol(rt, rt->curvol); return 0; case V4L2_CID_AUDIO_VOLUME: - rt_setvol(rt,ctrl->value); + rt_setvol(rt, ctrl->value); return 0; } return -EINVAL; } -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -360,36 +339,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack_exclusive_open(struct file *file) +static int rtrack_open(struct file *file) { - return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack_exclusive_release(struct file *file) +static int rtrack_release(struct file *file) { - clear_bit(0, &rtrack_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack_fops = { .owner = THIS_MODULE, - .open = rtrack_exclusive_open, - .release = rtrack_exclusive_release, + .open = rtrack_open, + .release = rtrack_release, .ioctl = video_ioctl2, }; @@ -408,64 +389,69 @@ static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device rtrack_radio = { - .name = "RadioTrack radio", - .fops = &rtrack_fops, - .ioctl_ops = &rtrack_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init rtrack_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct rtrack *rt = &rtrack_card; + struct v4l2_device *v4l2_dev = &rt->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); + rt->io = io; + + if (rt->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "rtrack")) - { - printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); + if (!request_region(rt->io, 2, "rtrack")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); return -EBUSY; } - video_set_drvdata(&rtrack_radio, &rtrack_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(rt->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); + return res; + } + + strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); + rt->vdev.v4l2_dev = v4l2_dev; + rt->vdev.fops = &rtrack_fops; + rt->vdev.ioctl_ops = &rtrack_ioctl_ops; + rt->vdev.release = video_device_release_empty; + video_set_drvdata(&rt->vdev, rt); - if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); return -EINVAL; } - printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ - mutex_init(&lock); + mutex_init(&rt->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0x48, io); /* volume down but still "on" */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xc0, io); /* steady volume, mute card */ - rtrack_unit.curvol = 0; + outb(0xc0, rt->io); /* steady volume, mute card */ return 0; } -MODULE_AUTHOR("M.Kirkwood"); -MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); -module_param(radio_nr, int, 0); - -static void __exit cleanup_rtrack_module(void) +static void __exit rtrack_exit(void) { - video_unregister_device(&rtrack_radio); - release_region(io,2); + struct rtrack *rt = &rtrack_card; + + video_unregister_device(&rt->vdev); + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); } module_init(rtrack_init); -module_exit(cleanup_rtrack_module); +module_exit(rtrack_exit); -- cgit v1.2.3 From e307d0fca84d4a54dd56ab786481a76e40f19d77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:18 +0100 Subject: radio-aztech: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aztech.c | 381 +++++++++++++++---------------- 1 file changed, 182 insertions(+), 199 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index d4d5babcd..dcf53edc2 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -29,34 +29,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Aztech radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -67,55 +50,64 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; -static struct mutex lock; -struct az_device +module_param(io, int, 0); +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct aztech { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int stereo; + struct mutex lock; }; +static struct aztech aztech_card; + static int volconvert(int level) { - level>>=14; /* Map 16bits down to 2 bit */ - level&=3; + level >>= 14; /* Map 16bits down to 2 bit */ + level &= 3; /* convert to card-friendly values */ - switch (level) - { - case 0: - return 0; - case 1: - return 1; - case 2: - return 4; - case 3: - return 5; + switch (level) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 4; + case 3: + return 5; } return 0; /* Quieten gcc */ } -static void send_0_byte (struct az_device *dev) +static void send_0_byte(struct aztech *az) { udelay(radio_wait_time); - outb_p(2+volconvert(dev->curvol), io); - outb_p(64+2+volconvert(dev->curvol), io); + outb_p(2 + volconvert(az->curvol), az->io); + outb_p(64 + 2 + volconvert(az->curvol), az->io); } -static void send_1_byte (struct az_device *dev) +static void send_1_byte(struct aztech *az) { udelay (radio_wait_time); - outb_p(128+2+volconvert(dev->curvol), io); - outb_p(128+64+2+volconvert(dev->curvol), io); + outb_p(128 + 2 + volconvert(az->curvol), az->io); + outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); } -static int az_setvol(struct az_device *dev, int vol) +static int az_setvol(struct aztech *az, int vol) { - mutex_lock(&lock); - outb (volconvert(vol), io); - mutex_unlock(&lock); + mutex_lock(&az->lock); + outb(volconvert(vol), az->io); + mutex_unlock(&az->lock); return 0; } @@ -127,116 +119,110 @@ static int az_setvol(struct az_device *dev, int vol) * */ -static int az_getsigstr(struct az_device *dev) +static int az_getsigstr(struct aztech *az) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&az->lock); + return sig; } -static int az_getstereo(struct az_device *dev) +static int az_getstereo(struct aztech *az) { - if (inb(io) & 1) /* bit set = mono */ - return 0; - return 1; /* stereo */ + int stereo = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 1) /* bit set = mono */ + stereo = 0; + mutex_unlock(&az->lock); + return stereo; } -static int az_setfreq(struct az_device *dev, unsigned long frequency) +static int az_setfreq(struct aztech *az, unsigned long frequency) { int i; + mutex_lock(&az->lock); + + az->curfreq = frequency; frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); - - send_0_byte (dev); /* 0: LSB of frequency */ + send_0_byte(az); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (frequency & (1 << i)) - send_1_byte (dev); + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_0_byte (dev); /* 14: test bit - always 0 */ - send_0_byte (dev); /* 15: test bit - always 0 */ - send_0_byte (dev); /* 16: band data 0 - always 0 */ - if (dev->stereo) /* 17: stereo (1 to enable) */ - send_1_byte (dev); + send_0_byte(az); /* 14: test bit - always 0 */ + send_0_byte(az); /* 15: test bit - always 0 */ + send_0_byte(az); /* 16: band data 0 - always 0 */ + if (az->stereo) /* 17: stereo (1 to enable) */ + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_1_byte (dev); /* 18: band data 1 - unknown */ - send_0_byte (dev); /* 19: time base - always 0 */ - send_0_byte (dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 23: AM/FM (FM = 1, always) */ + send_1_byte(az); /* 18: band data 1 - unknown */ + send_0_byte(az); /* 19: time base - always 0 */ + send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ /* latch frequency */ - udelay (radio_wait_time); - outb_p(128+64+volconvert(dev->curvol), io); + udelay(radio_wait_time); + outb_p(128 + 64 + volconvert(az->curvol), az->io); - mutex_unlock(&lock); + mutex_unlock(&az->lock); return 0; } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); - strlcpy(v->card, "Aztech Radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); + strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); + strlcpy(v->card, "Aztech Radio", sizeof(v->card)); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow=(87*16000); - v->rangehigh=(108*16000); - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(az_getstereo(az)) + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (az_getstereo(az)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xFFFF*az_getsigstr(az); + v->signal = 0xFFFF * az_getsigstr(az); return 0; } - -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; -} - -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) @@ -247,113 +233,107 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } - -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); - az->curfreq = f->frequency; - az_setfreq(az, az->curfreq); + az_setfreq(az, f->frequency); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; - return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return (0); - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, +static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (az->curvol==0) - ctrl->value=1; - else - ctrl->value=0; - return (0); - case V4L2_CID_AUDIO_VOLUME: - ctrl->value=az->curvol * 6554; - return (0); + case V4L2_CID_AUDIO_MUTE: + if (az->curvol == 0) + ctrl->value = 1; + else + ctrl->value = 0; + return 0; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = az->curvol * 6554; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, +static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - az_setvol(az,0); - } else { - az_setvol(az,az->curvol); - } - return (0); - case V4L2_CID_AUDIO_VOLUME: - az_setvol(az,ctrl->value); - return (0); + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) + az_setvol(az, 0); + else + az_setvol(az, az->curvol); + return 0; + case V4L2_CID_AUDIO_VOLUME: + az_setvol(az, ctrl->value); + return 0; } return -EINVAL; } -static struct az_device aztech_unit; - -static int aztech_exclusive_open(struct file *file) +static int aztech_open(struct file *file) { - return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; + return 0; } -static int aztech_exclusive_release(struct file *file) +static int aztech_release(struct file *file) { - clear_bit(0, &aztech_unit.in_use); return 0; } static const struct v4l2_file_operations aztech_fops = { .owner = THIS_MODULE, - .open = aztech_exclusive_open, - .release = aztech_exclusive_release, + .open = aztech_open, + .release = aztech_release, .ioctl = video_ioctl2, }; @@ -372,57 +352,60 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device aztech_radio = { - .name = "Aztech radio", - .fops = &aztech_fops, - .ioctl_ops = &aztech_ioctl_ops, - .release = video_device_release_empty, -}; - -module_param_named(debug,aztech_radio.debug, int, 0644); -MODULE_PARM_DESC(debug,"activates debug info"); - static int __init aztech_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct aztech *az = &aztech_card; + struct v4l2_device *v4l2_dev = &az->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); + az->io = io; + + if (az->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "aztech")) - { - printk(KERN_ERR "aztech: port 0x%x already in use\n", io); + if (!request_region(az->io, 2, "aztech")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); return -EBUSY; } - mutex_init(&lock); - video_set_drvdata(&aztech_radio, &aztech_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(az->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + mutex_init(&az->lock); + strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); + az->vdev.v4l2_dev = v4l2_dev; + az->vdev.fops = &aztech_fops; + az->vdev.ioctl_ops = &aztech_ioctl_ops; + az->vdev.release = video_device_release_empty; + video_set_drvdata(&az->vdev, az); + + if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(az->io, 2); return -EINVAL; } - printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); + v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); /* mute card - prevents noisy bootups */ - outb (0, io); + outb(0, az->io); return 0; } -MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Aztech radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -module_param(radio_nr, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); - -static void __exit aztech_cleanup(void) +static void __exit aztech_exit(void) { - video_unregister_device(&aztech_radio); - release_region(io,2); + struct aztech *az = &aztech_card; + + video_unregister_device(&az->vdev); + v4l2_device_unregister(&az->v4l2_dev); + release_region(az->io, 2); } module_init(aztech_init); -module_exit(aztech_cleanup); +module_exit(aztech_exit); -- cgit v1.2.3 From cbc98821002e4065b69ce74c892bb9ad2085428f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:47 +0100 Subject: radio-cadet: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-cadet.c | 622 ++++++++++++++++---------------- 1 file changed, 307 insertions(+), 315 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 7425aef88..03e76bc74 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -35,363 +35,346 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* V4L2 API defs */ -#include -#include #include #include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" + +MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); +MODULE_LICENSE("GPL"); + +static int io = -1; /* default to isapnp activation */ +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); +module_param(radio_nr, int, 0); + +#define CADET_VERSION KERNEL_VERSION(0, 3, 3) #define RDS_BUFFER 256 #define RDS_RX_FLAG 1 #define MBS_RX_FLAG 2 -#define CADET_VERSION KERNEL_VERSION(0,3,3) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } +struct cadet { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int users; + int curtuner; + int tunestat; + int sigstrength; + wait_queue_head_t read_queue; + struct timer_list readtimer; + __u8 rdsin, rdsout, rdsstat; + unsigned char rdsbuf[RDS_BUFFER]; + struct mutex lock; + int reading; }; -static int io=-1; /* default to isapnp activation */ -static int radio_nr = -1; -static int users; -static int curtuner; -static int tunestat; -static int sigstrength; -static wait_queue_head_t read_queue; -static struct timer_list readtimer; -static __u8 rdsin, rdsout, rdsstat; -static unsigned char rdsbuf[RDS_BUFFER]; -static spinlock_t cadet_io_lock; - -static int cadet_probe(void); +static struct cadet cadet_card; /* * Signal Strength Threshold Values * The V4L API spec does not define any particular unit for the signal * strength value. These values are in microvolts of RF at the tuner's input. */ -static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; +static __u16 sigtable[2][4] = { + { 5, 10, 30, 150 }, + { 28, 40, 63, 1000 } +}; #if 0 /* Note: cadet_getrds() is not used at the moment. It will be useful for future extensions, e.g. an ioctl to query RDS reception quality. - Hans J. Koch */ -static int -cadet_getrds(void) +static int cadet_getrds(struct cadet *dev) { - int rds_mbs_stat=0; + int rds_mbs_stat = 0; - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + outb(inb(dev->io + 1) & 0x7f, dev->io + 1); /* Reset RDS detection */ + mutex_unlock(&dev->lock); msleep(100); - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - if((inb(io+1)&0x80)!=0) { + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + if ((inb(dev->io + 1) & 0x80) != 0) rds_mbs_stat |= RDS_RX_FLAG; - } - if((inb(io+1)&0x10)!=0) { + if ((inb(dev->io + 1) & 0x10) != 0) rds_mbs_stat |= MBS_RX_FLAG; - } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return rds_mbs_stat; } #endif -static int -cadet_getstereo(void) +static int cadet_getstereo(struct cadet *dev) { int ret = V4L2_TUNER_SUB_MONO; - if(curtuner != 0) /* Only FM has stereo capability! */ + + if (dev->curtuner != 0) /* Only FM has stereo capability! */ return V4L2_TUNER_SUB_MONO; - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if( (inb(io+1) & 0x40) == 0) + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x40) == 0) ret = V4L2_TUNER_SUB_STEREO; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static unsigned -cadet_gettune(void) +static unsigned cadet_gettune(struct cadet *dev) { - int curvol,i; - unsigned fifo=0; + int curvol, i; + unsigned fifo = 0; /* * Prepare for read */ - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); /* Save current volume/mute setting */ - outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ - tunestat=0xffff; + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); /* Save current volume/mute setting */ + outb(0x00, dev->io + 1); /* Ensure WRITE-ENABLE is LOW */ + dev->tunestat = 0xffff; /* * Read the shift register */ - for(i=0;i<25;i++) { - fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); - if(i<24) { - outb(0x01,io+1); - tunestat&=inb(io+1); - outb(0x00,io+1); + for (i = 0; i < 25; i++) { + fifo = (fifo << 1) | ((inb(dev->io + 1) >> 7) & 0x01); + if (i < 24) { + outb(0x01, dev->io + 1); + dev->tunestat &= inb(dev->io + 1); + outb(0x00, dev->io + 1); } } /* * Restore volume/mute setting */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); return fifo; } -static unsigned -cadet_getfreq(void) +static unsigned cadet_getfreq(struct cadet *dev) { int i; - unsigned freq=0,test,fifo=0; + unsigned freq = 0, test, fifo = 0; /* * Read current tuning */ - fifo=cadet_gettune(); + fifo = cadet_gettune(dev); /* * Convert to actual frequency */ - if(curtuner==0) { /* FM */ - test=12500; - for(i=0;i<14;i++) { - if((fifo&0x01)!=0) { - freq+=test; - } - test=test<<1; - fifo=fifo>>1; + if (dev->curtuner == 0) { /* FM */ + test = 12500; + for (i = 0; i < 14; i++) { + if ((fifo & 0x01) != 0) + freq += test; + test = test << 1; + fifo = fifo >> 1; } - freq-=10700000; /* IF frequency is 10.7 MHz */ - freq=(freq*16)/1000000; /* Make it 1/16 MHz */ - } - if(curtuner==1) { /* AM */ - freq=((fifo&0x7fff)-2010)*16; + freq -= 10700000; /* IF frequency is 10.7 MHz */ + freq = (freq * 16) / 1000000; /* Make it 1/16 MHz */ } + if (dev->curtuner == 1) /* AM */ + freq = ((fifo & 0x7fff) - 2010) * 16; return freq; } -static void -cadet_settune(unsigned fifo) +static void cadet_settune(struct cadet *dev, unsigned fifo) { int i; unsigned test; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ + outb(7, dev->io); /* Select tuner control */ /* * Write the shift register */ - test=0; - test=(fifo>>23)&0x02; /* Align data for SDO */ - test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ - outb(7,io); /* Select tuner control */ - outb(test,io+1); /* Initialize for write */ - for(i=0;i<25;i++) { - test|=0x01; /* Toggle SCK High */ - outb(test,io+1); - test&=0xfe; /* Toggle SCK Low */ - outb(test,io+1); - fifo=fifo<<1; /* Prepare the next bit */ - test=0x1c|((fifo>>23)&0x02); - outb(test,io+1); + test = 0; + test = (fifo >> 23) & 0x02; /* Align data for SDO */ + test |= 0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ + outb(7, dev->io); /* Select tuner control */ + outb(test, dev->io + 1); /* Initialize for write */ + for (i = 0; i < 25; i++) { + test |= 0x01; /* Toggle SCK High */ + outb(test, dev->io + 1); + test &= 0xfe; /* Toggle SCK Low */ + outb(test, dev->io + 1); + fifo = fifo << 1; /* Prepare the next bit */ + test = 0x1c | ((fifo >> 23) & 0x02); + outb(test, dev->io + 1); } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } -static void -cadet_setfreq(unsigned freq) +static void cadet_setfreq(struct cadet *dev, unsigned freq) { unsigned fifo; - int i,j,test; + int i, j, test; int curvol; /* * Formulate a fifo command */ - fifo=0; - if(curtuner==0) { /* FM */ - test=102400; - freq=(freq*1000)/16; /* Make it kHz */ - freq+=10700; /* IF is 10700 kHz */ - for(i=0;i<14;i++) { - fifo=fifo<<1; - if(freq>=test) { - fifo|=0x01; - freq-=test; + fifo = 0; + if (dev->curtuner == 0) { /* FM */ + test = 102400; + freq = (freq * 1000) / 16; /* Make it kHz */ + freq += 10700; /* IF is 10700 kHz */ + for (i = 0; i < 14; i++) { + fifo = fifo << 1; + if (freq >= test) { + fifo |= 0x01; + freq -= test; } - test=test>>1; + test = test >> 1; } } - if(curtuner==1) { /* AM */ - fifo=(freq/16)+2010; /* Make it kHz */ - fifo|=0x100000; /* Select AM Band */ + if (dev->curtuner == 1) { /* AM */ + fifo = (freq / 16) + 2010; /* Make it kHz */ + fifo |= 0x100000; /* Select AM Band */ } /* * Save current volume/mute setting */ - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); + mutex_unlock(&dev->lock); /* * Tune the card */ - for(j=3;j>-1;j--) { - cadet_settune(fifo|(j<<16)); + for (j = 3; j > -1; j--) { + cadet_settune(dev, fifo | (j << 16)); - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); msleep(100); - cadet_gettune(); - if((tunestat & 0x40) == 0) { /* Tuned */ - sigstrength=sigtable[curtuner][j]; + cadet_gettune(dev); + if ((dev->tunestat & 0x40) == 0) { /* Tuned */ + dev->sigstrength = sigtable[dev->curtuner][j]; return; } } - sigstrength=0; + dev->sigstrength = 0; } -static int -cadet_getvol(void) +static int cadet_getvol(struct cadet *dev) { int ret = 0; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - if((inb(io + 1) & 0x20) != 0) + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x20) != 0) ret = 0xffff; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static void -cadet_setvol(int vol) +static void cadet_setvol(struct cadet *dev, int vol) { - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if(vol>0) - outb(0x20,io+1); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if (vol > 0) + outb(0x20, dev->io + 1); else - outb(0x00,io+1); - spin_unlock(&cadet_io_lock); + outb(0x00, dev->io + 1); + mutex_unlock(&dev->lock); } -static void -cadet_handler(unsigned long data) +static void cadet_handler(unsigned long data) { - /* - * Service the RDS fifo - */ + struct cadet *dev = (void *)data; - if(spin_trylock(&cadet_io_lock)) - { - outb(0x3,io); /* Select RDS Decoder Control */ - if((inb(io+1)&0x20)!=0) { + /* Service the RDS fifo */ + if (mutex_trylock(&dev->lock)) { + outb(0x3, dev->io); /* Select RDS Decoder Control */ + if ((inb(dev->io + 1) & 0x20) != 0) printk(KERN_CRIT "cadet: RDS fifo overflow\n"); - } - outb(0x80,io); /* Select RDS fifo */ - while((inb(io)&0x80)!=0) { - rdsbuf[rdsin]=inb(io+1); - if(rdsin==rdsout) + outb(0x80, dev->io); /* Select RDS fifo */ + while ((inb(dev->io) & 0x80) != 0) { + dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); + if (dev->rdsin == dev->rdsout) printk(KERN_WARNING "cadet: RDS buffer overflow\n"); else - rdsin++; + dev->rdsin++; } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } /* * Service pending read */ - if( rdsin!=rdsout) - wake_up_interruptible(&read_queue); + if (dev->rdsin != dev->rdsout) + wake_up_interruptible(&dev->read_queue); /* * Clean up and exit */ - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)0; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - -static ssize_t -cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - int i=0; + struct cadet *dev = video_drvdata(file); unsigned char readbuf[RDS_BUFFER]; - - if(rdsstat==0) { - spin_lock(&cadet_io_lock); - rdsstat=1; - outb(0x80,io); /* Select RDS fifo */ - spin_unlock(&cadet_io_lock); - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + int i = 0; + + if (dev->rdsstat == 0) { + mutex_lock(&dev->lock); + dev->rdsstat = 1; + outb(0x80, dev->io); /* Select RDS fifo */ + mutex_unlock(&dev->lock); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)dev; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - if(rdsin==rdsout) { + if (dev->rdsin == dev->rdsout) { if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - interruptible_sleep_on(&read_queue); + interruptible_sleep_on(&dev->read_queue); } - while( irdsin != dev->rdsout) + readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - if (copy_to_user(data,readbuf,i)) + if (copy_to_user(data, readbuf, i)) return -EFAULT; return i; } @@ -400,38 +383,40 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - v->capabilities = - V4L2_CAP_TUNER | - V4L2_CAP_READWRITE; + strlcpy(v->driver, "ADS Cadet", sizeof(v->driver)); + strlcpy(v->card, "ADS Cadet", sizeof(v->card)); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = CADET_VERSION; - strcpy(v->driver, "ADS Cadet"); - strcpy(v->card, "ADS Cadet"); + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct cadet *dev = video_drvdata(file); + v->type = V4L2_TUNER_RADIO; switch (v->index) { case 0: - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_STEREO; v->rangelow = 1400; /* 87.5 MHz */ v->rangehigh = 1728; /* 108.0 MHz */ - v->rxsubchans=cadet_getstereo(); - switch (v->rxsubchans){ + v->rxsubchans = cadet_getstereo(dev); + switch (v->rxsubchans) { case V4L2_TUNER_SUB_MONO: v->audmode = V4L2_TUNER_MODE_MONO; break; case V4L2_TUNER_SUB_STEREO: v->audmode = V4L2_TUNER_MODE_STEREO; break; - default: ; + default: + break; } break; case 1: - strcpy(v->name, "AM"); + strlcpy(v->name, "AM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_LOW; v->rangelow = 8320; /* 520 kHz */ v->rangehigh = 26400; /* 1650 kHz */ @@ -441,25 +426,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, default: return -EINVAL; } - v->signal = sigstrength; /* We might need to modify scaling of this */ + v->signal = dev->sigstrength; /* We might need to modify scaling of this */ return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if((v->index != 0)&&(v->index != 1)) + struct cadet *dev = video_drvdata(file); + + if (v->index != 0 && v->index != 1) return -EINVAL; - curtuner = v->index; + dev->curtuner = v->index; return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - f->tuner = curtuner; + struct cadet *dev = video_drvdata(file); + + f->tuner = dev->curtuner; f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(); + f->frequency = cadet_getfreq(dev); return 0; } @@ -467,27 +456,26 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct cadet *dev = video_drvdata(file); + if (f->type != V4L2_TUNER_RADIO) return -EINVAL; - if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) + if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728)) return -EINVAL; - if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) + if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400)) return -EINVAL; - cadet_setfreq(f->frequency); + cadet_setfreq(dev, f->frequency); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } @@ -495,12 +483,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - switch (ctrl->id){ + struct cadet *dev = video_drvdata(file); + + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - ctrl->value = (cadet_getvol() == 0); + ctrl->value = (cadet_getvol(dev) == 0); break; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = cadet_getvol(); + ctrl->value = cadet_getvol(dev); break; default: return -EINVAL; @@ -511,15 +501,17 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct cadet *dev = video_drvdata(file); + switch (ctrl->id){ case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ if (ctrl->value) - cadet_setvol(0); + cadet_setvol(dev, 0); else - cadet_setvol(0xffff); + cadet_setvol(dev, 0xffff); break; case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(ctrl->value); + cadet_setvol(dev, ctrl->value); break; default: return -EINVAL; @@ -527,16 +519,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return 0; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -545,43 +527,52 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int -cadet_open(struct file *file) +static int cadet_open(struct file *file) { - users++; - if (1 == users) init_waitqueue_head(&read_queue); + struct cadet *dev = video_drvdata(file); + + dev->users++; + if (1 == dev->users) + init_waitqueue_head(&dev->read_queue); return 0; } -static int -cadet_release(struct file *file) +static int cadet_release(struct file *file) { - users--; - if (0 == users){ - del_timer_sync(&readtimer); - rdsstat=0; + struct cadet *dev = video_drvdata(file); + + dev->users--; + if (0 == dev->users) { + del_timer_sync(&dev->readtimer); + dev->rdsstat = 0; } return 0; } -static unsigned int -cadet_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { - poll_wait(file,&read_queue,wait); - if(rdsin != rdsout) + struct cadet *dev = video_drvdata(file); + + poll_wait(file, &dev->read_queue, wait); + if (dev->rdsin != dev->rdsout) return POLLIN | POLLRDNORM; return 0; } @@ -611,13 +602,6 @@ static const struct v4l2_ioctl_ops cadet_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device cadet_radio = { - .name = "Cadet radio", - .fops = &cadet_fops, - .ioctl_ops = &cadet_ioctl_ops, - .release = video_device_release_empty, -}; - #ifdef CONFIG_PNP static struct pnp_device_id cadet_pnp_devices[] = { @@ -628,7 +612,7 @@ static struct pnp_device_id cadet_pnp_devices[] = { MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices); -static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +static int cadet_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { if (!dev) return -ENODEV; @@ -636,13 +620,12 @@ static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev if (io > 0) return -EBUSY; - if (!pnp_port_valid(dev, 0)) { + if (!pnp_port_valid(dev, 0)) return -ENODEV; - } io = pnp_port_start(dev, 0); - printk ("radio-cadet: PnP reports device at %#x\n", io); + printk(KERN_INFO "radio-cadet: PnP reports device at %#x\n", io); return io; } @@ -658,23 +641,23 @@ static struct pnp_driver cadet_pnp_driver = { static struct pnp_driver cadet_pnp_driver; #endif -static int cadet_probe(void) +static void cadet_probe(struct cadet *dev) { - static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; + static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e }; int i; - for(i=0;i<8;i++) { - io=iovals[i]; - if (request_region(io, 2, "cadet-probe")) { - cadet_setfreq(1410); - if(cadet_getfreq()==1410) { - release_region(io, 2); - return io; + for (i = 0; i < 8; i++) { + dev->io = iovals[i]; + if (request_region(dev->io, 2, "cadet-probe")) { + cadet_setfreq(dev, 1410); + if (cadet_getfreq(dev) == 1410) { + release_region(dev->io, 2); + return; } - release_region(io, 2); + release_region(dev->io, 2); } } - return -1; + dev->io = -1; } /* @@ -684,59 +667,68 @@ static int cadet_probe(void) static int __init cadet_init(void) { - spin_lock_init(&cadet_io_lock); + struct cadet *dev = &cadet_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; - /* - * If a probe was requested then probe ISAPnP first (safest) - */ + strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); + mutex_init(&dev->lock); + + /* If a probe was requested then probe ISAPnP first (safest) */ if (io < 0) pnp_register_driver(&cadet_pnp_driver); - /* - * If that fails then probe unsafely if probe is requested - */ - if(io < 0) - io = cadet_probe (); + dev->io = io; - /* - * Else we bail out - */ + /* If that fails then probe unsafely if probe is requested */ + if (dev->io < 0) + cadet_probe(dev); - if(io < 0) { + /* Else we bail out */ + if (dev->io < 0) { #ifdef MODULE - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); #endif goto fail; } - if (!request_region(io,2,"cadet")) + if (!request_region(dev->io, 2, "cadet")) goto fail; - if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); goto fail; } - printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &cadet_fops; + dev->vdev.ioctl_ops = &cadet_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 2); + goto fail; + } + v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io); return 0; fail: pnp_unregister_driver(&cadet_pnp_driver); - return -1; + return -ENODEV; } - - -MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); -module_param(radio_nr, int, 0); - -static void __exit cadet_cleanup_module(void) +static void __exit cadet_exit(void) { - video_unregister_device(&cadet_radio); - release_region(io,2); + struct cadet *dev = &cadet_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 2); pnp_unregister_driver(&cadet_pnp_driver); } module_init(cadet_init); -module_exit(cadet_cleanup_module); +module_exit(cadet_exit); -- cgit v1.2.3 From 4a0a23dc3b75fa7ca0bb514cb7ad2a51eb2236eb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:07 +0100 Subject: radio-gemtek-pci: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek-pci.c | 340 +++++++++++++-------------- 1 file changed, 165 insertions(+), 175 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index 7edd3e594..b68e2ba4c 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -44,36 +44,28 @@ #include #include #include -#include "compat.h" #include -#include -#include #include - #include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +#include +#include +#include +#include +#include "compat.h" -#include -#include +MODULE_AUTHOR("Vladimir Shebordaev "); +MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card"); +MODULE_LICENSE("GPL"); + +static int nr_radio = -1; +static int mx = 1; + +module_param(mx, bool, 0); +MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not"); +module_param(nr_radio, int, 0); +MODULE_PARM_DESC(nr_radio, "video4linux device number to use"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) #ifndef PCI_VENDOR_ID_GEMTEK #define PCI_VENDOR_ID_GEMTEK 0x5046 @@ -91,8 +83,11 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define GEMTEK_PCI_RANGE_HIGH (108*16000) #endif -struct gemtek_pci_card { - struct video_device *videodev; +struct gemtek_pci { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + struct pci_dev *pdev; u32 iobase; u32 length; @@ -101,116 +96,133 @@ struct gemtek_pci_card { u8 mute; }; -static int nr_radio = -1; -static unsigned long in_use; +static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev); +} -static inline u8 gemtek_pci_out( u16 value, u32 port ) +static inline u8 gemtek_pci_out(u16 value, u32 port) { - outw( value, port ); + outw(value, port); return (u8)value; } -#define _b0( v ) *((u8 *)&v) -static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) +#define _b0(v) (*((u8 *)&v)) + +static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep) { - register u8 byte = *last_byte; + u8 byte = *last_byte; - if ( !value ) { - if ( !keep ) + if (!value) { + if (!keep) value = (u16)port; byte &= 0xfd; } else byte |= 2; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte |= 1; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte &= 0xfe; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); *last_byte = byte; } -static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) +static inline void gemtek_pci_nil(u32 port, u8 *last_byte) { - __gemtek_pci_cmd( 0x00, port, last_byte, false ); + __gemtek_pci_cmd(0x00, port, last_byte, false); } -static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) +static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte) { - __gemtek_pci_cmd( cmd, port, last_byte, true ); + __gemtek_pci_cmd(cmd, port, last_byte, true); } -static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) +static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency) { - register int i; - register u32 value = frequency / 200 + 856; - register u16 mask = 0x8000; + int i; + u32 value = frequency / 200 + 856; + u16 mask = 0x8000; u8 last_byte; u32 port = card->iobase; - last_byte = gemtek_pci_out( 0x06, port ); + mutex_lock(&card->lock); + card->current_frequency = frequency; + last_byte = gemtek_pci_out(0x06, port); i = 0; do { - gemtek_pci_nil( port, &last_byte ); + gemtek_pci_nil(port, &last_byte); i++; - } while ( i < 9 ); + } while (i < 9); i = 0; do { - gemtek_pci_cmd( value & mask, port, &last_byte ); + gemtek_pci_cmd(value & mask, port, &last_byte); mask >>= 1; i++; - } while ( i < 16 ); + } while (i < 16); - outw( 0x10, port ); + outw(0x10, port); + mutex_unlock(&card->lock); } -static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) +static void gemtek_pci_mute(struct gemtek_pci *card) { - outb( 0x1f, card->iobase ); + mutex_lock(&card->lock); + outb(0x1f, card->iobase); card->mute = true; + mutex_unlock(&card->lock); } -static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) +static void gemtek_pci_unmute(struct gemtek_pci *card) { - if ( card->mute ) { - gemtek_pci_setfrequency( card, card->current_frequency ); + mutex_lock(&card->lock); + if (card->mute) { + gemtek_pci_setfrequency(card, card->current_frequency); card->mute = false; } + mutex_unlock(&card->lock); } -static inline unsigned int gemtek_pci_getsignal( struct gemtek_pci_card *card ) +static int gemtek_pci_getsignal(struct gemtek_pci *card) { - return ( inb( card->iobase ) & 0x08 ) ? 0 : 1; + int sig; + + mutex_lock(&card->lock); + sig = (inb(card->iobase) & 0x08) ? 0 : 1; + mutex_unlock(&card->lock); + return sig; } static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct gemtek_pci *card = video_drvdata(file); + strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = GEMTEK_PCI_RANGE_LOW; v->rangehigh = GEMTEK_PCI_RANGE_HIGH; @@ -224,21 +236,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); - if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || - (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) + if (f->frequency < GEMTEK_PCI_RANGE_LOW || + f->frequency > GEMTEK_PCI_RANGE_HIGH) return -EINVAL; gemtek_pci_setfrequency(card, f->frequency); - card->current_frequency = f->frequency; card->mute = false; return 0; } @@ -246,7 +255,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; @@ -256,13 +265,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); } return -EINVAL; } @@ -270,7 +277,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -289,7 +296,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -308,17 +315,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -327,17 +323,22 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } enum { @@ -355,25 +356,22 @@ static struct pci_device_id gemtek_pci_id[] = { 0 } }; -MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); - -static int mx = 1; +MODULE_DEVICE_TABLE(pci, gemtek_pci_id); -static int gemtek_pci_exclusive_open(struct file *file) +static int gemtek_pci_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_pci_exclusive_release(struct file *file) +static int gemtek_pci_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .open = gemtek_pci_exclusive_open, - .release = gemtek_pci_exclusive_release, + .open = gemtek_pci_open, + .release = gemtek_pci_release, .ioctl = video_ioctl2, }; @@ -392,114 +390,106 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device vdev_template = { - .name = "Gemtek PCI Radio", - .fops = &gemtek_pci_fops, - .ioctl_ops = &gemtek_pci_ioctl_ops, - .release = video_device_release_empty, -}; - -static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) +static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { - struct gemtek_pci_card *card; - struct video_device *devradio; + struct gemtek_pci *card; + struct v4l2_device *v4l2_dev; + int res; - if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); + card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL); + if (card == NULL) { + dev_err(&pdev->dev, "out of memory\n"); return -ENOMEM; } - if ( pci_enable_device( pci_dev ) ) - goto err_pci; + v4l2_dev = &card->v4l2_dev; + mutex_init(&card->lock); + card->pdev = pdev; - card->iobase = pci_resource_start( pci_dev, 0 ); - card->length = pci_resource_len( pci_dev, 0 ); + strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name)); - if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) { - printk( KERN_ERR "gemtek_pci: i/o port already in use\n" ); - goto err_pci; + res = v4l2_device_register(&pdev->dev, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + kfree(card); + return res; } - pci_set_drvdata( pci_dev, card ); + if (pci_enable_device(pdev)) + goto err_pci; - if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); - goto err_video; + card->iobase = pci_resource_start(pdev, 0); + card->length = pci_resource_len(pdev, 0); + + if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { + v4l2_err(v4l2_dev, "i/o port already in use\n"); + goto err_pci; } - *devradio = vdev_template; - if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) { - kfree( devradio ); + strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name)); + card->vdev.v4l2_dev = v4l2_dev; + card->vdev.fops = &gemtek_pci_fops; + card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops; + card->vdev.release = video_device_release_empty; + video_set_drvdata(&card->vdev, card); + + if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0) goto err_video; - } - card->videodev = devradio; - video_set_drvdata(devradio, card); - gemtek_pci_mute( card ); + gemtek_pci_mute(card); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - pci_dev->revision, card->iobase, card->iobase + card->length - 1 ); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + pdev->revision, card->iobase, card->iobase + card->length - 1); #else - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - v4l_compat_pci_rev(pci_dev), card->iobase, - card->iobase + card->length - 1 ); + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + v4l_compat_pci_rev(pdev), card->iobase, + card->iobase + card->length - 1); #endif return 0; err_video: - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); err_pci: - kfree( card ); + v4l2_device_unregister(v4l2_dev); + kfree(card); return -ENODEV; } -static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev ) +static void __devexit gemtek_pci_remove(struct pci_dev *pdev) { - struct gemtek_pci_card *card = pci_get_drvdata( pci_dev ); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct gemtek_pci *card = to_gemtek_pci(v4l2_dev); - video_unregister_device( card->videodev ); - kfree( card->videodev ); + video_unregister_device(&card->vdev); + v4l2_device_unregister(v4l2_dev); - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); - if ( mx ) - gemtek_pci_mute( card ); + if (mx) + gemtek_pci_mute(card); - kfree( card ); - - pci_set_drvdata( pci_dev, NULL ); + kfree(card); } -static struct pci_driver gemtek_pci_driver = -{ +static struct pci_driver gemtek_pci_driver = { .name = "gemtek_pci", .id_table = gemtek_pci_id, .probe = gemtek_pci_probe, .remove = __devexit_p(gemtek_pci_remove), }; -static int __init gemtek_pci_init_module( void ) +static int __init gemtek_pci_init(void) { - return pci_register_driver( &gemtek_pci_driver ); + return pci_register_driver(&gemtek_pci_driver); } -static void __exit gemtek_pci_cleanup_module( void ) +static void __exit gemtek_pci_exit(void) { pci_unregister_driver(&gemtek_pci_driver); } -MODULE_AUTHOR( "Vladimir Shebordaev " ); -MODULE_DESCRIPTION( "The video4linux driver for the Gemtek PCI Radio Card" ); -MODULE_LICENSE("GPL"); - -module_param(mx, bool, 0); -MODULE_PARM_DESC( mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not" ); -module_param(nr_radio, int, 0); -MODULE_PARM_DESC( nr_radio, "video4linux device number to use"); - -module_init( gemtek_pci_init_module ); -module_exit( gemtek_pci_cleanup_module ); - +module_init(gemtek_pci_init); +module_exit(gemtek_pci_exit); -- cgit v1.2.3 From 48a5a5d79f817cd2646721c2deaf2a357a5f4f7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:42 +0100 Subject: radio-gemtek: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek.c | 399 +++++++++++++++---------------- 1 file changed, 188 insertions(+), 211 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index a1ae890c8..0cb1cb0a1 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -20,17 +20,16 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ +#include /* for KERNEL_VERSION MACRO */ +#include +#include /* outb, outb_p */ +#include /* copy to/from user */ #include -#include -#include +#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,3) -#define RADIO_BANNER "GemTek Radio card driver: v0.0.3" +#define RADIO_VERSION KERNEL_VERSION(0, 0, 3) /* * Module info. @@ -58,7 +57,6 @@ static int shutdown = 1; static int keepmuted = 1; static int initmute = 1; static int radio_nr = -1; -static unsigned long in_use; module_param(io, int, 0444); MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " @@ -113,12 +111,19 @@ module_param(radio_nr, int, 0444); #define SHORT_DELAY 5 /* usec */ #define LONG_DELAY 75 /* usec */ -struct gemtek_device { +struct gemtek { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; unsigned long lastfreq; int muted; + int verified; + int io; u32 bu2614data; }; +static struct gemtek gemtek_card; + #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ #define BU2614_VOID_BITS 4 /* unused */ @@ -154,10 +159,6 @@ struct gemtek_device { #define BU2614_FMUN_MASK MKMASK(FMUN) #define BU2614_TEST_MASK MKMASK(TEST) -static struct gemtek_device gemtek_unit; - -static spinlock_t lock; - /* * Set data which will be sent to BU2614FS. */ @@ -167,33 +168,33 @@ static spinlock_t lock; /* * Transmit settings to BU2614FS over GemTek IC. */ -static void gemtek_bu2614_transmit(struct gemtek_device *dev) +static void gemtek_bu2614_transmit(struct gemtek *gt) { int i, bit, q, mute; - spin_lock(&lock); + mutex_lock(>->lock); - mute = dev->muted ? GEMTEK_MT : 0x00; + mute = gt->muted ? GEMTEK_MT : 0x00; - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) { - bit = (q & 1) ? GEMTEK_DA : 0; - outb_p(mute | GEMTEK_CE | bit, io); - udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io); - udelay(SHORT_DELAY); + for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { + bit = (q & 1) ? GEMTEK_DA : 0; + outb_p(mute | GEMTEK_CE | bit, gt->io); + udelay(SHORT_DELAY); + outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); + udelay(SHORT_DELAY); } - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - spin_unlock(&lock); + mutex_unlock(>->lock); } /* @@ -207,107 +208,109 @@ static unsigned long gemtek_convfreq(unsigned long freq) /* * Set FM-frequency. */ -static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) +static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) { - - if (keepmuted && hardmute && dev->muted) + if (keepmuted && hardmute && gt->muted) return; - if (freq < GEMTEK_LOWFREQ) - freq = GEMTEK_LOWFREQ; - else if (freq > GEMTEK_HIGHFREQ) - freq = GEMTEK_HIGHFREQ; + freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); - dev->lastfreq = freq; - dev->muted = 0; + gt->lastfreq = freq; + gt->muted = 0; - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); - gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq)); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); + gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); - gemtek_bu2614_transmit(dev); + gemtek_bu2614_transmit(gt); } /* * Set mute flag. */ -static void gemtek_mute(struct gemtek_device *dev) +static void gemtek_mute(struct gemtek *gt) { int i; - dev->muted = 1; + + gt->muted = 1; if (hardmute) { /* Turn off PLL, disable data output */ - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */ - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF); - gemtek_bu2614_set(dev, BU2614_FREQ, 0); - gemtek_bu2614_transmit(dev); - } else { - spin_lock(&lock); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 0); /* GT bit off */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); + gemtek_bu2614_set(gt, BU2614_FREQ, 0); + gemtek_bu2614_transmit(gt); + return; + } - /* Read bus contents (CE, CK and DA). */ - i = inb_p(io); - /* Write it back with mute flag set. */ - outb_p((i >> 5) | GEMTEK_MT, io); - udelay(SHORT_DELAY); + mutex_lock(>->lock); - spin_unlock(&lock); - } + /* Read bus contents (CE, CK and DA). */ + i = inb_p(gt->io); + /* Write it back with mute flag set. */ + outb_p((i >> 5) | GEMTEK_MT, gt->io); + udelay(SHORT_DELAY); + + mutex_unlock(>->lock); } /* * Unset mute flag. */ -static void gemtek_unmute(struct gemtek_device *dev) +static void gemtek_unmute(struct gemtek *gt) { int i; - dev->muted = 0; + gt->muted = 0; if (hardmute) { /* Turn PLL back on. */ - gemtek_setfreq(dev, dev->lastfreq); - } else { - spin_lock(&lock); + gemtek_setfreq(gt, gt->lastfreq); + return; + } + mutex_lock(>->lock); - i = inb_p(io); - outb_p(i >> 5, io); - udelay(SHORT_DELAY); + i = inb_p(gt->io); + outb_p(i >> 5, gt->io); + udelay(SHORT_DELAY); - spin_unlock(&lock); - } + mutex_unlock(>->lock); } /* * Get signal strength (= stereo status). */ -static inline int gemtek_getsigstr(void) +static inline int gemtek_getsigstr(struct gemtek *gt) { - return inb_p(io) & GEMTEK_NS ? 0 : 1; + int sig; + + mutex_lock(>->lock); + sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; + mutex_unlock(>->lock); + return sig; } /* * Check if requested card acts like GemTek Radio card. */ -static int gemtek_verify(int port) +static int gemtek_verify(struct gemtek *gt, int port) { - static int verified = -1; int i, q; - if (verified == port) + if (gt->verified == port) return 1; - spin_lock(&lock); + mutex_lock(>->lock); q = inb_p(port); /* Read bus contents before probing. */ /* Try to turn on CE, CK and DA respectively and check if card responds @@ -317,15 +320,15 @@ static int gemtek_verify(int port) udelay(SHORT_DELAY); if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { - spin_unlock(&lock); + mutex_unlock(>->lock); return 0; } } outb_p(q >> 5, port); /* Write bus contents back. */ udelay(SHORT_DELAY); - spin_unlock(&lock); - verified = port; + mutex_unlock(>->lock); + gt->verified = port; return 1; } @@ -333,83 +336,61 @@ static int gemtek_verify(int port) /* * Automatic probing for card. */ -static int gemtek_probe(void) +static int gemtek_probe(struct gemtek *gt) { + struct v4l2_device *v4l2_dev = >->v4l2_dev; int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; int i; if (!probe) { - printk(KERN_INFO "Automatic device probing disabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); return -1; } - printk(KERN_INFO "Automatic device probing enabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); for (i = 0; i < ARRAY_SIZE(ioports); ++i) { - printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]); + v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); if (!request_region(ioports[i], 1, "gemtek-probe")) { - printk(KERN_WARNING "I/O port 0x%x busy!\n", + v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", ioports[i]); continue; } - if (gemtek_verify(ioports[i])) { - printk(KERN_INFO "Card found from I/O port " + if (gemtek_verify(gt, ioports[i])) { + v4l2_info(v4l2_dev, "Card found from I/O port " "0x%x!\n", ioports[i]); release_region(ioports[i], 1); - - io = ioports[i]; - return io; + gt->io = ioports[i]; + return gt->io; } release_region(ioports[i], 1); } - printk(KERN_ERR "Automatic probing failed!\n"); - + v4l2_err(v4l2_dev, "Automatic probing failed!\n"); return -1; } /* * Video 4 Linux stuff. */ - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - -static int gemtek_exclusive_open(struct file *file) +static int gemtek_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_exclusive_release(struct file *file) +static int gemtek_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, - .open = gemtek_exclusive_open, - .release = gemtek_exclusive_release, + .open = gemtek_open, + .release = gemtek_release, .ioctl = video_ioctl2, }; @@ -418,23 +399,25 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); strlcpy(v->card, "GemTek", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct gemtek *gt = video_drvdata(file); + if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = GEMTEK_LOWFREQ; v->rangehigh = GEMTEK_HIGHFREQ; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - v->signal = 0xffff * gemtek_getsigstr(); + v->signal = 0xffff * gemtek_getsigstr(gt); if (v->signal) { v->audmode = V4L2_TUNER_MODE_STEREO; v->rxsubchans = V4L2_TUNER_SUB_STEREO; @@ -442,65 +425,56 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) v->audmode = V4L2_TUNER_MODE_MONO; v->rxsubchans = V4L2_TUNER_SUB_MONO; } - return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return (v->index != 0) ? -EINVAL : 0; } -static int vidioc_s_frequency(struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_device *rt = video_drvdata(file); - - gemtek_setfreq(rt, f->frequency); + struct gemtek *gt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = gt->lastfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); - f->type = V4L2_TUNER_RADIO; - f->frequency = rt->lastfreq; + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + gemtek_setfreq(gt, f->frequency); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + default: + return -EINVAL; } - return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = rt->muted; - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (rt->muted) - ctrl->value = 0; - else - ctrl->value = 65535; + ctrl->value = gt->muted; return 0; } return -EINVAL; @@ -509,35 +483,19 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - gemtek_mute(rt); - else - gemtek_unmute(rt); - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value) - gemtek_unmute(rt); + gemtek_mute(gt); else - gemtek_mute(rt); + gemtek_unmute(gt); return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -546,16 +504,20 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return (i != 0) ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return (a->index != 0) ? -EINVAL : 0; } static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { @@ -573,62 +535,73 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl }; -static struct video_device gemtek_radio = { - .name = "GemTek Radio card", - .fops = &gemtek_fops, - .ioctl_ops = &gemtek_ioctl_ops, - .release = video_device_release_empty, -}; - /* * Initialization / cleanup related stuff. */ -/* - * Initilize card. - */ static int __init gemtek_init(void) { - printk(KERN_INFO RADIO_BANNER "\n"); + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + int res; - spin_lock_init(&lock); + strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); - gemtek_probe(); - if (io) { - if (!request_region(io, 1, "gemtek")) { - printk(KERN_ERR "I/O port 0x%x already in use.\n", io); + v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); + + mutex_init(>->lock); + + gt->verified = -1; + gt->io = io; + gemtek_probe(gt); + if (gt->io) { + if (!request_region(gt->io, 1, "gemtek")) { + v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); return -EBUSY; } - if (!gemtek_verify(io)) - printk(KERN_WARNING "Card at I/O port 0x%x does not " + if (!gemtek_verify(gt, gt->io)) + v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " "respond properly, check your " - "configuration.\n", io); + "configuration.\n", gt->io); else - printk(KERN_INFO "Using I/O port 0x%x.\n", io); + v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); } else if (probe) { - printk(KERN_ERR "Automatic probing failed and no " + v4l2_err(v4l2_dev, "Automatic probing failed and no " "fixed I/O port defined.\n"); return -ENODEV; } else { - printk(KERN_ERR "Automatic probing disabled but no fixed " + v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " "I/O port defined."); return -EINVAL; } - video_set_drvdata(&gemtek_radio, &gemtek_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + release_region(gt->io, 1); + return res; + } - if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 1); + strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); + gt->vdev.v4l2_dev = v4l2_dev; + gt->vdev.fops = &gemtek_fops; + gt->vdev.ioctl_ops = &gemtek_ioctl_ops; + gt->vdev.release = video_device_release_empty; + video_set_drvdata(>->vdev, gt); + + if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(gt->io, 1); return -EBUSY; } /* Set defaults */ - gemtek_unit.lastfreq = GEMTEK_LOWFREQ; - gemtek_unit.bu2614data = 0; + gt->lastfreq = GEMTEK_LOWFREQ; + gt->bu2614data = 0; if (initmute) - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); return 0; } @@ -638,15 +611,19 @@ static int __init gemtek_init(void) */ static void __exit gemtek_exit(void) { + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + if (shutdown) { hardmute = 1; /* Turn off PLL */ - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); } else { - printk(KERN_INFO "Module unloaded but card not muted!\n"); + v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); } - video_unregister_device(&gemtek_radio); - release_region(io, 1); + video_unregister_device(>->vdev); + v4l2_device_unregister(>->v4l2_dev); + release_region(gt->io, 1); } module_init(gemtek_init); -- cgit v1.2.3 From a6922f733d048625fdb478ea22a1964acad3ef58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:08 +0100 Subject: radio-maestro: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maestro.c | 338 +++++++++++++++--------------- 1 file changed, 164 insertions(+), 174 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index 7442be614..b35092f30 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -22,28 +22,24 @@ #include #include #include -#include -#include +#include /* for KERNEL_VERSION MACRO */ #include #include -#include +#include +#include +#include #include #include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,6) -#define DRIVER_VERSION "0.06" +MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); +MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); +MODULE_LICENSE("GPL"); -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 6) +#define DRIVER_VERSION "0.06" #define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ @@ -73,62 +69,27 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int radio_nr = -1; -module_param(radio_nr, int, 0); +struct maestro { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; + struct mutex lock; -static unsigned long in_use; - -static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + u16 io; /* base of Maestro card radio io (GPIO_DATA)*/ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ +}; -static int maestro_exclusive_open(struct file *file) +static inline struct maestro *to_maestro(struct v4l2_device *v4l2_dev) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return container_of(v4l2_dev, struct maestro, v4l2_dev); } -static int maestro_exclusive_release(struct file *file) +static u32 radio_bits_get(struct maestro *dev) { - clear_bit(0, &in_use); - return 0; -} - -static void maestro_remove(struct pci_dev *pdev); - -static struct pci_device_id maestro_r_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); - -static struct pci_driver maestro_r_driver = { - .name = "maestro_radio", - .id_table = maestro_r_pci_tbl, - .probe = maestro_probe, - .remove = __devexit_p(maestro_remove), -}; - -static const struct v4l2_file_operations maestro_fops = { - .owner = THIS_MODULE, - .open = maestro_exclusive_open, - .release = maestro_exclusive_release, - .ioctl = video_ioctl2, -}; - -struct radio_device { - u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ -}; - -static u32 radio_bits_get(struct radio_device *dev) -{ - register u16 io=dev->io, l, rdata; - register u32 data=0; + u16 io = dev->io, l, rdata; + u32 data = 0; u16 omask; omask = inw(io + IO_MASK); @@ -136,25 +97,23 @@ static u32 radio_bits_get(struct radio_device *dev) outw(0, io); udelay(16); - for (l=24;l--;) { + for (l = 24; l--;) { outw(STR_CLK, io); /* HI state */ udelay(2); - if(!l) + if (!l) dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff; outw(0, io); /* LO state */ udelay(2); data <<= 1; /* shift data */ rdata = inw(io); - if(!l) - dev->stereo = rdata & STR_MOST ? - 0 : 1; - else - if(rdata & STR_DATA) - data++; + if (!l) + dev->stereo = (rdata & STR_MOST) ? 0 : 1; + else if (rdata & STR_DATA) + data++; udelay(2); } - if(dev->muted) + if (dev->muted) outw(STR_WREN, io); udelay(4); @@ -163,18 +122,18 @@ static u32 radio_bits_get(struct radio_device *dev) return data & 0x3ffe; } -static void radio_bits_set(struct radio_device *dev, u32 data) +static void radio_bits_set(struct maestro *dev, u32 data) { - register u16 io=dev->io, l, bits; + u16 io = dev->io, l, bits; u16 omask, odir; omask = inw(io + IO_MASK); - odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); + odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); outw(odir | STR_DATA, io + IO_DIR); outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); udelay(16); - for (l=25;l;l--) { - bits = ((data >> 18) & STR_DATA) | STR_WREN ; + for (l = 25; l; l--) { + bits = ((data >> 18) & STR_DATA) | STR_WREN; data <<= 1; /* shift data */ outw(bits, io); /* start strobe */ udelay(2); @@ -184,7 +143,7 @@ static void radio_bits_set(struct radio_device *dev, u32 data) udelay(4); } - if(!dev->muted) + if (!dev->muted) outw(0, io); udelay(4); @@ -196,78 +155,79 @@ static void radio_bits_set(struct radio_device *dev, u32 data) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct maestro *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maestro", sizeof(v->driver)); strlcpy(v->card, "Maestro Radio", sizeof(v->card)); - sprintf(v->bus_info, "PCI"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - (void)radio_bits_get(card); + mutex_lock(&dev->lock); + radio_bits_get(dev); - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if(card->stereo) + if (dev->stereo) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = card->tuned; + v->signal = dev->tuned; + mutex_unlock(&dev->lock); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; - radio_bits_set(card, FREQ2BITS(f->frequency)); + mutex_lock(&dev->lock); + radio_bits_set(dev, FREQ2BITS(f->frequency)); + mutex_unlock(&dev->lock); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = BITS2FREQ(radio_bits_get(card)); + mutex_lock(&dev->lock); + f->frequency = BITS2FREQ(radio_bits_get(dev)); + mutex_unlock(&dev->lock); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } return -EINVAL; } @@ -275,11 +235,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = card->muted; + ctrl->value = dev->muted; return 0; } return -EINVAL; @@ -288,56 +248,85 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); - register u16 io = card->io; - register u16 omask = inw(io + IO_MASK); + struct maestro *dev = video_drvdata(file); + u16 io = dev->io; + u16 omask; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + omask = inw(io + IO_MASK); outw(~STR_WREN, io + IO_MASK); - outw((card->muted = ctrl->value ) ? - STR_WREN : 0, io); + dev->muted = ctrl->value; + outw(dev->muted ? STR_WREN : 0, io); udelay(4); outw(omask, io + IO_MASK); msleep(125); + mutex_unlock(&dev->lock); return 0; } return -EINVAL; } +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + return i ? -EINVAL : 0; +} + static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) { - *i = 0; - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +static int maestro_open(struct file *file) { - if (i != 0) - return -EINVAL; return 0; } -static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) +static int maestro_release(struct file *file) { - if (a->index != 0) - return -EINVAL; return 0; } -static u16 __devinit radio_power_on(struct radio_device *dev) +static const struct v4l2_file_operations maestro_fops = { + .owner = THIS_MODULE, + .open = maestro_open, + .release = maestro_release, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops maestro_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, +}; + +static u16 __devinit radio_power_on(struct maestro *dev) { register u16 io = dev->io; register u32 ofreq; @@ -361,33 +350,11 @@ static u16 __devinit radio_power_on(struct radio_device *dev) return (ofreq == radio_bits_get(dev)); } -static const struct v4l2_ioctl_ops maestro_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, -}; - -static struct video_device maestro_radio = { - .name = "Maestro radio", - .fops = &maestro_fops, - .ioctl_ops = &maestro_ioctl_ops, - .release = video_device_release, -}; - static int __devinit maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct radio_device *radio_unit; - struct video_device *maestro_radio_inst; + struct maestro *dev; + struct v4l2_device *v4l2_dev; int retval; retval = pci_enable_device(pdev); @@ -398,46 +365,53 @@ static int __devinit maestro_probe(struct pci_dev *pdev, retval = -ENOMEM; - radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL); - if (radio_unit == NULL) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { dev_err(&pdev->dev, "not enough memory\n"); goto err; } - radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; - maestro_radio_inst = video_device_alloc(); - if (maestro_radio_inst == NULL) { - dev_err(&pdev->dev, "not enough memory\n"); + strlcpy(v4l2_dev->name, "maestro", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); goto errfr; } - memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio)); - video_set_drvdata(maestro_radio_inst, radio_unit); - pci_set_drvdata(pdev, maestro_radio_inst); + dev->io = pci_resource_start(pdev, 0) + GPIO_DATA; - retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maestro_fops; + dev->vdev.ioctl_ops = &maestro_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr); if (retval) { - printk(KERN_ERR "can't register video device!\n"); + v4l2_err(v4l2_dev, "can't register video device!\n"); goto errfr1; } - if (!radio_power_on(radio_unit)) { + if (!radio_power_on(dev)) { retval = -EIO; goto errunr; } - dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " " - __DATE__ "\n"); - dev_info(&pdev->dev, "radio chip initialized\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); return 0; errunr: - video_unregister_device(maestro_radio_inst); + video_unregister_device(&dev->vdev); errfr1: - video_device_release(maestro_radio_inst); + v4l2_device_unregister(v4l2_dev); errfr: - kfree(radio_unit); + kfree(dev); err: return retval; @@ -445,11 +419,31 @@ err: static void __devexit maestro_remove(struct pci_dev *pdev) { - struct video_device *vdev = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maestro *dev = to_maestro(v4l2_dev); - video_unregister_device(vdev); + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); } +static struct pci_device_id maestro_r_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); + +static struct pci_driver maestro_r_driver = { + .name = "maestro_radio", + .id_table = maestro_r_pci_tbl, + .probe = maestro_probe, + .remove = __devexit_p(maestro_remove), +}; + static int __init maestro_radio_init(void) { int retval = pci_register_driver(&maestro_r_driver); @@ -467,7 +461,3 @@ static void __exit maestro_radio_exit(void) module_init(maestro_radio_init); module_exit(maestro_radio_exit); - -MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); -MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8dcdc9fab2af7f5123f3660b04f2ca497d6ec098 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:33 +0100 Subject: radio-maxiradio: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maxiradio.c | 375 ++++++++++++++-------------- 1 file changed, 186 insertions(+), 189 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index cb9d07bc7..fa2c5f1ef 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -37,39 +37,34 @@ #include #include #include -#include -#include #include - #include #include -#include +#include /* for KERNEL_VERSION MACRO */ +#include +#include +#include #include #include "compat.h" +MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); +MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); +MODULE_LICENSE("GPL"); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + #define DRIVER_VERSION "0.77" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,7,7) - -static struct video_device maxiradio_radio; - -#define dprintk(num, fmt, arg...) \ - do { \ - if (maxiradio_radio.debug >= num) \ - printk(KERN_DEBUG "%s: " fmt, \ - maxiradio_radio.name, ## arg); } while (0) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +#define RADIO_VERSION KERNEL_VERSION(0, 7, 7) + +#define dprintk(dev, num, fmt, arg...) \ + v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) #ifndef PCI_VENDOR_ID_GUILLEMOT #define PCI_VENDOR_ID_GUILLEMOT 0x5046 @@ -81,90 +76,70 @@ static struct v4l2_queryctrl radio_qctrl[] = { /* TEA5757 pin mappings */ -static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ; - -static int radio_nr = -1; -module_param(radio_nr, int, 0); +static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; -static unsigned long in_use; - -#define FREQ_LO 50*16000 -#define FREQ_HI 150*16000 +#define FREQ_LO (50 * 16000) +#define FREQ_HI (150 * 16000) #define FREQ_IF 171200 /* 10.7*16000 */ #define FREQ_STEP 200 /* 12.5*16 */ /* (x==fmhz*16*1000) -> bits */ -#define FREQ2BITS(x) ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \ - /(FREQ_STEP<<2))<<2) +#define FREQ2BITS(x) \ + ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int maxiradio_exclusive_open(struct file *file) +struct maxiradio { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; -} - -static int maxiradio_exclusive_release(struct file *file) -{ - clear_bit(0, &in_use); - return 0; -} - -static const struct v4l2_file_operations maxiradio_fops = { - .owner = THIS_MODULE, - .open = maxiradio_exclusive_open, - .release = maxiradio_exclusive_release, - .ioctl = video_ioctl2, -}; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; -static struct radio_device -{ - __u16 io, /* base of radio io */ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ + u16 io; /* base of radio io */ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ unsigned long freq; struct mutex lock; -} radio_unit = { - .muted =1, - .freq = FREQ_LO, }; -static void outbit(unsigned long bit, __u16 io) +static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) { - if (bit != 0) - { - outb( power|wren|data ,io); udelay(4); - outb( power|wren|data|clk ,io); udelay(4); - outb( power|wren|data ,io); udelay(4); - } - else - { - outb( power|wren ,io); udelay(4); - outb( power|wren|clk ,io); udelay(4); - outb( power|wren ,io); udelay(4); - } + return container_of(v4l2_dev, struct maxiradio, v4l2_dev); } -static void turn_power(__u16 io, int p) +static void outbit(unsigned long bit, u16 io) +{ + int val = power | wren | (bit ? data : 0); + + outb(val, io); + udelay(4); + outb(val | clk, io); + udelay(4); + outb(val, io); + udelay(4); +} + +static void turn_power(struct maxiradio *dev, int p) { if (p != 0) { - dprintk(1, "Radio powered on\n"); - outb(power, io); + dprintk(dev, 1, "Radio powered on\n"); + outb(power, dev->io); } else { - dprintk(1, "Radio powered off\n"); - outb(0,io); + dprintk(dev, 1, "Radio powered off\n"); + outb(0, dev->io); } } -static void set_freq(__u16 io, __u32 freq) +static void set_freq(struct maxiradio *dev, u32 freq) { unsigned long int si; int bl; + int io = dev->io; int val = FREQ2BITS(freq); /* TEA5757 shift register bits (see pdf) */ @@ -189,14 +164,14 @@ static void set_freq(__u16 io, __u32 freq) si >>= 1; } - dprintk(1, "Radio freq set to %d.%02d MHz\n", + dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", freq / 16000, freq % 16000 * 100 / 16000); - turn_power(io, 1); + turn_power(dev, 1); } -static int get_stereo(__u16 io) +static int get_stereo(u16 io) { outb(power,io); udelay(4); @@ -204,7 +179,7 @@ static int get_stereo(__u16 io) return !(inb(io) & mo_st); } -static int get_tune(__u16 io) +static int get_tune(u16 io) { outb(power+clk,io); udelay(4); @@ -213,95 +188,84 @@ static int get_tune(__u16 io) } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); - strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + struct maxiradio *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); + strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "FM"); + mutex_lock(&dev->lock); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - - v->rangelow=FREQ_LO; - v->rangehigh=FREQ_HI; - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(get_stereo(card->io)) + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (get_stereo(dev->io)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xffff*get_tune(card->io); + v->signal = 0xffff * get_tune(dev->io); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; -} - -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "FM"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; - return 0; } static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { - dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", + dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", f->frequency / 16000, f->frequency % 16000 * 100 / 16000, FREQ_LO / 16000, FREQ_HI / 16000); @@ -309,75 +273,91 @@ static int vidioc_s_frequency (struct file *file, void *priv, return -EINVAL; } - card->freq = f->frequency; - set_freq(card->io, card->freq); + mutex_lock(&dev->lock); + dev->freq = f->frequency; + set_freq(dev, dev->freq); msleep(125); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = card->freq; + f->frequency = dev->freq; - dprintk(4, "radio freq is %d.%02d MHz", + dprintk(dev, 4, "radio freq is %d.%02d MHz", f->frequency / 16000, f->frequency % 16000 * 100 / 16000); return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return (0); - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } - return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value=card->muted; - return (0); + case V4L2_CID_AUDIO_MUTE: + ctrl->value = dev->muted; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - card->muted = ctrl->value; - if(card->muted) - turn_power(card->io, 0); - else - set_freq(card->io, card->freq); - return 0; + case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + dev->muted = ctrl->value; + if (dev->muted) + turn_power(dev, 0); + else + set_freq(dev, dev->freq); + mutex_unlock(&dev->lock); + return 0; } return -EINVAL; } +static int maxiradio_open(struct file *file) +{ + return 0; +} + +static int maxiradio_release(struct file *file) +{ + return 0; +} + +static const struct v4l2_file_operations maxiradio_fops = { + .owner = THIS_MODULE, + .open = maxiradio_open, + .release = maxiradio_release, + .ioctl = video_ioctl2, +}; + static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, @@ -393,60 +373,84 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device maxiradio_radio = { - .name = "Maxi Radio FM2000 radio", - .fops = &maxiradio_fops, - .ioctl_ops = &maxiradio_ioctl_ops, - .release = video_device_release_empty, -}; - static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - if(!request_region(pci_resource_start(pdev, 0), + struct maxiradio *dev; + struct v4l2_device *v4l2_dev; + int retval = -ENOMEM; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&pdev->dev, "not enough memory\n"); + return -ENOMEM; + } + + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; + dev->muted = 1; + dev->freq = FREQ_LO; + + strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + goto errfr; + } + + if (!request_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { - printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); + v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); goto err_out; } if (pci_enable_device(pdev)) goto err_out_free_region; - radio_unit.io = pci_resource_start(pdev, 0); - mutex_init(&radio_unit.lock); - video_set_drvdata(&maxiradio_radio, &radio_unit); + dev->io = pci_resource_start(pdev, 0); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maxiradio_fops; + dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); - if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - printk("radio-maxiradio: can't register device!"); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_err(v4l2_dev, "can't register device!"); goto err_out_free_region; } - printk(KERN_INFO "radio-maxiradio: version " - DRIVER_VERSION - " time " - __TIME__ " " - __DATE__ - "\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION + " time " __TIME__ " " __DATE__ "\n"); - printk(KERN_INFO "radio-maxiradio: found Guillemot MAXI Radio device (io = 0x%x)\n", - radio_unit.io); + v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", + dev->io); return 0; err_out_free_region: release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); err_out: + v4l2_device_unregister(v4l2_dev); +errfr: + kfree(dev); return -ENODEV; } static void __devexit maxiradio_remove_one(struct pci_dev *pdev) { - video_unregister_device(&maxiradio_radio); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maxiradio *dev = to_maxiradio(v4l2_dev); + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); } static struct pci_device_id maxiradio_pci_tbl[] = { { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, PCI_ANY_ID, PCI_ANY_ID, }, - { 0,} + { 0 } }; MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); @@ -470,10 +474,3 @@ static void __exit maxiradio_radio_exit(void) module_init(maxiradio_radio_init); module_exit(maxiradio_radio_exit); - -MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); -MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); -MODULE_LICENSE("GPL"); - -module_param_named(debug,maxiradio_radio.debug, int, 0644); -MODULE_PARM_DESC(debug,"activates debug info"); -- cgit v1.2.3 From 62c50db1615e612d466a6bfcd9badcd300b54609 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:06 +0100 Subject: radio-rtrack2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-rtrack2.c | 280 ++++++++++++++---------------- 1 file changed, 130 insertions(+), 150 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index fa9e243c8..93b3da04a 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -13,35 +13,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Ben Pfaff"); +MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK2_PORT #define CONFIG_RADIO_RTRACK2_PORT -1 @@ -49,79 +32,89 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_RTRACK2_PORT; static int radio_nr = -1; -static spinlock_t lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; unsigned long curfreq; int muted; + struct mutex lock; }; +static struct rtrack2 rtrack2_card; + /* local things */ -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack2 *dev) { - if(dev->muted) + if (dev->muted) return; - spin_lock(&lock); - outb(1, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(1, dev->io); + mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); dev->muted = 1; } -static void rt_unmute(struct rt_device *dev) +static void rt_unmute(struct rtrack2 *dev) { if(dev->muted == 0) return; - spin_lock(&lock); - outb(0, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(0, dev->io); + mutex_unlock(&dev->lock); dev->muted = 0; } -static void zero(void) +static void zero(struct rtrack2 *dev) { - outb_p(1, io); - outb_p(3, io); - outb_p(1, io); + outb_p(1, dev->io); + outb_p(3, dev->io); + outb_p(1, dev->io); } -static void one(void) +static void one(struct rtrack2 *dev) { - outb_p(5, io); - outb_p(7, io); - outb_p(5, io); + outb_p(5, dev->io); + outb_p(7, dev->io); + outb_p(5, dev->io); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) { int i; + mutex_lock(&dev->lock); + dev->curfreq = freq; freq = freq / 200 + 856; - spin_lock(&lock); - - outb_p(0xc8, io); - outb_p(0xc9, io); - outb_p(0xc9, io); + outb_p(0xc8, dev->io); + outb_p(0xc9, dev->io); + outb_p(0xc9, dev->io); for (i = 0; i < 10; i++) - zero (); + zero(dev); for (i = 14; i >= 0; i--) if (freq & (1 << i)) - one (); + one(dev); else - zero (); + zero(dev); - outb_p(0xc8, io); + outb_p(0xc8, dev->io); if (!dev->muted) - outb_p(0, io); + outb_p(0, dev->io); - spin_unlock(&lock); + mutex_unlock(&dev->lock); return 0; } @@ -130,61 +123,61 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); strlcpy(v->card, "RadioTrack II", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; + return v->index ? -EINVAL : 0; } -static int rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack2 *dev) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&dev->lock); + if (inb(dev->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&dev->lock); + return sig; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (88*16000); - v->rangehigh = (108*16000); + v->rangelow = 88 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*rt_getsigstr(rt); + v->signal = 0xFFFF * rt_getsigstr(rt); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -194,14 +187,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); } return -EINVAL; } @@ -209,7 +199,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -228,7 +218,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -247,17 +237,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +245,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack2_exclusive_open(struct file *file) +static int rtrack2_open(struct file *file) { - return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack2_exclusive_release(struct file *file) +static int rtrack2_release(struct file *file) { - clear_bit(0, &rtrack2_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack2_fops = { .owner = THIS_MODULE, - .open = rtrack2_exclusive_open, - .release = rtrack2_exclusive_release, + .open = rtrack2_open, + .release = rtrack2_release, .ioctl = video_ioctl2, }; @@ -314,62 +295,61 @@ static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device rtrack2_radio = { - .name = "RadioTrack II radio", - .fops = &rtrack2_fops, - .ioctl_ops = &rtrack2_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init rtrack2_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); + struct rtrack2 *dev = &rtrack2_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); + dev->io = io; + if (dev->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); return -EINVAL; } - if (!request_region(io, 4, "rtrack2")) - { - printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); + if (!request_region(dev->io, 4, "rtrack2")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); return -EBUSY; } - video_set_drvdata(&rtrack2_radio, &rtrack2_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 4); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - spin_lock_init(&lock); - if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 4); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &rtrack2_fops; + dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + mutex_init(&dev->lock); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 4); return -EINVAL; } - printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); /* mute card - prevents noisy bootups */ - outb(1, io); - rtrack2_unit.muted = 1; + outb(1, dev->io); + dev->muted = 1; return 0; } -MODULE_AUTHOR("Ben Pfaff"); -MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit rtrack2_cleanup_module(void) +static void __exit rtrack2_exit(void) { - video_unregister_device(&rtrack2_radio); - release_region(io,4); + struct rtrack2 *dev = &rtrack2_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 4); } module_init(rtrack2_init); -module_exit(rtrack2_cleanup_module); - -/* - Local variables: - compile-command: "mmake" - End: -*/ +module_exit(rtrack2_exit); -- cgit v1.2.3 From cf853d565db80b0025c0f9d25582b7825d258f21 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:34 +0100 Subject: radio-sf16fmi: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmi.c | 286 ++++++++++++++---------------- 1 file changed, 136 insertions(+), 150 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index 3cce0afb4..392aa27e0 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -22,114 +22,111 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include "compat.h" -#include /* kernel radio structs */ -#include -#include #include -#include /* outb, outb_p */ -#include /* copy to/from user */ #include +#include /* kernel radio structs */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); +MODULE_DESCRIPTION("A driver for the SF16MI radio."); +MODULE_LICENSE("GPL"); -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +static int io = -1; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); +module_param(radio_nr, int, 0); -struct fmi_device +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct fmi { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ __u32 flags; + struct mutex lock; }; -static int io = -1; -static int radio_nr = -1; -static struct pnp_dev *dev = NULL; -static struct mutex lock; +static struct fmi fmi_card; +static struct pnp_dev *dev; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ -#define RSF16_ENCODE(x) ((x)/800+214) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 800 + 214) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static void outbits(int bits, unsigned int data, int port) +static void outbits(int bits, unsigned int data, int io) { - while(bits--) { - if(data & 1) { - outb(5, port); + while (bits--) { + if (data & 1) { + outb(5, io); udelay(6); - outb(7, port); + outb(7, io); udelay(6); } else { - outb(1, port); + outb(1, io); udelay(6); - outb(3, port); + outb(3, io); udelay(6); } - data>>=1; + data >>= 1; } } -static inline void fmi_mute(int port) +static inline void fmi_mute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x00, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x00, fmi->io); + mutex_unlock(&fmi->lock); } -static inline void fmi_unmute(int port) +static inline void fmi_unmute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x08, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x08, fmi->io); + mutex_unlock(&fmi->lock); } -static inline int fmi_setfreq(struct fmi_device *dev) +static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq) { - int myport = dev->port; - unsigned long freq = dev->curfreq; - - mutex_lock(&lock); + mutex_lock(&fmi->lock); + fmi->curfreq = freq; - outbits(16, RSF16_ENCODE(freq), myport); - outbits(8, 0xC0, myport); + outbits(16, RSF16_ENCODE(freq), fmi->io); + outbits(8, 0xC0, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - mutex_unlock(&lock); - if (dev->curvol) fmi_unmute(myport); + mutex_unlock(&fmi->lock); + if (fmi->curvol) + fmi_unmute(fmi); return 0; } -static inline int fmi_getsigstr(struct fmi_device *dev) +static inline int fmi_getsigstr(struct fmi *fmi) { int val; int res; - int myport = dev->port; - - mutex_lock(&lock); - val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ - outb(val, myport); - outb(val | 0x10, myport); + mutex_lock(&fmi->lock); + val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */ + outb(val, fmi->io); + outb(val | 0x10, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - res = (int)inb(myport+1); - outb(val, myport); + res = (int)inb(fmi->io + 1); + outb(val, fmi->io); - mutex_unlock(&lock); + mutex_unlock(&fmi->lock); return (res & 2) ? 0 : 0xFFFF; } @@ -138,9 +135,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); strlcpy(v->card, "SF16-FMx radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -148,18 +145,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; - v->capability = fmi->flags&V4L2_TUNER_CAP_LOW; + v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; @@ -168,32 +165,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 800 to match th freq - that will be used */ - fmi->curfreq = (f->frequency/800)*800; - fmi_setfreq(fmi); + /* rounding in steps of 800 to match the freq + that will be used */ + fmi_setfreq(fmi, (f->frequency / 800) * 800); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; @@ -205,14 +199,9 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } return -EINVAL; } @@ -220,7 +209,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -233,31 +222,20 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - fmi_mute(fmi->port); + fmi_mute(fmi); else - fmi_unmute(fmi->port); + fmi_unmute(fmi); fmi->curvol = ctrl->value; return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +244,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmi_device fmi_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmi_exclusive_open(struct file *file) +static int fmi_open(struct file *file) { - return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmi_exclusive_release(struct file *file) +static int fmi_release(struct file *file) { - clear_bit(0, &fmi_unit.in_use); return 0; } static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, - .open = fmi_exclusive_open, - .release = fmi_exclusive_release, + .open = fmi_open, + .release = fmi_release, .ioctl = video_ioctl2, }; @@ -314,13 +294,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device fmi_radio = { - .name = "SF16FMx radio", - .fops = &fmi_fops, - .ioctl_ops = &fmi_ioctl_ops, - .release = video_device_release_empty, -}; - /* ladis: this is my card. does any other types exist? */ static struct isapnp_device_id id_table[] __devinitdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, @@ -345,7 +318,7 @@ static int __init isapnp_fmi_probe(void) if (pnp_device_attach(dev) < 0) return -EAGAIN; if (pnp_activate_dev(dev) < 0) { - printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n"); + printk(KERN_ERR "radio-sf16fmi: PnP configure failed (out of resources?)\n"); pnp_device_detach(dev); return -ENOMEM; } @@ -355,59 +328,72 @@ static int __init isapnp_fmi_probe(void) } i = pnp_port_start(dev, 0); - printk ("radio-sf16fmi: PnP reports card at %#x\n", i); + printk(KERN_INFO "radio-sf16fmi: PnP reports card at %#x\n", i); return i; } static int __init fmi_init(void) { + struct fmi *fmi = &fmi_card; + struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; + int res; + if (io < 0) io = isapnp_fmi_probe(); - if (io < 0) { - printk(KERN_ERR "radio-sf16fmi: No PnP card found.\n"); - return io; + strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); + fmi->io = io; + if (fmi->io < 0) { + v4l2_err(v4l2_dev, "No PnP card found.\n"); + return fmi->io; } if (!request_region(io, 2, "radio-sf16fmi")) { - printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io); + v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io); pnp_device_detach(dev); return -EBUSY; } - fmi_unit.port = io; - fmi_unit.curvol = 0; - fmi_unit.curfreq = 0; - fmi_unit.flags = V4L2_TUNER_CAP_LOW; - video_set_drvdata(&fmi_radio, &fmi_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmi->io, 2); + pnp_device_detach(dev); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + fmi->flags = V4L2_TUNER_CAP_LOW; + strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); + fmi->vdev.v4l2_dev = v4l2_dev; + fmi->vdev.fops = &fmi_fops; + fmi->vdev.ioctl_ops = &fmi_ioctl_ops; + fmi->vdev.release = video_device_release_empty; + video_set_drvdata(&fmi->vdev, fmi); - mutex_init(&lock); + mutex_init(&fmi->lock); - if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmi->io, 2); + pnp_device_detach(dev); return -EINVAL; } - printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io); + v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io); /* mute card - prevents noisy bootups */ - fmi_mute(io); + fmi_mute(fmi); return 0; } -MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); -MODULE_DESCRIPTION("A driver for the SF16MI radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); -module_param(radio_nr, int, 0); - -static void __exit fmi_cleanup_module(void) +static void __exit fmi_exit(void) { - video_unregister_device(&fmi_radio); - release_region(io, 2); + struct fmi *fmi = &fmi_card; + + video_unregister_device(&fmi->vdev); + v4l2_device_unregister(&fmi->v4l2_dev); + release_region(fmi->io, 2); if (dev) pnp_device_detach(dev); } module_init(fmi_init); -module_exit(fmi_cleanup_module); +module_exit(fmi_exit); -- cgit v1.2.3 From b4fe8e07fa8e6266902aa003db9f8653a9190e2f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:26 +0100 Subject: radio-sf16fmr2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmr2.c | 374 ++++++++++++++--------------- 1 file changed, 176 insertions(+), 198 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 69a28d1ff..34de92f82 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -18,41 +18,30 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include -#include #include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -static struct mutex lock; +MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); +MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); +MODULE_LICENSE("GPL"); + +static int io = 0x384; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); +module_param(radio_nr, int, 0); -#include /* for KERNEL_VERSION MACRO */ #define RADIO_VERSION KERNEL_VERSION(0,0,2) #define AUD_VOL_INDEX 1 -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - [AUD_VOL_INDEX] = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 15, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - #undef DEBUG //#define DEBUG 1 @@ -63,156 +52,160 @@ static struct v4l2_queryctrl radio_qctrl[] = { #endif /* this should be static vars for module size */ -struct fmr2_device +struct fmr2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + int io; int curvol; /* 0-15 */ int mute; int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ int card_type; - __u32 flags; + u32 flags; }; -static int io = 0x384; -static int radio_nr = -1; +static struct fmr2 fmr2_card; /* hw precision is 12.5 kHz * It is only useful to give freq in intervall of 200 (=0.0125Mhz), * other bits will be truncated */ -#define RSF16_ENCODE(x) ((x)/200+856) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 200 + 856) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static inline void wait(int n,int port) +static inline void wait(int n, int io) { - for (;n;--n) inb(port); + for (; n; --n) + inb(io); } -static void outbits(int bits, unsigned int data, int nWait, int port) +static void outbits(int bits, unsigned int data, int nWait, int io) { int bit; - for(;--bits>=0;) { - bit = (data>>bits) & 1; - outb(bit,port); - wait(nWait,port); - outb(bit|2,port); - wait(nWait,port); - outb(bit,port); - wait(nWait,port); + + for (; --bits >= 0;) { + bit = (data >> bits) & 1; + outb(bit, io); + wait(nWait, io); + outb(bit | 2, io); + wait(nWait, io); + outb(bit, io); + wait(nWait, io); } } -static inline void fmr2_mute(int port) +static inline void fmr2_mute(int io) { - outb(0x00, port); - wait(4,port); + outb(0x00, io); + wait(4, io); } -static inline void fmr2_unmute(int port) +static inline void fmr2_unmute(int io) { - outb(0x04, port); - wait(4,port); + outb(0x04, io); + wait(4, io); } -static inline int fmr2_stereo_mode(int port) +static inline int fmr2_stereo_mode(int io) { - int n = inb(port); - outb(6,port); - inb(port); - n = ((n>>3)&1)^1; + int n = inb(io); + + outb(6, io); + inb(io); + n = ((n >> 3) & 1) ^ 1; debug_print((KERN_DEBUG "stereo: %d\n", n)); return n; } -static int fmr2_product_info(struct fmr2_device *dev) +static int fmr2_product_info(struct fmr2 *dev) { - int n = inb(dev->port); + int n = inb(dev->io); + n &= 0xC1; - if (n == 0) - { + if (n == 0) { /* this should support volume set */ dev->card_type = 12; return 0; } /* not volume (mine is 11) */ - dev->card_type = (n==128)?11:0; + dev->card_type = (n == 128) ? 11 : 0; return n; } -static inline int fmr2_getsigstr(struct fmr2_device *dev) +static inline int fmr2_getsigstr(struct fmr2 *dev) { - /* !!! work only if scanning freq */ - int port = dev->port, res = 0xffff; - outb(5,port); - wait(4,port); - if (!(inb(port)&1)) res = 0; + /* !!! works only if scanning freq */ + int res = 0xffff; + + outb(5, dev->io); + wait(4, dev->io); + if (!(inb(dev->io) & 1)) + res = 0; debug_print((KERN_DEBUG "signal: %d\n", res)); return res; } /* set frequency and unmute card */ -static int fmr2_setfreq(struct fmr2_device *dev) +static int fmr2_setfreq(struct fmr2 *dev) { - int port = dev->port; unsigned long freq = dev->curfreq; - fmr2_mute(port); + fmr2_mute(dev->io); /* 0x42 for mono output * 0x102 forward scanning * 0x182 scansione avanti */ - outbits(9,0x2,3,port); - outbits(16,RSF16_ENCODE(freq),2,port); + outbits(9, 0x2, 3, dev->io); + outbits(16, RSF16_ENCODE(freq), 2, dev->io); - fmr2_unmute(port); + fmr2_unmute(dev->io); /* wait 0.11 sec */ msleep(110); /* NOTE if mute this stop radio you must set freq on unmute */ - dev->stereo = fmr2_stereo_mode(port); + dev->stereo = fmr2_stereo_mode(dev->io); return 0; } /* !!! not tested, in my card this does't work !!! */ -static int fmr2_setvolume(struct fmr2_device *dev) +static int fmr2_setvolume(struct fmr2 *dev) { int vol[16] = { 0x021, 0x084, 0x090, 0x104, 0x110, 0x204, 0x210, 0x402, 0x404, 0x408, 0x410, 0x801, 0x802, 0x804, 0x808, 0x810 }; - int i, a, port = dev->port; + int i, a; int n = vol[dev->curvol & 0x0f]; if (dev->card_type != 11) return 1; for (i = 12; --i >= 0; ) { - a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ - outb(a | 4, port); - wait(4, port); - outb(a | 0x24, port); - wait(4, port); - outb(a | 4, port); - wait(4, port); + a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */ + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } for (i = 6; --i >= 0; ) { a = ((0x18 >> i) & 1) << 6; - outb(a | 4, port); - wait(4,port); - outb(a | 0x24, port); - wait(4,port); - outb(a|4, port); - wait(4,port); + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } - wait(4, port); - outb(0x14, port); - + wait(4, dev->io); + outb(0x14, dev->io); return 0; } @@ -221,9 +214,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver)); strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -231,54 +224,52 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; - mutex_lock(&lock); + mutex_lock(&fmr2->lock); v->signal = fmr2_getsigstr(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 200 to match th freq - that will be used */ - fmr2->curfreq = (f->frequency/200)*200; + /* rounding in steps of 200 to match the freq + that will be used */ + fmr2->curfreq = (f->frequency / 200) * 200; /* set card freq (if not muted) */ if (fmr2->curvol && !fmr2->mute) { - mutex_lock(&lock); + mutex_lock(&fmr2->lock); fmr2_setfreq(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); } return 0; } @@ -286,7 +277,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; @@ -298,13 +289,16 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; + struct fmr2 *fmr2 = video_drvdata(file); - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &radio_qctrl[i], sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + /* Only card_type == 11 implements volume */ + if (fmr2->card_type == 11) + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0); + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); } return -EINVAL; } @@ -312,7 +306,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -328,18 +322,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: fmr2->mute = ctrl->value; break; case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) - fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum; - else - fmr2->curvol = ctrl->value; - + fmr2->curvol = ctrl->value; break; default: return -EINVAL; @@ -352,25 +342,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, printk(KERN_DEBUG "mute\n"); #endif - mutex_lock(&lock); + mutex_lock(&fmr2->lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); /* Set frequency and unmute card */ fmr2_setfreq(fmr2); } else - fmr2_mute(fmr2->port); - mutex_unlock(&lock); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; + fmr2_mute(fmr2->io); + mutex_unlock(&fmr2->lock); return 0; } @@ -382,36 +361,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmr2_device fmr2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmr2_exclusive_open(struct file *file) +static int fmr2_open(struct file *file) { - return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmr2_exclusive_release(struct file *file) +static int fmr2_release(struct file *file) { - clear_bit(0, &fmr2_unit.in_use); return 0; } static const struct v4l2_file_operations fmr2_fops = { .owner = THIS_MODULE, - .open = fmr2_exclusive_open, - .release = fmr2_exclusive_release, + .open = fmr2_open, + .release = fmr2_release, .ioctl = video_ioctl2, }; @@ -430,67 +411,64 @@ static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device fmr2_radio = { - .name = "SF16FMR2 radio", - .fops = &fmr2_fops, - .ioctl_ops = &fmr2_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init fmr2_init(void) { - fmr2_unit.port = io; - fmr2_unit.curvol = 0; - fmr2_unit.mute = 0; - fmr2_unit.curfreq = 0; - fmr2_unit.stereo = 1; - fmr2_unit.flags = V4L2_TUNER_CAP_LOW; - fmr2_unit.card_type = 0; - video_set_drvdata(&fmr2_radio, &fmr2_unit); - - mutex_init(&lock); - - if (!request_region(io, 2, "sf16fmr2")) { - printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n"); + struct fmr2 *fmr2 = &fmr2_card; + struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); + fmr2->io = io; + fmr2->stereo = 1; + fmr2->flags = V4L2_TUNER_CAP_LOW; + mutex_init(&fmr2->lock); + + if (!request_region(fmr2->io, 2, "sf16fmr2")) { + v4l2_err(v4l2_dev, "request_region failed!\n"); return -EBUSY; } - if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); - return -EINVAL; + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmr2->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; } - printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); - /* mute card - prevents noisy bootups */ - mutex_lock(&lock); - fmr2_mute(io); - fmr2_product_info(&fmr2_unit); - mutex_unlock(&lock); - debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); + strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name)); + fmr2->vdev.v4l2_dev = v4l2_dev; + fmr2->vdev.fops = &fmr2_fops; + fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops; + fmr2->vdev.release = video_device_release_empty; + video_set_drvdata(&fmr2->vdev, fmr2); - /* Only card_type == 11 implements volume */ - if (fmr2_unit.card_type != 11) - radio_qctrl[AUD_VOL_INDEX].maximum = 1; + if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmr2->io, 2); + return -EINVAL; + } + v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); + /* mute card - prevents noisy bootups */ + mutex_lock(&fmr2->lock); + fmr2_mute(fmr2->io); + fmr2_product_info(fmr2); + mutex_unlock(&fmr2->lock); + debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type)); return 0; } -MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); -MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); -module_param(radio_nr, int, 0); - -static void __exit fmr2_cleanup_module(void) +static void __exit fmr2_exit(void) { - video_unregister_device(&fmr2_radio); - release_region(io,2); + struct fmr2 *fmr2 = &fmr2_card; + + video_unregister_device(&fmr2->vdev); + v4l2_device_unregister(&fmr2->v4l2_dev); + release_region(fmr2->io, 2); } module_init(fmr2_init); -module_exit(fmr2_cleanup_module); +module_exit(fmr2_exit); #ifndef MODULE -- cgit v1.2.3 From 241f0d88b7d45102e0c58b0532cbc4b4b3090a87 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:58 +0100 Subject: radio-terratec: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-terratec.c | 312 ++++++++++++++--------------- 1 file changed, 148 insertions(+), 164 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 1c2b4db2d..b63443076 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -28,16 +28,31 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("R.OFFERMANNS & others"); +MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); +MODULE_LICENSE("GPL"); + +#ifndef CONFIG_RADIO_TERRATEC_PORT +#define CONFIG_RADIO_TERRATEC_PORT 0x590 +#endif + +static int io = CONFIG_RADIO_TERRATEC_PORT; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) static struct v4l2_queryctrl radio_qctrl[] = { { @@ -58,13 +73,6 @@ static struct v4l2_queryctrl radio_qctrl[] = { } }; -#ifndef CONFIG_RADIO_TERRATEC_PORT -#define CONFIG_RADIO_TERRATEC_PORT 0x590 -#endif - -/**************** this ones are for the terratec *******************/ -#define BASEPORT 0x590 -#define VOLPORT 0x591 #define WRT_DIS 0x00 #define CLK_OFF 0x00 #define IIC_DATA 0x01 @@ -72,138 +80,124 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define DATA 0x04 #define CLK_ON 0x08 #define WRT_EN 0x10 -/*******************************************************************/ - -static int io = CONFIG_RADIO_TERRATEC_PORT; -static int radio_nr = -1; -static spinlock_t lock; -struct tt_device +struct terratec { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int muted; + struct mutex lock; }; +static struct terratec terratec_card; /* local things */ -static void cardWriteVol(int volume) +static void tt_write_vol(struct terratec *tt, int volume) { int i; - volume = volume+(volume * 32); // change both channels - spin_lock(&lock); - for (i=0;i<8;i++) - { - if (volume & (0x80>>i)) - outb(0x80, VOLPORT); - else outb(0x00, VOLPORT); + + volume = volume + (volume * 32); /* change both channels */ + mutex_lock(&tt->lock); + for (i = 0; i < 8; i++) { + if (volume & (0x80 >> i)) + outb(0x80, tt->io + 1); + else + outb(0x00, tt->io + 1); } - spin_unlock(&lock); + mutex_unlock(&tt->lock); } -static void tt_mute(struct tt_device *dev) +static void tt_mute(struct terratec *tt) { - dev->muted = 1; - cardWriteVol(0); + tt->muted = 1; + tt_write_vol(tt, 0); } -static int tt_setvol(struct tt_device *dev, int vol) +static int tt_setvol(struct terratec *tt, int vol) { - -// printk(KERN_ERR "setvol called, vol = %d\n", vol); - - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - cardWriteVol(vol); /* enable card */ + if (vol == tt->curvol) { /* requested volume = current */ + if (tt->muted) { /* user is unmuting the card */ + tt->muted = 0; + tt_write_vol(tt, vol); /* enable card */ } - return 0; } - if(vol == 0) { /* volume = 0 means mute the card */ - cardWriteVol(0); /* "turn off card" by setting vol to 0 */ - dev->curvol = vol; /* track the volume state! */ + if (vol == 0) { /* volume = 0 means mute the card */ + tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0 */ + tt->curvol = vol; /* track the volume state! */ return 0; } - dev->muted = 0; - - cardWriteVol(vol); - - dev->curvol = vol; - + tt->muted = 0; + tt_write_vol(tt, vol); + tt->curvol = vol; return 0; - } /* this is the worst part in this driver */ /* many more or less strange things are going on here, but hey, it works :) */ -static int tt_setfreq(struct tt_device *dev, unsigned long freq1) +static int tt_setfreq(struct terratec *tt, unsigned long freq1) { int freq; int i; int p; int temp; long rest; - unsigned char buffer[25]; /* we have to bit shift 25 registers */ - freq = freq1/160; /* convert the freq. to a nice to handle value */ - for(i=24;i>-1;i--) - buffer[i]=0; - rest = freq*10+10700; /* i once had understood what is going on here */ + mutex_lock(&tt->lock); + + tt->curfreq = freq1; + + freq = freq1 / 160; /* convert the freq. to a nice to handle value */ + memset(buffer, 0, sizeof(buffer)); + + rest = freq * 10 + 10700; /* I once had understood what is going on here */ /* maybe some wise guy (friedhelm?) can comment this stuff */ - i=13; - p=10; - temp=102400; - while (rest!=0) - { - if (rest%temp == rest) + i = 13; + p = 10; + temp = 102400; + while (rest != 0) { + if (rest % temp == rest) buffer[i] = 0; - else - { + else { buffer[i] = 1; - rest = rest-temp; + rest = rest - temp; } i--; p--; - temp = temp/2; + temp = temp / 2; } - spin_lock(&lock); - - for (i=24;i>-1;i--) /* bit shift the values to the radiocard */ - { - if (buffer[i]==1) - { - outb(WRT_EN|DATA, BASEPORT); - outb(WRT_EN|DATA|CLK_ON , BASEPORT); - outb(WRT_EN|DATA, BASEPORT); - } - else - { - outb(WRT_EN|0x00, BASEPORT); - outb(WRT_EN|0x00|CLK_ON , BASEPORT); + for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */ + if (buffer[i] == 1) { + outb(WRT_EN | DATA, tt->io); + outb(WRT_EN | DATA | CLK_ON, tt->io); + outb(WRT_EN | DATA, tt->io); + } else { + outb(WRT_EN | 0x00, tt->io); + outb(WRT_EN | 0x00 | CLK_ON, tt->io); } } - outb(0x00, BASEPORT); + outb(0x00, tt->io); - spin_unlock(&lock); + mutex_unlock(&tt->lock); return 0; } -static int tt_getsigstr(struct tt_device *dev) /* TODO */ +static int tt_getsigstr(struct terratec *tt) { - if (inb(io) & 2) /* bit set = no signal present */ + if (inb(tt->io) & 2) /* bit set = no signal present */ return 0; return 1; /* signal present */ } @@ -213,53 +207,50 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-terratec", sizeof(v->driver)); strlcpy(v->card, "ActiveRadio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87*16000); - v->rangehigh = (108*16000); + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*tt_getsigstr(tt); + v->signal = 0xFFFF * tt_getsigstr(tt); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); - tt->curfreq = f->frequency; - tt_setfreq(tt, tt->curfreq); + tt_setfreq(tt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = tt->curfreq; @@ -273,8 +264,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); + memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); return 0; } } @@ -284,7 +274,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -303,7 +293,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -319,17 +309,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -338,36 +317,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct tt_device terratec_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int terratec_exclusive_open(struct file *file) +static int terratec_open(struct file *file) { - return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; + return 0; } -static int terratec_exclusive_release(struct file *file) +static int terratec_release(struct file *file) { - clear_bit(0, &terratec_unit.in_use); return 0; } static const struct v4l2_file_operations terratec_fops = { .owner = THIS_MODULE, - .open = terratec_exclusive_open, - .release = terratec_exclusive_release, + .open = terratec_open, + .release = terratec_release, .ioctl = video_ioctl2, }; @@ -386,60 +367,63 @@ static const struct v4l2_ioctl_ops terratec_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device terratec_radio = { - .name = "TerraTec ActiveRadio", - .fops = &terratec_fops, - .ioctl_ops = &terratec_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init terratec_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct terratec *tt = &terratec_card; + struct v4l2_device *v4l2_dev = &tt->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); + tt->io = io; + if (tt->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "terratec")) - { - printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); + if (!request_region(tt->io, 2, "terratec")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", io); return -EBUSY; } - video_set_drvdata(&terratec_radio, &terratec_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(tt->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name)); + tt->vdev.v4l2_dev = v4l2_dev; + tt->vdev.fops = &terratec_fops; + tt->vdev.ioctl_ops = &terratec_ioctl_ops; + tt->vdev.release = video_device_release_empty; + video_set_drvdata(&tt->vdev, tt); - spin_lock_init(&lock); + mutex_init(&tt->lock); - if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&tt->v4l2_dev); + release_region(tt->io, 2); return -EINVAL; } - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n"); + v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - cardWriteVol(0); - terratec_unit.curvol = 0; - + tt_write_vol(tt, 0); return 0; } -MODULE_AUTHOR("R.OFFERMANNS & others"); -MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); -MODULE_LICENSE("GPL"); -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); -module_param(radio_nr, int, 0); - -static void __exit terratec_cleanup_module(void) +static void __exit terratec_exit(void) { - video_unregister_device(&terratec_radio); - release_region(io,2); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); + struct terratec *tt = &terratec_card; + struct v4l2_device *v4l2_dev = &tt->v4l2_dev; + + video_unregister_device(&tt->vdev); + v4l2_device_unregister(&tt->v4l2_dev); + release_region(tt->io, 2); + v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n"); } module_init(terratec_init); -module_exit(terratec_cleanup_module); +module_exit(terratec_exit); -- cgit v1.2.3 From ea7413e897555d76567d20e4124ba38502f71e52 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:23 +0100 Subject: radio-trust: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-trust.c | 349 ++++++++++++++++---------------- 1 file changed, 180 insertions(+), 169 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 5ce7a9d1d..196db11de 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -19,50 +19,17 @@ #include #include #include -#include -#include -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include -#include +#include +#include +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 2048, - .default_value = 65535, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - }, -}; +MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -72,26 +39,41 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_TRUST_PORT; static int radio_nr = -1; -static int ioval = 0xf; -static __u16 curvol; -static __u16 curbass; -static __u16 curtreble; -static unsigned long curfreq; -static int curstereo; -static int curmute; -static unsigned long in_use; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct trust { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int ioval; + __u16 curvol; + __u16 curbass; + __u16 curtreble; + int muted; + unsigned long curfreq; + int curstereo; + int curmute; + struct mutex lock; +}; + +static struct trust trust_card; /* i2c addresses */ #define TDA7318_ADDR 0x88 #define TSA6060T_ADDR 0xc4 -#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0) -#define TR_SET_SCL outb(ioval |= 2, io) -#define TR_CLR_SCL outb(ioval &= 0xfd, io) -#define TR_SET_SDA outb(ioval |= 1, io) -#define TR_CLR_SDA outb(ioval &= 0xfe, io) +#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) +#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) +#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) +#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) +#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) -static void write_i2c(int n, ...) +static void write_i2c(struct trust *tr, int n, ...) { unsigned char val, mask; va_list args; @@ -137,62 +119,77 @@ static void write_i2c(int n, ...) va_end(args); } -static void tr_setvol(__u16 vol) +static void tr_setvol(struct trust *tr, __u16 vol) { - curvol = vol / 2048; - write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f); + mutex_lock(&tr->lock); + tr->curvol = vol / 2048; + write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); + mutex_unlock(&tr->lock); } static int basstreble2chip[15] = { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 }; -static void tr_setbass(__u16 bass) +static void tr_setbass(struct trust *tr, __u16 bass) { - curbass = bass / 4370; - write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]); + mutex_lock(&tr->lock); + tr->curbass = bass / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); + mutex_unlock(&tr->lock); } -static void tr_settreble(__u16 treble) +static void tr_settreble(struct trust *tr, __u16 treble) { - curtreble = treble / 4370; - write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]); + mutex_lock(&tr->lock); + tr->curtreble = treble / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); + mutex_unlock(&tr->lock); } -static void tr_setstereo(int stereo) +static void tr_setstereo(struct trust *tr, int stereo) { - curstereo = !!stereo; - ioval = (ioval & 0xfb) | (!curstereo << 2); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curstereo = !!stereo; + tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static void tr_setmute(int mute) +static void tr_setmute(struct trust *tr, int mute) { - curmute = !!mute; - ioval = (ioval & 0xf7) | (curmute << 3); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curmute = !!mute; + tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static int tr_getsigstr(void) +static int tr_getsigstr(struct trust *tr) { int i, v; - for(i = 0, v = 0; i < 100; i++) v |= inb(io); - return (v & 1)? 0 : 0xffff; + mutex_lock(&tr->lock); + for (i = 0, v = 0; i < 100; i++) + v |= inb(tr->io); + mutex_unlock(&tr->lock); + return (v & 1) ? 0 : 0xffff; } -static int tr_getstereo(void) +static int tr_getstereo(struct trust *tr) { /* don't know how to determine it, just return the setting */ - return curstereo; + return tr->curstereo; } -static void tr_setfreq(unsigned long f) +static void tr_setfreq(struct trust *tr, unsigned long f) { + mutex_lock(&tr->lock); + tr->curfreq = f; f /= 160; /* Convert to 10 kHz units */ - f += 1070; /* Add 10.7 MHz IF */ - - write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + f += 1070; /* Add 10.7 MHz IF */ + write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + mutex_unlock(&tr->lock); } static int vidioc_querycap(struct file *file, void *priv, @@ -200,68 +197,75 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-trust", sizeof(v->driver)); strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct trust *tr = video_drvdata(file); + if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87.5*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 87.5 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if (tr_getstereo()) + if (tr_getstereo(tr)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = tr_getsigstr(); + v->signal = tr_getsigstr(tr); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; + struct trust *tr = video_drvdata(file); + if (v->index) + return -EINVAL; + tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - curfreq = f->frequency; - tr_setfreq(curfreq); + struct trust *tr = video_drvdata(file); + + tr_setfreq(tr, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct trust *tr = video_drvdata(file); + f->type = V4L2_TUNER_RADIO; - f->frequency = curfreq; + f->frequency = tr->curfreq; return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535); + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); } return -EINVAL; } @@ -269,18 +273,20 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = curmute; + ctrl->value = tr->curmute; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = curvol * 2048; + ctrl->value = tr->curvol * 2048; return 0; case V4L2_CID_AUDIO_BASS: - ctrl->value = curbass * 4370; + ctrl->value = tr->curbass * 4370; return 0; case V4L2_CID_AUDIO_TREBLE: - ctrl->value = curtreble * 4370; + ctrl->value = tr->curtreble * 4370; return 0; } return -EINVAL; @@ -289,37 +295,25 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - tr_setmute(ctrl->value); + tr_setmute(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_VOLUME: - tr_setvol(ctrl->value); + tr_setvol(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_BASS: - tr_setbass(ctrl->value); + tr_setbass(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_TREBLE: - tr_settreble(ctrl->value); + tr_settreble(tr, ctrl->value); return 0; } -#if 0 /* Should implement mono/stereo on V4L2 */ - tr_setstereo(v->mode & VIDEO_SOUND_STEREO); -#endif return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -328,34 +322,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int trust_exclusive_open(struct file *file) +static int trust_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int trust_exclusive_release(struct file *file) +static int trust_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations trust_fops = { .owner = THIS_MODULE, - .open = trust_exclusive_open, - .release = trust_exclusive_release, + .open = trust_open, + .release = trust_release, .ioctl = video_ioctl2, }; @@ -374,59 +372,72 @@ static const struct v4l2_ioctl_ops trust_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device trust_radio = { - .name = "Trust FM Radio", - .fops = &trust_fops, - .ioctl_ops = &trust_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init trust_init(void) { - if(io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct trust *tr = &trust_card; + struct v4l2_device *v4l2_dev = &tr->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); + tr->io = io; + tr->ioval = 0xf; + mutex_init(&tr->lock); + + if (tr->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if(!request_region(io, 2, "Trust FM Radio")) { - printk(KERN_ERR "trust: port 0x%x already in use\n", io); + if (!request_region(tr->io, 2, "Trust FM Radio")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); return -EBUSY; } - if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(tr->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); + tr->vdev.v4l2_dev = v4l2_dev; + tr->vdev.fops = &trust_fops; + tr->vdev.ioctl_ops = &trust_ioctl_ops; + tr->vdev.release = video_device_release_empty; + video_set_drvdata(&tr->vdev, tr); + + if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(tr->io, 2); return -EINVAL; } - printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); + v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); - write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - tr_setvol(0x8000); - tr_setbass(0x8000); - tr_settreble(0x8000); - tr_setstereo(1); + tr_setvol(tr, 0xffff); + tr_setbass(tr, 0x8000); + tr_settreble(tr, 0x8000); + tr_setstereo(tr, 1); /* mute card - prevents noisy bootups */ - tr_setmute(1); + tr_setmute(tr, 1); return 0; } -MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); -module_param(radio_nr, int, 0); - static void __exit cleanup_trust_module(void) { - video_unregister_device(&trust_radio); - release_region(io, 2); + struct trust *tr = &trust_card; + + video_unregister_device(&tr->vdev); + v4l2_device_unregister(&tr->v4l2_dev); + release_region(tr->io, 2); } module_init(trust_init); -- cgit v1.2.3 From 60f11d69155659eb8ed46eb60c0fa3fa2c48fb77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:52 +0100 Subject: radio-typhoon: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-typhoon.c | 352 ++++++++++++------------------ 1 file changed, 142 insertions(+), 210 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index bf812fbb5..11e3775ab 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -34,38 +34,17 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* radio card status report */ -#include -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include /* kernel radio structs */ -#include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,1,1) -#define BANNER "Typhoon Radio Card driver v0.1.1\n" - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 1<<14, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - +MODULE_AUTHOR("Dr. Henrik Seidel"); +MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_TYPHOON_PORT #define CONFIG_RADIO_TYPHOON_PORT -1 @@ -75,13 +54,26 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 #endif -#ifndef CONFIG_PROC_FS -#undef CONFIG_RADIO_TYPHOON_PROC_FS -#endif +static int io = CONFIG_RADIO_TYPHOON_PORT; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); + +module_param(radio_nr, int, 0); + +static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ; +module_param(mutefreq, ulong, 0); +MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); + +#define RADIO_VERSION KERNEL_VERSION(0, 1, 1) + +#define BANNER "Typhoon Radio Card driver v0.1.1\n" -struct typhoon_device { - unsigned long in_use; - int iobase; +struct typhoon { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; int muted; unsigned long curfreq; @@ -89,25 +81,19 @@ struct typhoon_device { struct mutex lock; }; -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol); -static int typhoon_setfreq_generic(struct typhoon_device *dev, - unsigned long frequency); -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency); -static void typhoon_mute(struct typhoon_device *dev); -static void typhoon_unmute(struct typhoon_device *dev); -static int typhoon_setvol(struct typhoon_device *dev, int vol); +static struct typhoon typhoon_card; -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) +static void typhoon_setvol_generic(struct typhoon *dev, int vol) { mutex_lock(&dev->lock); vol >>= 14; /* Map 16 bit to 2 bit */ vol &= 3; - outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */ - outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */ + outb_p(vol / 2, dev->io); /* Set the volume, high bit. */ + outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */ mutex_unlock(&dev->lock); } -static int typhoon_setfreq_generic(struct typhoon_device *dev, +static int typhoon_setfreq_generic(struct typhoon *dev, unsigned long frequency) { unsigned long outval; @@ -131,22 +117,22 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, outval -= (10 * x * x + 10433) / 20866; outval += 4 * x - 11505; - outb_p((outval >> 8) & 0x01, dev->iobase + 4); - outb_p(outval >> 9, dev->iobase + 6); - outb_p(outval & 0xff, dev->iobase + 8); + outb_p((outval >> 8) & 0x01, dev->io + 4); + outb_p(outval >> 9, dev->io + 6); + outb_p(outval & 0xff, dev->io + 8); mutex_unlock(&dev->lock); return 0; } -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency) +static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency) { typhoon_setfreq_generic(dev, frequency); dev->curfreq = frequency; return 0; } -static void typhoon_mute(struct typhoon_device *dev) +static void typhoon_mute(struct typhoon *dev) { if (dev->muted == 1) return; @@ -155,7 +141,7 @@ static void typhoon_mute(struct typhoon_device *dev) dev->muted = 1; } -static void typhoon_unmute(struct typhoon_device *dev) +static void typhoon_unmute(struct typhoon *dev) { if (dev->muted == 0) return; @@ -164,7 +150,7 @@ static void typhoon_unmute(struct typhoon_device *dev) dev->muted = 0; } -static int typhoon_setvol(struct typhoon_device *dev, int vol) +static int typhoon_setvol(struct typhoon *dev, int vol) { if (dev->muted && vol != 0) { /* user is unmuting the card */ dev->curvol = vol; @@ -189,9 +175,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-typhoon", sizeof(v->driver)); strlcpy(v->card, "Typhoon Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -201,10 +187,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87.5*16000); - v->rangehigh = (108*16000); + v->rangelow = 87.5 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; @@ -215,44 +201,37 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; + return v->index ? -EINVAL : 0; } -static int vidioc_s_frequency(struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); - typhoon->curfreq = f->frequency; - typhoon_setfreq(typhoon, typhoon->curfreq); + f->type = V4L2_TUNER_RADIO; + f->frequency = dev->curfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct typhoon_device *typhoon = video_drvdata(file); - - f->type = V4L2_TUNER_RADIO; - f->frequency = typhoon->curfreq; + struct typhoon *dev = video_drvdata(file); + dev->curfreq = f->frequency; + typhoon_setfreq(dev, dev->curfreq); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535); } return -EINVAL; } @@ -260,14 +239,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = typhoon->muted; + ctrl->value = dev->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = typhoon->curvol; + ctrl->value = dev->curvol; return 0; } return -EINVAL; @@ -276,33 +255,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - typhoon_mute(typhoon); + typhoon_mute(dev); else - typhoon_unmute(typhoon); + typhoon_unmute(dev); return 0; case V4L2_CID_AUDIO_VOLUME: - typhoon_setvol(typhoon, ctrl->value); + typhoon_setvol(dev, ctrl->value); return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -311,45 +279,62 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static struct typhoon_device typhoon_unit = +static int vidioc_log_status(struct file *file, void *priv) { - .iobase = CONFIG_RADIO_TYPHOON_PORT, - .curfreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, - .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, -}; + struct typhoon *dev = video_drvdata(file); + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + + v4l2_info(v4l2_dev, BANNER); +#ifdef MODULE + v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n"); +#else + v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n"); +#endif + v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4); + v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol); + v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off"); + v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io); + v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4); + return 0; +} -static int typhoon_exclusive_open(struct file *file) +static int typhoon_open(struct file *file) { - return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; + return 0; } -static int typhoon_exclusive_release(struct file *file) +static int typhoon_release(struct file *file) { - clear_bit(0, &typhoon_unit.in_use); return 0; } static const struct v4l2_file_operations typhoon_fops = { .owner = THIS_MODULE, - .open = typhoon_exclusive_open, - .release = typhoon_exclusive_release, + .open = typhoon_open, + .release = typhoon_release, .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { + .vidioc_log_status = vidioc_log_status, .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, @@ -364,125 +349,72 @@ static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device typhoon_radio = { - .name = "Typhoon Radio", - .fops = &typhoon_fops, - .ioctl_ops = &typhoon_ioctl_ops, - .release = video_device_release_empty, -}; - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - -static int typhoon_proc_show(struct seq_file *m, void *v) -{ - #ifdef MODULE - #define MODULEPROCSTRING "Driver loaded as a module" - #else - #define MODULEPROCSTRING "Driver compiled into kernel" - #endif - - seq_puts(m, BANNER); - seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n"); - seq_printf(m, "frequency = %lu kHz\n", - typhoon_unit.curfreq >> 4); - seq_printf(m, "volume = %d\n", typhoon_unit.curvol); - seq_printf(m, "mute = %s\n", typhoon_unit.muted ? - "on" : "off"); - seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase); - seq_printf(m, "mute frequency = %lu kHz\n", - typhoon_unit.mutefreq >> 4); - return 0; -} - -static int typhoon_proc_open(struct inode *inode, struct file *file) +static int __init typhoon_init(void) { - return single_open(file, typhoon_proc_show, NULL); -} + struct typhoon *dev = &typhoon_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; -static const struct file_operations typhoon_proc_fops = { - .owner = THIS_MODULE, - .open = typhoon_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ + strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); + dev->io = io; + dev->curfreq = dev->mutefreq = mutefreq; -MODULE_AUTHOR("Dr. Henrik Seidel"); -MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); -MODULE_LICENSE("GPL"); - -static int io = -1; -static int radio_nr = -1; - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); -module_param(radio_nr, int, 0); - -#ifdef MODULE -static unsigned long mutefreq; -module_param(mutefreq, ulong, 0); -MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); -#endif - -static int __init typhoon_init(void) -{ -#ifdef MODULE - if (io == -1) { - printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n"); + if (dev->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n"); return -EINVAL; } - typhoon_unit.iobase = io; - if (mutefreq < 87000 || mutefreq > 108500) { - printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n"); - printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); + if (dev->mutefreq < 87000 || dev->mutefreq > 108500) { + v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n"); + v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); return -EINVAL; } - typhoon_unit.mutefreq = mutefreq; -#endif /* MODULE */ - - printk(KERN_INFO BANNER); - mutex_init(&typhoon_unit.lock); - io = typhoon_unit.iobase; - if (!request_region(io, 8, "typhoon")) { - printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", - typhoon_unit.iobase); + + mutex_init(&dev->lock); + if (!request_region(dev->io, 8, "typhoon")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", + dev->io); return -EBUSY; } - video_set_drvdata(&typhoon_radio, &typhoon_unit); - if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 8); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 8); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + v4l2_info(v4l2_dev, BANNER); + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &typhoon_fops; + dev->vdev.ioctl_ops = &typhoon_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 8); return -EINVAL; } - printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); - printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", - typhoon_unit.mutefreq); - typhoon_unit.mutefreq <<= 4; + v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); + v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq); + dev->mutefreq <<= 4; /* mute card - prevents noisy bootups */ - typhoon_mute(&typhoon_unit); - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops)) - printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); -#endif + typhoon_mute(dev); return 0; } -static void __exit typhoon_cleanup_module(void) +static void __exit typhoon_exit(void) { + struct typhoon *dev = &typhoon_card; -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - remove_proc_entry("driver/radio-typhoon", NULL); -#endif - - video_unregister_device(&typhoon_radio); - release_region(io, 8); + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 8); } module_init(typhoon_init); -module_exit(typhoon_cleanup_module); +module_exit(typhoon_exit); -- cgit v1.2.3 From 8cf31fefb7f2a3a6c95c9f66fc63e00ec6b0bec0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:55:34 +0100 Subject: radio-zoltrix: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-zoltrix.c | 381 ++++++++++++++---------------- 1 file changed, 179 insertions(+), 202 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 4654ecd8b..93bc72adb 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -33,34 +33,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay, msleep */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 4096, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("C.van Schaik"); +MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_ZOLTRIX_PORT #define CONFIG_RADIO_ZOLTRIX_PORT -1 @@ -69,9 +53,16 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_ZOLTRIX_PORT; static int radio_nr = -1; -struct zol_device { - unsigned long in_use; - int port; +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct zoltrix { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int muted; @@ -79,161 +70,158 @@ struct zol_device { struct mutex lock; }; -static int zol_setvol(struct zol_device *dev, int vol) +static struct zoltrix zoltrix_card; + +static int zol_setvol(struct zoltrix *zol, int vol) { - dev->curvol = vol; - if (dev->muted) + zol->curvol = vol; + if (zol->muted) return 0; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); if (vol == 0) { - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); return 0; } - outb(dev->curvol-1, io); + outb(zol->curvol-1, zol->io); msleep(10); - inb(io + 2); - mutex_unlock(&dev->lock); + inb(zol->io + 2); + mutex_unlock(&zol->lock); return 0; } -static void zol_mute(struct zol_device *dev) +static void zol_mute(struct zoltrix *zol) { - dev->muted = 1; - mutex_lock(&dev->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + zol->muted = 1; + mutex_lock(&zol->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); } -static void zol_unmute(struct zol_device *dev) +static void zol_unmute(struct zoltrix *zol) { - dev->muted = 0; - zol_setvol(dev, dev->curvol); + zol->muted = 0; + zol_setvol(zol, zol->curvol); } -static int zol_setfreq(struct zol_device *dev, unsigned long freq) +static int zol_setfreq(struct zoltrix *zol, unsigned long freq) { /* tunes the radio to the desired frequency */ + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; unsigned long long bitmask, f, m; - unsigned int stereo = dev->stereo; + unsigned int stereo = zol->stereo; int i; if (freq == 0) { - printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n"); + v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); return -EINVAL; } m = (freq / 160 - 8800) * 2; - f = (unsigned long long) m + 0x4d1c; + f = (unsigned long long)m + 0x4d1c; bitmask = 0xc480402c10080000ull; i = 45; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ + zol->curfreq = freq; - outb(0x40, io); - outb(0xc0, io); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31)); + outb(0x40, zol->io); + outb(0xc0, zol->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); while (i--) { if ((bitmask & 0x8000000000000000ull) != 0) { - outb(0x80, io); + outb(0x80, zol->io); udelay(50); - outb(0x00, io); + outb(0x00, zol->io); udelay(50); - outb(0x80, io); + outb(0x80, zol->io); udelay(50); } else { - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); - outb(0x40, io); + outb(0x40, zol->io); udelay(50); - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); } bitmask *= 2; } /* termination sequence */ - outb(0x80, io); - outb(0xc0, io); - outb(0x40, io); + outb(0x80, zol->io); + outb(0xc0, zol->io); + outb(0x40, zol->io); udelay(1000); - inb(io+2); + inb(zol->io + 2); udelay(1000); - if (dev->muted) - { - outb(0, io); - outb(0, io); - inb(io + 3); + if (zol->muted) { + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); udelay(1000); } - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if(!dev->muted) - { - zol_setvol(dev, dev->curvol); - } + if (!zol->muted) + zol_setvol(zol, zol->curvol); return 0; } /* Get signal strength */ - -static int zol_getsigstr(struct zol_device *dev) +static int zol_getsigstr(struct zoltrix *zol) { int a, b; - mutex_lock(&dev->lock); - outb(0x00, io); /* This stuff I found to do nothing */ - outb(dev->curvol, io); + mutex_lock(&zol->lock); + outb(0x00, zol->io); /* This stuff I found to do nothing */ + outb(zol->curvol, zol->io); msleep(20); - a = inb(io); + a = inb(zol->io); msleep(10); - b = inb(io); + b = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); if (a != b) - return (0); + return 0; - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ - || (a == 0xef)) /* with a binary scanner on the card io */ - return (1); - return (0); + /* I found this out by playing with a binary scanner on the card io */ + return a == 0xcf || a == 0xdf || a == 0xef; } -static int zol_is_stereo (struct zol_device *dev) +static int zol_is_stereo(struct zoltrix *zol) { int x1, x2; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0x00, io); - outb(dev->curvol, io); + outb(0x00, zol->io); + outb(zol->curvol, zol->io); msleep(20); - x1 = inb(io); + x1 = inb(zol->io); msleep(10); - x2 = inb(io); + x2 = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if ((x1 == x2) && (x1 == 0xcf)) - return 1; - return 0; + return x1 == x2 && x1 == 0xcf; } static int vidioc_querycap(struct file *file, void *priv, @@ -241,59 +229,54 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); strlcpy(v->card, "Zoltrix Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (88*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 88 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; if (zol_is_stereo(zol)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*zol_getsigstr(zol); + v->signal = 0xFFFF * zol_getsigstr(zol); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); - zol->curfreq = f->frequency; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, f->frequency) != 0) return -EINVAL; - } return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; @@ -303,14 +286,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535); } return -EINVAL; } @@ -318,7 +298,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -334,7 +314,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -342,43 +322,30 @@ static int vidioc_s_ctrl(struct file *file, void *priv, zol_mute(zol); else { zol_unmute(zol); - zol_setvol(zol,zol->curvol); + zol_setvol(zol, zol->curvol); } return 0; case V4L2_CID_AUDIO_VOLUME: - zol_setvol(zol,ctrl->value/4096); + zol_setvol(zol, ctrl->value / 4096); return 0; } zol->stereo = 1; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, zol->curfreq) != 0) return -EINVAL; - } #if 0 /*keep*/ /* FIXME: Implement stereo/mono switch on V4L2 */ - if (v->mode & VIDEO_SOUND_STEREO) { - zol->stereo = 1; - zol_setfreq(zol, zol->curfreq); - } - if (v->mode & VIDEO_SOUND_MONO) { - zol->stereo = 0; - zol_setfreq(zol, zol->curfreq); - } + if (v->mode & VIDEO_SOUND_STEREO) { + zol->stereo = 1; + zol_setfreq(zol, zol->curfreq); + } + if (v->mode & VIDEO_SOUND_MONO) { + zol->stereo = 0; + zol_setfreq(zol, zol->curfreq); + } #endif return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -387,37 +354,39 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct zol_device zoltrix_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int zoltrix_exclusive_open(struct file *file) +static int zoltrix_open(struct file *file) { - return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; + return 0; } -static int zoltrix_exclusive_release(struct file *file) +static int zoltrix_release(struct file *file) { - clear_bit(0, &zoltrix_unit.in_use); return 0; } static const struct v4l2_file_operations zoltrix_fops = { .owner = THIS_MODULE, - .open = zoltrix_exclusive_open, - .release = zoltrix_exclusive_release, + .open = zoltrix_open, + .release = zoltrix_release, .ioctl = video_ioctl2, }; @@ -436,67 +405,75 @@ static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device zoltrix_radio = { - .name = "Zoltrix Radio Plus", - .fops = &zoltrix_fops, - .ioctl_ops = &zoltrix_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init zoltrix_init(void) { - if (io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct zoltrix *zol = &zoltrix_card; + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); + zol->io = io; + if (zol->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if ((io != 0x20c) && (io != 0x30c)) { - printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n"); + if (zol->io != 0x20c && zol->io != 0x30c) { + v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); return -ENXIO; } - video_set_drvdata(&zoltrix_radio, &zoltrix_unit); - if (!request_region(io, 2, "zoltrix")) { - printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); + if (!request_region(zol->io, 2, "zoltrix")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); return -EBUSY; } - if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(zol->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); + zol->vdev.v4l2_dev = v4l2_dev; + zol->vdev.fops = &zoltrix_fops; + zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; + zol->vdev.release = video_device_release_empty; + video_set_drvdata(&zol->vdev, zol); + + if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(zol->io, 2); return -EINVAL; } - printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); + v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); - mutex_init(&zoltrix_unit.lock); + mutex_init(&zol->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0, io); - outb(0, io); + outb(0, zol->io); + outb(0, zol->io); msleep(20); - inb(io + 3); + inb(zol->io + 3); - zoltrix_unit.curvol = 0; - zoltrix_unit.stereo = 1; + zol->curvol = 0; + zol->stereo = 1; return 0; } -MODULE_AUTHOR("C.van Schaik"); -MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit zoltrix_cleanup_module(void) +static void __exit zoltrix_exit(void) { - video_unregister_device(&zoltrix_radio); - release_region(io, 2); + struct zoltrix *zol = &zoltrix_card; + + video_unregister_device(&zol->vdev); + v4l2_device_unregister(&zol->v4l2_dev); + release_region(zol->io, 2); } module_init(zoltrix_init); -module_exit(zoltrix_cleanup_module); +module_exit(zoltrix_exit); -- cgit v1.2.3 From 53cbcc79992f562a58926c0aeef0f0f710a69d89 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 7 Mar 2009 01:32:54 +0300 Subject: stv0900: delete debug messages not related to stv0900 tuning algorythm From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900_core.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index c86c3017e..b5a564086 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -59,20 +59,10 @@ static struct stv0900_inode *find_inode(struct i2c_adapter *i2c_adap, find it by i2c adapter and i2c address */ while ((temp_chip != NULL) && ((temp_chip->internal->i2c_adap != i2c_adap) || - (temp_chip->internal->i2c_addr != i2c_addr))) { + (temp_chip->internal->i2c_addr != i2c_addr))) temp_chip = temp_chip->next_inode; - dprintk(KERN_INFO "%s: store.adap %x\n", __func__, - (int)&(*temp_chip->internal->i2c_adap)); - dprintk(KERN_INFO "%s: init.adap %x\n", __func__, - (int)&(*i2c_adap)); - } - if (temp_chip != NULL) {/* find by i2c adapter & address */ - dprintk(KERN_INFO "%s: store.adap %x\n", __func__, - (int)temp_chip->internal->i2c_adap); - dprintk(KERN_INFO "%s: init.adap %x\n", __func__, - (int)i2c_adap); - } + } return temp_chip; @@ -1496,7 +1486,7 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, enum fe_stv0900_error error = STV0900_NO_ERROR; - dprintk(KERN_INFO "%s: Internal = %x\n", __func__, (u32)i_params); + dprintk(KERN_INFO "%s: ", __func__); p_result.locked = FALSE; p_search.path = state->demod; @@ -1619,7 +1609,7 @@ static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct stv0900_state *state = fe->demodulator_priv; - dprintk("%s: Internal = %x\n", __func__, (unsigned int)state->internal); + dprintk("%s: ", __func__); if ((stv0900_status(state->internal, state->demod)) == TRUE) { dprintk("DEMOD LOCK OK\n"); @@ -1935,8 +1925,6 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, if (err_stv0900) goto error; - dprintk(KERN_INFO "%s: Init Result = %d, handle_stv0900 = %x\n", - __func__, err_stv0900, (unsigned int)state->internal); break; default: goto error; -- cgit v1.2.3 From ca54d2e82573c1440b4e32208496dd4f79b01059 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 10:56:19 +0100 Subject: w9968cf: add v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/w9968cf.c | 20 +++++++++++++------- linux/drivers/media/video/w9968cf.h | 16 ++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 0b5109ed9..6c7be3a36 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3506,12 +3506,14 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) if (!cam) return -ENOMEM; + err = v4l2_device_register(&udev->dev, &cam->v4l2_dev); + if (err) + goto fail0; + mutex_init(&cam->dev_mutex); mutex_lock(&cam->dev_mutex); cam->usbdev = udev; - /* NOTE: a local copy is used to avoid possible race conditions */ - memcpy(&cam->dev, &udev->dev, sizeof(struct device)); DBG(2, "%s detected", symbolic(camlist, mod_id)) @@ -3560,7 +3562,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - cam->v4ldev->parent = &cam->dev; + cam->v4ldev->v4l2_dev = &cam->v4l2_dev; err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -3590,6 +3592,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); + + if (ovmod_load) + request_module("ovcamchip"); return 0; fail: /* Free unused memory */ @@ -3598,6 +3603,8 @@ fail: /* Free unused memory */ if (cam->v4ldev) video_device_release(cam->v4ldev); mutex_unlock(&cam->dev_mutex); + v4l2_device_unregister(&cam->v4l2_dev); +fail0: kfree(cam); return err; } @@ -3633,8 +3640,10 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) mutex_unlock(&cam->dev_mutex); - if (!cam->users) + if (!cam->users) { + v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); + } } up_write(&w9968cf_disconnect); @@ -3661,9 +3670,6 @@ static int __init w9968cf_module_init(void) KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION) KDBG(3, W9968CF_MODULE_AUTHOR) - if (ovmod_load) - request_module("ovcamchip"); - if ((err = usb_register(&w9968cf_usb_driver))) return err; diff --git a/linux/drivers/media/video/w9968cf.h b/linux/drivers/media/video/w9968cf.h index 62c26b1ed..184f96311 100644 --- a/linux/drivers/media/video/w9968cf.h +++ b/linux/drivers/media/video/w9968cf.h @@ -33,6 +33,7 @@ #include #include +#include #include #include "compat.h" @@ -196,10 +197,9 @@ enum w9968cf_vpp_flag { /* Main device driver structure */ struct w9968cf_device { - struct device dev; /* device structure */ - enum w9968cf_model_id id; /* private device identifier */ + struct v4l2_device v4l2_dev; struct video_device* v4ldev; /* -> V4L structure */ struct list_head v4llist; /* entry of the list of V4L cameras */ @@ -292,14 +292,14 @@ struct w9968cf_device { if ( ((specific_debug) && (debug == (level))) || \ ((!specific_debug) && (debug >= (level))) ) { \ if ((level) == 1) \ - dev_err(&cam->dev, fmt "\n", ## args); \ + v4l2_err(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) == 2 || (level) == 3) \ - dev_info(&cam->dev, fmt "\n", ## args); \ + v4l2_info(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) == 4) \ - dev_warn(&cam->dev, fmt "\n", ## args); \ + v4l2_warn(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) >= 5) \ - dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ + v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", \ + __func__, __LINE__ , ## args); \ } \ } /* For generic kernel (not device specific) messages */ @@ -322,7 +322,7 @@ struct w9968cf_device { #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); +v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ -- cgit v1.2.3 From 74a6094f9f289036473f782e306a3bdd2d41ce34 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 14:19:44 +0100 Subject: w9968cf/ovcamchip: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- .../drivers/media/video/ovcamchip/ovcamchip_core.c | 220 ++++++++++----------- .../drivers/media/video/ovcamchip/ovcamchip_priv.h | 7 + linux/drivers/media/video/w9968cf.c | 117 +++-------- linux/drivers/media/video/w9968cf.h | 8 +- 4 files changed, 146 insertions(+), 206 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c index c841f4e4f..63303b70f 100644 --- a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include "ovcamchip_priv.h" #define DRIVER_VERSION "v2.27 for Linux 2.6" @@ -44,6 +47,20 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { + /* ov7xxx */ + 0x42 >> 1, 0x46 >> 1, 0x4a >> 1, 0x4e >> 1, + 0x52 >> 1, 0x56 >> 1, 0x5a >> 1, 0x5e >> 1, + /* ov6xxx */ + 0xc0 >> 1, 0xc4 >> 1, 0xc8 >> 1, 0xcc >> 1, + 0xd0 >> 1, 0xd4 >> 1, 0xd8 >> 1, 0xdc >> 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; +#endif + /* Registers common to all chips, that are needed for detection */ #define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ @@ -61,10 +78,6 @@ static char *chip_names[NUM_CC_TYPES] = { [CC_OV6630AF] = "OV6630AF", }; -/* Forward declarations */ -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ----------------------------------------------------------------------- */ int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) @@ -253,112 +266,36 @@ static int ovcamchip_detect(struct i2c_client *c) /* Test for 7xx0 */ PDEBUG(3, "Testing for 0V7xx0"); - c->addr = OV7xx0_SID; - if (init_camchip(c) < 0) { - /* Test for 6xx0 */ - PDEBUG(3, "Testing for 0V6xx0"); - c->addr = OV6xx0_SID; - if (init_camchip(c) < 0) { - return -ENODEV; - } else { - if (ov6xx0_detect(c) < 0) { - PERROR("Failed to init OV6xx0"); - return -EIO; - } - } - } else { + if (init_camchip(c) < 0) + return -ENODEV; + /* 7-bit addresses with bit 0 set are for the OV7xx0 */ + if (c->addr & 1) { if (ov7xx0_detect(c) < 0) { PERROR("Failed to init OV7xx0"); return -EIO; } + return 0; + } + /* Test for 6xx0 */ + PDEBUG(3, "Testing for 0V6xx0"); + if (ov6xx0_detect(c) < 0) { + PERROR("Failed to init OV6xx0"); + return -EIO; } - return 0; } /* ----------------------------------------------------------------------- */ -static int ovcamchip_attach(struct i2c_adapter *adap) +static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { - int rc = 0; - struct ovcamchip *ov; - struct i2c_client *c; - - /* I2C is not a PnP bus, so we can never be certain that we're talking - * to the right chip. To prevent damage to EEPROMS and such, only - * attach to adapters that are known to contain OV camera chips. */ - - switch (adap->id) { - case I2C_HW_SMBUS_OV511: - case I2C_HW_SMBUS_OV518: - case I2C_HW_SMBUS_W9968CF: - PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id); - break; - default: - PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id); - return -ENODEV; - } - - c = kmalloc(sizeof *c, GFP_KERNEL); - if (!c) { - rc = -ENOMEM; - goto no_client; - } - memcpy(c, &client_template, sizeof *c); - c->adapter = adap; - strcpy(c->name, "OV????"); - - ov = kzalloc(sizeof *ov, GFP_KERNEL); - if (!ov) { - rc = -ENOMEM; - goto no_ov; - } - i2c_set_clientdata(c, ov); - - rc = ovcamchip_detect(c); - if (rc < 0) - goto error; - - strcpy(c->name, chip_names[ov->subtype]); - - PDEBUG(1, "Camera chip detection complete"); - - i2c_attach_client(c); - - return rc; -error: - kfree(ov); -no_ov: - kfree(c); -no_client: - PDEBUG(1, "returning %d", rc); - return rc; -} - -static int ovcamchip_detach(struct i2c_client *c) -{ - struct ovcamchip *ov = i2c_get_clientdata(c); - int rc; - - rc = ov->sops->free(c); - if (rc < 0) - return rc; - - i2c_detach_client(c); - - kfree(ov); - kfree(c); - return 0; -} - -static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) -{ - struct ovcamchip *ov = i2c_get_clientdata(c); + struct ovcamchip *ov = to_ovcamchip(sd); + struct i2c_client *c = v4l2_get_subdevdata(sd); if (!ov->initialized && cmd != OVCAMCHIP_CMD_Q_SUBTYPE && cmd != OVCAMCHIP_CMD_INITIALIZE) { - dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n"); + v4l2_err(sd, "Camera chip not initialized yet!\n"); return -EPERM; } @@ -379,10 +316,10 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) if (ov->mono) { if (ov->subtype != CC_OV7620) - dev_warn(&c->dev, "Warning: Monochrome not " + v4l2_warn(sd, "Monochrome not " "implemented for this chip\n"); else - dev_info(&c->dev, "Initializing chip as " + v4l2_info(sd, "Initializing chip as " "monochrome\n"); } @@ -398,37 +335,84 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) } } +static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "ovcamchip", - }, - .id = I2C_DRIVERID_OVCAMCHIP, - .attach_adapter = ovcamchip_attach, - .detach_client = ovcamchip_detach, - .command = ovcamchip_command, +static const struct v4l2_subdev_core_ops ovcamchip_core_ops = { + .ioctl = ovcamchip_ioctl, }; -static struct i2c_client client_template = { - .name = "(unset)", - .driver = &driver, +static const struct v4l2_subdev_ops ovcamchip_ops = { + .core = &ovcamchip_core_ops, }; -static int __init ovcamchip_init(void) +static int ovcamchip_probe(struct i2c_client *client, + const struct i2c_device_id *id) { -#ifdef DEBUG - ovcamchip_debug = debug; -#endif + struct ovcamchip *ov; + struct v4l2_subdev *sd; + int rc = 0; + + ov = kzalloc(sizeof *ov, GFP_KERNEL); + if (!ov) { + rc = -ENOMEM; + goto no_ov; + } + sd = &ov->sd; + v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops); + + rc = ovcamchip_detect(client); + if (rc < 0) + goto error; + + v4l_info(client, "%s found @ 0x%02x (%s)\n", + chip_names[ov->subtype], client->addr << 1, client->adapter->name); + + PDEBUG(1, "Camera chip detection complete"); - PINFO(DRIVER_VERSION " : " DRIVER_DESC); - return i2c_add_driver(&driver); + return rc; +error: + kfree(ov); +no_ov: + PDEBUG(1, "returning %d", rc); + return rc; } -static void __exit ovcamchip_exit(void) +static int ovcamchip_remove(struct i2c_client *client) { - i2c_del_driver(&driver); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ovcamchip *ov = to_ovcamchip(sd); + int rc; + + v4l2_device_unregister_subdev(sd); + rc = ov->sops->free(client); + if (rc < 0) + return rc; + + kfree(ov); + return 0; } -module_init(ovcamchip_init); -module_exit(ovcamchip_exit); +/* ----------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id ovcamchip_id[] = { + { "ovcamchip", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ovcamchip_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ovcamchip", + .command = ovcamchip_command, + .probe = ovcamchip_probe, + .remove = ovcamchip_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = ovcamchip_id, +#endif +}; diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h index a05650fae..4f07b78c8 100644 --- a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -16,6 +16,7 @@ #define __LINUX_OVCAMCHIP_PRIV_H #include +#include #include #ifdef DEBUG @@ -46,6 +47,7 @@ struct ovcamchip_ops { }; struct ovcamchip { + struct v4l2_subdev sd; struct ovcamchip_ops *sops; void *spriv; /* Private data for OV7x10.c etc... */ int subtype; /* = SEN_OV7610 etc... */ @@ -53,6 +55,11 @@ struct ovcamchip { int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ }; +static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ovcamchip, sd); +} + extern struct ovcamchip_ops ov6x20_ops; extern struct ovcamchip_ops ov6x30_ops; extern struct ovcamchip_ops ov7x10_ops; diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 6c7be3a36..dd519e48c 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -68,7 +68,6 @@ MODULE_VERSION(W9968CF_MODULE_VERSION); MODULE_LICENSE(W9968CF_MODULE_LICENSE); MODULE_SUPPORTED_DEVICE("Video"); -static int ovmod_load = W9968CF_OVMOD_LOAD; static unsigned short simcams = W9968CF_SIMCAMS; static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = @@ -111,9 +110,6 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG; static unsigned int param_nv[24]; /* number of values per parameter */ -#ifdef CONFIG_MODULES -module_param(ovmod_load, bool, 0644); -#endif module_param(simcams, ushort, 0644); module_param_array(video_nr, short, ¶m_nv[0], 0444); module_param_array(packet_size, uint, ¶m_nv[1], 0444); @@ -144,18 +140,6 @@ module_param(debug, ushort, 0644); module_param(specific_debug, bool, 0644); #endif -#ifdef CONFIG_MODULES -MODULE_PARM_DESC(ovmod_load, - "\n<0|1> Automatic 'ovcamchip' module loading." - "\n0 disabled, 1 enabled." - "\nIf enabled,'insmod' searches for the required 'ovcamchip'" - "\nmodule in the system, according to its configuration, and" - "\nattempts to load that module automatically. This action is" - "\nperformed once as soon as the 'w9968cf' module is loaded" - "\ninto memory." - "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." - "\n"); -#endif MODULE_PARM_DESC(simcams, "\n Number of cameras allowed to stream simultaneously." "\nn may vary from 0 to " @@ -447,8 +431,6 @@ static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data*); static u32 w9968cf_i2c_func(struct i2c_adapter*); -static int w9968cf_i2c_attach_inform(struct i2c_client*); -static int w9968cf_i2c_detach_inform(struct i2c_client*); /* Memory management */ static void* rvmalloc(unsigned long size); @@ -1451,19 +1433,11 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { - struct w9968cf_device* cam = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); + struct w9968cf_device *cam = to_cam(v4l2_dev); u8 i; int err = 0; - switch (addr) { - case OV6xx0_SID: - case OV7xx0_SID: - break; - default: - DBG(4, "Rejected slave ID 0x%04X", addr) - return -EINVAL; - } - if (size == I2C_SMBUS_BYTE) { /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ addr <<= 1; @@ -1471,8 +1445,17 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, if (read_write == I2C_SMBUS_WRITE) err = w9968cf_i2c_adap_write_byte(cam, addr, command); else if (read_write == I2C_SMBUS_READ) - err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); - + for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { + err = w9968cf_i2c_adap_read_byte(cam, addr, + &data->byte); + if (err) { + if (w9968cf_smbus_refresh_bus(cam)) { + err = -EIO; + break; + } + } else + break; + } } else if (size == I2C_SMBUS_BYTE_DATA) { addr <<= 1; @@ -1499,7 +1482,6 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, DBG(4, "Unsupported I2C transfer mode (%d)", size) return -EINVAL; } - return err; } @@ -1512,44 +1494,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap) } -static int w9968cf_i2c_attach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - int id = client->driver->id, err = 0; - - if (id == I2C_DRIVERID_OVCAMCHIP) { - cam->sensor_client = client; - err = w9968cf_sensor_init(cam); - if (err) { - cam->sensor_client = NULL; - return err; - } - } else { - DBG(4, "Rejected client [%s] with driver [%s]", - client->name, client->driver->driver.name) - return -EINVAL; - } - - DBG(5, "I2C attach client [%s] with driver [%s]", - client->name, client->driver->driver.name) - - return 0; -} - - -static int w9968cf_i2c_detach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - - if (cam->sensor_client == client) - cam->sensor_client = NULL; - - DBG(5, "I2C detach client [%s]", client->name) - - return 0; -} - - static int w9968cf_i2c_init(struct w9968cf_device* cam) { int err = 0; @@ -1565,15 +1509,16 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) static struct i2c_adapter adap = { .id = I2C_HW_SMBUS_W9968CF, .owner = THIS_MODULE, - .client_register = w9968cf_i2c_attach_inform, - .client_unregister = w9968cf_i2c_detach_inform, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) + .class = I2C_CLASS_TV_ANALOG, +#endif .algo = &algo, }; memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); strcpy(cam->i2c_adapter.name, "w9968cf"); cam->i2c_adapter.dev.parent = &cam->usbdev->dev; - i2c_set_adapdata(&cam->i2c_adapter, cam); + i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev); DBG(6, "Registering I2C adapter with kernel...") @@ -2176,13 +2121,9 @@ w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) static int w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) { - struct i2c_client* c = cam->sensor_client; - int rc = 0; + int rc; - if (!c || !c->driver || !c->driver->command) - return -EINVAL; - - rc = c->driver->command(c, cmd, arg); + rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg); /* The I2C driver returns -EPERM on non-supported controls */ return (rc < 0 && rc != -EPERM) ? rc : 0; } @@ -2357,7 +2298,7 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam) goto error; /* NOTE: Make sure width and height are a multiple of 16 */ - switch (cam->sensor_client->addr) { + switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) { case OV6xx0_SID: cam->maxwidth = 352; cam->maxheight = 288; @@ -2662,6 +2603,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) w9968cf_deallocate_memory(cam); kfree(cam->control_buffer); kfree(cam->data_buffer); + v4l2_device_unregister(&cam->v4l2_dev); mutex_unlock(&w9968cf_devlist_mutex); } @@ -3491,6 +3433,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) struct list_head* ptr; u8 sc = 0; /* number of simultaneous cameras */ static unsigned short dev_nr; /* 0 - we are handling device number n */ + static unsigned short addrs[] = { + OV7xx0_SID, + OV6xx0_SID, + I2C_CLIENT_END + }; if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) @@ -3589,12 +3536,13 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_turn_on_led(cam); w9968cf_i2c_init(cam); + cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter, + "ovcamchip", "ovcamchip", addrs); usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); - if (ovmod_load) - request_module("ovcamchip"); + err = w9968cf_sensor_init(cam); return 0; fail: /* Free unused memory */ @@ -3615,9 +3563,8 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) struct w9968cf_device* cam = (struct w9968cf_device*)usb_get_intfdata(intf); - down_write(&w9968cf_disconnect); - if (cam) { + down_write(&w9968cf_disconnect); /* Prevent concurrent accesses to data */ mutex_lock(&cam->dev_mutex); @@ -3639,14 +3586,12 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) w9968cf_release_resources(cam); mutex_unlock(&cam->dev_mutex); + up_write(&w9968cf_disconnect); if (!cam->users) { - v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); } } - - up_write(&w9968cf_disconnect); } diff --git a/linux/drivers/media/video/w9968cf.h b/linux/drivers/media/video/w9968cf.h index 184f96311..989d414d6 100644 --- a/linux/drivers/media/video/w9968cf.h +++ b/linux/drivers/media/video/w9968cf.h @@ -44,7 +44,6 @@ * Default values * ****************************************************************************/ -#define W9968CF_OVMOD_LOAD 1 /* automatic 'ovcamchip' module loading */ #define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ /* Comment/uncomment the following line to enable/disable debugging messages */ @@ -266,7 +265,7 @@ struct w9968cf_device { /* I2C interface to kernel */ struct i2c_adapter i2c_adapter; - struct i2c_client* sensor_client; + struct v4l2_subdev *sensor_sd; /* Locks */ struct mutex dev_mutex, /* for probe, disconnect,open and close */ @@ -278,6 +277,11 @@ struct w9968cf_device { char command[16]; /* name of the program holding the device */ }; +static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev); +} + /**************************************************************************** * Macros for debugging * -- cgit v1.2.3 From 78a6eb45bbd3dfed11a9ac8287a6060464eba7ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 23:01:08 -0300 Subject: dvb/frontends: fix duplicate 'debug' symbol From: Randy Dunlap Fix dvb frontend debug variable to be static, to avoid linker errors: drivers/built-in.o:(.data+0xf4b0): multiple definition of `debug' arch/x86/kernel/built-in.o:(.kprobes.text+0x90): first defined here ld: Warning: size of symbol `debug' changed from 85 in arch/x86/kernel/built-in.o to 4 in drivers/built-in.o It would also be Good if arch/x86/kernel/entry_32.S didn't have a non-static 'debug' symbol. OTOH, it helps catch things like this one. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stv0900_core.c | 4 ++-- linux/drivers/media/dvb/frontends/stv0900_priv.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index c86c3017e..9ff9744a1 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -34,8 +34,8 @@ #include "stv0900_priv.h" #include "stv0900_init.h" -int debug = 1; -module_param(debug, int, 0644); +static int stvdebug = 1; +module_param_named(debug, stvdebug, int, 0644); /* internal params node */ struct stv0900_inode { diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h index 28350fbeb..762d5af62 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_priv.h +++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h @@ -62,11 +62,11 @@ #define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a)) -extern int debug; +static int stvdebug; #define dprintk(args...) \ do { \ - if (debug) \ + if (stvdebug) \ printk(KERN_DEBUG args); \ } while (0) -- cgit v1.2.3 From 74c1d5f410c25958fd587a05987e654bb9104d22 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Mar 2009 12:11:21 +0100 Subject: ISA radio drivers: improve kernel log message From: Hans Verkuil It's much nicer if the log message tells you which io ports are possible, rather than having to run modinfo or look it up in the source or manual. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 2 +- linux/drivers/media/radio/radio-aztech.c | 2 +- linux/drivers/media/radio/radio-cadet.c | 3 ++- linux/drivers/media/radio/radio-terratec.c | 2 +- linux/drivers/media/radio/radio-trust.c | 2 +- linux/drivers/media/radio/radio-zoltrix.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 57b896968..7c3a81ad9 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -399,7 +399,7 @@ static int __init rtrack_init(void) rt->io = io; if (rt->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index dcf53edc2..8826b90a3 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -362,7 +362,7 @@ static int __init aztech_init(void) az->io = io; if (az->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 03e76bc74..373a34fde 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -686,7 +686,8 @@ static int __init cadet_init(void) /* Else we bail out */ if (dev->io < 0) { #ifdef MODULE - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x330, 0x332, 0x334,\n"); + v4l2_err(v4l2_dev, "0x336, 0x338, 0x33a, 0x33c or 0x33e\n"); #endif goto fail; } diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index b63443076..9bb1773ca 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -376,7 +376,7 @@ static int __init terratec_init(void) strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); tt->io = io; if (tt->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); return -EINVAL; } if (!request_region(tt->io, 2, "terratec")) { diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 196db11de..9d2dcb0a7 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -384,7 +384,7 @@ static int __init trust_init(void) mutex_init(&tr->lock); if (tr->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); return -EINVAL; } if (!request_region(tr->io, 2, "Trust FM Radio")) { diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 93bc72adb..3662f68da 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -414,7 +414,7 @@ static int __init zoltrix_init(void) strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); zol->io = io; if (zol->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); return -EINVAL; } if (zol->io != 0x20c && zol->io != 0x30c) { -- cgit v1.2.3 From b3e737a176ce96bee38fb7d0ee5cf6def9da8ad1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Mar 2009 22:16:42 -0300 Subject: v4l2-ioctl: get rid of video_decoder.h From: Mauro Carvalho Chehab The V4L1 obsoleted header video_decoder.h is not used anymore by any driver. Only a name decoding function at v4l2-ioctl still implements it. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-ioctl.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index e079a343a..230299801 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "compat.h" #define dbgarg(cmd, fmt, arg...) \ @@ -277,19 +276,6 @@ static const char *v4l2_ioctls[] = { #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) static const char *v4l2_int_ioctls[] = { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", - [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", - [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", - [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT", - [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT", - [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT", - [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE", - [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO", - [_IOC_NR(DECODER_INIT)] = "DECODER_INIT", - [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS", - [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", -#endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", -- cgit v1.2.3 From cc7dac29c9d92dd6beeb364950c93682d25e997e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 00:49:58 -0300 Subject: /frontends/Kconfig: Move af9013 Kconfig option to its proper place From: Mauro Carvalho Chehab af9013 is not a development tool. It is, instead, a DVB-T module. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 3205e302d..2887d3398 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -3,7 +3,7 @@ config DVB_FE_CUSTOMISE depends on DVB_CORE default N help - This allows the user to select/deselect frontend drivers for their + This allows the user to select/deselect frontend drivers for their hardware from the build. Use this option with care as deselecting frontends which are in fact @@ -14,7 +14,7 @@ config DVB_FE_CUSTOMISE if DVB_FE_CUSTOMISE -menu "Customise DVB Frontends" +menu "Customise DVB Frontends" comment "Multistandard (satellite) frontends" depends on DVB_CORE @@ -313,6 +313,13 @@ config DVB_TDA10048 help A DVB-T tuner module. Say Y when you want to support this frontend. +config DVB_AF9013 + tristate "Afatech AF9013 demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -503,13 +510,6 @@ comment "Tools to develop new frontends" config DVB_DUMMY_FE tristate "Dummy frontend driver" default n - -config DVB_AF9013 - tristate "Afatech AF9013 demodulator" - depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE - help - Say Y when you want to support this frontend. endmenu endif -- cgit v1.2.3 From b08b8d66d6c66efb91344fad801cabb14ced6c33 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 02:30:23 -0300 Subject: Fix Kbuild MEDIA_TUNER_CUSTOMIZE dependencies From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/Kconfig | 20 ++++++++++---------- linux/drivers/media/video/au0828/Kconfig | 6 +++--- linux/drivers/media/video/cx23885/Kconfig | 8 ++++---- linux/drivers/media/video/pvrusb2/Kconfig | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig index 7969b695c..724e6870c 100644 --- a/linux/drivers/media/common/tuners/Kconfig +++ b/linux/drivers/media/common/tuners/Kconfig @@ -66,14 +66,14 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A silicon tuner module. Say Y when you want to support this tuner. @@ -110,28 +110,28 @@ config MEDIA_TUNER_MT20XX config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner QT1010 from Quantek. @@ -145,7 +145,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called togther with a @@ -154,21 +154,21 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Freescale MC44S803 based tuners diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index deb00e4ac..20993ae17 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 28896aa31..e603ceb28 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index bb4271393..17cde1757 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE ---help--- This option enables a DVB interface for the pvrusb2 driver. -- cgit v1.2.3