From 2914e72681cdb3f310b0a0d570e9ac17b8c37d0c Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:24 -0300 Subject: [media] media: s3c-camif: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Sylwester Nawrocki Acked-by: Sylwester Nawrocki Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-capture.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index aa40c8269ab8..54479d60cc0d 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -536,24 +536,12 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&camif->slock, flags); } -static void camif_lock(struct vb2_queue *vq) -{ - struct camif_vp *vp = vb2_get_drv_priv(vq); - mutex_lock(&vp->camif->lock); -} - -static void camif_unlock(struct vb2_queue *vq) -{ - struct camif_vp *vp = vb2_get_drv_priv(vq); - mutex_unlock(&vp->camif->lock); -} - static const struct vb2_ops s3c_camif_qops = { .queue_setup = queue_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, - .wait_prepare = camif_unlock, - .wait_finish = camif_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .start_streaming = start_streaming, .stop_streaming = stop_streaming, }; @@ -1161,6 +1149,7 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx) q->buf_struct_size = sizeof(struct camif_buffer); q->drv_priv = vp; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &vp->camif->lock; ret = vb2_queue_init(q); if (ret) -- cgit v1.2.3 From 3d0aed38342b42bc532cc16cf4bf57a863f32df3 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:25 -0300 Subject: [media] media: ti-vpe: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Kukjin Kim Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpe.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index d628d1a7cf9e..968fb63caf94 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -1913,30 +1913,19 @@ static void vpe_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); } -static void vpe_wait_prepare(struct vb2_queue *q) -{ - struct vpe_ctx *ctx = vb2_get_drv_priv(q); - vpe_unlock(ctx); -} - -static void vpe_wait_finish(struct vb2_queue *q) -{ - struct vpe_ctx *ctx = vb2_get_drv_priv(q); - vpe_lock(ctx); -} - static struct vb2_ops vpe_qops = { .queue_setup = vpe_queue_setup, .buf_prepare = vpe_buf_prepare, .buf_queue = vpe_buf_queue, - .wait_prepare = vpe_wait_prepare, - .wait_finish = vpe_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) { struct vpe_ctx *ctx = priv; + struct vpe_dev *dev = ctx->dev; int ret; memset(src_vq, 0, sizeof(*src_vq)); @@ -1947,6 +1936,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->ops = &vpe_qops; src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &dev->dev_mutex; ret = vb2_queue_init(src_vq); if (ret) @@ -1960,6 +1950,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->ops = &vpe_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &dev->dev_mutex; return vb2_queue_init(dst_vq); } -- cgit v1.2.3 From 0637f054cef5b734b0b1dc5de7ee21aad6e0f441 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:26 -0300 Subject: [media] media: exynos-gsc: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Kukjin Kim Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-core.h | 12 ------------ drivers/media/platform/exynos-gsc/gsc-m2m.c | 6 ++++-- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index 0abdb17fb19c..fa572aacdb3f 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -466,18 +466,6 @@ static inline void gsc_hw_clear_irq(struct gsc_dev *dev, int irq) writel(cfg, dev->regs + GSC_IRQ); } -static inline void gsc_lock(struct vb2_queue *vq) -{ - struct gsc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_lock(&ctx->gsc_dev->lock); -} - -static inline void gsc_unlock(struct vb2_queue *vq) -{ - struct gsc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_unlock(&ctx->gsc_dev->lock); -} - static inline bool gsc_ctx_state_is_set(u32 mask, struct gsc_ctx *ctx) { unsigned long flags; diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 74e1de637e8f..d5cffef2e227 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -267,8 +267,8 @@ static struct vb2_ops gsc_m2m_qops = { .queue_setup = gsc_m2m_queue_setup, .buf_prepare = gsc_m2m_buf_prepare, .buf_queue = gsc_m2m_buf_queue, - .wait_prepare = gsc_unlock, - .wait_finish = gsc_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .stop_streaming = gsc_m2m_stop_streaming, .start_streaming = gsc_m2m_start_streaming, }; @@ -590,6 +590,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->gsc_dev->lock; ret = vb2_queue_init(src_vq); if (ret) @@ -603,6 +604,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->gsc_dev->lock; return vb2_queue_init(dst_vq); } -- cgit v1.2.3 From 8776ff659d8f9e86850fbe432610461ab09a94a0 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:28 -0300 Subject: [media] media: sh_veu: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_veu.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index aaa1f6f25a29..a901b6248557 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -242,20 +242,6 @@ static void sh_veu_job_abort(void *priv) veu->aborting = true; } -static void sh_veu_lock(void *priv) -{ - struct sh_veu_dev *veu = priv; - - mutex_lock(&veu->fop_lock); -} - -static void sh_veu_unlock(void *priv) -{ - struct sh_veu_dev *veu = priv; - - mutex_unlock(&veu->fop_lock); -} - static void sh_veu_process(struct sh_veu_dev *veu, struct vb2_buffer *src_buf, struct vb2_buffer *dst_buf) @@ -950,36 +936,28 @@ static void sh_veu_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(veu->m2m_ctx, vb); } -static void sh_veu_wait_prepare(struct vb2_queue *q) -{ - sh_veu_unlock(vb2_get_drv_priv(q)); -} - -static void sh_veu_wait_finish(struct vb2_queue *q) -{ - sh_veu_lock(vb2_get_drv_priv(q)); -} - static const struct vb2_ops sh_veu_qops = { .queue_setup = sh_veu_queue_setup, .buf_prepare = sh_veu_buf_prepare, .buf_queue = sh_veu_buf_queue, - .wait_prepare = sh_veu_wait_prepare, - .wait_finish = sh_veu_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) { + struct sh_veu_dev *veu = priv; int ret; memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP | VB2_USERPTR; - src_vq->drv_priv = priv; + src_vq->drv_priv = veu; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &sh_veu_qops; src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->lock = &veu->fop_lock; ret = vb2_queue_init(src_vq); if (ret < 0) @@ -988,10 +966,11 @@ static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq, memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; - dst_vq->drv_priv = priv; + dst_vq->drv_priv = veu; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &sh_veu_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->lock = &veu->fop_lock; return vb2_queue_init(dst_vq); } -- cgit v1.2.3 From c747404dbf2dcc0d8cb5d2e8aee5810b6ebba496 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:30 -0300 Subject: [media] media: s5p-tv: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Kyungmin Park Cc: Tomasz Stanislawski Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_video.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index b4d2696501e4..72d4f2e1efc0 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -926,22 +926,6 @@ static void buf_queue(struct vb2_buffer *vb) mxr_dbg(mdev, "queuing buffer\n"); } -static void wait_lock(struct vb2_queue *vq) -{ - struct mxr_layer *layer = vb2_get_drv_priv(vq); - - mxr_dbg(layer->mdev, "%s\n", __func__); - mutex_lock(&layer->mutex); -} - -static void wait_unlock(struct vb2_queue *vq) -{ - struct mxr_layer *layer = vb2_get_drv_priv(vq); - - mxr_dbg(layer->mdev, "%s\n", __func__); - mutex_unlock(&layer->mutex); -} - static int start_streaming(struct vb2_queue *vq, unsigned int count) { struct mxr_layer *layer = vb2_get_drv_priv(vq); @@ -1040,8 +1024,8 @@ static void stop_streaming(struct vb2_queue *vq) static struct vb2_ops mxr_video_qops = { .queue_setup = queue_setup, .buf_queue = buf_queue, - .wait_prepare = wait_unlock, - .wait_finish = wait_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .start_streaming = start_streaming, .stop_streaming = stop_streaming, }; @@ -1122,6 +1106,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, .ops = &mxr_video_qops, .min_buffers_needed = 1, .mem_ops = &vb2_dma_contig_memops, + .lock = &layer->mutex, }; return layer; -- cgit v1.2.3 From 654a731be1a0b6f606f3f3d12b50db08f2ae3c34 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Wed, 26 Nov 2014 19:42:32 -0300 Subject: [media] media: s5p-mfc: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Kyungmin Park Cc: Kamil Debski Cc: Jeongtae Park Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 + drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 20 ++------------------ drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 20 ++------------------ 3 files changed, 5 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index fbfdf03b9054..8e44a59d8ec2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -810,6 +810,7 @@ static int s5p_mfc_open(struct file *file) q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; q->drv_priv = &ctx->fh; + q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index c6c3452ccca1..9b14827ef4b9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -944,22 +944,6 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, return 0; } -static void s5p_mfc_unlock(struct vb2_queue *q) -{ - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); - struct s5p_mfc_dev *dev = ctx->dev; - - mutex_unlock(&dev->mfc_mutex); -} - -static void s5p_mfc_lock(struct vb2_queue *q) -{ - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); - struct s5p_mfc_dev *dev = ctx->dev; - - mutex_lock(&dev->mfc_mutex); -} - static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; @@ -1107,8 +1091,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) static struct vb2_ops s5p_mfc_dec_qops = { .queue_setup = s5p_mfc_queue_setup, - .wait_prepare = s5p_mfc_unlock, - .wait_finish = s5p_mfc_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .buf_init = s5p_mfc_buf_init, .start_streaming = s5p_mfc_start_streaming, .stop_streaming = s5p_mfc_stop_streaming, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index bd64f1dcbdb5..ac12f653ddce 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1867,22 +1867,6 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, return 0; } -static void s5p_mfc_unlock(struct vb2_queue *q) -{ - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); - struct s5p_mfc_dev *dev = ctx->dev; - - mutex_unlock(&dev->mfc_mutex); -} - -static void s5p_mfc_lock(struct vb2_queue *q) -{ - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); - struct s5p_mfc_dev *dev = ctx->dev; - - mutex_lock(&dev->mfc_mutex); -} - static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; @@ -2052,8 +2036,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) static struct vb2_ops s5p_mfc_enc_qops = { .queue_setup = s5p_mfc_queue_setup, - .wait_prepare = s5p_mfc_unlock, - .wait_finish = s5p_mfc_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .buf_init = s5p_mfc_buf_init, .buf_prepare = s5p_mfc_buf_prepare, .start_streaming = s5p_mfc_start_streaming, -- cgit v1.2.3 From 215cedec379b69427c457104f0c36b389edc471c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Dec 2014 10:10:42 -0300 Subject: [media] media: remove emacs editor variables 1) This is not allowed by the kernel coding style 2) Just configure your editor correctly 3) It's really ugly Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml | 8 -------- Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml | 8 -------- drivers/media/common/btcx-risc.c | 6 ------ drivers/media/common/btcx-risc.h | 6 ------ drivers/media/dvb-frontends/au8522.h | 5 ----- drivers/media/dvb-frontends/lg2160.c | 6 ------ drivers/media/dvb-frontends/lgdt3305.c | 6 ------ drivers/media/dvb-frontends/lgdt330x.c | 6 ------ drivers/media/dvb-frontends/lgdt330x.h | 6 ------ drivers/media/dvb-frontends/lgdt330x_priv.h | 6 ------ drivers/media/dvb-frontends/nxt200x.h | 6 ------ drivers/media/dvb-frontends/or51132.c | 6 ------ drivers/media/dvb-frontends/or51132.h | 6 ------ drivers/media/dvb-frontends/s5h1409.c | 6 ------ drivers/media/dvb-frontends/s5h1409.h | 5 ----- drivers/media/dvb-frontends/s5h1411.c | 5 ----- drivers/media/dvb-frontends/s5h1411.h | 5 ----- drivers/media/i2c/msp3400-driver.c | 8 -------- drivers/media/pci/bt8xx/bt878.c | 6 ------ drivers/media/pci/bt8xx/bttv-cards.c | 7 ------- drivers/media/pci/bt8xx/bttv-driver.c | 6 ------ drivers/media/pci/bt8xx/bttv-gpio.c | 6 ------ drivers/media/pci/bt8xx/bttv-if.c | 6 ------ drivers/media/pci/bt8xx/bttv-risc.c | 6 ------ drivers/media/pci/bt8xx/bttv-vbi.c | 7 ------- drivers/media/pci/bt8xx/bttv.h | 5 ----- drivers/media/pci/bt8xx/bttvp.h | 6 ------ drivers/media/pci/cx88/cx88-core.c | 7 ------- drivers/media/pci/cx88/cx88-mpeg.c | 7 ------- drivers/media/pci/cx88/cx88-tvaudio.c | 7 ------- drivers/media/tuners/mt20xx.c | 8 -------- drivers/media/tuners/mt2131.c | 5 ----- drivers/media/tuners/mt2131.h | 5 ----- drivers/media/tuners/mt2131_priv.h | 5 ----- drivers/media/tuners/mxl5007t.c | 8 -------- drivers/media/tuners/mxl5007t.h | 9 --------- drivers/media/tuners/tda18271-fe.c | 8 -------- drivers/media/tuners/tda18271-maps.c | 8 -------- drivers/media/tuners/tda18271-priv.h | 8 -------- drivers/media/tuners/tda827x.c | 8 -------- drivers/media/tuners/tda8290.c | 8 -------- drivers/media/tuners/tda9887.c | 8 -------- drivers/media/tuners/tuner-simple.c | 8 -------- drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | 8 -------- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h | 9 --------- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 6 ------ drivers/media/usb/dvb-usb-v2/mxl111sf.h | 6 ------ drivers/media/usb/dvb-usb/m920x.c | 5 ----- drivers/media/usb/pvrusb2/pvrusb2-audio.c | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-audio.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-context.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-context.h | 9 --------- drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-ctrl.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-ctrl.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c | 12 ------------ drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-debug.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-debugifc.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-debugifc.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-devattr.c | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-devattr.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-eeprom.c | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-eeprom.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-encoder.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-encoder.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-hdw.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-io.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-io.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-ioread.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-ioread.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-main.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-std.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-std.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-sysfs.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-sysfs.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-util.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-v4l2.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c | 11 ----------- drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2-wm8775.c | 12 ------------ drivers/media/usb/pvrusb2/pvrusb2-wm8775.h | 10 ---------- drivers/media/usb/pvrusb2/pvrusb2.h | 10 ---------- drivers/media/usb/usbvision/usbvision-core.c | 8 -------- drivers/media/usb/usbvision/usbvision-i2c.c | 8 -------- drivers/media/usb/usbvision/usbvision-video.c | 8 -------- drivers/media/usb/usbvision/usbvision.h | 8 -------- drivers/media/v4l2-core/v4l2-dev.c | 7 ------- include/media/videobuf-dvb.h | 6 ------ 104 files changed, 840 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index 28a8c1e1c705..a2017bfcaed2 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -212,11 +212,3 @@ standards set in the standards field. &return-value; - - diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index b9fdfeacdbcb..6e3cadd4e1f9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -131,11 +131,3 @@ is out of bounds or the pad number is invalid. - - diff --git a/drivers/media/common/btcx-risc.c b/drivers/media/common/btcx-risc.c index ac1b2687a20d..e67338aa8c89 100644 --- a/drivers/media/common/btcx-risc.c +++ b/drivers/media/common/btcx-risc.c @@ -252,9 +252,3 @@ EXPORT_SYMBOL(btcx_screen_clips); EXPORT_SYMBOL(btcx_align); EXPORT_SYMBOL(btcx_sort_clips); EXPORT_SYMBOL(btcx_calc_skips); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/common/btcx-risc.h b/drivers/media/common/btcx-risc.h index f8bc6e8e7b51..03583ef90506 100644 --- a/drivers/media/common/btcx-risc.h +++ b/drivers/media/common/btcx-risc.h @@ -26,9 +26,3 @@ void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); void btcx_calc_skips(int line, int width, int *maxy, struct btcx_skiplist *skips, unsigned int *nskips, const struct v4l2_clip *clips, unsigned int nclips); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h index 83fe9a615619..612251958855 100644 --- a/drivers/media/dvb-frontends/au8522.h +++ b/drivers/media/dvb-frontends/au8522.h @@ -91,8 +91,3 @@ enum au8522_audio_input { }; #endif /* __AU8522_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index 5fd14f840ab0..99efeba3c31a 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c @@ -1456,9 +1456,3 @@ MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.3"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 92c891a571ab..60df376e65c5 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -1215,9 +1215,3 @@ MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.2"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index e046622df0e4..2e1a61893fc1 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -823,9 +823,3 @@ MODULE_AUTHOR("Wilson Michaels"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(lgdt330x_attach); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/lgdt330x.h b/drivers/media/dvb-frontends/lgdt330x.h index ca0eab562e1e..8bb332219fc4 100644 --- a/drivers/media/dvb-frontends/lgdt330x.h +++ b/drivers/media/dvb-frontends/lgdt330x.h @@ -65,9 +65,3 @@ static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* #endif // CONFIG_DVB_LGDT330X #endif /* LGDT330X_H */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/lgdt330x_priv.h b/drivers/media/dvb-frontends/lgdt330x_priv.h index 38c76695abfe..1922f09a02d0 100644 --- a/drivers/media/dvb-frontends/lgdt330x_priv.h +++ b/drivers/media/dvb-frontends/lgdt330x_priv.h @@ -69,9 +69,3 @@ enum I2C_REG { }; #endif /* _LGDT330X_PRIV_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/nxt200x.h b/drivers/media/dvb-frontends/nxt200x.h index b518d545609e..e38d01fb6c2b 100644 --- a/drivers/media/dvb-frontends/nxt200x.h +++ b/drivers/media/dvb-frontends/nxt200x.h @@ -55,9 +55,3 @@ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* c #endif // CONFIG_DVB_NXT200X #endif /* NXT200X_H */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 5ef921823c15..cbbd259eacfe 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -623,9 +623,3 @@ MODULE_AUTHOR("Trent Piepho"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(or51132_attach); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/or51132.h b/drivers/media/dvb-frontends/or51132.h index 938958386cb1..cdb5be3c65d6 100644 --- a/drivers/media/dvb-frontends/or51132.h +++ b/drivers/media/dvb-frontends/or51132.h @@ -47,9 +47,3 @@ static inline struct dvb_frontend* or51132_attach(const struct or51132_config* c #endif // CONFIG_DVB_OR51132 #endif // OR51132_H - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c index f71b06221e14..5ff474a7ff29 100644 --- a/drivers/media/dvb-frontends/s5h1409.c +++ b/drivers/media/dvb-frontends/s5h1409.c @@ -1021,9 +1021,3 @@ static struct dvb_frontend_ops s5h1409_ops = { MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); - - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/dvb-frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h index 63b1e0a34e4e..9e143f5c8107 100644 --- a/drivers/media/dvb-frontends/s5h1409.h +++ b/drivers/media/dvb-frontends/s5h1409.h @@ -81,8 +81,3 @@ static inline struct dvb_frontend *s5h1409_attach( #endif /* CONFIG_DVB_S5H1409 */ #endif /* __S5H1409_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 6cc4b7a9dd60..64f35fed7ae1 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -944,8 +944,3 @@ MODULE_PARM_DESC(debug, "Enable verbose debug messages"); MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/dvb-frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h index e4f56871f982..1d7deb615674 100644 --- a/drivers/media/dvb-frontends/s5h1411.h +++ b/drivers/media/dvb-frontends/s5h1411.h @@ -83,8 +83,3 @@ static inline struct dvb_frontend *s5h1411_attach( #endif /* CONFIG_DVB_S5H1411 */ #endif /* __S5H1411_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 4d9c6bc34265..dcc68ec71732 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -904,11 +904,3 @@ static struct i2c_driver msp_driver = { }; module_i2c_driver(msp_driver); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 11765835d7b2..0939d399b774 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -590,9 +590,3 @@ module_init(bt878_init_module); module_exit(bt878_cleanup_module); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 41055606b969..c5186778fc8c 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -5048,10 +5048,3 @@ int bttv_handle_chipset(struct bttv *btv) pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); return 0; } - - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 4a8176c09fc9..665e46dafe68 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -4429,9 +4429,3 @@ static void __exit bttv_cleanup_module(void) module_init(bttv_init_module); module_exit(bttv_cleanup_module); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c index 3f364b7062b9..25b9916906d5 100644 --- a/drivers/media/pci/bt8xx/bttv-gpio.c +++ b/drivers/media/pci/bt8xx/bttv-gpio.c @@ -181,9 +181,3 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits) btwrite(data,BT848_GPIO_DATA); spin_unlock_irqrestore(&btv->gpio_lock,flags); } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-if.c b/drivers/media/pci/bt8xx/bttv-if.c index a6a540dc9e4b..538652e16a5c 100644 --- a/drivers/media/pci/bt8xx/bttv-if.c +++ b/drivers/media/pci/bt8xx/bttv-if.c @@ -113,9 +113,3 @@ int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) bttv_gpio_tracking(btv,"extern write"); return 0; } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 4d3f05a19af3..3859dde98be2 100644 --- a/drivers/media/pci/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c @@ -901,9 +901,3 @@ bttv_overlay_risc(struct bttv *btv, buf->vb.field = ov->field; return 0; } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c index b433267d9aa9..e77129c92fa0 100644 --- a/drivers/media/pci/bt8xx/bttv-vbi.c +++ b/drivers/media/pci/bt8xx/bttv-vbi.c @@ -450,10 +450,3 @@ void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm) /* See bttv_vbi_fmt_set(). */ f->end = tvnorm->vbistart[0] * 2 + 2; } - -/* ----------------------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index f08126244662..91301c3cad1e 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -378,8 +378,3 @@ extern void bttv_input_fini(struct bttv *dev); extern void bttv_input_irq(struct bttv *dev); #endif /* _BTTV_H_ */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 9fe19488b30b..e6e2c60f9e3e 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -531,9 +531,3 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv, #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) #endif /* _BTTVP_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index dee177ed5fe9..c38d5a12e277 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -1091,10 +1091,3 @@ EXPORT_SYMBOL(cx88_core_put); EXPORT_SYMBOL(cx88_ir_start); EXPORT_SYMBOL(cx88_ir_stop); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index 1c1f69e6b0b9..a369b0840acf 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c @@ -833,10 +833,3 @@ EXPORT_SYMBOL(cx8802_start_dma); EXPORT_SYMBOL(cx8802_register_driver); EXPORT_SYMBOL(cx8802_unregister_driver); EXPORT_SYMBOL(cx8802_get_driver); -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c index 424fd97495dc..6bbce6ad6295 100644 --- a/drivers/media/pci/cx88/cx88-tvaudio.c +++ b/drivers/media/pci/cx88/cx88-tvaudio.c @@ -1050,10 +1050,3 @@ EXPORT_SYMBOL(cx88_newstation); EXPORT_SYMBOL(cx88_set_stereo); EXPORT_SYMBOL(cx88_get_stereo); EXPORT_SYMBOL(cx88_audio_thread); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/tuners/mt20xx.c b/drivers/media/tuners/mt20xx.c index 0e74e97e0d1a..9e031040c13f 100644 --- a/drivers/media/tuners/mt20xx.c +++ b/drivers/media/tuners/mt20xx.c @@ -660,11 +660,3 @@ EXPORT_SYMBOL_GPL(microtune_attach); MODULE_DESCRIPTION("Microtune tuner driver"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/mt2131.c b/drivers/media/tuners/mt2131.c index f83b0c1ea6c8..6e2cdd2b6175 100644 --- a/drivers/media/tuners/mt2131.c +++ b/drivers/media/tuners/mt2131.c @@ -294,8 +294,3 @@ EXPORT_SYMBOL(mt2131_attach); MODULE_AUTHOR("Steven Toth"); MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver"); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/tuners/mt2131.h b/drivers/media/tuners/mt2131.h index 09ceaf68e47c..837c854b9c65 100644 --- a/drivers/media/tuners/mt2131.h +++ b/drivers/media/tuners/mt2131.h @@ -47,8 +47,3 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe, #endif /* CONFIG_MEDIA_TUNER_MT2131 */ #endif /* __MT2131_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/tuners/mt2131_priv.h b/drivers/media/tuners/mt2131_priv.h index 62aeedf5c550..91283b599cb3 100644 --- a/drivers/media/tuners/mt2131_priv.h +++ b/drivers/media/tuners/mt2131_priv.h @@ -41,8 +41,3 @@ struct mt2131_priv { }; #endif /* __MT2131_PRIV_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/tuners/mxl5007t.c b/drivers/media/tuners/mxl5007t.c index 1810ad66888e..f4ae04c3328a 100644 --- a/drivers/media/tuners/mxl5007t.c +++ b/drivers/media/tuners/mxl5007t.c @@ -938,11 +938,3 @@ MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.2"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/mxl5007t.h b/drivers/media/tuners/mxl5007t.h index 37b0942e2385..ae7037d681c5 100644 --- a/drivers/media/tuners/mxl5007t.h +++ b/drivers/media/tuners/mxl5007t.h @@ -93,12 +93,3 @@ static inline struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe, #endif #endif /* __MXL5007T_H__ */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/media/tuners/tda18271-fe.c b/drivers/media/tuners/tda18271-fe.c index 4995b890c164..f8620741bb5f 100644 --- a/drivers/media/tuners/tda18271-fe.c +++ b/drivers/media/tuners/tda18271-fe.c @@ -1355,11 +1355,3 @@ MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.4"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tda18271-maps.c b/drivers/media/tuners/tda18271-maps.c index b62e925f643f..1e89dd93c4bb 100644 --- a/drivers/media/tuners/tda18271-maps.c +++ b/drivers/media/tuners/tda18271-maps.c @@ -1305,11 +1305,3 @@ int tda18271_assign_map_layout(struct dvb_frontend *fe) return ret; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tda18271-priv.h b/drivers/media/tuners/tda18271-priv.h index b36a7b754772..cc80f544af34 100644 --- a/drivers/media/tuners/tda18271-priv.h +++ b/drivers/media/tuners/tda18271-priv.h @@ -226,11 +226,3 @@ extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq); extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq); #endif /* __TDA18271_PRIV_H__ */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tda827x.c b/drivers/media/tuners/tda827x.c index 73453a255cdc..edcb4a723aa1 100644 --- a/drivers/media/tuners/tda827x.c +++ b/drivers/media/tuners/tda827x.c @@ -907,11 +907,3 @@ MODULE_DESCRIPTION("DVB TDA827x driver"); MODULE_AUTHOR("Hartmut Hackmann "); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c index ab4106c17b4c..998e82bba9c0 100644 --- a/drivers/media/tuners/tda8290.c +++ b/drivers/media/tuners/tda8290.c @@ -881,11 +881,3 @@ EXPORT_SYMBOL_GPL(tda829x_probe); MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tda9887.c b/drivers/media/tuners/tda9887.c index 9823248d743f..56be6c29399b 100644 --- a/drivers/media/tuners/tda9887.c +++ b/drivers/media/tuners/tda9887.c @@ -707,11 +707,3 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, EXPORT_SYMBOL_GPL(tda9887_attach); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c index ca274c2d8c70..8e9ce144da9a 100644 --- a/drivers/media/tuners/tuner-simple.c +++ b/drivers/media/tuners/tuner-simple.c @@ -1148,11 +1148,3 @@ EXPORT_SYMBOL_GPL(simple_tuner_attach); MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index 0a98d04c53e4..ecefa5c477fa 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -604,9 +604,3 @@ MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h index 2d4530f5be54..0bd83e52669c 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h @@ -47,9 +47,3 @@ struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, #endif /* CONFIG_DVB_USB_MXL111SF */ #endif /* __MXL111SF_DEMOD_H__ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c index a619410adde4..2180c13a6dcc 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c @@ -755,9 +755,3 @@ int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode) } return 0; } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h index b85a5772d771..16fa4d4daf88 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h @@ -48,9 +48,3 @@ int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state, enum mxl111sf_mux_config pin_mux_config); #endif /* _DVB_USB_MXL111SF_GPIO_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index a101d06eb143..283495c84ba3 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c @@ -842,9 +842,3 @@ int mxl111sf_i2c_xfer(struct i2c_adapter *adap, return i == num ? num : -EREMOTEIO; } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h index 465762145ad2..c486fe02f018 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h @@ -27,9 +27,3 @@ int mxl111sf_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num); #endif /* _DVB_USB_MXL111SF_I2C_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c index f6b348024bec..5b0191178f9f 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c @@ -335,9 +335,3 @@ int mxl111sf_idac_config(struct mxl111sf_state *state, return ret; } - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h index 0643738de7de..25aa4a1ea755 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h @@ -45,9 +45,3 @@ int mxl111sf_idac_config(struct mxl111sf_state *state, u8 current_value, u8 hysteresis_value); #endif /* _DVB_USB_MXL111SF_PHY_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h index 89bf115e927e..1f4bfbcdbabb 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h @@ -171,9 +171,3 @@ #define V6_DIG_RF_PWR_MSB_REG 0x47 #endif /* _DVB_USB_MXL111SF_REG_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index a8d2c7053674..444579be0b77 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -515,11 +515,3 @@ MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index 2046db22519e..e6caab21a197 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -77,12 +77,3 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, #endif #endif /* __MXL111SF_TUNER_H__ */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index c3447eaf1104..bec12b0e076b 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -1425,9 +1425,3 @@ MODULE_AUTHOR("Michael Krufky "); MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 8516c011b7cc..ee70df1f1e94 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -152,9 +152,3 @@ extern int dvb_usb_mxl111sf_debug; }) #endif /* _DVB_USB_MXL111SF_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index abf8ab2e02e5..eafc5c82467f 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c @@ -1269,8 +1269,3 @@ MODULE_AUTHOR("Aapo Tahkola "); MODULE_DESCRIPTION("DVB Driver for ULI M920x"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.c b/drivers/media/usb/pvrusb2/pvrusb2-audio.c index cc06d5e4adcc..45276c628482 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.c @@ -84,13 +84,3 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); } } - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.h b/drivers/media/usb/pvrusb2/pvrusb2-audio.h index e3e63d750891..27cefb5cb170 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.h @@ -25,13 +25,3 @@ #include "pvrusb2-hdw-internal.h" void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c index c8761c71c9d2..924fc4c6019a 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-context.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c @@ -418,14 +418,3 @@ struct pvr2_ioread *pvr2_channel_create_mpeg_stream( pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key)); return cp; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.h b/drivers/media/usb/pvrusb2/pvrusb2-context.h index d657e53bbfa3..1c1d442d9ea3 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-context.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-context.h @@ -83,12 +83,3 @@ int pvr2_context_global_init(void); void pvr2_context_global_done(void); #endif /* __PVRUSB2_CONTEXT_H */ -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c index 88320900dbd4..f82f0f0f2c04 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c @@ -82,14 +82,3 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sd->ops->audio->s_routing(sd, input, 0, 0); } } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h index 53ba548b72a7..86c17bee56f9 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h @@ -36,13 +36,3 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_CS53L32A_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c index 7d5a7139a45a..958db170a048 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c @@ -596,14 +596,3 @@ int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr, } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h index 794ff90121c7..c175571868a3 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h @@ -110,13 +110,3 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *, unsigned int *len); #endif /* __PVRUSB2_CTRL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c index c514d0b9ffdc..1a81aa70509b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -152,15 +152,3 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0); } } - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h index e35c2322a08c..2eed7b7ee25e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -40,13 +40,3 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_CX2584X_V4L_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debug.h b/drivers/media/usb/pvrusb2/pvrusb2-debug.h index be79249f8628..4ef2ebcd97a5 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-debug.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-debug.h @@ -57,13 +57,3 @@ extern int pvrusb2_debug; #endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c index 4279ebb811a1..e4022bcb155b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c @@ -322,14 +322,3 @@ int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf, return 0; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h index 2f8d46761cd0..a8dfc55f136f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h @@ -40,13 +40,3 @@ int pvr2_debugifc_docmd(struct pvr2_hdw *, const char *buf_ptr,unsigned int buf_size); #endif /* __PVRUSB2_DEBUGIFC_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c index adc501d3c287..06c4c3dabcde 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c @@ -564,13 +564,3 @@ MODULE_FIRMWARE(PVR2_FIRMWARE_29xxx); MODULE_FIRMWARE(PVR2_FIRMWARE_24xxx); MODULE_FIRMWARE(PVR2_FIRMWARE_73xxx); MODULE_FIRMWARE(PVR2_FIRMWARE_75xxx); - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-devattr.h b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h index 273c8d4b3853..5aeefb6a991f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h @@ -187,13 +187,3 @@ struct pvr2_device_desc { extern struct usb_device_id pvr2_device_table[]; #endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c index 9515f3a68f8f..e1907cd0c3b7 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c @@ -152,13 +152,3 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) return 0; } - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h index cca3216f94cc..f1e33c807f46 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h @@ -27,13 +27,3 @@ struct pvr2_hdw; int pvr2_eeprom_analyze(struct pvr2_hdw *); #endif /* __PVRUSB2_EEPROM_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c index f7702aeeda3f..593b3e9b6bfd 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c @@ -538,14 +538,3 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) return status; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.h b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h index 232fefbcd1ac..a2bfb48f1ecd 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h @@ -30,13 +30,3 @@ int pvr2_encoder_start(struct pvr2_hdw *); int pvr2_encoder_stop(struct pvr2_hdw *); #endif /* __PVRUSB2_ENCODER_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h index 614755ea2ea3..06a15a68bcfd 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h @@ -60,13 +60,3 @@ #define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3u #endif /* _PVRUSB2_FX2_CMD_H_ */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h index 036952f2a3cb..1f9c02801cee 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h @@ -394,13 +394,3 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); void pvr2_hdw_status_poll(struct pvr2_hdw *); #endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 41847076f51a..fc5037957669 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -343,13 +343,3 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw); int pvr2_upload_firmware2(struct pvr2_hdw *hdw); #endif /* __PVRUSB2_HDW_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c index b5e929f1bf82..4baa9d632a4e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c @@ -686,13 +686,3 @@ void pvr2_i2c_core_done(struct pvr2_hdw *hdw) hdw->i2c_linked = 0; } } - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h index 6a75769200bd..a10a3e8e9345 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h @@ -27,14 +27,3 @@ void pvr2_i2c_core_done(struct pvr2_hdw *); #endif /* __PVRUSB2_I2C_ADAPTER_H */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c index 1e354747de3f..0c08f22bdfce 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-io.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c @@ -682,14 +682,3 @@ int pvr2_buffer_get_id(struct pvr2_buffer *bp) { return bp->id; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.h b/drivers/media/usb/pvrusb2/pvrusb2-io.h index afb7e87c0394..0c47c6a95ab2 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-io.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.h @@ -90,13 +90,3 @@ int pvr2_buffer_get_id(struct pvr2_buffer *); int pvr2_buffer_queue(struct pvr2_buffer *); #endif /* __PVRUSB2_IO_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ioread.c b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c index bba6115c9ae8..cd995b54732e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-ioread.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c @@ -499,14 +499,3 @@ int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt) cp,req_cnt,ret); return ret; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-ioread.h b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h index 100e0780e1aa..0b1f0fbc3438 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-ioread.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h @@ -36,13 +36,3 @@ int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt); int pvr2_ioread_avail(struct pvr2_ioread *); #endif /* __PVRUSB2_IOREAD_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-main.c b/drivers/media/usb/pvrusb2/pvrusb2-main.c index c1d9bb61cd77..86be902a0049 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-main.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-main.c @@ -169,14 +169,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_VERSION("0.9.1"); - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.c b/drivers/media/usb/pvrusb2/pvrusb2-std.c index 453627b07833..9a596a3a4c27 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-std.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-std.c @@ -398,14 +398,3 @@ v4l2_std_id pvr2_std_get_usable(void) { return CSTD_ALL; } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.h b/drivers/media/usb/pvrusb2/pvrusb2-std.h index a35c53d0b320..ed4ec0474429 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-std.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-std.h @@ -47,13 +47,3 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, v4l2_std_id pvr2_std_get_usable(void); #endif /* __PVRUSB2_STD_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c index 6ef1335b2858..06fe63ced58c 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c @@ -848,14 +848,3 @@ static ssize_t debugcmd_store(struct device *class_dev, return count; } #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h index 6d875bfe7991..6f0579e1e07b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h @@ -34,13 +34,3 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *, struct pvr2_sysfs_class *); #endif /* __PVRUSB2_SYSFS_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-util.h b/drivers/media/usb/pvrusb2/pvrusb2-util.h index 92b75544ee2e..5465bf9cd73e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-util.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-util.h @@ -50,13 +50,3 @@ #endif /* __PVRUSB2_UTIL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 1b158f1167ed..422d79e71e97 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -1360,13 +1360,3 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) pvr2_v4l2_destroy_no_lock(vp); return NULL; } - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h index 34c011a7b107..e455c9515841 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h @@ -27,13 +27,3 @@ struct pvr2_v4l2; struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *); #endif /* __PVRUSB2_V4L2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c index 2e205c99eb96..139b39740534 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c @@ -101,14 +101,3 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sd->ops->video->s_routing(sd, input, 0, 0); } } - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h index 3b0bd5db602b..dacf3ec7f9e1 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h @@ -36,13 +36,3 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_VIDEO_V4L_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c index 3ac8d751a5c0..f1df94a2436f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c @@ -56,15 +56,3 @@ void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sd->ops->audio->s_routing(sd, input, 0, 0); } } - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h index 0577bc7246fb..a4ee12e28d5c 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h @@ -40,13 +40,3 @@ void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_WM8775_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2.h b/drivers/media/usb/pvrusb2/pvrusb2.h index 240de9b35661..95f98a87abb3 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2.h +++ b/drivers/media/usb/pvrusb2/pvrusb2.h @@ -30,13 +30,3 @@ #define PVR_NUM 20 #endif /* __PVRUSB2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 302aa07c458f..2144b7b31be0 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -2502,11 +2502,3 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) usbvision_set_audio(usbvision, audio[channel]); return 0; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/usbvision/usbvision-i2c.c b/drivers/media/usb/usbvision/usbvision-i2c.c index ba262a32bd3a..26dbcb1146af 100644 --- a/drivers/media/usb/usbvision/usbvision-i2c.c +++ b/drivers/media/usb/usbvision/usbvision-i2c.c @@ -445,11 +445,3 @@ static struct i2c_adapter i2c_adap_template = { .owner = THIS_MODULE, .name = "usbvision", }; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 693d5f409138..cd2fbf11e3b4 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1716,11 +1716,3 @@ static void __exit usbvision_exit(void) module_init(usbvision_init); module_exit(usbvision_exit); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h index a0c73cf1517c..77aeb1ed9a81 100644 --- a/drivers/media/usb/usbvision/usbvision.h +++ b/drivers/media/usb/usbvision/usbvision.h @@ -517,11 +517,3 @@ int usbvision_power_off(struct usb_usbvision *usbvision); int usbvision_power_on(struct usb_usbvision *usbvision); #endif /* __LINUX_USBVISION_H */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 9aa530a8bea9..a13cc6123dd2 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -1033,10 +1033,3 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); - - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h index d63965a1faaf..c3bfa473c3aa 100644 --- a/include/media/videobuf-dvb.h +++ b/include/media/videobuf-dvb.h @@ -56,9 +56,3 @@ struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_fro int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p); #endif /* _VIDEOBUF_DVB_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3 From 1a023feb9c880bdf61502c5f8ef7b499133de8da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 4 Dec 2014 06:54:52 -0300 Subject: [media] v4l2 subdevs: replace get/set_crop by get/set_selection The crop and selection pad ops are duplicates. Replace all uses of get/set_crop by get/set_selection. This will make it possible to drop get/set_crop altogether. Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Acked-by: Laurent Pinchart Cc: Prabhakar Lad Cc: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9m032.c | 42 ++++++++------- drivers/media/i2c/mt9p031.c | 41 ++++++++------- drivers/media/i2c/mt9t001.c | 41 ++++++++------- drivers/media/i2c/mt9v032.c | 43 ++++++++------- drivers/media/i2c/s5k6aa.c | 44 +++++++++------- drivers/staging/media/davinci_vpfe/dm365_isif.c | 69 +++++++++++++------------ 6 files changed, 156 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index 45b3fca188ca..76431223f0ff 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -422,22 +422,25 @@ done: return ret; } -static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9m032 *sensor = to_mt9m032(subdev); + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + mutex_lock(&sensor->lock); - crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); + sel->r = *__mt9m032_get_pad_crop(sensor, fh, sel->which); mutex_unlock(&sensor->lock); return 0; } -static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9m032 *sensor = to_mt9m032(subdev); struct v4l2_mbus_framefmt *format; @@ -445,9 +448,12 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, struct v4l2_rect rect; int ret = 0; + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + mutex_lock(&sensor->lock); - if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ret = -EBUSY; goto done; } @@ -455,13 +461,13 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, /* Clamp the crop rectangle boundaries and align them to a multiple of 2 * pixels to ensure a GRBG Bayer pattern. */ - rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, + rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN, MT9M032_COLUMN_START_MAX); - rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, + rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN, MT9M032_ROW_START_MAX); - rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2), + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX); - rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2), + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX); rect.width = min_t(unsigned int, rect.width, @@ -469,21 +475,21 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, rect.height = min_t(unsigned int, rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); - __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); + __crop = __mt9m032_get_pad_crop(sensor, fh, sel->which); if (rect.width != __crop->width || rect.height != __crop->height) { /* Reset the output image size if the crop rectangle size has * been modified. */ - format = __mt9m032_get_pad_format(sensor, fh, crop->which); + format = __mt9m032_get_pad_format(sensor, fh, sel->which); format->width = rect.width; format->height = rect.height; } *__crop = rect; - crop->rect = rect; + sel->r = rect; - if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) ret = mt9m032_update_geom_timing(sensor); done: @@ -690,8 +696,8 @@ static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { .enum_frame_size = mt9m032_enum_frame_size, .get_fmt = mt9m032_get_pad_format, .set_fmt = mt9m032_set_pad_format, - .set_crop = mt9m032_set_pad_crop, - .get_crop = mt9m032_get_pad_crop, + .set_selection = mt9m032_set_pad_selection, + .get_selection = mt9m032_get_pad_selection, }; static const struct v4l2_subdev_ops mt9m032_ops = { diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index edb76bd33d16..e3acae9a2ec3 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -581,37 +581,42 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev, return 0; } -static int mt9p031_get_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9p031_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9p031 *mt9p031 = to_mt9p031(subdev); - crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad, - crop->which); + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + sel->r = *__mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which); return 0; } -static int mt9p031_set_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9p031_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9p031 *mt9p031 = to_mt9p031(subdev); struct v4l2_mbus_framefmt *__format; struct v4l2_rect *__crop; struct v4l2_rect rect; + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + /* Clamp the crop rectangle boundaries and align them to a multiple of 2 * pixels to ensure a GRBG Bayer pattern. */ - rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN, + rect.left = clamp(ALIGN(sel->r.left, 2), MT9P031_COLUMN_START_MIN, MT9P031_COLUMN_START_MAX); - rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN, + rect.top = clamp(ALIGN(sel->r.top, 2), MT9P031_ROW_START_MIN, MT9P031_ROW_START_MAX); - rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2), + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), MT9P031_WINDOW_WIDTH_MIN, MT9P031_WINDOW_WIDTH_MAX); - rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2), + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), MT9P031_WINDOW_HEIGHT_MIN, MT9P031_WINDOW_HEIGHT_MAX); @@ -620,20 +625,20 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev, rect.height = min_t(unsigned int, rect.height, MT9P031_PIXEL_ARRAY_HEIGHT - rect.top); - __crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which); + __crop = __mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which); if (rect.width != __crop->width || rect.height != __crop->height) { /* Reset the output image size if the crop rectangle size has * been modified. */ - __format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad, - crop->which); + __format = __mt9p031_get_pad_format(mt9p031, fh, sel->pad, + sel->which); __format->width = rect.width; __format->height = rect.height; } *__crop = rect; - crop->rect = rect; + sel->r = rect; return 0; } @@ -980,8 +985,8 @@ static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = { .enum_frame_size = mt9p031_enum_frame_size, .get_fmt = mt9p031_get_format, .set_fmt = mt9p031_set_format, - .get_crop = mt9p031_get_crop, - .set_crop = mt9p031_set_crop, + .get_selection = mt9p031_get_selection, + .set_selection = mt9p031_set_selection, }; static struct v4l2_subdev_ops mt9p031_subdev_ops = { diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index d9e9889b579f..f6ca636b538d 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c @@ -401,39 +401,44 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev, return 0; } -static int mt9t001_get_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9t001_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9t001 *mt9t001 = to_mt9t001(subdev); - crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad, - crop->which); + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + sel->r = *__mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which); return 0; } -static int mt9t001_set_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9t001_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9t001 *mt9t001 = to_mt9t001(subdev); struct v4l2_mbus_framefmt *__format; struct v4l2_rect *__crop; struct v4l2_rect rect; + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + /* Clamp the crop rectangle boundaries and align them to a multiple of 2 * pixels. */ - rect.left = clamp(ALIGN(crop->rect.left, 2), + rect.left = clamp(ALIGN(sel->r.left, 2), MT9T001_COLUMN_START_MIN, MT9T001_COLUMN_START_MAX); - rect.top = clamp(ALIGN(crop->rect.top, 2), + rect.top = clamp(ALIGN(sel->r.top, 2), MT9T001_ROW_START_MIN, MT9T001_ROW_START_MAX); - rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2), + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), MT9T001_WINDOW_WIDTH_MIN + 1, MT9T001_WINDOW_WIDTH_MAX + 1); - rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2), + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), MT9T001_WINDOW_HEIGHT_MIN + 1, MT9T001_WINDOW_HEIGHT_MAX + 1); @@ -442,20 +447,20 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev, rect.height = min_t(unsigned int, rect.height, MT9T001_PIXEL_ARRAY_HEIGHT - rect.top); - __crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which); + __crop = __mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which); if (rect.width != __crop->width || rect.height != __crop->height) { /* Reset the output image size if the crop rectangle size has * been modified. */ - __format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad, - crop->which); + __format = __mt9t001_get_pad_format(mt9t001, fh, sel->pad, + sel->which); __format->width = rect.width; __format->height = rect.height; } *__crop = rect; - crop->rect = rect; + sel->r = rect; return 0; } @@ -819,8 +824,8 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = { .enum_frame_size = mt9t001_enum_frame_size, .get_fmt = mt9t001_get_format, .set_fmt = mt9t001_set_format, - .get_crop = mt9t001_get_crop, - .set_crop = mt9t001_set_crop, + .get_selection = mt9t001_get_selection, + .set_selection = mt9t001_set_selection, }; static struct v4l2_subdev_ops mt9t001_subdev_ops = { diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 93687c1e4097..bd3f979a4d49 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -552,39 +552,44 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, return 0; } -static int mt9v032_get_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9v032_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9v032 *mt9v032 = to_mt9v032(subdev); - crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad, - crop->which); + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which); return 0; } -static int mt9v032_set_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int mt9v032_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct mt9v032 *mt9v032 = to_mt9v032(subdev); struct v4l2_mbus_framefmt *__format; struct v4l2_rect *__crop; struct v4l2_rect rect; + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + /* Clamp the crop rectangle boundaries and align them to a non multiple * of 2 pixels to ensure a GRBG Bayer pattern. */ - rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1, + rect.left = clamp(ALIGN(sel->r.left + 1, 2) - 1, MT9V032_COLUMN_START_MIN, MT9V032_COLUMN_START_MAX); - rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1, + rect.top = clamp(ALIGN(sel->r.top + 1, 2) - 1, MT9V032_ROW_START_MIN, MT9V032_ROW_START_MAX); - rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2), + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), MT9V032_WINDOW_WIDTH_MIN, MT9V032_WINDOW_WIDTH_MAX); - rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2), + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), MT9V032_WINDOW_HEIGHT_MIN, MT9V032_WINDOW_HEIGHT_MAX); @@ -593,17 +598,17 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev, rect.height = min_t(unsigned int, rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); - __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which); + __crop = __mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which); if (rect.width != __crop->width || rect.height != __crop->height) { /* Reset the output image size if the crop rectangle size has * been modified. */ - __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad, - crop->which); + __format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad, + sel->which); __format->width = rect.width; __format->height = rect.height; - if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { mt9v032->hratio = 1; mt9v032->vratio = 1; mt9v032_configure_pixel_rate(mt9v032); @@ -611,7 +616,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev, } *__crop = rect; - crop->rect = rect; + sel->r = rect; return 0; } @@ -844,8 +849,8 @@ static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = { .enum_frame_size = mt9v032_enum_frame_size, .get_fmt = mt9v032_get_format, .set_fmt = mt9v032_set_format, - .get_crop = mt9v032_get_crop, - .set_crop = mt9v032_set_crop, + .get_selection = mt9v032_get_selection, + .set_selection = mt9v032_set_selection, }; static struct v4l2_subdev_ops mt9v032_subdev_ops = { diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 2851581e0061..19edafb82b5b 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -1161,17 +1161,21 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return ret; } -static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int s5k6aa_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct s5k6aa *s5k6aa = to_s5k6aa(sd); struct v4l2_rect *rect; - memset(crop->reserved, 0, sizeof(crop->reserved)); + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + memset(sel->reserved, 0, sizeof(sel->reserved)); mutex_lock(&s5k6aa->lock); - rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which); - crop->rect = *rect; + rect = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which); + sel->r = *rect; mutex_unlock(&s5k6aa->lock); v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n", @@ -1180,35 +1184,39 @@ static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return 0; } -static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +static int s5k6aa_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct s5k6aa *s5k6aa = to_s5k6aa(sd); struct v4l2_mbus_framefmt *mf; unsigned int max_x, max_y; struct v4l2_rect *crop_r; + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + mutex_lock(&s5k6aa->lock); - crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which); + crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which); - if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { mf = &s5k6aa->preset->mbus_fmt; s5k6aa->apply_crop = 1; } else { mf = v4l2_subdev_get_try_format(fh, 0); } - v4l_bound_align_image(&crop->rect.width, mf->width, + v4l_bound_align_image(&sel->r.width, mf->width, S5K6AA_WIN_WIDTH_MAX, 1, - &crop->rect.height, mf->height, + &sel->r.height, mf->height, S5K6AA_WIN_HEIGHT_MAX, 1, 0); - max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1; - max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1; + max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1; + max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1; - crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x); - crop->rect.top = clamp_t(unsigned int, crop->rect.top, 0, max_y); + sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x); + sel->r.top = clamp_t(unsigned int, sel->r.top, 0, max_y); - *crop_r = crop->rect; + *crop_r = sel->r; mutex_unlock(&s5k6aa->lock); @@ -1224,8 +1232,8 @@ static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = { .enum_frame_interval = s5k6aa_enum_frame_interval, .get_fmt = s5k6aa_get_fmt, .set_fmt = s5k6aa_set_fmt, - .get_crop = s5k6aa_get_crop, - .set_crop = s5k6aa_set_crop, + .get_selection = s5k6aa_get_selection, + .set_selection = s5k6aa_set_selection, }; static const struct v4l2_subdev_video_ops s5k6aa_video_ops = { diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 0ba0bf2c1cff..bcf762bc233d 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -1535,7 +1535,7 @@ isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, } /* - * isif_pad_set_crop() - set crop rectangle on pad + * isif_pad_set_selection() - set crop rectangle on pad * @sd: VPFE isif V4L2 subdevice * @fh: V4L2 subdev file handle * @code: pointer to v4l2_subdev_mbus_code_enum structure @@ -1543,35 +1543,36 @@ isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, * Return 0 on success, -EINVAL if pad is invalid */ static int -isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +isif_pad_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; - /* check wether its a valid pad */ - if (crop->pad != ISIF_PAD_SINK) + /* check whether it's a valid pad and target */ + if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; - format = __isif_get_format(vpfe_isif, fh, crop->pad, crop->which); + format = __isif_get_format(vpfe_isif, fh, sel->pad, sel->which); if (format == NULL) return -EINVAL; /* check wether crop rect is within limits */ - if (crop->rect.top < 0 || crop->rect.left < 0 || - (crop->rect.left + crop->rect.width > + if (sel->r.top < 0 || sel->r.left < 0 || + (sel->r.left + sel->r.width > vpfe_isif->formats[ISIF_PAD_SINK].width) || - (crop->rect.top + crop->rect.height > + (sel->r.top + sel->r.height > vpfe_isif->formats[ISIF_PAD_SINK].height)) { - crop->rect.left = 0; - crop->rect.top = 0; - crop->rect.width = format->width; - crop->rect.height = format->height; + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = format->width; + sel->r.height = format->height; } /* adjust the width to 16 pixel boundary */ - crop->rect.width = ((crop->rect.width + 15) & ~0xf); - vpfe_isif->crop = crop->rect; - if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + sel->r.width = ((sel->r.width + 15) & ~0xf); + vpfe_isif->crop = sel->r; + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { isif_set_image_window(vpfe_isif); } else { struct v4l2_rect *rect; @@ -1583,7 +1584,7 @@ isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, } /* - * isif_pad_get_crop() - get crop rectangle on pad + * isif_pad_get_selection() - get crop rectangle on pad * @sd: VPFE isif V4L2 subdevice * @fh: V4L2 subdev file handle * @code: pointer to v4l2_subdev_mbus_code_enum structure @@ -1591,22 +1592,23 @@ isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, * Return 0 on success, -EINVAL if pad is invalid */ static int -isif_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop) +isif_pad_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) { struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - /* check wether its a valid pad */ - if (crop->pad != ISIF_PAD_SINK) + /* check whether it's a valid pad and target */ + if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; - if (crop->which == V4L2_SUBDEV_FORMAT_TRY) { + if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { struct v4l2_rect *rect; rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK); - memcpy(&crop->rect, rect, sizeof(*rect)); + memcpy(&sel->r, rect, sizeof(*rect)); } else { - crop->rect = vpfe_isif->crop; + sel->r = vpfe_isif->crop; } return 0; @@ -1626,7 +1628,7 @@ isif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct v4l2_subdev_format format; - struct v4l2_subdev_crop crop; + struct v4l2_subdev_selection sel; memset(&format, 0, sizeof(format)); format.pad = ISIF_PAD_SINK; @@ -1644,12 +1646,13 @@ isif_init_formats(struct v4l2_subdev *sd, format.format.height = MAX_HEIGHT; isif_set_format(sd, fh, &format); - memset(&crop, 0, sizeof(crop)); - crop.pad = ISIF_PAD_SINK; - crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - crop.rect.width = MAX_WIDTH; - crop.rect.height = MAX_HEIGHT; - isif_pad_set_crop(sd, fh, &crop); + memset(&sel, 0, sizeof(sel)); + sel.pad = ISIF_PAD_SINK; + sel.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP; + sel.r.width = MAX_WIDTH; + sel.r.height = MAX_HEIGHT; + isif_pad_set_selection(sd, fh, &sel); return 0; } @@ -1675,8 +1678,8 @@ static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = { .enum_frame_size = isif_enum_frame_size, .get_fmt = isif_get_format, .set_fmt = isif_set_format, - .set_crop = isif_pad_set_crop, - .get_crop = isif_pad_get_crop, + .set_selection = isif_pad_set_selection, + .get_selection = isif_pad_get_selection, }; /* subdev operations */ -- cgit v1.2.3 From 05b9cc3eeffcb2b0d6720930fc144058d4ace1aa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 4 Dec 2014 06:54:53 -0300 Subject: [media] v4l2-subdev: drop get/set_crop pad ops Drop the duplicate get/set_crop pad ops and only use get/set_selection. It makes no sense to have two duplicate ops in the internal subdev API. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-subdev.c | 8 -------- include/media/v4l2-subdev.h | 4 ---- 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 543631c3557a..19a034e79be4 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -283,10 +283,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (rval) return rval; - rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); - if (rval != -ENOIOCTLCMD) - return rval; - memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; @@ -308,10 +304,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (rval) return rval; - rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); - if (rval != -ENOIOCTLCMD) - return rval; - memset(&sel, 0, sizeof(sel)); sel.which = crop->which; sel.pad = crop->pad; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 5860292d42eb..b052184512e2 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -503,10 +503,6 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); - int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop); - int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, - struct v4l2_subdev_crop *crop); int (*get_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_selection *sel); int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, -- cgit v1.2.3 From 584ca0252abf31388cacbdb3018aab2c70362d8d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 4 Dec 2014 06:54:56 -0300 Subject: [media] media/i2c/Kconfig: drop superfluous MEDIA_CONTROLLER These drivers depend on VIDEO_V4L2_SUBDEV_API, which in turn depends on MEDIA_CONTROLLER. So it is sufficient to just depend on VIDEO_V4L2_SUBDEV_API. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 205d71364343..ca84543cf6ac 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -196,7 +196,7 @@ config VIDEO_ADV7183 config VIDEO_ADV7604 tristate "Analog Devices ADV7604 decoder" - depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API ---help--- Support for the Analog Devices ADV7604 video decoder. @@ -208,7 +208,7 @@ config VIDEO_ADV7604 config VIDEO_ADV7842 tristate "Analog Devices ADV7842 decoder" - depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API ---help--- Support for the Analog Devices ADV7842 video decoder. @@ -422,7 +422,7 @@ config VIDEO_ADV7393 config VIDEO_ADV7511 tristate "Analog Devices ADV7511 encoder" - depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API ---help--- Support for the Analog Devices ADV7511 video encoder. -- cgit v1.2.3 From aadec012eabf0e5147103cfd2ffde27e5aad65e2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 25 Sep 2014 09:22:00 -0300 Subject: [media] omap3isp: Fix division by 0 If the requested clock rate passed to the XCLK set_rate or round_rate operation is 0, the driver will try to divide by 0. Fix this. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 51c2129bdcc6..deca80903c3a 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -220,6 +220,9 @@ static u32 isp_xclk_calc_divider(unsigned long *rate, unsigned long parent_rate) return ISPTCTRL_CTRL_DIV_BYPASS; } + if (*rate == 0) + *rate = 1; + divider = DIV_ROUND_CLOSEST(parent_rate, *rate); if (divider >= ISPTCTRL_CTRL_DIV_BYPASS) divider = ISPTCTRL_CTRL_DIV_BYPASS - 1; -- cgit v1.2.3 From 3e90f789739e5685da0d0b716b04e49e17671877 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 14 Nov 2013 01:03:10 -0300 Subject: [media] v4l: omap4iss: Enable DMABUF support Enable DMABUF import and export operations using videobuf2. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index cdee5966cbca..2085f699da67 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -772,6 +772,14 @@ iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) return vb2_qbuf(&vfh->queue, b); } +static int +iss_video_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *e) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + + return vb2_expbuf(&vfh->queue, e); +} + static int iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) { @@ -1021,6 +1029,7 @@ static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { .vidioc_reqbufs = iss_video_reqbufs, .vidioc_querybuf = iss_video_querybuf, .vidioc_qbuf = iss_video_qbuf, + .vidioc_expbuf = iss_video_expbuf, .vidioc_dqbuf = iss_video_dqbuf, .vidioc_streamon = iss_video_streamon, .vidioc_streamoff = iss_video_streamoff, @@ -1071,7 +1080,7 @@ static int iss_video_open(struct file *file) q = &handle->queue; q->type = video->type; - q->io_modes = VB2_MMAP; + q->io_modes = VB2_MMAP | VB2_DMABUF; q->drv_priv = handle; q->ops = &iss_video_vb2ops; q->mem_ops = &vb2_dma_contig_memops; -- cgit v1.2.3 From dd162547f10132b8ea63adb7f795acc5020616fd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 7 Jul 2014 18:31:24 -0300 Subject: [media] v4l: omap4iss: Remove bogus frame number propagation Frame number propagation tries to increase the robustness of the frame number counter by using sources less likely to be missed than the end of frame interrupts, such as hardware frame counters or start of frame interrupts. Increasing the frame number in the IPIPE ISIF and resizer end of frame interrupt handlers is pointless as it doesn't bring any improvement. Don't do it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_ipipeif.c | 22 +++------------------- drivers/staging/media/omap4iss/iss_resizer.c | 18 +----------------- 2 files changed, 4 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 32a748398ced..3943fae699ee 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -241,23 +241,6 @@ static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif) ipipeif_write_enable(ipipeif, 1); } -/* - * ipipeif_isif0_isr - Handle ISIF0 event - * @ipipeif: Pointer to ISP IPIPEIF device. - * - * Executes LSC deferred enablement before next frame starts. - */ -static void ipipeif_isif0_isr(struct iss_ipipeif_device *ipipeif) -{ - struct iss_pipeline *pipe = - to_iss_pipeline(&ipipeif->subdev.entity); - if (pipe->do_propagation) - atomic_inc(&pipe->frame_number); - - if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) - ipipeif_isr_buffer(ipipeif); -} - /* * omap4iss_ipipeif_isr - Configure ipipeif during interframe time. * @ipipeif: Pointer to ISP IPIPEIF device. @@ -269,8 +252,9 @@ void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) &ipipeif->stopping)) return; - if (events & ISP5_IRQ_ISIF_INT(0)) - ipipeif_isif0_isr(ipipeif); + if ((events & ISP5_IRQ_ISIF_INT(0)) && + (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) + ipipeif_isr_buffer(ipipeif); } /* ----------------------------------------------------------------------------- diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 88522a8cdf56..3ab972818f1b 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -282,22 +282,6 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer) resizer_enable(resizer, 1); } -/* - * resizer_isif0_isr - Handle ISIF0 event - * @resizer: Pointer to ISP RESIZER device. - * - * Executes LSC deferred enablement before next frame starts. - */ -static void resizer_int_dma_isr(struct iss_resizer_device *resizer) -{ - struct iss_pipeline *pipe = - to_iss_pipeline(&resizer->subdev.entity); - if (pipe->do_propagation) - atomic_inc(&pipe->frame_number); - - resizer_isr_buffer(resizer); -} - /* * omap4iss_resizer_isr - Configure resizer during interframe time. * @resizer: Pointer to ISP RESIZER device. @@ -322,7 +306,7 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) return; if (events & ISP5_IRQ_RSZ_INT_DMA) - resizer_int_dma_isr(resizer); + resizer_isr_buffer(resizer); } /* ----------------------------------------------------------------------------- -- cgit v1.2.3 From 707acfc072676d4b9f5db8d2082e2f0c79c34bb4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 7 Jul 2014 18:44:15 -0300 Subject: [media] v4l: omap4iss: csi2: Perform real frame number propagation Compute the pipeline frame number from the frame number sent by the sensor instead of incrementing the frame number in software. This improves dropped frames detection. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 5 ++++ drivers/staging/media/omap4iss/iss_csi2.c | 43 ++++++++++++++++++++++++------- drivers/staging/media/omap4iss/iss_csi2.h | 2 +- drivers/staging/media/omap4iss/iss_regs.h | 2 ++ 4 files changed, 41 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index cc1dfadd91eb..d6534f5dc7f1 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -612,7 +612,12 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, ret = v4l2_subdev_call(subdev, video, s_stream, mode); if (ret < 0 && ret != -ENOIOCTLCMD) return ret; + + if (subdev == &iss->csi2a.subdev || + subdev == &iss->csi2b.subdev) + pipe->do_propagation = true; } + iss_print_status(pipe->output->iss); return 0; } diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index 21971c675b8c..2d96fb3eca53 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -319,6 +319,8 @@ static void csi2_ctx_config(struct iss_csi2_device *csi2, { u32 reg = 0; + ctx->frame = 0; + /* Set up CSI2_CTx_CTRL1 */ if (ctx->eof_enabled) reg = CSI2_CTX_CTRL1_EOF_EN; @@ -396,21 +398,18 @@ static void csi2_timing_config(struct iss_csi2_device *csi2, */ static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) { - u32 reg = CSI2_CTX_IRQ_FE; + const u32 mask = CSI2_CTX_IRQ_FE | CSI2_CTX_IRQ_FS; int i; - if (csi2->use_fs_irq) - reg |= CSI2_CTX_IRQ_FS; - for (i = 0; i < 8; i++) { iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i), - reg); + mask); if (enable) iss_reg_set(csi2->iss, csi2->regs1, - CSI2_CTX_IRQENABLE(i), reg); + CSI2_CTX_IRQENABLE(i), mask); else iss_reg_clr(csi2->iss, csi2->regs1, - CSI2_CTX_IRQENABLE(i), reg); + CSI2_CTX_IRQENABLE(i), mask); } } @@ -679,8 +678,34 @@ static void csi2_isr_ctx(struct iss_csi2_device *csi2, if (status & CSI2_CTX_IRQ_FS) { struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); - if (pipe->do_propagation) + u16 frame; + u16 delta; + + frame = iss_reg_read(csi2->iss, csi2->regs1, + CSI2_CTX_CTRL2(ctx->ctxnum)) + >> CSI2_CTX_CTRL2_FRAME_SHIFT; + + if (frame == 0) { + /* A zero value means that the counter isn't implemented + * by the source. Increment the frame number in software + * in that case. + */ atomic_inc(&pipe->frame_number); + } else { + /* Extend the 16 bit frame number to 32 bits by + * computing the delta between two consecutive CSI2 + * frame numbers and adding it to the software frame + * number. The hardware counter starts at 1 and wraps + * from 0xffff to 1 without going through 0, so subtract + * 1 when the counter wraps. + */ + delta = frame - ctx->frame; + if (frame < ctx->frame) + delta--; + ctx->frame = frame; + + atomic_add(delta, &pipe->frame_number); + } } if (!(status & CSI2_CTX_IRQ_FE)) @@ -1039,7 +1064,6 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) { struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct iss_device *iss = csi2->iss; - struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); struct iss_video *video_out = &csi2->video_out; int ret = 0; @@ -1058,7 +1082,6 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) if (omap4iss_csiphy_acquire(csi2->phy) < 0) return -ENODEV; - csi2->use_fs_irq = pipe->do_propagation; csi2_configure(csi2); csi2_print_status(csi2); diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h index 971aa7b08013..3b37978a3bdf 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ b/drivers/staging/media/omap4iss/iss_csi2.h @@ -82,6 +82,7 @@ struct iss_csi2_ctx_cfg { u8 virtual_id; u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */ u8 dpcm_predictor; /* 1: simple, 0: advanced */ + u16 frame; /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */ u16 alpha; @@ -137,7 +138,6 @@ struct iss_csi2_device { u32 output; /* output to IPIPEIF, memory or both? */ bool dpcm_decompress; unsigned int frame_skip; - bool use_fs_irq; struct iss_csiphy *phy; struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1]; diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index efd0291a86f7..d2b6b6ae9174 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -215,6 +215,8 @@ #define CSI2_CTX_CTRL1_CTX_EN (1 << 0) #define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * i)) +#define CSI2_CTX_CTRL2_FRAME_MASK (0xffff << 16) +#define CSI2_CTX_CTRL2_FRAME_SHIFT 16 #define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13 #define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK \ (0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT) -- cgit v1.2.3 From 9587a3fc4333efd9cfd56a0754cabf76bdcdb3b0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Oct 2014 09:07:37 -0300 Subject: [media] v4l: omap4iss: Stop started entities when pipeline start fails If an entity can't be started when starting a pipeline we need to clean up by stopping all entities that have been successfully started. Otherwise the hardware and software states won't match, potentially leading to crashes (for instance due to the CSI2 receiver receiving interrupts with a NULL pipeline pointer). Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 108 +++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index d6534f5dc7f1..44b81a2c8b6f 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -559,6 +559,61 @@ static int iss_pipeline_link_notify(struct media_link *link, u32 flags, * Pipeline stream management */ +/* + * iss_pipeline_disable - Disable streaming on a pipeline + * @pipe: ISS pipeline + * @until: entity at which to stop pipeline walk + * + * Walk the entities chain starting at the pipeline output video node and stop + * all modules in the chain. Wait synchronously for the modules to be stopped if + * necessary. + * + * If the until argument isn't NULL, stop the pipeline walk when reaching the + * until entity. This is used to disable a partially started pipeline due to a + * subdev start error. + */ +static int iss_pipeline_disable(struct iss_pipeline *pipe, + struct media_entity *until) +{ + struct iss_device *iss = pipe->output->iss; + struct media_entity *entity; + struct media_pad *pad; + struct v4l2_subdev *subdev; + int failure = 0; + int ret; + + entity = &pipe->output->video.entity; + while (1) { + pad = &entity->pads[0]; + if (!(pad->flags & MEDIA_PAD_FL_SINK)) + break; + + pad = media_entity_remote_pad(pad); + if (pad == NULL || + media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + break; + + entity = pad->entity; + if (entity == until) + break; + + subdev = media_entity_to_v4l2_subdev(entity); + ret = v4l2_subdev_call(subdev, video, s_stream, 0); + if (ret < 0) { + dev_dbg(iss->dev, "%s: module stop timeout.\n", + subdev->name); + /* If the entity failed to stopped, assume it has + * crashed. Mark it as such, the ISS will be reset when + * applications will release it. + */ + iss->crashed |= 1U << subdev->entity.id; + failure = -ETIMEDOUT; + } + } + + return failure; +} + /* * iss_pipeline_enable - Enable streaming on a pipeline * @pipe: ISS pipeline @@ -610,8 +665,10 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, subdev = media_entity_to_v4l2_subdev(entity); ret = v4l2_subdev_call(subdev, video, s_stream, mode); - if (ret < 0 && ret != -ENOIOCTLCMD) + if (ret < 0 && ret != -ENOIOCTLCMD) { + iss_pipeline_disable(pipe, entity); return ret; + } if (subdev == &iss->csi2a.subdev || subdev == &iss->csi2b.subdev) @@ -622,53 +679,6 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, return 0; } -/* - * iss_pipeline_disable - Disable streaming on a pipeline - * @pipe: ISS pipeline - * - * Walk the entities chain starting at the pipeline output video node and stop - * all modules in the chain. Wait synchronously for the modules to be stopped if - * necessary. - */ -static int iss_pipeline_disable(struct iss_pipeline *pipe) -{ - struct iss_device *iss = pipe->output->iss; - struct media_entity *entity; - struct media_pad *pad; - struct v4l2_subdev *subdev; - int failure = 0; - int ret; - - entity = &pipe->output->video.entity; - while (1) { - pad = &entity->pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - pad = media_entity_remote_pad(pad); - if (pad == NULL || - media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - break; - - entity = pad->entity; - subdev = media_entity_to_v4l2_subdev(entity); - - ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (ret < 0) { - dev_dbg(iss->dev, "%s: module stop timeout.\n", - subdev->name); - /* If the entity failed to stopped, assume it has - * crashed. Mark it as such, the ISS will be reset when - * applications will release it. - */ - iss->crashed |= 1U << subdev->entity.id; - failure = -ETIMEDOUT; - } - } - - return failure; -} - /* * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline * @pipe: ISS pipeline @@ -687,7 +697,7 @@ int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, int ret; if (state == ISS_PIPELINE_STREAM_STOPPED) - ret = iss_pipeline_disable(pipe); + ret = iss_pipeline_disable(pipe, NULL); else ret = iss_pipeline_enable(pipe, state); -- cgit v1.2.3 From 5fb3f55504d5d9b6ca97131091707afd351fe1dc Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Wed, 26 Nov 2014 20:25:44 -0300 Subject: [media] media: usb: uvc: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_queue.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index cc960723b926..10c554e7655c 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -143,20 +143,6 @@ static void uvc_buffer_finish(struct vb2_buffer *vb) uvc_video_clock_update(stream, &vb->v4l2_buf, buf); } -static void uvc_wait_prepare(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_unlock(&queue->mutex); -} - -static void uvc_wait_finish(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_lock(&queue->mutex); -} - static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); @@ -195,8 +181,8 @@ static struct vb2_ops uvc_queue_qops = { .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, .buf_finish = uvc_buffer_finish, - .wait_prepare = uvc_wait_prepare, - .wait_finish = uvc_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .start_streaming = uvc_start_streaming, .stop_streaming = uvc_stop_streaming, }; @@ -214,6 +200,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, queue->queue.mem_ops = &vb2_vmalloc_memops; queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_TSTAMP_SRC_SOE; + queue->queue.lock = &queue->mutex; ret = vb2_queue_init(&queue->queue); if (ret) return ret; -- cgit v1.2.3 From 1b8dc32286a1a4fb73cfc7793ef103f3993a6478 Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 8 Dec 2014 15:57:58 -0300 Subject: [media] uvcvideo: Add GUID for BGR 8:8:8 The Magewell XI100DUSB-HDMI[1] video capture device reports the pixel format "e436eb7d-524f-11ce-9f53-0020af0ba770". This is its GUID for BGR 8:8:8. The UVC 1.5 spec[2] only defines GUIDs for YUY2, NV12, M420 and I420. This seems to be an extension documented in the Microsoft Windows Media Format SDK[3] - or at least the Media Format SDK was the only hit that Google gave when searching for the GUID. This Media Format SDK defines this GUID as corresponding to `MEDIASUBTYPE_RGB24`. Note though, the XI100DUSB outputs BGR e.g. byte-reversed. I don't know if its the capture device in error or Microsoft mean BGR when they say RGB. [1]: http://www.magewell.com/hardware/dongles/xi100dusb-hdmi/xi100dusb-hdmi_features.html?lang=en [2]: http://www.usb.org/developers/docs/devclass_docs/USB_Video_Class_1_5.zip [3]: http://msdn.microsoft.com/en-gb/library/windows/desktop/dd757532(v=vs.85).aspx Signed-off-by: William Manley Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 5 +++++ drivers/media/usb/uvc/uvcvideo.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 6a4b0b8cd270..cf27006c29dc 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -137,6 +137,11 @@ static struct uvc_format_desc uvc_fmts[] = { .guid = UVC_GUID_FORMAT_RGBP, .fcc = V4L2_PIX_FMT_RGB565, }, + { + .name = "BGR 8:8:8 (BGR3)", + .guid = UVC_GUID_FORMAT_BGR3, + .fcc = V4L2_PIX_FMT_BGR24, + }, { .name = "H.264", .guid = UVC_GUID_FORMAT_H264, diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index f0a04b532ede..c63e5b55e143 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -109,6 +109,9 @@ #define UVC_GUID_FORMAT_RGBP \ { 'R', 'G', 'B', 'P', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_BGR3 \ + { 0x7d, 0xeb, 0x36, 0xe4, 0x4f, 0x52, 0xce, 0x11, \ + 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} #define UVC_GUID_FORMAT_M420 \ { 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -- cgit v1.2.3 From 32d17597d3e299ffe8b07e3afc12f8074e7ae483 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Apr 2014 08:13:18 -0300 Subject: [media] v4l: vsp1: Remove support for platform data Now that all platforms instantiate the VSP1 through DT, platform data support isn't needed anymore. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 2 +- drivers/media/platform/vsp1/vsp1.h | 14 +++++- drivers/media/platform/vsp1/vsp1_drv.c | 81 ++++++++++++---------------------- drivers/media/platform/vsp1/vsp1_wpf.c | 2 +- include/linux/platform_data/vsp1.h | 27 ------------ 5 files changed, 43 insertions(+), 83 deletions(-) delete mode 100644 include/linux/platform_data/vsp1.h (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 765bffb49a72..480a174832a6 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -223,7 +223,7 @@ config VIDEO_SH_VEU config VIDEO_RENESAS_VSP1 tristate "Renesas VSP1 Video Processing Engine" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on (ARCH_SHMOBILE && OF) || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG ---help--- This is a V4L2 driver for the Renesas VSP1 video processing engine. diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 12467191dff4..989e96f7e360 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -40,9 +39,20 @@ struct vsp1_uds; #define VSP1_MAX_UDS 3 #define VSP1_MAX_WPF 4 +#define VSP1_HAS_LIF (1 << 0) +#define VSP1_HAS_LUT (1 << 1) +#define VSP1_HAS_SRU (1 << 2) + +struct vsp1_platform_data { + unsigned int features; + unsigned int rpf_count; + unsigned int uds_count; + unsigned int wpf_count; +}; + struct vsp1_device { struct device *dev; - struct vsp1_platform_data *pdata; + struct vsp1_platform_data pdata; void __iomem *mmio; struct clk *clock; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 5eb16e87d53f..913485a90e97 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -40,7 +40,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) irqreturn_t ret = IRQ_NONE; unsigned int i; - for (i = 0; i < vsp1->pdata->wpf_count; ++i) { + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { struct vsp1_rwpf *wpf = vsp1->wpf[i]; struct vsp1_pipeline *pipe; u32 status; @@ -181,7 +181,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities); - if (vsp1->pdata->features & VSP1_HAS_LIF) { + if (vsp1->pdata.features & VSP1_HAS_LIF) { vsp1->lif = vsp1_lif_create(vsp1); if (IS_ERR(vsp1->lif)) { ret = PTR_ERR(vsp1->lif); @@ -191,7 +191,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities); } - if (vsp1->pdata->features & VSP1_HAS_LUT) { + if (vsp1->pdata.features & VSP1_HAS_LUT) { vsp1->lut = vsp1_lut_create(vsp1); if (IS_ERR(vsp1->lut)) { ret = PTR_ERR(vsp1->lut); @@ -201,7 +201,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata->rpf_count; ++i) { + for (i = 0; i < vsp1->pdata.rpf_count; ++i) { struct vsp1_rwpf *rpf; rpf = vsp1_rpf_create(vsp1, i); @@ -214,7 +214,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&rpf->entity.list_dev, &vsp1->entities); } - if (vsp1->pdata->features & VSP1_HAS_SRU) { + if (vsp1->pdata.features & VSP1_HAS_SRU) { vsp1->sru = vsp1_sru_create(vsp1); if (IS_ERR(vsp1->sru)) { ret = PTR_ERR(vsp1->sru); @@ -224,7 +224,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata->uds_count; ++i) { + for (i = 0; i < vsp1->pdata.uds_count; ++i) { struct vsp1_uds *uds; uds = vsp1_uds_create(vsp1, i); @@ -237,7 +237,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&uds->entity.list_dev, &vsp1->entities); } - for (i = 0; i < vsp1->pdata->wpf_count; ++i) { + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { struct vsp1_rwpf *wpf; wpf = vsp1_wpf_create(vsp1, i); @@ -261,7 +261,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) goto done; } - if (vsp1->pdata->features & VSP1_HAS_LIF) { + if (vsp1->pdata.features & VSP1_HAS_LIF) { ret = media_entity_create_link( &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); @@ -294,7 +294,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1) /* Reset any channel that might be running. */ status = vsp1_read(vsp1, VI6_STATUS); - for (i = 0; i < vsp1->pdata->wpf_count; ++i) { + for (i = 0; i < vsp1->pdata.wpf_count; ++i) { unsigned int timeout; if (!(status & VI6_STATUS_SYS_ACT(i))) @@ -318,10 +318,10 @@ static int vsp1_device_init(struct vsp1_device *vsp1) vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) | (8 << VI6_CLK_DCSWT_CSTRW_SHIFT)); - for (i = 0; i < vsp1->pdata->rpf_count; ++i) + for (i = 0; i < vsp1->pdata.rpf_count; ++i) vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED); - for (i = 0; i < vsp1->pdata->uds_count; ++i) + for (i = 0; i < vsp1->pdata.uds_count; ++i) vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); @@ -428,28 +428,36 @@ static const struct dev_pm_ops vsp1_pm_ops = { * Platform Driver */ -static int vsp1_validate_platform_data(struct platform_device *pdev, - struct vsp1_platform_data *pdata) +static int vsp1_parse_dt(struct vsp1_device *vsp1) { - if (pdata == NULL) { - dev_err(&pdev->dev, "missing platform data\n"); - return -EINVAL; - } + struct device_node *np = vsp1->dev->of_node; + struct vsp1_platform_data *pdata = &vsp1->pdata; + + if (of_property_read_bool(np, "renesas,has-lif")) + pdata->features |= VSP1_HAS_LIF; + if (of_property_read_bool(np, "renesas,has-lut")) + pdata->features |= VSP1_HAS_LUT; + if (of_property_read_bool(np, "renesas,has-sru")) + pdata->features |= VSP1_HAS_SRU; + + of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count); + of_property_read_u32(np, "renesas,#uds", &pdata->uds_count); + of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count); if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) { - dev_err(&pdev->dev, "invalid number of RPF (%u)\n", + dev_err(vsp1->dev, "invalid number of RPF (%u)\n", pdata->rpf_count); return -EINVAL; } if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) { - dev_err(&pdev->dev, "invalid number of UDS (%u)\n", + dev_err(vsp1->dev, "invalid number of UDS (%u)\n", pdata->uds_count); return -EINVAL; } if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) { - dev_err(&pdev->dev, "invalid number of WPF (%u)\n", + dev_err(vsp1->dev, "invalid number of WPF (%u)\n", pdata->wpf_count); return -EINVAL; } @@ -457,33 +465,6 @@ static int vsp1_validate_platform_data(struct platform_device *pdev, return 0; } -static struct vsp1_platform_data * -vsp1_get_platform_data(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct vsp1_platform_data *pdata; - - if (!IS_ENABLED(CONFIG_OF) || np == NULL) - return pdev->dev.platform_data; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (pdata == NULL) - return NULL; - - if (of_property_read_bool(np, "renesas,has-lif")) - pdata->features |= VSP1_HAS_LIF; - if (of_property_read_bool(np, "renesas,has-lut")) - pdata->features |= VSP1_HAS_LUT; - if (of_property_read_bool(np, "renesas,has-sru")) - pdata->features |= VSP1_HAS_SRU; - - of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count); - of_property_read_u32(np, "renesas,#uds", &pdata->uds_count); - of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count); - - return pdata; -} - static int vsp1_probe(struct platform_device *pdev) { struct vsp1_device *vsp1; @@ -499,11 +480,7 @@ static int vsp1_probe(struct platform_device *pdev) mutex_init(&vsp1->lock); INIT_LIST_HEAD(&vsp1->entities); - vsp1->pdata = vsp1_get_platform_data(pdev); - if (vsp1->pdata == NULL) - return -ENODEV; - - ret = vsp1_validate_platform_data(pdev, vsp1->pdata); + ret = vsp1_parse_dt(vsp1); if (ret < 0) return ret; diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 6e057762c933..b1089d05583a 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -280,7 +280,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) * except for the WPF0 source link if a LIF is present. */ flags = MEDIA_LNK_FL_ENABLED; - if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0) + if (!(vsp1->pdata.features & VSP1_HAS_LIF) || index != 0) flags |= MEDIA_LNK_FL_IMMUTABLE; ret = media_entity_create_link(&wpf->entity.subdev.entity, diff --git a/include/linux/platform_data/vsp1.h b/include/linux/platform_data/vsp1.h deleted file mode 100644 index 63170e2614b3..000000000000 --- a/include/linux/platform_data/vsp1.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * vsp1.h -- R-Car VSP1 Platform Data - * - * Copyright (C) 2013 Renesas Corporation - * - * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef __PLATFORM_VSP1_H__ -#define __PLATFORM_VSP1_H__ - -#define VSP1_HAS_LIF (1 << 0) -#define VSP1_HAS_LUT (1 << 1) -#define VSP1_HAS_SRU (1 << 2) - -struct vsp1_platform_data { - unsigned int features; - unsigned int rpf_count; - unsigned int uds_count; - unsigned int wpf_count; -}; - -#endif /* __PLATFORM_VSP1_H__ */ -- cgit v1.2.3 From 857161fc7d3734f8fd8707f1bc756c1158694371 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 26 Nov 2014 22:25:01 -0300 Subject: [media] v4l: vsp1: Reset VSP1 RPF source address Source address of VSP1 RPF needs to be reset whenever crop offsets are recalculated. This correctly reflects a crop setting even VIDIOC_QBUF is called before VIDIOC_STREAMON is called. Signed-off-by: Takanari Hayama Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 18 ++++++++++++++++++ drivers/media/platform/vsp1/vsp1_rwpf.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index d14d26b718ef..3294529a3108 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -106,11 +106,22 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) + crop->left * fmtinfo->bpp[0] / 8; pstride = format->plane_fmt[0].bytesperline << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; + + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, + rpf->buf_addr[0] + rpf->offsets[0]); + if (format->num_planes > 1) { rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline + crop->left * fmtinfo->bpp[1] / 8; pstride |= format->plane_fmt[1].bytesperline << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; + + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, + rpf->buf_addr[1] + rpf->offsets[1]); + + if (format->num_planes > 2) + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, + rpf->buf_addr[2] + rpf->offsets[1]); } vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); @@ -179,6 +190,13 @@ static void rpf_vdev_queue(struct vsp1_video *video, struct vsp1_video_buffer *buf) { struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video); + unsigned int i; + + for (i = 0; i < 3; ++i) + rpf->buf_addr[i] = buf->addr[i]; + + if (!vsp1_entity_is_streaming(&rpf->entity)) + return; vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, buf->addr[0] + rpf->offsets[0]); diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 28dd9e7b3838..2cf1f13d3bf9 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -39,6 +39,7 @@ struct vsp1_rwpf { struct v4l2_rect crop; unsigned int offsets[2]; + dma_addr_t buf_addr[3]; }; static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) -- cgit v1.2.3 From 5d0beeec59e303c76160ddd67fa73dcfc5d76de0 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 26 Nov 2014 22:25:02 -0300 Subject: [media] v4l: vsp1: Always enable virtual RPF when BRU is in use Regardless of a number of inputs, we should always enable virtual RPF when BRU is used. This allows the case when there's only one input to BRU, and a size of the input is smaller than a size of an output of BRU. Signed-off-by: Takanari Hayama Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_wpf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index b1089d05583a..1d2b3a2f1573 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -92,19 +92,20 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) return 0; } - /* Sources. If the pipeline has a single input configure it as the - * master layer. Otherwise configure all inputs as sub-layers and - * select the virtual RPF as the master layer. + /* Sources. If the pipeline has a single input and BRU is not used, + * configure it as the master layer. Otherwise configure all + * inputs as sub-layers and select the virtual RPF as the master + * layer. */ for (i = 0; i < pipe->num_inputs; ++i) { struct vsp1_rwpf *input = pipe->inputs[i]; - srcrpf |= pipe->num_inputs == 1 + srcrpf |= (!pipe->bru && pipe->num_inputs == 1) ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index); } - if (pipe->num_inputs > 1) + if (pipe->bru || pipe->num_inputs > 1) srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); -- cgit v1.2.3 From 5ede94c7055392bb55c6d2e26f1912f68ef4b875 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:54 -0300 Subject: [media] cx25821: remove bogus btcx_risc dependency Those btcx_risc functions are meant for use with bttv, other drivers should just allocate the memory themselves. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/Kconfig | 1 - drivers/media/pci/cx25821/Makefile | 1 - drivers/media/pci/cx25821/cx25821-alsa.c | 6 ++++-- drivers/media/pci/cx25821/cx25821-core.c | 36 +++++++++++++++++++++++++------ drivers/media/pci/cx25821/cx25821-video.c | 6 ++++-- drivers/media/pci/cx25821/cx25821.h | 21 ++++++++++++------ 6 files changed, 52 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 6439a847680c..0e69cabb006f 100644 --- a/drivers/media/pci/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig @@ -2,7 +2,6 @@ config VIDEO_CX25821 tristate "Conexant cx25821 support" depends on VIDEO_DEV && PCI && I2C select I2C_ALGOBIT - select VIDEO_BTCX select VIDEOBUF_DMA_SG ---help--- This is a video4linux driver for Conexant 25821 based diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index fb76c3d3713a..5872feb266a6 100644 --- a/drivers/media/pci/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile @@ -6,4 +6,3 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o ccflags-y += -Idrivers/media/i2c -ccflags-y += -Idrivers/media/common diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 2dd5bcaa7e53..27e6493622b6 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -63,7 +63,7 @@ static int devno; struct cx25821_audio_buffer { unsigned int bpl; - struct btcx_riscmem risc; + struct cx25821_riscmem risc; struct videobuf_dmabuf dma; }; @@ -330,12 +330,14 @@ out: static int dsp_buffer_free(struct cx25821_audio_dev *chip) { + struct cx25821_riscmem *risc = &chip->buf->risc; + BUG_ON(!chip->dma_size); dprintk(2, "Freeing buffer\n"); videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); - btcx_riscmem_free(chip->pci, &chip->buf->risc); + pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma); kfree(chip->buf); chip->dma_risc = NULL; diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 389fffd2f36f..c8c65b793581 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -979,6 +979,27 @@ void cx25821_dev_unregister(struct cx25821_dev *dev) } EXPORT_SYMBOL(cx25821_dev_unregister); +int cx25821_riscmem_alloc(struct pci_dev *pci, + struct cx25821_riscmem *risc, + unsigned int size) +{ + __le32 *cpu; + dma_addr_t dma = 0; + + if (NULL != risc->cpu && risc->size < size) + pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); + if (NULL == risc->cpu) { + cpu = pci_zalloc_consistent(pci, size, &dma); + if (NULL == cpu) + return -ENOMEM; + risc->cpu = cpu; + risc->dma = dma; + risc->size = size; + } + return 0; +} +EXPORT_SYMBOL(cx25821_riscmem_alloc); + static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, @@ -1035,7 +1056,7 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, return rp; } -int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, unsigned int padding, unsigned int lines) @@ -1059,7 +1080,7 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); instructions += 2; - rc = btcx_riscmem_alloc(pci, risc, instructions * 12); + rc = cx25821_riscmem_alloc(pci, risc, instructions * 12); if (rc < 0) return rc; @@ -1146,7 +1167,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, } int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, + struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, unsigned int lines, unsigned int lpi) @@ -1163,7 +1184,7 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; instructions += 1; - rc = btcx_riscmem_alloc(pci, risc, instructions * 12); + rc = cx25821_riscmem_alloc(pci, risc, instructions * 12); if (rc < 0) return rc; @@ -1179,13 +1200,13 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, } EXPORT_SYMBOL(cx25821_risc_databuffer_audio); -int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx25821_risc_stopper(struct pci_dev *pci, struct cx25821_riscmem *risc, u32 reg, u32 mask, u32 value) { __le32 *rp; int rc; - rc = btcx_riscmem_alloc(pci, risc, 4 * 16); + rc = cx25821_riscmem_alloc(pci, risc, 4 * 16); if (rc < 0) return rc; @@ -1211,7 +1232,8 @@ void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) videobuf_waiton(q, &buf->vb, 0, 0); videobuf_dma_unmap(q->dev, dma); videobuf_dma_free(dma); - btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); + pci_free_consistent(to_pci_dev(q->dev), + buf->risc.size, buf->risc.cpu, buf->risc.dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; } diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 3a419f134584..3eda1a1e1e25 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -1017,11 +1017,13 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) cx_clear(PCI_INT_MSK, 1); if (video_is_registered(&dev->channels[chan_num].vdev)) { + struct cx25821_riscmem *risc = + &dev->channels[chan_num].dma_vidq.stopper; + video_unregister_device(&dev->channels[chan_num].vdev); v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl); - btcx_riscmem_free(dev->pci, - &dev->channels[chan_num].dma_vidq.stopper); + pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); } } diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 90bdc196929f..38beec2c0969 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -36,7 +36,6 @@ #include #include -#include "btcx-risc.h" #include "cx25821-reg.h" #include "cx25821-medusa-reg.h" #include "cx25821-sram.h" @@ -111,6 +110,13 @@ enum cx25821_src_sel_type { CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO }; +struct cx25821_riscmem { + unsigned int size; + __le32 *cpu; + __le32 *jmp; + dma_addr_t dma; +}; + /* buffer for one video frame */ struct cx25821_buffer { /* common v4l buffer stuff -- must be first */ @@ -118,7 +124,7 @@ struct cx25821_buffer { /* cx25821 specific */ unsigned int bpl; - struct btcx_riscmem risc; + struct cx25821_riscmem risc; const struct cx25821_fmt *fmt; u32 count; }; @@ -161,7 +167,7 @@ struct cx25821_dmaqueue { struct list_head active; struct list_head queued; struct timer_list timeout; - struct btcx_riscmem stopper; + struct cx25821_riscmem stopper; u32 count; }; @@ -405,20 +411,23 @@ extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, const struct sram_channel *ch, unsigned int bpl, u32 risc); -extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, +extern int cx25821_riscmem_alloc(struct pci_dev *pci, + struct cx25821_riscmem *risc, + unsigned int size); +extern int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, unsigned int padding, unsigned int lines); extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, + struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, unsigned int lines, unsigned int lpi); extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf); -extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +extern int cx25821_risc_stopper(struct pci_dev *pci, struct cx25821_riscmem *risc, u32 reg, u32 mask, u32 value); extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, const struct sram_channel *ch); -- cgit v1.2.3 From 1e4518086ae863814a3481a180264a1ac89a730b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:55 -0300 Subject: [media] cx231xx: remove btcx_riscmem reference Remove this comment block, it's unused. This removes the btcx_riscmem reference as well, since that will no longer be available to other drivers except bttv. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index f9e262eb0db9..6d6f3ee812f6 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -532,15 +532,7 @@ struct cx231xx_video_mode { unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ u16 end_point_addr; }; -/* -struct cx23885_dmaqueue { - struct list_head active; - struct list_head queued; - struct timer_list timeout; - struct btcx_riscmem stopper; - u32 count; -}; -*/ + struct cx231xx_tsport { struct cx231xx *dev; -- cgit v1.2.3 From 90ca8bef9082c2036a200dd2cd17924944cd339b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:56 -0300 Subject: [media] btcx-risc: move to bt8xx The btcx-risc module is no longer used by other drivers except for bttv. So move it from common to bt8xx and make it part of the bttv driver instead of as a separate module. This module should never have been a common module since most of the code has always been bttv specific. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/Kconfig | 4 - drivers/media/common/Makefile | 1 - drivers/media/common/btcx-risc.c | 254 ------------------------------------ drivers/media/pci/bt8xx/Kconfig | 1 - drivers/media/pci/bt8xx/Makefile | 2 +- drivers/media/pci/bt8xx/btcx-risc.c | 240 ++++++++++++++++++++++++++++++++++ drivers/media/pci/bt8xx/btcx-risc.h | 26 ++++ 7 files changed, 267 insertions(+), 261 deletions(-) delete mode 100644 drivers/media/common/btcx-risc.c create mode 100644 drivers/media/pci/bt8xx/btcx-risc.c create mode 100644 drivers/media/pci/bt8xx/btcx-risc.h (limited to 'drivers') diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index b85f88c8ddbd..21154dd87b0b 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -8,10 +8,6 @@ comment "common driver options" config VIDEO_CX2341X tristate -config VIDEO_BTCX - depends on PCI - tristate - config VIDEO_TVEEPROM tristate depends on I2C diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index d208de3b7cc0..89b795df2cdd 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,5 +1,4 @@ obj-y += b2c2/ saa7146/ siano/ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o -obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o diff --git a/drivers/media/common/btcx-risc.c b/drivers/media/common/btcx-risc.c deleted file mode 100644 index e67338aa8c89..000000000000 --- a/drivers/media/common/btcx-risc.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - - btcx-risc.c - - bt848/bt878/cx2388x risc code generator. - - (c) 2000-03 Gerd Knorr [SuSE Labs] - - 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 -#include - -#include "btcx-risc.h" - -MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers"); -MODULE_AUTHOR("Gerd Knorr"); -MODULE_LICENSE("GPL"); - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)"); - -/* ---------------------------------------------------------- */ -/* allocate/free risc memory */ - -static int memcnt; - -void btcx_riscmem_free(struct pci_dev *pci, - struct btcx_riscmem *risc) -{ - if (NULL == risc->cpu) - return; - if (debug) { - memcnt--; - printk("btcx: riscmem free [%d] dma=%lx\n", - memcnt, (unsigned long)risc->dma); - } - pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); - memset(risc,0,sizeof(*risc)); -} - -int btcx_riscmem_alloc(struct pci_dev *pci, - struct btcx_riscmem *risc, - unsigned int size) -{ - __le32 *cpu; - dma_addr_t dma = 0; - - if (NULL != risc->cpu && risc->size < size) - btcx_riscmem_free(pci,risc); - if (NULL == risc->cpu) { - cpu = pci_alloc_consistent(pci, size, &dma); - if (NULL == cpu) - return -ENOMEM; - risc->cpu = cpu; - risc->dma = dma; - risc->size = size; - if (debug) { - memcnt++; - printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n", - memcnt, (unsigned long)dma, cpu, size); - } - } - memset(risc->cpu,0,risc->size); - return 0; -} - -/* ---------------------------------------------------------- */ -/* screen overlay helpers */ - -int -btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, - struct v4l2_clip *clips, unsigned int n) -{ - if (win->left < 0) { - /* left */ - clips[n].c.left = 0; - clips[n].c.top = 0; - clips[n].c.width = -win->left; - clips[n].c.height = win->height; - n++; - } - if (win->left + win->width > swidth) { - /* right */ - clips[n].c.left = swidth - win->left; - clips[n].c.top = 0; - clips[n].c.width = win->width - clips[n].c.left; - clips[n].c.height = win->height; - n++; - } - if (win->top < 0) { - /* top */ - clips[n].c.left = 0; - clips[n].c.top = 0; - clips[n].c.width = win->width; - clips[n].c.height = -win->top; - n++; - } - if (win->top + win->height > sheight) { - /* bottom */ - clips[n].c.left = 0; - clips[n].c.top = sheight - win->top; - clips[n].c.width = win->width; - clips[n].c.height = win->height - clips[n].c.top; - n++; - } - return n; -} - -int -btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask) -{ - s32 nx,nw,dx; - unsigned int i; - - /* fixup window */ - nx = (win->left + mask) & ~mask; - nw = (win->width) & ~mask; - if (nx + nw > win->left + win->width) - nw -= mask+1; - dx = nx - win->left; - win->left = nx; - win->width = nw; - if (debug) - printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n", - win->width, win->height, win->left, win->top, dx); - - /* fixup clips */ - for (i = 0; i < n; i++) { - nx = (clips[i].c.left-dx) & ~mask; - nw = (clips[i].c.width) & ~mask; - if (nx + nw < clips[i].c.left-dx + clips[i].c.width) - nw += mask+1; - clips[i].c.left = nx; - clips[i].c.width = nw; - if (debug) - printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n", - clips[i].c.width, clips[i].c.height, - clips[i].c.left, clips[i].c.top); - } - return 0; -} - -void -btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips) -{ - struct v4l2_clip swap; - int i,j,n; - - if (nclips < 2) - return; - for (i = nclips-2; i >= 0; i--) { - for (n = 0, j = 0; j <= i; j++) { - if (clips[j].c.left > clips[j+1].c.left) { - swap = clips[j]; - clips[j] = clips[j+1]; - clips[j+1] = swap; - n++; - } - } - if (0 == n) - break; - } -} - -void -btcx_calc_skips(int line, int width, int *maxy, - struct btcx_skiplist *skips, unsigned int *nskips, - const struct v4l2_clip *clips, unsigned int nclips) -{ - unsigned int clip,skip; - int end, maxline; - - skip=0; - maxline = 9999; - for (clip = 0; clip < nclips; clip++) { - - /* sanity checks */ - if (clips[clip].c.left + clips[clip].c.width <= 0) - continue; - if (clips[clip].c.left > (signed)width) - break; - - /* vertical range */ - if (line > clips[clip].c.top+clips[clip].c.height-1) - continue; - if (line < clips[clip].c.top) { - if (maxline > clips[clip].c.top-1) - maxline = clips[clip].c.top-1; - continue; - } - if (maxline > clips[clip].c.top+clips[clip].c.height-1) - maxline = clips[clip].c.top+clips[clip].c.height-1; - - /* horizontal range */ - if (0 == skip || clips[clip].c.left > skips[skip-1].end) { - /* new one */ - skips[skip].start = clips[clip].c.left; - if (skips[skip].start < 0) - skips[skip].start = 0; - skips[skip].end = clips[clip].c.left + clips[clip].c.width; - if (skips[skip].end > width) - skips[skip].end = width; - skip++; - } else { - /* overlaps -- expand last one */ - end = clips[clip].c.left + clips[clip].c.width; - if (skips[skip-1].end < end) - skips[skip-1].end = end; - if (skips[skip-1].end > width) - skips[skip-1].end = width; - } - } - *nskips = skip; - *maxy = maxline; - - if (debug) { - printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline); - for (skip = 0; skip < *nskips; skip++) { - printk(" %d-%d",skips[skip].start,skips[skip].end); - } - printk("\n"); - } -} - -/* ---------------------------------------------------------- */ - -EXPORT_SYMBOL(btcx_riscmem_alloc); -EXPORT_SYMBOL(btcx_riscmem_free); - -EXPORT_SYMBOL(btcx_screen_clips); -EXPORT_SYMBOL(btcx_align); -EXPORT_SYMBOL(btcx_sort_clips); -EXPORT_SYMBOL(btcx_calc_skips); diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig index 61d09e010814..496cf6b2dc43 100644 --- a/drivers/media/pci/bt8xx/Kconfig +++ b/drivers/media/pci/bt8xx/Kconfig @@ -2,7 +2,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT - select VIDEO_BTCX select VIDEOBUF_DMA_SG depends on RC_CORE select VIDEO_TUNER diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile index f9fe7c4e7d53..2d4c3dd88be1 100644 --- a/drivers/media/pci/bt8xx/Makefile +++ b/drivers/media/pci/bt8xx/Makefile @@ -1,6 +1,6 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ - bttv-input.o bttv-audio-hook.o + bttv-input.o bttv-audio-hook.o btcx-risc.o obj-$(CONFIG_VIDEO_BT848) += bttv.o obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o diff --git a/drivers/media/pci/bt8xx/btcx-risc.c b/drivers/media/pci/bt8xx/btcx-risc.c new file mode 100644 index 000000000000..00f0880b6d66 --- /dev/null +++ b/drivers/media/pci/bt8xx/btcx-risc.c @@ -0,0 +1,240 @@ +/* + + btcx-risc.c + + bt848/bt878/cx2388x risc code generator. + + (c) 2000-03 Gerd Knorr [SuSE Labs] + + 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 +#include + +#include "btcx-risc.h" + +static unsigned int btcx_debug; +module_param(btcx_debug, int, 0644); +MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)"); + +/* ---------------------------------------------------------- */ +/* allocate/free risc memory */ + +static int memcnt; + +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc) +{ + if (NULL == risc->cpu) + return; + if (btcx_debug) { + memcnt--; + printk("btcx: riscmem free [%d] dma=%lx\n", + memcnt, (unsigned long)risc->dma); + } + pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); + memset(risc,0,sizeof(*risc)); +} + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size) +{ + __le32 *cpu; + dma_addr_t dma = 0; + + if (NULL != risc->cpu && risc->size < size) + btcx_riscmem_free(pci,risc); + if (NULL == risc->cpu) { + cpu = pci_alloc_consistent(pci, size, &dma); + if (NULL == cpu) + return -ENOMEM; + risc->cpu = cpu; + risc->dma = dma; + risc->size = size; + if (btcx_debug) { + memcnt++; + printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n", + memcnt, (unsigned long)dma, cpu, size); + } + } + memset(risc->cpu,0,risc->size); + return 0; +} + +/* ---------------------------------------------------------- */ +/* screen overlay helpers */ + +int +btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n) +{ + if (win->left < 0) { + /* left */ + clips[n].c.left = 0; + clips[n].c.top = 0; + clips[n].c.width = -win->left; + clips[n].c.height = win->height; + n++; + } + if (win->left + win->width > swidth) { + /* right */ + clips[n].c.left = swidth - win->left; + clips[n].c.top = 0; + clips[n].c.width = win->width - clips[n].c.left; + clips[n].c.height = win->height; + n++; + } + if (win->top < 0) { + /* top */ + clips[n].c.left = 0; + clips[n].c.top = 0; + clips[n].c.width = win->width; + clips[n].c.height = -win->top; + n++; + } + if (win->top + win->height > sheight) { + /* bottom */ + clips[n].c.left = 0; + clips[n].c.top = sheight - win->top; + clips[n].c.width = win->width; + clips[n].c.height = win->height - clips[n].c.top; + n++; + } + return n; +} + +int +btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask) +{ + s32 nx,nw,dx; + unsigned int i; + + /* fixup window */ + nx = (win->left + mask) & ~mask; + nw = (win->width) & ~mask; + if (nx + nw > win->left + win->width) + nw -= mask+1; + dx = nx - win->left; + win->left = nx; + win->width = nw; + if (btcx_debug) + printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n", + win->width, win->height, win->left, win->top, dx); + + /* fixup clips */ + for (i = 0; i < n; i++) { + nx = (clips[i].c.left-dx) & ~mask; + nw = (clips[i].c.width) & ~mask; + if (nx + nw < clips[i].c.left-dx + clips[i].c.width) + nw += mask+1; + clips[i].c.left = nx; + clips[i].c.width = nw; + if (btcx_debug) + printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n", + clips[i].c.width, clips[i].c.height, + clips[i].c.left, clips[i].c.top); + } + return 0; +} + +void +btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips) +{ + struct v4l2_clip swap; + int i,j,n; + + if (nclips < 2) + return; + for (i = nclips-2; i >= 0; i--) { + for (n = 0, j = 0; j <= i; j++) { + if (clips[j].c.left > clips[j+1].c.left) { + swap = clips[j]; + clips[j] = clips[j+1]; + clips[j+1] = swap; + n++; + } + } + if (0 == n) + break; + } +} + +void +btcx_calc_skips(int line, int width, int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips) +{ + unsigned int clip,skip; + int end, maxline; + + skip=0; + maxline = 9999; + for (clip = 0; clip < nclips; clip++) { + + /* sanity checks */ + if (clips[clip].c.left + clips[clip].c.width <= 0) + continue; + if (clips[clip].c.left > (signed)width) + break; + + /* vertical range */ + if (line > clips[clip].c.top+clips[clip].c.height-1) + continue; + if (line < clips[clip].c.top) { + if (maxline > clips[clip].c.top-1) + maxline = clips[clip].c.top-1; + continue; + } + if (maxline > clips[clip].c.top+clips[clip].c.height-1) + maxline = clips[clip].c.top+clips[clip].c.height-1; + + /* horizontal range */ + if (0 == skip || clips[clip].c.left > skips[skip-1].end) { + /* new one */ + skips[skip].start = clips[clip].c.left; + if (skips[skip].start < 0) + skips[skip].start = 0; + skips[skip].end = clips[clip].c.left + clips[clip].c.width; + if (skips[skip].end > width) + skips[skip].end = width; + skip++; + } else { + /* overlaps -- expand last one */ + end = clips[clip].c.left + clips[clip].c.width; + if (skips[skip-1].end < end) + skips[skip-1].end = end; + if (skips[skip-1].end > width) + skips[skip-1].end = width; + } + } + *nskips = skip; + *maxy = maxline; + + if (btcx_debug) { + printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline); + for (skip = 0; skip < *nskips; skip++) { + printk(" %d-%d",skips[skip].start,skips[skip].end); + } + printk("\n"); + } +} diff --git a/drivers/media/pci/bt8xx/btcx-risc.h b/drivers/media/pci/bt8xx/btcx-risc.h new file mode 100644 index 000000000000..1ed7a000160a --- /dev/null +++ b/drivers/media/pci/bt8xx/btcx-risc.h @@ -0,0 +1,26 @@ +struct btcx_riscmem { + unsigned int size; + __le32 *cpu; + __le32 *jmp; + dma_addr_t dma; +}; + +struct btcx_skiplist { + int start; + int end; +}; + +int btcx_riscmem_alloc(struct pci_dev *pci, + struct btcx_riscmem *risc, + unsigned int size); +void btcx_riscmem_free(struct pci_dev *pci, + struct btcx_riscmem *risc); + +int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, + struct v4l2_clip *clips, unsigned int n); +int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, + unsigned int n, int mask); +void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); +void btcx_calc_skips(int line, int width, int *maxy, + struct btcx_skiplist *skips, unsigned int *nskips, + const struct v4l2_clip *clips, unsigned int nclips); -- cgit v1.2.3 From 8d8e6d6005de1f2421b7846bfb50782b09cd63a7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:57 -0300 Subject: [media] cx28521: drop videobuf abuse in cx25821-alsa The alsa driver uses videobuf low-level functions that are not available in vb2, so replace them by driver-specific functions. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/cx25821-alsa.c | 107 ++++++++++++++++++++++++++----- 1 file changed, 90 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 27e6493622b6..24f964bcc53a 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -64,7 +64,10 @@ static int devno; struct cx25821_audio_buffer { unsigned int bpl; struct cx25821_riscmem risc; - struct videobuf_dmabuf dma; + void *vaddr; + struct scatterlist *sglist; + int sglen; + int nr_pages; }; struct cx25821_audio_dev { @@ -87,8 +90,6 @@ struct cx25821_audio_dev { unsigned int period_size; unsigned int num_periods; - struct videobuf_dmabuf *dma_risc; - struct cx25821_audio_buffer *buf; struct snd_pcm_substream *substream; @@ -142,6 +143,83 @@ MODULE_PARM_DESC(debug, "enable debug messages"); #define PCI_MSK_AUD_EXT (1 << 4) #define PCI_MSK_AUD_INT (1 << 3) + +static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip, int nr_pages) +{ + struct cx25821_audio_buffer *buf = chip->buf; + struct page *pg; + int i; + + buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); + if (NULL == buf->vaddr) { + dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); + return -ENOMEM; + } + + dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", + (unsigned long)buf->vaddr, + nr_pages << PAGE_SHIFT); + + memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); + buf->nr_pages = nr_pages; + + buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); + if (NULL == buf->sglist) + goto vzalloc_err; + + sg_init_table(buf->sglist, buf->nr_pages); + for (i = 0; i < buf->nr_pages; i++) { + pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); + if (NULL == pg) + goto vmalloc_to_page_err; + sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); + } + return 0; + +vmalloc_to_page_err: + vfree(buf->sglist); + buf->sglist = NULL; +vzalloc_err: + vfree(buf->vaddr); + buf->vaddr = NULL; + return -ENOMEM; +} + +static int cx25821_alsa_dma_map(struct cx25821_audio_dev *dev) +{ + struct cx25821_audio_buffer *buf = dev->buf; + + buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist, + buf->nr_pages, PCI_DMA_FROMDEVICE); + + if (0 == buf->sglen) { + pr_warn("%s: cx25821_alsa_map_sg failed\n", __func__); + return -ENOMEM; + } + return 0; +} + +static int cx25821_alsa_dma_unmap(struct cx25821_audio_dev *dev) +{ + struct cx25821_audio_buffer *buf = dev->buf; + + if (!buf->sglen) + return 0; + + dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE); + buf->sglen = 0; + return 0; +} + +static int cx25821_alsa_dma_free(struct cx25821_audio_buffer *buf) +{ + vfree(buf->sglist); + buf->sglist = NULL; + vfree(buf->vaddr); + buf->vaddr = NULL; + return 0; +} + /* * BOARD Specific: Sets audio DMA */ @@ -335,12 +413,12 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip) BUG_ON(!chip->dma_size); dprintk(2, "Freeing buffer\n"); - videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); - videobuf_dma_free(chip->dma_risc); + cx25821_alsa_dma_unmap(chip); + cx25821_alsa_dma_free(chip->buf); pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma); kfree(chip->buf); - chip->dma_risc = NULL; + chip->buf = NULL; chip->dma_size = 0; return 0; @@ -432,8 +510,6 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); - struct videobuf_dmabuf *dma; - struct cx25821_audio_buffer *buf; int ret; @@ -457,19 +533,18 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, chip->period_size = AUDIO_LINE_SIZE; buf->bpl = chip->period_size; + chip->buf = buf; - dma = &buf->dma; - videobuf_dma_init(dma); - ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, + ret = cx25821_alsa_dma_init(chip, (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); if (ret < 0) goto error; - ret = videobuf_dma_map(&chip->pci->dev, dma); + ret = cx25821_alsa_dma_map(chip); if (ret < 0) goto error; - ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, + ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, buf->sglist, chip->period_size, chip->num_periods, 1); if (ret < 0) { pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); @@ -481,16 +556,14 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - chip->buf = buf; - chip->dma_risc = dma; - - substream->runtime->dma_area = chip->dma_risc->vaddr; + substream->runtime->dma_area = chip->buf->vaddr; substream->runtime->dma_bytes = chip->dma_size; substream->runtime->dma_addr = 0; return 0; error: + chip->buf = NULL; kfree(buf); return ret; } -- cgit v1.2.3 From b671ae6bdc1ad77a63536c6f74940976b9b89322 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:58 -0300 Subject: [media] cx25821: convert to vb2 This patch converts the cx25821 driver from the old videobuf framework to the new vb2 framework. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/Kconfig | 2 +- drivers/media/pci/cx25821/cx25821-core.c | 76 ++-- drivers/media/pci/cx25821/cx25821-video.c | 682 ++++++++---------------------- drivers/media/pci/cx25821/cx25821.h | 24 +- 4 files changed, 207 insertions(+), 577 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 0e69cabb006f..1755d3d2feaa 100644 --- a/drivers/media/pci/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig @@ -2,7 +2,7 @@ config VIDEO_CX25821 tristate "Conexant cx25821 support" depends on VIDEO_DEV && PCI && I2C select I2C_ALGOBIT - select VIDEOBUF_DMA_SG + select VIDEOBUF2_DMA_SG ---help--- This is a video4linux driver for Conexant 25821 based TV cards. diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index c8c65b793581..c1ea24e951f3 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -874,10 +874,9 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) if (dev->pci->device != 0x8210) { pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", __func__, dev->pci->device); - return -1; - } else { - pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device); + return -ENODEV; } + pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device); /* Apply a sensible clock frequency for the PCIe bridge */ dev->clk_freq = 28000000; @@ -1003,11 +1002,17 @@ EXPORT_SYMBOL(cx25821_riscmem_alloc); static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, - unsigned int lines) + unsigned int lines, bool jump) { struct scatterlist *sg; unsigned int line, todo; + if (jump) { + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(0); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + } + /* sync instruction */ if (sync_line != NO_SYNC_LINE) *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); @@ -1073,13 +1078,13 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc, fields++; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Padding + one write per scan line + syncs + jump (all 3 dwords). Padding can cause next bpl to start close to a page border. First DMA region may be smaller than PAGE_SIZE */ /* write and jump need and extra dword */ instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); - instructions += 2; + instructions += 5; rc = cx25821_riscmem_alloc(pci, risc, instructions * 12); if (rc < 0) @@ -1090,17 +1095,17 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc, if (UNSET != top_offset) { rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, - lines); + lines, true); } if (UNSET != bottom_offset) { rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, - padding, lines); + padding, lines, UNSET == top_offset); } /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + BUG_ON((risc->jmp - risc->cpu + 3) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -1200,41 +1205,14 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, } EXPORT_SYMBOL(cx25821_risc_databuffer_audio); -int cx25821_risc_stopper(struct pci_dev *pci, struct cx25821_riscmem *risc, - u32 reg, u32 mask, u32 value) +void cx25821_free_buffer(struct cx25821_dev *dev, struct cx25821_buffer *buf) { - __le32 *rp; - int rc; - - rc = cx25821_riscmem_alloc(pci, risc, 4 * 16); - - if (rc < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - - *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); - *(rp++) = cpu_to_le32(reg); - *(rp++) = cpu_to_le32(value); - *(rp++) = cpu_to_le32(mask); - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc->dma); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - return 0; -} - -void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) -{ - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); - BUG_ON(in_interrupt()); - videobuf_waiton(q, &buf->vb, 0, 0); - videobuf_dma_unmap(q->dev, dma); - videobuf_dma_free(dma); - pci_free_consistent(to_pci_dev(q->dev), + if (WARN_ON(buf->risc.size == 0)) + return; + pci_free_consistent(dev->pci, buf->risc.size, buf->risc.cpu, buf->risc.dma); - buf->vb.state = VIDEOBUF_NEEDS_INIT; + memset(&buf->risc, 0, sizeof(buf->risc)); } static irqreturn_t cx25821_irq(int irq, void *dev_id) @@ -1319,14 +1297,15 @@ static int cx25821_initdev(struct pci_dev *pci_dev, goto fail_unregister_device; } + dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev); + if (IS_ERR(dev->alloc_ctx)) { + err = PTR_ERR(dev->alloc_ctx); + goto fail_unregister_pci; + } err = cx25821_dev_setup(dev); - if (err) { - if (err == -EBUSY) - goto fail_unregister_device; - else - goto fail_unregister_pci; - } + if (err) + goto fail_free_ctx; /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); @@ -1356,6 +1335,8 @@ fail_irq: pr_info("cx25821_initdev() can't get IRQ !\n"); cx25821_dev_unregister(dev); +fail_free_ctx: + vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); fail_unregister_pci: pci_disable_device(pci_dev); fail_unregister_device: @@ -1379,6 +1360,7 @@ static void cx25821_finidev(struct pci_dev *pci_dev) free_irq(pci_dev->irq, dev); cx25821_dev_unregister(dev); + vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); v4l2_device_unregister(v4l2_dev); kfree(dev); } diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 3eda1a1e1e25..3497946c72ea 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Conexant Systems Inc. * Authors , - * Based on Steven Toth cx23885 driver + * Based on Steven Toth cx25821 driver * Parts adapted/taken from Eduardo Moscoso Rubino * Copyright (C) 2009 Eduardo Moscoso Rubino * @@ -46,10 +46,6 @@ static unsigned int irq_debug; module_param(irq_debug, int, 0644); MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); -static unsigned int vid_limit = 16; -module_param(vid_limit, int, 0644); -MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); - #define FORMAT_FLAGS_PACKED 0x01 static const struct cx25821_fmt formats[] = { @@ -76,41 +72,6 @@ static const struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) return NULL; } -void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, - u32 count) -{ - struct cx25821_buffer *buf; - int bc; - - for (bc = 0;; bc++) { - if (list_empty(&q->active)) { - dprintk(1, "bc=%d (=0: active empty)\n", bc); - break; - } - - buf = list_entry(q->active.next, struct cx25821_buffer, - vb.queue); - - /* count comes from the hw and it is 16bit wide -- - * this trick handles wrap-arounds correctly for - * up to 32767 buffers in flight... */ - if ((s16) (count - buf->count) < 0) - break; - - v4l2_get_timestamp(&buf->vb.ts); - buf->vb.state = VIDEOBUF_DONE; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - } - - if (list_empty(&q->active)) - del_timer(&q->timeout); - else - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - if (bc != 1) - pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); -} - int cx25821_start_video_dma(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, struct cx25821_buffer *buf, @@ -123,7 +84,6 @@ int cx25821_start_video_dma(struct cx25821_dev *dev, /* reset counter */ cx_write(channel->gpcnt_ctl, 3); - q->count = 1; /* enable irq */ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i)); @@ -139,86 +99,8 @@ int cx25821_start_video_dma(struct cx25821_dev *dev, return 0; } -static int cx25821_restart_video_queue(struct cx25821_dev *dev, - struct cx25821_dmaqueue *q, - const struct sram_channel *channel) -{ - struct cx25821_buffer *buf, *prev; - struct list_head *item; - - if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, - vb.queue); - - cx25821_start_video_dma(dev, q, buf, channel); - - list_for_each(item, &q->active) { - buf = list_entry(item, struct cx25821_buffer, vb.queue); - buf->count = q->count++; - } - - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - return 0; - } - - prev = NULL; - for (;;) { - if (list_empty(&q->queued)) - return 0; - - buf = list_entry(q->queued.next, struct cx25821_buffer, - vb.queue); - - if (NULL == prev) { - list_move_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, channel); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_move_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ - } else { - return 0; - } - prev = buf; - } -} - -static void cx25821_vid_timeout(unsigned long data) -{ - struct cx25821_data *timeout_data = (struct cx25821_data *)data; - struct cx25821_dev *dev = timeout_data->dev; - const struct sram_channel *channel = timeout_data->channel; - struct cx25821_dmaqueue *q = &dev->channels[channel->i].dma_vidq; - struct cx25821_buffer *buf; - unsigned long flags; - - /* cx25821_sram_channel_dump(dev, channel); */ - cx_clear(channel->dma_ctl, 0x11); - - spin_lock_irqsave(&dev->slock, flags); - while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, - vb.queue); - list_del(&buf->vb.queue); - - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - } - - cx25821_restart_video_queue(dev, q, channel); - spin_unlock_irqrestore(&dev->slock, flags); -} - int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) { - u32 count = 0; int handled = 0; u32 mask; const struct sram_channel *channel = dev->channels[chan_num].sram_channels; @@ -239,317 +121,197 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) /* risc1 y */ if (status & FLD_VID_DST_RISC1) { - spin_lock(&dev->slock); - count = cx_read(channel->gpcnt); - cx25821_video_wakeup(dev, &dev->channels[channel->i].dma_vidq, - count); - spin_unlock(&dev->slock); - handled++; - } + struct cx25821_dmaqueue *dmaq = + &dev->channels[channel->i].dma_vidq; + struct cx25821_buffer *buf; - /* risc2 y */ - if (status & 0x10) { - dprintk(2, "stopper video\n"); spin_lock(&dev->slock); - cx25821_restart_video_queue(dev, - &dev->channels[channel->i].dma_vidq, channel); + if (!list_empty(&dmaq->active)) { + buf = list_entry(dmaq->active.next, + struct cx25821_buffer, queue); + + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + buf->vb.v4l2_buf.sequence = dmaq->count++; + list_del(&buf->queue); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + } spin_unlock(&dev->slock); handled++; } return handled; } -static int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) +static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) { - struct cx25821_channel *chan = q->priv_data; - - *size = chan->fmt->depth * chan->width * chan->height >> 3; - - if (0 == *count) - *count = 32; - - if (*size * *count > vid_limit * 1024 * 1024) - *count = (vid_limit * 1024 * 1024) / *size; + struct cx25821_channel *chan = q->drv_priv; + *num_planes = 1; + sizes[0] = (chan->fmt->depth * chan->width * chan->height) >> 3; + alloc_ctxs[0] = chan->dev->alloc_ctx; return 0; } -static int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) +static int cx25821_buffer_prepare(struct vb2_buffer *vb) { - struct cx25821_channel *chan = q->priv_data; + struct cx25821_channel *chan = vb->vb2_queue->drv_priv; struct cx25821_dev *dev = chan->dev; struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - int rc, init_buffer = 0; + struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); u32 line0_offset; - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int bpl_local = LINE_SIZE_D1; + int ret; - BUG_ON(NULL == chan->fmt); - if (chan->width < 48 || chan->width > 720 || - chan->height < 32 || chan->height > 576) - return -EINVAL; - - buf->vb.size = (chan->width * chan->height * chan->fmt->depth) >> 3; + if (chan->pixel_formats == PIXEL_FRMT_411) + buf->bpl = (chan->fmt->depth * chan->width) >> 3; + else + buf->bpl = (chan->fmt->depth >> 3) * chan->width; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (vb2_plane_size(vb, 0) < chan->height * buf->bpl) return -EINVAL; + vb2_set_plane_payload(vb, 0, chan->height * buf->bpl); + buf->vb.v4l2_buf.field = chan->field; - if (buf->fmt != chan->fmt || - buf->vb.width != chan->width || - buf->vb.height != chan->height || buf->vb.field != field) { - buf->fmt = chan->fmt; - buf->vb.width = chan->width; - buf->vb.height = chan->height; - buf->vb.field = field; - init_buffer = 1; - } + if (chan->pixel_formats == PIXEL_FRMT_411) { + bpl_local = buf->bpl; + } else { + bpl_local = buf->bpl; /* Default */ - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - init_buffer = 1; - rc = videobuf_iolock(q, &buf->vb, NULL); - if (0 != rc) { - printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n")); - goto fail; + if (chan->use_cif_resolution) { + if (dev->tvnorm & V4L2_STD_625_50) + bpl_local = 352 << 1; + else + bpl_local = chan->cif_width << 1; } } - dprintk(1, "init_buffer=%d\n", init_buffer); - - if (init_buffer) { - if (chan->pixel_formats == PIXEL_FRMT_411) - buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; - else - buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); - - if (chan->pixel_formats == PIXEL_FRMT_411) { - bpl_local = buf->bpl; - } else { - bpl_local = buf->bpl; /* Default */ - - if (chan->use_cif_resolution) { - if (dev->tvnorm & V4L2_STD_625_50) - bpl_local = 352 << 1; - else - bpl_local = chan->cif_width << 1; - } - } - - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, 0, UNSET, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_BOTTOM: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, UNSET, 0, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_INTERLACED: - /* All other formats are top field first */ - line0_offset = 0; - dprintk(1, "top field first\n"); - - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, line0_offset, - bpl_local, bpl_local, bpl_local, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_TB: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - 0, buf->bpl * (buf->vb.height >> 1), - buf->bpl, 0, buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_BT: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - buf->bpl * (buf->vb.height >> 1), 0, - buf->bpl, 0, buf->vb.height >> 1); - break; - default: - BUG(); - } + switch (chan->field) { + case V4L2_FIELD_TOP: + ret = cx25821_risc_buffer(dev->pci, &buf->risc, + sgt->sgl, 0, UNSET, + buf->bpl, 0, chan->height); + break; + case V4L2_FIELD_BOTTOM: + ret = cx25821_risc_buffer(dev->pci, &buf->risc, + sgt->sgl, UNSET, 0, + buf->bpl, 0, chan->height); + break; + case V4L2_FIELD_INTERLACED: + /* All other formats are top field first */ + line0_offset = 0; + dprintk(1, "top field first\n"); + + ret = cx25821_risc_buffer(dev->pci, &buf->risc, + sgt->sgl, line0_offset, + bpl_local, bpl_local, bpl_local, + chan->height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + ret = cx25821_risc_buffer(dev->pci, &buf->risc, + sgt->sgl, + 0, buf->bpl * (chan->height >> 1), + buf->bpl, 0, chan->height >> 1); + break; + case V4L2_FIELD_SEQ_BT: + ret = cx25821_risc_buffer(dev->pci, &buf->risc, + sgt->sgl, + buf->bpl * (chan->height >> 1), 0, + buf->bpl, 0, chan->height >> 1); + break; + default: + WARN_ON(1); + ret = -EINVAL; + break; } dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.i, chan->width, chan->height, chan->fmt->depth, - chan->fmt->name, (unsigned long)buf->risc.dma); - - buf->vb.state = VIDEOBUF_PREPARED; - - return 0; + buf, buf->vb.v4l2_buf.index, chan->width, chan->height, + chan->fmt->depth, chan->fmt->name, + (unsigned long)buf->risc.dma); -fail: - cx25821_free_buffer(q, buf); - return rc; + return ret; } -static void cx25821_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void cx25821_buffer_finish(struct vb2_buffer *vb) { struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_channel *chan = vb->vb2_queue->drv_priv; + struct cx25821_dev *dev = chan->dev; - cx25821_free_buffer(q, buf); -} - -static int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct cx25821_channel *chan = video_drvdata(file); - - return videobuf_mmap_mapper(&chan->vidq, vma); + cx25821_free_buffer(dev, buf); } - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static void cx25821_buffer_queue(struct vb2_buffer *vb) { struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_channel *chan = vq->priv_data; + struct cx25821_channel *chan = vb->vb2_queue->drv_priv; struct cx25821_dev *dev = chan->dev; + struct cx25821_buffer *prev; struct cx25821_dmaqueue *q = &dev->channels[chan->id].dma_vidq; - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, chan->sram_channels); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); + buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 12); + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 12); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + if (list_empty(&q->active)) { + list_add_tail(&buf->queue, &q->active); } else { + buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); prev = list_entry(q->active.prev, struct cx25821_buffer, - vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } + queue); + list_add_tail(&buf->queue, &q->active); + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); } - - if (list_empty(&q->active)) - dprintk(2, "active queue empty!\n"); } -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t *ppos) +static int cx25821_start_streaming(struct vb2_queue *q, unsigned int count) { - struct v4l2_fh *fh = file->private_data; - struct cx25821_channel *chan = video_drvdata(file); + struct cx25821_channel *chan = q->drv_priv; struct cx25821_dev *dev = chan->dev; - int err = 0; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - if (chan->streaming_fh && chan->streaming_fh != fh) { - err = -EBUSY; - goto unlock; - } - chan->streaming_fh = fh; + struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq; + struct cx25821_buffer *buf = list_entry(dmaq->active.next, + struct cx25821_buffer, queue); - err = videobuf_read_one(&chan->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); -unlock: - mutex_unlock(&dev->lock); - return err; -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_channel *chan = video_drvdata(file); - unsigned long req_events = poll_requested_events(wait); - unsigned int res = v4l2_ctrl_poll(file, wait); - - if (req_events & (POLLIN | POLLRDNORM)) - res |= videobuf_poll_stream(file, &chan->vidq, wait); - return res; - - /* This doesn't belong in poll(). This can be done - * much better with vb2. We keep this code here as a - * reminder. - if ((res & POLLIN) && buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = chan->dev; - - if (dev && chan->use_cif_resolution) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (chan->width * 2), - (chan->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - */ + dmaq->count = 0; + cx25821_start_video_dma(dev, dmaq, buf, chan->sram_channels); + return 0; } -static int video_release(struct file *file) +static void cx25821_stop_streaming(struct vb2_queue *q) { - struct cx25821_channel *chan = video_drvdata(file); - struct v4l2_fh *fh = file->private_data; + struct cx25821_channel *chan = q->drv_priv; struct cx25821_dev *dev = chan->dev; - const struct sram_channel *sram_ch = - dev->channels[0].sram_channels; - - mutex_lock(&dev->lock); - /* stop the risc engine and fifo */ - cx_write(sram_ch->dma_ctl, 0); /* FIFO and RISC disable */ + struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq; + unsigned long flags; - /* stop video capture */ - if (chan->streaming_fh == fh) { - videobuf_queue_cancel(&chan->vidq); - chan->streaming_fh = NULL; - } + cx_write(chan->sram_channels->dma_ctl, 0); /* FIFO and RISC disable */ + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&dmaq->active)) { + struct cx25821_buffer *buf = list_entry(dmaq->active.next, + struct cx25821_buffer, queue); - if (chan->vidq.read_buf) { - cx25821_buffer_release(&chan->vidq, chan->vidq.read_buf); - kfree(chan->vidq.read_buf); + list_del(&buf->queue); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } - - videobuf_mmap_free(&chan->vidq); - mutex_unlock(&dev->lock); - - return v4l2_fh_release(file); + spin_unlock_irqrestore(&dev->slock, flags); } +static struct vb2_ops cx25821_video_qops = { + .queue_setup = cx25821_queue_setup, + .buf_prepare = cx25821_buffer_prepare, + .buf_finish = cx25821_buffer_finish, + .buf_queue = cx25821_buffer_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .start_streaming = cx25821_start_streaming, + .stop_streaming = cx25821_stop_streaming, +}; + /* VIDEO IOCTLS */ static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, @@ -571,7 +333,7 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = chan->width; f->fmt.pix.height = chan->height; - f->fmt.pix.field = chan->vidq.field; + f->fmt.pix.field = chan->field; f->fmt.pix.pixelformat = chan->fmt->fourcc; f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3; f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline; @@ -632,7 +394,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return err; chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); - chan->vidq.field = f->fmt.pix.field; + chan->field = f->fmt.pix.field; chan->width = f->fmt.pix.width; chan->height = f->fmt.pix.height; @@ -654,47 +416,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_channel *chan = video_drvdata(file); - - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (chan->streaming_fh && chan->streaming_fh != priv) - return -EBUSY; - chan->streaming_fh = priv; - - return videobuf_streamon(&chan->vidq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_channel *chan = video_drvdata(file); - - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (chan->streaming_fh && chan->streaming_fh != priv) - return -EBUSY; - if (chan->streaming_fh == NULL) - return 0; - - chan->streaming_fh = NULL; - return videobuf_streamoff(&chan->vidq); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_channel *chan = video_drvdata(file); - - ret_val = videobuf_dqbuf(&chan->vidq, p, file->f_flags & O_NONBLOCK); - p->sequence = chan->dma_vidq.count; - - return ret_val; -} - static int vidioc_log_status(struct file *file, void *priv) { struct cx25821_channel *chan = video_drvdata(file); @@ -729,29 +450,6 @@ static int cx25821_vidioc_querycap(struct file *file, void *priv, return 0; } -static int cx25821_vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct cx25821_channel *chan = video_drvdata(file); - - return videobuf_reqbufs(&chan->vidq, p); -} - -static int cx25821_vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct cx25821_channel *chan = video_drvdata(file); - - return videobuf_querybuf(&chan->vidq, p); -} - -static int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx25821_channel *chan = video_drvdata(file); - - return videobuf_qbuf(&chan->vidq, p); -} - static int cx25821_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorms) { struct cx25821_channel *chan = video_drvdata(file); @@ -880,7 +578,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, return err; chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); - chan->vidq.field = f->fmt.pix.field; + chan->field = f->fmt.pix.field; chan->width = f->fmt.pix.width; chan->height = f->fmt.pix.height; if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) @@ -890,52 +588,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, return 0; } -static ssize_t video_write(struct file *file, const char __user *data, size_t count, - loff_t *ppos) -{ - struct cx25821_channel *chan = video_drvdata(file); - struct cx25821_dev *dev = chan->dev; - struct v4l2_fh *fh = file->private_data; - int err = 0; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - if (chan->streaming_fh && chan->streaming_fh != fh) { - err = -EBUSY; - goto unlock; - } - if (!chan->streaming_fh) { - err = cx25821_vidupstream_init(chan, chan->pixel_formats); - if (err) - goto unlock; - chan->streaming_fh = fh; - } - - err = cx25821_write_frame(chan, data, count); - count -= err; - *ppos += err; - -unlock: - mutex_unlock(&dev->lock); - return err; -} - -static int video_out_release(struct file *file) -{ - struct cx25821_channel *chan = video_drvdata(file); - struct cx25821_dev *dev = chan->dev; - struct v4l2_fh *fh = file->private_data; - - mutex_lock(&dev->lock); - if (chan->streaming_fh == fh) { - cx25821_stop_upstream_video(chan); - chan->streaming_fh = NULL; - } - mutex_unlock(&dev->lock); - - return v4l2_fh_release(file); -} - static const struct v4l2_ctrl_ops cx25821_ctrl_ops = { .s_ctrl = cx25821_s_ctrl, }; @@ -943,11 +595,11 @@ static const struct v4l2_ctrl_ops cx25821_ctrl_ops = { static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -956,17 +608,18 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_std = cx25821_vidioc_g_std, .vidioc_s_std = cx25821_vidioc_s_std, .vidioc_enum_input = cx25821_vidioc_enum_input, .vidioc_g_input = cx25821_vidioc_g_input, .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, .vidioc_log_status = vidioc_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -984,9 +637,11 @@ static const struct video_device cx25821_video_device = { static const struct v4l2_file_operations video_out_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, - .write = video_write, - .release = video_out_release, + .release = vb2_fop_release, + .write = vb2_fop_write, + .poll = vb2_fop_poll, .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, }; static const struct v4l2_ioctl_ops video_out_ioctl_ops = { @@ -1017,13 +672,8 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) cx_clear(PCI_INT_MSK, 1); if (video_is_registered(&dev->channels[chan_num].vdev)) { - struct cx25821_riscmem *risc = - &dev->channels[chan_num].dma_vidq.stopper; - video_unregister_device(&dev->channels[chan_num].vdev); v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl); - - pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); } } @@ -1041,6 +691,7 @@ int cx25821_video_register(struct cx25821_dev *dev) struct cx25821_channel *chan = &dev->channels[i]; struct video_device *vdev = &chan->vdev; struct v4l2_ctrl_handler *hdl = &chan->hdl; + struct vb2_queue *q; bool is_output = i > SRAM_CH08; if (i == SRAM_CH08) /* audio channel */ @@ -1068,11 +719,9 @@ int cx25821_video_register(struct cx25821_dev *dev) chan->out->chan = chan; } - cx25821_risc_stopper(dev->pci, &chan->dma_vidq.stopper, - chan->sram_channels->dma_ctl, 0x11, 0); - chan->sram_channels = &cx25821_sram_channels[i]; chan->width = 720; + chan->field = V4L2_FIELD_INTERLACED; if (dev->tvnorm & V4L2_STD_625_50) chan->height = 576; else @@ -1086,19 +735,27 @@ int cx25821_video_register(struct cx25821_dev *dev) cx_write(chan->sram_channels->int_stat, 0xffffffff); INIT_LIST_HEAD(&chan->dma_vidq.active); - INIT_LIST_HEAD(&chan->dma_vidq.queued); - chan->timeout_data.dev = dev; - chan->timeout_data.channel = &cx25821_sram_channels[i]; - chan->dma_vidq.timeout.function = cx25821_vid_timeout; - chan->dma_vidq.timeout.data = (unsigned long)&chan->timeout_data; - init_timer(&chan->dma_vidq.timeout); + q = &chan->vidq; + + q->type = is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT : + V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->io_modes |= is_output ? VB2_WRITE : VB2_READ; + q->gfp_flags = GFP_DMA32; + q->min_buffers_needed = 2; + q->drv_priv = chan; + q->buf_struct_size = sizeof(struct cx25821_buffer); + q->ops = &cx25821_video_qops; + q->mem_ops = &vb2_dma_sg_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &dev->lock; - if (!is_output) - videobuf_queue_sg_init(&chan->vidq, &cx25821_video_qops, &dev->pci->dev, - &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), - chan, &dev->lock); + if (!is_output) { + err = vb2_queue_init(q); + if (err < 0) + goto fail_unreg; + } /* register v4l devices */ *vdev = is_output ? cx25821_video_out_device : cx25821_video_device; @@ -1108,6 +765,7 @@ int cx25821_video_register(struct cx25821_dev *dev) else vdev->vfl_dir = VFL_DIR_TX; vdev->lock = &dev->lock; + vdev->queue = q; snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i); video_set_drvdata(vdev, chan); diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 38beec2c0969..34c5ff136598 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "cx25821-reg.h" #include "cx25821-medusa-reg.h" @@ -120,13 +120,13 @@ struct cx25821_riscmem { /* buffer for one video frame */ struct cx25821_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; + struct vb2_buffer vb; + struct list_head queue; /* cx25821 specific */ unsigned int bpl; struct cx25821_riscmem risc; const struct cx25821_fmt *fmt; - u32 count; }; enum port { @@ -165,17 +165,9 @@ struct cx25821_i2c { struct cx25821_dmaqueue { struct list_head active; - struct list_head queued; - struct timer_list timeout; - struct cx25821_riscmem stopper; u32 count; }; -struct cx25821_data { - struct cx25821_dev *dev; - const struct sram_channel *channel; -}; - struct cx25821_dev; struct cx25821_channel; @@ -213,18 +205,17 @@ struct cx25821_video_out_data { struct cx25821_channel { unsigned id; struct cx25821_dev *dev; - struct v4l2_fh *streaming_fh; struct v4l2_ctrl_handler hdl; - struct cx25821_data timeout_data; struct video_device vdev; struct cx25821_dmaqueue dma_vidq; - struct videobuf_queue vidq; + struct vb2_queue vidq; const struct sram_channel *sram_channels; const struct cx25821_fmt *fmt; + unsigned field; unsigned int width, height; int pixel_formats; int use_cif_resolution; @@ -250,6 +241,7 @@ struct cx25821_dev { int hwrevision; /* used by cx25821-alsa */ struct snd_card *card; + void *alloc_ctx; u32 clk_freq; @@ -425,10 +417,8 @@ extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, struct scatterlist *sglist, unsigned int bpl, unsigned int lines, unsigned int lpi); -extern void cx25821_free_buffer(struct videobuf_queue *q, +extern void cx25821_free_buffer(struct cx25821_dev *dev, struct cx25821_buffer *buf); -extern int cx25821_risc_stopper(struct pci_dev *pci, struct cx25821_riscmem *risc, - u32 reg, u32 mask, u32 value); extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, const struct sram_channel *ch); extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, -- cgit v1.2.3 From 11c8a2df2cf8c213e1970d548aee067887971ef8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:27:59 -0300 Subject: [media] cx25821: add create_bufs support Add support for the VIDIOC_CREATE_BUFS ioctl. This was missing in this driver and in vb2 it's trivial to add. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/cx25821-video.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 3497946c72ea..827c3c036ba3 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -146,9 +146,13 @@ static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fm unsigned int sizes[], void *alloc_ctxs[]) { struct cx25821_channel *chan = q->drv_priv; + unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3; + + if (fmt && fmt->fmt.pix.sizeimage < size) + return -EINVAL; *num_planes = 1; - sizes[0] = (chan->fmt->depth * chan->width * chan->height) >> 3; + sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size; alloc_ctxs[0] = chan->dev->alloc_ctx; return 0; } @@ -610,6 +614,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_reqbufs = vb2_ioctl_reqbufs, .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, -- cgit v1.2.3 From b6f21dc3541a3660acfec1e789a011e6d4154173 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Dec 2014 10:28:00 -0300 Subject: [media] cx25821: remove video output support The video output functionality never worked for this driver. Now remove the creation of the output video nodes as well to prevent users from thinking that video output is available, when it isn't. To correctly implement this the video output should use vb2 as well, and that requires rewriting the output DMA setup. But without hardware to test I am not able to do that. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/Makefile | 2 +- drivers/media/pci/cx25821/cx25821-core.c | 6 +++++- drivers/media/pci/cx25821/cx25821-video.c | 2 +- drivers/media/pci/cx25821/cx25821.h | 7 +++++++ 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index 5872feb266a6..c8f8598a2b86 100644 --- a/drivers/media/pci/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile @@ -1,6 +1,6 @@ cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ cx25821-gpio.o cx25821-medusa-video.o \ - cx25821-video.o cx25821-video-upstream.o + cx25821-video.o obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index c1ea24e951f3..559f8293c53a 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -965,11 +965,15 @@ void cx25821_dev_unregister(struct cx25821_dev *dev) release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); - for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; i++) { + for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; i++) { if (i == SRAM_CH08) /* audio channel */ continue; + /* + * TODO: enable when video output is properly + * supported. if (i == SRAM_CH09 || i == SRAM_CH10) cx25821_free_mem_upstream(&dev->channels[i]); + */ cx25821_video_unregister(dev, i); } diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 827c3c036ba3..7bc495e4ece2 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -692,7 +692,7 @@ int cx25821_video_register(struct cx25821_dev *dev) spin_lock_init(&dev->slock); - for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) { + for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; ++i) { struct cx25821_channel *chan = &dev->channels[i]; struct video_device *vdev = &chan->vdev; struct v4l2_ctrl_handler *hdl = &chan->hdl; diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 34c5ff136598..d81a08a2df4f 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -88,6 +88,13 @@ #define CX25821_BOARD_CONEXANT_ATHENA10 1 #define MAX_VID_CHANNEL_NUM 12 + +/* + * Maximum capture-only channels. This can go away once video/audio output + * is fully supported in this driver. + */ +#define MAX_VID_CAP_CHANNEL_NUM 10 + #define VID_CHANNEL_NUM 8 struct cx25821_fmt { -- cgit v1.2.3 From e476f4e15d859d1112872667983918bdfa4e663b Mon Sep 17 00:00:00 2001 From: Andrey Utkin Date: Wed, 5 Nov 2014 17:11:14 -0300 Subject: [media] solo6x10: just pass frame motion flag from hardware, drop additional handling as complicated and unstable Dropping code (introduced in 316d9e84a72069e04e483de0d5934c1d75f6a44c) which intends to make raising of motion events more "smooth"(?). It made motion event never appear in my installation. That code is complicated, so I couldn't figure out quickly how to fix it, so dropping it seems better to me. Another justification is that anyway application would implement "motion signal stabilization" if required, it is not necessarily kernel driver's job. Signed-off-by: Andrey Utkin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c | 30 +------------------------- drivers/media/pci/solo6x10/solo6x10.h | 2 -- 2 files changed, 1 insertion(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 6e933d383fa2..1c9688f58c5c 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -239,8 +239,6 @@ static int solo_enc_on(struct solo_enc_dev *solo_enc) if (solo_enc->bw_weight > solo_dev->enc_bw_remain) return -EBUSY; solo_enc->sequence = 0; - solo_enc->motion_last_state = false; - solo_enc->frames_since_last_motion = 0; solo_dev->enc_bw_remain -= solo_enc->bw_weight; if (solo_enc->type == SOLO_ENC_TYPE_EXT) @@ -529,36 +527,12 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, } if (!ret) { - bool send_event = false; - vb->v4l2_buf.sequence = solo_enc->sequence++; vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh); vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh); /* Check for motion flags */ - if (solo_is_motion_on(solo_enc)) { - /* It takes a few frames for the hardware to detect - * motion. Once it does it clears the motion detection - * register and it takes again a few frames before - * motion is seen. This means in practice that when the - * motion field is 1, it will go back to 0 for the next - * frame. This leads to motion detection event being - * sent all the time, which is not what we want. - * Instead wait a few frames before deciding that the - * motion has halted. After some experimentation it - * turns out that waiting for 5 frames works well. - */ - if (enc_buf->motion == 0 && - solo_enc->motion_last_state && - solo_enc->frames_since_last_motion++ > 5) - send_event = true; - else if (enc_buf->motion) { - solo_enc->frames_since_last_motion = 0; - send_event = !solo_enc->motion_last_state; - } - } - - if (send_event) { + if (solo_is_motion_on(solo_enc) && enc_buf->motion) { struct v4l2_event ev = { .type = V4L2_EVENT_MOTION_DET, .u.motion_det = { @@ -568,8 +542,6 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, }, }; - solo_enc->motion_last_state = enc_buf->motion; - solo_enc->frames_since_last_motion = 0; v4l2_event_queue(solo_enc->vfd, &ev); } } diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h index bd8edfa319b8..6c9bc707773f 100644 --- a/drivers/media/pci/solo6x10/solo6x10.h +++ b/drivers/media/pci/solo6x10/solo6x10.h @@ -159,8 +159,6 @@ struct solo_enc_dev { u16 motion_thresh; bool motion_global; bool motion_enabled; - bool motion_last_state; - u8 frames_since_last_motion; u16 width; u16 height; -- cgit v1.2.3 From 21a7e0596a63abdf12a9591c29359f7f15e18c16 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Dec 2014 10:10:43 -0300 Subject: [media] media: drivers shouldn't touch debug field in video_device The debug field in struct video_device is for internal use only and drivers should mix that with their own debug module options. It is handled by the V4L2 core and users can set it using /sys/class/video4linux//debug. It has been deprecated for some time now, so it is time to remove it completely from the drivers. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 1 - drivers/media/pci/cx88/cx88-blackbird.c | 3 --- drivers/media/platform/marvell-ccic/mcam-core.c | 1 - drivers/media/usb/cx231xx/cx231xx-video.c | 1 - drivers/media/usb/em28xx/em28xx-video.c | 1 - drivers/media/usb/stk1160/stk1160-v4l.c | 5 ----- drivers/media/usb/stkwebcam/stk-webcam.c | 1 - drivers/media/usb/tm6000/tm6000-video.c | 3 +-- drivers/media/usb/zr364xx/zr364xx.c | 2 -- drivers/staging/media/tlg2300/pd-common.h | 1 - drivers/staging/media/tlg2300/pd-radio.c | 3 --- drivers/staging/media/tlg2300/pd-video.c | 10 ---------- 12 files changed, 1 insertion(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 665e46dafe68..6eed8f75c13c 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3884,7 +3884,6 @@ static struct video_device *vdev_init(struct bttv *btv, *vfd = *template; vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release; - vfd->debug = bttv_debug; video_set_drvdata(vfd, btv); snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index d3c79d964f2c..b6be46e94289 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -1234,6 +1234,3 @@ static void __exit blackbird_fini(void) module_init(blackbird_init); module_exit(blackbird_fini); - -module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644); -MODULE_PARM_DESC(debug,"enable debug messages [video]"); diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 193373ff268d..dd5b1415f974 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -1913,7 +1913,6 @@ int mccic_register(struct mcam_camera *cam) mutex_lock(&cam->s_mutex); cam->vdev = mcam_v4l_template; - cam->vdev.debug = 0; cam->vdev.v4l2_dev = &cam->v4l2_dev; video_set_drvdata(&cam->vdev, cam); ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 53ca12c1ff69..ecea76fe07f6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -2062,7 +2062,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, *vfd = *template; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; - vfd->debug = video_debug; vfd->lock = &dev->lock; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index cf7f58b76292..3691b39424be 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2192,7 +2192,6 @@ static struct video_device *vfd = *template; vfd->v4l2_dev = &dev->v4l2->v4l2_dev; - vfd->debug = video_debug; vfd->lock = &dev->lock; if (dev->board.is_webcam) vfd->tvnorms = 0; diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index a47629108c1b..65a326c5128f 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -38,10 +38,6 @@ #include "stk1160.h" #include "stk1160-reg.h" -static unsigned int vidioc_debug; -module_param(vidioc_debug, int, 0644); -MODULE_PARM_DESC(vidioc_debug, "enable debug messages [vidioc]"); - static bool keep_buffers; module_param(keep_buffers, bool, 0644); MODULE_PARM_DESC(keep_buffers, "don't release buffers upon stop streaming"); @@ -659,7 +655,6 @@ int stk1160_video_register(struct stk1160 *dev) /* Initialize video_device with a template structure */ dev->vdev = v4l_template; - dev->vdev.debug = vidioc_debug; dev->vdev.queue = &dev->vb_vidq; /* diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 3588dc38db87..e08fa587332f 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -1262,7 +1262,6 @@ static int stk_register_video_device(struct stk_camera *dev) dev->vdev = stk_v4l_data; dev->vdev.lock = &dev->lock; - dev->vdev.debug = debug; dev->vdev.v4l2_dev = &dev->v4l2_dev; video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 793577fc4633..0f14d3ccc7b4 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -941,7 +941,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (NULL == fmt) { - dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)" + dprintk(dev, 2, "Fourcc format (0x%08x)" " invalid.\n", f->fmt.pix.pixelformat); return -EINVAL; } @@ -1622,7 +1622,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev, *vfd = *template; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; - vfd->debug = tm6000_debug; vfd->lock = &dev->lock; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 5c006277b8b1..ca850316d379 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -1454,8 +1454,6 @@ static int zr364xx_probe(struct usb_interface *intf, cam->vdev.v4l2_dev = &cam->v4l2_dev; cam->vdev.ctrl_handler = &cam->ctrl_handler; video_set_drvdata(&cam->vdev, cam); - if (debug) - cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; cam->udev = udev; diff --git a/drivers/staging/media/tlg2300/pd-common.h b/drivers/staging/media/tlg2300/pd-common.h index 9e23ad32d2fe..04c5aacd836e 100644 --- a/drivers/staging/media/tlg2300/pd-common.h +++ b/drivers/staging/media/tlg2300/pd-common.h @@ -250,7 +250,6 @@ void free_all_urb_generic(struct urb **urb_array, int num); /* misc */ void poseidon_delete(struct kref *kref); extern int debug_mode; -void set_debug_mode(struct video_device *vfd, int debug_mode); #ifdef CONFIG_PM #define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) diff --git a/drivers/staging/media/tlg2300/pd-radio.c b/drivers/staging/media/tlg2300/pd-radio.c index b391194a840c..c0567b5ed363 100644 --- a/drivers/staging/media/tlg2300/pd-radio.c +++ b/drivers/staging/media/tlg2300/pd-radio.c @@ -98,12 +98,9 @@ static int poseidon_fm_open(struct file *filp) usb_autopm_get_interface(p->interface); if (0 == p->state) { - struct video_device *vfd = &p->radio_data.fm_dev; - /* default pre-emphasis */ if (p->radio_data.pre_emphasis == 0) p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; - set_debug_mode(vfd, debug_mode); ret = poseidon_check_mode_radio(p); if (ret < 0) { diff --git a/drivers/staging/media/tlg2300/pd-video.c b/drivers/staging/media/tlg2300/pd-video.c index 8cd7f02fcf9f..c0c3c1c4517c 100644 --- a/drivers/staging/media/tlg2300/pd-video.c +++ b/drivers/staging/media/tlg2300/pd-video.c @@ -1299,15 +1299,6 @@ static int pm_video_resume(struct poseidon *pd) } #endif -void set_debug_mode(struct video_device *vfd, int debug_mode) -{ - vfd->debug = 0; - if (debug_mode & 0x1) - vfd->debug = V4L2_DEBUG_IOCTL; - if (debug_mode & 0x2) - vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; -} - static void init_video_context(struct running_context *context) { context->sig_index = 0; @@ -1354,7 +1345,6 @@ static int pd_video_open(struct file *file) front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; pd->video_data.users++; - set_debug_mode(vfd, debug_mode); videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, NULL, &front->queue_lock, -- cgit v1.2.3 From 17028cdb74bf8bb593aebe5550bc90325fa9af88 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Dec 2014 10:10:44 -0300 Subject: [media] v4l2 core: improve debug flag handling The old debug field is renamed to dev_debug to ensure that existing drivers (including out-of-tree drivers) that try to use the old name will no longer compile. A comment has also been added that makes it explicit that drivers shouldn't use this field. Additional bits have been added to the debug flag to be more fine-grained when debugging, especially when dealing with streaming ioctls and read, write and poll. You want to enable those explicitly to prevent flooding the log when streaming unless you actually want to do that. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 28 +++++++++++++++------------- drivers/media/v4l2-core/v4l2-ioctl.c | 10 +++++++--- include/media/v4l2-dev.h | 3 ++- include/media/v4l2-ioctl.h | 15 ++++++++++++--- 4 files changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index a13cc6123dd2..86bb93fd7db8 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -47,15 +47,15 @@ static ssize_t index_show(struct device *cd, } static DEVICE_ATTR_RO(index); -static ssize_t debug_show(struct device *cd, +static ssize_t dev_debug_show(struct device *cd, struct device_attribute *attr, char *buf) { struct video_device *vdev = to_video_device(cd); - return sprintf(buf, "%i\n", vdev->debug); + return sprintf(buf, "%i\n", vdev->dev_debug); } -static ssize_t debug_store(struct device *cd, struct device_attribute *attr, +static ssize_t dev_debug_store(struct device *cd, struct device_attribute *attr, const char *buf, size_t len) { struct video_device *vdev = to_video_device(cd); @@ -66,10 +66,10 @@ static ssize_t debug_store(struct device *cd, struct device_attribute *attr, if (res) return res; - vdev->debug = value; + vdev->dev_debug = value; return len; } -static DEVICE_ATTR_RW(debug); +static DEVICE_ATTR_RW(dev_debug); static ssize_t name_show(struct device *cd, struct device_attribute *attr, char *buf) @@ -82,7 +82,7 @@ static DEVICE_ATTR_RO(name); static struct attribute *video_device_attrs[] = { &dev_attr_name.attr, - &dev_attr_debug.attr, + &dev_attr_dev_debug.attr, &dev_attr_index.attr, NULL, }; @@ -304,7 +304,8 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, return -EINVAL; if (video_is_registered(vdev)) ret = vdev->fops->read(filp, buf, sz, off); - if (vdev->debug) + if ((vdev->dev_debug & V4L2_DEV_DEBUG_FOP) && + (vdev->dev_debug & V4L2_DEV_DEBUG_STREAMING)) printk(KERN_DEBUG "%s: read: %zd (%d)\n", video_device_node_name(vdev), sz, ret); return ret; @@ -320,7 +321,8 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, return -EINVAL; if (video_is_registered(vdev)) ret = vdev->fops->write(filp, buf, sz, off); - if (vdev->debug) + if ((vdev->dev_debug & V4L2_DEV_DEBUG_FOP) && + (vdev->dev_debug & V4L2_DEV_DEBUG_STREAMING)) printk(KERN_DEBUG "%s: write: %zd (%d)\n", video_device_node_name(vdev), sz, ret); return ret; @@ -335,7 +337,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) return DEFAULT_POLLMASK; if (video_is_registered(vdev)) res = vdev->fops->poll(filp, poll); - if (vdev->debug > 2) + if (vdev->dev_debug & V4L2_DEV_DEBUG_POLL) printk(KERN_DEBUG "%s: poll: %08x\n", video_device_node_name(vdev), res); return res; @@ -404,7 +406,7 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp, if (!video_is_registered(vdev)) return -ENODEV; ret = vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); - if (vdev->debug) + if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) printk(KERN_DEBUG "%s: get_unmapped_area (%d)\n", video_device_node_name(vdev), ret); return ret; @@ -420,7 +422,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) return -ENODEV; if (video_is_registered(vdev)) ret = vdev->fops->mmap(filp, vm); - if (vdev->debug) + if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) printk(KERN_DEBUG "%s: mmap (%d)\n", video_device_node_name(vdev), ret); return ret; @@ -450,7 +452,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) ret = -ENODEV; } - if (vdev->debug) + if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) printk(KERN_DEBUG "%s: open (%d)\n", video_device_node_name(vdev), ret); /* decrease the refcount in case of an error */ @@ -467,7 +469,7 @@ static int v4l2_release(struct inode *inode, struct file *filp) if (vdev->fops->release) ret = vdev->fops->release(filp); - if (vdev->debug) + if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) printk(KERN_DEBUG "%s: release\n", video_device_node_name(vdev)); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index faac2f4e0f3a..b08407225db1 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2339,7 +2339,7 @@ static long __video_do_ioctl(struct file *file, const struct v4l2_ioctl_info *info; void *fh = file->private_data; struct v4l2_fh *vfh = NULL; - int debug = vfd->debug; + int dev_debug = vfd->dev_debug; long ret = -ENOTTY; if (ops == NULL) { @@ -2388,11 +2388,15 @@ static long __video_do_ioctl(struct file *file, } done: - if (debug) { + if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) { + if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) && + (cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF)) + return ret; + v4l_printk_ioctl(video_device_node_name(vfd), cmd); if (ret < 0) pr_cont(": error %ld", ret); - if (debug == V4L2_DEBUG_IOCTL) + if (!(dev_debug & V4L2_DEV_DEBUG_IOCTL_ARG)) pr_cont("\n"); else if (_IOC_DIR(cmd) == _IOC_NONE) info->debug(arg, write_only); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index eb76cfd47189..3e4fddfc840c 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -124,7 +124,8 @@ struct video_device spinlock_t fh_lock; /* Lock for all v4l2_fhs */ struct list_head fh_list; /* List of struct v4l2_fh */ - int debug; /* Activates debug level*/ + /* Internal device debug flags, not for use by drivers */ + int dev_debug; /* Video standard vars */ v4l2_std_id tvnorms; /* Supported tv norms */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 53605f0f9903..8537983b9b22 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -291,9 +291,18 @@ struct v4l2_ioctl_ops { /* v4l debugging and diagnostics */ -/* Debug bitmask flags to be used on V4L2 */ -#define V4L2_DEBUG_IOCTL 0x01 -#define V4L2_DEBUG_IOCTL_ARG 0x02 +/* Device debug flags to be used with the video device debug attribute */ + +/* Just log the ioctl name + error code */ +#define V4L2_DEV_DEBUG_IOCTL 0x01 +/* Log the ioctl name arguments + error code */ +#define V4L2_DEV_DEBUG_IOCTL_ARG 0x02 +/* Log the file operations open, release, mmap and get_unmapped_area */ +#define V4L2_DEV_DEBUG_FOP 0x04 +/* Log the read and write file operations and the VIDIOC_(D)QBUF ioctls */ +#define V4L2_DEV_DEBUG_STREAMING 0x08 +/* Log poll() */ +#define V4L2_DEV_DEBUG_POLL 0x10 /* Video standard functions */ extern const char *v4l2_norm_to_name(v4l2_std_id id); -- cgit v1.2.3 From e5b30145e56a20caeffed553d1239e401e4fb4e2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:51 -0300 Subject: [media] av7110: fix sparse warning drivers/media/pci/ttpci/av7110.c:1226:15: warning: memset with byte count of 192512 Instead of memsetting this in one go, loop over each line and memset each line separately. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/av7110.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index c1f0617a6973..45199a12b9d9 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -1219,11 +1219,14 @@ static int stop_ts_capture(struct av7110 *budget) static int start_ts_capture(struct av7110 *budget) { + unsigned y; + dprintk(2, "budget: %p\n", budget); if (budget->feeding1) return ++budget->feeding1; - memset(budget->grabbing, 0x00, TS_BUFLEN); + for (y = 0; y < TS_HEIGHT; y++) + memset(budget->grabbing + y * TS_WIDTH, 0x00, TS_WIDTH); budget->ttbp = 0; SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */ SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ -- cgit v1.2.3 From 65adb86d6142f1233e84c81112907f4caa6afffd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:52 -0300 Subject: [media] budget-core: fix sparse warnings Fixes these sparse warnings. drivers/media/pci/ttpci/budget-core.c:250:17: warning: context imbalance in 'ttpci_budget_debiread' - different lock contexts for basic block drivers/media/pci/ttpci/budget-core.c:289:17: warning: context imbalance in 'ttpci_budget_debiwrite' - different lock contexts for basic block To be honest, the new code does look better than the old. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/budget-core.c | 89 +++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index 37d02fe09137..23e05499b509 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -231,63 +231,59 @@ static void vpeirq(unsigned long data) } -int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, - int uselocks, int nobusyloop) +static int ttpci_budget_debiread_nolock(struct budget *budget, u32 config, + int addr, int count, int nobusyloop) { struct saa7146_dev *saa = budget->dev; - int result = 0; - unsigned long flags = 0; - - if (count > 4 || count <= 0) - return 0; - - if (uselocks) - spin_lock_irqsave(&budget->debilock, flags); + int result; - if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { - if (uselocks) - spin_unlock_irqrestore(&budget->debilock, flags); + result = saa7146_wait_for_debi_done(saa, nobusyloop); + if (result < 0) return result; - } saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); saa7146_write(saa, DEBI_CONFIG, config); saa7146_write(saa, DEBI_PAGE, 0); saa7146_write(saa, MC2, (2 << 16) | 2); - if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { - if (uselocks) - spin_unlock_irqrestore(&budget->debilock, flags); + result = saa7146_wait_for_debi_done(saa, nobusyloop); + if (result < 0) return result; - } result = saa7146_read(saa, DEBI_AD); result &= (0xffffffffUL >> ((4 - count) * 8)); - - if (uselocks) - spin_unlock_irqrestore(&budget->debilock, flags); - return result; } -int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, - int count, u32 value, int uselocks, int nobusyloop) +int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, + int uselocks, int nobusyloop) { - struct saa7146_dev *saa = budget->dev; - unsigned long flags = 0; - int result; - if (count > 4 || count <= 0) return 0; - if (uselocks) - spin_lock_irqsave(&budget->debilock, flags); + if (uselocks) { + unsigned long flags; + int result; - if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { - if (uselocks) - spin_unlock_irqrestore(&budget->debilock, flags); + spin_lock_irqsave(&budget->debilock, flags); + result = ttpci_budget_debiread_nolock(budget, config, addr, + count, nobusyloop); + spin_unlock_irqrestore(&budget->debilock, flags); return result; } + return ttpci_budget_debiread_nolock(budget, config, addr, + count, nobusyloop); +} + +static int ttpci_budget_debiwrite_nolock(struct budget *budget, u32 config, + int addr, int count, u32 value, int nobusyloop) +{ + struct saa7146_dev *saa = budget->dev; + int result; + + result = saa7146_wait_for_debi_done(saa, nobusyloop); + if (result < 0) + return result; saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff)); saa7146_write(saa, DEBI_CONFIG, config); @@ -295,15 +291,28 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, saa7146_write(saa, DEBI_AD, value); saa7146_write(saa, MC2, (2 << 16) | 2); - if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { - if (uselocks) - spin_unlock_irqrestore(&budget->debilock, flags); - return result; - } + result = saa7146_wait_for_debi_done(saa, nobusyloop); + return result < 0 ? result : 0; +} - if (uselocks) +int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, + int count, u32 value, int uselocks, int nobusyloop) +{ + if (count > 4 || count <= 0) + return 0; + + if (uselocks) { + unsigned long flags; + int result; + + spin_lock_irqsave(&budget->debilock, flags); + result = ttpci_budget_debiwrite_nolock(budget, config, addr, + count, value, nobusyloop); spin_unlock_irqrestore(&budget->debilock, flags); - return 0; + return result; + } + return ttpci_budget_debiwrite_nolock(budget, config, addr, + count, value, nobusyloop); } -- cgit v1.2.3 From d832672f2038d7b36dc08636468cbbed4afe625b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:53 -0300 Subject: [media] ivtv: fix sparse warning Fix this warning: drivers/media/pci/ivtv/ivtv-irq.c:418:9: warning: context imbalance in 'ivtv_dma_stream_dec_prepare' - different lock contexts for basic block sparse didn't quite understand the locking scheme, so rewrite it to keep sparse happy. Signed-off-by: Hans Verkuil Cc: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtv-irq.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index ab6d5d25aa6f..e7d701777e53 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c @@ -357,7 +357,6 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; int y_done = 0; int bytes_written = 0; - unsigned long flags = 0; int idx = 0; IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); @@ -407,16 +406,21 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) /* Sync Hardware SG List of buffers */ ivtv_stream_sync_for_device(s); - if (lock) + if (lock) { + unsigned long flags = 0; + spin_lock_irqsave(&itv->dma_reg_lock, flags); - if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) { - ivtv_dma_dec_start(s); - } - else { - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); - } - if (lock) + if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) + ivtv_dma_dec_start(s); + else + set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); spin_unlock_irqrestore(&itv->dma_reg_lock, flags); + } else { + if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) + ivtv_dma_dec_start(s); + else + set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); + } } static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s) -- cgit v1.2.3 From 7c424dd14fcf4c2905778ecd3f1ad10c5a097b5b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:54 -0300 Subject: [media] videobuf2-vmalloc: fix sparse warning Fix this warning: drivers/media/v4l2-core/videobuf2-vmalloc.c:98:28: warning: incorrect type in assignment (different address spaces) drivers/media/v4l2-core/videobuf2-vmalloc.c:158:28: warning: incorrect type in argument 1 (different address spaces) The warning is correct, but we have no other choice here to forcibly cast. At least it is now explicit that such a cast is needed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-vmalloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c index fba944e50227..7f6d41b18de9 100644 --- a/drivers/media/v4l2-core/videobuf2-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c @@ -95,7 +95,7 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) goto fail_pages_array_alloc; buf->vma = vma; - buf->vaddr = ioremap_nocache(physp, size); + buf->vaddr = (__force void *)ioremap_nocache(physp, size); if (!buf->vaddr) goto fail_pages_array_alloc; } else { @@ -155,7 +155,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) kfree(buf->pages); } else { vb2_put_vma(buf->vma); - iounmap(buf->vaddr); + iounmap((__force void __iomem *)buf->vaddr); } kfree(buf); } -- cgit v1.2.3 From 50fd5e8c1e02ac471a0a4f3aaa87684a5152a0b4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:56 -0300 Subject: [media] hd29l2: fix sparse error and warnings drivers/media/dvb-frontends/hd29l2.c:29:18: warning: Variable length array is used. drivers/media/dvb-frontends/hd29l2.c:34:32: error: cannot size expression drivers/media/dvb-frontends/hd29l2.c:125:5: warning: symbol 'hd29l2_rd_reg_mask' was not declared. Should it be static? Variable length arrays are frowned upon, so replace with a fixed length and check that there won't be a buffer overrun. Signed-off-by: Hans Verkuil Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/hd29l2.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c index d7b9d549156d..67c8e6df42e8 100644 --- a/drivers/media/dvb-frontends/hd29l2.c +++ b/drivers/media/dvb-frontends/hd29l2.c @@ -22,20 +22,24 @@ #include "hd29l2_priv.h" +#define HD29L2_MAX_LEN (3) + /* write multiple registers */ static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[2 + len]; + u8 buf[2 + HD29L2_MAX_LEN]; struct i2c_msg msg[1] = { { .addr = priv->cfg.i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 2 + len, .buf = buf, } }; + if (len > HD29L2_MAX_LEN) + return -EINVAL; buf[0] = 0x00; buf[1] = reg; memcpy(&buf[2], val, len); @@ -118,7 +122,7 @@ static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask) } /* read single register with mask */ -int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask) +static int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask) { int ret, i; u8 tmp; -- cgit v1.2.3 From d3acd83e6ea42146189c0b60de24fd89bcb92e4b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:57 -0300 Subject: [media] m5mols: fix sparse warnings drivers/media/i2c/m5mols/m5mols_core.c:128:24: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:128:24: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:128:24: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:128:24: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:130:24: warning: cast to restricted __be32 drivers/media/i2c/m5mols/m5mols_core.c:457:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:457:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:457:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:457:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:458:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:458:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:458:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:458:19: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:459:22: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:459:22: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:459:22: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:459:22: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:460:20: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:460:20: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:460:20: warning: cast to restricted __be16 drivers/media/i2c/m5mols/m5mols_core.c:460:20: warning: cast to restricted __be16 The be16_to_cpu conversions in m5mols_get_version() are not needed since the data is already using cpu endianness. This was never noticed since these version fields are never used. Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/m5mols/m5mols_core.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 2820f7c38cba..6ed16e569bbf 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -125,9 +125,9 @@ static u32 m5mols_swap_byte(u8 *data, u8 length) if (length == 1) return *data; else if (length == 2) - return be16_to_cpu(*((u16 *)data)); + return be16_to_cpu(*((__be16 *)data)); else - return be32_to_cpu(*((u32 *)data)); + return be32_to_cpu(*((__be32 *)data)); } /** @@ -454,11 +454,6 @@ static int m5mols_get_version(struct v4l2_subdev *sd) return ret; } - ver->fw = be16_to_cpu(ver->fw); - ver->hw = be16_to_cpu(ver->hw); - ver->param = be16_to_cpu(ver->param); - ver->awb = be16_to_cpu(ver->awb); - v4l2_info(sd, "Manufacturer\t[%s]\n", is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? "Samsung Electro-Machanics" : -- cgit v1.2.3 From b75f2d16cb0d3f75104f8565dd5f713dbf4a074d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:58 -0300 Subject: [media] s5k4ecgx: fix sparse warnings drivers/media/i2c/s5k4ecgx.c:223:16: warning: cast to restricted __be16 drivers/media/i2c/s5k4ecgx.c:223:16: warning: cast to restricted __be16 drivers/media/i2c/s5k4ecgx.c:223:16: warning: cast to restricted __be16 drivers/media/i2c/s5k4ecgx.c:223:16: warning: cast to restricted __be16 drivers/media/i2c/s5k4ecgx.c:344:20: warning: cast to restricted __le32 drivers/media/i2c/s5k4ecgx.c:354:20: warning: cast to restricted __le32 drivers/media/i2c/s5k4ecgx.c:364:24: warning: cast to restricted __le32 drivers/media/i2c/s5k4ecgx.c:366:23: warning: cast to restricted __le16 The get_unaligned_le*() functions return the value using cpu endianness, so calling le*_to_cpu is wrong. It hasn't been not noticed because this code has only been run on little endian systems, so le*_to_cpu doesn't do anything. Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k4ecgx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index d1c50c9d43ae..70071314789e 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c @@ -220,7 +220,7 @@ static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val) msg[1].buf = rbuf; ret = i2c_transfer(client->adapter, msg, 2); - *val = be16_to_cpu(*((u16 *)rbuf)); + *val = be16_to_cpu(*((__be16 *)rbuf)); v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val); @@ -341,7 +341,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd) v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE); return err; } - regs_num = le32_to_cpu(get_unaligned_le32(fw->data)); + regs_num = get_unaligned_le32(fw->data); v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n", S5K4ECGX_FIRMWARE, fw->size, regs_num); @@ -351,8 +351,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd) err = -EINVAL; goto fw_out; } - crc_file = le32_to_cpu(get_unaligned_le32(fw->data + - regs_num * FW_RECORD_SIZE)); + crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE); crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE); if (crc != crc_file) { v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file); @@ -361,9 +360,9 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd) } ptr = fw->data + FW_RECORD_SIZE; for (i = 1; i < regs_num; i++) { - addr = le32_to_cpu(get_unaligned_le32(ptr)); + addr = get_unaligned_le32(ptr); ptr += sizeof(u32); - val = le16_to_cpu(get_unaligned_le16(ptr)); + val = get_unaligned_le16(ptr); ptr += sizeof(u16); if (addr - addr_inc != 2) err = s5k4ecgx_write(client, addr, val); -- cgit v1.2.3 From 7c7586bb3c132f93b27148fe686dbd979f64d902 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:52:59 -0300 Subject: [media] s5k6aa: fix sparse warnings drivers/media/i2c/s5k6aa.c:351:16: warning: cast to restricted __be16 drivers/media/i2c/s5k6aa.c:351:16: warning: cast to restricted __be16 drivers/media/i2c/s5k6aa.c:351:16: warning: cast to restricted __be16 drivers/media/i2c/s5k6aa.c:351:16: warning: cast to restricted __be16 Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k6aa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 19edafb82b5b..b1c583239dab 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -348,7 +348,7 @@ static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val) msg[1].buf = rbuf; ret = i2c_transfer(client->adapter, msg, 2); - *val = be16_to_cpu(*((u16 *)rbuf)); + *val = be16_to_cpu(*((__be16 *)rbuf)); v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val); -- cgit v1.2.3 From 0348bb1a7aa6093e9aead41d50c792576839a3a1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Dec 2014 08:53:00 -0300 Subject: [media] s5k5baf: fix sparse warnings drivers/media/i2c/s5k5baf.c:1796:33: warning: duplicate const drivers/media/i2c/s5k5baf.c:379:24: warning: cast to restricted __le16 drivers/media/i2c/s5k5baf.c:437:11: warning: incorrect type in assignment (different base types) drivers/media/i2c/s5k5baf.c:445:16: warning: incorrect type in return expression (different base types) Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k5baf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 60a74d8d38d5..a3d7d0391302 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -353,7 +353,7 @@ static struct v4l2_rect s5k5baf_cis_rect = { * */ static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw, - size_t count, const u16 *data) + size_t count, const __le16 *data) { struct s5k5baf_fw *f; u16 *d, i, *end; @@ -421,6 +421,7 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr) { struct i2c_client *c = v4l2_get_subdevdata(&state->sd); __be16 w, r; + u16 res; struct i2c_msg msg[] = { { .addr = c->addr, .flags = 0, .len = 2, .buf = (u8 *)&w }, @@ -434,15 +435,15 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr) w = cpu_to_be16(addr); ret = i2c_transfer(c->adapter, msg, 2); - r = be16_to_cpu(r); + res = be16_to_cpu(r); - v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, r); + v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, res); if (ret != 2) { v4l2_err(c, "i2c_read: error during transfer (%d)\n", ret); state->error = ret; } - return r; + return res; } static void s5k5baf_i2c_write(struct s5k5baf *state, u16 addr, u16 val) @@ -1037,7 +1038,7 @@ static int s5k5baf_load_setfile(struct s5k5baf *state) } ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2, - (u16 *)fw->data); + (__le16 *)fw->data); release_firmware(fw); @@ -1793,7 +1794,7 @@ static const struct v4l2_subdev_ops s5k5baf_subdev_ops = { static int s5k5baf_configure_gpios(struct s5k5baf *state) { - static const char const *name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" }; + static const char * const name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" }; struct i2c_client *c = v4l2_get_subdevdata(&state->sd); struct s5k5baf_gpio *g = state->gpios; int ret, i; -- cgit v1.2.3 From 9571a17fc253e1b362217352d7faa815ba5b5a3e Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 16 Dec 2014 20:17:20 -0300 Subject: [media] media: au0828 VBI support comment cleanup This driver supports VBI and the comment "VBI support is not yet working" is inaccurate. Remove it. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 5f337b118bff..8a7a54750aee 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -22,7 +22,6 @@ /* Developer Notes: * - * VBI support is not yet working * The hardware scaler supported is unimplemented * AC97 audio support is unimplemented (only i2s audio mode) * -- cgit v1.2.3 From 94acbe12f589bfcb37ed8a12c5efd14140044642 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 15 Dec 2014 10:55:37 -0300 Subject: [media] VIDEO_CAFE_CCIC should select VIDEOBUF2_DMA_SG If VIDEO_CAFE_CCIC=y, but VIDEOBUF2_DMA_SG=m: drivers/built-in.o: In function `mcam_v4l_open': mcam-core.c:(.text+0x1c2e81): undefined reference to `vb2_dma_sg_memops' mcam-core.c:(.text+0x1c2eb0): undefined reference to `vb2_dma_sg_init_ctx' drivers/built-in.o: In function `mcam_v4l_release': mcam-core.c:(.text+0x1c34bf): undefined reference to `vb2_dma_sg_cleanup_ctx' Reported-by: Fengguang Wu Signed-off-by: Geert Uytterhoeven Acked-by: Jonathan Corbet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig index 6265d36adceb..3d166568bd69 100644 --- a/drivers/media/platform/marvell-ccic/Kconfig +++ b/drivers/media/platform/marvell-ccic/Kconfig @@ -5,6 +5,7 @@ config VIDEO_CAFE_CCIC select VIDEO_OV7670 select VIDEOBUF2_VMALLOC select VIDEOBUF2_DMA_CONTIG + select VIDEOBUF2_DMA_SG ---help--- This is a video4linux2 driver for the Marvell 88ALP01 integrated CMOS camera controller. This is the controller found on first- -- cgit v1.2.3 From 29867e2febad863fb3cef99ad894cd992df5e665 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 18 Oct 2014 06:11:19 -0300 Subject: [media] smiapp: Remove FSF's address from the license header Remove FSF's address information from the license header in the smiapp driver and the smiapp-pll PLL calculator. This should no longer be needed, and would be rendered outdated in case the FSF chooses to relocate its office. Signed-off-by: Sakari Ailus Cc: Timo Ahonen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp-pll.c | 6 ------ drivers/media/i2c/smiapp-pll.h | 6 ------ drivers/media/i2c/smiapp/smiapp-core.c | 6 ------ drivers/media/i2c/smiapp/smiapp-limits.c | 6 ------ drivers/media/i2c/smiapp/smiapp-limits.h | 6 ------ drivers/media/i2c/smiapp/smiapp-quirk.c | 6 ------ drivers/media/i2c/smiapp/smiapp-quirk.h | 6 ------ drivers/media/i2c/smiapp/smiapp-reg-defs.h | 6 ------ drivers/media/i2c/smiapp/smiapp-reg.h | 6 ------ drivers/media/i2c/smiapp/smiapp-regs.c | 6 ------ drivers/media/i2c/smiapp/smiapp-regs.h | 6 ------ drivers/media/i2c/smiapp/smiapp.h | 6 ------ 12 files changed, 72 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c index e40d9027df3d..2b84d097cfa5 100644 --- a/drivers/media/i2c/smiapp-pll.c +++ b/drivers/media/i2c/smiapp-pll.c @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h index e8f035a50c76..77f7ff2ff0f2 100644 --- a/drivers/media/i2c/smiapp-pll.h +++ b/drivers/media/i2c/smiapp-pll.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #ifndef SMIAPP_PLL_H diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 0df5070e73c7..cee1a9ae6ec8 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -18,12 +18,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include diff --git a/drivers/media/i2c/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c index 847cb235e198..784b114d3f8b 100644 --- a/drivers/media/i2c/smiapp/smiapp-limits.c +++ b/drivers/media/i2c/smiapp/smiapp-limits.c @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include "smiapp.h" diff --git a/drivers/media/i2c/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h index 343e9c3827fc..b20124862a14 100644 --- a/drivers/media/i2c/smiapp/smiapp-limits.h +++ b/drivers/media/i2c/smiapp/smiapp-limits.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY 0 diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c index e0bee8752122..dd4ae6f4ba3e 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.c +++ b/drivers/media/i2c/smiapp/smiapp-quirk.c @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h index 46e9ea8bfa08..3a3c3e57515f 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.h +++ b/drivers/media/i2c/smiapp/smiapp-quirk.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #ifndef __SMIAPP_QUIRK__ diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h index c488ef028074..f928d4cc8e26 100644 --- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h +++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r)) #define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r)) diff --git a/drivers/media/i2c/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h index b0dcbb8fa5e2..4c8b40614969 100644 --- a/drivers/media/i2c/smiapp/smiapp-reg.h +++ b/drivers/media/i2c/smiapp/smiapp-reg.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #ifndef __SMIAPP_REG_H_ diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c index a2098007fb70..6b6c20b61397 100644 --- a/drivers/media/i2c/smiapp/smiapp-regs.c +++ b/drivers/media/i2c/smiapp/smiapp-regs.c @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h index 35521125a2cc..6dd0e499c845 100644 --- a/drivers/media/i2c/smiapp/smiapp-regs.h +++ b/drivers/media/i2c/smiapp/smiapp-regs.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #ifndef SMIAPP_REGS_H diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index f88f8ec344d3..8fded46ac584 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -14,12 +14,6 @@ * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #ifndef __SMIAPP_PRIV_H_ -- cgit v1.2.3 From 8c20ee6e92e435609f8d7dd0c2b4b77c8dbb3f18 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 18 Oct 2014 06:16:20 -0300 Subject: [media] smiapp-pll: include linux/device.h in smiapp-pll.c, not in smiapp-pll.h struct device has a forward declaration in the header already. The header is only needed in the .c file. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp-pll.c | 1 + drivers/media/i2c/smiapp-pll.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c index 2b84d097cfa5..e3348db56c46 100644 --- a/drivers/media/i2c/smiapp-pll.c +++ b/drivers/media/i2c/smiapp-pll.c @@ -16,6 +16,7 @@ * General Public License for more details. */ +#include #include #include #include diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h index 77f7ff2ff0f2..b98d143b64e1 100644 --- a/drivers/media/i2c/smiapp-pll.h +++ b/drivers/media/i2c/smiapp-pll.h @@ -19,8 +19,6 @@ #ifndef SMIAPP_PLL_H #define SMIAPP_PLL_H -#include - /* CSI-2 or CCP-2 */ #define SMIAPP_PLL_BUS_TYPE_CSI2 0x00 #define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01 -- cgit v1.2.3 From 3d9bb7a620f061fd94da043bd9e69a65a9510981 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 8 Dec 2014 17:49:31 -0300 Subject: [media] smiapp: Don't give the source sub-device a temporary name The source sub-device's name will be overwritten shortly. Don't give it a name in the meantime. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index cee1a9ae6ec8..3d5fba4cc66a 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2458,8 +2458,6 @@ static int smiapp_identify_module(struct v4l2_subdev *subdev) minfo->name, minfo->manufacturer_id, minfo->model_id, minfo->revision_number_major); - strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name)); - return 0; } -- cgit v1.2.3 From f73108eb8e804180cb7f834649c670ba8b892777 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 30 Nov 2013 17:51:15 -0300 Subject: [media] smiapp: Register async subdev Register and unregister async sub-device for DT. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 3d5fba4cc66a..2c65ff3ed769 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2942,8 +2942,21 @@ static int smiapp_probe(struct i2c_client *client, sensor->src->sensor = sensor; sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE; - return media_entity_init(&sensor->src->sd.entity, 2, + rval = media_entity_init(&sensor->src->sd.entity, 2, sensor->src->pads, 0); + if (rval < 0) + return rval; + + rval = v4l2_async_register_subdev(&sensor->src->sd); + if (rval < 0) + goto out_media_entity_cleanup; + + return 0; + +out_media_entity_cleanup: + media_entity_cleanup(&sensor->src->sd.entity); + + return rval; } static int smiapp_remove(struct i2c_client *client) @@ -2952,6 +2965,8 @@ static int smiapp_remove(struct i2c_client *client) struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); unsigned int i; + v4l2_async_unregister_subdev(subdev); + if (sensor->power_count) { if (gpio_is_valid(sensor->platform_data->xshutdown)) gpio_set_value(sensor->platform_data->xshutdown, 0); -- cgit v1.2.3 From 575ea5b3a41c3facb6e7973fdce865d208bf89c9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 26 Jan 2014 21:13:13 -0300 Subject: [media] smiapp: The sensor only needs a single clock, name may be NULL The SMIA compatible sensors only need a single clock. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 2c65ff3ed769..3dd32b1761e4 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2482,7 +2482,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) } if (!sensor->platform_data->set_xclk) { - sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk"); + sensor->ext_clk = devm_clk_get(&client->dev, NULL); if (IS_ERR(sensor->ext_clk)) { dev_err(&client->dev, "could not get clock\n"); return PTR_ERR(sensor->ext_clk); -- cgit v1.2.3 From 390a5fa5bd07fd683f8f8a2b2959400242e0b76f Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 30 Nov 2013 17:51:15 -0300 Subject: [media] smiapp: Obtain device information from the Device Tree if OF node exists Platform data support is retained. of_property_read_u64_array() isn't used yet as it's not in yet. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 114 ++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 3dd32b1761e4..a6bc5eff266a 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "smiapp.h" @@ -2919,19 +2921,121 @@ static int smiapp_resume(struct device *dev) #endif /* CONFIG_PM */ +static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev) +{ + struct smiapp_platform_data *pdata; + struct v4l2_of_endpoint bus_cfg; + struct device_node *ep; + struct property *prop; + __be32 *val; + uint32_t asize; + unsigned int i; + int rval; + + if (!dev->of_node) + return dev->platform_data; + + ep = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!ep) + return NULL; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + rval = -ENOMEM; + goto out_err; + } + + v4l2_of_parse_endpoint(ep, &bus_cfg); + + switch (bus_cfg.bus_type) { + case V4L2_MBUS_CSI2: + pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2; + break; + /* FIXME: add CCP2 support. */ + default: + rval = -EINVAL; + goto out_err; + } + + pdata->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + dev_dbg(dev, "lanes %u\n", pdata->lanes); + + /* xshutdown GPIO is optional */ + pdata->xshutdown = of_get_named_gpio(dev->of_node, "reset-gpios", 0); + + /* NVM size is not mandatory */ + of_property_read_u32(dev->of_node, "nokia,nvm-size", + &pdata->nvm_size); + + rval = of_property_read_u32(dev->of_node, "clock-frequency", + &pdata->ext_clk); + if (rval) { + dev_warn(dev, "can't get clock-frequency\n"); + goto out_err; + } + + dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown, + pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode); + + rval = of_get_property( + dev->of_node, "link-frequencies", &asize) ? 0 : -ENOENT; + if (rval) { + dev_warn(dev, "can't get link-frequencies array size\n"); + goto out_err; + } + + pdata->op_sys_clock = devm_kzalloc(dev, asize, GFP_KERNEL); + if (!pdata->op_sys_clock) { + rval = -ENOMEM; + goto out_err; + } + + asize /= sizeof(*pdata->op_sys_clock); + /* + * Read a 64-bit array --- this will be replaced with a + * of_property_read_u64_array() once it's merged. + */ + prop = of_find_property(dev->of_node, "link-frequencies", NULL); + if (!prop) + goto out_err; + if (!prop->value) + goto out_err; + if (asize * sizeof(*pdata->op_sys_clock) > prop->length) + goto out_err; + val = prop->value; + if (IS_ERR(val)) + goto out_err; + + for (i = 0; i < asize; i++) + pdata->op_sys_clock[i] = of_read_number(val + i * 2, 2); + + for (; asize > 0; asize--) + dev_dbg(dev, "freq %d: %lld\n", asize - 1, + pdata->op_sys_clock[asize - 1]); + + of_node_put(ep); + return pdata; + +out_err: + of_node_put(ep); + return NULL; +} + static int smiapp_probe(struct i2c_client *client, const struct i2c_device_id *devid) { struct smiapp_sensor *sensor; + struct smiapp_platform_data *pdata = smiapp_get_pdata(&client->dev); + int rval; - if (client->dev.platform_data == NULL) + if (pdata == NULL) return -ENODEV; sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (sensor == NULL) return -ENOMEM; - sensor->platform_data = client->dev.platform_data; + sensor->platform_data = pdata; mutex_init(&sensor->mutex); mutex_init(&sensor->power_mutex); sensor->src = &sensor->ssds[sensor->ssds_used]; @@ -2990,6 +3094,11 @@ static int smiapp_remove(struct i2c_client *client) return 0; } +static const struct of_device_id smiapp_of_table[] = { + { .compatible = "nokia,smia" }, + { }, +}; + static const struct i2c_device_id smiapp_id_table[] = { { SMIAPP_NAME, 0 }, { }, @@ -3003,6 +3112,7 @@ static const struct dev_pm_ops smiapp_pm_ops = { static struct i2c_driver smiapp_i2c_driver = { .driver = { + .of_match_table = smiapp_of_table, .name = SMIAPP_NAME, .pm = &smiapp_pm_ops, }, -- cgit v1.2.3 From 7095108b1674d3e0fd02b3fb51c9b302346c0260 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 14 Sep 2014 17:59:00 -0300 Subject: [media] smiapp: Split sub-device initialisation off from the registered callback The registered callback is called by the V4L2 async framework after the bound callback. This allows separating the functionality in the registered callback so that on DT based systems only sub-device registration is done there. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 82 ++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index a6bc5eff266a..7b13617a74c9 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2467,6 +2467,56 @@ static const struct v4l2_subdev_ops smiapp_ops; static const struct v4l2_subdev_internal_ops smiapp_internal_ops; static const struct media_entity_operations smiapp_entity_ops; +static int smiapp_register_subdevs(struct smiapp_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct smiapp_subdev *ssds[] = { + sensor->scaler, + sensor->binner, + sensor->pixel_array, + }; + unsigned int i; + int rval; + + for (i = 0; i < SMIAPP_SUBDEVS - 1; i++) { + struct smiapp_subdev *this = ssds[i + 1]; + struct smiapp_subdev *last = ssds[i]; + + if (!last) + continue; + + rval = media_entity_init(&this->sd.entity, + this->npads, this->pads, 0); + if (rval) { + dev_err(&client->dev, + "media_entity_init failed\n"); + return rval; + } + + rval = media_entity_create_link(&this->sd.entity, + this->source_pad, + &last->sd.entity, + last->sink_pad, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (rval) { + dev_err(&client->dev, + "media_entity_create_link failed\n"); + return rval; + } + + rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, + &this->sd); + if (rval) { + dev_err(&client->dev, + "v4l2_device_register_subdev failed\n"); + return rval; + } + } + + return 0; +} + static int smiapp_registered(struct v4l2_subdev *subdev) { struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); @@ -2705,37 +2755,13 @@ static int smiapp_registered(struct v4l2_subdev *subdev) this->sd.owner = THIS_MODULE; v4l2_set_subdevdata(&this->sd, client); - rval = media_entity_init(&this->sd.entity, - this->npads, this->pads, 0); - if (rval) { - dev_err(&client->dev, - "media_entity_init failed\n"); - goto out_nvm_release; - } - - rval = media_entity_create_link(&this->sd.entity, - this->source_pad, - &last->sd.entity, - last->sink_pad, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (rval) { - dev_err(&client->dev, - "media_entity_create_link failed\n"); - goto out_nvm_release; - } - - rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, - &this->sd); - if (rval) { - dev_err(&client->dev, - "v4l2_device_register_subdev failed\n"); - goto out_nvm_release; - } - last = this; } + rval = smiapp_register_subdevs(sensor); + if (rval) + goto out_nvm_release; + dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); sensor->pixel_array->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; -- cgit v1.2.3 From 4c94468459884f10834b436620d2bd591c4cb105 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 14 Sep 2014 18:53:06 -0300 Subject: [media] smiapp: Fully probe the device in probe In the case of platform data, ISPs that provide clocks to the sensor must probe before the sensor does. Accessing the sensor does require the clocks, and thus, probe cannot access the sensor in such a system. This limitation does not exist in the case of the DT. Perform all initialisation except Media entity initialisation, link creation and sub-device registration in probe. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 68 +++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 7b13617a74c9..91ab71c3280e 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2334,10 +2334,9 @@ static DEVICE_ATTR(ident, S_IRUGO, smiapp_sysfs_ident_read, NULL); * V4L2 subdev core operations */ -static int smiapp_identify_module(struct v4l2_subdev *subdev) +static int smiapp_identify_module(struct smiapp_sensor *sensor) { - struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); - struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); struct smiapp_module_info *minfo = &sensor->minfo; unsigned int i; int rval = 0; @@ -2517,10 +2516,17 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor) return 0; } -static int smiapp_registered(struct v4l2_subdev *subdev) +static void smiapp_cleanup(struct smiapp_sensor *sensor) { - struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); - struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + + device_remove_file(&client->dev, &dev_attr_nvm); + device_remove_file(&client->dev, &dev_attr_ident); +} + +static int smiapp_init(struct smiapp_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); struct smiapp_pll *pll = &sensor->pll; struct smiapp_subdev *last = NULL; u32 tmp; @@ -2566,7 +2572,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) if (rval) return -ENODEV; - rval = smiapp_identify_module(subdev); + rval = smiapp_identify_module(sensor); if (rval) { rval = -ENODEV; goto out_power_off; @@ -2646,13 +2652,13 @@ static int smiapp_registered(struct v4l2_subdev *subdev) if (sensor->nvm == NULL) { dev_err(&client->dev, "nvm buf allocation failed\n"); rval = -ENOMEM; - goto out_ident_release; + goto out_cleanup; } if (device_create_file(&client->dev, &dev_attr_nvm) != 0) { dev_err(&client->dev, "sysfs nvm entry failed\n"); rval = -EBUSY; - goto out_ident_release; + goto out_cleanup; } } @@ -2696,7 +2702,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) rval = smiapp_get_mbus_formats(sensor); if (rval) { rval = -ENODEV; - goto out_nvm_release; + goto out_cleanup; } for (i = 0; i < SMIAPP_SUBDEVS; i++) { @@ -2758,10 +2764,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev) last = this; } - rval = smiapp_register_subdevs(sensor); - if (rval) - goto out_nvm_release; - dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); sensor->pixel_array->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; @@ -2770,14 +2772,14 @@ static int smiapp_registered(struct v4l2_subdev *subdev) smiapp_read_frame_fmt(sensor); rval = smiapp_init_controls(sensor); if (rval < 0) - goto out_nvm_release; + goto out_cleanup; mutex_lock(&sensor->mutex); rval = smiapp_update_mode(sensor); mutex_unlock(&sensor->mutex); if (rval) { dev_err(&client->dev, "update mode failed\n"); - goto out_nvm_release; + goto out_cleanup; } sensor->streaming = false; @@ -2787,23 +2789,39 @@ static int smiapp_registered(struct v4l2_subdev *subdev) rval = smiapp_read(sensor, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp); sensor->flash_capability = tmp; if (rval) - goto out_nvm_release; + goto out_cleanup; smiapp_power_off(sensor); return 0; -out_nvm_release: - device_remove_file(&client->dev, &dev_attr_nvm); - -out_ident_release: - device_remove_file(&client->dev, &dev_attr_ident); +out_cleanup: + smiapp_cleanup(sensor); out_power_off: smiapp_power_off(sensor); return rval; } +static int smiapp_registered(struct v4l2_subdev *subdev) +{ + struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); + struct i2c_client *client = v4l2_get_subdevdata(subdev); + int rval; + + if (!client->dev.of_node) { + rval = smiapp_init(sensor); + if (rval) + return rval; + } + + rval = smiapp_register_subdevs(sensor); + if (rval) + smiapp_cleanup(sensor); + + return rval; +} + static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct smiapp_subdev *ssd = to_smiapp_subdev(sd); @@ -3077,6 +3095,12 @@ static int smiapp_probe(struct i2c_client *client, if (rval < 0) return rval; + if (client->dev.of_node) { + rval = smiapp_init(sensor); + if (rval) + goto out_media_entity_cleanup; + } + rval = v4l2_async_register_subdev(&sensor->src->sd); if (rval < 0) goto out_media_entity_cleanup; -- cgit v1.2.3 From 0691b40e88350cbfa686ca25f98ab614f1919d73 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 3 Oct 2014 11:21:52 -0300 Subject: [media] smiapp: Access flash capabilities through limits The flash capability register is already read as part of the limit registers. Do no access it separately; instead use the value from the limits. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 9 +-------- drivers/media/i2c/smiapp/smiapp.h | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 91ab71c3280e..22eddd6f92fc 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -1483,7 +1483,7 @@ static int smiapp_start_streaming(struct smiapp_sensor *sensor) if (rval < 0) goto out; - if ((sensor->flash_capability & + if ((sensor->limits[SMIAPP_LIMIT_FLASH_MODE_CAPABILITY] & (SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE | SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) && sensor->platform_data->strobe_setup != NULL && @@ -2529,7 +2529,6 @@ static int smiapp_init(struct smiapp_sensor *sensor) struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); struct smiapp_pll *pll = &sensor->pll; struct smiapp_subdev *last = NULL; - u32 tmp; unsigned int i; int rval; @@ -2785,12 +2784,6 @@ static int smiapp_init(struct smiapp_sensor *sensor) sensor->streaming = false; sensor->dev_init_done = true; - /* check flash capability */ - rval = smiapp_read(sensor, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp); - sensor->flash_capability = tmp; - if (rval) - goto out_cleanup; - smiapp_power_off(sensor); return 0; diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index 8fded46ac584..ed010a8a49d7 100644 --- a/drivers/media/i2c/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -216,7 +216,6 @@ struct smiapp_sensor { u8 scaling_mode; u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ - u8 flash_capability; u8 frame_skip; int power_count; -- cgit v1.2.3 From f7350a034af4531f6df7e66cd5661f0f9a0ec4d6 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 3 Oct 2014 11:20:37 -0300 Subject: [media] smiapp: Free control handlers in sub-device cleanup Also call smiapp_cleanup() in smiapp_remove(), replacing code that did the same than the function. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 22eddd6f92fc..d0a55fbc081c 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2522,6 +2522,8 @@ static void smiapp_cleanup(struct smiapp_sensor *sensor) device_remove_file(&client->dev, &dev_attr_nvm); device_remove_file(&client->dev, &dev_attr_ident); + + smiapp_free_controls(sensor); } static int smiapp_init(struct smiapp_sensor *sensor) @@ -3124,15 +3126,11 @@ static int smiapp_remove(struct i2c_client *client) sensor->power_count = 0; } - device_remove_file(&client->dev, &dev_attr_ident); - if (sensor->nvm) - device_remove_file(&client->dev, &dev_attr_nvm); - for (i = 0; i < sensor->ssds_used; i++) { v4l2_device_unregister_subdev(&sensor->ssds[i].sd); media_entity_cleanup(&sensor->ssds[i].sd.entity); } - smiapp_free_controls(sensor); + smiapp_cleanup(sensor); return 0; } -- cgit v1.2.3 From 6208aebd33d341d5068ab0ccbff8035ff4034c08 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 9 Dec 2014 14:35:43 -0300 Subject: [media] smiapp: Clean up smiapp_init_controls() Clean up smiapp_init_controls() by adding newlines to appropriate places and by removing superfluous error handling. The caller will clean up control handlers in any case if the function fails. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index d0a55fbc081c..8361070f523f 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -527,6 +527,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12); if (rval) return rval; + sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; sensor->analog_gain = v4l2_ctrl_new_std( @@ -585,8 +586,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) dev_err(&client->dev, "pixel array controls initialization failed (%d)\n", sensor->pixel_array->ctrl_handler.error); - rval = sensor->pixel_array->ctrl_handler.error; - goto error; + return sensor->pixel_array->ctrl_handler.error; } sensor->pixel_array->sd.ctrl_handler = @@ -596,7 +596,8 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0); if (rval) - goto error; + return rval; + sensor->src->ctrl_handler.lock = &sensor->mutex; for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++); @@ -614,20 +615,12 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) dev_err(&client->dev, "src controls initialization failed (%d)\n", sensor->src->ctrl_handler.error); - rval = sensor->src->ctrl_handler.error; - goto error; + return sensor->src->ctrl_handler.error; } - sensor->src->sd.ctrl_handler = - &sensor->src->ctrl_handler; + sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler; return 0; - -error: - v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler); - v4l2_ctrl_handler_free(&sensor->src->ctrl_handler); - - return rval; } static void smiapp_free_controls(struct smiapp_sensor *sensor) -- cgit v1.2.3 From 2e9f3c1c4443b2e46ef15e021cdf693b16c5231d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 9 Dec 2014 13:48:58 -0300 Subject: [media] smiapp: Separate late controls from the rest The default values and limits for certain controls need the knowledge of available media bus codes or link frequencies. Create such controls later on, so that most of the initialisation of the sensor has already been done when the init quirk is called. [mchehab@osg.samsung.com: make checkpatch.pl happier] Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 54 ++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 8361070f523f..fb8f8a85f850 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -519,9 +519,6 @@ static const struct v4l2_ctrl_ops smiapp_ctrl_ops = { static int smiapp_init_controls(struct smiapp_sensor *sensor) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - unsigned long *valid_link_freqs = &sensor->valid_link_freqs[ - sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE]; - unsigned int max, i; int rval; rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12); @@ -573,15 +570,6 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) ARRAY_SIZE(smiapp_test_patterns) - 1, 0, 0, smiapp_test_patterns); - for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { - int max_value = (1 << sensor->csi_format->width) - 1; - sensor->test_data[i] = - v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, - &smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i, - 0, max_value, 1, max_value); - } - if (sensor->pixel_array->ctrl_handler.error) { dev_err(&client->dev, "pixel array controls initialization failed (%d)\n", @@ -600,13 +588,6 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) sensor->src->ctrl_handler.lock = &sensor->mutex; - for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++); - - sensor->link_freq = v4l2_ctrl_new_int_menu( - &sensor->src->ctrl_handler, &smiapp_ctrl_ops, - V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), - __ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock); - sensor->pixel_rate_csi = v4l2_ctrl_new_std( &sensor->src->ctrl_handler, &smiapp_ctrl_ops, V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); @@ -623,6 +604,35 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) return 0; } +/* + * For controls that require information on available media bus codes + * and linke frequencies. + */ +static int smiapp_init_late_controls(struct smiapp_sensor *sensor) +{ + unsigned long *valid_link_freqs = &sensor->valid_link_freqs[ + sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE]; + unsigned int max, i; + + for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { + int max_value = (1 << sensor->csi_format->width) - 1; + + sensor->test_data[i] = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, + &smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i, + 0, max_value, 1, max_value); + } + + for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++); + + sensor->link_freq = v4l2_ctrl_new_int_menu( + &sensor->src->ctrl_handler, &smiapp_ctrl_ops, + V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), + __ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock); + + return sensor->src->ctrl_handler.error; +} + static void smiapp_free_controls(struct smiapp_sensor *sensor) { unsigned int i; @@ -2768,6 +2778,12 @@ static int smiapp_init(struct smiapp_sensor *sensor) if (rval < 0) goto out_cleanup; + rval = smiapp_init_late_controls(sensor); + if (rval) { + rval = -ENODEV; + goto out_cleanup; + } + mutex_lock(&sensor->mutex); rval = smiapp_update_mode(sensor); mutex_unlock(&sensor->mutex); -- cgit v1.2.3 From 5313c00266700d231d9b386d9c0e4faad710c729 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 9 Dec 2014 14:22:31 -0300 Subject: [media] smiapp: Move enumerating available media bus codes later As the controls creation is separated in two sections, the available media bus codes and link frequencies can be enumerated later on. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index fb8f8a85f850..aa27a1b2e1ae 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2703,12 +2703,6 @@ static int smiapp_init(struct smiapp_sensor *sensor) if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; - rval = smiapp_get_mbus_formats(sensor); - if (rval) { - rval = -ENODEV; - goto out_cleanup; - } - for (i = 0; i < SMIAPP_SUBDEVS; i++) { struct { struct smiapp_subdev *ssd; @@ -2778,6 +2772,12 @@ static int smiapp_init(struct smiapp_sensor *sensor) if (rval < 0) goto out_cleanup; + rval = smiapp_get_mbus_formats(sensor); + if (rval) { + rval = -ENODEV; + goto out_cleanup; + } + rval = smiapp_init_late_controls(sensor); if (rval) { rval = -ENODEV; -- cgit v1.2.3 From 0d825a1226466512f44d4a81ce11ad15ca9334b0 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 3 Oct 2014 11:38:32 -0300 Subject: [media] smiapp: Replace pll_flags quirk with more generic init quirk The pll_flags quirk just returned the extra PLL flags the sensor required, but the init quirk is far more versatile. It can be used to perform any extra initialisation needed by the sensor, including allocating memory for sensor specific struct and creating sensor specific new controls. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 5 ++++- drivers/media/i2c/smiapp/smiapp-quirk.c | 8 +++++--- drivers/media/i2c/smiapp/smiapp-quirk.h | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index aa27a1b2e1ae..b3c81257e08d 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2697,7 +2697,6 @@ static int smiapp_init(struct smiapp_sensor *sensor) pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; pll->csi2.lanes = sensor->platform_data->lanes; pll->ext_clk_freq_hz = sensor->platform_data->ext_clk; - pll->flags = smiapp_call_quirk(sensor, pll_flags); pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]; /* Profile 0 sensors have no separate OP clock branch. */ if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) @@ -2772,6 +2771,10 @@ static int smiapp_init(struct smiapp_sensor *sensor) if (rval < 0) goto out_cleanup; + rval = smiapp_call_quirk(sensor, init); + if (rval) + goto out_cleanup; + rval = smiapp_get_mbus_formats(sensor); if (rval) { rval = -ENODEV; diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c index dd4ae6f4ba3e..abf9ea7a0fb7 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.c +++ b/drivers/media/i2c/smiapp/smiapp-quirk.c @@ -214,9 +214,11 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor) return smiapp_write_8(sensor, 0x3328, 0x80); } -static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor) +static int jt8ev1_init(struct smiapp_sensor *sensor) { - return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + + return 0; } const struct smiapp_quirk smiapp_jt8ev1_quirk = { @@ -224,7 +226,7 @@ const struct smiapp_quirk smiapp_jt8ev1_quirk = { .post_poweron = jt8ev1_post_poweron, .pre_streamon = jt8ev1_pre_streamon, .post_streamoff = jt8ev1_post_streamoff, - .pll_flags = jt8ev1_pll_flags, + .init = jt8ev1_init, }; static int tcm8500md_limits(struct smiapp_sensor *sensor) diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h index 3a3c3e57515f..a24eb435eb28 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.h +++ b/drivers/media/i2c/smiapp/smiapp-quirk.h @@ -29,6 +29,9 @@ struct smiapp_sensor; * @post_poweron: Called always after the sensor has been fully powered on. * @pre_streamon: Called just before streaming is enabled. * @post_streamon: Called right after stopping streaming. + * @pll_flags: Return flags for the PLL calculator. + * @init: Quirk initialisation, called the last in probe(). This is + * also appropriate for adding sensor specific controls, for instance. * @reg_access: Register access quirk. The quirk may divert the access * to another register, or no register at all. * @@ -47,6 +50,7 @@ struct smiapp_quirk { int (*pre_streamon)(struct smiapp_sensor *sensor); int (*post_streamoff)(struct smiapp_sensor *sensor); unsigned long (*pll_flags)(struct smiapp_sensor *sensor); + int (*init)(struct smiapp_sensor *sensor); int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg, u32 *val); unsigned long flags; -- cgit v1.2.3 From 3b1635e02e524e2cc7bded4b998d35074b68065e Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 9 Dec 2014 18:43:16 -0300 Subject: [media] smiapp: Add parentheses to macro arguments used in macros This makes the macros a little bit safer. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-quirk.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h index a24eb435eb28..dac5566a2f7a 100644 --- a/drivers/media/i2c/smiapp/smiapp-quirk.h +++ b/drivers/media/i2c/smiapp/smiapp-quirk.h @@ -72,14 +72,14 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor, .val = _val, \ } -#define smiapp_call_quirk(_sensor, _quirk, ...) \ - (_sensor->minfo.quirk && \ - _sensor->minfo.quirk->_quirk ? \ - _sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0) +#define smiapp_call_quirk(sensor, _quirk, ...) \ + ((sensor)->minfo.quirk && \ + (sensor)->minfo.quirk->_quirk ? \ + (sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0) -#define smiapp_needs_quirk(_sensor, _quirk) \ - (_sensor->minfo.quirk ? \ - _sensor->minfo.quirk->flags & _quirk : 0) +#define smiapp_needs_quirk(sensor, _quirk) \ + ((sensor)->minfo.quirk ? \ + (sensor)->minfo.quirk->flags & _quirk : 0) extern const struct smiapp_quirk smiapp_jt8ev1_quirk; extern const struct smiapp_quirk smiapp_imx125es_quirk; -- cgit v1.2.3 From 417d2e507edcb5cf15eb344f86bd3dd28737f24e Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 9 Dec 2014 16:43:44 -0300 Subject: [media] media: platform: add VPFE capture driver support for AM437X This patch adds Video Processing Front End (VPFE) driver for AM437X family of devices Driver supports the following: - V4L2 API using MMAP buffer access based on videobuf2 api - Asynchronous sensor/decoder sub device registration - DT support Signed-off-by: Benoit Parrot Signed-off-by: Darren Etheridge Signed-off-by: Lad, Prabhakar [hans.verkuil@cisco.com: swapped two lines to fix vpfe_release() & add pinctrl include] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/ti-am437x-vpfe.txt | 61 + MAINTAINERS | 9 + drivers/media/platform/Kconfig | 1 + drivers/media/platform/Makefile | 2 + drivers/media/platform/am437x/Kconfig | 11 + drivers/media/platform/am437x/Makefile | 3 + drivers/media/platform/am437x/am437x-vpfe.c | 2778 ++++++++++++++++++++ drivers/media/platform/am437x/am437x-vpfe.h | 283 ++ drivers/media/platform/am437x/am437x-vpfe_regs.h | 140 + include/uapi/linux/Kbuild | 1 + include/uapi/linux/am437x-vpfe.h | 122 + 11 files changed, 3411 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt create mode 100644 drivers/media/platform/am437x/Kconfig create mode 100644 drivers/media/platform/am437x/Makefile create mode 100644 drivers/media/platform/am437x/am437x-vpfe.c create mode 100644 drivers/media/platform/am437x/am437x-vpfe.h create mode 100644 drivers/media/platform/am437x/am437x-vpfe_regs.h create mode 100644 include/uapi/linux/am437x-vpfe.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt b/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt new file mode 100644 index 000000000000..3932e766553a --- /dev/null +++ b/Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt @@ -0,0 +1,61 @@ +Texas Instruments AM437x CAMERA (VPFE) +-------------------------------------- + +The Video Processing Front End (VPFE) is a key component for image capture +applications. The capture module provides the system interface and the +processing capability to connect RAW image-sensor modules and video decoders +to the AM437x device. + +Required properties: +- compatible: must be "ti,am437x-vpfe" +- reg: physical base address and length of the registers set for the device; +- interrupts: should contain IRQ line for the VPFE; +- ti,am437x-vpfe-interface: can be one of the following, + 0 - Raw Bayer Interface. + 1 - 8 Bit BT656 Interface. + 2 - 10 Bit BT656 Interface. + 3 - YCbCr 8 Bit Interface. + 4 - YCbCr 16 Bit Interface. + +VPFE supports a single port node with parallel bus. It should contain one +'port' child node with child 'endpoint' node. Please refer to the bindings +defined in Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + vpfe: vpfe@f0034000 { + compatible = "ti,am437x-vpfe"; + reg = <0x48328000 0x2000>; + interrupts = ; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe_pins_default>; + pinctrl-1 = <&vpfe_pins_sleep>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + vpfe0_ep: endpoint { + remote-endpoint = <&ov2659_1>; + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; + }; + + i2c1: i2c@4802a000 { + + ov2659@30 { + compatible = "ti,ov2659"; + reg = <0x30>; + + port { + ov2659_1: endpoint { + remote-endpoint = <&vpfe0_ep>; + bus-width = <8>; + mclk-frequency = <12000000>; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index dc2d91252d8b..4318f348dbd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8745,6 +8745,15 @@ S: Maintained F: drivers/media/platform/davinci/ F: include/media/davinci/ +TI AM437X VPFE DRIVER +M: Lad, Prabhakar +L: linux-media@vger.kernel.org +W: http://linuxtv.org/ +Q: http://patchwork.linuxtv.org/project/linux-media/list/ +T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git +S: Maintained +F: drivers/media/platform/am437x/ + SIS 190 ETHERNET DRIVER M: Francois Romieu L: netdev@vger.kernel.org diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 480a174832a6..71e8873ceb94 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -118,6 +118,7 @@ config VIDEO_S3C_CAMIF source "drivers/media/platform/soc_camera/Kconfig" source "drivers/media/platform/exynos4-is/Kconfig" source "drivers/media/platform/s5p-tv/Kconfig" +source "drivers/media/platform/am437x/Kconfig" endif # V4L_PLATFORM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index a49936b8ce8a..3ec154742083 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -46,4 +46,6 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ obj-y += omap/ +obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/ + ccflags-y += -I$(srctree)/drivers/media/i2c diff --git a/drivers/media/platform/am437x/Kconfig b/drivers/media/platform/am437x/Kconfig new file mode 100644 index 000000000000..7b023a76e32e --- /dev/null +++ b/drivers/media/platform/am437x/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_AM437X_VPFE + tristate "TI AM437x VPFE video capture driver" + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on SOC_AM43XX || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + help + Support for AM437x Video Processing Front End based Video + Capture Driver. + + To compile this driver as a module, choose M here. The module + will be called am437x-vpfe. diff --git a/drivers/media/platform/am437x/Makefile b/drivers/media/platform/am437x/Makefile new file mode 100644 index 000000000000..d11fff16f260 --- /dev/null +++ b/drivers/media/platform/am437x/Makefile @@ -0,0 +1,3 @@ +# Makefile for AM437x VPFE driver + +obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x-vpfe.o diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c new file mode 100644 index 000000000000..e01ac22d6244 --- /dev/null +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -0,0 +1,2778 @@ +/* + * TI VPFE capture Driver + * + * Copyright (C) 2013 - 2014 Texas Instruments, Inc. + * + * Benoit Parrot + * Lad, Prabhakar + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "am437x-vpfe.h" + +#define VPFE_MODULE_NAME "vpfe" +#define VPFE_VERSION "0.1.0" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-8"); + +#define vpfe_dbg(level, dev, fmt, arg...) \ + v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ##arg) +#define vpfe_info(dev, fmt, arg...) \ + v4l2_info(&dev->v4l2_dev, fmt, ##arg) +#define vpfe_err(dev, fmt, arg...) \ + v4l2_err(&dev->v4l2_dev, fmt, ##arg) + +/* standard information */ +struct vpfe_standard { + v4l2_std_id std_id; + unsigned int width; + unsigned int height; + struct v4l2_fract pixelaspect; + int frame_format; +}; + +const struct vpfe_standard vpfe_standards[] = { + {V4L2_STD_525_60, 720, 480, {11, 10}, 1}, + {V4L2_STD_625_50, 720, 576, {54, 59}, 1}, +}; + +struct bus_format { + unsigned int width; + unsigned int bpp; +}; + +/* + * struct vpfe_fmt - VPFE media bus format information + * @name: V4L2 format description + * @code: V4L2 media bus format code + * @shifted: V4L2 media bus format code for the same pixel layout but + * shifted to be 8 bits per pixel. =0 if format is not shiftable. + * @pixelformat: V4L2 pixel format FCC identifier + * @width: Bits per pixel (when transferred over a bus) + * @bpp: Bytes per pixel (when stored in memory) + * @supported: Indicates format supported by subdev + */ +struct vpfe_fmt { + const char *name; + u32 fourcc; + u32 code; + struct bus_format l; + struct bus_format s; + bool supported; + u32 index; +}; + +static struct vpfe_fmt formats[] = { + { + .name = "YUV 4:2:2 packed, YCbYCr", + .fourcc = V4L2_PIX_FMT_YUYV, + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, { + .name = "YUV 4:2:2 packed, CbYCrY", + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, { + .name = "YUV 4:2:2 packed, YCrYCb", + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, { + .name = "YUV 4:2:2 packed, CrYCbY", + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, { + .name = "RAW8 BGGR", + .fourcc = V4L2_PIX_FMT_SBGGR8, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .l.width = 10, + .l.bpp = 2, + .s.width = 8, + .s.bpp = 1, + .supported = false, + }, { + .name = "RAW8 GBRG", + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .l.width = 10, + .l.bpp = 2, + .s.width = 8, + .s.bpp = 1, + .supported = false, + }, { + .name = "RAW8 GRBG", + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .l.width = 10, + .l.bpp = 2, + .s.width = 8, + .s.bpp = 1, + .supported = false, + }, { + .name = "RAW8 RGGB", + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .l.width = 10, + .l.bpp = 2, + .s.width = 8, + .s.bpp = 1, + .supported = false, + }, { + .name = "RGB565 (LE)", + .fourcc = V4L2_PIX_FMT_RGB565, + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, { + .name = "RGB565 (BE)", + .fourcc = V4L2_PIX_FMT_RGB565X, + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .l.width = 10, + .l.bpp = 4, + .s.width = 8, + .s.bpp = 2, + .supported = false, + }, +}; + +static int +__vpfe_get_format(struct vpfe_device *vpfe, + struct v4l2_format *format, unsigned int *bpp); + +static struct vpfe_fmt *find_format_by_code(unsigned int code) +{ + struct vpfe_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->code == code) + return fmt; + } + + return NULL; +} + +static struct vpfe_fmt *find_format_by_pix(unsigned int pixelformat) +{ + struct vpfe_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} + +static void +mbus_to_pix(struct vpfe_device *vpfe, + const struct v4l2_mbus_framefmt *mbus, + struct v4l2_pix_format *pix, unsigned int *bpp) +{ + struct vpfe_subdev_info *sdinfo = vpfe->current_subdev; + unsigned int bus_width = sdinfo->vpfe_param.bus_width; + struct vpfe_fmt *fmt; + + fmt = find_format_by_code(mbus->code); + if (WARN_ON(fmt == NULL)) { + pr_err("Invalid mbus code set\n"); + *bpp = 1; + return; + } + + memset(pix, 0, sizeof(*pix)); + v4l2_fill_pix_format(pix, mbus); + pix->pixelformat = fmt->fourcc; + *bpp = (bus_width == 10) ? fmt->l.bpp : fmt->s.bpp; + + /* pitch should be 32 bytes aligned */ + pix->bytesperline = ALIGN(pix->width * *bpp, 32); + pix->sizeimage = pix->bytesperline * pix->height; +} + +static void pix_to_mbus(struct vpfe_device *vpfe, + struct v4l2_pix_format *pix_fmt, + struct v4l2_mbus_framefmt *mbus_fmt) +{ + struct vpfe_fmt *fmt; + + fmt = find_format_by_pix(pix_fmt->pixelformat); + if (!fmt) { + /* default to first entry */ + vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n", + pix_fmt->pixelformat); + fmt = &formats[0]; + } + + memset(mbus_fmt, 0, sizeof(*mbus_fmt)); + v4l2_fill_mbus_format(mbus_fmt, pix_fmt, fmt->code); +} + +/* Print Four-character-code (FOURCC) */ +static char *print_fourcc(u32 fmt) +{ + static char code[5]; + + code[0] = (unsigned char)(fmt & 0xff); + code[1] = (unsigned char)((fmt >> 8) & 0xff); + code[2] = (unsigned char)((fmt >> 16) & 0xff); + code[3] = (unsigned char)((fmt >> 24) & 0xff); + code[4] = '\0'; + + return code; +} + +static int +cmp_v4l2_format(const struct v4l2_format *lhs, const struct v4l2_format *rhs) +{ + return lhs->type == rhs->type && + lhs->fmt.pix.width == rhs->fmt.pix.width && + lhs->fmt.pix.height == rhs->fmt.pix.height && + lhs->fmt.pix.pixelformat == rhs->fmt.pix.pixelformat && + lhs->fmt.pix.field == rhs->fmt.pix.field && + lhs->fmt.pix.colorspace == rhs->fmt.pix.colorspace && + lhs->fmt.pix.ycbcr_enc == rhs->fmt.pix.ycbcr_enc && + lhs->fmt.pix.quantization == rhs->fmt.pix.quantization; +} + +static inline u32 vpfe_reg_read(struct vpfe_ccdc *ccdc, u32 offset) +{ + return ioread32(ccdc->ccdc_cfg.base_addr + offset); +} + +static inline void vpfe_reg_write(struct vpfe_ccdc *ccdc, u32 val, u32 offset) +{ + iowrite32(val, ccdc->ccdc_cfg.base_addr + offset); +} + +static inline struct vpfe_device *to_vpfe(struct vpfe_ccdc *ccdc) +{ + return container_of(ccdc, struct vpfe_device, ccdc); +} + +static inline struct vpfe_cap_buffer *to_vpfe_buffer(struct vb2_buffer *vb) +{ + return container_of(vb, struct vpfe_cap_buffer, vb); +} + +static inline void vpfe_pcr_enable(struct vpfe_ccdc *ccdc, int flag) +{ + vpfe_reg_write(ccdc, !!flag, VPFE_PCR); +} + +static void vpfe_config_enable(struct vpfe_ccdc *ccdc, int flag) +{ + unsigned int cfg; + + if (!flag) { + cfg = vpfe_reg_read(ccdc, VPFE_CONFIG); + cfg &= ~(VPFE_CONFIG_EN_ENABLE << VPFE_CONFIG_EN_SHIFT); + } else { + cfg = VPFE_CONFIG_EN_ENABLE << VPFE_CONFIG_EN_SHIFT; + } + + vpfe_reg_write(ccdc, cfg, VPFE_CONFIG); +} + +static void vpfe_ccdc_setwin(struct vpfe_ccdc *ccdc, + struct v4l2_rect *image_win, + enum ccdc_frmfmt frm_fmt, + int bpp) +{ + int horz_start, horz_nr_pixels; + int vert_start, vert_nr_lines; + int val, mid_img; + + /* + * ppc - per pixel count. indicates how many pixels per cell + * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. + * raw capture this is 1 + */ + horz_start = image_win->left * bpp; + horz_nr_pixels = (image_win->width * bpp) - 1; + vpfe_reg_write(ccdc, (horz_start << VPFE_HORZ_INFO_SPH_SHIFT) | + horz_nr_pixels, VPFE_HORZ_INFO); + + vert_start = image_win->top; + + if (frm_fmt == CCDC_FRMFMT_INTERLACED) { + vert_nr_lines = (image_win->height >> 1) - 1; + vert_start >>= 1; + /* Since first line doesn't have any data */ + vert_start += 1; + /* configure VDINT0 */ + val = (vert_start << VPFE_VDINT_VDINT0_SHIFT); + } else { + /* Since first line doesn't have any data */ + vert_start += 1; + vert_nr_lines = image_win->height - 1; + /* + * configure VDINT0 and VDINT1. VDINT1 will be at half + * of image height + */ + mid_img = vert_start + (image_win->height / 2); + val = (vert_start << VPFE_VDINT_VDINT0_SHIFT) | + (mid_img & VPFE_VDINT_VDINT1_MASK); + } + + vpfe_reg_write(ccdc, val, VPFE_VDINT); + + vpfe_reg_write(ccdc, (vert_start << VPFE_VERT_START_SLV0_SHIFT) | + vert_start, VPFE_VERT_START); + vpfe_reg_write(ccdc, vert_nr_lines, VPFE_VERT_LINES); +} + +static void vpfe_reg_dump(struct vpfe_ccdc *ccdc) +{ + struct vpfe_device *vpfe = to_vpfe(ccdc); + + vpfe_dbg(3, vpfe, "ALAW: 0x%x\n", vpfe_reg_read(ccdc, VPFE_ALAW)); + vpfe_dbg(3, vpfe, "CLAMP: 0x%x\n", vpfe_reg_read(ccdc, VPFE_CLAMP)); + vpfe_dbg(3, vpfe, "DCSUB: 0x%x\n", vpfe_reg_read(ccdc, VPFE_DCSUB)); + vpfe_dbg(3, vpfe, "BLKCMP: 0x%x\n", vpfe_reg_read(ccdc, VPFE_BLKCMP)); + vpfe_dbg(3, vpfe, "COLPTN: 0x%x\n", vpfe_reg_read(ccdc, VPFE_COLPTN)); + vpfe_dbg(3, vpfe, "SDOFST: 0x%x\n", vpfe_reg_read(ccdc, VPFE_SDOFST)); + vpfe_dbg(3, vpfe, "SYN_MODE: 0x%x\n", + vpfe_reg_read(ccdc, VPFE_SYNMODE)); + vpfe_dbg(3, vpfe, "HSIZE_OFF: 0x%x\n", + vpfe_reg_read(ccdc, VPFE_HSIZE_OFF)); + vpfe_dbg(3, vpfe, "HORZ_INFO: 0x%x\n", + vpfe_reg_read(ccdc, VPFE_HORZ_INFO)); + vpfe_dbg(3, vpfe, "VERT_START: 0x%x\n", + vpfe_reg_read(ccdc, VPFE_VERT_START)); + vpfe_dbg(3, vpfe, "VERT_LINES: 0x%x\n", + vpfe_reg_read(ccdc, VPFE_VERT_LINES)); +} + +static int +vpfe_ccdc_validate_param(struct vpfe_ccdc *ccdc, + struct vpfe_ccdc_config_params_raw *ccdcparam) +{ + struct vpfe_device *vpfe = to_vpfe(ccdc); + u8 max_gamma, max_data; + + if (!ccdcparam->alaw.enable) + return 0; + + max_gamma = ccdc_gamma_width_max_bit(ccdcparam->alaw.gamma_wd); + max_data = ccdc_data_size_max_bit(ccdcparam->data_sz); + + if (ccdcparam->alaw.gamma_wd > VPFE_CCDC_GAMMA_BITS_09_0 || + ccdcparam->alaw.gamma_wd < VPFE_CCDC_GAMMA_BITS_15_6 || + max_gamma > max_data) { + vpfe_dbg(1, vpfe, "Invalid data line select\n"); + return -EINVAL; + } + + return 0; +} + +static void +vpfe_ccdc_update_raw_params(struct vpfe_ccdc *ccdc, + struct vpfe_ccdc_config_params_raw *raw_params) +{ + struct vpfe_ccdc_config_params_raw *config_params = + &ccdc->ccdc_cfg.bayer.config_params; + + config_params = raw_params; +} + +/* + * vpfe_ccdc_restore_defaults() + * This function will write defaults to all CCDC registers + */ +static void vpfe_ccdc_restore_defaults(struct vpfe_ccdc *ccdc) +{ + int i; + + /* Disable CCDC */ + vpfe_pcr_enable(ccdc, 0); + + /* set all registers to default value */ + for (i = 4; i <= 0x94; i += 4) + vpfe_reg_write(ccdc, 0, i); + + vpfe_reg_write(ccdc, VPFE_NO_CULLING, VPFE_CULLING); + vpfe_reg_write(ccdc, VPFE_CCDC_GAMMA_BITS_11_2, VPFE_ALAW); +} + +static int vpfe_ccdc_close(struct vpfe_ccdc *ccdc, struct device *dev) +{ + int dma_cntl, i, pcr; + + /* If the CCDC module is still busy wait for it to be done */ + for (i = 0; i < 10; i++) { + usleep_range(5000, 6000); + pcr = vpfe_reg_read(ccdc, VPFE_PCR); + if (!pcr) + break; + + /* make sure it it is disabled */ + vpfe_pcr_enable(ccdc, 0); + } + + /* Disable CCDC by resetting all register to default POR values */ + vpfe_ccdc_restore_defaults(ccdc); + + /* if DMA_CNTL overflow bit is set. Clear it + * It appears to take a while for this to become quiescent ~20ms + */ + for (i = 0; i < 10; i++) { + dma_cntl = vpfe_reg_read(ccdc, VPFE_DMA_CNTL); + if (!(dma_cntl & VPFE_DMA_CNTL_OVERFLOW)) + break; + + /* Clear the overflow bit */ + vpfe_reg_write(ccdc, dma_cntl, VPFE_DMA_CNTL); + usleep_range(5000, 6000); + } + + /* Disabled the module at the CONFIG level */ + vpfe_config_enable(ccdc, 0); + + pm_runtime_put_sync(dev); + + return 0; +} + +static int vpfe_ccdc_set_params(struct vpfe_ccdc *ccdc, void __user *params) +{ + struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc); + struct vpfe_ccdc_config_params_raw raw_params; + int x; + + if (ccdc->ccdc_cfg.if_type != VPFE_RAW_BAYER) + return -EINVAL; + + x = copy_from_user(&raw_params, params, sizeof(raw_params)); + if (x) { + vpfe_dbg(1, vpfe, + "vpfe_ccdc_set_params: error in copying ccdc params, %d\n", + x); + return -EFAULT; + } + + if (!vpfe_ccdc_validate_param(ccdc, &raw_params)) { + vpfe_ccdc_update_raw_params(ccdc, &raw_params); + return 0; + } + + return -EINVAL; +} + +/* + * vpfe_ccdc_config_ycbcr() + * This function will configure CCDC for YCbCr video capture + */ +static void vpfe_ccdc_config_ycbcr(struct vpfe_ccdc *ccdc) +{ + struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc); + struct ccdc_params_ycbcr *params = &ccdc->ccdc_cfg.ycbcr; + u32 syn_mode; + + vpfe_dbg(3, vpfe, "vpfe_ccdc_config_ycbcr:\n"); + /* + * first restore the CCDC registers to default values + * This is important since we assume default values to be set in + * a lot of registers that we didn't touch + */ + vpfe_ccdc_restore_defaults(ccdc); + + /* + * configure pixel format, frame format, configure video frame + * format, enable output to SDRAM, enable internal timing generator + * and 8bit pack mode + */ + syn_mode = (((params->pix_fmt & VPFE_SYN_MODE_INPMOD_MASK) << + VPFE_SYN_MODE_INPMOD_SHIFT) | + ((params->frm_fmt & VPFE_SYN_FLDMODE_MASK) << + VPFE_SYN_FLDMODE_SHIFT) | VPFE_VDHDEN_ENABLE | + VPFE_WEN_ENABLE | VPFE_DATA_PACK_ENABLE); + + /* setup BT.656 sync mode */ + if (params->bt656_enable) { + vpfe_reg_write(ccdc, VPFE_REC656IF_BT656_EN, VPFE_REC656IF); + + /* + * configure the FID, VD, HD pin polarity, + * fld,hd pol positive, vd negative, 8-bit data + */ + syn_mode |= VPFE_SYN_MODE_VD_POL_NEGATIVE; + if (ccdc->ccdc_cfg.if_type == VPFE_BT656_10BIT) + syn_mode |= VPFE_SYN_MODE_10BITS; + else + syn_mode |= VPFE_SYN_MODE_8BITS; + } else { + /* y/c external sync mode */ + syn_mode |= (((params->fid_pol & VPFE_FID_POL_MASK) << + VPFE_FID_POL_SHIFT) | + ((params->hd_pol & VPFE_HD_POL_MASK) << + VPFE_HD_POL_SHIFT) | + ((params->vd_pol & VPFE_VD_POL_MASK) << + VPFE_VD_POL_SHIFT)); + } + vpfe_reg_write(ccdc, syn_mode, VPFE_SYNMODE); + + /* configure video window */ + vpfe_ccdc_setwin(ccdc, ¶ms->win, + params->frm_fmt, params->bytesperpixel); + + /* + * configure the order of y cb cr in SDRAM, and disable latch + * internal register on vsync + */ + if (ccdc->ccdc_cfg.if_type == VPFE_BT656_10BIT) + vpfe_reg_write(ccdc, + (params->pix_order << VPFE_CCDCFG_Y8POS_SHIFT) | + VPFE_LATCH_ON_VSYNC_DISABLE | + VPFE_CCDCFG_BW656_10BIT, VPFE_CCDCFG); + else + vpfe_reg_write(ccdc, + (params->pix_order << VPFE_CCDCFG_Y8POS_SHIFT) | + VPFE_LATCH_ON_VSYNC_DISABLE, VPFE_CCDCFG); + + /* + * configure the horizontal line offset. This should be a + * on 32 byte boundary. So clear LSB 5 bits + */ + vpfe_reg_write(ccdc, params->bytesperline, VPFE_HSIZE_OFF); + + /* configure the memory line offset */ + if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) + /* two fields are interleaved in memory */ + vpfe_reg_write(ccdc, VPFE_SDOFST_FIELD_INTERLEAVED, + VPFE_SDOFST); +} + +static void +vpfe_ccdc_config_black_clamp(struct vpfe_ccdc *ccdc, + struct vpfe_ccdc_black_clamp *bclamp) +{ + u32 val; + + if (!bclamp->enable) { + /* configure DCSub */ + val = (bclamp->dc_sub) & VPFE_BLK_DC_SUB_MASK; + vpfe_reg_write(ccdc, val, VPFE_DCSUB); + vpfe_reg_write(ccdc, VPFE_CLAMP_DEFAULT_VAL, VPFE_CLAMP); + return; + } + /* + * Configure gain, Start pixel, No of line to be avg, + * No of pixel/line to be avg, & Enable the Black clamping + */ + val = ((bclamp->sgain & VPFE_BLK_SGAIN_MASK) | + ((bclamp->start_pixel & VPFE_BLK_ST_PXL_MASK) << + VPFE_BLK_ST_PXL_SHIFT) | + ((bclamp->sample_ln & VPFE_BLK_SAMPLE_LINE_MASK) << + VPFE_BLK_SAMPLE_LINE_SHIFT) | + ((bclamp->sample_pixel & VPFE_BLK_SAMPLE_LN_MASK) << + VPFE_BLK_SAMPLE_LN_SHIFT) | VPFE_BLK_CLAMP_ENABLE); + vpfe_reg_write(ccdc, val, VPFE_CLAMP); + /* If Black clamping is enable then make dcsub 0 */ + vpfe_reg_write(ccdc, VPFE_DCSUB_DEFAULT_VAL, VPFE_DCSUB); +} + +static void +vpfe_ccdc_config_black_compense(struct vpfe_ccdc *ccdc, + struct vpfe_ccdc_black_compensation *bcomp) +{ + u32 val; + + val = ((bcomp->b & VPFE_BLK_COMP_MASK) | + ((bcomp->gb & VPFE_BLK_COMP_MASK) << + VPFE_BLK_COMP_GB_COMP_SHIFT) | + ((bcomp->gr & VPFE_BLK_COMP_MASK) << + VPFE_BLK_COMP_GR_COMP_SHIFT) | + ((bcomp->r & VPFE_BLK_COMP_MASK) << + VPFE_BLK_COMP_R_COMP_SHIFT)); + vpfe_reg_write(ccdc, val, VPFE_BLKCMP); +} + +/* + * vpfe_ccdc_config_raw() + * This function will configure CCDC for Raw capture mode + */ +static void vpfe_ccdc_config_raw(struct vpfe_ccdc *ccdc) +{ + struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc); + struct vpfe_ccdc_config_params_raw *config_params = + &ccdc->ccdc_cfg.bayer.config_params; + struct ccdc_params_raw *params = &ccdc->ccdc_cfg.bayer; + unsigned int syn_mode; + unsigned int val; + + vpfe_dbg(3, vpfe, "vpfe_ccdc_config_raw:\n"); + + /* Reset CCDC */ + vpfe_ccdc_restore_defaults(ccdc); + + /* Disable latching function registers on VSYNC */ + vpfe_reg_write(ccdc, VPFE_LATCH_ON_VSYNC_DISABLE, VPFE_CCDCFG); + + /* + * Configure the vertical sync polarity(SYN_MODE.VDPOL), + * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity + * (SYN_MODE.FLDPOL), frame format(progressive or interlace), + * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output + * SDRAM, enable internal timing generator + */ + syn_mode = (((params->vd_pol & VPFE_VD_POL_MASK) << VPFE_VD_POL_SHIFT) | + ((params->hd_pol & VPFE_HD_POL_MASK) << VPFE_HD_POL_SHIFT) | + ((params->fid_pol & VPFE_FID_POL_MASK) << + VPFE_FID_POL_SHIFT) | ((params->frm_fmt & + VPFE_FRM_FMT_MASK) << VPFE_FRM_FMT_SHIFT) | + ((config_params->data_sz & VPFE_DATA_SZ_MASK) << + VPFE_DATA_SZ_SHIFT) | ((params->pix_fmt & + VPFE_PIX_FMT_MASK) << VPFE_PIX_FMT_SHIFT) | + VPFE_WEN_ENABLE | VPFE_VDHDEN_ENABLE); + + /* Enable and configure aLaw register if needed */ + if (config_params->alaw.enable) { + val = ((config_params->alaw.gamma_wd & + VPFE_ALAW_GAMMA_WD_MASK) | VPFE_ALAW_ENABLE); + vpfe_reg_write(ccdc, val, VPFE_ALAW); + vpfe_dbg(3, vpfe, "\nWriting 0x%x to ALAW...\n", val); + } + + /* Configure video window */ + vpfe_ccdc_setwin(ccdc, ¶ms->win, params->frm_fmt, + params->bytesperpixel); + + /* Configure Black Clamp */ + vpfe_ccdc_config_black_clamp(ccdc, &config_params->blk_clamp); + + /* Configure Black level compensation */ + vpfe_ccdc_config_black_compense(ccdc, &config_params->blk_comp); + + /* If data size is 8 bit then pack the data */ + if ((config_params->data_sz == VPFE_CCDC_DATA_8BITS) || + config_params->alaw.enable) + syn_mode |= VPFE_DATA_PACK_ENABLE; + + /* + * Configure Horizontal offset register. If pack 8 is enabled then + * 1 pixel will take 1 byte + */ + vpfe_reg_write(ccdc, params->bytesperline, VPFE_HSIZE_OFF); + + vpfe_dbg(3, vpfe, "Writing %d (%x) to HSIZE_OFF\n", + params->bytesperline, params->bytesperline); + + /* Set value for SDOFST */ + if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { + if (params->image_invert_enable) { + /* For interlace inverse mode */ + vpfe_reg_write(ccdc, VPFE_INTERLACED_IMAGE_INVERT, + VPFE_SDOFST); + } else { + /* For interlace non inverse mode */ + vpfe_reg_write(ccdc, VPFE_INTERLACED_NO_IMAGE_INVERT, + VPFE_SDOFST); + } + } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { + vpfe_reg_write(ccdc, VPFE_PROGRESSIVE_NO_IMAGE_INVERT, + VPFE_SDOFST); + } + + vpfe_reg_write(ccdc, syn_mode, VPFE_SYNMODE); + + vpfe_reg_dump(ccdc); +} + +static inline int +vpfe_ccdc_set_buftype(struct vpfe_ccdc *ccdc, + enum ccdc_buftype buf_type) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + ccdc->ccdc_cfg.bayer.buf_type = buf_type; + else + ccdc->ccdc_cfg.ycbcr.buf_type = buf_type; + + return 0; +} + +static inline enum ccdc_buftype vpfe_ccdc_get_buftype(struct vpfe_ccdc *ccdc) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + return ccdc->ccdc_cfg.bayer.buf_type; + + return ccdc->ccdc_cfg.ycbcr.buf_type; +} + +static int vpfe_ccdc_set_pixel_format(struct vpfe_ccdc *ccdc, u32 pixfmt) +{ + struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc); + + vpfe_dbg(1, vpfe, "vpfe_ccdc_set_pixel_format: if_type: %d, pixfmt:%s\n", + ccdc->ccdc_cfg.if_type, print_fourcc(pixfmt)); + + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) { + ccdc->ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; + /* + * Need to clear it in case it was left on + * after the last capture. + */ + ccdc->ccdc_cfg.bayer.config_params.alaw.enable = 0; + + switch (pixfmt) { + case V4L2_PIX_FMT_SBGGR8: + ccdc->ccdc_cfg.bayer.config_params.alaw.enable = 1; + break; + + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_RGB565X: + break; + + case V4L2_PIX_FMT_SBGGR16: + default: + return -EINVAL; + } + } else { + switch (pixfmt) { + case V4L2_PIX_FMT_YUYV: + ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; + break; + + case V4L2_PIX_FMT_UYVY: + ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; + break; + + default: + return -EINVAL; + } + } + + return 0; +} + +static u32 vpfe_ccdc_get_pixel_format(struct vpfe_ccdc *ccdc) +{ + u32 pixfmt; + + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) { + pixfmt = V4L2_PIX_FMT_YUYV; + } else { + if (ccdc->ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) + pixfmt = V4L2_PIX_FMT_YUYV; + else + pixfmt = V4L2_PIX_FMT_UYVY; + } + + return pixfmt; +} + +static int +vpfe_ccdc_set_image_window(struct vpfe_ccdc *ccdc, + struct v4l2_rect *win, unsigned int bpp) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) { + ccdc->ccdc_cfg.bayer.win = *win; + ccdc->ccdc_cfg.bayer.bytesperpixel = bpp; + ccdc->ccdc_cfg.bayer.bytesperline = ALIGN(win->width * bpp, 32); + } else { + ccdc->ccdc_cfg.ycbcr.win = *win; + ccdc->ccdc_cfg.ycbcr.bytesperpixel = bpp; + ccdc->ccdc_cfg.ycbcr.bytesperline = ALIGN(win->width * bpp, 32); + } + + return 0; +} + +static inline void +vpfe_ccdc_get_image_window(struct vpfe_ccdc *ccdc, + struct v4l2_rect *win) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + *win = ccdc->ccdc_cfg.bayer.win; + else + *win = ccdc->ccdc_cfg.ycbcr.win; +} + +static inline unsigned int vpfe_ccdc_get_line_length(struct vpfe_ccdc *ccdc) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + return ccdc->ccdc_cfg.bayer.bytesperline; + + return ccdc->ccdc_cfg.ycbcr.bytesperline; +} + +static inline int +vpfe_ccdc_set_frame_format(struct vpfe_ccdc *ccdc, + enum ccdc_frmfmt frm_fmt) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + ccdc->ccdc_cfg.bayer.frm_fmt = frm_fmt; + else + ccdc->ccdc_cfg.ycbcr.frm_fmt = frm_fmt; + + return 0; +} + +static inline enum ccdc_frmfmt +vpfe_ccdc_get_frame_format(struct vpfe_ccdc *ccdc) +{ + if (ccdc->ccdc_cfg.if_type == VPFE_RAW_BAYER) + return ccdc->ccdc_cfg.bayer.frm_fmt; + + return ccdc->ccdc_cfg.ycbcr.frm_fmt; +} + +static inline int vpfe_ccdc_getfid(struct vpfe_ccdc *ccdc) +{ + return (vpfe_reg_read(ccdc, VPFE_SYNMODE) >> 15) & 1; +} + +static inline void vpfe_set_sdr_addr(struct vpfe_ccdc *ccdc, unsigned long addr) +{ + vpfe_reg_write(ccdc, addr & 0xffffffe0, VPFE_SDR_ADDR); +} + +static int vpfe_ccdc_set_hw_if_params(struct vpfe_ccdc *ccdc, + struct vpfe_hw_if_param *params) +{ + struct vpfe_device *vpfe = container_of(ccdc, struct vpfe_device, ccdc); + + ccdc->ccdc_cfg.if_type = params->if_type; + + switch (params->if_type) { + case VPFE_BT656: + case VPFE_YCBCR_SYNC_16: + case VPFE_YCBCR_SYNC_8: + case VPFE_BT656_10BIT: + ccdc->ccdc_cfg.ycbcr.vd_pol = params->vdpol; + ccdc->ccdc_cfg.ycbcr.hd_pol = params->hdpol; + break; + + case VPFE_RAW_BAYER: + ccdc->ccdc_cfg.bayer.vd_pol = params->vdpol; + ccdc->ccdc_cfg.bayer.hd_pol = params->hdpol; + if (params->bus_width == 10) + ccdc->ccdc_cfg.bayer.config_params.data_sz = + VPFE_CCDC_DATA_10BITS; + else + ccdc->ccdc_cfg.bayer.config_params.data_sz = + VPFE_CCDC_DATA_8BITS; + vpfe_dbg(1, vpfe, "params.bus_width: %d\n", + params->bus_width); + vpfe_dbg(1, vpfe, "config_params.data_sz: %d\n", + ccdc->ccdc_cfg.bayer.config_params.data_sz); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static void vpfe_clear_intr(struct vpfe_ccdc *ccdc, int vdint) +{ + unsigned int vpfe_int_status; + + vpfe_int_status = vpfe_reg_read(ccdc, VPFE_IRQ_STS); + + switch (vdint) { + /* VD0 interrupt */ + case VPFE_VDINT0: + vpfe_int_status &= ~VPFE_VDINT0; + vpfe_int_status |= VPFE_VDINT0; + break; + + /* VD1 interrupt */ + case VPFE_VDINT1: + vpfe_int_status &= ~VPFE_VDINT1; + vpfe_int_status |= VPFE_VDINT1; + break; + + /* VD2 interrupt */ + case VPFE_VDINT2: + vpfe_int_status &= ~VPFE_VDINT2; + vpfe_int_status |= VPFE_VDINT2; + break; + + /* Clear all interrupts */ + default: + vpfe_int_status &= ~(VPFE_VDINT0 | + VPFE_VDINT1 | + VPFE_VDINT2); + vpfe_int_status |= (VPFE_VDINT0 | + VPFE_VDINT1 | + VPFE_VDINT2); + break; + } + /* Clear specific VDINT from the status register */ + vpfe_reg_write(ccdc, vpfe_int_status, VPFE_IRQ_STS); + + vpfe_int_status = vpfe_reg_read(ccdc, VPFE_IRQ_STS); + + /* Acknowledge that we are done with all interrupts */ + vpfe_reg_write(ccdc, 1, VPFE_IRQ_EOI); +} + +static void vpfe_ccdc_config_defaults(struct vpfe_ccdc *ccdc) +{ + ccdc->ccdc_cfg.if_type = VPFE_RAW_BAYER; + + ccdc->ccdc_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT; + ccdc->ccdc_cfg.ycbcr.frm_fmt = CCDC_FRMFMT_INTERLACED; + ccdc->ccdc_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE; + ccdc->ccdc_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE; + ccdc->ccdc_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE; + ccdc->ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; + ccdc->ccdc_cfg.ycbcr.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED; + + ccdc->ccdc_cfg.ycbcr.win.left = 0; + ccdc->ccdc_cfg.ycbcr.win.top = 0; + ccdc->ccdc_cfg.ycbcr.win.width = 720; + ccdc->ccdc_cfg.ycbcr.win.height = 576; + ccdc->ccdc_cfg.ycbcr.bt656_enable = 1; + + ccdc->ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; + ccdc->ccdc_cfg.bayer.frm_fmt = CCDC_FRMFMT_PROGRESSIVE; + ccdc->ccdc_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE; + ccdc->ccdc_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE; + ccdc->ccdc_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE; + + ccdc->ccdc_cfg.bayer.win.left = 0; + ccdc->ccdc_cfg.bayer.win.top = 0; + ccdc->ccdc_cfg.bayer.win.width = 800; + ccdc->ccdc_cfg.bayer.win.height = 600; + ccdc->ccdc_cfg.bayer.config_params.data_sz = VPFE_CCDC_DATA_8BITS; + ccdc->ccdc_cfg.bayer.config_params.alaw.gamma_wd = + VPFE_CCDC_GAMMA_BITS_09_0; +} + +/* + * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings + */ +static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe, + struct v4l2_format *f) +{ + struct v4l2_rect image_win; + enum ccdc_buftype buf_type; + enum ccdc_frmfmt frm_fmt; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vpfe_ccdc_get_image_window(&vpfe->ccdc, &image_win); + f->fmt.pix.width = image_win.width; + f->fmt.pix.height = image_win.height; + f->fmt.pix.bytesperline = vpfe_ccdc_get_line_length(&vpfe->ccdc); + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * + f->fmt.pix.height; + buf_type = vpfe_ccdc_get_buftype(&vpfe->ccdc); + f->fmt.pix.pixelformat = vpfe_ccdc_get_pixel_format(&vpfe->ccdc); + frm_fmt = vpfe_ccdc_get_frame_format(&vpfe->ccdc); + + if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { + f->fmt.pix.field = V4L2_FIELD_NONE; + } else if (frm_fmt == CCDC_FRMFMT_INTERLACED) { + if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) { + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + } else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) { + f->fmt.pix.field = V4L2_FIELD_SEQ_TB; + } else { + vpfe_err(vpfe, "Invalid buf_type\n"); + return -EINVAL; + } + } else { + vpfe_err(vpfe, "Invalid frm_fmt\n"); + return -EINVAL; + } + return 0; +} + +static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe) +{ + enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; + int ret; + + vpfe_dbg(2, vpfe, "vpfe_config_ccdc_image_format\n"); + + vpfe_dbg(1, vpfe, "pixelformat: %s\n", + print_fourcc(vpfe->fmt.fmt.pix.pixelformat)); + + if (vpfe_ccdc_set_pixel_format(&vpfe->ccdc, + vpfe->fmt.fmt.pix.pixelformat) < 0) { + vpfe_err(vpfe, "couldn't set pix format in ccdc\n"); + return -EINVAL; + } + + /* configure the image window */ + vpfe_ccdc_set_image_window(&vpfe->ccdc, &vpfe->crop, vpfe->bpp); + + switch (vpfe->fmt.fmt.pix.field) { + case V4L2_FIELD_INTERLACED: + /* do nothing, since it is default */ + ret = vpfe_ccdc_set_buftype( + &vpfe->ccdc, + CCDC_BUFTYPE_FLD_INTERLEAVED); + break; + + case V4L2_FIELD_NONE: + frm_fmt = CCDC_FRMFMT_PROGRESSIVE; + /* buffer type only applicable for interlaced scan */ + break; + + case V4L2_FIELD_SEQ_TB: + ret = vpfe_ccdc_set_buftype( + &vpfe->ccdc, + CCDC_BUFTYPE_FLD_SEPARATED); + break; + + default: + return -EINVAL; + } + + if (ret) + return ret; + + return vpfe_ccdc_set_frame_format(&vpfe->ccdc, frm_fmt); +} + +/* + * vpfe_config_image_format() + * For a given standard, this functions sets up the default + * pix format & crop values in the vpfe device and ccdc. It first + * starts with defaults based values from the standard table. + * It then checks if sub device support g_mbus_fmt and then override the + * values based on that.Sets crop values to match with scan resolution + * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the + * values in ccdc + */ +static int vpfe_config_image_format(struct vpfe_device *vpfe, + v4l2_std_id std_id) +{ + struct v4l2_pix_format *pix = &vpfe->fmt.fmt.pix; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) { + if (vpfe_standards[i].std_id & std_id) { + vpfe->std_info.active_pixels = + vpfe_standards[i].width; + vpfe->std_info.active_lines = + vpfe_standards[i].height; + vpfe->std_info.frame_format = + vpfe_standards[i].frame_format; + vpfe->std_index = i; + + break; + } + } + + if (i == ARRAY_SIZE(vpfe_standards)) { + vpfe_err(vpfe, "standard not supported\n"); + return -EINVAL; + } + + vpfe->crop.top = vpfe->crop.left = 0; + vpfe->crop.width = vpfe->std_info.active_pixels; + vpfe->crop.height = vpfe->std_info.active_lines; + pix->width = vpfe->crop.width; + pix->height = vpfe->crop.height; + pix->pixelformat = V4L2_PIX_FMT_YUYV; + + /* first field and frame format based on standard frame format */ + if (vpfe->std_info.frame_format) + pix->field = V4L2_FIELD_INTERLACED; + else + pix->field = V4L2_FIELD_NONE; + + ret = __vpfe_get_format(vpfe, &vpfe->fmt, &vpfe->bpp); + if (ret) + return ret; + + /* Update the crop window based on found values */ + vpfe->crop.width = pix->width; + vpfe->crop.height = pix->height; + + return vpfe_config_ccdc_image_format(vpfe); +} + +static int vpfe_initialize_device(struct vpfe_device *vpfe) +{ + struct vpfe_subdev_info *sdinfo; + int ret; + + sdinfo = &vpfe->cfg->sub_devs[0]; + sdinfo->sd = vpfe->sd[0]; + vpfe->current_input = 0; + vpfe->std_index = 0; + /* Configure the default format information */ + ret = vpfe_config_image_format(vpfe, + vpfe_standards[vpfe->std_index].std_id); + if (ret) + return ret; + + pm_runtime_get_sync(vpfe->pdev); + + vpfe_config_enable(&vpfe->ccdc, 1); + + vpfe_ccdc_restore_defaults(&vpfe->ccdc); + + /* Clear all VPFE interrupts */ + vpfe_clear_intr(&vpfe->ccdc, -1); + + return ret; +} + +/* + * vpfe_release : This function is based on the vb2_fop_release + * helper function. + * It has been augmented to handle module power management, + * by disabling/enabling h/w module fcntl clock when necessary. + */ +static int vpfe_release(struct file *file) +{ + struct vpfe_device *vpfe = video_drvdata(file); + int ret; + + mutex_lock(&vpfe->lock); + + if (v4l2_fh_is_singular_file(file)) + vpfe_ccdc_close(&vpfe->ccdc, vpfe->pdev); + ret = _vb2_fop_release(file, NULL); + + mutex_unlock(&vpfe->lock); + + return ret; +} + +/* + * vpfe_open : This function is based on the v4l2_fh_open helper function. + * It has been augmented to handle module power management, + * by disabling/enabling h/w module fcntl clock when necessary. + */ +static int vpfe_open(struct file *file) +{ + struct vpfe_device *vpfe = video_drvdata(file); + int ret; + + mutex_lock(&vpfe->lock); + + ret = v4l2_fh_open(file); + if (ret) { + vpfe_err(vpfe, "v4l2_fh_open failed\n"); + goto unlock; + } + + if (!v4l2_fh_is_singular_file(file)) + goto unlock; + + if (vpfe_initialize_device(vpfe)) { + v4l2_fh_release(file); + ret = -ENODEV; + } + +unlock: + mutex_unlock(&vpfe->lock); + return ret; +} + +/** + * vpfe_schedule_next_buffer: set next buffer address for capture + * @vpfe : ptr to vpfe device + * + * This function will get next buffer from the dma queue and + * set the buffer address in the vpfe register for capture. + * the buffer is marked active + * + * Assumes caller is holding vpfe->dma_queue_lock already + */ +static inline void vpfe_schedule_next_buffer(struct vpfe_device *vpfe) +{ + vpfe->next_frm = list_entry(vpfe->dma_queue.next, + struct vpfe_cap_buffer, list); + list_del(&vpfe->next_frm->list); + + vpfe_set_sdr_addr(&vpfe->ccdc, + vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0)); +} + +static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe) +{ + unsigned long addr; + + addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb, 0) + + vpfe->field_off; + + vpfe_set_sdr_addr(&vpfe->ccdc, addr); +} + +/* + * vpfe_process_buffer_complete: process a completed buffer + * @vpfe : ptr to vpfe device + * + * This function time stamp the buffer and mark it as DONE. It also + * wake up any process waiting on the QUEUE and set the next buffer + * as current + */ +static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe) +{ + v4l2_get_timestamp(&vpfe->cur_frm->vb.v4l2_buf.timestamp); + vpfe->cur_frm->vb.v4l2_buf.field = vpfe->fmt.fmt.pix.field; + vpfe->cur_frm->vb.v4l2_buf.sequence = vpfe->sequence++; + vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_DONE); + vpfe->cur_frm = vpfe->next_frm; +} + +/* + * vpfe_isr : ISR handler for vpfe capture (VINT0) + * @irq: irq number + * @dev_id: dev_id ptr + * + * It changes status of the captured buffer, takes next buffer from the queue + * and sets its address in VPFE registers + */ +static irqreturn_t vpfe_isr(int irq, void *dev) +{ + struct vpfe_device *vpfe = (struct vpfe_device *)dev; + enum v4l2_field field; + int intr_status; + int fid; + + intr_status = vpfe_reg_read(&vpfe->ccdc, VPFE_IRQ_STS); + + if (intr_status & VPFE_VDINT0) { + field = vpfe->fmt.fmt.pix.field; + + if (field == V4L2_FIELD_NONE) { + /* handle progressive frame capture */ + if (vpfe->cur_frm != vpfe->next_frm) + vpfe_process_buffer_complete(vpfe); + goto next_intr; + } + + /* interlaced or TB capture check which field + we are in hardware */ + fid = vpfe_ccdc_getfid(&vpfe->ccdc); + + /* switch the software maintained field id */ + vpfe->field ^= 1; + if (fid == vpfe->field) { + /* we are in-sync here,continue */ + if (fid == 0) { + /* + * One frame is just being captured. If the + * next frame is available, release the + * current frame and move on + */ + if (vpfe->cur_frm != vpfe->next_frm) + vpfe_process_buffer_complete(vpfe); + /* + * based on whether the two fields are stored + * interleave or separately in memory, + * reconfigure the CCDC memory address + */ + if (field == V4L2_FIELD_SEQ_TB) + vpfe_schedule_bottom_field(vpfe); + + goto next_intr; + } + /* + * if one field is just being captured configure + * the next frame get the next frame from the empty + * queue if no frame is available hold on to the + * current buffer + */ + spin_lock(&vpfe->dma_queue_lock); + if (!list_empty(&vpfe->dma_queue) && + vpfe->cur_frm == vpfe->next_frm) + vpfe_schedule_next_buffer(vpfe); + spin_unlock(&vpfe->dma_queue_lock); + } else if (fid == 0) { + /* + * out of sync. Recover from any hardware out-of-sync. + * May loose one frame + */ + vpfe->field = fid; + } + } + +next_intr: + if (intr_status & VPFE_VDINT1) { + spin_lock(&vpfe->dma_queue_lock); + if (vpfe->fmt.fmt.pix.field == V4L2_FIELD_NONE && + !list_empty(&vpfe->dma_queue) && + vpfe->cur_frm == vpfe->next_frm) + vpfe_schedule_next_buffer(vpfe); + spin_unlock(&vpfe->dma_queue_lock); + } + + vpfe_clear_intr(&vpfe->ccdc, intr_status); + + return IRQ_HANDLED; +} + +static inline void vpfe_detach_irq(struct vpfe_device *vpfe) +{ + unsigned int intr = VPFE_VDINT0; + enum ccdc_frmfmt frame_format; + + frame_format = vpfe_ccdc_get_frame_format(&vpfe->ccdc); + if (frame_format == CCDC_FRMFMT_PROGRESSIVE) + intr |= VPFE_VDINT1; + + vpfe_reg_write(&vpfe->ccdc, intr, VPFE_IRQ_EN_CLR); +} + +static inline void vpfe_attach_irq(struct vpfe_device *vpfe) +{ + unsigned int intr = VPFE_VDINT0; + enum ccdc_frmfmt frame_format; + + frame_format = vpfe_ccdc_get_frame_format(&vpfe->ccdc); + if (frame_format == CCDC_FRMFMT_PROGRESSIVE) + intr |= VPFE_VDINT1; + + vpfe_reg_write(&vpfe->ccdc, intr, VPFE_IRQ_EN_SET); +} + +static int vpfe_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + vpfe_dbg(2, vpfe, "vpfe_querycap\n"); + + strlcpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver)); + strlcpy(cap->card, "TI AM437x VPFE", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", vpfe->v4l2_dev.name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +/* get the format set at output pad of the adjacent subdev */ +static int __vpfe_get_format(struct vpfe_device *vpfe, + struct v4l2_format *format, unsigned int *bpp) +{ + struct v4l2_mbus_framefmt mbus_fmt; + struct vpfe_subdev_info *sdinfo; + struct v4l2_subdev_format fmt; + int ret; + + sdinfo = vpfe->current_subdev; + if (!sdinfo->sd) + return -EINVAL; + + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.pad = 0; + + ret = v4l2_subdev_call(sdinfo->sd, pad, get_fmt, NULL, &fmt); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + if (!ret) { + v4l2_fill_pix_format(&format->fmt.pix, &fmt.format); + mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp); + } else { + ret = v4l2_device_call_until_err(&vpfe->v4l2_dev, + sdinfo->grp_id, + video, g_mbus_fmt, + &mbus_fmt); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt); + mbus_to_pix(vpfe, &mbus_fmt, &format->fmt.pix, bpp); + } + + format->type = vpfe->fmt.type; + + vpfe_dbg(1, vpfe, + "%s size %dx%d (%s) bytesperline = %d, size = %d, bpp = %d\n", + __func__, format->fmt.pix.width, format->fmt.pix.height, + print_fourcc(format->fmt.pix.pixelformat), + format->fmt.pix.bytesperline, format->fmt.pix.sizeimage, *bpp); + + return 0; +} + +/* set the format at output pad of the adjacent subdev */ +static int __vpfe_set_format(struct vpfe_device *vpfe, + struct v4l2_format *format, unsigned int *bpp) +{ + struct v4l2_mbus_framefmt mbus_fmt; + struct vpfe_subdev_info *sdinfo; + struct v4l2_subdev_format fmt; + int ret; + + vpfe_dbg(2, vpfe, "__vpfe_set_format\n"); + + sdinfo = vpfe->current_subdev; + if (!sdinfo->sd) + return -EINVAL; + + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.pad = 0; + + pix_to_mbus(vpfe, &format->fmt.pix, &fmt.format); + + ret = v4l2_subdev_call(sdinfo->sd, pad, set_fmt, NULL, &fmt); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + if (!ret) { + v4l2_fill_pix_format(&format->fmt.pix, &fmt.format); + mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp); + } else { + ret = v4l2_device_call_until_err(&vpfe->v4l2_dev, + sdinfo->grp_id, + video, s_mbus_fmt, + &mbus_fmt); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt); + mbus_to_pix(vpfe, &mbus_fmt, &format->fmt.pix, bpp); + } + + format->type = vpfe->fmt.type; + + vpfe_dbg(1, vpfe, + "%s size %dx%d (%s) bytesperline = %d, size = %d, bpp = %d\n", + __func__, format->fmt.pix.width, format->fmt.pix.height, + print_fourcc(format->fmt.pix.pixelformat), + format->fmt.pix.bytesperline, format->fmt.pix.sizeimage, *bpp); + + return 0; +} + +static int vpfe_g_fmt(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + vpfe_dbg(2, vpfe, "vpfe_g_fmt\n"); + + *fmt = vpfe->fmt; + + return 0; +} + +static int vpfe_enum_fmt(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + struct vpfe_fmt *fmt = NULL; + unsigned int k; + + vpfe_dbg(2, vpfe, "vpfe_enum_format index:%d\n", + f->index); + + sdinfo = vpfe->current_subdev; + if (!sdinfo->sd) + return -EINVAL; + + if (f->index > ARRAY_SIZE(formats)) + return -EINVAL; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + if (formats[k].index == f->index) { + fmt = &formats[k]; + break; + } + } + if (!fmt) + return -EINVAL; + + strncpy(f->description, fmt->name, sizeof(f->description) - 1); + f->pixelformat = fmt->fourcc; + f->type = vpfe->fmt.type; + + vpfe_dbg(1, vpfe, "vpfe_enum_format: mbus index: %d code: %x pixelformat: %s [%s]\n", + f->index, fmt->code, print_fourcc(fmt->fourcc), fmt->name); + + return 0; +} + +static int vpfe_try_fmt(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpfe_device *vpfe = video_drvdata(file); + unsigned int bpp; + + vpfe_dbg(2, vpfe, "vpfe_try_fmt\n"); + + return __vpfe_get_format(vpfe, fmt, &bpp); +} + +static int vpfe_s_fmt(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct v4l2_format format; + unsigned int bpp; + int ret; + + vpfe_dbg(2, vpfe, "vpfe_s_fmt\n"); + + /* If streaming is started, return error */ + if (vb2_is_busy(&vpfe->buffer_queue)) { + vpfe_err(vpfe, "%s device busy\n", __func__); + return -EBUSY; + } + + ret = vpfe_try_fmt(file, priv, fmt); + if (ret) + return ret; + + + if (!cmp_v4l2_format(fmt, &format)) { + /* Sensor format is different from the requested format + * so we need to change it + */ + ret = __vpfe_set_format(vpfe, fmt, &bpp); + if (ret) + return ret; + } else /* Just make sure all of the fields are consistent */ + *fmt = format; + + /* First detach any IRQ if currently attached */ + vpfe_detach_irq(vpfe); + vpfe->fmt = *fmt; + vpfe->bpp = bpp; + + /* Update the crop window based on found values */ + vpfe->crop.width = fmt->fmt.pix.width; + vpfe->crop.height = fmt->fmt.pix.height; + + /* set image capture parameters in the ccdc */ + return vpfe_config_ccdc_image_format(vpfe); +} + +static int vpfe_enum_size(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct v4l2_subdev_frame_size_enum fse; + struct vpfe_subdev_info *sdinfo; + struct v4l2_mbus_framefmt mbus; + struct v4l2_pix_format pix; + struct vpfe_fmt *fmt; + int ret; + + vpfe_dbg(2, vpfe, "vpfe_enum_size\n"); + + /* check for valid format */ + fmt = find_format_by_pix(fsize->pixel_format); + if (!fmt) { + vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n", + fsize->pixel_format); + return -EINVAL; + } + + memset(fsize->reserved, 0x0, sizeof(fsize->reserved)); + + sdinfo = vpfe->current_subdev; + if (!sdinfo->sd) + return -EINVAL; + + memset(&pix, 0x0, sizeof(pix)); + /* Construct pix from parameter and use default for the rest */ + pix.pixelformat = fsize->pixel_format; + pix.width = 640; + pix.height = 480; + pix.colorspace = V4L2_COLORSPACE_SRGB; + pix.field = V4L2_FIELD_NONE; + pix_to_mbus(vpfe, &pix, &mbus); + + memset(&fse, 0x0, sizeof(fse)); + fse.index = fsize->index; + fse.pad = 0; + fse.code = mbus.code; + ret = v4l2_subdev_call(sdinfo->sd, pad, enum_frame_size, NULL, &fse); + if (ret) + return -EINVAL; + + vpfe_dbg(1, vpfe, "vpfe_enum_size: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", + fse.index, fse.code, fse.min_width, fse.max_width, + fse.min_height, fse.max_height); + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width; + fsize->discrete.height = fse.max_height; + + vpfe_dbg(1, vpfe, "vpfe_enum_size: index: %d pixformat: %s size: %dx%d\n", + fsize->index, print_fourcc(fsize->pixel_format), + fsize->discrete.width, fsize->discrete.height); + + return 0; +} + +/* + * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a + * given app input index + */ +static int +vpfe_get_subdev_input_index(struct vpfe_device *vpfe, + int *subdev_index, + int *subdev_input_index, + int app_input_index) +{ + struct vpfe_config *cfg = vpfe->cfg; + struct vpfe_subdev_info *sdinfo; + int i, j = 0; + + for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) { + sdinfo = &cfg->sub_devs[i]; + if (app_input_index < (j + 1)) { + *subdev_index = i; + *subdev_input_index = app_input_index - j; + return 0; + } + j++; + } + return -EINVAL; +} + +/* + * vpfe_get_app_input - Get app input index for a given subdev input index + * driver stores the input index of the current sub device and translate it + * when application request the current input + */ +static int vpfe_get_app_input_index(struct vpfe_device *vpfe, + int *app_input_index) +{ + struct vpfe_config *cfg = vpfe->cfg; + struct vpfe_subdev_info *sdinfo; + int i, j = 0; + + for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) { + sdinfo = &cfg->sub_devs[i]; + if (!strcmp(sdinfo->name, vpfe->current_subdev->name)) { + if (vpfe->current_input >= 1) + return -1; + *app_input_index = j + vpfe->current_input; + return 0; + } + j++; + } + return -EINVAL; +} + +static int vpfe_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int subdev, index; + + vpfe_dbg(2, vpfe, "vpfe_enum_input\n"); + + if (vpfe_get_subdev_input_index(vpfe, &subdev, &index, + inp->index) < 0) { + vpfe_dbg(1, vpfe, + "input information not found for the subdev\n"); + return -EINVAL; + } + sdinfo = &vpfe->cfg->sub_devs[subdev]; + *inp = sdinfo->inputs[index]; + + return 0; +} + +static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + vpfe_dbg(2, vpfe, "vpfe_g_input\n"); + + return vpfe_get_app_input_index(vpfe, index); +} + +/* Assumes caller is holding vpfe_dev->lock */ +static int vpfe_set_input(struct vpfe_device *vpfe, unsigned int index) +{ + int subdev_index = 0, inp_index = 0; + struct vpfe_subdev_info *sdinfo; + struct vpfe_route *route; + u32 input, output; + int ret; + + vpfe_dbg(2, vpfe, "vpfe_set_input: index: %d\n", index); + + /* If streaming is started, return error */ + if (vb2_is_busy(&vpfe->buffer_queue)) { + vpfe_err(vpfe, "%s device busy\n", __func__); + return -EBUSY; + } + ret = vpfe_get_subdev_input_index(vpfe, + &subdev_index, + &inp_index, + index); + if (ret < 0) { + vpfe_err(vpfe, "invalid input index: %d\n", index); + goto get_out; + } + + sdinfo = &vpfe->cfg->sub_devs[subdev_index]; + sdinfo->sd = vpfe->sd[subdev_index]; + route = &sdinfo->routes[inp_index]; + if (route && sdinfo->can_route) { + input = route->input; + output = route->output; + if (sdinfo->sd) { + ret = v4l2_subdev_call(sdinfo->sd, video, + s_routing, input, output, 0); + if (ret) { + vpfe_err(vpfe, "s_routing failed\n"); + ret = -EINVAL; + goto get_out; + } + } + + } + + vpfe->current_subdev = sdinfo; + if (sdinfo->sd) + vpfe->v4l2_dev.ctrl_handler = sdinfo->sd->ctrl_handler; + vpfe->current_input = index; + vpfe->std_index = 0; + + /* set the bus/interface parameter for the sub device in ccdc */ + ret = vpfe_ccdc_set_hw_if_params(&vpfe->ccdc, &sdinfo->vpfe_param); + if (ret) + return ret; + + /* set the default image parameters in the device */ + return vpfe_config_image_format(vpfe, + vpfe_standards[vpfe->std_index].std_id); + +get_out: + return ret; +} + +static int vpfe_s_input(struct file *file, void *priv, unsigned int index) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + vpfe_dbg(2, vpfe, + "vpfe_s_input: index: %d\n", index); + + return vpfe_set_input(vpfe, index); +} + +static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + + vpfe_dbg(2, vpfe, "vpfe_querystd\n"); + + sdinfo = vpfe->current_subdev; + if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD)) + return -ENODATA; + + /* Call querystd function of decoder device */ + return v4l2_device_call_until_err(&vpfe->v4l2_dev, sdinfo->grp_id, + video, querystd, std_id); +} + +static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int ret; + + vpfe_dbg(2, vpfe, "vpfe_s_std\n"); + + sdinfo = vpfe->current_subdev; + if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD)) + return -ENODATA; + + /* If streaming is started, return error */ + if (vb2_is_busy(&vpfe->buffer_queue)) { + vpfe_err(vpfe, "%s device busy\n", __func__); + ret = -EBUSY; + return ret; + } + + ret = v4l2_device_call_until_err(&vpfe->v4l2_dev, sdinfo->grp_id, + video, s_std, std_id); + if (ret < 0) { + vpfe_err(vpfe, "Failed to set standard\n"); + return ret; + } + ret = vpfe_config_image_format(vpfe, std_id); + + return ret; +} + +static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + + vpfe_dbg(2, vpfe, "vpfe_g_std\n"); + + sdinfo = vpfe->current_subdev; + if (sdinfo->inputs[0].capabilities != V4L2_IN_CAP_STD) + return -ENODATA; + + *std_id = vpfe_standards[vpfe->std_index].std_id; + + return 0; +} + +/* + * vpfe_calculate_offsets : This function calculates buffers offset + * for top and bottom field + */ +static void vpfe_calculate_offsets(struct vpfe_device *vpfe) +{ + struct v4l2_rect image_win; + + vpfe_dbg(2, vpfe, "vpfe_calculate_offsets\n"); + + vpfe_ccdc_get_image_window(&vpfe->ccdc, &image_win); + vpfe->field_off = image_win.height * image_win.width; +} + +/* + * vpfe_queue_setup - Callback function for buffer setup. + * @vq: vb2_queue ptr + * @fmt: v4l2 format + * @nbuffers: ptr to number of buffers requested by application + * @nplanes:: contains number of distinct video planes needed to hold a frame + * @sizes[]: contains the size (in bytes) of each plane. + * @alloc_ctxs: ptr to allocation context + * + * This callback function is called when reqbuf() is called to adjust + * the buffer count and buffer size + */ +static int vpfe_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct vpfe_device *vpfe = vb2_get_drv_priv(vq); + + if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage) + return -EINVAL; + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + + *nplanes = 1; + sizes[0] = fmt ? fmt->fmt.pix.sizeimage : vpfe->fmt.fmt.pix.sizeimage; + alloc_ctxs[0] = vpfe->alloc_ctx; + + vpfe_dbg(1, vpfe, + "nbuffers=%d, size=%u\n", *nbuffers, sizes[0]); + + /* Calculate field offset */ + vpfe_calculate_offsets(vpfe); + + return 0; +} + +/* + * vpfe_buffer_prepare : callback function for buffer prepare + * @vb: ptr to vb2_buffer + * + * This is the callback function for buffer prepare when vb2_qbuf() + * function is called. The buffer is prepared and user space virtual address + * or user address is converted into physical address + */ +static int vpfe_buffer_prepare(struct vb2_buffer *vb) +{ + struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue); + + vb2_set_plane_payload(vb, 0, vpfe->fmt.fmt.pix.sizeimage); + + if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) + return -EINVAL; + + vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field; + + return 0; +} + +/* + * vpfe_buffer_queue : Callback function to add buffer to DMA queue + * @vb: ptr to vb2_buffer + */ +static void vpfe_buffer_queue(struct vb2_buffer *vb) +{ + struct vpfe_device *vpfe = vb2_get_drv_priv(vb->vb2_queue); + struct vpfe_cap_buffer *buf = to_vpfe_buffer(vb); + unsigned long flags = 0; + + /* add the buffer to the DMA queue */ + spin_lock_irqsave(&vpfe->dma_queue_lock, flags); + list_add_tail(&buf->list, &vpfe->dma_queue); + spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); +} + +/* + * vpfe_start_streaming : Starts the DMA engine for streaming + * @vb: ptr to vb2_buffer + * @count: number of buffers + */ +static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct vpfe_device *vpfe = vb2_get_drv_priv(vq); + struct vpfe_cap_buffer *buf, *tmp; + struct vpfe_subdev_info *sdinfo; + unsigned long flags; + unsigned long addr; + int ret; + + spin_lock_irqsave(&vpfe->dma_queue_lock, flags); + + vpfe->field = 0; + vpfe->sequence = 0; + + sdinfo = vpfe->current_subdev; + + vpfe_attach_irq(vpfe); + + if (vpfe->ccdc.ccdc_cfg.if_type == VPFE_RAW_BAYER) + vpfe_ccdc_config_raw(&vpfe->ccdc); + else + vpfe_ccdc_config_ycbcr(&vpfe->ccdc); + + /* Get the next frame from the buffer queue */ + vpfe->next_frm = list_entry(vpfe->dma_queue.next, + struct vpfe_cap_buffer, list); + vpfe->cur_frm = vpfe->next_frm; + /* Remove buffer from the buffer queue */ + list_del(&vpfe->cur_frm->list); + spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); + + addr = vb2_dma_contig_plane_dma_addr(&vpfe->cur_frm->vb, 0); + + vpfe_set_sdr_addr(&vpfe->ccdc, (unsigned long)(addr)); + + vpfe_pcr_enable(&vpfe->ccdc, 1); + + ret = v4l2_subdev_call(sdinfo->sd, video, s_stream, 1); + if (ret < 0) { + vpfe_err(vpfe, "Error in attaching interrupt handle\n"); + goto err; + } + + return 0; + +err: + list_for_each_entry_safe(buf, tmp, &vpfe->dma_queue, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); + } + spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); + + return ret; +} + +/* + * vpfe_stop_streaming : Stop the DMA engine + * @vq: ptr to vb2_queue + * + * This callback stops the DMA engine and any remaining buffers + * in the DMA queue are released. + */ +static void vpfe_stop_streaming(struct vb2_queue *vq) +{ + struct vpfe_device *vpfe = vb2_get_drv_priv(vq); + struct vpfe_subdev_info *sdinfo; + unsigned long flags; + int ret; + + vpfe_pcr_enable(&vpfe->ccdc, 0); + + vpfe_detach_irq(vpfe); + + sdinfo = vpfe->current_subdev; + ret = v4l2_subdev_call(sdinfo->sd, video, s_stream, 0); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) + vpfe_dbg(1, vpfe, "stream off failed in subdev\n"); + + /* release all active buffers */ + spin_lock_irqsave(&vpfe->dma_queue_lock, flags); + if (vpfe->cur_frm == vpfe->next_frm) { + vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_ERROR); + } else { + if (vpfe->cur_frm != NULL) + vb2_buffer_done(&vpfe->cur_frm->vb, + VB2_BUF_STATE_ERROR); + if (vpfe->next_frm != NULL) + vb2_buffer_done(&vpfe->next_frm->vb, + VB2_BUF_STATE_ERROR); + } + + while (!list_empty(&vpfe->dma_queue)) { + vpfe->next_frm = list_entry(vpfe->dma_queue.next, + struct vpfe_cap_buffer, list); + list_del(&vpfe->next_frm->list); + vb2_buffer_done(&vpfe->next_frm->vb, VB2_BUF_STATE_ERROR); + } + spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); +} + +static int vpfe_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *crop) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + vpfe_dbg(2, vpfe, "vpfe_cropcap\n"); + + if (vpfe->std_index >= ARRAY_SIZE(vpfe_standards)) + return -EINVAL; + + memset(crop, 0, sizeof(struct v4l2_cropcap)); + + crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop->defrect.width = vpfe_standards[vpfe->std_index].width; + crop->bounds.width = crop->defrect.width; + crop->defrect.height = vpfe_standards[vpfe->std_index].height; + crop->bounds.height = crop->defrect.height; + crop->pixelaspect = vpfe_standards[vpfe->std_index].pixelaspect; + + return 0; +} + +static int +vpfe_g_selection(struct file *file, void *fh, struct v4l2_selection *s) +{ + struct vpfe_device *vpfe = video_drvdata(file); + + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + s->r.left = s->r.top = 0; + s->r.width = vpfe->crop.width; + s->r.height = vpfe->crop.height; + break; + + case V4L2_SEL_TGT_CROP: + s->r = vpfe->crop; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) +{ + if (a->left < b->left || a->top < b->top) + return 0; + + if (a->left + a->width > b->left + b->width) + return 0; + + if (a->top + a->height > b->top + b->height) + return 0; + + return 1; +} + +static int +vpfe_s_selection(struct file *file, void *fh, struct v4l2_selection *s) +{ + struct vpfe_device *vpfe = video_drvdata(file); + struct v4l2_rect cr = vpfe->crop; + struct v4l2_rect r = s->r; + + /* If streaming is started, return error */ + if (vb2_is_busy(&vpfe->buffer_queue)) { + vpfe_err(vpfe, "%s device busy\n", __func__); + return -EBUSY; + } + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + s->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + v4l_bound_align_image(&r.width, 0, cr.width, 0, + &r.height, 0, cr.height, 0, 0); + + r.left = clamp_t(unsigned int, r.left, 0, cr.width - r.width); + r.top = clamp_t(unsigned int, r.top, 0, cr.height - r.height); + + if (s->flags & V4L2_SEL_FLAG_LE && !enclosed_rectangle(&r, &s->r)) + return -ERANGE; + + if (s->flags & V4L2_SEL_FLAG_GE && !enclosed_rectangle(&s->r, &r)) + return -ERANGE; + + s->r = vpfe->crop = r; + + vpfe_ccdc_set_image_window(&vpfe->ccdc, &r, vpfe->bpp); + vpfe->fmt.fmt.pix.width = r.width; + vpfe->fmt.fmt.pix.height = r.height; + vpfe->fmt.fmt.pix.bytesperline = vpfe_ccdc_get_line_length(&vpfe->ccdc); + vpfe->fmt.fmt.pix.sizeimage = vpfe->fmt.fmt.pix.bytesperline * + vpfe->fmt.fmt.pix.height; + + vpfe_dbg(1, vpfe, "cropped (%d,%d)/%dx%d of %dx%d\n", + r.left, r.top, r.width, r.height, cr.width, cr.height); + + return 0; +} + +static long vpfe_ioctl_default(struct file *file, void *priv, + bool valid_prio, unsigned int cmd, void *param) +{ + struct vpfe_device *vpfe = video_drvdata(file); + int ret; + + vpfe_dbg(2, vpfe, "vpfe_ioctl_default\n"); + + if (!valid_prio) { + vpfe_err(vpfe, "%s device busy\n", __func__); + return -EBUSY; + } + + /* If streaming is started, return error */ + if (vb2_is_busy(&vpfe->buffer_queue)) { + vpfe_err(vpfe, "%s device busy\n", __func__); + return -EBUSY; + } + + switch (cmd) { + case VIDIOC_AM437X_CCDC_CFG: + ret = vpfe_ccdc_set_params(&vpfe->ccdc, param); + if (ret) { + vpfe_dbg(2, vpfe, + "Error setting parameters in CCDC\n"); + return ret; + } + ret = vpfe_get_ccdc_image_format(vpfe, + &vpfe->fmt); + if (ret < 0) { + vpfe_dbg(2, vpfe, + "Invalid image format at CCDC\n"); + return ret; + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +static const struct vb2_ops vpfe_video_qops = { + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .queue_setup = vpfe_queue_setup, + .buf_prepare = vpfe_buffer_prepare, + .buf_queue = vpfe_buffer_queue, + .start_streaming = vpfe_start_streaming, + .stop_streaming = vpfe_stop_streaming, +}; + +/* vpfe capture driver file operations */ +static const struct v4l2_file_operations vpfe_fops = { + .owner = THIS_MODULE, + .open = vpfe_open, + .release = vpfe_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, +}; + +/* vpfe capture ioctl operations */ +static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { + .vidioc_querycap = vpfe_querycap, + .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt, + .vidioc_g_fmt_vid_cap = vpfe_g_fmt, + .vidioc_s_fmt_vid_cap = vpfe_s_fmt, + .vidioc_try_fmt_vid_cap = vpfe_try_fmt, + + .vidioc_enum_framesizes = vpfe_enum_size, + + .vidioc_enum_input = vpfe_enum_input, + .vidioc_g_input = vpfe_g_input, + .vidioc_s_input = vpfe_s_input, + + .vidioc_querystd = vpfe_querystd, + .vidioc_s_std = vpfe_s_std, + .vidioc_g_std = vpfe_g_std, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + + .vidioc_cropcap = vpfe_cropcap, + .vidioc_g_selection = vpfe_g_selection, + .vidioc_s_selection = vpfe_s_selection, + + .vidioc_default = vpfe_ioctl_default, +}; + +static int +vpfe_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct vpfe_device *vpfe = container_of(notifier->v4l2_dev, + struct vpfe_device, v4l2_dev); + struct v4l2_subdev_mbus_code_enum mbus_code; + struct vpfe_subdev_info *sdinfo; + bool found = false; + int i, j; + + vpfe_dbg(1, vpfe, "vpfe_async_bound\n"); + + for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) { + sdinfo = &vpfe->cfg->sub_devs[i]; + + if (!strcmp(sdinfo->name, subdev->name)) { + vpfe->sd[i] = subdev; + vpfe_info(vpfe, + "v4l2 sub device %s registered\n", + subdev->name); + vpfe->sd[i]->grp_id = + sdinfo->grp_id; + /* update tvnorms from the sub devices */ + for (j = 0; j < 1; j++) + vpfe->video_dev->tvnorms |= + sdinfo->inputs[j].std; + + found = true; + break; + } + } + + if (!found) { + vpfe_info(vpfe, "sub device (%s) not matched\n", subdev->name); + return -EINVAL; + } + + /* setup the supported formats & indexes */ + for (j = 0, i = 0; ; ++j) { + struct vpfe_fmt *fmt; + int ret; + + memset(&mbus_code, 0, sizeof(mbus_code)); + mbus_code.index = j; + ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, + NULL, &mbus_code); + if (ret) + break; + + fmt = find_format_by_code(mbus_code.code); + if (!fmt) + continue; + + fmt->supported = true; + fmt->index = i++; + } + + return 0; +} + +static int vpfe_probe_complete(struct vpfe_device *vpfe) +{ + struct video_device *vdev; + struct vb2_queue *q; + int err; + + spin_lock_init(&vpfe->dma_queue_lock); + mutex_init(&vpfe->lock); + + vpfe->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + /* set first sub device as current one */ + vpfe->current_subdev = &vpfe->cfg->sub_devs[0]; + vpfe->v4l2_dev.ctrl_handler = vpfe->sd[0]->ctrl_handler; + + err = vpfe_set_input(vpfe, 0); + if (err) + goto probe_out; + + /* Initialize videobuf2 queue as per the buffer type */ + vpfe->alloc_ctx = vb2_dma_contig_init_ctx(vpfe->pdev); + if (IS_ERR(vpfe->alloc_ctx)) { + vpfe_err(vpfe, "Failed to get the context\n"); + err = PTR_ERR(vpfe->alloc_ctx); + goto probe_out; + } + + q = &vpfe->buffer_queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = vpfe; + q->ops = &vpfe_video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct vpfe_cap_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &vpfe->lock; + q->min_buffers_needed = 1; + + err = vb2_queue_init(q); + if (err) { + vpfe_err(vpfe, "vb2_queue_init() failed\n"); + vb2_dma_contig_cleanup_ctx(vpfe->alloc_ctx); + goto probe_out; + } + + INIT_LIST_HEAD(&vpfe->dma_queue); + + vdev = vpfe->video_dev; + strlcpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name)); + vdev->release = video_device_release; + vdev->fops = &vpfe_fops; + vdev->ioctl_ops = &vpfe_ioctl_ops; + vdev->v4l2_dev = &vpfe->v4l2_dev; + vdev->vfl_dir = VFL_DIR_RX; + vdev->queue = q; + vdev->lock = &vpfe->lock; + video_set_drvdata(vdev, vpfe); + err = video_register_device(vpfe->video_dev, VFL_TYPE_GRABBER, -1); + if (err) { + vpfe_err(vpfe, + "Unable to register video device.\n"); + goto probe_out; + } + + return 0; + +probe_out: + v4l2_device_unregister(&vpfe->v4l2_dev); + return err; +} + +static int vpfe_async_complete(struct v4l2_async_notifier *notifier) +{ + struct vpfe_device *vpfe = container_of(notifier->v4l2_dev, + struct vpfe_device, v4l2_dev); + + return vpfe_probe_complete(vpfe); +} + +static struct vpfe_config * +vpfe_get_pdata(struct platform_device *pdev) +{ + struct device_node *endpoint = NULL, *rem = NULL; + struct v4l2_of_endpoint bus_cfg; + struct vpfe_subdev_info *sdinfo; + struct vpfe_config *pdata; + unsigned int flags; + unsigned int i; + int err; + + dev_dbg(&pdev->dev, "vpfe_get_pdata\n"); + + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) + return pdev->dev.platform_data; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, + endpoint); + if (!endpoint) + break; + + sdinfo = &pdata->sub_devs[i]; + sdinfo->grp_id = 0; + + /* we only support camera */ + sdinfo->inputs[0].index = i; + strcpy(sdinfo->inputs[0].name, "Camera"); + sdinfo->inputs[0].type = V4L2_INPUT_TYPE_CAMERA; + sdinfo->inputs[0].std = V4L2_STD_ALL; + sdinfo->inputs[0].capabilities = V4L2_IN_CAP_STD; + + sdinfo->can_route = 0; + sdinfo->routes = NULL; + + of_property_read_u32(endpoint, "ti,am437x-vpfe-interface", + &sdinfo->vpfe_param.if_type); + if (sdinfo->vpfe_param.if_type < 0 || + sdinfo->vpfe_param.if_type > 4) { + sdinfo->vpfe_param.if_type = VPFE_RAW_BAYER; + } + + err = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + if (err) { + dev_err(&pdev->dev, "Could not parse the endpoint\n"); + goto done; + } + + sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width; + + if (sdinfo->vpfe_param.bus_width < 8 || + sdinfo->vpfe_param.bus_width > 16) { + dev_err(&pdev->dev, "Invalid bus width.\n"); + goto done; + } + + flags = bus_cfg.bus.parallel.flags; + + if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + sdinfo->vpfe_param.hdpol = 1; + + if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + sdinfo->vpfe_param.vdpol = 1; + + rem = of_graph_get_remote_port_parent(endpoint); + if (!rem) { + dev_err(&pdev->dev, "Remote device at %s not found\n", + endpoint->full_name); + goto done; + } + + strncpy(sdinfo->name, rem->name, sizeof(sdinfo->name)); + + pdata->asd[i] = devm_kzalloc(&pdev->dev, + sizeof(struct v4l2_async_subdev), + GFP_KERNEL); + pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_OF; + pdata->asd[i]->match.of.node = rem; + of_node_put(endpoint); + of_node_put(rem); + } + + of_node_put(endpoint); + return pdata; + +done: + of_node_put(endpoint); + of_node_put(rem); + return NULL; +} + +/* + * vpfe_probe : This function creates device entries by register + * itself to the V4L2 driver and initializes fields of each + * device objects + */ +static int vpfe_probe(struct platform_device *pdev) +{ + struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev); + struct vpfe_device *vpfe; + struct vpfe_ccdc *ccdc; + struct resource *res; + int ret; + + if (!vpfe_cfg) { + dev_err(&pdev->dev, "No platform data\n"); + return -EINVAL; + } + + vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL); + if (!vpfe) + return -ENOMEM; + + vpfe->pdev = &pdev->dev; + vpfe->cfg = vpfe_cfg; + ccdc = &vpfe->ccdc; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ccdc->ccdc_cfg.base_addr)) + return PTR_ERR(ccdc->ccdc_cfg.base_addr); + + vpfe->irq = platform_get_irq(pdev, 0); + if (vpfe->irq <= 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return -ENODEV; + } + + ret = devm_request_irq(vpfe->pdev, vpfe->irq, vpfe_isr, 0, + "vpfe_capture0", vpfe); + if (ret) { + dev_err(&pdev->dev, "Unable to request interrupt\n"); + return -EINVAL; + } + + vpfe->video_dev = video_device_alloc(); + if (!vpfe->video_dev) { + dev_err(&pdev->dev, "Unable to allocate video device\n"); + return -ENOMEM; + } + + ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev); + if (ret) { + vpfe_err(vpfe, + "Unable to register v4l2 device.\n"); + goto probe_out_video_release; + } + + /* set the driver data in platform device */ + platform_set_drvdata(pdev, vpfe); + /* Enabling module functional clock */ + pm_runtime_enable(&pdev->dev); + + /* for now just enable it here instead of waiting for the open */ + pm_runtime_get_sync(&pdev->dev); + + vpfe_ccdc_config_defaults(ccdc); + + pm_runtime_put_sync(&pdev->dev); + + vpfe->sd = devm_kzalloc(&pdev->dev, sizeof(struct v4l2_subdev *) * + ARRAY_SIZE(vpfe->cfg->asd), GFP_KERNEL); + if (!vpfe->sd) { + ret = -ENOMEM; + goto probe_out_v4l2_unregister; + } + + vpfe->notifier.subdevs = vpfe->cfg->asd; + vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd); + vpfe->notifier.bound = vpfe_async_bound; + vpfe->notifier.complete = vpfe_async_complete; + ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, + &vpfe->notifier); + if (ret) { + vpfe_err(vpfe, "Error registering async notifier\n"); + ret = -EINVAL; + goto probe_out_v4l2_unregister; + } + + return 0; + +probe_out_v4l2_unregister: + v4l2_device_unregister(&vpfe->v4l2_dev); +probe_out_video_release: + if (!video_is_registered(vpfe->video_dev)) + video_device_release(vpfe->video_dev); + return ret; +} + +/* + * vpfe_remove : It un-register device from V4L2 driver + */ +static int vpfe_remove(struct platform_device *pdev) +{ + struct vpfe_device *vpfe = platform_get_drvdata(pdev); + + vpfe_dbg(2, vpfe, "vpfe_remove\n"); + + pm_runtime_disable(&pdev->dev); + + v4l2_async_notifier_unregister(&vpfe->notifier); + v4l2_device_unregister(&vpfe->v4l2_dev); + video_unregister_device(vpfe->video_dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP + +static void vpfe_save_context(struct vpfe_ccdc *ccdc) +{ + ccdc->ccdc_ctx[VPFE_PCR >> 2] = vpfe_reg_read(ccdc, VPFE_PCR); + ccdc->ccdc_ctx[VPFE_SYNMODE >> 2] = vpfe_reg_read(ccdc, VPFE_SYNMODE); + ccdc->ccdc_ctx[VPFE_SDOFST >> 2] = vpfe_reg_read(ccdc, VPFE_SDOFST); + ccdc->ccdc_ctx[VPFE_SDR_ADDR >> 2] = vpfe_reg_read(ccdc, VPFE_SDR_ADDR); + ccdc->ccdc_ctx[VPFE_CLAMP >> 2] = vpfe_reg_read(ccdc, VPFE_CLAMP); + ccdc->ccdc_ctx[VPFE_DCSUB >> 2] = vpfe_reg_read(ccdc, VPFE_DCSUB); + ccdc->ccdc_ctx[VPFE_COLPTN >> 2] = vpfe_reg_read(ccdc, VPFE_COLPTN); + ccdc->ccdc_ctx[VPFE_BLKCMP >> 2] = vpfe_reg_read(ccdc, VPFE_BLKCMP); + ccdc->ccdc_ctx[VPFE_VDINT >> 2] = vpfe_reg_read(ccdc, VPFE_VDINT); + ccdc->ccdc_ctx[VPFE_ALAW >> 2] = vpfe_reg_read(ccdc, VPFE_ALAW); + ccdc->ccdc_ctx[VPFE_REC656IF >> 2] = vpfe_reg_read(ccdc, VPFE_REC656IF); + ccdc->ccdc_ctx[VPFE_CCDCFG >> 2] = vpfe_reg_read(ccdc, VPFE_CCDCFG); + ccdc->ccdc_ctx[VPFE_CULLING >> 2] = vpfe_reg_read(ccdc, VPFE_CULLING); + ccdc->ccdc_ctx[VPFE_HD_VD_WID >> 2] = vpfe_reg_read(ccdc, + VPFE_HD_VD_WID); + ccdc->ccdc_ctx[VPFE_PIX_LINES >> 2] = vpfe_reg_read(ccdc, + VPFE_PIX_LINES); + ccdc->ccdc_ctx[VPFE_HORZ_INFO >> 2] = vpfe_reg_read(ccdc, + VPFE_HORZ_INFO); + ccdc->ccdc_ctx[VPFE_VERT_START >> 2] = vpfe_reg_read(ccdc, + VPFE_VERT_START); + ccdc->ccdc_ctx[VPFE_VERT_LINES >> 2] = vpfe_reg_read(ccdc, + VPFE_VERT_LINES); + ccdc->ccdc_ctx[VPFE_HSIZE_OFF >> 2] = vpfe_reg_read(ccdc, + VPFE_HSIZE_OFF); +} + +static int vpfe_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vpfe_device *vpfe = platform_get_drvdata(pdev); + struct vpfe_ccdc *ccdc = &vpfe->ccdc; + + /* if streaming has not started we don't care */ + if (!vb2_start_streaming_called(&vpfe->buffer_queue)) + return 0; + + pm_runtime_get_sync(dev); + vpfe_config_enable(ccdc, 1); + + /* Save VPFE context */ + vpfe_save_context(ccdc); + + /* Disable CCDC */ + vpfe_pcr_enable(ccdc, 0); + vpfe_config_enable(ccdc, 0); + + /* Disable both master and slave clock */ + pm_runtime_put_sync(dev); + + /* Select sleep pin state */ + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +static void vpfe_restore_context(struct vpfe_ccdc *ccdc) +{ + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SYNMODE >> 2], VPFE_SYNMODE); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CULLING >> 2], VPFE_CULLING); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SDOFST >> 2], VPFE_SDOFST); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_SDR_ADDR >> 2], VPFE_SDR_ADDR); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CLAMP >> 2], VPFE_CLAMP); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_DCSUB >> 2], VPFE_DCSUB); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_COLPTN >> 2], VPFE_COLPTN); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_BLKCMP >> 2], VPFE_BLKCMP); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VDINT >> 2], VPFE_VDINT); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_ALAW >> 2], VPFE_ALAW); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_REC656IF >> 2], VPFE_REC656IF); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_CCDCFG >> 2], VPFE_CCDCFG); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_PCR >> 2], VPFE_PCR); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HD_VD_WID >> 2], + VPFE_HD_VD_WID); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_PIX_LINES >> 2], + VPFE_PIX_LINES); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HORZ_INFO >> 2], + VPFE_HORZ_INFO); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VERT_START >> 2], + VPFE_VERT_START); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_VERT_LINES >> 2], + VPFE_VERT_LINES); + vpfe_reg_write(ccdc, ccdc->ccdc_ctx[VPFE_HSIZE_OFF >> 2], + VPFE_HSIZE_OFF); +} + +static int vpfe_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vpfe_device *vpfe = platform_get_drvdata(pdev); + struct vpfe_ccdc *ccdc = &vpfe->ccdc; + + /* if streaming has not started we don't care */ + if (!vb2_start_streaming_called(&vpfe->buffer_queue)) + return 0; + + /* Enable both master and slave clock */ + pm_runtime_get_sync(dev); + vpfe_config_enable(ccdc, 1); + + /* Restore VPFE context */ + vpfe_restore_context(ccdc); + + vpfe_config_enable(ccdc, 0); + pm_runtime_put_sync(dev); + + /* Select default pin state */ + pinctrl_pm_select_default_state(dev); + + return 0; +} + +#endif + +static SIMPLE_DEV_PM_OPS(vpfe_pm_ops, vpfe_suspend, vpfe_resume); + +static const struct of_device_id vpfe_of_match[] = { + { .compatible = "ti,am437x-vpfe", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, vpfe_of_match); + +static struct platform_driver vpfe_driver = { + .probe = vpfe_probe, + .remove = vpfe_remove, + .driver = { + .name = VPFE_MODULE_NAME, + .owner = THIS_MODULE, + .pm = &vpfe_pm_ops, + .of_match_table = of_match_ptr(vpfe_of_match), + }, +}; + +module_platform_driver(vpfe_driver); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("TI AM437x VPFE driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(VPFE_VERSION); diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h new file mode 100644 index 000000000000..0f557352313d --- /dev/null +++ b/drivers/media/platform/am437x/am437x-vpfe.h @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2013 - 2014 Texas Instruments, Inc. + * + * Benoit Parrot + * Lad, Prabhakar + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef AM437X_VPFE_H +#define AM437X_VPFE_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "am437x-vpfe_regs.h" + +enum vpfe_pin_pol { + VPFE_PINPOL_POSITIVE = 0, + VPFE_PINPOL_NEGATIVE, +}; + +enum vpfe_hw_if_type { + /* Raw Bayer */ + VPFE_RAW_BAYER = 0, + /* BT656 - 8 bit */ + VPFE_BT656, + /* BT656 - 10 bit */ + VPFE_BT656_10BIT, + /* YCbCr - 8 bit with external sync */ + VPFE_YCBCR_SYNC_8, + /* YCbCr - 16 bit with external sync */ + VPFE_YCBCR_SYNC_16, +}; + +/* interface description */ +struct vpfe_hw_if_param { + enum vpfe_hw_if_type if_type; + enum vpfe_pin_pol hdpol; + enum vpfe_pin_pol vdpol; + unsigned int bus_width; +}; + +#define VPFE_MAX_SUBDEV 1 +#define VPFE_MAX_INPUTS 1 + +struct vpfe_pixel_format { + struct v4l2_fmtdesc fmtdesc; + /* bytes per pixel */ + int bpp; +}; + +struct vpfe_std_info { + int active_pixels; + int active_lines; + /* current frame format */ + int frame_format; +}; + +struct vpfe_route { + u32 input; + u32 output; +}; + +struct vpfe_subdev_info { + char name[32]; + /* Sub device group id */ + int grp_id; + /* inputs available at the sub device */ + struct v4l2_input inputs[VPFE_MAX_INPUTS]; + /* Sub dev routing information for each input */ + struct vpfe_route *routes; + /* check if sub dev supports routing */ + int can_route; + /* ccdc bus/interface configuration */ + struct vpfe_hw_if_param vpfe_param; + struct v4l2_subdev *sd; +}; + +struct vpfe_config { + /* information about each subdev */ + struct vpfe_subdev_info sub_devs[VPFE_MAX_SUBDEV]; + /* Flat array, arranged in groups */ + struct v4l2_async_subdev *asd[VPFE_MAX_SUBDEV]; +}; + +struct vpfe_cap_buffer { + struct vb2_buffer vb; + struct list_head list; +}; + +enum ccdc_pixfmt { + CCDC_PIXFMT_RAW = 0, + CCDC_PIXFMT_YCBCR_16BIT, + CCDC_PIXFMT_YCBCR_8BIT, +}; + +enum ccdc_frmfmt { + CCDC_FRMFMT_PROGRESSIVE = 0, + CCDC_FRMFMT_INTERLACED, +}; + +/* PIXEL ORDER IN MEMORY from LSB to MSB */ +/* only applicable for 8-bit input mode */ +enum ccdc_pixorder { + CCDC_PIXORDER_YCBYCR, + CCDC_PIXORDER_CBYCRY, +}; + +enum ccdc_buftype { + CCDC_BUFTYPE_FLD_INTERLEAVED, + CCDC_BUFTYPE_FLD_SEPARATED +}; + + +/* returns the highest bit used for the gamma */ +static inline u8 ccdc_gamma_width_max_bit(enum vpfe_ccdc_gamma_width width) +{ + return 15 - width; +} + +/* returns the highest bit used for this data size */ +static inline u8 ccdc_data_size_max_bit(enum vpfe_ccdc_data_size sz) +{ + return sz == VPFE_CCDC_DATA_8BITS ? 7 : 15 - sz; +} + +/* Structure for CCDC configuration parameters for raw capture mode */ +struct ccdc_params_raw { + /* pixel format */ + enum ccdc_pixfmt pix_fmt; + /* progressive or interlaced frame */ + enum ccdc_frmfmt frm_fmt; + struct v4l2_rect win; + /* Current Format Bytes Per Pixels */ + unsigned int bytesperpixel; + /* Current Format Bytes per Lines + * (Aligned to 32 bytes) used for HORZ_INFO + */ + unsigned int bytesperline; + /* field id polarity */ + enum vpfe_pin_pol fid_pol; + /* vertical sync polarity */ + enum vpfe_pin_pol vd_pol; + /* horizontal sync polarity */ + enum vpfe_pin_pol hd_pol; + /* interleaved or separated fields */ + enum ccdc_buftype buf_type; + /* + * enable to store the image in inverse + * order in memory(bottom to top) + */ + unsigned char image_invert_enable; + /* configurable parameters */ + struct vpfe_ccdc_config_params_raw config_params; +}; + +struct ccdc_params_ycbcr { + /* pixel format */ + enum ccdc_pixfmt pix_fmt; + /* progressive or interlaced frame */ + enum ccdc_frmfmt frm_fmt; + struct v4l2_rect win; + /* Current Format Bytes Per Pixels */ + unsigned int bytesperpixel; + /* Current Format Bytes per Lines + * (Aligned to 32 bytes) used for HORZ_INFO + */ + unsigned int bytesperline; + /* field id polarity */ + enum vpfe_pin_pol fid_pol; + /* vertical sync polarity */ + enum vpfe_pin_pol vd_pol; + /* horizontal sync polarity */ + enum vpfe_pin_pol hd_pol; + /* enable BT.656 embedded sync mode */ + int bt656_enable; + /* cb:y:cr:y or y:cb:y:cr in memory */ + enum ccdc_pixorder pix_order; + /* interleaved or separated fields */ + enum ccdc_buftype buf_type; +}; + +/* + * CCDC operational configuration + */ +struct ccdc_config { + /* CCDC interface type */ + enum vpfe_hw_if_type if_type; + /* Raw Bayer configuration */ + struct ccdc_params_raw bayer; + /* YCbCr configuration */ + struct ccdc_params_ycbcr ycbcr; + /* ccdc base address */ + void __iomem *base_addr; +}; + +struct vpfe_ccdc { + struct ccdc_config ccdc_cfg; + u32 ccdc_ctx[VPFE_REG_END / sizeof(u32)]; +}; + +struct vpfe_device { + /* V4l2 specific parameters */ + /* Identifies video device for this channel */ + struct video_device *video_dev; + /* sub devices */ + struct v4l2_subdev **sd; + /* vpfe cfg */ + struct vpfe_config *cfg; + /* V4l2 device */ + struct v4l2_device v4l2_dev; + /* parent device */ + struct device *pdev; + /* subdevice async Notifier */ + struct v4l2_async_notifier notifier; + /* Indicates id of the field which is being displayed */ + unsigned field; + unsigned sequence; + /* current interface type */ + struct vpfe_hw_if_param vpfe_if_params; + /* ptr to currently selected sub device */ + struct vpfe_subdev_info *current_subdev; + /* current input at the sub device */ + int current_input; + /* Keeps track of the information about the standard */ + struct vpfe_std_info std_info; + /* std index into std table */ + int std_index; + /* IRQs used when CCDC output to SDRAM */ + unsigned int irq; + /* Pointer pointing to current v4l2_buffer */ + struct vpfe_cap_buffer *cur_frm; + /* Pointer pointing to next v4l2_buffer */ + struct vpfe_cap_buffer *next_frm; + /* Used to store pixel format */ + struct v4l2_format fmt; + /* Used to store current bytes per pixel based on current format */ + unsigned int bpp; + /* + * used when IMP is chained to store the crop window which + * is different from the image window + */ + struct v4l2_rect crop; + /* Buffer queue used in video-buf */ + struct vb2_queue buffer_queue; + /* Allocator-specific contexts for each plane */ + struct vb2_alloc_ctx *alloc_ctx; + /* Queue of filled frames */ + struct list_head dma_queue; + /* IRQ lock for DMA queue */ + spinlock_t dma_queue_lock; + /* lock used to access this structure */ + struct mutex lock; + /* + * offset where second field starts from the starting of the + * buffer for field separated YCbCr formats + */ + u32 field_off; + struct vpfe_ccdc ccdc; +}; + +#endif /* AM437X_VPFE_H */ diff --git a/drivers/media/platform/am437x/am437x-vpfe_regs.h b/drivers/media/platform/am437x/am437x-vpfe_regs.h new file mode 100644 index 000000000000..4a0ed29723e8 --- /dev/null +++ b/drivers/media/platform/am437x/am437x-vpfe_regs.h @@ -0,0 +1,140 @@ +/* + * TI AM437x Image Sensor Interface Registers + * + * Copyright (C) 2013 - 2014 Texas Instruments, Inc. + * + * Benoit Parrot + * Lad, Prabhakar + * + * 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 "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef AM437X_VPFE_REGS_H +#define AM437X_VPFE_REGS_H + +/* VPFE module register offset */ +#define VPFE_REVISION 0x0 +#define VPFE_PCR 0x4 +#define VPFE_SYNMODE 0x8 +#define VPFE_HD_VD_WID 0xc +#define VPFE_PIX_LINES 0x10 +#define VPFE_HORZ_INFO 0x14 +#define VPFE_VERT_START 0x18 +#define VPFE_VERT_LINES 0x1c +#define VPFE_CULLING 0x20 +#define VPFE_HSIZE_OFF 0x24 +#define VPFE_SDOFST 0x28 +#define VPFE_SDR_ADDR 0x2c +#define VPFE_CLAMP 0x30 +#define VPFE_DCSUB 0x34 +#define VPFE_COLPTN 0x38 +#define VPFE_BLKCMP 0x3c +#define VPFE_VDINT 0x48 +#define VPFE_ALAW 0x4c +#define VPFE_REC656IF 0x50 +#define VPFE_CCDCFG 0x54 +#define VPFE_DMA_CNTL 0x98 +#define VPFE_SYSCONFIG 0x104 +#define VPFE_CONFIG 0x108 +#define VPFE_IRQ_EOI 0x110 +#define VPFE_IRQ_STS_RAW 0x114 +#define VPFE_IRQ_STS 0x118 +#define VPFE_IRQ_EN_SET 0x11c +#define VPFE_IRQ_EN_CLR 0x120 +#define VPFE_REG_END 0x124 + +/* Define bit fields within selected registers */ +#define VPFE_FID_POL_MASK 1 +#define VPFE_FID_POL_SHIFT 4 +#define VPFE_HD_POL_MASK 1 +#define VPFE_HD_POL_SHIFT 3 +#define VPFE_VD_POL_MASK 1 +#define VPFE_VD_POL_SHIFT 2 +#define VPFE_HSIZE_OFF_MASK 0xffffffe0 +#define VPFE_32BYTE_ALIGN_VAL 31 +#define VPFE_FRM_FMT_MASK 0x1 +#define VPFE_FRM_FMT_SHIFT 7 +#define VPFE_DATA_SZ_MASK 7 +#define VPFE_DATA_SZ_SHIFT 8 +#define VPFE_PIX_FMT_MASK 3 +#define VPFE_PIX_FMT_SHIFT 12 +#define VPFE_VP2SDR_DISABLE 0xfffbffff +#define VPFE_WEN_ENABLE (1 << 17) +#define VPFE_SDR2RSZ_DISABLE 0xfff7ffff +#define VPFE_VDHDEN_ENABLE (1 << 16) +#define VPFE_LPF_ENABLE (1 << 14) +#define VPFE_ALAW_ENABLE (1 << 3) +#define VPFE_ALAW_GAMMA_WD_MASK 7 +#define VPFE_BLK_CLAMP_ENABLE (1 << 31) +#define VPFE_BLK_SGAIN_MASK 0x1f +#define VPFE_BLK_ST_PXL_MASK 0x7fff +#define VPFE_BLK_ST_PXL_SHIFT 10 +#define VPFE_BLK_SAMPLE_LN_MASK 7 +#define VPFE_BLK_SAMPLE_LN_SHIFT 28 +#define VPFE_BLK_SAMPLE_LINE_MASK 7 +#define VPFE_BLK_SAMPLE_LINE_SHIFT 25 +#define VPFE_BLK_DC_SUB_MASK 0x03fff +#define VPFE_BLK_COMP_MASK 0xff +#define VPFE_BLK_COMP_GB_COMP_SHIFT 8 +#define VPFE_BLK_COMP_GR_COMP_SHIFT 16 +#define VPFE_BLK_COMP_R_COMP_SHIFT 24 +#define VPFE_LATCH_ON_VSYNC_DISABLE (1 << 15) +#define VPFE_DATA_PACK_ENABLE (1 << 11) +#define VPFE_HORZ_INFO_SPH_SHIFT 16 +#define VPFE_VERT_START_SLV0_SHIFT 16 +#define VPFE_VDINT_VDINT0_SHIFT 16 +#define VPFE_VDINT_VDINT1_MASK 0xffff +#define VPFE_PPC_RAW 1 +#define VPFE_DCSUB_DEFAULT_VAL 0 +#define VPFE_CLAMP_DEFAULT_VAL 0 +#define VPFE_COLPTN_VAL 0xbb11bb11 +#define VPFE_TWO_BYTES_PER_PIXEL 2 +#define VPFE_INTERLACED_IMAGE_INVERT 0x4b6d +#define VPFE_INTERLACED_NO_IMAGE_INVERT 0x0249 +#define VPFE_PROGRESSIVE_IMAGE_INVERT 0x4000 +#define VPFE_PROGRESSIVE_NO_IMAGE_INVERT 0 +#define VPFE_INTERLACED_HEIGHT_SHIFT 1 +#define VPFE_SYN_MODE_INPMOD_SHIFT 12 +#define VPFE_SYN_MODE_INPMOD_MASK 3 +#define VPFE_SYN_MODE_8BITS (7 << 8) +#define VPFE_SYN_MODE_10BITS (6 << 8) +#define VPFE_SYN_MODE_11BITS (5 << 8) +#define VPFE_SYN_MODE_12BITS (4 << 8) +#define VPFE_SYN_MODE_13BITS (3 << 8) +#define VPFE_SYN_MODE_14BITS (2 << 8) +#define VPFE_SYN_MODE_15BITS (1 << 8) +#define VPFE_SYN_MODE_16BITS (0 << 8) +#define VPFE_SYN_FLDMODE_MASK 1 +#define VPFE_SYN_FLDMODE_SHIFT 7 +#define VPFE_REC656IF_BT656_EN 3 +#define VPFE_SYN_MODE_VD_POL_NEGATIVE (1 << 2) +#define VPFE_CCDCFG_Y8POS_SHIFT 11 +#define VPFE_CCDCFG_BW656_10BIT (1 << 5) +#define VPFE_SDOFST_FIELD_INTERLEAVED 0x249 +#define VPFE_NO_CULLING 0xffff00ff +#define VPFE_VDINT0 (1 << 0) +#define VPFE_VDINT1 (1 << 1) +#define VPFE_VDINT2 (1 << 2) +#define VPFE_DMA_CNTL_OVERFLOW (1 << 31) + +#define VPFE_CONFIG_PCLK_INV_SHIFT 0 +#define VPFE_CONFIG_PCLK_INV_MASK 1 +#define VPFE_CONFIG_PCLK_INV_NOT_INV 0 +#define VPFE_CONFIG_PCLK_INV_INV 1 +#define VPFE_CONFIG_EN_SHIFT 1 +#define VPFE_CONFIG_EN_MASK 2 +#define VPFE_CONFIG_EN_DISABLE 0 +#define VPFE_CONFIG_EN_ENABLE 1 +#define VPFE_CONFIG_ST_SHIFT 2 +#define VPFE_CONFIG_ST_MASK 4 +#define VPFE_CONFIG_ST_OCP_ACTIVE 0 +#define VPFE_CONFIG_ST_OCP_STANDBY 1 + +#endif /* AM437X_VPFE_REGS_H */ diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 00b100023c47..9312d5806541 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -35,6 +35,7 @@ header-y += adfs_fs.h header-y += affs_hardblocks.h header-y += agpgart.h header-y += aio_abi.h +header-y += am437x-vpfe.h header-y += apm_bios.h header-y += arcfb.h header-y += atalk.h diff --git a/include/uapi/linux/am437x-vpfe.h b/include/uapi/linux/am437x-vpfe.h new file mode 100644 index 000000000000..9b03033f9cd6 --- /dev/null +++ b/include/uapi/linux/am437x-vpfe.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2013 - 2014 Texas Instruments, Inc. + * + * Benoit Parrot + * Lad, Prabhakar + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef AM437X_VPFE_USER_H +#define AM437X_VPFE_USER_H + +enum vpfe_ccdc_data_size { + VPFE_CCDC_DATA_16BITS = 0, + VPFE_CCDC_DATA_15BITS, + VPFE_CCDC_DATA_14BITS, + VPFE_CCDC_DATA_13BITS, + VPFE_CCDC_DATA_12BITS, + VPFE_CCDC_DATA_11BITS, + VPFE_CCDC_DATA_10BITS, + VPFE_CCDC_DATA_8BITS, +}; + +/* enum for No of pixel per line to be avg. in Black Clamping*/ +enum vpfe_ccdc_sample_length { + VPFE_CCDC_SAMPLE_1PIXELS = 0, + VPFE_CCDC_SAMPLE_2PIXELS, + VPFE_CCDC_SAMPLE_4PIXELS, + VPFE_CCDC_SAMPLE_8PIXELS, + VPFE_CCDC_SAMPLE_16PIXELS, +}; + +/* enum for No of lines in Black Clamping */ +enum vpfe_ccdc_sample_line { + VPFE_CCDC_SAMPLE_1LINES = 0, + VPFE_CCDC_SAMPLE_2LINES, + VPFE_CCDC_SAMPLE_4LINES, + VPFE_CCDC_SAMPLE_8LINES, + VPFE_CCDC_SAMPLE_16LINES, +}; + +/* enum for Alaw gamma width */ +enum vpfe_ccdc_gamma_width { + VPFE_CCDC_GAMMA_BITS_15_6 = 0, /* use bits 15-6 for gamma */ + VPFE_CCDC_GAMMA_BITS_14_5, + VPFE_CCDC_GAMMA_BITS_13_4, + VPFE_CCDC_GAMMA_BITS_12_3, + VPFE_CCDC_GAMMA_BITS_11_2, + VPFE_CCDC_GAMMA_BITS_10_1, + VPFE_CCDC_GAMMA_BITS_09_0, /* use bits 9-0 for gamma */ +}; + +/* structure for ALaw */ +struct vpfe_ccdc_a_law { + /* Enable/disable A-Law */ + unsigned char enable; + /* Gamma Width Input */ + enum vpfe_ccdc_gamma_width gamma_wd; +}; + +/* structure for Black Clamping */ +struct vpfe_ccdc_black_clamp { + unsigned char enable; + /* only if bClampEnable is TRUE */ + enum vpfe_ccdc_sample_length sample_pixel; + /* only if bClampEnable is TRUE */ + enum vpfe_ccdc_sample_line sample_ln; + /* only if bClampEnable is TRUE */ + unsigned short start_pixel; + /* only if bClampEnable is TRUE */ + unsigned short sgain; + /* only if bClampEnable is FALSE */ + unsigned short dc_sub; +}; + +/* structure for Black Level Compensation */ +struct vpfe_ccdc_black_compensation { + /* Constant value to subtract from Red component */ + char r; + /* Constant value to subtract from Gr component */ + char gr; + /* Constant value to subtract from Blue component */ + char b; + /* Constant value to subtract from Gb component */ + char gb; +}; + +/* Structure for CCDC configuration parameters for raw capture mode passed + * by application + */ +struct vpfe_ccdc_config_params_raw { + /* data size value from 8 to 16 bits */ + enum vpfe_ccdc_data_size data_sz; + /* Structure for Optional A-Law */ + struct vpfe_ccdc_a_law alaw; + /* Structure for Optical Black Clamp */ + struct vpfe_ccdc_black_clamp blk_clamp; + /* Structure for Black Compensation */ + struct vpfe_ccdc_black_compensation blk_comp; +}; + +/* + * Private IOCTL + * VIDIOC_AM437X_CCDC_CFG - Set CCDC configuration for raw capture + * This is an experimental ioctl that will change in future kernels. So use + * this ioctl with care ! + **/ +#define VIDIOC_AM437X_CCDC_CFG \ + _IOW('V', BASE_VIDIOC_PRIVATE + 1, void *) + +#endif /* AM437X_VPFE_USER_H */ -- cgit v1.2.3 From d2fb785227c03443b5df4ea8e4b6f6d8bd2b2d13 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Wed, 26 Nov 2014 18:51:46 -0300 Subject: [media] mn88472: calculate the IF register values Add xtal as a configuration parameter so it can be used in the IF register value calculation. Signed-off-by: Benjamin Larsson Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mn88472.h | 6 ++++++ drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 1 + drivers/staging/media/mn88472/mn88472.c | 23 ++++++++--------------- drivers/staging/media/mn88472/mn88472_priv.h | 1 + 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h index da4558bce60f..e4e0b80d3091 100644 --- a/drivers/media/dvb-frontends/mn88472.h +++ b/drivers/media/dvb-frontends/mn88472.h @@ -33,6 +33,12 @@ struct mn88472_config { * DVB frontend. */ struct dvb_frontend **fe; + + /* + * Xtal frequency. + * Hz + */ + u32 xtal; }; #endif diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 896a225ee011..73580f8d5a17 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -852,6 +852,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) mn88472_config.fe = &adap->fe[1]; mn88472_config.i2c_wr_max = 22, strlcpy(info.type, "mn88472", I2C_NAME_SIZE); + mn88472_config.xtal = 20500000; info.addr = 0x18; info.platform_data = &mn88472_config; request_module(info.type); diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c index 52de8f85d36c..f648b58392c3 100644 --- a/drivers/staging/media/mn88472/mn88472.c +++ b/drivers/staging/media/mn88472/mn88472.c @@ -30,6 +30,7 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u32 if_frequency = 0; + u64 tmp; u8 delivery_system_val, if_val[3], bw_val[7], bw_val2; dev_dbg(&client->dev, @@ -62,17 +63,14 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) case SYS_DVBT2: if (c->bandwidth_hz <= 6000000) { /* IF 3570000 Hz, BW 6000000 Hz */ - memcpy(if_val, "\x2c\x94\xdb", 3); memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7); bw_val2 = 0x02; } else if (c->bandwidth_hz <= 7000000) { /* IF 4570000 Hz, BW 7000000 Hz */ - memcpy(if_val, "\x39\x11\xbc", 3); memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7); bw_val2 = 0x01; } else if (c->bandwidth_hz <= 8000000) { /* IF 4570000 Hz, BW 8000000 Hz */ - memcpy(if_val, "\x39\x11\xbc", 3); memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7); bw_val2 = 0x00; } else { @@ -82,7 +80,6 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) break; case SYS_DVBC_ANNEX_A: /* IF 5070000 Hz, BW 8000000 Hz */ - memcpy(if_val, "\x3f\x50\x2c", 3); memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7); bw_val2 = 0x00; break; @@ -106,17 +103,12 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) dev_dbg(&client->dev, "get_if_frequency=%d\n", if_frequency); } - switch (if_frequency) { - case 3570000: - case 4570000: - case 5070000: - break; - default: - dev_err(&client->dev, "IF frequency %d not supported\n", - if_frequency); - ret = -EINVAL; - goto err; - } + /* Calculate IF registers ( (1<<24)*IF / Xtal ) */ + tmp = div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2), + dev->xtal); + if_val[0] = ((tmp >> 16) & 0xff); + if_val[1] = ((tmp >> 8) & 0xff); + if_val[2] = ((tmp >> 0) & 0xff); ret = regmap_write(dev->regmap[2], 0xfb, 0x13); ret = regmap_write(dev->regmap[2], 0xef, 0x13); @@ -411,6 +403,7 @@ static int mn88472_probe(struct i2c_client *client, } dev->i2c_wr_max = config->i2c_wr_max; + dev->xtal = config->xtal; dev->client[0] = client; dev->regmap[0] = regmap_init_i2c(dev->client[0], ®map_config); if (IS_ERR(dev->regmap[0])) { diff --git a/drivers/staging/media/mn88472/mn88472_priv.h b/drivers/staging/media/mn88472/mn88472_priv.h index 1095949f040d..b12b731e2d4e 100644 --- a/drivers/staging/media/mn88472/mn88472_priv.h +++ b/drivers/staging/media/mn88472/mn88472_priv.h @@ -31,6 +31,7 @@ struct mn88472_dev { u16 i2c_wr_max; fe_delivery_system_t delivery_system; bool warm; /* FW running */ + u32 xtal; }; #endif -- cgit v1.2.3 From 645c7cea71a9b519cd9f98e45cbb923ef845b1b2 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Wed, 26 Nov 2014 18:51:47 -0300 Subject: [media] mn88472: document demod reset Signed-off-by: Benjamin Larsson Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/mn88472/mn88472.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c index f648b58392c3..36ef39bcc215 100644 --- a/drivers/staging/media/mn88472/mn88472.c +++ b/drivers/staging/media/mn88472/mn88472.c @@ -190,6 +190,8 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) ret = regmap_write(dev->regmap[0], 0xae, 0x00); ret = regmap_write(dev->regmap[2], 0x08, 0x1d); ret = regmap_write(dev->regmap[0], 0xd9, 0xe3); + + /* Reset demod */ ret = regmap_write(dev->regmap[2], 0xf8, 0x9f); if (ret) goto err; -- cgit v1.2.3 From bbfebeea7640973613c484f0281bdd15d68fd873 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:15 -0300 Subject: [media] em28xx: fix em28xx-input removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing the em28xx-rc module results in the following lockdep splat, which is caused by trying to call cancel_delayed_work_sync() on an uninitialised delayed work. Fix this by ensuring we always initialise the work. INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. CPU: 0 PID: 2183 Comm: rmmod Not tainted 3.18.0+ #1464 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [] (dump_backtrace) from [] (show_stack+0x18/0x1c) r6:c1419d2c r5:00000000 r4:00000000 r3:00000000 [] (show_stack) from [] (dump_stack+0x7c/0x98) [] (dump_stack) from [] (__lock_acquire+0x16d4/0x1bb0) r4:edf19f74 r3:df049380 [] (__lock_acquire) from [] (lock_acquire+0xb0/0x124) r10:00000000 r9:c003ba90 r8:00000000 r7:00000000 r6:00000000 r5:edf19f74 r4:00000000 [] (lock_acquire) from [] (flush_work+0x44/0x264) r10:00000000 r9:eaa86000 r8:edf190b0 r7:edf19f74 r6:00000001 r5:edf19f64 r4:00000000 [] (flush_work) from [] (__cancel_work_timer+0x8c/0x124) r7:00000000 r6:00000001 r5:00000000 r4:edf19f64 [] (__cancel_work_timer) from [] (cancel_delayed_work_sync+0x14/0x18) r7:00000000 r6:eccc3600 r5:00000000 r4:edf19000 [] (cancel_delayed_work_sync) from [] (em28xx_ir_fini+0x48/0xd8 [em28xx_rc]) [] (em28xx_ir_fini [em28xx_rc]) from [] (em28xx_unregister_extension+0x40/0x94 [em28xx]) r8:c000edc4 r7:00000081 r6:bf092bf4 r5:bf0b6a2c r4:edf19000 r3:bf0b5bc8 [] (em28xx_unregister_extension [em28xx]) from [] (em28xx_rc_unregister+0x14/0x1c [em28xx_rc]) r6:00000800 r5:00000000 r4:bf0b6a50 r3:bf0b64c8 [] (em28xx_rc_unregister [em28xx_rc]) from [] (SyS_delete_module+0x11c/0x180) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) r6:00000001 r5:beb0f813 r4:b8b17d00 Fixes: f52226099382 ("[media] em28xx: extend the support for device buttons") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index d8dc03aadfbd..ef36c49ef166 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -654,8 +654,6 @@ next_button: if (dev->num_button_polling_addresses) { memset(dev->button_polling_last_values, 0, EM28XX_NUM_BUTTON_ADDRESSES_MAX); - INIT_DELAYED_WORK(&dev->buttons_query_work, - em28xx_query_buttons); schedule_delayed_work(&dev->buttons_query_work, msecs_to_jiffies(dev->button_polling_interval)); } @@ -689,6 +687,7 @@ static int em28xx_ir_init(struct em28xx *dev) } kref_get(&dev->ref); + INIT_DELAYED_WORK(&dev->buttons_query_work, em28xx_query_buttons); if (dev->board.buttons) em28xx_init_buttons(dev); -- cgit v1.2.3 From 0418ca6073478f54f1da2e4013fa50d36838de75 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:20 -0300 Subject: [media] em28xx: ensure "closing" messages terminate with a newline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lockdep splat addressed in a previous commit revealed that at least one message in em28xx-input.c was missing a new line: em28178 #0: Closing input extensionINFO: trying to register non-static key. Further inspection shows several other messages also miss a new line. These will be fixed in a subsequent patch. Fixes: aa929ad783c0 ("[media] em28xx: print a message at disconnect") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 2 +- drivers/media/usb/em28xx/em28xx-dvb.c | 2 +- drivers/media/usb/em28xx/em28xx-input.c | 2 +- drivers/media/usb/em28xx/em28xx-video.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 44ae1e0661e6..52dc9d70da72 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -981,7 +981,7 @@ static int em28xx_audio_fini(struct em28xx *dev) return 0; } - em28xx_info("Closing audio extension"); + em28xx_info("Closing audio extension\n"); if (dev->adev.sndcard) { snd_card_disconnect(dev->adev.sndcard); diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 9877b699c6bc..80c384c390e2 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1724,7 +1724,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) if (!dev->dvb) return 0; - em28xx_info("Closing DVB extension"); + em28xx_info("Closing DVB extension\n"); dvb = dev->dvb; client = dvb->i2c_client_tuner; diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index ef36c49ef166..aea22deadc0a 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -832,7 +832,7 @@ static int em28xx_ir_fini(struct em28xx *dev) return 0; } - em28xx_info("Closing input extension"); + em28xx_info("Closing input extension\n"); em28xx_shutdown_buttons(dev); diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 3691b39424be..eeb4ad5a3a76 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1958,7 +1958,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev) if (v4l2 == NULL) return 0; - em28xx_info("Closing video extension"); + em28xx_info("Closing video extension\n"); mutex_lock(&dev->lock); -- cgit v1.2.3 From ebfd59cf549899a166d595bf1eab7eec3299ebe7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:26 -0300 Subject: [media] em28xx-input: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-input. Fix these. Fixes: 5025076aadfe ("[media] em28xx-input: implement em28xx_ops: suspend/resume hooks") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index aea22deadc0a..4007356d991d 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -861,7 +861,7 @@ static int em28xx_ir_suspend(struct em28xx *dev) if (dev->is_audio_only) return 0; - em28xx_info("Suspending input extension"); + em28xx_info("Suspending input extension\n"); if (ir) cancel_delayed_work_sync(&ir->work); cancel_delayed_work_sync(&dev->buttons_query_work); @@ -878,7 +878,7 @@ static int em28xx_ir_resume(struct em28xx *dev) if (dev->is_audio_only) return 0; - em28xx_info("Resuming input extension"); + em28xx_info("Resuming input extension\n"); /* if suspend calls ir_raw_event_unregister(), the should call ir_raw_event_register() */ if (ir) -- cgit v1.2.3 From 522adc7c1f70d302155bb07f7fdf5a7fe4ff9094 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:31 -0300 Subject: [media] em28xx-core: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-core. Fix these. Fixes: 9c669b731470 ("[media] em28xx: add suspend/resume to em28xx_ops") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 86461a708abe..37456079f490 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -1125,7 +1125,7 @@ int em28xx_suspend_extension(struct em28xx *dev) { const struct em28xx_ops *ops = NULL; - em28xx_info("Suspending extensions"); + em28xx_info("Suspending extensions\n"); mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(ops, &em28xx_extension_devlist, next) { if (ops->suspend) @@ -1139,7 +1139,7 @@ int em28xx_resume_extension(struct em28xx *dev) { const struct em28xx_ops *ops = NULL; - em28xx_info("Resuming extensions"); + em28xx_info("Resuming extensions\n"); mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(ops, &em28xx_extension_devlist, next) { if (ops->resume) -- cgit v1.2.3 From 7818b0aab87b680fb10f68eccebeeb6cd8283c73 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:36 -0300 Subject: [media] em28xx-audio: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-audio. Fix these. Fixes: 1b3fd2d34266 ("[media] em28xx-audio: don't hardcode audio URB calculus") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 52dc9d70da72..82d58eb3d32a 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -820,7 +820,7 @@ static int em28xx_audio_urb_init(struct em28xx *dev) if (urb_size > ep_size * npackets) npackets = DIV_ROUND_UP(urb_size, ep_size); - em28xx_info("Number of URBs: %d, with %d packets and %d size", + em28xx_info("Number of URBs: %d, with %d packets and %d size\n", num_urb, npackets, urb_size); /* Estimate the bytes per period */ -- cgit v1.2.3 From fbaa48d1853002c2e7bcf12c1fdc0f6fb16d1525 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:41 -0300 Subject: [media] em28xx-audio: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-audio. Fix these. Fixes: 6d746f91f230 ("[media] em28xx-audio: implement em28xx_ops: suspend/resume hooks") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 82d58eb3d32a..49a5f9532bd8 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -1005,7 +1005,7 @@ static int em28xx_audio_suspend(struct em28xx *dev) if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) return 0; - em28xx_info("Suspending audio extension"); + em28xx_info("Suspending audio extension\n"); em28xx_deinit_isoc_audio(dev); atomic_set(&dev->adev.stream_started, 0); return 0; @@ -1019,7 +1019,7 @@ static int em28xx_audio_resume(struct em28xx *dev) if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) return 0; - em28xx_info("Resuming audio extension"); + em28xx_info("Resuming audio extension\n"); /* Nothing to do other than schedule_work() ?? */ schedule_work(&dev->adev.wq_trigger); return 0; -- cgit v1.2.3 From a084c57fc1ccd24ef8e6ca41e75afa745d5dbb98 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:46 -0300 Subject: [media] em28xx-dvb: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-dvb. Fix these. Fixes: ca2b46dacbf5 ("[media] em28xx-dvb: implement em28xx_ops: suspend/resume hooks") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 80c384c390e2..aee70d483264 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1775,17 +1775,17 @@ static int em28xx_dvb_suspend(struct em28xx *dev) if (!dev->board.has_dvb) return 0; - em28xx_info("Suspending DVB extension"); + em28xx_info("Suspending DVB extension\n"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; if (dvb->fe[0]) { ret = dvb_frontend_suspend(dvb->fe[0]); - em28xx_info("fe0 suspend %d", ret); + em28xx_info("fe0 suspend %d\n", ret); } if (dvb->fe[1]) { dvb_frontend_suspend(dvb->fe[1]); - em28xx_info("fe1 suspend %d", ret); + em28xx_info("fe1 suspend %d\n", ret); } } @@ -1802,18 +1802,18 @@ static int em28xx_dvb_resume(struct em28xx *dev) if (!dev->board.has_dvb) return 0; - em28xx_info("Resuming DVB extension"); + em28xx_info("Resuming DVB extension\n"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; if (dvb->fe[0]) { ret = dvb_frontend_resume(dvb->fe[0]); - em28xx_info("fe0 resume %d", ret); + em28xx_info("fe0 resume %d\n", ret); } if (dvb->fe[1]) { ret = dvb_frontend_resume(dvb->fe[1]); - em28xx_info("fe1 resume %d", ret); + em28xx_info("fe1 resume %d\n", ret); } } -- cgit v1.2.3 From 32e63f0368ed16e5ac417dc0bc2a5f8acbfb1511 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Dec 2014 09:45:51 -0300 Subject: [media] em28xx-video: fix missing newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspection shows that newlines are missing from several kernel messages in em28xx-video. Fix these. Fixes: a61f68119af3 ("[media] em28xx-video: implement em28xx_ops: suspend/resume hooks") Cc: Signed-off-by: Russell King Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index eeb4ad5a3a76..9ecf65629b3d 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2007,7 +2007,7 @@ static int em28xx_v4l2_suspend(struct em28xx *dev) if (!dev->has_video) return 0; - em28xx_info("Suspending video extension"); + em28xx_info("Suspending video extension\n"); em28xx_stop_urbs(dev); return 0; } @@ -2020,7 +2020,7 @@ static int em28xx_v4l2_resume(struct em28xx *dev) if (!dev->has_video) return 0; - em28xx_info("Resuming video extension"); + em28xx_info("Resuming video extension\n"); /* what do we do here */ return 0; } -- cgit v1.2.3 From ab93ce06eef556cc85a016e12ff7c7a763f04c91 Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 11 Dec 2014 17:06:22 -0300 Subject: [media] rc: img-ir: add scancode requests to a struct The information being requested of hardware decode callbacks through the img-ir-hw scancode API is mounting up, so combine it into a struct which can be passed in with a single pointer rather than multiple pointer arguments. This allows it to be extended more easily without touching all the hardware decode callbacks. Signed-off-by: Sifan Naeem Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/img-ir-hw.c | 16 +++++++++------- drivers/media/rc/img-ir/img-ir-hw.h | 16 ++++++++++++++-- drivers/media/rc/img-ir/img-ir-jvc.c | 8 ++++---- drivers/media/rc/img-ir/img-ir-nec.c | 24 ++++++++++++------------ drivers/media/rc/img-ir/img-ir-sanyo.c | 8 ++++---- drivers/media/rc/img-ir/img-ir-sharp.c | 8 ++++---- drivers/media/rc/img-ir/img-ir-sony.c | 12 ++++++------ 7 files changed, 53 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 2fd47c9bf5d8..88fada5dd238 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -806,20 +806,22 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_priv_hw *hw = &priv->hw; const struct img_ir_decoder *dec = hw->decoder; int ret = IMG_IR_SCANCODE; - u32 scancode; - enum rc_type protocol = RC_TYPE_UNKNOWN; + struct img_ir_scancode_req request; + + request.protocol = RC_TYPE_UNKNOWN; if (dec->scancode) - ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols); + ret = dec->scancode(len, raw, hw->enabled_protocols, &request); else if (len >= 32) - scancode = (u32)raw; + request.scancode = (u32)raw; else if (len < 32) - scancode = (u32)raw & ((1 << len)-1); + request.scancode = (u32)raw & ((1 << len)-1); dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", scancode); - rc_keydown(hw->rdev, protocol, scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x\n", + request.scancode); + rc_keydown(hw->rdev, request.protocol, request.scancode, 0); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 5c2b216c5fe3..aeef3d1dd30d 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -132,6 +132,18 @@ struct img_ir_timing_regvals { #define IMG_IR_SCANCODE 0 /* new scancode */ #define IMG_IR_REPEATCODE 1 /* repeat the previous code */ +/** + * struct img_ir_scancode_req - Scancode request data. + * @protocol: Protocol code of received message (defaults to + * RC_TYPE_UNKNOWN). + * @scancode: Scan code of received message (must be written by + * handler if IMG_IR_SCANCODE is returned). + */ +struct img_ir_scancode_req { + enum rc_type protocol; + u32 scancode; +}; + /** * struct img_ir_decoder - Decoder settings for an IR protocol. * @type: Protocol types bitmap. @@ -162,8 +174,8 @@ struct img_ir_decoder { struct img_ir_control control; /* scancode logic */ - int (*scancode)(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols); + int (*scancode)(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request); int (*filter)(const struct rc_scancode_filter *in, struct img_ir_filter *out, u64 protocols); }; diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c index a60dda8bf706..d3e2fc0bcfe1 100644 --- a/drivers/media/rc/img-ir/img-ir-jvc.c +++ b/drivers/media/rc/img-ir/img-ir-jvc.c @@ -12,8 +12,8 @@ #include "img-ir-hw.h" /* Convert JVC data to a scancode */ -static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_jvc_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int cust, data; @@ -23,8 +23,8 @@ static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, cust = (raw >> 0) & 0xff; data = (raw >> 8) & 0xff; - *protocol = RC_TYPE_JVC; - *scancode = cust << 8 | data; + request->protocol = RC_TYPE_JVC; + request->scancode = cust << 8 | data; return IMG_IR_SCANCODE; } diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c index 739897549b5b..27a7ea8f1260 100644 --- a/drivers/media/rc/img-ir/img-ir-nec.c +++ b/drivers/media/rc/img-ir/img-ir-nec.c @@ -13,8 +13,8 @@ #include /* Convert NEC data to a scancode */ -static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int addr, addr_inv, data, data_inv; /* a repeat code has no data */ @@ -30,23 +30,23 @@ static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol, if ((data_inv ^ data) != 0xff) { /* 32-bit NEC (used by Apple and TiVo remotes) */ /* scan encoding: as transmitted, MSBit = first received bit */ - *scancode = bitrev8(addr) << 24 | - bitrev8(addr_inv) << 16 | - bitrev8(data) << 8 | - bitrev8(data_inv); + request->scancode = bitrev8(addr) << 24 | + bitrev8(addr_inv) << 16 | + bitrev8(data) << 8 | + bitrev8(data_inv); } else if ((addr_inv ^ addr) != 0xff) { /* Extended NEC */ /* scan encoding: AAaaDD */ - *scancode = addr << 16 | - addr_inv << 8 | - data; + request->scancode = addr << 16 | + addr_inv << 8 | + data; } else { /* Normal NEC */ /* scan encoding: AADD */ - *scancode = addr << 8 | - data; + request->scancode = addr << 8 | + data; } - *protocol = RC_TYPE_NEC; + request->protocol = RC_TYPE_NEC; return IMG_IR_SCANCODE; } diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c index 6b0653ecdf5a..f394994ffc22 100644 --- a/drivers/media/rc/img-ir/img-ir-sanyo.c +++ b/drivers/media/rc/img-ir/img-ir-sanyo.c @@ -23,8 +23,8 @@ #include "img-ir-hw.h" /* Convert Sanyo data to a scancode */ -static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_sanyo_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int addr, addr_inv, data, data_inv; /* a repeat code has no data */ @@ -44,8 +44,8 @@ static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol, return -EINVAL; /* Normal Sanyo */ - *protocol = RC_TYPE_SANYO; - *scancode = addr << 8 | data; + request->protocol = RC_TYPE_SANYO; + request->scancode = addr << 8 | data; return IMG_IR_SCANCODE; } diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c index 3300a38802ac..fe5acc4f030e 100644 --- a/drivers/media/rc/img-ir/img-ir-sharp.c +++ b/drivers/media/rc/img-ir/img-ir-sharp.c @@ -12,8 +12,8 @@ #include "img-ir-hw.h" /* Convert Sharp data to a scancode */ -static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_sharp_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int addr, cmd, exp, chk; @@ -32,8 +32,8 @@ static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol, /* probably the second half of the message */ return -EINVAL; - *protocol = RC_TYPE_SHARP; - *scancode = addr << 8 | cmd; + request->protocol = RC_TYPE_SHARP; + request->scancode = addr << 8 | cmd; return IMG_IR_SCANCODE; } diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c index 3a0f17b0752c..7f7375f82ed6 100644 --- a/drivers/media/rc/img-ir/img-ir-sony.c +++ b/drivers/media/rc/img-ir/img-ir-sony.c @@ -12,8 +12,8 @@ #include "img-ir-hw.h" /* Convert Sony data to a scancode */ -static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int dev, subdev, func; @@ -25,7 +25,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol, raw >>= 7; dev = raw & 0x1f; /* next 5 bits */ subdev = 0; - *protocol = RC_TYPE_SONY12; + request->protocol = RC_TYPE_SONY12; break; case 15: if (!(enabled_protocols & RC_BIT_SONY15)) @@ -34,7 +34,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol, raw >>= 7; dev = raw & 0xff; /* next 8 bits */ subdev = 0; - *protocol = RC_TYPE_SONY15; + request->protocol = RC_TYPE_SONY15; break; case 20: if (!(enabled_protocols & RC_BIT_SONY20)) @@ -44,12 +44,12 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol, dev = raw & 0x1f; /* next 5 bits */ raw >>= 5; subdev = raw & 0xff; /* next 8 bits */ - *protocol = RC_TYPE_SONY20; + request->protocol = RC_TYPE_SONY20; break; default: return -EINVAL; } - *scancode = dev << 16 | subdev << 8 | func; + request->scancode = dev << 16 | subdev << 8 | func; return IMG_IR_SCANCODE; } -- cgit v1.2.3 From 33e01833268d2f006e599b863a21d4e219f96bd7 Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 11 Dec 2014 17:06:23 -0300 Subject: [media] rc: img-ir: pass toggle bit to the rc driver Add toggle bit to struct img_ir_scancode_req so that protocols can provide it to img_ir_handle_data(), and pass that toggle bit up to rc_keydown instead of 0. This is needed for the upcoming rc-5 and rc-6 patches. Signed-off-by: Sifan Naeem Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/img-ir-hw.c | 8 +++++--- drivers/media/rc/img-ir/img-ir-hw.h | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 88fada5dd238..9cecda73f980 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -809,6 +809,7 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_scancode_req request; request.protocol = RC_TYPE_UNKNOWN; + request.toggle = 0; if (dec->scancode) ret = dec->scancode(len, raw, hw->enabled_protocols, &request); @@ -819,9 +820,10 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", - request.scancode); - rc_keydown(hw->rdev, request.protocol, request.scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x, toggle %u\n", + request.scancode, request.toggle); + rc_keydown(hw->rdev, request.protocol, request.scancode, + request.toggle); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index aeef3d1dd30d..beac3a6c4660 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -138,10 +138,12 @@ struct img_ir_timing_regvals { * RC_TYPE_UNKNOWN). * @scancode: Scan code of received message (must be written by * handler if IMG_IR_SCANCODE is returned). + * @toggle: Toggle bit (defaults to 0). */ struct img_ir_scancode_req { enum rc_type protocol; u32 scancode; + u8 toggle; }; /** -- cgit v1.2.3 From 02744c8c9a11a64bce740528077cf5223ab60e31 Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 11 Dec 2014 17:06:24 -0300 Subject: [media] rc: img-ir: biphase enabled with workaround Biphase decoding in the current img-ir has got a quirk, where multiple Interrupts are generated when an incomplete IR code is received by the decoder. Patch adds a work around for the quirk and enables biphase decoding. Signed-off-by: Sifan Naeem Acked-by: James Hogan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/img-ir-hw.c | 60 +++++++++++++++++++++++++++++++++++-- drivers/media/rc/img-ir/img-ir-hw.h | 4 +++ 2 files changed, 61 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 9cecda73f980..5c32f05b32ec 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -52,6 +52,11 @@ static struct img_ir_decoder *img_ir_decoders[] = { #define IMG_IR_QUIRK_CODE_BROKEN 0x1 /* Decode is broken */ #define IMG_IR_QUIRK_CODE_LEN_INCR 0x2 /* Bit length needs increment */ +/* + * The decoder generates rapid interrupts without actually having + * received any new data after an incomplete IR code is decoded. + */ +#define IMG_IR_QUIRK_CODE_IRQ 0x4 /* functions for preprocessing timings, ensuring max is set */ @@ -542,6 +547,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv, */ spin_unlock_irq(&priv->lock); del_timer_sync(&hw->end_timer); + del_timer_sync(&hw->suspend_timer); spin_lock_irq(&priv->lock); hw->stopping = false; @@ -861,6 +867,29 @@ static void img_ir_end_timer(unsigned long arg) spin_unlock_irq(&priv->lock); } +/* + * Timer function to re-enable the current protocol after it had been + * cleared when invalid interrupts were generated due to a quirk in the + * img-ir decoder. + */ +static void img_ir_suspend_timer(unsigned long arg) +{ + struct img_ir_priv *priv = (struct img_ir_priv *)arg; + + spin_lock_irq(&priv->lock); + /* + * Don't overwrite enabled valid/match IRQs if they have already been + * changed by e.g. a filter change. + */ + if ((priv->hw.quirk_suspend_irq & IMG_IR_IRQ_EDGE) == + img_ir_read(priv, IMG_IR_IRQ_ENABLE)) + img_ir_write(priv, IMG_IR_IRQ_ENABLE, + priv->hw.quirk_suspend_irq); + /* enable */ + img_ir_write(priv, IMG_IR_CONTROL, priv->hw.reg_timings.ctrl); + spin_unlock_irq(&priv->lock); +} + #ifdef CONFIG_COMMON_CLK static void img_ir_change_frequency(struct img_ir_priv *priv, struct clk_notifier_data *change) @@ -926,15 +955,38 @@ void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status) if (!hw->decoder) return; + ct = hw->decoder->control.code_type; + ir_status = img_ir_read(priv, IMG_IR_STATUS); - if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) + if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) { + if (!(priv->hw.ct_quirks[ct] & IMG_IR_QUIRK_CODE_IRQ) || + hw->stopping) + return; + /* + * The below functionality is added as a work around to stop + * multiple Interrupts generated when an incomplete IR code is + * received by the decoder. + * The decoder generates rapid interrupts without actually + * having received any new data. After a single interrupt it's + * expected to clear up, but instead multiple interrupts are + * rapidly generated. only way to get out of this loop is to + * reset the control register after a short delay. + */ + img_ir_write(priv, IMG_IR_CONTROL, 0); + hw->quirk_suspend_irq = img_ir_read(priv, IMG_IR_IRQ_ENABLE); + img_ir_write(priv, IMG_IR_IRQ_ENABLE, + hw->quirk_suspend_irq & IMG_IR_IRQ_EDGE); + + /* Timer activated to re-enable the protocol. */ + mod_timer(&hw->suspend_timer, + jiffies + msecs_to_jiffies(5)); return; + } ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2); img_ir_write(priv, IMG_IR_STATUS, ir_status); len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT; /* some versions report wrong length for certain code types */ - ct = hw->decoder->control.code_type; if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR) ++len; @@ -976,7 +1028,7 @@ static void img_ir_probe_hw_caps(struct img_ir_priv *priv) hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN] |= IMG_IR_QUIRK_CODE_LEN_INCR; hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE] - |= IMG_IR_QUIRK_CODE_BROKEN; + |= IMG_IR_QUIRK_CODE_IRQ; hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS] |= IMG_IR_QUIRK_CODE_BROKEN; } @@ -995,6 +1047,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv) /* Set up the end timer */ setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv); + setup_timer(&hw->suspend_timer, img_ir_suspend_timer, + (unsigned long)priv); /* Register a clock notifier */ if (!IS_ERR(priv->clk)) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index beac3a6c4660..b31ffc947e41 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -218,6 +218,7 @@ enum img_ir_mode { * @rdev: Remote control device * @clk_nb: Notifier block for clock notify events. * @end_timer: Timer until repeat timeout. + * @suspend_timer: Timer to re-enable protocol. * @decoder: Current decoder settings. * @enabled_protocols: Currently enabled protocols. * @clk_hz: Current core clock rate in Hz. @@ -228,12 +229,14 @@ enum img_ir_mode { * @stopping: Indicates that decoder is being taken down and timers * should not be restarted. * @suspend_irqen: Saved IRQ enable mask over suspend. + * @quirk_suspend_irq: Saved IRQ enable mask over quirk suspend timer. */ struct img_ir_priv_hw { unsigned int ct_quirks[4]; struct rc_dev *rdev; struct notifier_block clk_nb; struct timer_list end_timer; + struct timer_list suspend_timer; const struct img_ir_decoder *decoder; u64 enabled_protocols; unsigned long clk_hz; @@ -244,6 +247,7 @@ struct img_ir_priv_hw { enum img_ir_mode mode; bool stopping; u32 suspend_irqen; + u32 quirk_suspend_irq; }; static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw) -- cgit v1.2.3 From aa7383db35aec23906868a632a964b5783a5254d Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 11 Dec 2014 17:06:25 -0300 Subject: [media] rc: img-ir: add philips rc5 decoder module Add img-ir module for decoding Philips rc5 protocol. Signed-off-by: Sifan Naeem Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/Kconfig | 7 +++ drivers/media/rc/img-ir/Makefile | 1 + drivers/media/rc/img-ir/img-ir-hw.c | 3 ++ drivers/media/rc/img-ir/img-ir-hw.h | 1 + drivers/media/rc/img-ir/img-ir-rc5.c | 88 ++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc5.c (limited to 'drivers') diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index 580715c7fc5e..b20b3e9b441e 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -60,3 +60,10 @@ config IR_IMG_SANYO help Say Y here to enable support for the Sanyo protocol (used by Sanyo, Aiwa, Chinon remotes) in the ImgTec infrared decoder block. + +config IR_IMG_RC5 + bool "Philips RC5 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC5 protocol in the ImgTec + infrared decoder block. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 92a459d99509..898b1b8086d0 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -6,6 +6,7 @@ img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o +img-ir-$(CONFIG_IR_IMG_RC5) += img-ir-rc5.o img-ir-objs := $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 5c32f05b32ec..13f0b1e0e211 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -41,6 +41,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #endif #ifdef CONFIG_IR_IMG_SANYO &img_ir_sanyo, +#endif +#ifdef CONFIG_IR_IMG_RC5 + &img_ir_rc5, #endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index b31ffc947e41..b9e799d57d99 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -187,6 +187,7 @@ extern struct img_ir_decoder img_ir_jvc; extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; +extern struct img_ir_decoder img_ir_rc5; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc5.c b/drivers/media/rc/img-ir/img-ir-rc5.c new file mode 100644 index 000000000000..a8a28a377eee --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc5.c @@ -0,0 +1,88 @@ +/* + * ImgTec IR Decoder setup for Philips RC-5 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * 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. + */ + +#include "img-ir-hw.h" + +/* Convert RC5 data to a scancode */ +static int img_ir_rc5_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, tgl, start; + + /* Quirk in the decoder shifts everything by 2 to the left. */ + raw >>= 2; + + start = (raw >> 13) & 0x01; + tgl = (raw >> 11) & 0x01; + addr = (raw >> 6) & 0x1f; + cmd = raw & 0x3f; + /* + * 12th bit is used to extend the command in extended RC5 and has + * no effect on standard RC5. + */ + cmd += ((raw >> 12) & 0x01) ? 0 : 0x40; + + if (!start) + return -EINVAL; + + request->protocol = RC_TYPE_RC5; + request->scancode = addr << 8 | cmd; + request->toggle = tgl; + return IMG_IR_SCANCODE; +} + +/* Convert RC5 scancode to RC5 data filter */ +static int img_ir_rc5_filter(const struct rc_scancode_filter *in, + struct img_ir_filter *out, u64 protocols) +{ + /* Not supported by the hw. */ + return -EINVAL; +} + +/* + * RC-5 decoder + * see http://www.sbprojects.com/knowledge/ir/rc5.php + */ +struct img_ir_decoder img_ir_rc5 = { + .type = RC_BIT_RC5, + .control = { + .bitoriend2 = 1, + .code_type = IMG_IR_CODETYPE_BIPHASE, + .decodend2 = 1, + }, + /* main timings */ + .tolerance = 16, + .unit = 888888, /* 1/36k*32=888.888microseconds */ + .timings = { + /* 10 symbol */ + .s10 = { + .pulse = { 1 }, + .space = { 1 }, + }, + + /* 11 symbol */ + .s11 = { + .pulse = { 1 }, + .space = { 1 }, + }, + + /* free time */ + .ft = { + .minlen = 14, + .maxlen = 14, + .ft_min = 5, + }, + }, + + /* scancode logic */ + .scancode = img_ir_rc5_scancode, + .filter = img_ir_rc5_filter, +}; -- cgit v1.2.3 From cb9564e133f4f790920d715714790512085bb2e3 Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 11 Dec 2014 17:06:26 -0300 Subject: [media] rc: img-ir: add philips rc6 decoder module Add img-ir module for decoding Philips rc6 protocol. Signed-off-by: Sifan Naeem Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/img-ir/Kconfig | 8 +++ drivers/media/rc/img-ir/Makefile | 1 + drivers/media/rc/img-ir/img-ir-hw.c | 3 + drivers/media/rc/img-ir/img-ir-hw.h | 1 + drivers/media/rc/img-ir/img-ir-rc6.c | 117 +++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc6.c (limited to 'drivers') diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index b20b3e9b441e..a896d3c83a1c 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -67,3 +67,11 @@ config IR_IMG_RC5 help Say Y here to enable support for the RC5 protocol in the ImgTec infrared decoder block. + +config IR_IMG_RC6 + bool "Philips RC6 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC6 protocol in the ImgTec + infrared decoder block. + Note: This version only supports mode 0. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 898b1b8086d0..8e6d458e66ad 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -7,6 +7,7 @@ img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o img-ir-$(CONFIG_IR_IMG_RC5) += img-ir-rc5.o +img-ir-$(CONFIG_IR_IMG_RC6) += img-ir-rc6.o img-ir-objs := $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 13f0b1e0e211..7bb71bc9f534 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -44,6 +44,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #endif #ifdef CONFIG_IR_IMG_RC5 &img_ir_rc5, +#endif +#ifdef CONFIG_IR_IMG_RC6 + &img_ir_rc6, #endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index b9e799d57d99..91a297731661 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -188,6 +188,7 @@ extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; extern struct img_ir_decoder img_ir_rc5; +extern struct img_ir_decoder img_ir_rc6; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc6.c b/drivers/media/rc/img-ir/img-ir-rc6.c new file mode 100644 index 000000000000..de1e27534968 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc6.c @@ -0,0 +1,117 @@ +/* + * ImgTec IR Decoder setup for Philips RC-6 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * 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. + */ + +#include "img-ir-hw.h" + +/* Convert RC6 data to a scancode */ +static int img_ir_rc6_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, mode, trl1, trl2; + + /* + * Due to a side effect of the decoder handling the double length + * Trailer bit, the header information is a bit scrambled, and the + * raw data is shifted incorrectly. + * This workaround effectively recovers the header bits. + * + * The Header field should look like this: + * + * StartBit ModeBit2 ModeBit1 ModeBit0 TrailerBit + * + * But what we get is: + * + * ModeBit2 ModeBit1 ModeBit0 TrailerBit1 TrailerBit2 + * + * The start bit is not important to recover the scancode. + */ + + raw >>= 27; + + trl1 = (raw >> 17) & 0x01; + trl2 = (raw >> 16) & 0x01; + + mode = (raw >> 18) & 0x07; + addr = (raw >> 8) & 0xff; + cmd = raw & 0xff; + + /* + * Due to the above explained irregularity the trailer bits cannot + * have the same value. + */ + if (trl1 == trl2) + return -EINVAL; + + /* Only mode 0 supported for now */ + if (mode) + return -EINVAL; + + request->protocol = RC_TYPE_RC6_0; + request->scancode = addr << 8 | cmd; + request->toggle = trl2; + return IMG_IR_SCANCODE; +} + +/* Convert RC6 scancode to RC6 data filter */ +static int img_ir_rc6_filter(const struct rc_scancode_filter *in, + struct img_ir_filter *out, u64 protocols) +{ + /* Not supported by the hw. */ + return -EINVAL; +} + +/* + * RC-6 decoder + * see http://www.sbprojects.com/knowledge/ir/rc6.php + */ +struct img_ir_decoder img_ir_rc6 = { + .type = RC_BIT_RC6_0, + .control = { + .bitorien = 1, + .code_type = IMG_IR_CODETYPE_BIPHASE, + .decoden = 1, + .decodinpol = 1, + }, + /* main timings */ + .tolerance = 20, + /* + * Due to a quirk in the img-ir decoder, default header values do + * not work, the values described below were extracted from + * successful RTL test cases. + */ + .timings = { + /* leader symbol */ + .ldr = { + .pulse = { 650 }, + .space = { 660 }, + }, + /* 0 symbol */ + .s00 = { + .pulse = { 370 }, + .space = { 370 }, + }, + /* 01 symbol */ + .s01 = { + .pulse = { 370 }, + .space = { 370 }, + }, + /* free time */ + .ft = { + .minlen = 21, + .maxlen = 21, + .ft_min = 2666, /* 2.666 ms */ + }, + }, + + /* scancode logic */ + .scancode = img_ir_rc6_scancode, + .filter = img_ir_rc6_filter, +}; -- cgit v1.2.3 From 221ca91220a9a9efe27cde2ae4ef16e7dd44db69 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 10 Dec 2014 21:22:01 -0300 Subject: [media] staging: media: lirc: lirc_zilog.c: fix quoted strings split across lines checkpatch makes an exception to the 80-colum rule for quotes strings, and Documentation/CodingStyle recommends not splitting quotes strings across lines because it breaks the ability to grep for the string. Fixing these. WARNING: quoted string split across lines Signed-off-by: Luis de Bethencourt Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_zilog.c | 61 ++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index cc872fb4ca68..0d29c8e3ea03 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -372,14 +372,14 @@ static int add_to_buf(struct IR *ir) ret); if (failures >= 3) { mutex_unlock(&ir->ir_lock); - dev_err(ir->l.dev, "unable to read from the IR chip " - "after 3 resets, giving up\n"); + dev_err(ir->l.dev, + "unable to read from the IR chip after 3 resets, giving up\n"); break; } /* Looks like the chip crashed, reset it */ - dev_err(ir->l.dev, "polling the IR receiver chip failed, " - "trying reset\n"); + dev_err(ir->l.dev, + "polling the IR receiver chip failed, trying reset\n"); set_current_state(TASK_UNINTERRUPTIBLE); if (kthread_should_stop()) { @@ -405,8 +405,9 @@ static int add_to_buf(struct IR *ir) ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); mutex_unlock(&ir->ir_lock); if (ret != sizeof(keybuf)) { - dev_err(ir->l.dev, "i2c_master_recv failed with %d -- " - "keeping last read buffer\n", ret); + dev_err(ir->l.dev, + "i2c_master_recv failed with %d -- keeping last read buffer\n", + ret); } else { rx->b[0] = keybuf[3]; rx->b[1] = keybuf[4]; @@ -713,8 +714,9 @@ static int send_boot_data(struct IR_tx *tx) buf[0]); return 0; } - dev_notice(tx->ir->l.dev, "Zilog/Hauppauge IR blaster firmware version " - "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]); + dev_notice(tx->ir->l.dev, + "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n", + buf[1], buf[2], buf[3]); return 0; } @@ -792,9 +794,9 @@ static int fw_load(struct IR_tx *tx) if (!read_uint8(&data, tx_data->endp, &version)) goto corrupt; if (version != 1) { - dev_err(tx->ir->l.dev, "unsupported code set file version (%u, expected" - "1) -- please upgrade to a newer driver", - version); + dev_err(tx->ir->l.dev, + "unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver", + version); fw_unload_locked(); ret = -EFAULT; goto out; @@ -981,8 +983,9 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) ret = get_key_data(data_block, code, key); if (ret == -EPROTO) { - dev_err(tx->ir->l.dev, "failed to get data for code %u, key %u -- check " - "lircd.conf entries\n", code, key); + dev_err(tx->ir->l.dev, + "failed to get data for code %u, key %u -- check lircd.conf entries\n", + code, key); return ret; } else if (ret != 0) return ret; @@ -1057,12 +1060,14 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) ret = i2c_master_send(tx->c, buf, 1); if (ret == 1) break; - dev_dbg(tx->ir->l.dev, "NAK expected: i2c_master_send " - "failed with %d (try %d)\n", ret, i+1); + dev_dbg(tx->ir->l.dev, + "NAK expected: i2c_master_send failed with %d (try %d)\n", + ret, i+1); } if (ret != 1) { - dev_err(tx->ir->l.dev, "IR TX chip never got ready: last i2c_master_send " - "failed with %d\n", ret); + dev_err(tx->ir->l.dev, + "IR TX chip never got ready: last i2c_master_send failed with %d\n", + ret); return ret < 0 ? ret : -EFAULT; } @@ -1165,12 +1170,12 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, */ if (ret != 0) { /* Looks like the chip crashed, reset it */ - dev_err(tx->ir->l.dev, "sending to the IR transmitter chip " - "failed, trying reset\n"); + dev_err(tx->ir->l.dev, + "sending to the IR transmitter chip failed, trying reset\n"); if (failures >= 3) { - dev_err(tx->ir->l.dev, "unable to send to the IR chip " - "after 3 resets, giving up\n"); + dev_err(tx->ir->l.dev, + "unable to send to the IR chip after 3 resets, giving up\n"); mutex_unlock(&ir->ir_lock); mutex_unlock(&tx->client_lock); put_ir_tx(tx, false); @@ -1540,8 +1545,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Proceed only if the Rx client is also ready or not needed */ if (rx == NULL && !tx_only) { - dev_info(tx->ir->l.dev, "probe of IR Tx on %s (i2c-%d) done. Waiting" - " on IR Rx.\n", adap->name, adap->nr); + dev_info(tx->ir->l.dev, + "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n", + adap->name, adap->nr); goto out_ok; } } else { @@ -1579,8 +1585,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) "zilog-rx-i2c-%d", adap->nr); if (IS_ERR(rx->task)) { ret = PTR_ERR(rx->task); - dev_err(tx->ir->l.dev, "%s: could not start IR Rx polling thread" - "\n", __func__); + dev_err(tx->ir->l.dev, + "%s: could not start IR Rx polling thread\n", + __func__); /* Failed kthread, so put back the ir ref */ put_ir_device(ir, true); /* Failure exit, so put back rx ref from i2c_client */ @@ -1592,8 +1599,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Proceed only if the Tx client is also ready */ if (tx == NULL) { - pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting" - " on IR Tx.\n", adap->name, adap->nr); + pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting on IR Tx.\n", + adap->name, adap->nr); goto out_ok; } } -- cgit v1.2.3 From 2ecd424006d0e17c526a85e7d5ac4ace476b0dbb Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 10 Dec 2014 21:22:52 -0300 Subject: [media] staging: media: lirc: lirc_zilog.c: keep consistency in dev functions The previous patch switched some dev functions to move the string to a second line. Doing this for all similar functions because it makes the driver easier to read if all similar lines use the same criteria. Signed-off-by: Luis de Bethencourt Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_zilog.c | 57 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 0d29c8e3ea03..20fa40102886 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -369,7 +369,7 @@ static int add_to_buf(struct IR *ir) ret = i2c_master_send(rx->c, sendbuf, 1); if (ret != 1) { dev_err(ir->l.dev, "i2c_master_send failed with %d\n", - ret); + ret); if (failures >= 3) { mutex_unlock(&ir->ir_lock); dev_err(ir->l.dev, @@ -412,8 +412,9 @@ static int add_to_buf(struct IR *ir) rx->b[0] = keybuf[3]; rx->b[1] = keybuf[4]; rx->b[2] = keybuf[5]; - dev_dbg(ir->l.dev, "key (0x%02x/0x%02x)\n", - rx->b[0], rx->b[1]); + dev_dbg(ir->l.dev, + "key (0x%02x/0x%02x)\n", + rx->b[0], rx->b[1]); } /* key pressed ? */ @@ -657,8 +658,8 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block) dev_dbg(tx->ir->l.dev, "%*ph", 5, buf); ret = i2c_master_send(tx->c, buf, tosend + 1); if (ret != tosend + 1) { - dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", - ret); + dev_err(tx->ir->l.dev, + "i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } i += tosend; @@ -711,7 +712,7 @@ static int send_boot_data(struct IR_tx *tx) } if ((buf[0] != 0x80) && (buf[0] != 0xa0)) { dev_err(tx->ir->l.dev, "unexpected IR TX init response: %02x\n", - buf[0]); + buf[0]); return 0; } dev_notice(tx->ir->l.dev, @@ -761,8 +762,9 @@ static int fw_load(struct IR_tx *tx) /* Request codeset data file */ ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); if (ret != 0) { - dev_err(tx->ir->l.dev, "firmware haup-ir-blaster.bin not available (%d)\n", - ret); + dev_err(tx->ir->l.dev, + "firmware haup-ir-blaster.bin not available (%d)\n", + ret); ret = ret < 0 ? ret : -EFAULT; goto out; } @@ -812,7 +814,7 @@ static int fw_load(struct IR_tx *tx) goto corrupt; dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n", - tx_data->num_code_sets); + tx_data->num_code_sets); tx_data->code_sets = vmalloc( tx_data->num_code_sets * sizeof(char *)); @@ -942,8 +944,9 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n, unsigned char buf[MAX_XFER_SIZE]; if (rbuf->chunk_size > sizeof(buf)) { - dev_err(ir->l.dev, "chunk_size is too big (%d)!\n", - rbuf->chunk_size); + dev_err(ir->l.dev, + "chunk_size is too big (%d)!\n", + rbuf->chunk_size); ret = -EINVAL; break; } @@ -966,8 +969,8 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n, put_ir_rx(rx, false); set_current_state(TASK_RUNNING); - dev_dbg(ir->l.dev, "read result = %d (%s)\n", - ret, ret ? "Error" : "OK"); + dev_dbg(ir->l.dev, "read result = %d (%s)\n", ret, + ret ? "Error" : "OK"); return ret ? ret : written; } @@ -1079,7 +1082,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) } if (buf[0] != 0x80) { dev_err(tx->ir->l.dev, "unexpected IR TX response #2: %02x\n", - buf[0]); + buf[0]); return -EFAULT; } @@ -1231,7 +1234,7 @@ static unsigned int poll(struct file *filep, poll_table *wait) ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM); dev_dbg(ir->l.dev, "poll result = %s\n", - ret ? "POLLIN|POLLRDNORM" : "none"); + ret ? "POLLIN|POLLRDNORM" : "none"); return ret; } @@ -1338,7 +1341,8 @@ static int close(struct inode *node, struct file *filep) struct IR *ir = filep->private_data; if (ir == NULL) { - dev_err(ir->l.dev, "close: no private_data attached to the file!\n"); + dev_err(ir->l.dev, + "close: no private_data attached to the file!\n"); return -ENODEV; } @@ -1609,13 +1613,15 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->l.minor = minor; /* module option: user requested minor number */ ir->l.minor = lirc_register_driver(&ir->l); if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { - dev_err(tx->ir->l.dev, "%s: \"minor\" must be between 0 and %d (%d)!\n", - __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); + dev_err(tx->ir->l.dev, + "%s: \"minor\" must be between 0 and %d (%d)!\n", + __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); ret = -EBADRQC; goto out_put_xx; } - dev_info(ir->l.dev, "IR unit on %s (i2c-%d) registered as lirc%d and ready\n", - adap->name, adap->nr, ir->l.minor); + dev_info(ir->l.dev, + "IR unit on %s (i2c-%d) registered as lirc%d and ready\n", + adap->name, adap->nr, ir->l.minor); out_ok: if (rx != NULL) @@ -1623,8 +1629,9 @@ out_ok: if (tx != NULL) put_ir_tx(tx, true); put_ir_device(ir, true); - dev_info(ir->l.dev, "probe of IR %s on %s (i2c-%d) done\n", - tx_probe ? "Tx" : "Rx", adap->name, adap->nr); + dev_info(ir->l.dev, + "probe of IR %s on %s (i2c-%d) done\n", + tx_probe ? "Tx" : "Rx", adap->name, adap->nr); mutex_unlock(&ir_devices_lock); return 0; @@ -1636,9 +1643,9 @@ out_put_xx: out_put_ir: put_ir_device(ir, true); out_no_ir: - dev_err(&client->dev, "%s: probing IR %s on %s (i2c-%d) failed with %d\n", - __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, - ret); + dev_err(&client->dev, + "%s: probing IR %s on %s (i2c-%d) failed with %d\n", + __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, ret); mutex_unlock(&ir_devices_lock); return ret; } -- cgit v1.2.3 From 40b8a5a65aa3ba51a80f7bd667df8403d54d6e7a Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 10 Dec 2014 21:23:42 -0300 Subject: [media] staging: media: lirc: lirc_zilog.c: missing newline in dev_err() Missing newline character at the end of string passed to dev_err() Signed-off-by: Luis de Bethencourt Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_zilog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 20fa40102886..e16627ca488e 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -797,7 +797,7 @@ static int fw_load(struct IR_tx *tx) goto corrupt; if (version != 1) { dev_err(tx->ir->l.dev, - "unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver", + "unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n", version); fw_unload_locked(); ret = -EFAULT; -- cgit v1.2.3 From 983c5bd26b86ba1c0d79b770e596bb8b77e42f32 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 8 Dec 2014 13:17:07 -0300 Subject: [media] rc-main: Re-apply filter for no-op protocol change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit da6e162d6a46 ("[media] rc-core: simplify sysfs code"), when the IR protocol is set using the sysfs interface to the same set of protocols that are already set, store_protocols() does not refresh the scancode filter with the new protocol, even if it has already called the change_protocol() callback successfully. This results in the filter being disabled in the hardware and not re-enabled until the filter is set again using sysfs. Fix in store_protocols() by still re-applying the filter whenever the change_protocol() driver callback succeeded. The problem can be reproduced with the img-ir driver by setting a filter, and then setting the protocol to the same protocol that is already set: $ echo nec > protocols $ echo 0xffff > filter_mask $ echo nec > protocols After this, messages which don't match the filter were still being received. Fixes: da6e162d6a46 ("[media] rc-core: simplify sysfs code") Reported-by: Sifan Naeem Signed-off-by: James Hogan Cc: David Härdeman Cc: # v3.17+ Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 86ffcd54339e..f8c5e47a30aa 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1021,16 +1021,16 @@ static ssize_t store_protocols(struct device *device, goto out; } - if (new_protocols == old_protocols) { - rc = len; - goto out; + if (new_protocols != old_protocols) { + *current_protocols = new_protocols; + IR_dprintk(1, "Protocols changed to 0x%llx\n", + (long long)new_protocols); } - *current_protocols = new_protocols; - IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols); - /* - * If the protocol is changed the filter needs updating. + * If a protocol change was attempted the filter may need updating, even + * if the actual protocol mask hasn't changed (since the driver may have + * cleared the filter). * Try setting the same filter with the new protocol (if any). * Fall back to clearing the filter. */ -- cgit v1.2.3 From 99f3cd52aee21091ce62442285a68873e3be833f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 15 Dec 2014 10:40:28 -0300 Subject: [media] vb2-vmalloc: Protect DMA-specific code by #ifdef CONFIG_HAS_DMA If NO_DMA=y: drivers/built-in.o: In function `vb2_vmalloc_dmabuf_ops_detach': videobuf2-vmalloc.c:(.text+0x6f11b0): undefined reference to `dma_unmap_sg' drivers/built-in.o: In function `vb2_vmalloc_dmabuf_ops_map': videobuf2-vmalloc.c:(.text+0x6f1266): undefined reference to `dma_unmap_sg' videobuf2-vmalloc.c:(.text+0x6f1282): undefined reference to `dma_map_sg' As we don't want to make the core VIDEOBUF2_VMALLOC depend on HAS_DMA (it's v4l2 core code, and selected by a lot of drivers), stub out the DMA support if HAS_DMA is not set. Signed-off-by: Geert Uytterhoeven Acked-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-vmalloc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c index 7f6d41b18de9..bcde88572429 100644 --- a/drivers/media/v4l2-core/videobuf2-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c @@ -211,6 +211,7 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma) return 0; } +#ifdef CONFIG_HAS_DMA /*********************************************/ /* DMABUF ops for exporters */ /*********************************************/ @@ -380,6 +381,8 @@ static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flag return dbuf; } +#endif /* CONFIG_HAS_DMA */ + /*********************************************/ /* callbacks for DMABUF buffers */ @@ -437,7 +440,9 @@ const struct vb2_mem_ops vb2_vmalloc_memops = { .put = vb2_vmalloc_put, .get_userptr = vb2_vmalloc_get_userptr, .put_userptr = vb2_vmalloc_put_userptr, +#ifdef CONFIG_HAS_DMA .get_dmabuf = vb2_vmalloc_get_dmabuf, +#endif .map_dmabuf = vb2_vmalloc_map_dmabuf, .unmap_dmabuf = vb2_vmalloc_unmap_dmabuf, .attach_dmabuf = vb2_vmalloc_attach_dmabuf, -- cgit v1.2.3 From 3b952436d4cca59bfdc8ede174dd746a4b31c804 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Dec 2014 10:59:13 -0300 Subject: [media] cx23885: do not unregister demod I2C client twice on error Demod I2C client should be NULL after demod is unregistered on error path, otherwise it will be unregistered again when driver is unload. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index c47d18270cfc..6bb79355892c 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1793,12 +1793,14 @@ static int dvb_register(struct cx23885_tsport *port) client_tuner->dev.driver == NULL) { module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; goto frontend_detach; } if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; goto frontend_detach; } port->i2c_client_tuner = client_tuner; @@ -1843,12 +1845,14 @@ static int dvb_register(struct cx23885_tsport *port) client_tuner->dev.driver == NULL) { module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; goto frontend_detach; } if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; goto frontend_detach; } port->i2c_client_tuner = client_tuner; @@ -1989,6 +1993,7 @@ static int dvb_register(struct cx23885_tsport *port) client_tuner->dev.driver == NULL) { module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; goto frontend_detach; } if (!try_module_get(client_tuner->dev.driver->owner)) { -- cgit v1.2.3 From a593f2cfc1b89d0342b82242ed3d31c1a4494f24 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Dec 2014 11:05:59 -0300 Subject: [media] cx23885: correct some I2C client indentations These comparisons fit single line. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 6bb79355892c..0f60bc4b8611 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1823,8 +1823,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2168_config; request_module(info.type); client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info); - if (client_demod == NULL || - client_demod->dev.driver == NULL) + if (client_demod == NULL || client_demod->dev.driver == NULL) goto frontend_detach; if (!try_module_get(client_demod->dev.driver->owner)) { i2c_unregister_device(client_demod); @@ -1841,8 +1840,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2157_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) { + if (client_tuner == NULL || client_tuner->dev.driver == NULL) { module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); port->i2c_client_demod = NULL; @@ -1878,8 +1876,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &m88ts2022_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) + if (client_tuner == NULL || client_tuner->dev.driver == NULL) goto frontend_detach; if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); @@ -1925,8 +1922,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &m88ts2022_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) + if (client_tuner == NULL || client_tuner->dev.driver == NULL) goto frontend_detach; if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); @@ -1971,8 +1967,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2168_config; request_module(info.type); client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info); - if (client_demod == NULL || - client_demod->dev.driver == NULL) + if (client_demod == NULL || client_demod->dev.driver == NULL) goto frontend_detach; if (!try_module_get(client_demod->dev.driver->owner)) { i2c_unregister_device(client_demod); @@ -1989,8 +1984,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2157_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) { + if (client_tuner == NULL || client_tuner->dev.driver == NULL) { module_put(client_demod->dev.driver->owner); i2c_unregister_device(client_demod); port->i2c_client_demod = NULL; @@ -2115,8 +2109,7 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &sp2_config; request_module(info.type); client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info); - if (client_ci == NULL || - client_ci->dev.driver == NULL) { + if (client_ci == NULL || client_ci->dev.driver == NULL) { if (client_tuner) { module_put(client_tuner->dev.driver->owner); i2c_unregister_device(client_tuner); -- cgit v1.2.3 From 93009ca673394f0bfb99aa8d8e76f3581a2b38e8 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 11 Dec 2014 15:44:51 -0300 Subject: [media] cx23885: fix I2C scan printout 1) I2C slave addresses were printed so called 8-bit format. Use standard 7-bit notation. 2) I2C slave address was printed with hex formatted without leading zeros, which makes output one digit shorter in a case of address fit to one hex digit. Use 4 char wide hex number with leading zeros as usually used for I2C slave addresses. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c index fd71306af6e2..1135ea3f6ce5 100644 --- a/drivers/media/pci/cx23885/cx23885-i2c.c +++ b/drivers/media/pci/cx23885/cx23885-i2c.c @@ -300,8 +300,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c) rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n", - name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + printk(KERN_INFO "%s: i2c scan: found device @ 0x%04x [%s]\n", + name, i, i2c_devs[i] ? i2c_devs[i] : "???"); } } -- cgit v1.2.3 From 1fc77d013ba85a29e2edfaba02fd21e8c8187fae Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 11 Dec 2014 16:12:46 -0300 Subject: [media] cx23885: Hauppauge WinTV-HVR5525 Add board profile for Hauppauge WinTV-HVR5525. Device is build upon following main components: Conexant CX23888 Montage M88RS6000 Allegro A8293 Silicon Labs Si2168-B40 Silicon Labs Si2157-A30 Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/Kconfig | 1 + drivers/media/pci/cx23885/cx23885-cards.c | 43 ++++++++++++++ drivers/media/pci/cx23885/cx23885-dvb.c | 98 +++++++++++++++++++++++++++++++ drivers/media/pci/cx23885/cx23885.h | 1 + 4 files changed, 143 insertions(+) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index f613314b360b..74d774e5227b 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig @@ -41,6 +41,7 @@ config VIDEO_CX23885 select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Conexant 23885 based diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index db99ca2613ba..2a92bcdceb8f 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -706,6 +706,11 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR5525] = { + .name = "Hauppauge WinTV-HVR5525", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -989,6 +994,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x4254, .subdevice = 0x0982, .card = CX23885_BOARD_DVBSKY_T982, + }, { + .subvendor = 0x0070, + .subdevice = 0xf038, + .card = CX23885_BOARD_HAUPPAUGE_HVR5525, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1161,6 +1170,8 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 85721: /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR, Dual channel ATSC and Basic analog */ + case 150329: + /* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */ break; default: printk(KERN_WARNING "%s: warning: " @@ -1632,6 +1643,29 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) msleep(100); cx23885_gpio_set(dev, GPIO_2); break; + case CX23885_BOARD_HAUPPAUGE_HVR5525: + /* + * GPIO-00 IR_WIDE + * GPIO-02 wake# + * GPIO-03 VAUX Pres. + * GPIO-07 PROG# + * GPIO-08 SAT_RESN + * GPIO-09 TER_RESN + * GPIO-10 B2_SENSE + * GPIO-11 B1_SENSE + * GPIO-15 IR_LED_STATUS + * GPIO-19 IR_NARROW + * GPIO-20 Blauster1 + * ALTGPIO VAUX_SWITCH + * AUX_PLL_CLK : Blaster2 + */ + /* Put the parts into reset and back */ + cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1); + cx23885_gpio_clear(dev, GPIO_8 | GPIO_9); + msleep(100); + cx23885_gpio_set(dev, GPIO_8 | GPIO_9); + msleep(100); + break; } } @@ -1873,6 +1907,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_HAUPPAUGE_HVR4400: case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE: + case CX23885_BOARD_HAUPPAUGE_HVR5525: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -1997,6 +2032,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_HAUPPAUGE_HVR5525: + ts1->gen_ctrl_val = 0x5; /* Parallel */ + 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: diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 0f60bc4b8611..63c0de3cfadb 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -74,6 +74,7 @@ #include "sp2.h" #include "m88ds3103.h" #include "m88ts2022.h" +#include "m88rs6000t.h" static unsigned int debug; @@ -915,6 +916,16 @@ static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = { .agc = 0x99, }; +static const struct m88ds3103_config hauppauge_hvr5525_m88ds3103_config = { + .i2c_addr = 0x69, + .clock = 27000000, + .i2c_wr_max = 33, + .ts_mode = M88DS3103_TS_PARALLEL, + .ts_clk = 16000, + .ts_clk_pol = 1, + .agc = 0x99, +}; + static int netup_altera_fpga_rw(void *device, int flag, int data, int read) { struct cx23885_dev *dev = (struct cx23885_dev *)device; @@ -1999,6 +2010,93 @@ static int dvb_register(struct cx23885_tsport *port) } port->i2c_client_tuner = client_tuner; break; + case CX23885_BOARD_HAUPPAUGE_HVR5525: + switch (port->nr) { + struct m88rs6000t_config m88rs6000t_config; + + /* port b - satellite */ + case 1: + /* attach frontend */ + fe0->dvb.frontend = dvb_attach(m88ds3103_attach, + &hauppauge_hvr5525_m88ds3103_config, + &dev->i2c_bus[0].i2c_adap, &adapter); + if (fe0->dvb.frontend == NULL) + break; + + /* attach SEC */ + if (!dvb_attach(a8293_attach, fe0->dvb.frontend, + &dev->i2c_bus[0].i2c_adap, + &hauppauge_a8293_config)) + goto frontend_detach; + + /* attach tuner */ + memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config)); + m88rs6000t_config.fe = fe0->dvb.frontend; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "m88rs6000t", I2C_NAME_SIZE); + info.addr = 0x21; + info.platform_data = &m88rs6000t_config; + request_module("%s", info.type); + client_tuner = i2c_new_device(adapter, &info); + if (!client_tuner || !client_tuner->dev.driver) + goto frontend_detach; + if (!try_module_get(client_tuner->dev.driver->owner)) { + i2c_unregister_device(client_tuner); + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; + + /* delegate signal strength measurement to tuner */ + fe0->dvb.frontend->ops.read_signal_strength = + fe0->dvb.frontend->ops.tuner_ops.get_rf_strength; + break; + /* port c - terrestrial/cable */ + case 2: + /* attach frontend */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &fe0->dvb.frontend; + si2168_config.ts_mode = SI2168_TS_SERIAL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module("%s", info.type); + client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info); + if (!client_demod || !client_demod->dev.driver) + goto frontend_detach; + if (!try_module_get(client_demod->dev.driver->owner)) { + i2c_unregister_device(client_demod); + goto frontend_detach; + } + port->i2c_client_demod = client_demod; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = fe0->dvb.frontend; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module("%s", info.type); + client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info); + if (!client_tuner || !client_tuner->dev.driver) { + module_put(client_demod->dev.driver->owner); + i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; + goto frontend_detach; + } + if (!try_module_get(client_tuner->dev.driver->owner)) { + i2c_unregister_device(client_tuner); + module_put(client_demod->dev.driver->owner); + i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; + goto frontend_detach; + } + port->i2c_client_tuner = client_tuner; + break; + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index f55cd12da0fd..4f358ebc8e6b 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -99,6 +99,7 @@ #define CX23885_BOARD_DVBSKY_S950 49 #define CX23885_BOARD_DVBSKY_S952 50 #define CX23885_BOARD_DVBSKY_T982 51 +#define CX23885_BOARD_HAUPPAUGE_HVR5525 52 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From 92ced56d06a9c5cfa3ef3b628068c36fd3c34786 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Sat, 6 Dec 2014 18:57:31 -0300 Subject: [media] mn88472: add 5MHz dvb-t2 bandwitdh support Signed-off-by: Benjamin Larsson Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/mn88472/mn88472.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c index 36ef39bcc215..b6b015c2b516 100644 --- a/drivers/staging/media/mn88472/mn88472.c +++ b/drivers/staging/media/mn88472/mn88472.c @@ -61,7 +61,10 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) switch (c->delivery_system) { case SYS_DVBT: case SYS_DVBT2: - if (c->bandwidth_hz <= 6000000) { + if (c->bandwidth_hz <= 5000000) { + memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7); + bw_val2 = 0x03; + } else if (c->bandwidth_hz <= 6000000) { /* IF 3570000 Hz, BW 6000000 Hz */ memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7); bw_val2 = 0x02; -- cgit v1.2.3 From 551c33e729f654ecfaed00ad399f5d2a631b72cb Mon Sep 17 00:00:00 2001 From: Jurgen Kramer Date: Mon, 8 Dec 2014 05:30:44 -0300 Subject: [media] Si2168: increase timeout to fix firmware loading Increase si2168 cmd execute timeout to prevent firmware load failures. Tests shows it takes up to 52ms to load the 'dvb-demod-si2168-a30-01.fw' firmware. Increase timeout to a safe value of 70ms. Signed-off-by: Jurgen Kramer Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index ce9ab442b4b6..d2f1a3e959e7 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -39,7 +39,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) if (cmd->rlen) { /* wait cmd execution terminate */ - #define TIMEOUT 50 + #define TIMEOUT 70 timeout = jiffies + msecs_to_jiffies(TIMEOUT); while (!time_after(jiffies, timeout)) { ret = i2c_master_recv(s->client, cmd->args, cmd->rlen); -- cgit v1.2.3 From e32b31ae45c18679c186e67aa41d0e2318cae487 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2014 13:45:40 -0200 Subject: [media] mb86a20s: remove unused debug modprobe parameter The debug parameter is not used anymore, as this module was converted already to use dev_dbg(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mb86a20s.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index e6f165a5b90d..8f54c39ca63f 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -22,10 +22,6 @@ #define NUM_LAYERS 3 -static int debug = 1; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); - enum mb86a20s_bandwidth { MB86A20S_13SEG = 0, MB86A20S_13SEG_PARTIAL = 1, -- cgit v1.2.3 From a6c896c1b25d17e3098dbc295434925a04a5911e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 11 Dec 2014 16:53:17 -0300 Subject: [media] coda: coda-common: Remove mx53 entry from coda_platform_ids As mx53 is a dt-only architecture we can safely remove its entry from the coda_platform_ids[] structure. Signed-off-by: Fabio Estevam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 39330a70f752..efed0b802943 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -2001,7 +2001,6 @@ static const struct coda_devtype coda_devdata[] = { static struct platform_device_id coda_platform_ids[] = { { .name = "coda-imx27", .driver_data = CODA_IMX27 }, - { .name = "coda-imx53", .driver_data = CODA_IMX53 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, coda_platform_ids); -- cgit v1.2.3 From 3edd59abb0ad2142954eff6bb430a9020477f539 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 14 Dec 2014 03:49:47 -0300 Subject: [media] media: stb0899_drv: use time_after() To be future-proof and for better readability the time comparisons are modified to use time_after() instead of plain, error-prone math. Signed-off-by: Asaf Vertz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_drv.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 19646fbb061d..c73899d3a53d 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -691,7 +692,7 @@ static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeo reg = stb0899_read_reg(state, STB0899_DISSTATUS); if (!STB0899_GETFIELD(FIFOFULL, reg)) break; - if ((jiffies - start) > timeout) { + if (time_after(jiffies, start + timeout)) { dprintk(state->verbose, FE_ERROR, 1, "timed out !!"); return -ETIMEDOUT; } @@ -733,7 +734,7 @@ static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout) while (!STB0899_GETFIELD(RXEND, reg)) { reg = stb0899_read_reg(state, STB0899_DISRX_ST0); - if (jiffies - start > timeout) { + if (time_after(jiffies, start + timeout)) { dprintk(state->verbose, FE_ERROR, 1, "timed out!!"); return -ETIMEDOUT; } @@ -782,7 +783,7 @@ static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout) while (!STB0899_GETFIELD(TXIDLE, reg)) { reg = stb0899_read_reg(state, STB0899_DISSTATUS); - if (jiffies - start > timeout) { + if (time_after(jiffies, start + timeout)) { dprintk(state->verbose, FE_ERROR, 1, "timed out!!"); return -ETIMEDOUT; } -- cgit v1.2.3 From 4c036c4ffa12e195fd09c04a0bee16afff19c55b Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Fri, 19 Dec 2014 06:35:32 -0300 Subject: [media] media: Kconfig: drop duplicate dependency of HAS_DMA this patch drops duplicate dependency of HAS_DMA from VIDEO_SH_VEU. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 71e8873ceb94..d18a5353e4a4 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -214,7 +214,6 @@ config VIDEO_SAMSUNG_EXYNOS_GSC config VIDEO_SH_VEU tristate "SuperH VEU mem2mem video processing driver" depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA - depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV help -- cgit v1.2.3 From 58fc0461f6c2e5684177f4616b1e60e36c0237e4 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 21 Dec 2014 09:56:49 -0300 Subject: [media] media: radio: wl128x: fmdrv_rx.c: Remove unused function Remove the function fm_rx_get_rds_system() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_rx.c | 16 ---------------- drivers/media/radio/wl128x/fmdrv_rx.h | 1 - 2 files changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c index 09632cb26cb6..cfaeb2417fbb 100644 --- a/drivers/media/radio/wl128x/fmdrv_rx.c +++ b/drivers/media/radio/wl128x/fmdrv_rx.c @@ -785,22 +785,6 @@ int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode) return 0; } -/* Returns current RDS operation mode */ -int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode) -{ - if (fmdev->curr_fmmode != FM_MODE_RX) - return -EPERM; - - if (rds_mode == NULL) { - fmerr("Invalid memory\n"); - return -ENOMEM; - } - - *rds_mode = fmdev->rx.rds_mode; - - return 0; -} - /* Configures Alternate Frequency switch mode */ int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode) { diff --git a/drivers/media/radio/wl128x/fmdrv_rx.h b/drivers/media/radio/wl128x/fmdrv_rx.h index 32add81f8d87..23922188882f 100644 --- a/drivers/media/radio/wl128x/fmdrv_rx.h +++ b/drivers/media/radio/wl128x/fmdrv_rx.h @@ -40,7 +40,6 @@ void fm_rx_reset_station_info(struct fmdev *); int fm_rx_seek(struct fmdev *, u32, u32, u32); int fm_rx_get_rds_mode(struct fmdev *, u8 *); -int fm_rx_get_rds_system(struct fmdev *, u8 *); int fm_rx_get_mute_mode(struct fmdev *, u8 *); int fm_rx_get_volume(struct fmdev *, u16 *); int fm_rx_get_band_freq_range(struct fmdev *, -- cgit v1.2.3 From 861360a56d0bcbc0bec92a1f1266c66880b2e5ae Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2014 09:46:27 -0300 Subject: [media] videobuf: make unused exported functions static The videobuf_dma_init* and videobuf_dma_map() functions are no longer used except in videobuf-dma-sg.c itself. Make them static. These functions were abused in various drivers. All those drivers have now been fixed, so by no longer exporting these functions future abuse is now prevented. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf-dma-sg.c | 15 +++++---------- include/media/videobuf-dma-sg.h | 8 -------- 2 files changed, 5 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 3ff15f1c9d70..f669cedca8bd 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -145,12 +145,11 @@ struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf) } EXPORT_SYMBOL_GPL(videobuf_to_dma); -void videobuf_dma_init(struct videobuf_dmabuf *dma) +static void videobuf_dma_init(struct videobuf_dmabuf *dma) { memset(dma, 0, sizeof(*dma)); dma->magic = MAGIC_DMABUF; } -EXPORT_SYMBOL_GPL(videobuf_dma_init); static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) @@ -195,7 +194,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, return 0; } -int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) { int ret; @@ -206,9 +205,8 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, return ret; } -EXPORT_SYMBOL_GPL(videobuf_dma_init_user); -int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, int nr_pages) { int i; @@ -267,9 +265,8 @@ out_free_pages: return -ENOMEM; } -EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); -int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages) { dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n", @@ -284,9 +281,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) +static int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) { MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -328,7 +324,6 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) return 0; } -EXPORT_SYMBOL_GPL(videobuf_dma_map); int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index fb6fd4d8f4ed..d8b27854e3bf 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -84,16 +84,8 @@ struct videobuf_dma_sg_memory { * Despite the name, this is totally unrelated to videobuf, except that * videobuf-dma-sg uses the same API internally. */ -void videobuf_dma_init(struct videobuf_dmabuf *dma); -int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, - unsigned long data, unsigned long size); -int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, - int nr_pages); -int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, - dma_addr_t addr, int nr_pages); int videobuf_dma_free(struct videobuf_dmabuf *dma); -int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma); int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); -- cgit v1.2.3 From 8a4d9a9cf90202c37308ddd84818100c27c4155c Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Wed, 24 Dec 2014 08:35:59 -0300 Subject: [media] solo6x10: s/unsigned char/u8/ s/unsigned char/u8/ Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-enc.c | 6 +++--- drivers/media/pci/solo6x10/solo6x10-g723.c | 4 ++-- drivers/media/pci/solo6x10/solo6x10-jpeg.h | 4 ++-- drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c | 18 +++++++++--------- drivers/media/pci/solo6x10/solo6x10.h | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/solo6x10/solo6x10-enc.c b/drivers/media/pci/solo6x10/solo6x10-enc.c index d19c0aef5abc..d28211bb9674 100644 --- a/drivers/media/pci/solo6x10/solo6x10-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-enc.c @@ -136,11 +136,11 @@ static void solo_capture_config(struct solo_dev *solo_dev) int solo_osd_print(struct solo_enc_dev *solo_enc) { struct solo_dev *solo_dev = solo_enc->solo_dev; - unsigned char *str = solo_enc->osd_text; + u8 *str = solo_enc->osd_text; u8 *buf = solo_enc->osd_buf; u32 reg; const struct font_desc *vga = find_font("VGA8x16"); - const unsigned char *vga_data; + const u8 *vga_data; int i, j; if (WARN_ON_ONCE(!vga)) @@ -154,7 +154,7 @@ int solo_osd_print(struct solo_enc_dev *solo_enc) } memset(buf, 0, SOLO_OSD_WRITE_SIZE); - vga_data = (const unsigned char *)vga->data; + vga_data = (const u8 *)vga->data; for (i = 0; *str; i++, str++) { for (j = 0; j < 16; j++) { diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index c7141f2e63bd..7ddc76709caa 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c @@ -56,8 +56,8 @@ struct solo_snd_pcm { int on; spinlock_t lock; - struct solo_dev *solo_dev; - unsigned char *g723_buf; + struct solo_dev *solo_dev; + u8 *g723_buf; dma_addr_t g723_dma; }; diff --git a/drivers/media/pci/solo6x10/solo6x10-jpeg.h b/drivers/media/pci/solo6x10/solo6x10-jpeg.h index 1c66a46da514..3c611bd3f2d8 100644 --- a/drivers/media/pci/solo6x10/solo6x10-jpeg.h +++ b/drivers/media/pci/solo6x10/solo6x10-jpeg.h @@ -21,7 +21,7 @@ #ifndef __SOLO6X10_JPEG_H #define __SOLO6X10_JPEG_H -static const unsigned char jpeg_header[] = { +static const u8 jpeg_header[] = { 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c, 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16, @@ -106,7 +106,7 @@ static const unsigned char jpeg_header[] = { /* This is the byte marker for the start of the DQT */ #define DQT_START 17 #define DQT_LEN 138 -static const unsigned char jpeg_dqt[4][DQT_LEN] = { +static const u8 jpeg_dqt[4][DQT_LEN] = { { 0xff, 0xdb, 0x00, 0x43, 0x00, 0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 1c9688f58c5c..53fff5425c13 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -38,28 +38,28 @@ #define DMA_ALIGN 4096 /* 6010 M4V */ -static unsigned char vop_6010_ntsc_d1[] = { +static u8 vop_6010_ntsc_d1[] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, 0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f, }; -static unsigned char vop_6010_ntsc_cif[] = { +static u8 vop_6010_ntsc_cif[] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, 0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f, }; -static unsigned char vop_6010_pal_d1[] = { +static u8 vop_6010_pal_d1[] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, 0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f, }; -static unsigned char vop_6010_pal_cif[] = { +static u8 vop_6010_pal_cif[] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, @@ -67,25 +67,25 @@ static unsigned char vop_6010_pal_cif[] = { }; /* 6110 h.264 */ -static unsigned char vop_6110_ntsc_d1[] = { +static u8 vop_6110_ntsc_d1[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, 0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, }; -static unsigned char vop_6110_ntsc_cif[] = { +static u8 vop_6110_ntsc_cif[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, 0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, }; -static unsigned char vop_6110_pal_d1[] = { +static u8 vop_6110_pal_d1[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, 0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, }; -static unsigned char vop_6110_pal_cif[] = { +static u8 vop_6110_pal_cif[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, 0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, @@ -149,7 +149,7 @@ void solo_update_mode(struct solo_enc_dev *solo_enc) { struct solo_dev *solo_dev = solo_enc->solo_dev; int vop_len; - unsigned char *vop; + u8 *vop; solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0; solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1); diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h index 6c9bc707773f..1ca54b08b3aa 100644 --- a/drivers/media/pci/solo6x10/solo6x10.h +++ b/drivers/media/pci/solo6x10/solo6x10.h @@ -168,9 +168,9 @@ struct solo_enc_dev { __aligned(4); /* VOP stuff */ - unsigned char vop[64]; + u8 vop[64]; int vop_len; - unsigned char jpeg_header[1024]; + u8 jpeg_header[1024]; int jpeg_len; u32 fmt; -- cgit v1.2.3 From 469ac53e7c99b51bf0fa4ea0955271272e4ca2ea Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Wed, 24 Dec 2014 08:36:00 -0300 Subject: [media] solo6x10: Fix eeprom_* functions buffer's type s/unsigned short/u16/ Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c index 8cbe6b49f4c2..570d119ea18b 100644 --- a/drivers/media/pci/solo6x10/solo6x10-core.c +++ b/drivers/media/pci/solo6x10/solo6x10-core.c @@ -182,7 +182,7 @@ static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr, { struct solo_dev *solo_dev = container_of(dev, struct solo_dev, dev); - unsigned short *p = (unsigned short *)buf; + u16 *p = (u16 *)buf; int i; if (count & 0x1) @@ -212,7 +212,7 @@ static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr, { struct solo_dev *solo_dev = container_of(dev, struct solo_dev, dev); - unsigned short *p = (unsigned short *)buf; + u16 *p = (u16 *)buf; int count = (full_eeprom ? 128 : 64); int i; -- cgit v1.2.3 From b1bb7ee2d973ac4cd32f18f1801600ac502d37fa Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Wed, 24 Dec 2014 08:36:01 -0300 Subject: [media] solo6x10: Fix solo_eeprom_read retval type s/unsigned short/u16/ Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/solo6x10/solo6x10-eeprom.c b/drivers/media/pci/solo6x10/solo6x10-eeprom.c index da25ce4a6952..8e81186dc785 100644 --- a/drivers/media/pci/solo6x10/solo6x10-eeprom.c +++ b/drivers/media/pci/solo6x10/solo6x10-eeprom.c @@ -103,7 +103,7 @@ unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en) __be16 solo_eeprom_read(struct solo_dev *solo_dev, int loc) { int read_cmd = loc | (EE_READ_CMD << ADDR_LEN); - unsigned short retval = 0; + u16 retval = 0; int i; solo_eeprom_cmd(solo_dev, read_cmd); -- cgit v1.2.3 From af29ba97f17d2ba691d685f55436be5a82a3223d Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Wed, 24 Dec 2014 08:43:36 -0300 Subject: [media] solo6x10: s/uint8_t/u8/ s/uint8_t/u8/ Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-tw28.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/solo6x10/solo6x10-tw28.c b/drivers/media/pci/solo6x10/solo6x10-tw28.c index edd0781ee4b5..0632d3f7c73c 100644 --- a/drivers/media/pci/solo6x10/solo6x10-tw28.c +++ b/drivers/media/pci/solo6x10/solo6x10-tw28.c @@ -510,7 +510,7 @@ static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr) #define FIRST_ACTIVE_LINE 0x0008 #define LAST_ACTIVE_LINE 0x0102 -static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals, +static void saa712x_write_regs(struct solo_dev *dev, const u8 *vals, int start, int n) { for (; start < n; start++, vals++) { @@ -532,7 +532,7 @@ static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals, static void saa712x_setup(struct solo_dev *dev) { const int reg_start = 0x26; - const uint8_t saa7128_regs_ntsc[] = { + const u8 saa7128_regs_ntsc[] = { /* :0x26 */ 0x0d, 0x00, /* :0x28 */ -- cgit v1.2.3 From 30a8f2a08dfe61b3447476cf124d07c892f3ade0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Dec 2014 11:35:32 -0300 Subject: [media] au0828: Use setup_timer Convert a call to init_timer and accompanying intializations of the timer's data and function fields to a call to setup_timer. A simplified version of the semantic match that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression t,f,d; @@ -t.function = f; -t.data = d; -init_timer(&t); +setup_timer(&t,f,d); // Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 8a7a54750aee..60a684600456 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -2042,13 +2042,10 @@ int au0828_analog_register(struct au0828_dev *dev, INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); - dev->vid_timeout.function = au0828_vid_buffer_timeout; - dev->vid_timeout.data = (unsigned long) dev; - init_timer(&dev->vid_timeout); - - dev->vbi_timeout.function = au0828_vbi_buffer_timeout; - dev->vbi_timeout.data = (unsigned long) dev; - init_timer(&dev->vbi_timeout); + setup_timer(&dev->vid_timeout, au0828_vid_buffer_timeout, + (unsigned long)dev); + setup_timer(&dev->vbi_timeout, au0828_vbi_buffer_timeout, + (unsigned long)dev); dev->width = NTSC_STD_W; dev->height = NTSC_STD_H; -- cgit v1.2.3 From 8bf554cafdc9292633af89b3401f2aa62719b591 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Dec 2014 11:35:33 -0300 Subject: [media] s2255drv: Use setup_timer Convert a call to init_timer and accompanying intializations of the timer's data and function fields to a call to setup_timer. A simplified version of the semantic match that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression t,f,d; @@ -init_timer(&t); +setup_timer(&t,f,d); -t.function = f; -t.data = d; // Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/s2255/s2255drv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index de55e96fed15..0f3c34d47ec3 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -2274,9 +2274,7 @@ static int s2255_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); goto errorEP; } - init_timer(&dev->timer); - dev->timer.function = s2255_timer; - dev->timer.data = (unsigned long)dev->fw_data; + setup_timer(&dev->timer, s2255_timer, (unsigned long)dev->fw_data); init_waitqueue_head(&dev->fw_data->wait_fw); for (i = 0; i < MAX_CHANNELS; i++) { struct s2255_vc *vc = &dev->vc[i]; -- cgit v1.2.3 From f57cffb93457e968edac3afcae26f5c7670ed985 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Dec 2014 11:35:36 -0300 Subject: [media] usbvision: Use setup_timer Convert a call to init_timer and accompanying intializations of the timer's data and function fields to a call to setup_timer. A simplified version of the semantic match that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression t,f,d; @@ -init_timer(&t); +setup_timer(&t,f,d); -t.data = d; -t.function = f; // The semantic patch also changes the cast to long to a cast to unsigned long in the data initializer, as unsigned long is the type of the data field. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 2144b7b31be0..44b0c28d69b6 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -2194,9 +2194,8 @@ static void usbvision_power_off_timer(unsigned long data) void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) { - init_timer(&usbvision->power_off_timer); - usbvision->power_off_timer.data = (long)usbvision; - usbvision->power_off_timer.function = usbvision_power_off_timer; + setup_timer(&usbvision->power_off_timer, usbvision_power_off_timer, + (unsigned long)usbvision); } void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) -- cgit v1.2.3 From 03f23fc51dc943fbda437abf04df5d6a8498addc Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Dec 2014 11:35:50 -0300 Subject: [media] pvrusb2: Use setup_timer Convert a call to init_timer and accompanying intializations of the timer's data and function fields to a call to setup_timer. A simplified version of the semantic match that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression t,f,d; @@ -init_timer(&t); +setup_timer(&t,f,d); -t.data = d; -t.function = f; // Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 2fd9b5e0e2a9..08f2f5aced9f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2425,22 +2425,18 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, } if (!hdw) goto fail; - init_timer(&hdw->quiescent_timer); - hdw->quiescent_timer.data = (unsigned long)hdw; - hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; + setup_timer(&hdw->quiescent_timer, pvr2_hdw_quiescent_timeout, + (unsigned long)hdw); - init_timer(&hdw->decoder_stabilization_timer); - hdw->decoder_stabilization_timer.data = (unsigned long)hdw; - hdw->decoder_stabilization_timer.function = - pvr2_hdw_decoder_stabilization_timeout; + setup_timer(&hdw->decoder_stabilization_timer, + pvr2_hdw_decoder_stabilization_timeout, + (unsigned long)hdw); - init_timer(&hdw->encoder_wait_timer); - hdw->encoder_wait_timer.data = (unsigned long)hdw; - hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; + setup_timer(&hdw->encoder_wait_timer, pvr2_hdw_encoder_wait_timeout, + (unsigned long)hdw); - init_timer(&hdw->encoder_run_timer); - hdw->encoder_run_timer.data = (unsigned long)hdw; - hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout; + setup_timer(&hdw->encoder_run_timer, pvr2_hdw_encoder_run_timeout, + (unsigned long)hdw); hdw->master_state = PVR2_STATE_DEAD; @@ -3680,10 +3676,8 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, hdw->ctl_timeout_flag = 0; hdw->ctl_write_pend_flag = 0; hdw->ctl_read_pend_flag = 0; - init_timer(&timer); + setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw); timer.expires = jiffies + timeout; - timer.data = (unsigned long)hdw; - timer.function = pvr2_ctl_timeout; if (write_len) { hdw->cmd_debug_state = 2; -- cgit v1.2.3 From 11ede411b40d77174e28fda2d5cdfd43eb7b2b16 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Mon, 29 Dec 2014 11:29:39 -0300 Subject: [media] tw68: remove unnecessary version.h inclusion Based on versioncheck. Signed-off-by: Fabian Frederick Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw68/tw68.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h index 7a7501bd165f..93f2335e004b 100644 --- a/drivers/media/pci/tw68/tw68.h +++ b/drivers/media/pci/tw68/tw68.h @@ -25,7 +25,6 @@ * GNU General Public License for more details. */ -#include #include #include #include -- cgit v1.2.3 From 8059278603a24e6a5fe6fe3cd0787b9b7005a7df Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Mon, 29 Dec 2014 11:29:42 -0300 Subject: [media] vivid: remove unnecessary version.h inclusion Based on versioncheck. Signed-off-by: Fabian Frederick Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h index 9dc463a40ed3..bd8b1c760b3f 100644 --- a/drivers/media/platform/vivid/vivid-tpg.h +++ b/drivers/media/platform/vivid/vivid-tpg.h @@ -20,7 +20,6 @@ #ifndef _VIVID_TPG_H_ #define _VIVID_TPG_H_ -#include #include #include #include -- cgit v1.2.3 From 05a2ea7835b173bac745e95cda5f8dc1e634dced Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 13:13:20 -0300 Subject: [media] media: i2c: adv7604.c: Remove some unused functions Removes some functions that are not used anywhere: vblanking() hblanking() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 10 ---------- drivers/media/i2c/adv7842.c | 10 ---------- drivers/media/i2c/ths8200.c | 10 ---------- 3 files changed, 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index e43dd2e2a38a..0c81926a508d 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -333,21 +333,11 @@ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd) return container_of(sd, struct adv7604_state, sd); } -static inline unsigned hblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_WIDTH(t); -} - static inline unsigned htotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_WIDTH(t); } -static inline unsigned vblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_HEIGHT(t); -} - static inline unsigned vtotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_HEIGHT(t); diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 75d26dfd0939..6bc872d43717 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -220,21 +220,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd; } -static inline unsigned hblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_WIDTH(t); -} - static inline unsigned htotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_WIDTH(t); } -static inline unsigned vblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_HEIGHT(t); -} - static inline unsigned vtotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_HEIGHT(t); diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 656d889c1c79..4ebd329d7b42 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -58,21 +58,11 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) return container_of(sd, struct ths8200_state, sd); } -static inline unsigned hblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_WIDTH(t); -} - static inline unsigned htotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_WIDTH(t); } -static inline unsigned vblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_HEIGHT(t); -} - static inline unsigned vtotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_HEIGHT(t); -- cgit v1.2.3 From df58433145eeafd541289b03885b1b4c798fff32 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 13:55:01 -0300 Subject: [media] media: pci: mantis: mantis_core.c: Remove unused function Remove the function write_eeprom_byte() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/mantis/mantis_core.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/mantis/mantis_core.c b/drivers/media/pci/mantis/mantis_core.c index 684d9061fe2a..82220ea72dd3 100644 --- a/drivers/media/pci/mantis/mantis_core.c +++ b/drivers/media/pci/mantis/mantis_core.c @@ -56,29 +56,6 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } -static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) -{ - int err; - - struct i2c_msg msg = { - .addr = 0x50, - .flags = 0, - .buf = data, - .len = length - }; - - err = i2c_transfer(&mantis->adapter, &msg, 1); - if (err < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", - err, length, data[0], data[1]); - - return err; - } - - return 0; -} - static int get_mac_address(struct mantis_pci *mantis) { int err; -- cgit v1.2.3 From 0badd3c79b3a37c3586ee8a8ca32cf73ef9bb340 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 14:03:35 -0300 Subject: [media] media: pci: saa7134: saa7134-video.c: Remove unused function Remove the function saa7134_queue() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 701b52f34689..99d09a7566d3 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1084,11 +1084,6 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl) /* ------------------------------------------------------------------ */ -static inline struct vb2_queue *saa7134_queue(struct file *file) -{ - return video_devdata(file)->queue; -} - static int video_open(struct file *file) { struct video_device *vdev = video_devdata(file); -- cgit v1.2.3 From 39ddae9b225b830d3e21f495da180164a8b90a50 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 14:51:30 -0300 Subject: [media] media: platform: vsp1: vsp1_hsit: Remove unused function Remove the function vsp1_hsit_read() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_hsit.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 80bedc554ee3..0bc0471746c9 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -26,11 +26,6 @@ * Device Access */ -static inline u32 vsp1_hsit_read(struct vsp1_hsit *hsit, u32 reg) -{ - return vsp1_read(hsit->entity.vsp1, reg); -} - static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) { vsp1_write(hsit->entity.vsp1, reg, data); -- cgit v1.2.3 From 43abdd6b6bbb234b5eecfcbfdd4694b9158a172f Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Fri, 2 Jan 2015 20:29:08 -0300 Subject: [media] media: i2c: adv7604: Remove some unused functions Removes some functions that are not used anywhere: test_read() edid_read_block() dpp_write() dpp_read() esdp_write() esdp_read() cec_write_clr_set() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 66 --------------------------------------------- 1 file changed, 66 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 0c81926a508d..d228b7c82310 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -456,11 +456,6 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val); } -static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) -{ - return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val); -} - static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) { struct adv7604_state *state = to_state(sd); @@ -476,34 +471,6 @@ static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) reg, val); } -static inline int esdp_read(struct v4l2_subdev *sd, u8 reg) -{ - struct adv7604_state *state = to_state(sd); - - return adv_smbus_read_byte_data(state, ADV7604_PAGE_ESDP, reg); -} - -static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) -{ - struct adv7604_state *state = to_state(sd); - - return adv_smbus_write_byte_data(state, ADV7604_PAGE_ESDP, reg, val); -} - -static inline int dpp_read(struct v4l2_subdev *sd, u8 reg) -{ - struct adv7604_state *state = to_state(sd); - - return adv_smbus_read_byte_data(state, ADV7604_PAGE_DPP, reg); -} - -static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val) -{ - struct adv7604_state *state = to_state(sd); - - return adv_smbus_write_byte_data(state, ADV7604_PAGE_DPP, reg, val); -} - static inline int afe_read(struct v4l2_subdev *sd, u8 reg) { struct adv7604_state *state = to_state(sd); @@ -551,32 +518,6 @@ static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val); } -static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val) -{ - struct adv7604_state *state = to_state(sd); - struct i2c_client *client = state->i2c_clients[ADV7604_PAGE_EDID]; - u8 msgbuf0[1] = { 0 }; - u8 msgbuf1[256]; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .len = 1, - .buf = msgbuf0 - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = len, - .buf = msgbuf1 - }, - }; - - if (i2c_transfer(client->adapter, msg, 2) < 0) - return -EIO; - memcpy(val, msgbuf1, len); - return 0; -} - static inline int edid_write_block(struct v4l2_subdev *sd, unsigned len, const u8 *val) { @@ -642,13 +583,6 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val); } -static inline int test_read(struct v4l2_subdev *sd, u8 reg) -{ - struct adv7604_state *state = to_state(sd); - - return adv_smbus_read_byte_data(state, ADV7604_PAGE_TEST, reg); -} - static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv7604_state *state = to_state(sd); -- cgit v1.2.3 From 811afabf147fc0c03f4b56a53e5440ceb556bdcb Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 11 Jan 2015 12:38:14 -0300 Subject: [media] usb: pvrusb2: pvrusb2-hdw: Remove unused function Remove the function pvr2_hdw_cmd_powerdown() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 5 ----- drivers/media/usb/pvrusb2/pvrusb2-hdw.h | 3 --- 2 files changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 08f2f5aced9f..ff73f4036b7b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -4029,11 +4029,6 @@ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) } -int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) -{ - return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF); -} - int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index fc5037957669..a82a00dd7329 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -271,9 +271,6 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *); /* Execute simple reset command */ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); -/* suspend */ -int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); - /* Order decoder to reset */ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); -- cgit v1.2.3 From 36eb6c41ce499c88719702be2dd86869eae5264d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 Dec 2014 19:18:29 -0300 Subject: [media] staging: media: bcm2048: Remove obsolete cleanup for clientdata A few new i2c-drivers came into the kernel which clear the clientdata-pointer on exit or error. This is obsolete meanwhile, the core will do it. Signed-off-by: Wolfram Sang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/bcm2048/radio-bcm2048.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 60a57b2a8fb2..4d5e2f400ff6 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2699,8 +2699,6 @@ static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client) kfree(bdev); } - i2c_set_clientdata(client, NULL); - return 0; } -- cgit v1.2.3 From 1b500373157c7c4da2765e3416834e86224373d6 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 15 Jan 2015 17:10:45 -0300 Subject: [media] bttv: Convert to generic TEA575x interface Remove tea575x-specific code from bttv and use the common driver instead. Only set_frequency is implemented (signal/stereo detection or seek would require more changes to bttv). It works fine on Video Highway Xtreme (it actually makes the radio usable as it currently cannot be tuned properly). Miro/Pinnacle is untested but seems to be simple and should work. However, I don't understand the Terratec Active Radio Upgrade code. The HW seems to need IOR, IOW and CSEL signals that were taken from ISA bus on older cards (IOR and IOW directly and CSEL from some address decoder) and are emulated here using GPIOs. But the code manipulating these signals in bttv seems to be broken - it never asserts the IOR signal. If anyone has this HW, please test if I got that right. Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/Kconfig | 3 + drivers/media/pci/bt8xx/bttv-cards.c | 317 ++++++++++++---------------------- drivers/media/pci/bt8xx/bttv-driver.c | 6 +- drivers/media/pci/bt8xx/bttvp.h | 14 +- 4 files changed, 125 insertions(+), 215 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig index 496cf6b2dc43..4a93f6ded100 100644 --- a/drivers/media/pci/bt8xx/Kconfig +++ b/drivers/media/pci/bt8xx/Kconfig @@ -4,12 +4,15 @@ config VIDEO_BT848 select I2C_ALGOBIT select VIDEOBUF_DMA_SG depends on RC_CORE + depends on MEDIA_RADIO_SUPPORT select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT + select RADIO_ADAPTERS + select RADIO_TEA575X ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index c5186778fc8c..4654fb65ca21 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -84,8 +84,7 @@ static void gv800s_init(struct bttv *btv); static void td3116_muxsel(struct bttv *btv, unsigned int input); 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); +static int tea575x_init(struct bttv *btv); static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]); static int pvr_boot(struct bttv *btv); @@ -3085,12 +3084,12 @@ static void miro_pinnacle_gpio(struct bttv *btv) if (0 == (gpio & 0x20)) { btv->has_radio = 1; if (!miro_fmtuner[id]) { - btv->has_matchbox = 1; - btv->mbox_we = (1<<6); - btv->mbox_most = (1<<7); - btv->mbox_clk = (1<<8); - btv->mbox_data = (1<<9); - btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9); + btv->has_tea575x = 1; + btv->tea_gpio.wren = 6; + btv->tea_gpio.most = 7; + btv->tea_gpio.clk = 8; + btv->tea_gpio.data = 9; + tea575x_init(btv); } } else { btv->has_radio = 0; @@ -3104,7 +3103,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", btv->c.nr, id+1, btv->tuner_type, !btv->has_radio ? "no" : - (btv->has_matchbox ? "matchbox" : "fmtuner"), + (btv->has_tea575x ? "tea575x" : "fmtuner"), (-1 == msp) ? "no" : "yes"); } else { /* new cards with microtune tuner */ @@ -3382,12 +3381,12 @@ void bttv_init_card2(struct bttv *btv) break; case BTTV_BOARD_VHX: btv->has_radio = 1; - btv->has_matchbox = 1; - btv->mbox_we = 0x20; - btv->mbox_most = 0; - btv->mbox_clk = 0x08; - btv->mbox_data = 0x10; - btv->mbox_mask = 0x38; + btv->has_tea575x = 1; + btv->tea_gpio.wren = 5; + btv->tea_gpio.most = 6; + btv->tea_gpio.clk = 3; + btv->tea_gpio.data = 4; + tea575x_init(btv); break; case BTTV_BOARD_VOBIS_BOOSTAR: case BTTV_BOARD_TERRATV: @@ -3745,33 +3744,112 @@ static void hauppauge_eeprom(struct bttv *btv) btv->radio_uses_msp_demodulator = 1; } -static int terratec_active_radio_upgrade(struct bttv *btv) +/* ----------------------------------------------------------------------- */ + +static void bttv_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) +{ + struct bttv *btv = tea->private_data; + struct bttv_tea575x_gpio gpio = btv->tea_gpio; + u16 val = 0; + + val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0; + val |= (pins & TEA575X_CLK) ? (1 << gpio.clk) : 0; + val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0; + + gpio_bits((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren), val); + if (btv->mbox_ior) { + /* IOW and CSEL active */ + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); + udelay(5); + /* all inactive */ + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + } +} + +static u8 bttv_tea575x_get_pins(struct snd_tea575x *tea) { - int freq; + struct bttv *btv = tea->private_data; + struct bttv_tea575x_gpio gpio = btv->tea_gpio; + u8 ret = 0; + u16 val; + + if (btv->mbox_ior) { + /* IOR and CSEL active */ + gpio_bits(btv->mbox_ior | btv->mbox_csel, 0); + udelay(5); + } + val = gpio_read(); + if (btv->mbox_ior) { + /* all inactive */ + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + } + + if (val & (1 << gpio.data)) + ret |= TEA575X_DATA; + if (val & (1 << gpio.most)) + ret |= TEA575X_MOST; + + return ret; +} + +static void bttv_tea575x_set_direction(struct snd_tea575x *tea, bool output) +{ + struct bttv *btv = tea->private_data; + struct bttv_tea575x_gpio gpio = btv->tea_gpio; + u32 mask = (1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) | + (1 << gpio.most); + + if (output) + gpio_inout(mask, (1 << gpio.data) | (1 << gpio.clk) | + (1 << gpio.wren)); + else + gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren)); +} + +static struct snd_tea575x_ops bttv_tea_ops = { + .set_pins = bttv_tea575x_set_pins, + .get_pins = bttv_tea575x_get_pins, + .set_direction = bttv_tea575x_set_direction, +}; + +static int tea575x_init(struct bttv *btv) +{ + btv->tea.private_data = btv; + btv->tea.ops = &bttv_tea_ops; + if (!snd_tea575x_hw_init(&btv->tea)) { + pr_info("%d: detected TEA575x radio\n", btv->c.nr); + btv->tea.mute = false; + return 0; + } + btv->has_tea575x = 0; + btv->has_radio = 0; + + return -ENODEV; +} + +/* ----------------------------------------------------------------------- */ + +static int terratec_active_radio_upgrade(struct bttv *btv) +{ btv->has_radio = 1; - btv->has_matchbox = 1; - btv->mbox_we = 0x10; - btv->mbox_most = 0x20; - btv->mbox_clk = 0x08; - btv->mbox_data = 0x04; - btv->mbox_mask = 0x3c; + btv->has_tea575x = 1; + btv->tea_gpio.wren = 4; + btv->tea_gpio.most = 5; + btv->tea_gpio.clk = 3; + btv->tea_gpio.data = 2; btv->mbox_iow = 1 << 8; btv->mbox_ior = 1 << 9; btv->mbox_csel = 1 << 10; - freq=88000/62.5; - tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */ - if (0x1ed8 == tea5757_read(btv)) { + if (!tea575x_init(btv)) { pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr); - btv->has_radio = 1; - btv->has_saa6588 = 1; - btv->has_matchbox = 1; - } else { - btv->has_radio = 0; - btv->has_matchbox = 0; + btv->has_saa6588 = 1; } + return 0; } @@ -4292,181 +4370,6 @@ init_PCI8604PW(struct bttv *btv) } } - - -/* ----------------------------------------------------------------------- */ -/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ -/* - * Copyright (c) 1999 Csaba Halasz - * This code is placed under the terms of the GNU General Public License - * - * Brutally hacked by Dan Sheridan djs52 8/3/00 - */ - -static void bus_low(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - gpio_bits(bit,0); - udelay(5); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } -} - -static void bus_high(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - gpio_bits(bit,bit); - udelay(5); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } -} - -static int bus_in(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } - return gpio_read() & (bit); -} - -/* TEA5757 register bits */ -#define TEA_FREQ 0:14 -#define TEA_BUFFER 15:15 - -#define TEA_SIGNAL_STRENGTH 16:17 - -#define TEA_PORT1 18:18 -#define TEA_PORT0 19:19 - -#define TEA_BAND 20:21 -#define TEA_BAND_FM 0 -#define TEA_BAND_MW 1 -#define TEA_BAND_LW 2 -#define TEA_BAND_SW 3 - -#define TEA_MONO 22:22 -#define TEA_ALLOW_STEREO 0 -#define TEA_FORCE_MONO 1 - -#define TEA_SEARCH_DIRECTION 23:23 -#define TEA_SEARCH_DOWN 0 -#define TEA_SEARCH_UP 1 - -#define TEA_STATUS 24:24 -#define TEA_STATUS_TUNED 0 -#define TEA_STATUS_SEARCHING 1 - -/* Low-level stuff */ -static int tea5757_read(struct bttv *btv) -{ - unsigned long timeout; - int value = 0; - int i; - - /* better safe than sorry */ - gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - if (bttv_gpio) - bttv_gpio_tracking(btv,"tea5757 read"); - - bus_low(btv,btv->mbox_we); - bus_low(btv,btv->mbox_clk); - - udelay(10); - timeout= jiffies + msecs_to_jiffies(1000); - - /* wait for DATA line to go low; error if it doesn't */ - while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout)) - schedule(); - if (bus_in(btv,btv->mbox_data)) { - pr_warn("%d: tea5757: read timeout\n", btv->c.nr); - return -1; - } - - dprintk("%d: tea5757:", btv->c.nr); - for (i = 0; i < 24; i++) { - udelay(5); - bus_high(btv,btv->mbox_clk); - udelay(5); - dprintk_cont("%c", - bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-'); - bus_low(btv,btv->mbox_clk); - value <<= 1; - value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */ - dprintk_cont("%c", - bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M'); - } - dprintk_cont("\n"); - dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value); - return value; -} - -static int tea5757_write(struct bttv *btv, int value) -{ - int i; - int reg = value; - - gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - if (bttv_gpio) - bttv_gpio_tracking(btv,"tea5757 write"); - - dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value); - bus_low(btv,btv->mbox_clk); - bus_high(btv,btv->mbox_we); - for (i = 0; i < 25; i++) { - if (reg & 0x1000000) - bus_high(btv,btv->mbox_data); - else - bus_low(btv,btv->mbox_data); - reg <<= 1; - bus_high(btv,btv->mbox_clk); - udelay(10); - bus_low(btv,btv->mbox_clk); - udelay(10); - } - bus_low(btv,btv->mbox_we); /* unmute !!! */ - return 0; -} - -void tea5757_set_freq(struct bttv *btv, unsigned short freq) -{ - dprintk("tea5757_set_freq %d\n",freq); - tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */ -} - /* RemoteVision MX (rv605) muxsel helper [Miguel Freitas] * * This is needed because rv605 don't use a normal multiplex, but a crosspoint diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 6eed8f75c13c..e7f8aded35f8 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1874,8 +1874,10 @@ static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f) if (new_freq.type == V4L2_TUNER_RADIO) { radio_enable(btv); btv->radio_freq = new_freq.frequency; - if (btv->has_matchbox) - tea5757_set_freq(btv, btv->radio_freq); + if (btv->has_tea575x) { + btv->tea.freq = btv->radio_freq; + snd_tea575x_set_freq(&btv->tea); + } } else { btv->tv_freq = new_freq.frequency; } diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index e6e2c60f9e3e..bc048c586b1f 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -42,6 +42,7 @@ #include #include #include +#include #include "bt848.h" #include "bttv.h" @@ -359,6 +360,10 @@ struct bttv_suspend_state { struct bttv_buffer *vbi; }; +struct bttv_tea575x_gpio { + u8 data, clk, wren, most; +}; + struct bttv { struct bttv_core c; @@ -445,12 +450,9 @@ struct bttv { /* miro/pinnacle + Aimslab VHX philips matchbox (tea5757 radio tuner) support */ - int has_matchbox; - int mbox_we; - int mbox_data; - int mbox_clk; - int mbox_most; - int mbox_mask; + int has_tea575x; + struct bttv_tea575x_gpio tea_gpio; + struct snd_tea575x tea; /* ISA stuff (Terratec Active Radio Upgrade) */ int mbox_ior; -- cgit v1.2.3 From 6994ca3df1b4cd7a2577a1b6e41431d8ace457a4 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 15 Jan 2015 17:10:46 -0300 Subject: [media] tea575x: split and export functions Split ioctl interface from enum_freq_bands, g_tuner and s_hw_freq_seek functions and export them to be used in other drivers like bttv. Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/tea575x.c | 41 ++++++++++++++++++++++++++++++++--------- include/media/tea575x.h | 5 +++++ 2 files changed, 37 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index f1a0867789fe..43d1ea53cb66 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -247,10 +247,9 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_freq_bands(struct file *file, void *priv, - struct v4l2_frequency_band *band) +int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea, + struct v4l2_frequency_band *band) { - struct snd_tea575x *tea = video_drvdata(file); int index; if (band->tuner != 0) @@ -279,18 +278,25 @@ static int vidioc_enum_freq_bands(struct file *file, void *priv, return 0; } +EXPORT_SYMBOL(snd_tea575x_enum_freq_bands); -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) +static int vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) { struct snd_tea575x *tea = video_drvdata(file); + + return snd_tea575x_enum_freq_bands(tea, band); +} + +int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v) +{ struct v4l2_frequency_band band_fm = { 0, }; if (v->index > 0) return -EINVAL; snd_tea575x_read(tea); - vidioc_enum_freq_bands(file, priv, &band_fm); + snd_tea575x_enum_freq_bands(tea, &band_fm); memset(v, 0, sizeof(*v)); strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); @@ -304,6 +310,15 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->signal = tea->tuned ? 0xffff : 0; return 0; } +EXPORT_SYMBOL(snd_tea575x_g_tuner); + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct snd_tea575x *tea = video_drvdata(file); + + return snd_tea575x_g_tuner(tea, v); +} static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *v) @@ -356,10 +371,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } -static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - const struct v4l2_hw_freq_seek *a) +int snd_tea575x_s_hw_freq_seek(struct file *file, struct snd_tea575x *tea, + const struct v4l2_hw_freq_seek *a) { - struct snd_tea575x *tea = video_drvdata(file); unsigned long timeout; int i, spacing; @@ -442,6 +456,15 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh, snd_tea575x_set_freq(tea); return -ENODATA; } +EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek); + +static int vidioc_s_hw_freq_seek(struct file *file, void *fh, + const struct v4l2_hw_freq_seek *a) +{ + struct snd_tea575x *tea = video_drvdata(file); + + return snd_tea575x_s_hw_freq_seek(file, tea, a); +} static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) { diff --git a/include/media/tea575x.h b/include/media/tea575x.h index 2d4fa59db902..5d096578b736 100644 --- a/include/media/tea575x.h +++ b/include/media/tea575x.h @@ -71,6 +71,11 @@ struct snd_tea575x { int (*ext_init)(struct snd_tea575x *tea); }; +int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea, + struct v4l2_frequency_band *band); +int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v); +int snd_tea575x_s_hw_freq_seek(struct file *file, struct snd_tea575x *tea, + const struct v4l2_hw_freq_seek *a); int snd_tea575x_hw_init(struct snd_tea575x *tea); int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); void snd_tea575x_exit(struct snd_tea575x *tea); -- cgit v1.2.3 From 35655bf85473abae9ff76f25ec6b321f9935c7bc Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 16 Jan 2015 06:58:32 -0300 Subject: [media] bttv: Improve TEA575x support Improve g_tuner and add s_hw_freq_seek and enum_freq_bands support for cards with TEA575x radio. This allows signal/stereo detection and HW seek to work on these cards. Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index e7f8aded35f8..4ec2a3c3f23c 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2515,6 +2515,8 @@ static int bttv_querycap(struct file *file, void *priv, if (btv->has_saa6588) cap->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE; + if (btv->has_tea575x) + cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK; } return 0; } @@ -3244,6 +3246,9 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); + if (btv->has_tea575x) + return snd_tea575x_g_tuner(&btv->tea, t); + return 0; } @@ -3261,6 +3266,30 @@ static int radio_s_tuner(struct file *file, void *priv, return 0; } +static int radio_s_hw_freq_seek(struct file *file, void *priv, + const struct v4l2_hw_freq_seek *a) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + + if (btv->has_tea575x) + return snd_tea575x_s_hw_freq_seek(file, &btv->tea, a); + + return -ENOTTY; +} + +static int radio_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + + if (btv->has_tea575x) + return snd_tea575x_enum_freq_bands(&btv->tea, band); + + return -ENOTTY; +} + static ssize_t radio_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { @@ -3318,6 +3347,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_tuner = radio_s_tuner, .vidioc_g_frequency = bttv_g_frequency, .vidioc_s_frequency = bttv_s_frequency, + .vidioc_s_hw_freq_seek = radio_s_hw_freq_seek, + .vidioc_enum_freq_bands = radio_enum_freq_bands, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; -- cgit v1.2.3 From 88ca3af44beb281979e3f037d167cc3fec68c9de Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 8 Jan 2015 07:07:08 -0300 Subject: [media] coda: improve safety in coda_register_device() The "i" variable is used as an offset into both the dev->vfd[] and the dev->devtype->vdevs[] arrays. The second array is smaller so we should use that as a limit instead of ARRAY_SIZE(dev->vfd). Also the original check was off by one. We should use a format string as well in case the ->name has any funny characters and also to stop static checkers from complaining. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index efed0b802943..ea7a0dcf1530 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1844,10 +1844,11 @@ static int coda_register_device(struct coda_dev *dev, int i) { struct video_device *vfd = &dev->vfd[i]; - if (i > ARRAY_SIZE(dev->vfd)) + if (i >= dev->devtype->num_vdevs) return -EINVAL; - snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name); + snprintf(vfd->name, sizeof(vfd->name), "%s", + dev->devtype->vdevs[i]->name); vfd->fops = &coda_fops; vfd->ioctl_ops = &coda_ioctl_ops; vfd->release = video_device_release_empty, -- cgit v1.2.3 From 7657e0647c47393bc61b4e398b4d791350820bd1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 13:49:07 -0300 Subject: [media] adv7180: Remove the unneeded 'err' label There is no need to jump to the 'err' label as we can simply return the error code directly and make the code shorter. Signed-off-by: Fabio Estevam Acked-by: Lars-Peter Clausen Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index bffe6eb528a3..94a3341b091b 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -616,10 +616,8 @@ static int adv7180_probe(struct i2c_client *client, client->addr, client->adapter->name); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); - if (state == NULL) { - ret = -ENOMEM; - goto err; - } + if (state == NULL) + return -ENOMEM; state->irq = client->irq; mutex_init(&state->mutex); @@ -649,7 +647,6 @@ err_free_ctrl: adv7180_exit_controls(state); err_unreg_subdev: mutex_destroy(&state->mutex); -err: return ret; } -- cgit v1.2.3 From 2c676f378edb16cb68f7815581c8119fc43a4b85 Mon Sep 17 00:00:00 2001 From: Martin Bugge Date: Fri, 19 Dec 2014 09:14:21 -0300 Subject: [media] hdmi: added unpack and logging functions for InfoFrames When receiving video it is very useful to be able to unpack the InfoFrames. Logging is useful as well, both for transmitters and receivers. Especially when implementing the VIDIOC_LOG_STATUS ioctl (supported by many V4L2 drivers) for a receiver it is important to be able to easily log what the InfoFrame contains. This greatly simplifies debugging. Signed-off-by: Martin Bugge Signed-off-by: Hans Verkuil Acked-by: Thierry Reding Signed-off-by: Mauro Carvalho Chehab --- drivers/video/hdmi.c | 822 ++++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/hdmi.h | 4 + 2 files changed, 819 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 9e758a8f890d..a7c6ae4e10e5 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -27,10 +27,12 @@ #include #include #include +#include -static void hdmi_infoframe_checksum(void *buffer, size_t size) +#define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__) + +static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size) { - u8 *ptr = buffer; u8 csum = 0; size_t i; @@ -38,7 +40,14 @@ static void hdmi_infoframe_checksum(void *buffer, size_t size) for (i = 0; i < size; i++) csum += ptr[i]; - ptr[3] = 256 - csum; + return 256 - csum; +} + +static void hdmi_infoframe_set_checksum(void *buffer, size_t size) +{ + u8 *ptr = buffer; + + ptr[3] = hdmi_infoframe_checksum(buffer, size); } /** @@ -136,7 +145,7 @@ ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, ptr[11] = frame->right_bar & 0xff; ptr[12] = (frame->right_bar >> 8) & 0xff; - hdmi_infoframe_checksum(buffer, length); + hdmi_infoframe_set_checksum(buffer, length); return length; } @@ -206,7 +215,7 @@ ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer, ptr[24] = frame->sdi; - hdmi_infoframe_checksum(buffer, length); + hdmi_infoframe_set_checksum(buffer, length); return length; } @@ -281,7 +290,7 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, if (frame->downmix_inhibit) ptr[4] |= BIT(7); - hdmi_infoframe_checksum(buffer, length); + hdmi_infoframe_set_checksum(buffer, length); return length; } @@ -373,7 +382,7 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, ptr[9] = (frame->s3d_ext_data & 0xf) << 4; } - hdmi_infoframe_checksum(buffer, length); + hdmi_infoframe_set_checksum(buffer, length); return length; } @@ -434,3 +443,802 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size) return length; } EXPORT_SYMBOL(hdmi_infoframe_pack); + +static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type) +{ + if (type < 0x80 || type > 0x9f) + return "Invalid"; + switch (type) { + case HDMI_INFOFRAME_TYPE_VENDOR: + return "Vendor"; + case HDMI_INFOFRAME_TYPE_AVI: + return "Auxiliary Video Information (AVI)"; + case HDMI_INFOFRAME_TYPE_SPD: + return "Source Product Description (SPD)"; + case HDMI_INFOFRAME_TYPE_AUDIO: + return "Audio"; + } + return "Reserved"; +} + +static void hdmi_infoframe_log_header(const char *level, + struct device *dev, + struct hdmi_any_infoframe *frame) +{ + hdmi_log("HDMI infoframe: %s, version %u, length %u\n", + hdmi_infoframe_type_get_name(frame->type), + frame->version, frame->length); +} + +static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace) +{ + switch (colorspace) { + case HDMI_COLORSPACE_RGB: + return "RGB"; + case HDMI_COLORSPACE_YUV422: + return "YCbCr 4:2:2"; + case HDMI_COLORSPACE_YUV444: + return "YCbCr 4:4:4"; + case HDMI_COLORSPACE_YUV420: + return "YCbCr 4:2:0"; + case HDMI_COLORSPACE_RESERVED4: + return "Reserved (4)"; + case HDMI_COLORSPACE_RESERVED5: + return "Reserved (5)"; + case HDMI_COLORSPACE_RESERVED6: + return "Reserved (6)"; + case HDMI_COLORSPACE_IDO_DEFINED: + return "IDO Defined"; + } + return "Invalid"; +} + +static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode) +{ + switch (scan_mode) { + case HDMI_SCAN_MODE_NONE: + return "No Data"; + case HDMI_SCAN_MODE_OVERSCAN: + return "Overscan"; + case HDMI_SCAN_MODE_UNDERSCAN: + return "Underscan"; + case HDMI_SCAN_MODE_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry) +{ + switch (colorimetry) { + case HDMI_COLORIMETRY_NONE: + return "No Data"; + case HDMI_COLORIMETRY_ITU_601: + return "ITU601"; + case HDMI_COLORIMETRY_ITU_709: + return "ITU709"; + case HDMI_COLORIMETRY_EXTENDED: + return "Extended"; + } + return "Invalid"; +} + +static const char * +hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect) +{ + switch (picture_aspect) { + case HDMI_PICTURE_ASPECT_NONE: + return "No Data"; + case HDMI_PICTURE_ASPECT_4_3: + return "4:3"; + case HDMI_PICTURE_ASPECT_16_9: + return "16:9"; + case HDMI_PICTURE_ASPECT_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char * +hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect) +{ + if (active_aspect < 0 || active_aspect > 0xf) + return "Invalid"; + + switch (active_aspect) { + case HDMI_ACTIVE_ASPECT_16_9_TOP: + return "16:9 Top"; + case HDMI_ACTIVE_ASPECT_14_9_TOP: + return "14:9 Top"; + case HDMI_ACTIVE_ASPECT_16_9_CENTER: + return "16:9 Center"; + case HDMI_ACTIVE_ASPECT_PICTURE: + return "Same as Picture"; + case HDMI_ACTIVE_ASPECT_4_3: + return "4:3"; + case HDMI_ACTIVE_ASPECT_16_9: + return "16:9"; + case HDMI_ACTIVE_ASPECT_14_9: + return "14:9"; + case HDMI_ACTIVE_ASPECT_4_3_SP_14_9: + return "4:3 SP 14:9"; + case HDMI_ACTIVE_ASPECT_16_9_SP_14_9: + return "16:9 SP 14:9"; + case HDMI_ACTIVE_ASPECT_16_9_SP_4_3: + return "16:9 SP 4:3"; + } + return "Reserved"; +} + +static const char * +hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col) +{ + switch (ext_col) { + case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601: + return "xvYCC 601"; + case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709: + return "xvYCC 709"; + case HDMI_EXTENDED_COLORIMETRY_S_YCC_601: + return "sYCC 601"; + case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: + return "Adobe YCC 601"; + case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: + return "Adobe RGB"; + case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM: + return "BT.2020 Constant Luminance"; + case HDMI_EXTENDED_COLORIMETRY_BT2020: + return "BT.2020"; + case HDMI_EXTENDED_COLORIMETRY_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char * +hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange) +{ + switch (qrange) { + case HDMI_QUANTIZATION_RANGE_DEFAULT: + return "Default"; + case HDMI_QUANTIZATION_RANGE_LIMITED: + return "Limited"; + case HDMI_QUANTIZATION_RANGE_FULL: + return "Full"; + case HDMI_QUANTIZATION_RANGE_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char *hdmi_nups_get_name(enum hdmi_nups nups) +{ + switch (nups) { + case HDMI_NUPS_UNKNOWN: + return "Unknown Non-uniform Scaling"; + case HDMI_NUPS_HORIZONTAL: + return "Horizontally Scaled"; + case HDMI_NUPS_VERTICAL: + return "Vertically Scaled"; + case HDMI_NUPS_BOTH: + return "Horizontally and Vertically Scaled"; + } + return "Invalid"; +} + +static const char * +hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange) +{ + switch (qrange) { + case HDMI_YCC_QUANTIZATION_RANGE_LIMITED: + return "Limited"; + case HDMI_YCC_QUANTIZATION_RANGE_FULL: + return "Full"; + } + return "Invalid"; +} + +static const char * +hdmi_content_type_get_name(enum hdmi_content_type content_type) +{ + switch (content_type) { + case HDMI_CONTENT_TYPE_GRAPHICS: + return "Graphics"; + case HDMI_CONTENT_TYPE_PHOTO: + return "Photo"; + case HDMI_CONTENT_TYPE_CINEMA: + return "Cinema"; + case HDMI_CONTENT_TYPE_GAME: + return "Game"; + } + return "Invalid"; +} + +/** + * hdmi_avi_infoframe_log() - log info of HDMI AVI infoframe + * @level: logging level + * @dev: device + * @frame: HDMI AVI infoframe + */ +static void hdmi_avi_infoframe_log(const char *level, + struct device *dev, + struct hdmi_avi_infoframe *frame) +{ + hdmi_infoframe_log_header(level, dev, + (struct hdmi_any_infoframe *)frame); + + hdmi_log(" colorspace: %s\n", + hdmi_colorspace_get_name(frame->colorspace)); + hdmi_log(" scan mode: %s\n", + hdmi_scan_mode_get_name(frame->scan_mode)); + hdmi_log(" colorimetry: %s\n", + hdmi_colorimetry_get_name(frame->colorimetry)); + hdmi_log(" picture aspect: %s\n", + hdmi_picture_aspect_get_name(frame->picture_aspect)); + hdmi_log(" active aspect: %s\n", + hdmi_active_aspect_get_name(frame->active_aspect)); + hdmi_log(" itc: %s\n", frame->itc ? "IT Content" : "No Data"); + hdmi_log(" extended colorimetry: %s\n", + hdmi_extended_colorimetry_get_name(frame->extended_colorimetry)); + hdmi_log(" quantization range: %s\n", + hdmi_quantization_range_get_name(frame->quantization_range)); + hdmi_log(" nups: %s\n", hdmi_nups_get_name(frame->nups)); + hdmi_log(" video code: %u\n", frame->video_code); + hdmi_log(" ycc quantization range: %s\n", + hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range)); + hdmi_log(" hdmi content type: %s\n", + hdmi_content_type_get_name(frame->content_type)); + hdmi_log(" pixel repeat: %u\n", frame->pixel_repeat); + hdmi_log(" bar top %u, bottom %u, left %u, right %u\n", + frame->top_bar, frame->bottom_bar, + frame->left_bar, frame->right_bar); +} + +static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi) +{ + if (sdi < 0 || sdi > 0xff) + return "Invalid"; + switch (sdi) { + case HDMI_SPD_SDI_UNKNOWN: + return "Unknown"; + case HDMI_SPD_SDI_DSTB: + return "Digital STB"; + case HDMI_SPD_SDI_DVDP: + return "DVD Player"; + case HDMI_SPD_SDI_DVHS: + return "D-VHS"; + case HDMI_SPD_SDI_HDDVR: + return "HDD Videorecorder"; + case HDMI_SPD_SDI_DVC: + return "DVC"; + case HDMI_SPD_SDI_DSC: + return "DSC"; + case HDMI_SPD_SDI_VCD: + return "Video CD"; + case HDMI_SPD_SDI_GAME: + return "Game"; + case HDMI_SPD_SDI_PC: + return "PC General"; + case HDMI_SPD_SDI_BD: + return "Blu-Ray Disc (BD)"; + case HDMI_SPD_SDI_SACD: + return "Super Audio CD"; + case HDMI_SPD_SDI_HDDVD: + return "HD DVD"; + case HDMI_SPD_SDI_PMP: + return "PMP"; + } + return "Reserved"; +} + +/** + * hdmi_spd_infoframe_log() - log info of HDMI SPD infoframe + * @level: logging level + * @dev: device + * @frame: HDMI SPD infoframe + */ +static void hdmi_spd_infoframe_log(const char *level, + struct device *dev, + struct hdmi_spd_infoframe *frame) +{ + u8 buf[17]; + + hdmi_infoframe_log_header(level, dev, + (struct hdmi_any_infoframe *)frame); + + memset(buf, 0, sizeof(buf)); + + strncpy(buf, frame->vendor, 8); + hdmi_log(" vendor: %s\n", buf); + strncpy(buf, frame->product, 16); + hdmi_log(" product: %s\n", buf); + hdmi_log(" source device information: %s (0x%x)\n", + hdmi_spd_sdi_get_name(frame->sdi), frame->sdi); +} + +static const char * +hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type) +{ + switch (coding_type) { + case HDMI_AUDIO_CODING_TYPE_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_CODING_TYPE_PCM: + return "PCM"; + case HDMI_AUDIO_CODING_TYPE_AC3: + return "AC-3"; + case HDMI_AUDIO_CODING_TYPE_MPEG1: + return "MPEG1"; + case HDMI_AUDIO_CODING_TYPE_MP3: + return "MP3"; + case HDMI_AUDIO_CODING_TYPE_MPEG2: + return "MPEG2"; + case HDMI_AUDIO_CODING_TYPE_AAC_LC: + return "AAC"; + case HDMI_AUDIO_CODING_TYPE_DTS: + return "DTS"; + case HDMI_AUDIO_CODING_TYPE_ATRAC: + return "ATRAC"; + case HDMI_AUDIO_CODING_TYPE_DSD: + return "One Bit Audio"; + case HDMI_AUDIO_CODING_TYPE_EAC3: + return "Dolby Digital +"; + case HDMI_AUDIO_CODING_TYPE_DTS_HD: + return "DTS-HD"; + case HDMI_AUDIO_CODING_TYPE_MLP: + return "MAT (MLP)"; + case HDMI_AUDIO_CODING_TYPE_DST: + return "DST"; + case HDMI_AUDIO_CODING_TYPE_WMA_PRO: + return "WMA PRO"; + case HDMI_AUDIO_CODING_TYPE_CXT: + return "Refer to CXT"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size) +{ + switch (sample_size) { + case HDMI_AUDIO_SAMPLE_SIZE_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_SAMPLE_SIZE_16: + return "16 bit"; + case HDMI_AUDIO_SAMPLE_SIZE_20: + return "20 bit"; + case HDMI_AUDIO_SAMPLE_SIZE_24: + return "24 bit"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq) +{ + switch (freq) { + case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_32000: + return "32 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_44100: + return "44.1 kHz (CD)"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_48000: + return "48 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_88200: + return "88.2 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_96000: + return "96 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_176400: + return "176.4 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_192000: + return "192 kHz"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx) +{ + if (ctx < 0 || ctx > 0x1f) + return "Invalid"; + + switch (ctx) { + case HDMI_AUDIO_CODING_TYPE_EXT_STREAM: + return "Refer to CT"; + case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC: + return "HE AAC"; + case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2: + return "HE AAC v2"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND: + return "MPEG SURROUND"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC: + return "MPEG-4 HE AAC"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2: + return "MPEG-4 HE AAC v2"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC: + return "MPEG-4 AAC LC"; + case HDMI_AUDIO_CODING_TYPE_EXT_DRA: + return "DRA"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND: + return "MPEG-4 HE AAC + MPEG Surround"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND: + return "MPEG-4 AAC LC + MPEG Surround"; + } + return "Reserved"; +} + +/** + * hdmi_audio_infoframe_log() - log info of HDMI AUDIO infoframe + * @level: logging level + * @dev: device + * @frame: HDMI AUDIO infoframe + */ +static void hdmi_audio_infoframe_log(const char *level, + struct device *dev, + struct hdmi_audio_infoframe *frame) +{ + hdmi_infoframe_log_header(level, dev, + (struct hdmi_any_infoframe *)frame); + + if (frame->channels) + hdmi_log(" channels: %u\n", frame->channels - 1); + else + hdmi_log(" channels: Refer to stream header\n"); + hdmi_log(" coding type: %s\n", + hdmi_audio_coding_type_get_name(frame->coding_type)); + hdmi_log(" sample size: %s\n", + hdmi_audio_sample_size_get_name(frame->sample_size)); + hdmi_log(" sample frequency: %s\n", + hdmi_audio_sample_frequency_get_name(frame->sample_frequency)); + hdmi_log(" coding type ext: %s\n", + hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext)); + hdmi_log(" channel allocation: 0x%x\n", + frame->channel_allocation); + hdmi_log(" level shift value: %u dB\n", + frame->level_shift_value); + hdmi_log(" downmix inhibit: %s\n", + frame->downmix_inhibit ? "Yes" : "No"); +} + +static const char * +hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct) +{ + if (s3d_struct < 0 || s3d_struct > 0xf) + return "Invalid"; + + switch (s3d_struct) { + case HDMI_3D_STRUCTURE_FRAME_PACKING: + return "Frame Packing"; + case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE: + return "Field Alternative"; + case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE: + return "Line Alternative"; + case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL: + return "Side-by-side (Full)"; + case HDMI_3D_STRUCTURE_L_DEPTH: + return "L + Depth"; + case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH: + return "L + Depth + Graphics + Graphics-depth"; + case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM: + return "Top-and-Bottom"; + case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF: + return "Side-by-side (Half)"; + default: + break; + } + return "Reserved"; +} + +/** + * hdmi_vendor_infoframe_log() - log info of HDMI VENDOR infoframe + * @level: logging level + * @dev: device + * @frame: HDMI VENDOR infoframe + */ +static void +hdmi_vendor_any_infoframe_log(const char *level, + struct device *dev, + union hdmi_vendor_any_infoframe *frame) +{ + struct hdmi_vendor_infoframe *hvf = &frame->hdmi; + + hdmi_infoframe_log_header(level, dev, + (struct hdmi_any_infoframe *)frame); + + if (frame->any.oui != HDMI_IEEE_OUI) { + hdmi_log(" not a HDMI vendor infoframe\n"); + return; + } + if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) { + hdmi_log(" empty frame\n"); + return; + } + + if (hvf->vic) + hdmi_log(" HDMI VIC: %u\n", hvf->vic); + if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) { + hdmi_log(" 3D structure: %s\n", + hdmi_3d_structure_get_name(hvf->s3d_struct)); + if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + hdmi_log(" 3D extension data: %d\n", + hvf->s3d_ext_data); + } +} + +/** + * hdmi_infoframe_log() - log info of HDMI infoframe + * @level: logging level + * @dev: device + * @frame: HDMI infoframe + */ +void hdmi_infoframe_log(const char *level, + struct device *dev, + union hdmi_infoframe *frame) +{ + switch (frame->any.type) { + case HDMI_INFOFRAME_TYPE_AVI: + hdmi_avi_infoframe_log(level, dev, &frame->avi); + break; + case HDMI_INFOFRAME_TYPE_SPD: + hdmi_spd_infoframe_log(level, dev, &frame->spd); + break; + case HDMI_INFOFRAME_TYPE_AUDIO: + hdmi_audio_infoframe_log(level, dev, &frame->audio); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor); + break; + } +} +EXPORT_SYMBOL(hdmi_infoframe_log); + +/** + * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe + * @buffer: source buffer + * @frame: HDMI AVI infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Auxiliary Video (AVI) information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, + void *buffer) +{ + u8 *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI || + ptr[1] != 2 || + ptr[2] != HDMI_AVI_INFOFRAME_SIZE) + return -EINVAL; + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0) + return -EINVAL; + + ret = hdmi_avi_infoframe_init(frame); + if (ret) + return ret; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + frame->colorspace = (ptr[0] >> 5) & 0x3; + if (ptr[0] & 0x10) + frame->active_aspect = ptr[1] & 0xf; + if (ptr[0] & 0x8) { + frame->top_bar = (ptr[5] << 8) + ptr[6]; + frame->bottom_bar = (ptr[7] << 8) + ptr[8]; + } + if (ptr[0] & 0x4) { + frame->left_bar = (ptr[9] << 8) + ptr[10]; + frame->right_bar = (ptr[11] << 8) + ptr[12]; + } + frame->scan_mode = ptr[0] & 0x3; + + frame->colorimetry = (ptr[1] >> 6) & 0x3; + frame->picture_aspect = (ptr[1] >> 4) & 0x3; + frame->active_aspect = ptr[1] & 0xf; + + frame->itc = ptr[2] & 0x80 ? true : false; + frame->extended_colorimetry = (ptr[2] >> 4) & 0x7; + frame->quantization_range = (ptr[2] >> 2) & 0x3; + frame->nups = ptr[2] & 0x3; + + frame->video_code = ptr[3] & 0x7f; + frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3; + frame->content_type = (ptr[4] >> 4) & 0x3; + + frame->pixel_repeat = ptr[4] & 0xf; + + return 0; +} + +/** + * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe + * @buffer: source buffer + * @frame: HDMI SPD infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Source Product Description (SPD) information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, + void *buffer) +{ + u8 *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD || + ptr[1] != 1 || + ptr[2] != HDMI_SPD_INFOFRAME_SIZE) { + return -EINVAL; + } + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0) + return -EINVAL; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8); + if (ret) + return ret; + + frame->sdi = ptr[24]; + + return 0; +} + +/** + * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe + * @buffer: source buffer + * @frame: HDMI Audio infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Audio information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, + void *buffer) +{ + u8 *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO || + ptr[1] != 1 || + ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) { + return -EINVAL; + } + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0) + return -EINVAL; + + ret = hdmi_audio_infoframe_init(frame); + if (ret) + return ret; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + frame->channels = ptr[0] & 0x7; + frame->coding_type = (ptr[0] >> 4) & 0xf; + frame->sample_size = ptr[1] & 0x3; + frame->sample_frequency = (ptr[1] >> 2) & 0x7; + frame->coding_type_ext = ptr[2] & 0x1f; + frame->channel_allocation = ptr[3]; + frame->level_shift_value = (ptr[4] >> 3) & 0xf; + frame->downmix_inhibit = ptr[4] & 0x80 ? true : false; + + return 0; +} + +/** + * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe + * @buffer: source buffer + * @frame: HDMI Vendor infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Vendor information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int +hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, + void *buffer) +{ + u8 *ptr = buffer; + size_t length; + int ret; + u8 hdmi_video_format; + struct hdmi_vendor_infoframe *hvf = &frame->hdmi; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || + ptr[1] != 1 || + (ptr[2] != 5 && ptr[2] != 6)) + return -EINVAL; + + length = ptr[2]; + + if (hdmi_infoframe_checksum(buffer, + HDMI_INFOFRAME_HEADER_SIZE + length) != 0) + return -EINVAL; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + /* HDMI OUI */ + if ((ptr[0] != 0x03) || + (ptr[1] != 0x0c) || + (ptr[2] != 0x00)) + return -EINVAL; + + hdmi_video_format = ptr[3] >> 5; + + if (hdmi_video_format > 0x2) + return -EINVAL; + + ret = hdmi_vendor_infoframe_init(hvf); + if (ret) + return ret; + + hvf->length = length; + + if (hdmi_video_format == 0x1) { + hvf->vic = ptr[4]; + } else if (hdmi_video_format == 0x2) { + hvf->s3d_struct = ptr[4] >> 4; + if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) { + if (length == 6) + hvf->s3d_ext_data = ptr[5] >> 4; + else + return -EINVAL; + } + } + + return 0; +} + +/** + * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe + * @buffer: source buffer + * @frame: HDMI infoframe + * + * Unpacks the information contained in binary buffer @buffer into a structured + * @frame of a HDMI infoframe. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer) +{ + int ret; + u8 *ptr = buffer; + + switch (ptr[0]) { + case HDMI_INFOFRAME_TYPE_AVI: + ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer); + break; + case HDMI_INFOFRAME_TYPE_SPD: + ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer); + break; + case HDMI_INFOFRAME_TYPE_AUDIO: + ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL(hdmi_infoframe_unpack); diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 5afc0bff2bbe..2ff34315a1bb 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -25,6 +25,7 @@ #define __LINUX_HDMI_H_ #include +#include enum hdmi_infoframe_type { HDMI_INFOFRAME_TYPE_VENDOR = 0x81, @@ -327,5 +328,8 @@ union hdmi_infoframe { ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size); +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer); +void hdmi_infoframe_log(const char *level, struct device *dev, + union hdmi_infoframe *frame); #endif /* _DRM_HDMI_H */ -- cgit v1.2.3 From dc189053e1a5ae606c56e432dae1afc28261a819 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2014 09:14:22 -0300 Subject: [media] hdmi: rename HDMI_AUDIO_CODING_TYPE_EXT_STREAM to _EXT_CT As per the suggestion of Thierry Reding rename HDMI_AUDIO_CODING_TYPE_EXT_STREAM to HDMI_AUDIO_CODING_TYPE_EXT_CT to be consistent with the CEA-861 spec. Signed-off-by: Hans Verkuil Acked-by: Thierry Reding Signed-off-by: Mauro Carvalho Chehab --- drivers/video/hdmi.c | 2 +- include/linux/hdmi.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index a7c6ae4e10e5..162689227a23 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -842,7 +842,7 @@ hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx) return "Invalid"; switch (ctx) { - case HDMI_AUDIO_CODING_TYPE_EXT_STREAM: + case HDMI_AUDIO_CODING_TYPE_EXT_CT: return "Refer to CT"; case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC: return "HE AAC"; diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 2ff34315a1bb..e9744202fa29 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -230,7 +230,8 @@ enum hdmi_audio_sample_frequency { }; enum hdmi_audio_coding_type_ext { - HDMI_AUDIO_CODING_TYPE_EXT_STREAM, + /* Refer to Audio Coding Type (CT) field in Data Byte 1 */ + HDMI_AUDIO_CODING_TYPE_EXT_CT, /* * The next three CXT values are defined in CEA-861-E only. -- cgit v1.2.3 From 09f90c53acab944de89c3ad48a75e2b64f3211e3 Mon Sep 17 00:00:00 2001 From: Martin Bugge Date: Fri, 19 Dec 2014 09:14:23 -0300 Subject: [media] adv7842: simplify InfoFrame logging Use the new logging functions from the hdmi module. Signed-off-by: Martin Bugge Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/adv7842.c | 174 ++++++++++++-------------------------------- 2 files changed, 47 insertions(+), 128 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index ca84543cf6ac..0828b6b28fa4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -209,6 +209,7 @@ config VIDEO_ADV7604 config VIDEO_ADV7842 tristate "Analog Devices ADV7842 decoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API + select HDMI ---help--- Support for the Analog Devices ADV7842 video decoder. diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 6bc872d43717..7c215ee142c4 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -2098,149 +2099,65 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e) return err; } -/*********** avi info frame CEA-861-E **************/ -/* TODO move to common library */ - -struct avi_info_frame { - uint8_t f17; - uint8_t y10; - uint8_t a0; - uint8_t b10; - uint8_t s10; - uint8_t c10; - uint8_t m10; - uint8_t r3210; - uint8_t itc; - uint8_t ec210; - uint8_t q10; - uint8_t sc10; - uint8_t f47; - uint8_t vic; - uint8_t yq10; - uint8_t cn10; - uint8_t pr3210; - uint16_t etb; - uint16_t sbb; - uint16_t elb; - uint16_t srb; +struct adv7842_cfg_read_infoframe { + const char *desc; + u8 present_mask; + u8 head_addr; + u8 payload_addr; }; -static const char *y10_txt[4] = { - "RGB", - "YCbCr 4:2:2", - "YCbCr 4:4:4", - "Future", -}; - -static const char *c10_txt[4] = { - "No Data", - "SMPTE 170M", - "ITU-R 709", - "Extended Colorimetry information valied", -}; - -static const char *itc_txt[2] = { - "No Data", - "IT content", -}; - -static const char *ec210_txt[8] = { - "xvYCC601", - "xvYCC709", - "sYCC601", - "AdobeYCC601", - "AdobeRGB", - "5 reserved", - "6 reserved", - "7 reserved", -}; - -static const char *q10_txt[4] = { - "Default", - "Limited Range", - "Full Range", - "Reserved", -}; - -static void parse_avi_infoframe(struct v4l2_subdev *sd, uint8_t *buf, - struct avi_info_frame *avi) -{ - avi->f17 = (buf[1] >> 7) & 0x1; - avi->y10 = (buf[1] >> 5) & 0x3; - avi->a0 = (buf[1] >> 4) & 0x1; - avi->b10 = (buf[1] >> 2) & 0x3; - avi->s10 = buf[1] & 0x3; - avi->c10 = (buf[2] >> 6) & 0x3; - avi->m10 = (buf[2] >> 4) & 0x3; - avi->r3210 = buf[2] & 0xf; - avi->itc = (buf[3] >> 7) & 0x1; - avi->ec210 = (buf[3] >> 4) & 0x7; - avi->q10 = (buf[3] >> 2) & 0x3; - avi->sc10 = buf[3] & 0x3; - avi->f47 = (buf[4] >> 7) & 0x1; - avi->vic = buf[4] & 0x7f; - avi->yq10 = (buf[5] >> 6) & 0x3; - avi->cn10 = (buf[5] >> 4) & 0x3; - avi->pr3210 = buf[5] & 0xf; - avi->etb = buf[6] + 256*buf[7]; - avi->sbb = buf[8] + 256*buf[9]; - avi->elb = buf[10] + 256*buf[11]; - avi->srb = buf[12] + 256*buf[13]; -} - -static void print_avi_infoframe(struct v4l2_subdev *sd) +static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infoframe *cri) { int i; - uint8_t buf[14]; - u8 avi_len; - u8 avi_ver; - struct avi_info_frame avi; + uint8_t buffer[32]; + union hdmi_infoframe frame; + u8 len; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct device *dev = &client->dev; - if (!(hdmi_read(sd, 0x05) & 0x80)) { - v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); - return; - } - if (!(io_read(sd, 0x60) & 0x01)) { - v4l2_info(sd, "AVI infoframe not received\n"); + if (!(io_read(sd, 0x60) & cri->present_mask)) { + v4l2_info(sd, "%s infoframe not received\n", cri->desc); return; } - if (io_read(sd, 0x88) & 0x10) { - v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n"); - io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */ - if (io_read(sd, 0x88) & 0x10) { - v4l2_info(sd, "AVI infoframe checksum error still present\n"); - io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */ - } - } + for (i = 0; i < 3; i++) + buffer[i] = infoframe_read(sd, cri->head_addr + i); - avi_len = infoframe_read(sd, 0xe2); - avi_ver = infoframe_read(sd, 0xe1); - v4l2_info(sd, "AVI infoframe version %d (%d byte)\n", - avi_ver, avi_len); + len = buffer[2] + 1; - if (avi_ver != 0x02) + if (len + 3 > sizeof(buffer)) { + v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len); return; + } - for (i = 0; i < 14; i++) - buf[i] = infoframe_read(sd, i); + for (i = 0; i < len; i++) + buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i); - v4l2_info(sd, "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]); + if (hdmi_infoframe_unpack(&frame, buffer) < 0) { + v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc); + return; + } - parse_avi_infoframe(sd, buf, &avi); + hdmi_infoframe_log(KERN_INFO, dev, &frame); +} - if (avi.vic) - v4l2_info(sd, "\tVIC: %d\n", avi.vic); - if (avi.itc) - v4l2_info(sd, "\t%s\n", itc_txt[avi.itc]); +static void adv7842_log_infoframes(struct v4l2_subdev *sd) +{ + int i; + struct adv7842_cfg_read_infoframe cri[] = { + { "AVI", 0x01, 0xe0, 0x00 }, + { "Audio", 0x02, 0xe3, 0x1c }, + { "SDP", 0x04, 0xe6, 0x2a }, + { "Vendor", 0x10, 0xec, 0x54 } + }; - if (avi.y10) - v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], !avi.c10 ? "" : - (avi.c10 == 0x3 ? ec210_txt[avi.ec210] : c10_txt[avi.c10])); - else - v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], q10_txt[avi.q10]); + if (!(hdmi_read(sd, 0x05) & 0x80)) { + v4l2_info(sd, "receive DVI-D signal, no infoframes\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(cri); i++) + log_infoframe(sd, &cri[i]); } static const char * const prim_mode_txt[] = { @@ -2454,7 +2371,8 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd) v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]); - print_avi_infoframe(sd); + adv7842_log_infoframes(sd); + return 0; } -- cgit v1.2.3 From 8cb0b6349010ffa0f80d5fc9ff9201e43a51a161 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Wed, 21 Jan 2015 21:14:23 -0300 Subject: [media] v4l: vsp1: bru: Fix minimum input pixel size According to the spec, the minimum input pixel size for BRU is 1px, not 4px. Signed-off-by: Takanari Hayama Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_bru.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index b21f381a9862..401e2b77a0b6 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -20,7 +20,7 @@ #include "vsp1_bru.h" #include "vsp1_rwpf.h" -#define BRU_MIN_SIZE 4U +#define BRU_MIN_SIZE 1U #define BRU_MAX_SIZE 8190U /* ----------------------------------------------------------------------------- -- cgit v1.2.3 From 59a7954ce31f9256a5f0ef36732076349f058ec2 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 7 Jan 2015 04:37:53 -0300 Subject: [media] v4l: vsp1: Fix VI6_DISP_IRQ_ENB_LNEE macro LNEE bit in VI6_DISP_IRQ_ENB register are from the 0 bit to 4 bit. This fixes bit position specified by VI6_DISP_IRQ_ENB_LNEE. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 55f163d32d15..79d4063d798f 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -43,7 +43,7 @@ #define VI6_DISP_IRQ_ENB 0x0078 #define VI6_DISP_IRQ_ENB_DSTE (1 << 8) #define VI6_DISP_IRQ_ENB_MAEE (1 << 5) -#define VI6_DISP_IRQ_ENB_LNEE(n) (1 << ((n) + 4)) +#define VI6_DISP_IRQ_ENB_LNEE(n) (1 << (n)) #define VI6_DISP_IRQ_STA 0x007c #define VI6_DISP_IRQ_STA_DSE (1 << 8) -- cgit v1.2.3 From 533ab2231d15e082f4ef547ee2fe99a8a25ab046 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 7 Jan 2015 04:37:54 -0300 Subject: [media] v4l: vsp1: Fix VI6_DISP_IRQ_STA_LNE macro LNE bit in VI6_DISP_IRQ_STA register are from the 0 bit to 4 bit. This fixes bit position specified by VI6_DISP_IRQ_STA_LNE. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 79d4063d798f..da3c573e1efc 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -48,7 +48,7 @@ #define VI6_DISP_IRQ_STA 0x007c #define VI6_DISP_IRQ_STA_DSE (1 << 8) #define VI6_DISP_IRQ_STA_MAE (1 << 5) -#define VI6_DISP_IRQ_STA_LNE(n) (1 << ((n) + 4)) +#define VI6_DISP_IRQ_STA_LNE(n) (1 << (n)) #define VI6_WPF_LINE_COUNT(n) (0x0084 + (n) * 4) #define VI6_WPF_LINE_COUNT_MASK (0x1fffff << 0) -- cgit v1.2.3 From 9fae30acdeefb8955c9f90d4d18a3d1dc599a1ff Mon Sep 17 00:00:00 2001 From: Aviv Greenberg Date: Tue, 2 Sep 2014 03:16:28 -0300 Subject: [media] uvcvideo: Remove extra commit on resume() The UVC spec is a bit vague wrt devices using bulk endpoints, specifically, how to signal to a device to start streaming. For devices using isoc endpoints, the sequence for start streaming is: 1) The host sends PROBE_CONTROL(SET_CUR) PROBE_CONTROL(GET_CUR) 2) Host selects desired config and calls COMMIT_CONTROL(SET_CUR) 3) Host selects an alt interface other then zero - e.g SELECT_ALTERNATE_INTERFACE(1) 4) The device starts streaming However for devices using bulk endpoints, there must be *no* alt interface other than setting zero. From the UVC spec: "A VideoStreaming interface containing a bulk endpoint for streaming shall support only alternate setting zero. Additional alternate settings containing bulk endpoints are not permitted in a device that is compliant with the Video Class specification." So for devices using bulk endpoints, step #3 above is irrelevant, and thus cannot be used as an indication for the device to start streaming. So in practice, such devices start streaming immediately after a COMMIT_CONTROL(SET_CUR). In the uvc resume() handler, an unsolicited commit is sent, which causes devices using bulk endpoints to start streaming unintentionally. This patch modifies resume() handler to send a commit only if streaming needs to be reestablished, i.e if the device was actually streaming before is was suspended. Signed-off-by: Aviv Greenberg Signed-off-by: Guennadi Liakhovetski Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 9637e8b86949..20ccc9d315dc 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1734,13 +1734,13 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) uvc_video_clock_reset(stream); + if (!uvc_queue_streaming(&stream->queue)) + return 0; + ret = uvc_commit_video(stream, &stream->ctrl); if (ret < 0) return ret; - if (!uvc_queue_streaming(&stream->queue)) - return 0; - return uvc_init_video(stream, GFP_NOIO); } -- cgit v1.2.3 From 566cc8a5e7d6d9caed9958bf8358d9cacac056bc Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Mon, 29 Dec 2014 11:29:43 -0300 Subject: [media] uvcvideo: remove unnecessary version.h inclusion Based on versioncheck. Signed-off-by: Fabian Frederick Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_v4l2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 9c5cbcf16529..43e953f73e02 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From c97da15411bf87c432cc1ed91af70ad558d64835 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 22 Jan 2015 11:12:02 -0300 Subject: [media] Revert "[media] v4l: omap4iss: Add module debug parameter" This reverts commit 186612342500b0af8498d7c8bc6b3ac32ac7a48e. The video_device debug field has been renamed to dev_debug, resulting in a compilation failure. As v4l2 debugging is supposed to be controlled through a sysfs attribute created by the v4l2 core, there's no need to duplicate debug control through a module parameter. Remove it. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 2085f699da67..69550445a341 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -25,9 +25,6 @@ #include "iss_video.h" #include "iss.h" -static unsigned debug; -module_param(debug, uint, 0644); -MODULE_PARM_DESC(debug, "activates debug info"); /* ----------------------------------------------------------------------------- * Helper functions @@ -1053,8 +1050,6 @@ static int iss_video_open(struct file *file) if (handle == NULL) return -ENOMEM; - video->video.debug = debug; - v4l2_fh_init(&handle->vfh, &video->video); v4l2_fh_add(&handle->vfh); -- cgit v1.2.3 From c2c8386f825bebd383d78263d6d4757abd21d182 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 2 Dec 2014 10:55:17 -0300 Subject: [media] rtl2832: convert driver to I2C binding Convert that driver to I2C driver model. Legacy DVB binding is left also for later removal... Tested-by: Benjamin Larsson Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 108 +++++++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2832.h | 10 +++ drivers/media/dvb-frontends/rtl2832_priv.h | 1 + 3 files changed, 119 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 9026e1aee163..53b446afe030 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1183,6 +1183,114 @@ static struct dvb_frontend_ops rtl2832_ops = { .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, }; +static int rtl2832_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rtl2832_platform_data *pdata = client->dev.platform_data; + const struct rtl2832_config *config = pdata->config; + struct i2c_adapter *i2c = client->adapter; + struct rtl2832_priv *priv; + int ret; + u8 tmp; + + dev_dbg(&client->dev, "\n"); + + /* Caller really need to provide pointer for frontend we create. */ + if (pdata->dvb_frontend == NULL) { + dev_err(&client->dev, "frontend pointer not defined\n"); + ret = -EINVAL; + goto err; + } + + /* allocate memory for the internal state */ + priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); + if (priv == NULL) { + ret = -ENOMEM; + goto err; + } + + /* setup the priv */ + priv->client = client; + priv->i2c = i2c; + priv->tuner = config->tuner; + priv->sleeping = true; + memcpy(&priv->cfg, config, sizeof(struct rtl2832_config)); + INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work); + + /* create muxed i2c adapter for demod itself */ + priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, + rtl2832_select, NULL); + if (priv->i2c_adapter == NULL) { + ret = -ENODEV; + goto err_kfree; + } + + /* check if the demod is there */ + ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); + if (ret) + goto err_i2c_del_mux_adapter; + + /* create muxed i2c adapter for demod tuner bus */ + priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv, + 0, 1, 0, rtl2832_select, rtl2832_deselect); + if (priv->i2c_adapter_tuner == NULL) { + ret = -ENODEV; + goto err_i2c_del_mux_adapter; + } + + /* create dvb_frontend */ + memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); + priv->fe.ops.release = NULL; + priv->fe.demodulator_priv = priv; + i2c_set_clientdata(client, priv); + *pdata->dvb_frontend = &priv->fe; + + dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); + return 0; +err_i2c_del_mux_adapter: + i2c_del_mux_adapter(priv->i2c_adapter); +err_kfree: + kfree(priv); +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int rtl2832_remove(struct i2c_client *client) +{ + struct rtl2832_priv *priv = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + cancel_delayed_work_sync(&priv->i2c_gate_work); + + i2c_del_mux_adapter(priv->i2c_adapter_tuner); + + i2c_del_mux_adapter(priv->i2c_adapter); + + kfree(priv); + + return 0; +} + +static const struct i2c_device_id rtl2832_id_table[] = { + {"rtl2832", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, rtl2832_id_table); + +static struct i2c_driver rtl2832_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "rtl2832", + }, + .probe = rtl2832_probe, + .remove = rtl2832_remove, + .id_table = rtl2832_id_table, +}; + +module_i2c_driver(rtl2832_driver); + MODULE_AUTHOR("Thomas Mair "); MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 5254c1dfc8de..cfd69d8a9a81 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -50,6 +50,16 @@ struct rtl2832_config { u8 tuner; }; +struct rtl2832_platform_data { + const struct rtl2832_config *config; + + /* + * frontend + * returned by driver + */ + struct dvb_frontend **dvb_frontend; +}; + #if IS_ENABLED(CONFIG_DVB_RTL2832) struct dvb_frontend *rtl2832_attach( const struct rtl2832_config *cfg, diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index ae469f032fe6..05b2b62634c1 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -26,6 +26,7 @@ #include struct rtl2832_priv { + struct i2c_client *client; struct i2c_adapter *i2c; struct i2c_adapter *i2c_adapter; struct i2c_adapter *i2c_adapter_tuner; -- cgit v1.2.3 From 83b2f84957373683164e3780d040b3c007e06b05 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 2 Dec 2014 11:00:23 -0300 Subject: [media] rtl28xxu: switch rtl2832 demod attach to I2C binding As rtl2832 driver support now I2C binding we will switch to that one. Tested-by: Benjamin Larsson Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 29 ++++++++++++++++++++++++++--- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 1 + 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 73580f8d5a17..21657341ce35 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -790,7 +790,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2832_platform_data platform_data; const struct rtl2832_config *rtl2832_config; + struct i2c_board_info board_info = {}; + struct i2c_client *client; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -823,12 +826,26 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) } /* attach demodulator */ - adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap); - if (!adap->fe[0]) { + platform_data.config = rtl2832_config; + platform_data.dvb_frontend = &adap->fe[0]; + strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE); + board_info.addr = 0x10; + board_info.platform_data = &platform_data; + request_module("%s", board_info.type); + client = i2c_new_device(&d->i2c_adap, &board_info); + if (client == NULL || client->dev.driver == NULL) { + ret = -ENODEV; + goto err; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); ret = -ENODEV; goto err; } + priv->i2c_client_demod = client; + /* RTL2832 I2C repeater */ priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]); @@ -837,7 +854,6 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) if (priv->slave_demod) { struct i2c_board_info info = {}; - struct i2c_client *client; /* * We continue on reduced mode, without DVB-T2/C, using master @@ -1190,6 +1206,13 @@ static void rtl28xxu_exit(struct dvb_usb_device *d) i2c_unregister_device(client); } + /* remove I2C demod */ + client = priv->i2c_client_demod; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + return; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 3e3ea9d64a38..e52a2b731b92 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -57,6 +57,7 @@ struct rtl28xxu_priv { u8 page; /* integrated demod active register page */ struct i2c_adapter *demod_i2c_adapter; bool rc_active; + struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_tuner; struct i2c_client *i2c_client_slave_demod; #define SLAVE_DEMOD_NONE 0 -- cgit v1.2.3 From 8d44aeefcd79e9be3b6db4f37efc7544995b619e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 2 Dec 2014 11:23:49 -0300 Subject: [media] rtl28xxu: change module unregister order We must unregister frontend first and after that driver itself. That order went wrong after demod drivers were switched to kernel I2C drivers, causing crashes. Tested-by: Benjamin Larsson Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 77 +++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 21657341ce35..705c6c30acb7 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -917,6 +917,31 @@ err: return ret; } +static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct i2c_client *client; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* remove I2C slave demod */ + client = priv->i2c_client_slave_demod; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + /* remove I2C demod */ + client = priv->i2c_client_demod; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + return 0; +} + static struct qt1010_config rtl28xxu_qt1010_config = { .i2c_address = 0x62, /* 0xc4 */ }; @@ -1151,6 +1176,24 @@ err: return ret; } +static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct i2c_client *client; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* remove I2C tuner */ + client = priv->i2c_client_tuner; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + return 0; +} + static int rtl28xxu_init(struct dvb_usb_device *d) { int ret; @@ -1185,37 +1228,6 @@ err: return ret; } -static void rtl28xxu_exit(struct dvb_usb_device *d) -{ - struct rtl28xxu_priv *priv = d->priv; - struct i2c_client *client; - - dev_dbg(&d->udev->dev, "%s:\n", __func__); - - /* remove I2C tuner */ - client = priv->i2c_client_tuner; - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - - /* remove I2C slave demod */ - client = priv->i2c_client_slave_demod; - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - - /* remove I2C demod */ - client = priv->i2c_client_demod; - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - - return; -} - static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; @@ -1597,9 +1609,10 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .i2c_algo = &rtl28xxu_i2c_algo, .read_config = rtl2832u_read_config, .frontend_attach = rtl2832u_frontend_attach, + .frontend_detach = rtl2832u_frontend_detach, .tuner_attach = rtl2832u_tuner_attach, + .tuner_detach = rtl2832u_tuner_detach, .init = rtl28xxu_init, - .exit = rtl28xxu_exit, .get_rc_config = rtl2832u_get_rc_config, .num_adapters = 1, -- cgit v1.2.3 From cb88d7384e5e05f90c1daa7750bdb467fd026261 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 27 Jan 2015 07:18:49 -0300 Subject: [media] smiapp: Don't compile of_read_number() if CONFIG_OF isn't defined of_read_number() is defined in of.h but does not return an error code, so that non-of implementation could simply return an error. Temporarily work around this until of_read_number() can be replaced by of_property_read_u64_array(). Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index b3c81257e08d..d47eff5d3101 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2980,7 +2980,9 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev) struct property *prop; __be32 *val; uint32_t asize; +#ifdef CONFIG_OF unsigned int i; +#endif int rval; if (!dev->of_node) @@ -3057,8 +3059,10 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev) if (IS_ERR(val)) goto out_err; +#ifdef CONFIG_OF for (i = 0; i < asize; i++) pdata->op_sys_clock[i] = of_read_number(val + i * 2, 2); +#endif for (; asize > 0; asize--) dev_dbg(dev, "freq %d: %lld\n", asize - 1, -- cgit v1.2.3 From afad4dd50acbe6457413ec6a68708433d9824d37 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 27 Jan 2015 13:46:17 -0300 Subject: [media] vivid: Y offset should depend on quant. range When converting to or from Y'CbCr and R'G'B' the Y offset depends on the quantization range: it's 0 for full and 16 for limited range. But in the code it was hardcoded to 16. This messed up the brightness of the generated pattern. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c index fc9c6536ba02..34493f435d5a 100644 --- a/drivers/media/platform/vivid/vivid-tpg.c +++ b/drivers/media/platform/vivid/vivid-tpg.c @@ -352,13 +352,14 @@ static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b, { COEFF(0.5, 224), COEFF(-0.4629, 224), COEFF(-0.0405, 224) }, }; bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE; + unsigned y_offset = full ? 0 : 16; int lin_y, yc; switch (tpg->real_ycbcr_enc) { case V4L2_YCBCR_ENC_601: case V4L2_YCBCR_ENC_XV601: case V4L2_YCBCR_ENC_SYCC: - rgb2ycbcr(full ? bt601_full : bt601, r, g, b, 16, y, cb, cr); + rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr); break; case V4L2_YCBCR_ENC_BT2020: rgb2ycbcr(bt2020, r, g, b, 16, y, cb, cr); @@ -384,7 +385,7 @@ static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b, case V4L2_YCBCR_ENC_709: case V4L2_YCBCR_ENC_XV709: default: - rgb2ycbcr(full ? rec709_full : rec709, r, g, b, 0, y, cb, cr); + rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr); break; } } @@ -439,13 +440,14 @@ static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr, { COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) }, }; bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE; + unsigned y_offset = full ? 0 : 16; int lin_r, lin_g, lin_b, lin_y; switch (tpg->real_ycbcr_enc) { case V4L2_YCBCR_ENC_601: case V4L2_YCBCR_ENC_XV601: case V4L2_YCBCR_ENC_SYCC: - ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, 16, r, g, b); + ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b); break; case V4L2_YCBCR_ENC_BT2020: ycbcr2rgb(bt2020, y, cb, cr, 16, r, g, b); @@ -480,7 +482,7 @@ static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr, case V4L2_YCBCR_ENC_709: case V4L2_YCBCR_ENC_XV709: default: - ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, 16, r, g, b); + ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b); break; } } -- cgit v1.2.3 From 7cc42d9f75766246faab4a1436eb02b97041fb41 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Sun, 30 Nov 2014 23:27:53 -0300 Subject: [media] gspca_touptek: Add support for ToupTek UCMOS series USB cameras Adds support for AmScope MU800 / ToupTek UCMOS08000KPB USB microscope camera. Signed-off-by: John McMaster Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/Kconfig | 10 + drivers/media/usb/gspca/Makefile | 2 + drivers/media/usb/gspca/touptek.c | 732 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 744 insertions(+) create mode 100644 drivers/media/usb/gspca/touptek.c (limited to 'drivers') diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index eed10d782535..60af3b167f3b 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig @@ -395,6 +395,16 @@ config USB_GSPCA_TOPRO To compile this driver as a module, choose M here: the module will be called gspca_topro. +config USB_GSPCA_TOUPTEK + tristate "Touptek USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the ToupTek UCMOS + / AmScope MU series camera. + + To compile this driver as a module, choose M here: the + module will be called gspca_touptek. + config USB_GSPCA_TV8532 tristate "TV8532 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile index f46975e4c82d..9f5ccecb9c8a 100644 --- a/drivers/media/usb/gspca/Makefile +++ b/drivers/media/usb/gspca/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_USB_GSPCA_STK1135) += gspca_stk1135.o obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o +obj-$(CONFIG_USB_GSPCA_TOUPTEK) += gspca_touptek.o obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o @@ -86,6 +87,7 @@ gspca_stv0680-objs := stv0680.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o gspca_topro-objs := topro.o +gspca_touptek-objs := touptek.o gspca_tv8532-objs := tv8532.o gspca_vc032x-objs := vc032x.o gspca_vicam-objs := vicam.o diff --git a/drivers/media/usb/gspca/touptek.c b/drivers/media/usb/gspca/touptek.c new file mode 100644 index 000000000000..8b7c01e4b772 --- /dev/null +++ b/drivers/media/usb/gspca/touptek.c @@ -0,0 +1,732 @@ +/* + * ToupTek UCMOS / AmScope MU series camera driver + * TODO: contrast with ScopeTek / AmScope MDC cameras + * + * Copyright (C) 2012-2014 John McMaster + * + * Special thanks to Bushing for helping with the decrypt algorithm and + * Sean O'Sullivan / the Rensselaer Center for Open Source + * Software (RCOS) for helping me learn kernel development + * + * 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 + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gspca.h" + +#define MODULE_NAME "touptek" + +MODULE_AUTHOR("John McMaster"); +MODULE_DESCRIPTION("ToupTek UCMOS / Amscope MU microscope camera driver"); +MODULE_LICENSE("GPL"); + +/* +Exposure reg is linear with exposure time +Exposure (sec), E (reg) +0.000400, 0x0002 +0.001000, 0x0005 +0.005000, 0x0019 +0.020000, 0x0064 +0.080000, 0x0190 +0.400000, 0x07D0 +1.000000, 0x1388 +2.000000, 0x2710 + +Three gain stages +0x1000: master channel enable bit +0x007F: low gain bits +0x0080: medium gain bit +0x0100: high gain bit +gain = enable * (1 + regH) * (1 + regM) * z * regL + +Gain implementation +Want to do something similar to mt9v011.c's set_balance + +Gain does not vary with resolution (checked 640x480 vs 1600x1200) + +Constant derivation: + +Raw data: +Gain, GTOP, B, R, GBOT +1.00, 0x105C, 0x1068, 0x10C8, 0x105C +1.20, 0x106E, 0x107E, 0x10D6, 0x106E +1.40, 0x10C0, 0x10CA, 0x10E5, 0x10C0 +1.60, 0x10C9, 0x10D4, 0x10F3, 0x10C9 +1.80, 0x10D2, 0x10DE, 0x11C1, 0x10D2 +2.00, 0x10DC, 0x10E9, 0x11C8, 0x10DC +2.20, 0x10E5, 0x10F3, 0x11CF, 0x10E5 +2.40, 0x10EE, 0x10FE, 0x11D7, 0x10EE +2.60, 0x10F7, 0x11C4, 0x11DE, 0x10F7 +2.80, 0x11C0, 0x11CA, 0x11E5, 0x11C0 +3.00, 0x11C5, 0x11CF, 0x11ED, 0x11C5 + +zR = 0.0069605943152454778 + about 3/431 = 0.0069605568445475635 +zB = 0.0095695970695970703 + about 6/627 = 0.0095693779904306216 +zG = 0.010889328063241107 + about 6/551 = 0.010889292196007259 +about 10 bits for constant + 7 bits for value => at least 17 bit intermediate +with 32 bit ints should be fine for overflow etc +Essentially gains are in range 0-0x001FF + +However, V4L expects a main gain channel + R and B balance +To keep things simple for now saturate the values of balance is too high/low +This isn't really ideal but easy way to fit the Linux model + +Converted using gain model turns out to be quite linear: +Gain, GTOP, B, R, GBOT +1.00, 92, 104, 144, 92 +1.20, 110, 126, 172, 110 +1.40, 128, 148, 202, 128 +1.60, 146, 168, 230, 146 +1.80, 164, 188, 260, 164 +2.00, 184, 210, 288, 184 +2.20, 202, 230, 316, 202 +2.40, 220, 252, 348, 220 +2.60, 238, 272, 376, 238 +2.80, 256, 296, 404, 256 +3.00, 276, 316, 436, 276 + +Maximum gain is 0x7FF * 2 * 2 => 0x1FFC (8188) +or about 13 effective bits of gain +The highest the commercial driver goes in my setup 436 +However, because could *maybe* damage circuits +limit the gain until have a reason to go higher +Solution: gain clipped and warning emitted +*/ +#define GAIN_MAX 511 + +/* Frame sync is a short read */ +#define BULK_SIZE 0x4000 + +/* MT9E001 reg names to give a rough approximation */ +#define REG_COARSE_INTEGRATION_TIME_ 0x3012 +#define REG_GROUPED_PARAMETER_HOLD_ 0x3022 +#define REG_MODE_SELECT 0x0100 +#define REG_OP_SYS_CLK_DIV 0x030A +#define REG_VT_SYS_CLK_DIV 0x0302 +#define REG_PRE_PLL_CLK_DIV 0x0304 +#define REG_VT_PIX_CLK_DIV 0x0300 +#define REG_OP_PIX_CLK_DIV 0x0308 +#define REG_PLL_MULTIPLIER 0x0306 +#define REG_COARSE_INTEGRATION_TIME_ 0x3012 +#define REG_FRAME_LENGTH_LINES 0x0340 +#define REG_FRAME_LENGTH_LINES_ 0x300A +#define REG_GREEN1_GAIN 0x3056 +#define REG_GREEN2_GAIN 0x305C +#define REG_GROUPED_PARAMETER_HOLD 0x0104 +#define REG_LINE_LENGTH_PCK_ 0x300C +#define REG_MODE_SELECT 0x0100 +#define REG_PLL_MULTIPLIER 0x0306 +#define REG_READ_MODE 0x3040 +#define REG_BLUE_GAIN 0x3058 +#define REG_RED_GAIN 0x305A +#define REG_RESET_REGISTER 0x301A +#define REG_SCALE_M 0x0404 +#define REG_SCALING_MODE 0x0400 +#define REG_SOFTWARE_RESET 0x0103 +#define REG_X_ADDR_END 0x0348 +#define REG_X_ADDR_START 0x0344 +#define REG_X_ADDR_START 0x0344 +#define REG_X_OUTPUT_SIZE 0x034C +#define REG_Y_ADDR_END 0x034A +#define REG_Y_ADDR_START 0x0346 +#define REG_Y_OUTPUT_SIZE 0x034E + + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + /* How many bytes this frame */ + unsigned int this_f; + + /* + Device has separate gains for each Bayer quadrant + V4L supports master gain which is referenced to G1/G2 and supplies + individual balance controls for R/B + */ + struct v4l2_ctrl *blue; + struct v4l2_ctrl *red; +}; + +/* Used to simplify reg write error handling */ +struct cmd { + u16 value; + u16 index; +}; + +static const struct v4l2_pix_format vga_mode[] = { + {800, 600, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .bytesperline = 800, + .sizeimage = 800 * 600, + .colorspace = V4L2_COLORSPACE_SRGB}, + {1600, 1200, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .bytesperline = 1600, + .sizeimage = 1600 * 1200, + .colorspace = V4L2_COLORSPACE_SRGB}, + {3264, 2448, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .bytesperline = 3264, + .sizeimage = 3264 * 2448, + .colorspace = V4L2_COLORSPACE_SRGB}, +}; + +/* +As theres no known frame sync, the only way to keep synced is to try hard +to never miss any packets +*/ +#if MAX_NURBS < 4 +#error "Not enough URBs in the gspca table" +#endif + +static int val_reply(struct gspca_dev *gspca_dev, const char *reply, int rc) +{ + if (rc < 0) { + PERR("reply has error %d", rc); + return -EIO; + } + if (rc != 1) { + PERR("Bad reply size %d", rc); + return -EIO; + } + if (reply[0] != 0x08) { + PERR("Bad reply 0x%02X", reply[0]); + return -EIO; + } + return 0; +} + +static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) +{ + char buff[1]; + int rc; + + PDEBUG(D_USBO, "reg_w bReq=0x0B, bReqT=0xC0, wVal=0x%04X, wInd=0x%04X\n", + value, index); + rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), + 0x0B, 0xC0, value, index, buff, 1, 500); + PDEBUG(D_USBO, "rc=%d, ret={0x%02X}", rc, buff[0]); + if (rc < 0) { + PERR("Failed reg_w(0x0B, 0xC0, 0x%04X, 0x%04X) w/ rc %d\n", + value, index, rc); + gspca_dev->usb_err = rc; + return; + } + if (val_reply(gspca_dev, buff, rc)) { + PERR("Bad reply to reg_w(0x0B, 0xC0, 0x%04X, 0x%04X\n", + value, index); + gspca_dev->usb_err = -EIO; + } +} + +static void reg_w_buf(struct gspca_dev *gspca_dev, + const struct cmd *p, int l) +{ + do { + reg_w(gspca_dev, p->value, p->index); + p++; + } while (--l > 0); +} + +static void setexposure(struct gspca_dev *gspca_dev, s32 val) +{ + u16 value; + unsigned int w = gspca_dev->pixfmt.width; + + if (w == 800) + value = val * 5; + else if (w == 1600) + value = val * 3; + else if (w == 3264) + value = val * 3 / 2; + else { + PERR("Invalid width %u\n", w); + gspca_dev->usb_err = -EINVAL; + return; + } + PDEBUG(D_STREAM, "exposure: 0x%04X ms\n", value); + /* Wonder if theres a good reason for sending it twice */ + /* probably not but leave it in because...why not */ + reg_w(gspca_dev, value, REG_COARSE_INTEGRATION_TIME_); + reg_w(gspca_dev, value, REG_COARSE_INTEGRATION_TIME_); +} + +static int gainify(int in) +{ + /* + TODO: check if there are any issues with corner cases + 0x000 (0):0x07F (127): regL + 0x080 (128) - 0x0FF (255): regM, regL + 0x100 (256) - max: regH, regM, regL + */ + if (in <= 0x7F) + return 0x1000 | in; + else if (in <= 0xFF) + return 0x1080 | in / 2; + else + return 0x1180 | in / 4; +} + +static void setggain(struct gspca_dev *gspca_dev, u16 global_gain) +{ + u16 normalized; + + normalized = gainify(global_gain); + PDEBUG(D_STREAM, "gain G1/G2 (0x%04X): 0x%04X (src 0x%04X)\n", + REG_GREEN1_GAIN, + normalized, global_gain); + + reg_w(gspca_dev, normalized, REG_GREEN1_GAIN); + reg_w(gspca_dev, normalized, REG_GREEN2_GAIN); +} + +static void setbgain(struct gspca_dev *gspca_dev, + u16 gain, u16 global_gain) +{ + u16 normalized; + + normalized = global_gain + + ((u32)global_gain) * gain / GAIN_MAX; + if (normalized > GAIN_MAX) { + PDEBUG(D_STREAM, "Truncating blue 0x%04X w/ value 0x%04X\n", + GAIN_MAX, normalized); + normalized = GAIN_MAX; + } + normalized = gainify(normalized); + PDEBUG(D_STREAM, "gain B (0x%04X): 0x%04X w/ source 0x%04X\n", + REG_BLUE_GAIN, normalized, gain); + + reg_w(gspca_dev, normalized, REG_BLUE_GAIN); +} + +static void setrgain(struct gspca_dev *gspca_dev, + u16 gain, u16 global_gain) +{ + u16 normalized; + + normalized = global_gain + + ((u32)global_gain) * gain / GAIN_MAX; + if (normalized > GAIN_MAX) { + PDEBUG(D_STREAM, "Truncating gain 0x%04X w/ value 0x%04X\n", + GAIN_MAX, normalized); + normalized = GAIN_MAX; + } + normalized = gainify(normalized); + PDEBUG(D_STREAM, "gain R (0x%04X): 0x%04X w / source 0x%04X\n", + REG_RED_GAIN, normalized, gain); + + reg_w(gspca_dev, normalized, REG_RED_GAIN); +} + +static void configure_wh(struct gspca_dev *gspca_dev) +{ + unsigned int w = gspca_dev->pixfmt.width; + + PDEBUG(D_STREAM, "configure_wh\n"); + + if (w == 800) { + static const struct cmd reg_init_res[] = { + {0x0060, REG_X_ADDR_START}, + {0x0CD9, REG_X_ADDR_END}, + {0x0036, REG_Y_ADDR_START}, + {0x098F, REG_Y_ADDR_END}, + {0x07C7, REG_READ_MODE}, + }; + + reg_w_buf(gspca_dev, + reg_init_res, ARRAY_SIZE(reg_init_res)); + } else if (w == 1600) { + static const struct cmd reg_init_res[] = { + {0x009C, REG_X_ADDR_START}, + {0x0D19, REG_X_ADDR_END}, + {0x0068, REG_Y_ADDR_START}, + {0x09C5, REG_Y_ADDR_END}, + {0x06C3, REG_READ_MODE}, + }; + + reg_w_buf(gspca_dev, + reg_init_res, ARRAY_SIZE(reg_init_res)); + } else if (w == 3264) { + static const struct cmd reg_init_res[] = { + {0x00E8, REG_X_ADDR_START}, + {0x0DA7, REG_X_ADDR_END}, + {0x009E, REG_Y_ADDR_START}, + {0x0A2D, REG_Y_ADDR_END}, + {0x0241, REG_READ_MODE}, + }; + + reg_w_buf(gspca_dev, + reg_init_res, ARRAY_SIZE(reg_init_res)); + } else { + PERR("bad width %u\n", w); + gspca_dev->usb_err = -EINVAL; + return; + } + + reg_w(gspca_dev, 0x0000, REG_SCALING_MODE); + reg_w(gspca_dev, 0x0010, REG_SCALE_M); + reg_w(gspca_dev, w, REG_X_OUTPUT_SIZE); + reg_w(gspca_dev, gspca_dev->pixfmt.height, REG_Y_OUTPUT_SIZE); + + if (w == 800) { + reg_w(gspca_dev, 0x0384, REG_FRAME_LENGTH_LINES_); + reg_w(gspca_dev, 0x0960, REG_LINE_LENGTH_PCK_); + } else if (w == 1600) { + reg_w(gspca_dev, 0x0640, REG_FRAME_LENGTH_LINES_); + reg_w(gspca_dev, 0x0FA0, REG_LINE_LENGTH_PCK_); + } else if (w == 3264) { + reg_w(gspca_dev, 0x0B4B, REG_FRAME_LENGTH_LINES_); + reg_w(gspca_dev, 0x1F40, REG_LINE_LENGTH_PCK_); + } else { + PERR("bad width %u\n", w); + gspca_dev->usb_err = -EINVAL; + return; + } +} + +/* Packets that were encrypted, no idea if the grouping is significant */ +static void configure_encrypted(struct gspca_dev *gspca_dev) +{ + static const struct cmd reg_init_begin[] = { + {0x0100, REG_SOFTWARE_RESET}, + {0x0000, REG_MODE_SELECT}, + {0x0100, REG_GROUPED_PARAMETER_HOLD}, + {0x0004, REG_VT_PIX_CLK_DIV}, + {0x0001, REG_VT_SYS_CLK_DIV}, + {0x0008, REG_OP_PIX_CLK_DIV}, + {0x0001, REG_OP_SYS_CLK_DIV}, + {0x0004, REG_PRE_PLL_CLK_DIV}, + {0x0040, REG_PLL_MULTIPLIER}, + {0x0000, REG_GROUPED_PARAMETER_HOLD}, + {0x0100, REG_GROUPED_PARAMETER_HOLD}, + }; + static const struct cmd reg_init_end[] = { + {0x0000, REG_GROUPED_PARAMETER_HOLD}, + {0x0301, 0x31AE}, + {0x0805, 0x3064}, + {0x0071, 0x3170}, + {0x10DE, REG_RESET_REGISTER}, + {0x0000, REG_MODE_SELECT}, + {0x0010, REG_PLL_MULTIPLIER}, + {0x0100, REG_MODE_SELECT}, + }; + + PDEBUG(D_STREAM, "Encrypted begin, w = %u\n", gspca_dev->pixfmt.width); + reg_w_buf(gspca_dev, reg_init_begin, ARRAY_SIZE(reg_init_begin)); + configure_wh(gspca_dev); + reg_w_buf(gspca_dev, reg_init_end, ARRAY_SIZE(reg_init_end)); + reg_w(gspca_dev, 0x0100, REG_GROUPED_PARAMETER_HOLD); + reg_w(gspca_dev, 0x0000, REG_GROUPED_PARAMETER_HOLD); + + PDEBUG(D_STREAM, "Encrypted end\n"); +} + +static int configure(struct gspca_dev *gspca_dev) +{ + int rc; + uint8_t buff[4]; + + PDEBUG(D_STREAM, "configure()\n"); + + /* + First driver sets a sort of encryption key + A number of futur requests of this type have wValue and wIndex encrypted + as follows: + -Compute key = this wValue rotate left by 4 bits + (decrypt.py rotates right because we are decrypting) + -Later packets encrypt packets by XOR'ing with key + XOR encrypt/decrypt is symmetrical + wValue, and wIndex are encrypted + bRequest is not and bRequestType is always 0xC0 + This allows resyncing if key is unknown? + By setting 0 we XOR with 0 and the shifting and XOR drops out + */ + rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), + 0x16, 0xC0, 0x0000, 0x0000, buff, 2, 500); + if (val_reply(gspca_dev, buff, rc)) { + PERR("failed key req"); + return -EIO; + } + + /* + Next does some sort of 2 packet challenge / response + evidence suggests its an Atmel I2C crypto part but nobody cares to look + (to make sure its not cloned hardware?) + Ignore: I want to work with their hardware, not clone it + 16 bytes out challenge, requestType: 0x40 + 16 bytes in response, requestType: 0xC0 + */ + + rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), + 0x01, 0x40, 0x0001, 0x000F, NULL, 0, 500); + if (rc < 0) { + PERR("failed to replay packet 176 w/ rc %d\n", rc); + return rc; + } + + rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), + 0x01, 0x40, 0x0000, 0x000F, NULL, 0, 500); + if (rc < 0) { + PERR("failed to replay packet 178 w/ rc %d\n", rc); + return rc; + } + + rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), + 0x01, 0x40, 0x0001, 0x000F, NULL, 0, 500); + if (rc < 0) { + PERR("failed to replay packet 180 w/ rc %d\n", rc); + return rc; + } + + /* + Serial number? Doesn't seem to be required + cam1: \xE6\x0D\x00\x00, cam2: \x70\x19\x00\x00 + rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), + 0x20, 0xC0, 0x0000, 0x0000, buff, 4, 500); + */ + + /* Large (EEPROM?) read, skip it since no idea what to do with it */ + gspca_dev->usb_err = 0; + configure_encrypted(gspca_dev); + if (gspca_dev->usb_err) + return gspca_dev->usb_err; + + /* Omitted this by accident, does not work without it */ + rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), + 0x01, 0x40, 0x0003, 0x000F, NULL, 0, 500); + if (rc < 0) { + PERR("failed to replay final packet w/ rc %d\n", rc); + return rc; + } + + PDEBUG(D_STREAM, "Configure complete\n"); + return 0; +} + +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + gspca_dev->cam.cam_mode = vga_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); + + /* Yes we want URBs and we want them now! */ + gspca_dev->cam.no_urb_create = 0; + gspca_dev->cam.bulk_nurbs = 4; + /* Largest size the windows driver uses */ + gspca_dev->cam.bulk_size = BULK_SIZE; + /* Def need to use bulk transfers */ + gspca_dev->cam.bulk = 1; + + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int rc; + + sd->this_f = 0; + + rc = configure(gspca_dev); + if (rc < 0) { + PERR("Failed configure"); + return rc; + } + /* First two frames have messed up gains + Drop them to avoid special cases in user apps? */ + return 0; +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (len != BULK_SIZE) { + /* can we finish a frame? */ + if (sd->this_f + len == gspca_dev->pixfmt.sizeimage) { + gspca_frame_add(gspca_dev, LAST_PACKET, data, len); + PDEBUG(D_FRAM, "finish frame sz %u/%u w/ len %u\n", + sd->this_f, gspca_dev->pixfmt.sizeimage, len); + /* lost some data, discard the frame */ + } else { + gspca_frame_add(gspca_dev, DISCARD_PACKET, NULL, 0); + PDEBUG(D_FRAM, "abort frame sz %u/%u w/ len %u\n", + sd->this_f, gspca_dev->pixfmt.sizeimage, len); + } + sd->this_f = 0; + } else { + if (sd->this_f == 0) + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); + else + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + sd->this_f += len; + } +} + +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +static int sd_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct gspca_dev *gspca_dev = + container_of(ctrl->handler, struct gspca_dev, ctrl_handler); + struct sd *sd = (struct sd *) gspca_dev; + + gspca_dev->usb_err = 0; + + if (!gspca_dev->streaming) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + setexposure(gspca_dev, ctrl->val); + break; + case V4L2_CID_GAIN: + /* gspca_dev->gain automatically updated */ + setggain(gspca_dev, gspca_dev->gain->val); + break; + case V4L2_CID_BLUE_BALANCE: + sd->blue->val = ctrl->val; + setbgain(gspca_dev, sd->blue->val, gspca_dev->gain->val); + break; + case V4L2_CID_RED_BALANCE: + sd->red->val = ctrl->val; + setrgain(gspca_dev, sd->red->val, gspca_dev->gain->val); + break; + } + return gspca_dev->usb_err; +} + +static const struct v4l2_ctrl_ops sd_ctrl_ops = { + .s_ctrl = sd_s_ctrl, +}; + +static int sd_init_controls(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; + + gspca_dev->vdev.ctrl_handler = hdl; + v4l2_ctrl_handler_init(hdl, 4); + + gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + /* Mostly limited by URB timeouts */ + /* XXX: make dynamic based on frame rate? */ + V4L2_CID_EXPOSURE, 0, 800, 1, 350); + gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_GAIN, 0, 511, 1, 128); + sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_BLUE_BALANCE, 0, 1023, 1, 80); + sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_RED_BALANCE, 0, 1023, 1, 295); + + if (hdl->error) { + PERR("Could not initialize controls\n"); + return hdl->error; + } + return 0; +} + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .init_controls = sd_init_controls, + .start = sd_start, + .pkt_scan = sd_pkt_scan, +}; + +/* Table of supported USB devices */ +static const struct usb_device_id device_table[] = { + /* Commented out devices should be related */ + /* AS: AmScope, TT: ToupTek */ + /* { USB_DEVICE(0x0547, 0x6035) }, TT UCMOS00350KPA */ + /* { USB_DEVICE(0x0547, 0x6130) }, TT UCMOS01300KPA */ + /* { USB_DEVICE(0x0547, 0x6200) }, TT UCMOS02000KPA */ + /* { USB_DEVICE(0x0547, 0x6310) }, TT UCMOS03100KPA */ + /* { USB_DEVICE(0x0547, 0x6510) }, TT UCMOS05100KPA */ + /* { USB_DEVICE(0x0547, 0x6800) }, TT UCMOS08000KPA */ + /* { USB_DEVICE(0x0547, 0x6801) }, TT UCMOS08000KPB */ + { USB_DEVICE(0x0547, 0x6801) }, /* TT UCMOS08000KPB, AS MU800 */ + /* { USB_DEVICE(0x0547, 0x6900) }, TT UCMOS09000KPA */ + /* { USB_DEVICE(0x0547, 0x6901) }, TT UCMOS09000KPB */ + /* { USB_DEVICE(0x0547, 0x6010) }, TT UCMOS10000KPA */ + /* { USB_DEVICE(0x0547, 0x6014) }, TT UCMOS14000KPA */ + /* { USB_DEVICE(0x0547, 0x6131) }, TT UCMOS01300KMA */ + /* { USB_DEVICE(0x0547, 0x6511) }, TT UCMOS05100KMA */ + /* { USB_DEVICE(0x0547, 0x8080) }, TT UHCCD00800KPA */ + /* { USB_DEVICE(0x0547, 0x8140) }, TT UHCCD01400KPA */ + /* { USB_DEVICE(0x0547, 0x8141) }, TT EXCCD01400KPA */ + /* { USB_DEVICE(0x0547, 0x8200) }, TT UHCCD02000KPA */ + /* { USB_DEVICE(0x0547, 0x8201) }, TT UHCCD02000KPB */ + /* { USB_DEVICE(0x0547, 0x8310) }, TT UHCCD03100KPA */ + /* { USB_DEVICE(0x0547, 0x8500) }, TT UHCCD05000KPA */ + /* { USB_DEVICE(0x0547, 0x8510) }, TT UHCCD05100KPA */ + /* { USB_DEVICE(0x0547, 0x8600) }, TT UHCCD06000KPA */ + /* { USB_DEVICE(0x0547, 0x8800) }, TT UHCCD08000KPA */ + /* { USB_DEVICE(0x0547, 0x8315) }, TT UHCCD03150KPA */ + /* { USB_DEVICE(0x0547, 0x7800) }, TT UHCCD00800KMA */ + /* { USB_DEVICE(0x0547, 0x7140) }, TT UHCCD01400KMA */ + /* { USB_DEVICE(0x0547, 0x7141) }, TT UHCCD01400KMB */ + /* { USB_DEVICE(0x0547, 0x7200) }, TT UHCCD02000KMA */ + /* { USB_DEVICE(0x0547, 0x7315) }, TT UHCCD03150KMA */ + { } +}; +MODULE_DEVICE_TABLE(usb, device_table); + +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From 2c794075d420f22ba4280f46ac7d43be0acb3e95 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Jan 2015 18:22:04 -0200 Subject: [media] gspca/touptek: Fix a few CodingStyle issues Checkpatch complained about a few issues, like FSF address. Also, multi-line comments are not following the Kernel CodingStyle. While not too late, let's fix those issues. Cc: John McMaster Cc: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/touptek.c | 221 +++++++++++++++++++------------------- 1 file changed, 110 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/gspca/touptek.c b/drivers/media/usb/gspca/touptek.c index 8b7c01e4b772..7bac6bc96063 100644 --- a/drivers/media/usb/gspca/touptek.c +++ b/drivers/media/usb/gspca/touptek.c @@ -17,10 +17,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "gspca.h" @@ -32,80 +28,80 @@ MODULE_DESCRIPTION("ToupTek UCMOS / Amscope MU microscope camera driver"); MODULE_LICENSE("GPL"); /* -Exposure reg is linear with exposure time -Exposure (sec), E (reg) -0.000400, 0x0002 -0.001000, 0x0005 -0.005000, 0x0019 -0.020000, 0x0064 -0.080000, 0x0190 -0.400000, 0x07D0 -1.000000, 0x1388 -2.000000, 0x2710 - -Three gain stages -0x1000: master channel enable bit -0x007F: low gain bits -0x0080: medium gain bit -0x0100: high gain bit -gain = enable * (1 + regH) * (1 + regM) * z * regL - -Gain implementation -Want to do something similar to mt9v011.c's set_balance - -Gain does not vary with resolution (checked 640x480 vs 1600x1200) - -Constant derivation: - -Raw data: -Gain, GTOP, B, R, GBOT -1.00, 0x105C, 0x1068, 0x10C8, 0x105C -1.20, 0x106E, 0x107E, 0x10D6, 0x106E -1.40, 0x10C0, 0x10CA, 0x10E5, 0x10C0 -1.60, 0x10C9, 0x10D4, 0x10F3, 0x10C9 -1.80, 0x10D2, 0x10DE, 0x11C1, 0x10D2 -2.00, 0x10DC, 0x10E9, 0x11C8, 0x10DC -2.20, 0x10E5, 0x10F3, 0x11CF, 0x10E5 -2.40, 0x10EE, 0x10FE, 0x11D7, 0x10EE -2.60, 0x10F7, 0x11C4, 0x11DE, 0x10F7 -2.80, 0x11C0, 0x11CA, 0x11E5, 0x11C0 -3.00, 0x11C5, 0x11CF, 0x11ED, 0x11C5 - -zR = 0.0069605943152454778 - about 3/431 = 0.0069605568445475635 -zB = 0.0095695970695970703 - about 6/627 = 0.0095693779904306216 -zG = 0.010889328063241107 - about 6/551 = 0.010889292196007259 -about 10 bits for constant + 7 bits for value => at least 17 bit intermediate -with 32 bit ints should be fine for overflow etc -Essentially gains are in range 0-0x001FF - -However, V4L expects a main gain channel + R and B balance -To keep things simple for now saturate the values of balance is too high/low -This isn't really ideal but easy way to fit the Linux model - -Converted using gain model turns out to be quite linear: -Gain, GTOP, B, R, GBOT -1.00, 92, 104, 144, 92 -1.20, 110, 126, 172, 110 -1.40, 128, 148, 202, 128 -1.60, 146, 168, 230, 146 -1.80, 164, 188, 260, 164 -2.00, 184, 210, 288, 184 -2.20, 202, 230, 316, 202 -2.40, 220, 252, 348, 220 -2.60, 238, 272, 376, 238 -2.80, 256, 296, 404, 256 -3.00, 276, 316, 436, 276 - -Maximum gain is 0x7FF * 2 * 2 => 0x1FFC (8188) -or about 13 effective bits of gain -The highest the commercial driver goes in my setup 436 -However, because could *maybe* damage circuits -limit the gain until have a reason to go higher -Solution: gain clipped and warning emitted -*/ + * Exposure reg is linear with exposure time + * Exposure (sec), E (reg) + * 0.000400, 0x0002 + * 0.001000, 0x0005 + * 0.005000, 0x0019 + * 0.020000, 0x0064 + * 0.080000, 0x0190 + * 0.400000, 0x07D0 + * 1.000000, 0x1388 + * 2.000000, 0x2710 + * + * Three gain stages + * 0x1000: master channel enable bit + * 0x007F: low gain bits + * 0x0080: medium gain bit + * 0x0100: high gain bit + * gain = enable * (1 + regH) * (1 + regM) * z * regL + * + * Gain implementation + * Want to do something similar to mt9v011.c's set_balance + * + * Gain does not vary with resolution (checked 640x480 vs 1600x1200) + * + * Constant derivation: + * + * Raw data: + * Gain, GTOP, B, R, GBOT + * 1.00, 0x105C, 0x1068, 0x10C8, 0x105C + * 1.20, 0x106E, 0x107E, 0x10D6, 0x106E + * 1.40, 0x10C0, 0x10CA, 0x10E5, 0x10C0 + * 1.60, 0x10C9, 0x10D4, 0x10F3, 0x10C9 + * 1.80, 0x10D2, 0x10DE, 0x11C1, 0x10D2 + * 2.00, 0x10DC, 0x10E9, 0x11C8, 0x10DC + * 2.20, 0x10E5, 0x10F3, 0x11CF, 0x10E5 + * 2.40, 0x10EE, 0x10FE, 0x11D7, 0x10EE + * 2.60, 0x10F7, 0x11C4, 0x11DE, 0x10F7 + * 2.80, 0x11C0, 0x11CA, 0x11E5, 0x11C0 + * 3.00, 0x11C5, 0x11CF, 0x11ED, 0x11C5 + * + * zR = 0.0069605943152454778 + * about 3/431 = 0.0069605568445475635 + * zB = 0.0095695970695970703 + * about 6/627 = 0.0095693779904306216 + * zG = 0.010889328063241107 + * about 6/551 = 0.010889292196007259 + * about 10 bits for constant + 7 bits for value => at least 17 bit + * intermediate with 32 bit ints should be fine for overflow etc + * Essentially gains are in range 0-0x001FF + * + * However, V4L expects a main gain channel + R and B balance + * To keep things simple for now saturate the values of balance is too high/low + * This isn't really ideal but easy way to fit the Linux model + * + * Converted using gain model turns out to be quite linear: + * Gain, GTOP, B, R, GBOT + * 1.00, 92, 104, 144, 92 + * 1.20, 110, 126, 172, 110 + * 1.40, 128, 148, 202, 128 + * 1.60, 146, 168, 230, 146 + * 1.80, 164, 188, 260, 164 + * 2.00, 184, 210, 288, 184 + * 2.20, 202, 230, 316, 202 + * 2.40, 220, 252, 348, 220 + * 2.60, 238, 272, 376, 238 + * 2.80, 256, 296, 404, 256 + * 3.00, 276, 316, 436, 276 + * + * Maximum gain is 0x7FF * 2 * 2 => 0x1FFC (8188) + * or about 13 effective bits of gain + * The highest the commercial driver goes in my setup 436 + * However, because could *maybe* damage circuits + * limit the gain until have a reason to go higher + * Solution: gain clipped and warning emitted + */ #define GAIN_MAX 511 /* Frame sync is a short read */ @@ -189,9 +185,9 @@ static const struct v4l2_pix_format vga_mode[] = { }; /* -As theres no known frame sync, the only way to keep synced is to try hard -to never miss any packets -*/ + * As theres no known frame sync, the only way to keep synced is to try hard + * to never miss any packets + */ #if MAX_NURBS < 4 #error "Not enough URBs in the gspca table" #endif @@ -218,7 +214,8 @@ static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) char buff[1]; int rc; - PDEBUG(D_USBO, "reg_w bReq=0x0B, bReqT=0xC0, wVal=0x%04X, wInd=0x%04X\n", + PDEBUG(D_USBO, + "reg_w bReq=0x0B, bReqT=0xC0, wVal=0x%04X, wInd=0x%04X\n", value, index); rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), 0x0B, 0xC0, value, index, buff, 1, 500); @@ -271,11 +268,11 @@ static void setexposure(struct gspca_dev *gspca_dev, s32 val) static int gainify(int in) { /* - TODO: check if there are any issues with corner cases - 0x000 (0):0x07F (127): regL - 0x080 (128) - 0x0FF (255): regM, regL - 0x100 (256) - max: regH, regM, regL - */ + * TODO: check if there are any issues with corner cases + * 0x000 (0):0x07F (127): regL + * 0x080 (128) - 0x0FF (255): regM, regL + * 0x100 (256) - max: regH, regM, regL + */ if (in <= 0x7F) return 0x1000 | in; else if (in <= 0xFF) @@ -446,18 +443,18 @@ static int configure(struct gspca_dev *gspca_dev) PDEBUG(D_STREAM, "configure()\n"); /* - First driver sets a sort of encryption key - A number of futur requests of this type have wValue and wIndex encrypted - as follows: - -Compute key = this wValue rotate left by 4 bits - (decrypt.py rotates right because we are decrypting) - -Later packets encrypt packets by XOR'ing with key - XOR encrypt/decrypt is symmetrical - wValue, and wIndex are encrypted - bRequest is not and bRequestType is always 0xC0 - This allows resyncing if key is unknown? - By setting 0 we XOR with 0 and the shifting and XOR drops out - */ + * First driver sets a sort of encryption key + * A number of futur requests of this type have wValue and wIndex + * encrypted as follows: + * -Compute key = this wValue rotate left by 4 bits + * (decrypt.py rotates right because we are decrypting) + * -Later packets encrypt packets by XOR'ing with key + * XOR encrypt/decrypt is symmetrical + * wValue, and wIndex are encrypted + * bRequest is not and bRequestType is always 0xC0 + * This allows resyncing if key is unknown? + * By setting 0 we XOR with 0 and the shifting and XOR drops out + */ rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), 0x16, 0xC0, 0x0000, 0x0000, buff, 2, 500); if (val_reply(gspca_dev, buff, rc)) { @@ -466,13 +463,14 @@ static int configure(struct gspca_dev *gspca_dev) } /* - Next does some sort of 2 packet challenge / response - evidence suggests its an Atmel I2C crypto part but nobody cares to look - (to make sure its not cloned hardware?) - Ignore: I want to work with their hardware, not clone it - 16 bytes out challenge, requestType: 0x40 - 16 bytes in response, requestType: 0xC0 - */ + * Next does some sort of 2 packet challenge / response + * evidence suggests its an Atmel I2C crypto part but nobody cares to + * look + * (to make sure its not cloned hardware?) + * Ignore: I want to work with their hardware, not clone it + * 16 bytes out challenge, requestType: 0x40 + * 16 bytes in response, requestType: 0xC0 + */ rc = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0x01, 0x40, 0x0001, 0x000F, NULL, 0, 500); @@ -496,11 +494,12 @@ static int configure(struct gspca_dev *gspca_dev) } /* - Serial number? Doesn't seem to be required - cam1: \xE6\x0D\x00\x00, cam2: \x70\x19\x00\x00 - rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), - 0x20, 0xC0, 0x0000, 0x0000, buff, 4, 500); - */ + * Serial number? Doesn't seem to be required + * cam1: \xE6\x0D\x00\x00, cam2: \x70\x19\x00\x00 + * rc = usb_control_msg(gspca_dev->dev, + * usb_rcvctrlpipe(gspca_dev->dev, 0), + * 0x20, 0xC0, 0x0000, 0x0000, buff, 4, 500); + */ /* Large (EEPROM?) read, skip it since no idea what to do with it */ gspca_dev->usb_err = 0; -- cgit v1.2.3 From 44f8af68469a9a7c8507fade3e4ca4bba58c2ff1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 20 Nov 2014 11:59:04 -0300 Subject: [media] rc: sunxi-cir: Add support for an optional reset controller On sun6i the cir block is attached to the reset controller, add support for de-asserting the reset if a reset controller is specified in dt. Signed-off-by: Hans de Goede Acked-by: Mauro Carvalho Chehab Acked-by: Maxime Ripard Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/sunxi-ir.txt | 2 ++ drivers/media/rc/sunxi-cir.c | 25 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 23dd5ad07b7c..6b70b9b47b7d 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -10,6 +10,7 @@ Required properties: Optional properties: - linux,rc-map-name : Remote control map name. +- resets : phandle + reset specifier pair Example: @@ -17,6 +18,7 @@ ir0: ir@01c21800 { compatible = "allwinner,sun4i-a10-ir"; clocks = <&apb0_gates 6>, <&ir0_clk>; clock-names = "apb", "ir"; + resets = <&apb0_rst 1>; interrupts = <0 5 1>; reg = <0x01C21800 0x40>; linux,rc-map-name = "rc-rc6-mce"; diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index 340f7f51eed4..06170e01a5e9 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #define SUNXI_IR_DEV "sunxi-ir" @@ -95,6 +96,7 @@ struct sunxi_ir { int irq; struct clk *clk; struct clk *apb_clk; + struct reset_control *rst; const char *map_name; }; @@ -166,15 +168,29 @@ static int sunxi_ir_probe(struct platform_device *pdev) return PTR_ERR(ir->clk); } + /* Reset (optional) */ + ir->rst = devm_reset_control_get_optional(dev, NULL); + if (IS_ERR(ir->rst)) { + ret = PTR_ERR(ir->rst); + if (ret == -EPROBE_DEFER) + return ret; + ir->rst = NULL; + } else { + ret = reset_control_deassert(ir->rst); + if (ret) + return ret; + } + ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK); if (ret) { dev_err(dev, "set ir base clock failed!\n"); - return ret; + goto exit_reset_assert; } if (clk_prepare_enable(ir->apb_clk)) { dev_err(dev, "try to enable apb_ir_clk failed\n"); - return -EINVAL; + ret = -EINVAL; + goto exit_reset_assert; } if (clk_prepare_enable(ir->clk)) { @@ -271,6 +287,9 @@ exit_clkdisable_clk: clk_disable_unprepare(ir->clk); exit_clkdisable_apb_clk: clk_disable_unprepare(ir->apb_clk); +exit_reset_assert: + if (ir->rst) + reset_control_assert(ir->rst); return ret; } @@ -282,6 +301,8 @@ static int sunxi_ir_remove(struct platform_device *pdev) clk_disable_unprepare(ir->clk); clk_disable_unprepare(ir->apb_clk); + if (ir->rst) + reset_control_assert(ir->rst); spin_lock_irqsave(&ir->ir_lock, flags); /* disable IR IRQ */ -- cgit v1.2.3 From a4bca4c7ad36a4cdafc87d1dce3758cdccef1ca7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 20 Nov 2014 12:10:47 -0300 Subject: [media] rc: sunxi-cir: Add support for the larger fifo found on sun5i and sun6i Add support for the larger fifo found on sun5i and sun6i, having a separate compatible for the ir found on sun5i & sun6i also is useful if we ever want to add ir transmit support, because the sun5i & sun6i version do not have transmit support. Note this commits also adds checking for the end-of-packet interrupt flag (which was already enabled), as the fifo-data-available interrupt flag only gets set when the trigger-level is exceeded. So far we've been getting away with not doing this because of the low trigger-level, but this is something which we should have done since day one. Signed-off-by: Hans de Goede Acked-by: Mauro Carvalho Chehab Acked-by: Maxime Ripard Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/sunxi-ir.txt | 2 +- drivers/media/rc/sunxi-cir.c | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 6b70b9b47b7d..1811a067c72c 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -1,7 +1,7 @@ Device-Tree bindings for SUNXI IR controller found in sunXi SoC family Required properties: -- compatible : should be "allwinner,sun4i-a10-ir"; +- compatible : "allwinner,sun4i-a10-ir" or "allwinner,sun5i-a13-ir" - clocks : list of clock specifiers, corresponding to entries in clock-names property; - clock-names : should contain "apb" and "ir" entries; diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index 06170e01a5e9..7830aef3db45 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -56,12 +56,12 @@ #define REG_RXINT_RAI_EN BIT(4) /* Rx FIFO available byte level */ -#define REG_RXINT_RAL(val) (((val) << 8) & (GENMASK(11, 8))) +#define REG_RXINT_RAL(val) ((val) << 8) /* Rx Interrupt Status */ #define SUNXI_IR_RXSTA_REG 0x30 /* RX FIFO Get Available Counter */ -#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0))) +#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (ir->fifo_size * 2 - 1)) /* Clear all interrupt status value */ #define REG_RXSTA_CLEARALL 0xff @@ -72,10 +72,6 @@ /* CIR_REG register idle threshold */ #define REG_CIR_ITHR(val) (((val) << 8) & (GENMASK(15, 8))) -/* Hardware supported fifo size */ -#define SUNXI_IR_FIFO_SIZE 16 -/* How many messages in FIFO trigger IRQ */ -#define TRIGGER_LEVEL 8 /* Required frequency for IR0 or IR1 clock in CIR mode */ #define SUNXI_IR_BASE_CLK 8000000 /* Frequency after IR internal divider */ @@ -94,6 +90,7 @@ struct sunxi_ir { struct rc_dev *rc; void __iomem *base; int irq; + int fifo_size; struct clk *clk; struct clk *apb_clk; struct reset_control *rst; @@ -115,11 +112,11 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) /* clean all pending statuses */ writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG); - if (status & REG_RXINT_RAI_EN) { + if (status & (REG_RXINT_RAI_EN | REG_RXINT_RPEI_EN)) { /* How many messages in fifo */ rc = REG_RXSTA_GET_AC(status); /* Sanity check */ - rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc; + rc = rc > ir->fifo_size ? ir->fifo_size : rc; /* If we have data */ for (cnt = 0; cnt < rc; cnt++) { /* for each bit in fifo */ @@ -156,6 +153,11 @@ static int sunxi_ir_probe(struct platform_device *pdev) if (!ir) return -ENOMEM; + if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir")) + ir->fifo_size = 64; + else + ir->fifo_size = 16; + /* Clock */ ir->apb_clk = devm_clk_get(dev, "apb"); if (IS_ERR(ir->apb_clk)) { @@ -271,7 +273,7 @@ static int sunxi_ir_probe(struct platform_device *pdev) * level */ writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN | - REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1), + REG_RXINT_RAI_EN | REG_RXINT_RAL(ir->fifo_size / 2 - 1), ir->base + SUNXI_IR_RXINT_REG); /* Enable IR Module */ @@ -319,6 +321,7 @@ static int sunxi_ir_remove(struct platform_device *pdev) static const struct of_device_id sunxi_ir_match[] = { { .compatible = "allwinner,sun4i-a10-ir", }, + { .compatible = "allwinner,sun5i-a13-ir", }, {}, }; -- cgit v1.2.3 From 80b0963e1698e10a58451f0508058fc20e48334a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Aug 2014 07:29:59 -0300 Subject: [media] pwc: fix WARN_ON If start_streaming fails, then the buffers must be given back to vb2 with state QUEUED, not ERROR. Otherwise a WARN_ON will be generated. In the disconnect it is pointless to call pwc_cleanup_queued_bufs() as stop_streaming() will be called anyway. Signed-off-by: Hans Verkuil Tested-by: Hans Verkuil Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pwc/pwc-if.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 15b754da4a2c..702267e208ba 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -508,7 +508,8 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) } /* Must be called with vb_queue_lock hold */ -static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) +static void pwc_cleanup_queued_bufs(struct pwc_device *pdev, + enum vb2_buffer_state state) { unsigned long flags = 0; @@ -519,7 +520,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list); list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&buf->vb, state); } spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); } @@ -674,7 +675,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) pwc_set_leds(pdev, 0, 0); pwc_camera_power(pdev, 0); /* And cleanup any queued bufs!! */ - pwc_cleanup_queued_bufs(pdev); + pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED); } mutex_unlock(&pdev->v4l2_lock); @@ -692,7 +693,9 @@ static void stop_streaming(struct vb2_queue *vq) pwc_isoc_cleanup(pdev); } - pwc_cleanup_queued_bufs(pdev); + pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_ERROR); + if (pdev->fill_buf) + vb2_buffer_done(&pdev->fill_buf->vb, VB2_BUF_STATE_ERROR); mutex_unlock(&pdev->v4l2_lock); } @@ -1125,7 +1128,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) if (pdev->vb_queue.streaming) pwc_isoc_cleanup(pdev); pdev->udev = NULL; - pwc_cleanup_queued_bufs(pdev); v4l2_device_disconnect(&pdev->v4l2_dev); video_unregister_device(&pdev->vdev); -- cgit v1.2.3 From 13e6c9f4bc11a20b25718bd4197295aa56db8d38 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Fri, 11 Jul 2014 09:56:57 -0300 Subject: [media] gspca_stv06xx: enable button found on some Quickcam Express variant Signed-off-by: Antonio Ospite Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/stv06xx/stv06xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c index 49d209bbf9ee..6ac93d8db427 100644 --- a/drivers/media/usb/gspca/stv06xx/stv06xx.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c @@ -505,13 +505,13 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, { int ret = -EINVAL; - if (len == 1 && data[0] == 0x80) { + if (len == 1 && (data[0] == 0x80 || data[0] == 0x10)) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); input_sync(gspca_dev->input_dev); ret = 0; } - if (len == 1 && data[0] == 0x88) { + if (len == 1 && (data[0] == 0x88 || data[0] == 0x11)) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); input_sync(gspca_dev->input_dev); ret = 0; -- cgit v1.2.3 From 0f5b26576246251622e33c076486b7cb0bdb0d99 Mon Sep 17 00:00:00 2001 From: Joe Howse Date: Mon, 29 Dec 2014 12:00:03 -0300 Subject: [media] gspca: Add high-speed modes for PS3 Eye camera Add support in the PS3 Eye driver for QVGA capture at higher frame rates: 187, 150, and 137 FPS. This functionality is valuable because the PS3 Eye is popular for computer vision projects and no other camera in its price range supports such high frame rates. Correct a QVGA mode that was listed as 40 FPS. It is really 37 FPS (half of 75 FPS). Tests confirm that the nominal frame rates are achieved. Signed-off-by: Joe Howse Tested-by: Antonio Ospite Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/ov534.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index 90f0d637cd9d..a9c866d6d82d 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c @@ -12,6 +12,8 @@ * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr * PS3 Eye camera - brightness, contrast, awb, agc, aec controls * added by Max Thrun + * PS3 Eye camera - FPS range extended by Joseph Howse + * http://nummist.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -116,7 +118,7 @@ static const struct v4l2_pix_format ov767x_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG}, }; -static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; +static const u8 qvga_rates[] = {187, 150, 137, 125, 100, 75, 60, 50, 37, 30}; static const u8 vga_rates[] = {60, 50, 40, 30, 15}; static const struct framerates ov772x_framerates[] = { @@ -769,12 +771,16 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) {15, 0x03, 0x41, 0x04}, }; static const struct rate_s rate_1[] = { /* 320x240 */ +/* {205, 0x01, 0xc1, 0x02}, * 205 FPS: video is partly corrupt */ + {187, 0x01, 0x81, 0x02}, /* 187 FPS or below: video is valid */ + {150, 0x01, 0xc1, 0x04}, + {137, 0x02, 0xc1, 0x02}, {125, 0x02, 0x81, 0x02}, {100, 0x02, 0xc1, 0x04}, {75, 0x03, 0xc1, 0x04}, {60, 0x04, 0xc1, 0x04}, {50, 0x02, 0x41, 0x04}, - {40, 0x03, 0x41, 0x04}, + {37, 0x03, 0x41, 0x04}, {30, 0x04, 0x41, 0x04}, }; -- cgit v1.2.3 From c7e5a726d5fbf453c49fc8326a6580402643c900 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 15 Jan 2015 07:42:36 -0300 Subject: [media] gspca: Fix underflow in vidioc_s_parm() "n" is a user controlled integer. The code here doesn't handle the case where "n" is negative and this causes a static checker warning. drivers/media/usb/gspca/gspca.c:1571 vidioc_s_parm() warn: no lower bound on 'n' parm.capture.readbuffers is unsigned, so make n unsigned too, fixing this. Reported-by: Dan Carpenter Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 43d65057a5fe..e54cee856a80 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1562,7 +1562,7 @@ static int vidioc_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { struct gspca_dev *gspca_dev = video_drvdata(filp); - int n; + unsigned int n; n = parm->parm.capture.readbuffers; if (n == 0 || n >= GSPCA_MAX_FRAMES) -- cgit v1.2.3 From 91de062f50c969d1613dd9881c275e58f228b3ac Mon Sep 17 00:00:00 2001 From: Luca Bonissi Date: Mon, 26 Jan 2015 07:38:17 -0300 Subject: [media] gspca_vc032x: Fix wrong bytesperline I found a problem on vc032x gspca usb webcam subdriver: "bytesperline" property is wrong for YUYV and YVYU formats. With recent v4l-utils library (>=0.9.1), that uses "bytesperline" for pixel format conversion, the result is a wrong jerky image. Patch tested on my laptop (USB webcam Logitech Orbicam 046d:0892). BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=91181 Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/vc032x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c index c00ac57de510..b4efb2fb36fa 100644 --- a/drivers/media/usb/gspca/vc032x.c +++ b/drivers/media/usb/gspca/vc032x.c @@ -68,12 +68,12 @@ enum sensors { static const struct v4l2_pix_format vc0321_mode[] = { {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, - .bytesperline = 320, + .bytesperline = 320 * 2, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, - .bytesperline = 640, + .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, @@ -97,17 +97,17 @@ static const struct v4l2_pix_format vc0323_mode[] = { }; static const struct v4l2_pix_format bi_mode[] = { {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 320, + .bytesperline = 320 * 2, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2}, {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 640, + .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 1280, + .bytesperline = 1280 * 2, .sizeimage = 1280 * 1024 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, -- cgit v1.2.3 From bdba90df2e30e98d192121117aaca545875d9f39 Mon Sep 17 00:00:00 2001 From: Michael Ira Krufky Date: Sun, 21 Dec 2014 18:48:19 -0300 Subject: [media] lgdt3305: we only need to pass state into lgdt3305_mpeg_mode_polarity() Simplify the code a little bit by removing some uneeded arguments to lgdt3305_mpeg_mode_polarity(). Signed-off-by: Michael Ira Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/lgdt3305.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 60df376e65c5..13dddaf3ba10 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -236,12 +236,12 @@ static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state, return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode); } -static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state, - enum lgdt3305_tp_clock_edge edge, - enum lgdt3305_tp_valid_polarity valid) +static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state) { u8 val; int ret; + enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge; + enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity; lg_dbg("edge = %d, valid = %d\n", edge, valid); @@ -740,9 +740,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe) goto fail; /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */ - ret = lgdt3305_mpeg_mode_polarity(state, - state->cfg->tpclk_edge, - state->cfg->tpvalid_polarity); + ret = lgdt3305_mpeg_mode_polarity(state); fail: return ret; } @@ -806,9 +804,7 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe) goto fail; /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */ - ret = lgdt3305_mpeg_mode_polarity(state, - state->cfg->tpclk_edge, - state->cfg->tpvalid_polarity); + ret = lgdt3305_mpeg_mode_polarity(state); fail: return ret; } -- cgit v1.2.3 From 27f7ef7ca952cf39214520248b2d792add756117 Mon Sep 17 00:00:00 2001 From: Michael Ira Krufky Date: Sun, 21 Dec 2014 18:54:50 -0300 Subject: [media] lgdt3305: add support for fixed tp clock mode Add support for controlling TP clock mode for VSB and QAM annex-B/C mode. Gated clock mode is the default value, and does not support QAM annex-C. The patch enables setting this control to fixed clock mode. Signed-off-by: Michael Ira Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/lgdt3305.c | 3 +++ drivers/media/dvb-frontends/lgdt3305.h | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 13dddaf3ba10..d08570af1c10 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -241,6 +241,7 @@ static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state) u8 val; int ret; enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge; + enum lgdt3305_tp_clock_mode mode = state->cfg->tpclk_mode; enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity; lg_dbg("edge = %d, valid = %d\n", edge, valid); @@ -253,6 +254,8 @@ static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state) if (edge) val |= 0x08; + if (mode) + val |= 0x40; if (valid) val |= 0x01; diff --git a/drivers/media/dvb-frontends/lgdt3305.h b/drivers/media/dvb-frontends/lgdt3305.h index d9ab556c1b27..9c03e530e01b 100644 --- a/drivers/media/dvb-frontends/lgdt3305.h +++ b/drivers/media/dvb-frontends/lgdt3305.h @@ -37,6 +37,11 @@ enum lgdt3305_tp_clock_edge { LGDT3305_TPCLK_FALLING_EDGE = 1, }; +enum lgdt3305_tp_clock_mode { + LGDT3305_TPCLK_GATED = 0, + LGDT3305_TPCLK_FIXED = 1, +}; + enum lgdt3305_tp_valid_polarity { LGDT3305_TP_VALID_LOW = 0, LGDT3305_TP_VALID_HIGH = 1, @@ -70,6 +75,7 @@ struct lgdt3305_config { enum lgdt3305_mpeg_mode mpeg_mode; enum lgdt3305_tp_clock_edge tpclk_edge; + enum lgdt3305_tp_clock_mode tpclk_mode; enum lgdt3305_tp_valid_polarity tpvalid_polarity; enum lgdt_demod_chip_type demod_chip; }; -- cgit v1.2.3 From f1ecc5d119530fce01094307e029ed7f2c9067d8 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 25 Nov 2014 16:26:49 -0300 Subject: [media] si2168: define symbol rate limits w_scan complains about missing symbol rate limits: This dvb driver is *buggy*: the symbol rate limits are undefined - please report to linuxtv.org Chip supports 1 to 7.2 MSymbol/s on DVB-C. Cc: stable@vger.kernel.org Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index d2f1a3e959e7..579820dcb6ca 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -635,6 +635,8 @@ static const struct dvb_frontend_ops si2168_ops = { .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A}, .info = { .name = "Silicon Labs Si2168", + .symbol_rate_min = 1000000, + .symbol_rate_max = 7200000, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -- cgit v1.2.3 From bd01c7666cfebfee1b10e132a4f8df0fc82b9d48 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 25 Nov 2014 16:46:16 -0300 Subject: [media] si2168: rename device state variable from 's' to 'dev' 'dev' is most common name in kernel for structure containing device state instance, so rename it. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 202 +++++++++++++++--------------- drivers/media/dvb-frontends/si2168_priv.h | 2 +- 2 files changed, 102 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 579820dcb6ca..02009f8185b2 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -19,16 +19,16 @@ static const struct dvb_frontend_ops si2168_ops; /* execute firmware command */ -static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) +static int si2168_cmd_execute(struct si2168_dev *dev, struct si2168_cmd *cmd) { int ret; unsigned long timeout; - mutex_lock(&s->i2c_mutex); + mutex_lock(&dev->i2c_mutex); if (cmd->wlen) { /* write cmd and args for firmware */ - ret = i2c_master_send(s->client, cmd->args, cmd->wlen); + ret = i2c_master_send(dev->client, cmd->args, cmd->wlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->wlen) { @@ -42,7 +42,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) #define TIMEOUT 70 timeout = jiffies + msecs_to_jiffies(TIMEOUT); while (!time_after(jiffies, timeout)) { - ret = i2c_master_recv(s->client, cmd->args, cmd->rlen); + ret = i2c_master_recv(dev->client, cmd->args, cmd->rlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->rlen) { @@ -55,7 +55,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) break; } - dev_dbg(&s->client->dev, "cmd execution took %d ms\n", + dev_dbg(&dev->client->dev, "cmd execution took %d ms\n", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); @@ -68,26 +68,26 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) ret = 0; err_mutex_unlock: - mutex_unlock(&s->i2c_mutex); + mutex_unlock(&dev->i2c_mutex); if (ret) goto err; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct si2168 *s = fe->demodulator_priv; + struct si2168_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2168_cmd cmd; *status = 0; - if (!s->active) { + if (!dev->active) { ret = -EAGAIN; goto err; } @@ -113,7 +113,7 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) goto err; } - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -138,7 +138,7 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) break; } - s->fe_status = *status; + dev->fe_status = *status; if (*status & FE_HAS_LOCK) { c->cnr.len = 1; @@ -149,30 +149,30 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - dev_dbg(&s->client->dev, "status=%02x args=%*ph\n", + dev_dbg(&dev->client->dev, "status=%02x args=%*ph\n", *status, cmd.rlen, cmd.args); return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2168_set_frontend(struct dvb_frontend *fe) { - struct si2168 *s = fe->demodulator_priv; + struct si2168_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2168_cmd cmd; u8 bandwidth, delivery_system; - dev_dbg(&s->client->dev, + dev_dbg(&dev->client->dev, "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", c->delivery_system, c->modulation, c->frequency, c->bandwidth_hz, c->symbol_rate, c->inversion, c->stream_id); - if (!s->active) { + if (!dev->active) { ret = -EAGAIN; goto err; } @@ -217,7 +217,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); cmd.wlen = 5; cmd.rlen = 5; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -230,7 +230,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); cmd.wlen = 6; cmd.rlen = 3; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -241,7 +241,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; cmd.wlen = 3; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; } @@ -249,35 +249,35 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x51\x03", 2); cmd.wlen = 2; cmd.rlen = 12; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x12\x08\x04", 3); cmd.wlen = 3; cmd.rlen = 3; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -285,7 +285,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[4] = delivery_system | bandwidth; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -296,7 +296,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; } @@ -304,58 +304,58 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6); - cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10; + cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6); - cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10; + cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x85", 1); cmd.wlen = 1; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; - s->delivery_system = c->delivery_system; + dev->delivery_system = c->delivery_system; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2168_init(struct dvb_frontend *fe) { - struct si2168 *s = fe->demodulator_priv; + struct si2168_dev *dev = fe->demodulator_priv; int ret, len, remaining; const struct firmware *fw = NULL; u8 *fw_file; @@ -363,29 +363,29 @@ static int si2168_init(struct dvb_frontend *fe) struct si2168_cmd cmd; unsigned int chip_id; - dev_dbg(&s->client->dev, "\n"); + dev_dbg(&dev->client->dev, "\n"); /* initialize */ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); cmd.wlen = 13; cmd.rlen = 0; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; - if (s->fw_loaded) { + if (dev->fw_loaded) { /* resume */ memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); cmd.wlen = 8; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; memcpy(cmd.args, "\x85", 1); cmd.wlen = 1; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -396,7 +396,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); cmd.wlen = 8; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -404,7 +404,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x02", 1); cmd.wlen = 1; cmd.rlen = 13; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -426,7 +426,7 @@ static int si2168_init(struct dvb_frontend *fe) fw_file = SI2168_B40_FIRMWARE; break; default: - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); @@ -435,31 +435,31 @@ static int si2168_init(struct dvb_frontend *fe) } /* cold state - try to download firmware */ - dev_info(&s->client->dev, "found a '%s' in cold state\n", + dev_info(&dev->client->dev, "found a '%s' in cold state\n", si2168_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &s->client->dev); + ret = request_firmware(&fw, fw_file, &dev->client->dev); if (ret) { /* fallback mechanism to handle old name for Si2168 B40 fw */ if (chip_id == SI2168_B40) { fw_file = SI2168_B40_FIRMWARE_FALLBACK; - ret = request_firmware(&fw, fw_file, &s->client->dev); + ret = request_firmware(&fw, fw_file, &dev->client->dev); } if (ret == 0) { - dev_notice(&s->client->dev, + dev_notice(&dev->client->dev, "please install firmware file '%s'\n", SI2168_B40_FIRMWARE); } else { - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "firmware file '%s' not found\n", fw_file); goto error_fw_release; } } - dev_info(&s->client->dev, "downloading firmware from file '%s'\n", + dev_info(&dev->client->dev, "downloading firmware from file '%s'\n", fw_file); if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { @@ -469,9 +469,9 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) { - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "firmware download failed=%d\n", ret); goto error_fw_release; @@ -487,9 +487,9 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[fw->size - remaining], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) { - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "firmware download failed=%d\n", ret); goto error_fw_release; @@ -503,7 +503,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; @@ -511,58 +511,58 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x11", 1); cmd.wlen = 1; cmd.rlen = 10; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; - dev_dbg(&s->client->dev, "firmware version: %c.%c.%d\n", + dev_dbg(&dev->client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); /* set ts mode */ memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); - cmd.args[4] |= s->ts_mode; + cmd.args[4] |= dev->ts_mode; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; - s->fw_loaded = true; + dev->fw_loaded = true; - dev_info(&s->client->dev, "found a '%s' in warm state\n", + dev_info(&dev->client->dev, "found a '%s' in warm state\n", si2168_ops.info.name); warm: - s->active = true; + dev->active = true; return 0; error_fw_release: release_firmware(fw); err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2168_sleep(struct dvb_frontend *fe) { - struct si2168 *s = fe->demodulator_priv; + struct si2168_dev *dev = fe->demodulator_priv; int ret; struct si2168_cmd cmd; - dev_dbg(&s->client->dev, "\n"); + dev_dbg(&dev->client->dev, "\n"); - s->active = false; + dev->active = false; memcpy(cmd.args, "\x13", 1); cmd.wlen = 1; cmd.rlen = 0; - ret = si2168_cmd_execute(s, &cmd); + ret = si2168_cmd_execute(dev, &cmd); if (ret) goto err; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } @@ -581,21 +581,21 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe, */ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) { - struct si2168 *s = mux_priv; + struct si2168_dev *dev = mux_priv; int ret; struct i2c_msg gate_open_msg = { - .addr = s->client->addr, + .addr = dev->client->addr, .flags = 0, .len = 3, .buf = "\xc0\x0d\x01", }; - mutex_lock(&s->i2c_mutex); + mutex_lock(&dev->i2c_mutex); /* open tuner I2C gate */ - ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); + ret = __i2c_transfer(dev->client->adapter, &gate_open_msg, 1); if (ret != 1) { - dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); + dev_warn(&dev->client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { @@ -607,26 +607,26 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) { - struct si2168 *s = mux_priv; + struct si2168_dev *dev = mux_priv; int ret; struct i2c_msg gate_close_msg = { - .addr = s->client->addr, + .addr = dev->client->addr, .flags = 0, .len = 3, .buf = "\xc0\x0d\x00", }; /* close tuner I2C gate */ - ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); + ret = __i2c_transfer(dev->client->adapter, &gate_close_msg, 1); if (ret != 1) { - dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); + dev_warn(&dev->client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { ret = 0; } - mutex_unlock(&s->i2c_mutex); + mutex_unlock(&dev->i2c_mutex); return ret; } @@ -672,62 +672,62 @@ static int si2168_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si2168_config *config = client->dev.platform_data; - struct si2168 *s; + struct si2168_dev *dev; int ret; dev_dbg(&client->dev, "\n"); - s = kzalloc(sizeof(struct si2168), GFP_KERNEL); - if (!s) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { ret = -ENOMEM; dev_err(&client->dev, "kzalloc() failed\n"); goto err; } - s->client = client; - mutex_init(&s->i2c_mutex); + dev->client = client; + mutex_init(&dev->i2c_mutex); /* create mux i2c adapter for tuner */ - s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s, + dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, dev, 0, 0, 0, si2168_select, si2168_deselect); - if (s->adapter == NULL) { + if (dev->adapter == NULL) { ret = -ENODEV; goto err; } /* create dvb_frontend */ - memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); - s->fe.demodulator_priv = s; + memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); + dev->fe.demodulator_priv = dev; - *config->i2c_adapter = s->adapter; - *config->fe = &s->fe; - s->ts_mode = config->ts_mode; - s->ts_clock_inv = config->ts_clock_inv; - s->fw_loaded = false; + *config->i2c_adapter = dev->adapter; + *config->fe = &dev->fe; + dev->ts_mode = config->ts_mode; + dev->ts_clock_inv = config->ts_clock_inv; + dev->fw_loaded = false; - i2c_set_clientdata(client, s); + i2c_set_clientdata(client, dev); - dev_info(&s->client->dev, + dev_info(&dev->client->dev, "Silicon Labs Si2168 successfully attached\n"); return 0; err: - kfree(s); + kfree(dev); dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int si2168_remove(struct i2c_client *client) { - struct si2168 *s = i2c_get_clientdata(client); + struct si2168_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - i2c_del_mux_adapter(s->adapter); + i2c_del_mux_adapter(dev->adapter); - s->fe.ops.release = NULL; - s->fe.demodulator_priv = NULL; + dev->fe.ops.release = NULL; + dev->fe.demodulator_priv = NULL; - kfree(s); + kfree(dev); return 0; } diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index 60bc3349b6c3..cb8827af2a98 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -28,7 +28,7 @@ #define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw" /* state struct */ -struct si2168 { +struct si2168_dev { struct i2c_client *client; struct i2c_adapter *adapter; struct mutex i2c_mutex; -- cgit v1.2.3 From 6307b560800fd92b915a851186653317460039ad Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 25 Nov 2014 17:31:43 -0300 Subject: [media] si2168: carry pointer to client instead of state Carry struct i2c_client pointer inside struct dvb_frontend private pointer. This driver is I2C driver, which is represented as a struct i2c_client, so better to carry this top level structure for each routine in order to unify things. This allows further simplification. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 83 +++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 02009f8185b2..d0dfc73eb1f4 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -19,8 +19,9 @@ static const struct dvb_frontend_ops si2168_ops; /* execute firmware command */ -static int si2168_cmd_execute(struct si2168_dev *dev, struct si2168_cmd *cmd) +static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) { + struct si2168_dev *dev = i2c_get_clientdata(client); int ret; unsigned long timeout; @@ -80,7 +81,8 @@ err: static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct si2168_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2168_cmd cmd; @@ -113,7 +115,7 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) goto err; } - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -160,7 +162,8 @@ err: static int si2168_set_frontend(struct dvb_frontend *fe) { - struct si2168_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2168_cmd cmd; @@ -217,7 +220,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); cmd.wlen = 5; cmd.rlen = 5; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -230,7 +233,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); cmd.wlen = 6; cmd.rlen = 3; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -241,7 +244,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; cmd.wlen = 3; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; } @@ -249,35 +252,35 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x51\x03", 2); cmd.wlen = 2; cmd.rlen = 12; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x12\x08\x04", 3); cmd.wlen = 3; cmd.rlen = 3; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -285,7 +288,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[4] = delivery_system | bandwidth; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -296,7 +299,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; } @@ -304,7 +307,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -312,7 +315,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -320,28 +323,28 @@ static int si2168_set_frontend(struct dvb_frontend *fe) cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x85", 1); cmd.wlen = 1; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -355,7 +358,8 @@ err: static int si2168_init(struct dvb_frontend *fe) { - struct si2168_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; const struct firmware *fw = NULL; u8 *fw_file; @@ -369,7 +373,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); cmd.wlen = 13; cmd.rlen = 0; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -378,14 +382,14 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); cmd.wlen = 8; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; memcpy(cmd.args, "\x85", 1); cmd.wlen = 1; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -396,7 +400,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); cmd.wlen = 8; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -404,7 +408,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x02", 1); cmd.wlen = 1; cmd.rlen = 13; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -469,7 +473,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) { dev_err(&dev->client->dev, "firmware download failed=%d\n", @@ -487,7 +491,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[fw->size - remaining], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) { dev_err(&dev->client->dev, "firmware download failed=%d\n", @@ -503,7 +507,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -511,7 +515,7 @@ static int si2168_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x11", 1); cmd.wlen = 1; cmd.rlen = 10; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -523,7 +527,7 @@ static int si2168_init(struct dvb_frontend *fe) cmd.args[4] |= dev->ts_mode; cmd.wlen = 6; cmd.rlen = 4; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -545,7 +549,8 @@ err: static int si2168_sleep(struct dvb_frontend *fe) { - struct si2168_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); int ret; struct si2168_cmd cmd; @@ -556,7 +561,7 @@ static int si2168_sleep(struct dvb_frontend *fe) memcpy(cmd.args, "\x13", 1); cmd.wlen = 1; cmd.rlen = 0; - ret = si2168_cmd_execute(dev, &cmd); + ret = si2168_cmd_execute(client, &cmd); if (ret) goto err; @@ -581,7 +586,8 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe, */ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) { - struct si2168_dev *dev = mux_priv; + struct i2c_client *client = mux_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg gate_open_msg = { .addr = dev->client->addr, @@ -607,7 +613,8 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) { - struct si2168_dev *dev = mux_priv; + struct i2c_client *client = mux_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg gate_close_msg = { .addr = dev->client->addr, @@ -688,8 +695,8 @@ static int si2168_probe(struct i2c_client *client, mutex_init(&dev->i2c_mutex); /* create mux i2c adapter for tuner */ - dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, dev, - 0, 0, 0, si2168_select, si2168_deselect); + dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, + client, 0, 0, 0, si2168_select, si2168_deselect); if (dev->adapter == NULL) { ret = -ENODEV; goto err; @@ -697,7 +704,7 @@ static int si2168_probe(struct i2c_client *client, /* create dvb_frontend */ memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); - dev->fe.demodulator_priv = dev; + dev->fe.demodulator_priv = client; *config->i2c_adapter = dev->adapter; *config->fe = &dev->fe; -- cgit v1.2.3 From 3de3583539390a6e0d5b780f0c16980462991f7c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 25 Nov 2014 17:53:21 -0300 Subject: [media] si2168: get rid of own struct i2c_client pointer We don't need that anymore as same pointer is passed to each routine via struct dvb_frontend private field. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 61 +++++++++++++++---------------- drivers/media/dvb-frontends/si2168_priv.h | 1 - 2 files changed, 30 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index d0dfc73eb1f4..e00bc0467356 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -29,7 +29,7 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) if (cmd->wlen) { /* write cmd and args for firmware */ - ret = i2c_master_send(dev->client, cmd->args, cmd->wlen); + ret = i2c_master_send(client, cmd->args, cmd->wlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->wlen) { @@ -43,7 +43,7 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) #define TIMEOUT 70 timeout = jiffies + msecs_to_jiffies(TIMEOUT); while (!time_after(jiffies, timeout)) { - ret = i2c_master_recv(dev->client, cmd->args, cmd->rlen); + ret = i2c_master_recv(client, cmd->args, cmd->rlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->rlen) { @@ -56,7 +56,7 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) break; } - dev_dbg(&dev->client->dev, "cmd execution took %d ms\n", + dev_dbg(&client->dev, "cmd execution took %d ms\n", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); @@ -75,7 +75,7 @@ err_mutex_unlock: return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -151,12 +151,12 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - dev_dbg(&dev->client->dev, "status=%02x args=%*ph\n", + dev_dbg(&client->dev, "status=%02x args=%*ph\n", *status, cmd.rlen, cmd.args); return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -169,7 +169,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) struct si2168_cmd cmd; u8 bandwidth, delivery_system; - dev_dbg(&dev->client->dev, + dev_dbg(&client->dev, "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", c->delivery_system, c->modulation, c->frequency, c->bandwidth_hz, c->symbol_rate, @@ -352,7 +352,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -367,7 +367,7 @@ static int si2168_init(struct dvb_frontend *fe) struct si2168_cmd cmd; unsigned int chip_id; - dev_dbg(&dev->client->dev, "\n"); + dev_dbg(&client->dev, "\n"); /* initialize */ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); @@ -430,7 +430,7 @@ static int si2168_init(struct dvb_frontend *fe) fw_file = SI2168_B40_FIRMWARE; break; default: - dev_err(&dev->client->dev, + dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); @@ -439,31 +439,31 @@ static int si2168_init(struct dvb_frontend *fe) } /* cold state - try to download firmware */ - dev_info(&dev->client->dev, "found a '%s' in cold state\n", + dev_info(&client->dev, "found a '%s' in cold state\n", si2168_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &dev->client->dev); + ret = request_firmware(&fw, fw_file, &client->dev); if (ret) { /* fallback mechanism to handle old name for Si2168 B40 fw */ if (chip_id == SI2168_B40) { fw_file = SI2168_B40_FIRMWARE_FALLBACK; - ret = request_firmware(&fw, fw_file, &dev->client->dev); + ret = request_firmware(&fw, fw_file, &client->dev); } if (ret == 0) { - dev_notice(&dev->client->dev, + dev_notice(&client->dev, "please install firmware file '%s'\n", SI2168_B40_FIRMWARE); } else { - dev_err(&dev->client->dev, + dev_err(&client->dev, "firmware file '%s' not found\n", fw_file); goto error_fw_release; } } - dev_info(&dev->client->dev, "downloading firmware from file '%s'\n", + dev_info(&client->dev, "downloading firmware from file '%s'\n", fw_file); if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { @@ -475,7 +475,7 @@ static int si2168_init(struct dvb_frontend *fe) cmd.rlen = 1; ret = si2168_cmd_execute(client, &cmd); if (ret) { - dev_err(&dev->client->dev, + dev_err(&client->dev, "firmware download failed=%d\n", ret); goto error_fw_release; @@ -493,7 +493,7 @@ static int si2168_init(struct dvb_frontend *fe) cmd.rlen = 1; ret = si2168_cmd_execute(client, &cmd); if (ret) { - dev_err(&dev->client->dev, + dev_err(&client->dev, "firmware download failed=%d\n", ret); goto error_fw_release; @@ -519,7 +519,7 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - dev_dbg(&dev->client->dev, "firmware version: %c.%c.%d\n", + dev_dbg(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); /* set ts mode */ @@ -533,7 +533,7 @@ static int si2168_init(struct dvb_frontend *fe) dev->fw_loaded = true; - dev_info(&dev->client->dev, "found a '%s' in warm state\n", + dev_info(&client->dev, "found a '%s' in warm state\n", si2168_ops.info.name); warm: dev->active = true; @@ -543,7 +543,7 @@ warm: error_fw_release: release_firmware(fw); err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -554,7 +554,7 @@ static int si2168_sleep(struct dvb_frontend *fe) int ret; struct si2168_cmd cmd; - dev_dbg(&dev->client->dev, "\n"); + dev_dbg(&client->dev, "\n"); dev->active = false; @@ -567,7 +567,7 @@ static int si2168_sleep(struct dvb_frontend *fe) return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -590,7 +590,7 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) struct si2168_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg gate_open_msg = { - .addr = dev->client->addr, + .addr = client->addr, .flags = 0, .len = 3, .buf = "\xc0\x0d\x01", @@ -599,9 +599,9 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) mutex_lock(&dev->i2c_mutex); /* open tuner I2C gate */ - ret = __i2c_transfer(dev->client->adapter, &gate_open_msg, 1); + ret = __i2c_transfer(client->adapter, &gate_open_msg, 1); if (ret != 1) { - dev_warn(&dev->client->dev, "i2c write failed=%d\n", ret); + dev_warn(&client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { @@ -617,16 +617,16 @@ static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) struct si2168_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg gate_close_msg = { - .addr = dev->client->addr, + .addr = client->addr, .flags = 0, .len = 3, .buf = "\xc0\x0d\x00", }; /* close tuner I2C gate */ - ret = __i2c_transfer(dev->client->adapter, &gate_close_msg, 1); + ret = __i2c_transfer(client->adapter, &gate_close_msg, 1); if (ret != 1) { - dev_warn(&dev->client->dev, "i2c write failed=%d\n", ret); + dev_warn(&client->dev, "i2c write failed=%d\n", ret); if (ret >= 0) ret = -EREMOTEIO; } else { @@ -691,7 +691,6 @@ static int si2168_probe(struct i2c_client *client, goto err; } - dev->client = client; mutex_init(&dev->i2c_mutex); /* create mux i2c adapter for tuner */ @@ -714,7 +713,7 @@ static int si2168_probe(struct i2c_client *client, i2c_set_clientdata(client, dev); - dev_info(&dev->client->dev, + dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n"); return 0; err: diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index cb8827af2a98..aadd1367673f 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -29,7 +29,6 @@ /* state struct */ struct si2168_dev { - struct i2c_client *client; struct i2c_adapter *adapter; struct mutex i2c_mutex; struct dvb_frontend fe; -- cgit v1.2.3 From 4affbe1d0825dc3c9c5fcec8a4848d8bbdd718cb Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 14:30:44 -0300 Subject: [media] si2168: simplify si2168_cmd_execute() error path Remove if () from firmware command error path as there should not be any error prone conditional logic there. Use goto labels instead. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index e00bc0467356..3c102e519312 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -66,15 +66,11 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) } } - ret = 0; + mutex_unlock(&dev->i2c_mutex); + return 0; err_mutex_unlock: mutex_unlock(&dev->i2c_mutex); - if (ret) - goto err; - - return 0; -err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } -- cgit v1.2.3 From 346d4900f000eb938f918c1cb5b9c9d21013b175 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 14:54:14 -0300 Subject: [media] si2168: rename few things Rename some goto labels and more. No functionality changes. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 38 ++++++++++++------------------------ drivers/media/dvb-frontends/si2168.h | 6 ++---- 2 files changed, 14 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 3c102e519312..b23ae3a03a83 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -115,17 +115,6 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) if (ret) goto err; - /* - * Possible values seen, in order from strong signal to weak: - * 16 0001 0110 full lock - * 1e 0001 1110 partial lock - * 1a 0001 1010 partial lock - * 18 0001 1000 no lock - * - * [b3:b1] lock bits - * [b4] statistics ready? Set in a few secs after lock is gained. - */ - switch ((cmd.args[2] >> 1) & 0x03) { case 0x01: *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; @@ -291,7 +280,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) /* set DVB-C symbol rate */ if (c->delivery_system == SYS_DVBC_ANNEX_A) { memcpy(cmd.args, "\x14\x00\x02\x11", 4); - cmd.args[4] = (c->symbol_rate / 1000) & 0xff; + cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff; cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff; cmd.wlen = 6; cmd.rlen = 4; @@ -455,7 +444,7 @@ static int si2168_init(struct dvb_frontend *fe) dev_err(&client->dev, "firmware file '%s' not found\n", fw_file); - goto error_fw_release; + goto err_release_firmware; } } @@ -474,7 +463,7 @@ static int si2168_init(struct dvb_frontend *fe) dev_err(&client->dev, "firmware download failed=%d\n", ret); - goto error_fw_release; + goto err_release_firmware; } } } else { @@ -492,7 +481,7 @@ static int si2168_init(struct dvb_frontend *fe) dev_err(&client->dev, "firmware download failed=%d\n", ret); - goto error_fw_release; + goto err_release_firmware; } } } @@ -535,8 +524,7 @@ warm: dev->active = true; return 0; - -error_fw_release: +err_release_firmware: release_firmware(fw); err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -684,7 +672,7 @@ static int si2168_probe(struct i2c_client *client, if (!dev) { ret = -ENOMEM; dev_err(&client->dev, "kzalloc() failed\n"); - goto err; + goto err_kfree; } mutex_init(&dev->i2c_mutex); @@ -694,13 +682,12 @@ static int si2168_probe(struct i2c_client *client, client, 0, 0, 0, si2168_select, si2168_deselect); if (dev->adapter == NULL) { ret = -ENODEV; - goto err; + goto err_kfree; } /* create dvb_frontend */ memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); dev->fe.demodulator_priv = client; - *config->i2c_adapter = dev->adapter; *config->fe = &dev->fe; dev->ts_mode = config->ts_mode; @@ -709,10 +696,9 @@ static int si2168_probe(struct i2c_client *client, i2c_set_clientdata(client, dev); - dev_info(&client->dev, - "Silicon Labs Si2168 successfully attached\n"); + dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n"); return 0; -err: +err_kfree: kfree(dev); dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -734,11 +720,11 @@ static int si2168_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si2168_id[] = { +static const struct i2c_device_id si2168_id_table[] = { {"si2168", 0}, {} }; -MODULE_DEVICE_TABLE(i2c, si2168_id); +MODULE_DEVICE_TABLE(i2c, si2168_id_table); static struct i2c_driver si2168_driver = { .driver = { @@ -747,7 +733,7 @@ static struct i2c_driver si2168_driver = { }, .probe = si2168_probe, .remove = si2168_remove, - .id_table = si2168_id, + .id_table = si2168_id_table, }; module_i2c_driver(si2168_driver); diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h index 87bc12146667..70d702ae6f49 100644 --- a/drivers/media/dvb-frontends/si2168.h +++ b/drivers/media/dvb-frontends/si2168.h @@ -36,14 +36,12 @@ struct si2168_config { struct i2c_adapter **i2c_adapter; /* TS mode */ +#define SI2168_TS_PARALLEL 0x06 +#define SI2168_TS_SERIAL 0x03 u8 ts_mode; /* TS clock inverted */ bool ts_clock_inv; - }; -#define SI2168_TS_PARALLEL 0x06 -#define SI2168_TS_SERIAL 0x03 - #endif -- cgit v1.2.3 From 955e0ab8ce4cf5466e1c936f85d9ff28d316ee58 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 15:04:12 -0300 Subject: [media] si2168: change firmware version print from debug to info Even firmware version is not needed to know, it is still interesting and useful to know some cases. Due to that increase its printing to info log level. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index b23ae3a03a83..f953178b6bfc 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -504,7 +504,7 @@ static int si2168_init(struct dvb_frontend *fe) if (ret) goto err; - dev_dbg(&client->dev, "firmware version: %c.%c.%d\n", + dev_info(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); /* set ts mode */ -- cgit v1.2.3 From e5dd1100c7d3493a8a3c6ac79468978009204104 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 15:57:03 -0300 Subject: [media] si2168: change stream id debug log formatter Change formatter from signed to unsigned as stream_id is 32bit unsigned variable. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index f953178b6bfc..f3fabd5fe455 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -155,10 +155,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) u8 bandwidth, delivery_system; dev_dbg(&client->dev, - "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", - c->delivery_system, c->modulation, - c->frequency, c->bandwidth_hz, c->symbol_rate, - c->inversion, c->stream_id); + "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%u\n", + c->delivery_system, c->modulation, c->frequency, + c->bandwidth_hz, c->symbol_rate, c->inversion, + c->stream_id); if (!dev->active) { ret = -EAGAIN; -- cgit v1.2.3 From 1ee5e7dd5eced2ec13d3810c55b4ecd73cb5c92f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 16:02:42 -0300 Subject: [media] si2168: add own goto label for kzalloc failure Use own label for kzalloc failure in which does not call kfree(). kfree() could be called with NULL, but it is still better to have own label which skips unnecessary kfree(). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index f3fabd5fe455..06e54d10cc4f 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -672,7 +672,7 @@ static int si2168_probe(struct i2c_client *client, if (!dev) { ret = -ENOMEM; dev_err(&client->dev, "kzalloc() failed\n"); - goto err_kfree; + goto err; } mutex_init(&dev->i2c_mutex); @@ -700,6 +700,7 @@ static int si2168_probe(struct i2c_client *client, return 0; err_kfree: kfree(dev); +err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } -- cgit v1.2.3 From 68c16a76c64e2cd9c0dd4bda6400a3f28e82488e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 17:08:22 -0300 Subject: [media] si2168: enhance firmware download routine All known old firmware firmware formats are downloaded using 8 byte chunks. Reject firmware if it could not be divided to 8 byte chunks and because of that we could simplify some calculations. Now both supported firmware download routines are rather similar. Cc: Olli Salonen Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 06e54d10cc4f..66b9c9ca28f4 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -348,7 +348,6 @@ static int si2168_init(struct dvb_frontend *fe) int ret, len, remaining; const struct firmware *fw = NULL; u8 *fw_file; - const unsigned int i2c_wr_max = 8; struct si2168_cmd cmd; unsigned int chip_id; @@ -459,31 +458,28 @@ static int si2168_init(struct dvb_frontend *fe) cmd.wlen = len; cmd.rlen = 1; ret = si2168_cmd_execute(client, &cmd); - if (ret) { - dev_err(&client->dev, - "firmware download failed=%d\n", - ret); - goto err_release_firmware; - } + if (ret) + break; } - } else { + } else if (fw->size % 8 == 0) { /* firmware is in the old format */ - for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { - len = remaining; - if (len > i2c_wr_max) - len = i2c_wr_max; - + for (remaining = fw->size; remaining > 0; remaining -= 8) { + len = 8; memcpy(cmd.args, &fw->data[fw->size - remaining], len); cmd.wlen = len; cmd.rlen = 1; ret = si2168_cmd_execute(client, &cmd); - if (ret) { - dev_err(&client->dev, - "firmware download failed=%d\n", - ret); - goto err_release_firmware; - } + if (ret) + break; } + } else { + /* bad or unknown firmware format */ + ret = -EINVAL; + } + + if (ret) { + dev_err(&client->dev, "firmware download failed %d\n", ret); + goto err_release_firmware; } release_firmware(fw); -- cgit v1.2.3 From 58f6693fa1bfe97a40e3ba5e2271893b1074f161 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 17:22:42 -0300 Subject: [media] si2168: remove unneeded fw variable initialization commit 034e1ec0ce299b9e90056793dcb3187e7add6b62 si2168: One function call less in si2168_init() after error detection That commit added goto label for error path to release firmware, but forgets to remove variable NULL set. Remove those now. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 66b9c9ca28f4..766362ed6b52 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -346,7 +346,7 @@ static int si2168_init(struct dvb_frontend *fe) struct i2c_client *client = fe->demodulator_priv; struct si2168_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; - const struct firmware *fw = NULL; + const struct firmware *fw; u8 *fw_file; struct si2168_cmd cmd; unsigned int chip_id; @@ -483,7 +483,6 @@ static int si2168_init(struct dvb_frontend *fe) } release_firmware(fw); - fw = NULL; memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; -- cgit v1.2.3 From 9b7839c3061cfc4f9087c2ad67d56e844d087c55 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 17:43:27 -0300 Subject: [media] si2168: print chip version Print chip version once using log level into when init() is called. Remove cold/warm state printing as those are not very useful. old printing: si2168 6-0064: found a 'Silicon Labs Si2168' in cold state si2168 6-0064: downloading firmware from file 'dvb-demod-si2168-b40-01.fw' si2168 6-0064: firmware version: 4.0.11 si2168 6-0064: found a 'Silicon Labs Si2168' in warm state new printing: si2168 6-0064: found a 'Silicon Labs Si2168-B40' si2168 6-0064: downloading firmware from file 'dvb-demod-si2168-b40-01.fw' si2168 6-0064: firmware version: 4.0.11 Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 766362ed6b52..25fe63a2fb1f 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -414,17 +414,15 @@ static int si2168_init(struct dvb_frontend *fe) fw_file = SI2168_B40_FIRMWARE; break; default: - dev_err(&client->dev, - "unknown chip version Si21%d-%c%c%c\n", + dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); ret = -EINVAL; goto err; } - /* cold state - try to download firmware */ - dev_info(&client->dev, "found a '%s' in cold state\n", - si2168_ops.info.name); + dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", + cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, &client->dev); @@ -512,13 +510,11 @@ static int si2168_init(struct dvb_frontend *fe) goto err; dev->fw_loaded = true; - - dev_info(&client->dev, "found a '%s' in warm state\n", - si2168_ops.info.name); warm: dev->active = true; return 0; + err_release_firmware: release_firmware(fw); err: -- cgit v1.2.3 From c32b281628bec1a02b7847e9e14e0b9556a17f74 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 17:53:16 -0300 Subject: [media] si2168: change firmware variable name and type Rename firmware variable from fw_file to fw_name and change its type from u8 to const char as request_firmware() input defines. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 25fe63a2fb1f..63341f485f9f 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -347,7 +347,7 @@ static int si2168_init(struct dvb_frontend *fe) struct si2168_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; const struct firmware *fw; - u8 *fw_file; + const char *fw_name; struct si2168_cmd cmd; unsigned int chip_id; @@ -405,13 +405,13 @@ static int si2168_init(struct dvb_frontend *fe) switch (chip_id) { case SI2168_A20: - fw_file = SI2168_A20_FIRMWARE; + fw_name = SI2168_A20_FIRMWARE; break; case SI2168_A30: - fw_file = SI2168_A30_FIRMWARE; + fw_name = SI2168_A30_FIRMWARE; break; case SI2168_B40: - fw_file = SI2168_B40_FIRMWARE; + fw_name = SI2168_B40_FIRMWARE; break; default: dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", @@ -425,12 +425,12 @@ static int si2168_init(struct dvb_frontend *fe) cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &client->dev); + ret = request_firmware(&fw, fw_name, &client->dev); if (ret) { /* fallback mechanism to handle old name for Si2168 B40 fw */ if (chip_id == SI2168_B40) { - fw_file = SI2168_B40_FIRMWARE_FALLBACK; - ret = request_firmware(&fw, fw_file, &client->dev); + fw_name = SI2168_B40_FIRMWARE_FALLBACK; + ret = request_firmware(&fw, fw_name, &client->dev); } if (ret == 0) { @@ -440,13 +440,13 @@ static int si2168_init(struct dvb_frontend *fe) } else { dev_err(&client->dev, "firmware file '%s' not found\n", - fw_file); + fw_name); goto err_release_firmware; } } dev_info(&client->dev, "downloading firmware from file '%s'\n", - fw_file); + fw_name); if ((fw->size % 17 == 0) && (fw->data[0] > 5)) { /* firmware is in the new format */ -- cgit v1.2.3 From 70f13ff091a92a29d8463661a494fafaaff65395 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 5 Dec 2014 17:46:30 -0300 Subject: [media] si2157: rename device state variable from 's' to 'dev' 'dev' is likely most common name in kernel for structure containing device state instance, so rename it in order to keep things consistent. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 118 ++++++++++++++++++------------------- drivers/media/tuners/si2157_priv.h | 2 +- 2 files changed, 59 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 2180de9d654a..14d2f7363149 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -19,16 +19,16 @@ static const struct dvb_tuner_ops si2157_ops; /* execute firmware command */ -static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) +static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) { int ret; unsigned long timeout; - mutex_lock(&s->i2c_mutex); + mutex_lock(&dev->i2c_mutex); if (cmd->wlen) { /* write cmd and args for firmware */ - ret = i2c_master_send(s->client, cmd->args, cmd->wlen); + ret = i2c_master_send(dev->client, cmd->args, cmd->wlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->wlen) { @@ -42,7 +42,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) #define TIMEOUT 80 timeout = jiffies + msecs_to_jiffies(TIMEOUT); while (!time_after(jiffies, timeout)) { - ret = i2c_master_recv(s->client, cmd->args, cmd->rlen); + ret = i2c_master_recv(dev->client, cmd->args, cmd->rlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->rlen) { @@ -55,7 +55,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) break; } - dev_dbg(&s->client->dev, "cmd execution took %d ms\n", + dev_dbg(&dev->client->dev, "cmd execution took %d ms\n", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); @@ -68,32 +68,32 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) ret = 0; err_mutex_unlock: - mutex_unlock(&s->i2c_mutex); + mutex_unlock(&dev->i2c_mutex); if (ret) goto err; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2157_init(struct dvb_frontend *fe) { - struct si2157 *s = fe->tuner_priv; + struct si2157_dev *dev = fe->tuner_priv; int ret, len, remaining; struct si2157_cmd cmd; const struct firmware *fw = NULL; u8 *fw_file; unsigned int chip_id; - dev_dbg(&s->client->dev, "\n"); + dev_dbg(&dev->client->dev, "\n"); - if (s->fw_loaded) + if (dev->fw_loaded) goto warm; /* power up */ - if (s->chiptype == SI2157_CHIPTYPE_SI2146) { + if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); cmd.wlen = 9; } else { @@ -101,7 +101,7 @@ static int si2157_init(struct dvb_frontend *fe) cmd.wlen = 15; } cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; @@ -109,7 +109,7 @@ static int si2157_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x02", 1); cmd.wlen = 1; cmd.rlen = 13; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; @@ -132,7 +132,7 @@ static int si2157_init(struct dvb_frontend *fe) case SI2146_A10: goto skip_fw_download; default: - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); @@ -141,26 +141,26 @@ static int si2157_init(struct dvb_frontend *fe) } /* cold state - try to download firmware */ - dev_info(&s->client->dev, "found a '%s' in cold state\n", + dev_info(&dev->client->dev, "found a '%s' in cold state\n", si2157_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &s->client->dev); + ret = request_firmware(&fw, fw_file, &dev->client->dev); if (ret) { - dev_err(&s->client->dev, "firmware file '%s' not found\n", + dev_err(&dev->client->dev, "firmware file '%s' not found\n", fw_file); goto err; } /* firmware should be n chunks of 17 bytes */ if (fw->size % 17 != 0) { - dev_err(&s->client->dev, "firmware file '%s' is invalid\n", + dev_err(&dev->client->dev, "firmware file '%s' is invalid\n", fw_file); ret = -EINVAL; goto fw_release_exit; } - dev_info(&s->client->dev, "downloading firmware from file '%s'\n", + dev_info(&dev->client->dev, "downloading firmware from file '%s'\n", fw_file); for (remaining = fw->size; remaining > 0; remaining -= 17) { @@ -168,9 +168,9 @@ static int si2157_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) { - dev_err(&s->client->dev, + dev_err(&dev->client->dev, "firmware download failed=%d\n", ret); goto fw_release_exit; @@ -185,61 +185,61 @@ skip_fw_download: memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; - s->fw_loaded = true; + dev->fw_loaded = true; warm: - s->active = true; + dev->active = true; return 0; fw_release_exit: release_firmware(fw); err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2157_sleep(struct dvb_frontend *fe) { - struct si2157 *s = fe->tuner_priv; + struct si2157_dev *dev = fe->tuner_priv; int ret; struct si2157_cmd cmd; - dev_dbg(&s->client->dev, "\n"); + dev_dbg(&dev->client->dev, "\n"); - s->active = false; + dev->active = false; /* standby */ memcpy(cmd.args, "\x16\x00", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } static int si2157_set_params(struct dvb_frontend *fe) { - struct si2157 *s = fe->tuner_priv; + struct si2157_dev *dev = fe->tuner_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2157_cmd cmd; u8 bandwidth, delivery_system; - dev_dbg(&s->client->dev, + dev_dbg(&dev->client->dev, "delivery_system=%d frequency=%u bandwidth_hz=%u\n", c->delivery_system, c->frequency, c->bandwidth_hz); - if (!s->active) { + if (!dev->active) { ret = -EAGAIN; goto err; } @@ -274,21 +274,21 @@ static int si2157_set_params(struct dvb_frontend *fe) memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6); cmd.args[4] = delivery_system | bandwidth; - if (s->inversion) + if (dev->inversion) cmd.args[5] = 0x01; cmd.wlen = 6; cmd.rlen = 4; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; - if (s->chiptype == SI2157_CHIPTYPE_SI2146) + if (dev->chiptype == SI2157_CHIPTYPE_SI2146) memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6); else memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; @@ -300,13 +300,13 @@ static int si2157_set_params(struct dvb_frontend *fe) cmd.args[7] = (c->frequency >> 24) & 0xff; cmd.wlen = 8; cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; return 0; err: - dev_dbg(&s->client->dev, "failed=%d\n", ret); + dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } @@ -334,60 +334,58 @@ static int si2157_probe(struct i2c_client *client, { struct si2157_config *cfg = client->dev.platform_data; struct dvb_frontend *fe = cfg->fe; - struct si2157 *s; + struct si2157_dev *dev; struct si2157_cmd cmd; int ret; - s = kzalloc(sizeof(struct si2157), GFP_KERNEL); - if (!s) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { ret = -ENOMEM; dev_err(&client->dev, "kzalloc() failed\n"); goto err; } - s->client = client; - s->fe = cfg->fe; - s->inversion = cfg->inversion; - s->fw_loaded = false; - s->chiptype = (u8)id->driver_data; - mutex_init(&s->i2c_mutex); + dev->client = client; + dev->fe = cfg->fe; + dev->inversion = cfg->inversion; + dev->fw_loaded = false; + dev->chiptype = (u8)id->driver_data; + mutex_init(&dev->i2c_mutex); /* check if the tuner is there */ cmd.wlen = 0; cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); + ret = si2157_cmd_execute(dev, &cmd); if (ret) goto err; - fe->tuner_priv = s; - memcpy(&fe->ops.tuner_ops, &si2157_ops, - sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = dev; + memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); - i2c_set_clientdata(client, s); + i2c_set_clientdata(client, dev); - dev_info(&s->client->dev, + dev_info(&dev->client->dev, "Silicon Labs %s successfully attached\n", - s->chiptype == SI2157_CHIPTYPE_SI2146 ? + dev->chiptype == SI2157_CHIPTYPE_SI2146 ? "Si2146" : "Si2147/2148/2157/2158"); return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); - kfree(s); - + kfree(dev); return ret; } static int si2157_remove(struct i2c_client *client) { - struct si2157 *s = i2c_get_clientdata(client); - struct dvb_frontend *fe = s->fe; + struct si2157_dev *dev = i2c_get_clientdata(client); + struct dvb_frontend *fe = dev->fe; dev_dbg(&client->dev, "\n"); memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = NULL; - kfree(s); + kfree(dev); return 0; } diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index d6e07cdd2a07..8f6cfc00ddac 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -21,7 +21,7 @@ #include "si2157.h" /* state struct */ -struct si2157 { +struct si2157_dev { struct mutex i2c_mutex; struct i2c_client *client; struct dvb_frontend *fe; -- cgit v1.2.3 From 7cbf5d7651ca7ab91b57d194f388d8886dbe4c38 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 14:04:05 -0300 Subject: [media] si2157: simplify si2157_cmd_execute() error path Remove if () from firmware command error path as there should not be any error prone conditional logic there. Use goto labels instead. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 14d2f7363149..f7c38678f805 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -65,15 +65,11 @@ static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) } } - ret = 0; + mutex_unlock(&dev->i2c_mutex); + return 0; err_mutex_unlock: mutex_unlock(&dev->i2c_mutex); - if (ret) - goto err; - - return 0; -err: dev_dbg(&dev->client->dev, "failed=%d\n", ret); return ret; } -- cgit v1.2.3 From 8fe51725d8e7794443799566edc4bfd384bf8825 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 14:40:06 -0300 Subject: [media] si2157: carry pointer to client instead of state in tuner_priv Carry struct i2c_client pointer in tuner_priv. This driver is I2C driver, which is represented as a struct i2c_client, so better to carry this top level structure for each routine in order to unify things. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 78 +++++++++++++++++++------------------- drivers/media/tuners/si2157_priv.h | 1 - 2 files changed, 38 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index f7c38678f805..88afb2adfdd1 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -19,8 +19,9 @@ static const struct dvb_tuner_ops si2157_ops; /* execute firmware command */ -static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) +static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) { + struct si2157_dev *dev = i2c_get_clientdata(client); int ret; unsigned long timeout; @@ -28,7 +29,7 @@ static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) if (cmd->wlen) { /* write cmd and args for firmware */ - ret = i2c_master_send(dev->client, cmd->args, cmd->wlen); + ret = i2c_master_send(client, cmd->args, cmd->wlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->wlen) { @@ -42,7 +43,7 @@ static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) #define TIMEOUT 80 timeout = jiffies + msecs_to_jiffies(TIMEOUT); while (!time_after(jiffies, timeout)) { - ret = i2c_master_recv(dev->client, cmd->args, cmd->rlen); + ret = i2c_master_recv(client, cmd->args, cmd->rlen); if (ret < 0) { goto err_mutex_unlock; } else if (ret != cmd->rlen) { @@ -55,7 +56,7 @@ static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) break; } - dev_dbg(&dev->client->dev, "cmd execution took %d ms\n", + dev_dbg(&client->dev, "cmd execution took %d ms\n", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - TIMEOUT)); @@ -70,20 +71,21 @@ static int si2157_cmd_execute(struct si2157_dev *dev, struct si2157_cmd *cmd) err_mutex_unlock: mutex_unlock(&dev->i2c_mutex); - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int si2157_init(struct dvb_frontend *fe) { - struct si2157_dev *dev = fe->tuner_priv; + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; struct si2157_cmd cmd; const struct firmware *fw = NULL; u8 *fw_file; unsigned int chip_id; - dev_dbg(&dev->client->dev, "\n"); + dev_dbg(&client->dev, "\n"); if (dev->fw_loaded) goto warm; @@ -97,7 +99,7 @@ static int si2157_init(struct dvb_frontend *fe) cmd.wlen = 15; } cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; @@ -105,7 +107,7 @@ static int si2157_init(struct dvb_frontend *fe) memcpy(cmd.args, "\x02", 1); cmd.wlen = 1; cmd.rlen = 13; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; @@ -128,8 +130,7 @@ static int si2157_init(struct dvb_frontend *fe) case SI2146_A10: goto skip_fw_download; default: - dev_err(&dev->client->dev, - "unknown chip version Si21%d-%c%c%c\n", + dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); ret = -EINVAL; @@ -137,26 +138,26 @@ static int si2157_init(struct dvb_frontend *fe) } /* cold state - try to download firmware */ - dev_info(&dev->client->dev, "found a '%s' in cold state\n", + dev_info(&client->dev, "found a '%s' in cold state\n", si2157_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &dev->client->dev); + ret = request_firmware(&fw, fw_file, &client->dev); if (ret) { - dev_err(&dev->client->dev, "firmware file '%s' not found\n", + dev_err(&client->dev, "firmware file '%s' not found\n", fw_file); goto err; } /* firmware should be n chunks of 17 bytes */ if (fw->size % 17 != 0) { - dev_err(&dev->client->dev, "firmware file '%s' is invalid\n", + dev_err(&client->dev, "firmware file '%s' is invalid\n", fw_file); ret = -EINVAL; goto fw_release_exit; } - dev_info(&dev->client->dev, "downloading firmware from file '%s'\n", + dev_info(&client->dev, "downloading firmware from file '%s'\n", fw_file); for (remaining = fw->size; remaining > 0; remaining -= 17) { @@ -164,10 +165,9 @@ static int si2157_init(struct dvb_frontend *fe) memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); cmd.wlen = len; cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) { - dev_err(&dev->client->dev, - "firmware download failed=%d\n", + dev_err(&client->dev, "firmware download failed %d\n", ret); goto fw_release_exit; } @@ -181,7 +181,7 @@ skip_fw_download: memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; @@ -194,17 +194,18 @@ warm: fw_release_exit: release_firmware(fw); err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int si2157_sleep(struct dvb_frontend *fe) { - struct si2157_dev *dev = fe->tuner_priv; + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); int ret; struct si2157_cmd cmd; - dev_dbg(&dev->client->dev, "\n"); + dev_dbg(&client->dev, "\n"); dev->active = false; @@ -212,28 +213,28 @@ static int si2157_sleep(struct dvb_frontend *fe) memcpy(cmd.args, "\x16\x00", 2); cmd.wlen = 2; cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int si2157_set_params(struct dvb_frontend *fe) { - struct si2157_dev *dev = fe->tuner_priv; + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; struct si2157_cmd cmd; u8 bandwidth, delivery_system; - dev_dbg(&dev->client->dev, + dev_dbg(&client->dev, "delivery_system=%d frequency=%u bandwidth_hz=%u\n", - c->delivery_system, c->frequency, - c->bandwidth_hz); + c->delivery_system, c->frequency, c->bandwidth_hz); if (!dev->active) { ret = -EAGAIN; @@ -274,7 +275,7 @@ static int si2157_set_params(struct dvb_frontend *fe) cmd.args[5] = 0x01; cmd.wlen = 6; cmd.rlen = 4; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; @@ -284,7 +285,7 @@ static int si2157_set_params(struct dvb_frontend *fe) memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6); cmd.wlen = 6; cmd.rlen = 4; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; @@ -296,13 +297,13 @@ static int si2157_set_params(struct dvb_frontend *fe) cmd.args[7] = (c->frequency >> 24) & 0xff; cmd.wlen = 8; cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; return 0; err: - dev_dbg(&dev->client->dev, "failed=%d\n", ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -341,7 +342,7 @@ static int si2157_probe(struct i2c_client *client, goto err; } - dev->client = client; + i2c_set_clientdata(client, dev); dev->fe = cfg->fe; dev->inversion = cfg->inversion; dev->fw_loaded = false; @@ -351,17 +352,14 @@ static int si2157_probe(struct i2c_client *client, /* check if the tuner is there */ cmd.wlen = 0; cmd.rlen = 1; - ret = si2157_cmd_execute(dev, &cmd); + ret = si2157_cmd_execute(client, &cmd); if (ret) goto err; - fe->tuner_priv = dev; memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = client; - i2c_set_clientdata(client, dev); - - dev_info(&dev->client->dev, - "Silicon Labs %s successfully attached\n", + dev_info(&client->dev, "Silicon Labs %s successfully attached\n", dev->chiptype == SI2157_CHIPTYPE_SI2146 ? "Si2146" : "Si2147/2148/2157/2158"); diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index 8f6cfc00ddac..7aa53bce5593 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -23,7 +23,6 @@ /* state struct */ struct si2157_dev { struct mutex i2c_mutex; - struct i2c_client *client; struct dvb_frontend *fe; bool active; bool fw_loaded; -- cgit v1.2.3 From 78dab40a51fc4370744ba38b5d8b9c3294c8c136 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 14:51:17 -0300 Subject: [media] si2157: change firmware download error handling Rename firmare download error path goto label. Remove firmware NULL set as NULL value is not needed anymore, due to recent change which started using goto labels for firmware error handling. Cc: Olli Salonen Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 88afb2adfdd1..6174c8eaa8b4 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -81,7 +81,7 @@ static int si2157_init(struct dvb_frontend *fe) struct si2157_dev *dev = i2c_get_clientdata(client); int ret, len, remaining; struct si2157_cmd cmd; - const struct firmware *fw = NULL; + const struct firmware *fw; u8 *fw_file; unsigned int chip_id; @@ -154,7 +154,7 @@ static int si2157_init(struct dvb_frontend *fe) dev_err(&client->dev, "firmware file '%s' is invalid\n", fw_file); ret = -EINVAL; - goto fw_release_exit; + goto err_release_firmware; } dev_info(&client->dev, "downloading firmware from file '%s'\n", @@ -169,12 +169,11 @@ static int si2157_init(struct dvb_frontend *fe) if (ret) { dev_err(&client->dev, "firmware download failed %d\n", ret); - goto fw_release_exit; + goto err_release_firmware; } } release_firmware(fw); - fw = NULL; skip_fw_download: /* reboot the tuner with new firmware? */ @@ -191,7 +190,7 @@ warm: dev->active = true; return 0; -fw_release_exit: +err_release_firmware: release_firmware(fw); err: dev_dbg(&client->dev, "failed=%d\n", ret); -- cgit v1.2.3 From c12922338cb9d1f06cf0951ad3ee692f7d3d96f9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 15:07:45 -0300 Subject: [media] si2157: trivial ID table changes - Rename ID table. - Remove magic numbers from ID table driver data field. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 6174c8eaa8b4..211d500a74dd 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -383,12 +383,12 @@ static int si2157_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si2157_id[] = { - {"si2157", 0}, - {"si2146", 1}, +static const struct i2c_device_id si2157_id_table[] = { + {"si2157", SI2157_CHIPTYPE_SI2157}, + {"si2146", SI2157_CHIPTYPE_SI2146}, {} }; -MODULE_DEVICE_TABLE(i2c, si2157_id); +MODULE_DEVICE_TABLE(i2c, si2157_id_table); static struct i2c_driver si2157_driver = { .driver = { @@ -397,7 +397,7 @@ static struct i2c_driver si2157_driver = { }, .probe = si2157_probe, .remove = si2157_remove, - .id_table = si2157_id, + .id_table = si2157_id_table, }; module_i2c_driver(si2157_driver); -- cgit v1.2.3 From e7f3f9f36235ca604c336c424709a6ecdd39ce8f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 15:13:31 -0300 Subject: [media] si2157: add own goto label for kfree() on probe error Use own goto label for error case mem free is needed, even kfree could be called with NULL. I think it is better to have it, even not required. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 211d500a74dd..3f9aa7ae1613 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -353,7 +353,7 @@ static int si2157_probe(struct i2c_client *client, cmd.rlen = 1; ret = si2157_cmd_execute(client, &cmd); if (ret) - goto err; + goto err_kfree; memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = client; @@ -363,9 +363,11 @@ static int si2157_probe(struct i2c_client *client, "Si2146" : "Si2147/2148/2157/2158"); return 0; + +err_kfree: + kfree(dev); err: dev_dbg(&client->dev, "failed=%d\n", ret); - kfree(dev); return ret; } -- cgit v1.2.3 From c7011845ca72b52c0cac133a8cb5ffb602431705 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 17:25:24 -0300 Subject: [media] si2157: print firmware version Firmware version could be printed similarly than si2168 driver does. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 3f9aa7ae1613..6ae76204ddd4 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -184,6 +184,17 @@ skip_fw_download: if (ret) goto err; + /* query firmware version */ + memcpy(cmd.args, "\x11", 1); + cmd.wlen = 1; + cmd.rlen = 10; + ret = si2157_cmd_execute(client, &cmd); + if (ret) + goto err; + + dev_info(&client->dev, "firmware version: %c.%c.%d\n", + cmd.args[6], cmd.args[7], cmd.args[8]); + dev->fw_loaded = true; warm: -- cgit v1.2.3 From 6c3725332de55c0b668fe6c92fa45dcf8bf00fb9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 18:12:39 -0300 Subject: [media] si2157: print chip version Print chip version once using log level into when init() is called. Remove cold/warm state printing as those are not very useful. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 6ae76204ddd4..27b488b5f714 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -128,7 +128,8 @@ static int si2157_init(struct dvb_frontend *fe) case SI2157_A30: case SI2147_A30: case SI2146_A10: - goto skip_fw_download; + fw_file = NULL; + break; default: dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", cmd.args[2], cmd.args[1], @@ -137,9 +138,11 @@ static int si2157_init(struct dvb_frontend *fe) goto err; } - /* cold state - try to download firmware */ - dev_info(&client->dev, "found a '%s' in cold state\n", - si2157_ops.info.name); + dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", + cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); + + if (fw_file == NULL) + goto skip_fw_download; /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, &client->dev); -- cgit v1.2.3 From 08272db62a92c5b72033c332ced5f631bd9176de Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 6 Dec 2014 18:15:18 -0300 Subject: [media] si2157: change firmware variable name and type Rename firmware variable from fw_file to fw_name and change its type from u8 to const char as request_firmware() input is. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 27b488b5f714..fcf139dfdec6 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -82,7 +82,7 @@ static int si2157_init(struct dvb_frontend *fe) int ret, len, remaining; struct si2157_cmd cmd; const struct firmware *fw; - u8 *fw_file; + const char *fw_name; unsigned int chip_id; dev_dbg(&client->dev, "\n"); @@ -123,12 +123,12 @@ static int si2157_init(struct dvb_frontend *fe) switch (chip_id) { case SI2158_A20: case SI2148_A20: - fw_file = SI2158_A20_FIRMWARE; + fw_name = SI2158_A20_FIRMWARE; break; case SI2157_A30: case SI2147_A30: case SI2146_A10: - fw_file = NULL; + fw_name = NULL; break; default: dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", @@ -141,27 +141,27 @@ static int si2157_init(struct dvb_frontend *fe) dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); - if (fw_file == NULL) + if (fw_name == NULL) goto skip_fw_download; /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &client->dev); + ret = request_firmware(&fw, fw_name, &client->dev); if (ret) { dev_err(&client->dev, "firmware file '%s' not found\n", - fw_file); + fw_name); goto err; } /* firmware should be n chunks of 17 bytes */ if (fw->size % 17 != 0) { dev_err(&client->dev, "firmware file '%s' is invalid\n", - fw_file); + fw_name); ret = -EINVAL; goto err_release_firmware; } dev_info(&client->dev, "downloading firmware from file '%s'\n", - fw_file); + fw_name); for (remaining = fw->size; remaining > 0; remaining -= 17) { len = fw->data[fw->size - remaining]; -- cgit v1.2.3 From 3f7a3f6ecf3f8bb144617a190aef3e0dd258078d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2014 09:11:48 -0300 Subject: [media] tlg2300: remove deprecated staging driver This driver hasn't been tested in a long, long time. The company that made this chip has gone bust many years ago and hardware using this chip is next to impossible to find. This driver needs to be converted to newer media frameworks but due to the lack of hardware that's going to be impossible. Since cheap alternatives are easily available, there is little point in keeping this driver alive. This driver is already deprecated, so now remove it altogether. Signed-off-by: Hans Verkuil Cc: Huang Shijie Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 6 - drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/tlg2300/Kconfig | 21 - drivers/staging/media/tlg2300/Makefile | 9 - drivers/staging/media/tlg2300/pd-alsa.c | 337 ------ drivers/staging/media/tlg2300/pd-common.h | 270 ----- drivers/staging/media/tlg2300/pd-dvb.c | 597 ----------- drivers/staging/media/tlg2300/pd-main.c | 553 ---------- drivers/staging/media/tlg2300/pd-radio.c | 336 ------ drivers/staging/media/tlg2300/pd-video.c | 1560 ---------------------------- drivers/staging/media/tlg2300/vendorcmds.h | 243 ----- 12 files changed, 3935 deletions(-) delete mode 100644 drivers/staging/media/tlg2300/Kconfig delete mode 100644 drivers/staging/media/tlg2300/Makefile delete mode 100644 drivers/staging/media/tlg2300/pd-alsa.c delete mode 100644 drivers/staging/media/tlg2300/pd-common.h delete mode 100644 drivers/staging/media/tlg2300/pd-dvb.c delete mode 100644 drivers/staging/media/tlg2300/pd-main.c delete mode 100644 drivers/staging/media/tlg2300/pd-radio.c delete mode 100644 drivers/staging/media/tlg2300/pd-video.c delete mode 100644 drivers/staging/media/tlg2300/vendorcmds.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 15bec7491fe9..f3ae573d1d4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8393,12 +8393,6 @@ F: kernel/time/clocksource.c F: kernel/time/time*.c F: kernel/time/ntp.c -TLG2300 VIDEO4LINUX-2 DRIVER -M: Huang Shijie -M: Hans Verkuil -S: Odd Fixes -F: drivers/media/usb/tlg2300/ - SC1200 WDT DRIVER M: Zwane Mwaikambo S: Maintained diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 2a054a99d433..61e4acb1e4ae 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -27,8 +27,6 @@ source "drivers/staging/media/davinci_vpfe/Kconfig" source "drivers/staging/media/dt3155v4l/Kconfig" -source "drivers/staging/media/tlg2300/Kconfig" - source "drivers/staging/media/mn88472/Kconfig" source "drivers/staging/media/mn88473/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 412b28408398..b7bda1057f54 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -7,6 +7,5 @@ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_DVB_MN88473) += mn88473/ obj-y += parport/ -obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ obj-y += vino/ diff --git a/drivers/staging/media/tlg2300/Kconfig b/drivers/staging/media/tlg2300/Kconfig deleted file mode 100644 index 77d8753f6ba4..000000000000 --- a/drivers/staging/media/tlg2300/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -config VIDEO_TLG2300 - tristate "Telegent TLG2300 USB video capture support (Deprecated)" - depends on VIDEO_DEV && I2C && SND && DVB_CORE - depends on MEDIA_USB_SUPPORT - select VIDEO_TUNER - select VIDEO_TVEEPROM - depends on RC_CORE - select VIDEOBUF_VMALLOC - select SND_PCM - select VIDEOBUF_DVB - - ---help--- - This is a video4linux driver for Telegent tlg2300 based TV cards. - The driver supports V4L2, DVB-T and radio. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called poseidon diff --git a/drivers/staging/media/tlg2300/Makefile b/drivers/staging/media/tlg2300/Makefile deleted file mode 100644 index 137f8e38cdec..000000000000 --- a/drivers/staging/media/tlg2300/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o - -obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o - -ccflags-y += -Idrivers/media/i2c -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends - diff --git a/drivers/staging/media/tlg2300/pd-alsa.c b/drivers/staging/media/tlg2300/pd-alsa.c deleted file mode 100644 index dd8fe100590f..000000000000 --- a/drivers/staging/media/tlg2300/pd-alsa.c +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pd-common.h" -#include "vendorcmds.h" - -static void complete_handler_audio(struct urb *urb); -#define AUDIO_EP (0x83) -#define AUDIO_BUF_SIZE (512) -#define PERIOD_SIZE (1024 * 8) -#define PERIOD_MIN (4) -#define PERIOD_MAX PERIOD_MIN - -static struct snd_pcm_hardware snd_pd_hw_capture = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN, - .period_bytes_min = PERIOD_SIZE, - .period_bytes_max = PERIOD_SIZE, - .periods_min = PERIOD_MIN, - .periods_max = PERIOD_MAX, - /* - .buffer_bytes_max = 62720 * 8, - .period_bytes_min = 64, - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98 - */ -}; - -static int snd_pd_capture_open(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (!p) - return -ENODEV; - pa->users++; - pa->card_close = 0; - pa->capture_pcm_substream = substream; - runtime->private_data = p; - - runtime->hw = snd_pd_hw_capture; - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - usb_autopm_get_interface(p->interface); - kref_get(&p->kref); - return 0; -} - -static int snd_pd_pcm_close(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - - pa->users--; - pa->card_close = 1; - usb_autopm_put_interface(p->interface); - kref_put(&p->kref, poseidon_delete); - return 0; -} - -static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size; - - size = params_buffer_bytes(hw_params); - if (runtime->dma_area) { - if (runtime->dma_bytes > size) - return 0; - vfree(runtime->dma_area); - } - runtime->dma_area = vmalloc(size); - if (!runtime->dma_area) - return -ENOMEM; - else - runtime->dma_bytes = size; - return 0; -} - -static int audio_buf_free(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - int i; - - for (i = 0; i < AUDIO_BUFS; i++) - if (pa->urb_array[i]) - usb_kill_urb(pa->urb_array[i]); - free_all_urb_generic(pa->urb_array, AUDIO_BUFS); - logpm(); - return 0; -} - -static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - - logpm(); - audio_buf_free(p); - return 0; -} - -static int snd_pd_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -#define AUDIO_TRAILER_SIZE (16) -static inline void handle_audio_data(struct urb *urb, int *period_elapsed) -{ - struct poseidon_audio *pa = urb->context; - struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime; - - int stride = runtime->frame_bits >> 3; - int len = urb->actual_length / stride; - unsigned char *cp = urb->transfer_buffer; - unsigned int oldptr = pa->rcv_position; - - if (urb->actual_length == AUDIO_BUF_SIZE - 4) - len -= (AUDIO_TRAILER_SIZE / stride); - - /* do the copy */ - if (oldptr + len >= runtime->buffer_size) { - unsigned int cnt = runtime->buffer_size - oldptr; - - memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride); - memcpy(runtime->dma_area, (cp + cnt * stride), - (len * stride - cnt * stride)); - } else - memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); - - /* update the statas */ - snd_pcm_stream_lock(pa->capture_pcm_substream); - pa->rcv_position += len; - if (pa->rcv_position >= runtime->buffer_size) - pa->rcv_position -= runtime->buffer_size; - - pa->copied_position += (len); - if (pa->copied_position >= runtime->period_size) { - pa->copied_position -= runtime->period_size; - *period_elapsed = 1; - } - snd_pcm_stream_unlock(pa->capture_pcm_substream); -} - -static void complete_handler_audio(struct urb *urb) -{ - struct poseidon_audio *pa = urb->context; - struct snd_pcm_substream *substream = pa->capture_pcm_substream; - int period_elapsed = 0; - int ret; - - if (1 == pa->card_close || pa->capture_stream != STREAM_ON) - return; - - if (urb->status != 0) { - /*if (urb->status == -ESHUTDOWN)*/ - return; - } - - if (substream) { - if (urb->actual_length) { - handle_audio_data(urb, &period_elapsed); - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - } - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - log("audio urb failed (errcod = %i)", ret); - return; -} - -static int fire_audio_urb(struct poseidon *p) -{ - int i, ret = 0; - struct poseidon_audio *pa = &p->audio; - - alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS, - p->udev, AUDIO_EP, - AUDIO_BUF_SIZE, GFP_ATOMIC, - complete_handler_audio, pa); - - for (i = 0; i < AUDIO_BUFS; i++) { - ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL); - if (ret) - log("urb err : %d", ret); - } - log(); - return ret; -} - -static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - - if (debug_mode) - log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - if (pa->capture_stream == STREAM_ON) - return 0; - - pa->rcv_position = pa->copied_position = 0; - pa->capture_stream = STREAM_ON; - - if (in_hibernation(p)) - return 0; - fire_audio_urb(p); - return 0; - - case SNDRV_PCM_TRIGGER_SUSPEND: - pa->capture_stream = STREAM_SUSPEND; - return 0; - case SNDRV_PCM_TRIGGER_STOP: - pa->capture_stream = STREAM_OFF; - return 0; - default: - return -EINVAL; - } -} - -static snd_pcm_uframes_t -snd_pd_capture_pointer(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - return pa->rcv_position; -} - -static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - return vmalloc_to_page(pageptr); -} - -static struct snd_pcm_ops pcm_capture_ops = { - .open = snd_pd_capture_open, - .close = snd_pd_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pd_hw_capture_params, - .hw_free = snd_pd_hw_capture_free, - .prepare = snd_pd_prepare, - .trigger = snd_pd_capture_trigger, - .pointer = snd_pd_capture_pointer, - .page = snd_pcm_pd_get_page, -}; - -#ifdef CONFIG_PM -int pm_alsa_suspend(struct poseidon *p) -{ - logpm(p); - audio_buf_free(p); - return 0; -} - -int pm_alsa_resume(struct poseidon *p) -{ - logpm(p); - fire_audio_urb(p); - return 0; -} -#endif - -int poseidon_audio_init(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - struct snd_card *card; - struct snd_pcm *pcm; - int ret; - - ret = snd_card_new(&p->interface->dev, -1, "Telegent", - THIS_MODULE, 0, &card); - if (ret != 0) - return ret; - - ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm); - if (ret < 0) { - snd_card_free(card); - return ret; - } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); - pcm->info_flags = 0; - pcm->private_data = p; - strcpy(pcm->name, "poseidon audio capture"); - - strcpy(card->driver, "ALSA driver"); - strcpy(card->shortname, "poseidon Audio"); - strcpy(card->longname, "poseidon ALSA Audio"); - - if (snd_card_register(card)) { - snd_card_free(card); - return -ENOMEM; - } - pa->card = card; - return 0; -} - -int poseidon_audio_free(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - - if (pa->card) - snd_card_free(pa->card); - return 0; -} diff --git a/drivers/staging/media/tlg2300/pd-common.h b/drivers/staging/media/tlg2300/pd-common.h deleted file mode 100644 index 04c5aacd836e..000000000000 --- a/drivers/staging/media/tlg2300/pd-common.h +++ /dev/null @@ -1,270 +0,0 @@ -#ifndef PD_COMMON_H -#define PD_COMMON_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dvb_frontend.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dmxdev.h" - -#define SBUF_NUM 8 -#define MAX_BUFFER_NUM 6 -#define PK_PER_URB 32 -#define ISO_PKT_SIZE 3072 - -#define POSEIDON_STATE_NONE (0x0000) -#define POSEIDON_STATE_ANALOG (0x0001) -#define POSEIDON_STATE_FM (0x0002) -#define POSEIDON_STATE_DVBT (0x0004) -#define POSEIDON_STATE_DISCONNECT (0x0080) - -#define PM_SUSPEND_DELAY 3 - -#define V4L_PAL_VBI_LINES 18 -#define V4L_NTSC_VBI_LINES 12 -#define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2) -#define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2) - -#define TUNER_FREQ_MIN (45000000U) -#define TUNER_FREQ_MAX (862000000U) - -struct vbi_data { - struct video_device v_dev; - struct video_data *video; - struct front_face *front; - - unsigned int copied; - unsigned int vbi_size; /* the whole size of two fields */ - int users; -}; - -/* - * This is the running context of the video, it is useful for - * resume() - */ -struct running_context { - u32 freq; /* VIDIOC_S_FREQUENCY */ - int audio_idx; /* VIDIOC_S_TUNER */ - v4l2_std_id tvnormid; /* VIDIOC_S_STD */ - int sig_index; /* VIDIOC_S_INPUT */ - struct v4l2_pix_format pix; /* VIDIOC_S_FMT */ -}; - -struct video_data { - /* v4l2 video device */ - struct video_device v_dev; - struct v4l2_ctrl_handler ctrl_handler; - - /* the working context */ - struct running_context context; - - /* for data copy */ - int field_count; - - char *dst; - int lines_copied; - int prev_left; - - int lines_per_field; - int lines_size; - - /* for communication */ - u8 endpoint_addr; - struct urb *urb_array[SBUF_NUM]; - struct vbi_data *vbi; - struct poseidon *pd; - struct front_face *front; - - int is_streaming; - int users; - - /* for bubble handler */ - struct work_struct bubble_work; -}; - -enum pcm_stream_state { - STREAM_OFF, - STREAM_ON, - STREAM_SUSPEND, -}; - -#define AUDIO_BUFS (3) -#define CAPTURE_STREAM_EN 1 -struct poseidon_audio { - struct urb *urb_array[AUDIO_BUFS]; - unsigned int copied_position; - struct snd_pcm_substream *capture_pcm_substream; - - unsigned int rcv_position; - struct snd_card *card; - int card_close; - - int users; - int pm_state; - enum pcm_stream_state capture_stream; -}; - -struct radio_data { - __u32 fm_freq; - unsigned int is_radio_streaming; - int pre_emphasis; - struct video_device fm_dev; - struct v4l2_ctrl_handler ctrl_handler; -}; - -#define DVB_SBUF_NUM 4 -#define DVB_URB_BUF_SIZE 0x2000 -struct pd_dvb_adapter { - struct dvb_adapter dvb_adap; - struct dvb_frontend dvb_fe; - struct dmxdev dmxdev; - struct dvb_demux demux; - - atomic_t users; - atomic_t active_feed; - - /* data transfer */ - s32 is_streaming; - struct urb *urb_array[DVB_SBUF_NUM]; - struct poseidon *pd_device; - u8 ep_addr; - u8 reserved[3]; - - /* data for power resume*/ - struct dtv_frontend_properties fe_param; - - /* for channel scanning */ - int prev_freq; - int bandwidth; - unsigned long last_jiffies; -}; - -struct front_face { - /* use this field to distinguish VIDEO and VBI */ - enum v4l2_buf_type type; - - /* for host */ - struct videobuf_queue q; - - /* the bridge for host and device */ - struct videobuf_buffer *curr_frame; - - /* for device */ - spinlock_t queue_lock; - struct list_head active; - struct poseidon *pd; -}; - -struct poseidon { - struct list_head device_list; - - struct mutex lock; - struct kref kref; - - /* for V4L2 */ - struct v4l2_device v4l2_dev; - - /* hardware info */ - struct usb_device *udev; - struct usb_interface *interface; - int cur_transfer_mode; - - struct video_data video_data; /* video */ - struct vbi_data vbi_data; /* vbi */ - struct poseidon_audio audio; /* audio (alsa) */ - struct radio_data radio_data; /* FM */ - struct pd_dvb_adapter dvb_data; /* DVB */ - - u32 state; - struct file *file_for_stream; /* the active stream*/ - -#ifdef CONFIG_PM - int (*pm_suspend)(struct poseidon *); - int (*pm_resume)(struct poseidon *); - pm_message_t msg; - - struct work_struct pm_work; - u8 portnum; -#endif -}; - -struct poseidon_format { - char *name; - int fourcc; /* video4linux 2 */ - int depth; /* bit/pixel */ - int flags; -}; - -struct poseidon_tvnorm { - v4l2_std_id v4l2_id; - char name[12]; - u32 tlg_tvnorm; -}; - -/* video */ -int pd_video_init(struct poseidon *); -void pd_video_exit(struct poseidon *); -int stop_all_video_stream(struct poseidon *); - -/* alsa audio */ -int poseidon_audio_init(struct poseidon *); -int poseidon_audio_free(struct poseidon *); -#ifdef CONFIG_PM -int pm_alsa_suspend(struct poseidon *); -int pm_alsa_resume(struct poseidon *); -#endif - -/* dvb */ -int pd_dvb_usb_device_init(struct poseidon *); -void pd_dvb_usb_device_exit(struct poseidon *); -void pd_dvb_usb_device_cleanup(struct poseidon *); -int pd_dvb_get_adapter_num(struct pd_dvb_adapter *); -void dvb_stop_streaming(struct pd_dvb_adapter *); - -/* FM */ -int poseidon_fm_init(struct poseidon *); -int poseidon_fm_exit(struct poseidon *); - -/* vendor command ops */ -int send_set_req(struct poseidon*, u8, s32, s32*); -int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32); -s32 set_tuner_mode(struct poseidon*, unsigned char); - -/* bulk urb alloc/free */ -int alloc_bulk_urbs_generic(struct urb **urb_array, int num, - struct usb_device *udev, u8 ep_addr, - int buf_size, gfp_t gfp_flags, - usb_complete_t complete_fn, void *context); -void free_all_urb_generic(struct urb **urb_array, int num); - -/* misc */ -void poseidon_delete(struct kref *kref); -extern int debug_mode; - -#ifdef CONFIG_PM -#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) -#else -#define in_hibernation(pd) (0) -#endif -#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt)) - -#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \ - __func__, __LINE__, ## __VA_ARGS__) - -/* for power management */ -#define logpm(pd) do {\ - if (debug_mode & 0x10)\ - log();\ - } while (0) - -#endif diff --git a/drivers/staging/media/tlg2300/pd-dvb.c b/drivers/staging/media/tlg2300/pd-dvb.c deleted file mode 100644 index ca4994a5190c..000000000000 --- a/drivers/staging/media/tlg2300/pd-dvb.c +++ /dev/null @@ -1,597 +0,0 @@ -#include "pd-common.h" -#include -#include -#include -#include -#include -#include - -#include "vendorcmds.h" -#include -#include - -static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); - -static int dvb_bandwidth[][2] = { - { TLG_BW_8, 8000000 }, - { TLG_BW_7, 7000000 }, - { TLG_BW_6, 6000000 } -}; -static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); - -static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); -static int poseidon_check_mode_dvbt(struct poseidon *pd) -{ - s32 ret = 0, cmd_status = 0; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - - ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); - if (ret != 0) - return ret; - - ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); - if (ret) - return ret; - - /* signal source */ - ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); - if (ret|cmd_status) - return ret; - - return 0; -} - -/* acquire : - * 1 == open - * 0 == release - */ -static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb; - int ret = 0; - - if (!pd) - return -ENODEV; - - pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); - if (acquire) { - mutex_lock(&pd->lock); - if (pd->state & POSEIDON_STATE_DISCONNECT) { - ret = -ENODEV; - goto open_out; - } - - if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { - ret = -EBUSY; - goto open_out; - } - - usb_autopm_get_interface(pd->interface); - if (0 == pd->state) { - ret = poseidon_check_mode_dvbt(pd); - if (ret < 0) { - usb_autopm_put_interface(pd->interface); - goto open_out; - } - pd->state |= POSEIDON_STATE_DVBT; - pd_dvb->bandwidth = 0; - pd_dvb->prev_freq = 0; - } - atomic_inc(&pd_dvb->users); - kref_get(&pd->kref); -open_out: - mutex_unlock(&pd->lock); - } else { - dvb_stop_streaming(pd_dvb); - - if (atomic_dec_and_test(&pd_dvb->users)) { - mutex_lock(&pd->lock); - pd->state &= ~POSEIDON_STATE_DVBT; - mutex_unlock(&pd->lock); - } - kref_put(&pd->kref, poseidon_delete); - usb_autopm_put_interface(pd->interface); - } - return ret; -} - -#ifdef CONFIG_PM -static void poseidon_fe_release(struct dvb_frontend *fe) -{ - struct poseidon *pd = fe->demodulator_priv; - - pd->pm_suspend = NULL; - pd->pm_resume = NULL; -} -#else -#define poseidon_fe_release NULL -#endif - -static s32 poseidon_fe_sleep(struct dvb_frontend *fe) -{ - return 0; -} - -/* - * return true if we can satisfy the conditions, else return false. - */ -static bool check_scan_ok(__u32 freq, int bandwidth, - struct pd_dvb_adapter *adapter) -{ - if (bandwidth < 0) - return false; - - if (adapter->prev_freq == freq - && adapter->bandwidth == bandwidth) { - long nl = jiffies - adapter->last_jiffies; - unsigned int msec ; - - msec = jiffies_to_msecs(abs(nl)); - return msec > 15000 ? true : false; - } - return true; -} - -/* - * Check if the firmware delays too long for an invalid frequency. - */ -static int fw_delay_overflow(struct pd_dvb_adapter *adapter) -{ - long nl = jiffies - adapter->last_jiffies; - unsigned int msec ; - - msec = jiffies_to_msecs(abs(nl)); - return msec > 800 ? true : false; -} - -static int poseidon_set_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; - s32 ret = 0, cmd_status = 0; - s32 i, bandwidth = -1; - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - if (in_hibernation(pd)) - return -EBUSY; - - mutex_lock(&pd->lock); - for (i = 0; i < dvb_bandwidth_length; i++) - if (fep->bandwidth_hz == dvb_bandwidth[i][1]) - bandwidth = dvb_bandwidth[i][0]; - - if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { - ret = send_set_req(pd, TUNE_FREQ_SELECT, - fep->frequency / 1000, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - ret = send_set_req(pd, DVBT_BANDW_SEL, - bandwidth, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - /* save the context for future */ - memcpy(&pd_dvb->fe_param, fep, sizeof(*fep)); - pd_dvb->bandwidth = bandwidth; - pd_dvb->prev_freq = fep->frequency; - pd_dvb->last_jiffies = jiffies; - } -front_out: - mutex_unlock(&pd->lock); - return ret; -} - -#ifdef CONFIG_PM -static int pm_dvb_suspend(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - dvb_stop_streaming(pd_dvb); - dvb_urb_cleanup(pd_dvb); - msleep(500); - return 0; -} - -static int pm_dvb_resume(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - poseidon_check_mode_dvbt(pd); - msleep(300); - poseidon_set_fe(&pd_dvb->dvb_fe); - - dvb_start_streaming(pd_dvb); - return 0; -} -#endif - -static s32 poseidon_fe_init(struct dvb_frontend *fe) -{ - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - -#ifdef CONFIG_PM - pd->pm_suspend = pm_dvb_suspend; - pd->pm_resume = pm_dvb_resume; -#endif - memset(&pd_dvb->fe_param, 0, - sizeof(struct dtv_frontend_properties)); - return 0; -} - -static int poseidon_get_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - memcpy(fep, &pd_dvb->fe_param, sizeof(*fep)); - return 0; -} - -static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe, - struct dvb_frontend_tune_settings *tune) -{ - tune->min_delay_ms = 1000; - return 0; -} - -static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat) -{ - struct poseidon *pd = fe->demodulator_priv; - s32 ret = -1, cmd_status; - struct tuner_dtv_sig_stat_s status = {}; - - if (in_hibernation(pd)) - return -EBUSY; - mutex_lock(&pd->lock); - - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, - &status, &cmd_status, sizeof(status)); - if (ret | cmd_status) { - log("get tuner status error"); - goto out; - } - - if (debug_mode) - log("P : %d, L %d, LB :%d", status.sig_present, - status.sig_locked, status.sig_lock_busy); - - if (status.sig_lock_busy) { - goto out; - } else if (status.sig_present || status.sig_locked) { - *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER - | FE_HAS_SYNC | FE_HAS_VITERBI; - } else { - if (fw_delay_overflow(&pd->dvb_data)) - *stat |= FE_TIMEDOUT; - } -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - struct poseidon *pd = fe->demodulator_priv; - struct tuner_ber_rate_s tlg_ber = {}; - s32 ret = -1, cmd_status; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_BER_RATE, 0, - &tlg_ber, &cmd_status, sizeof(tlg_ber)); - if (ret | cmd_status) - goto out; - *ber = tlg_ber.ber_rate; -out: - mutex_unlock(&pd->lock); - return ret; -} - -static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct poseidon *pd = fe->demodulator_priv; - struct tuner_dtv_sig_stat_s status = {}; - s32 ret = 0, cmd_status; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, - &status, &cmd_status, sizeof(status)); - if (ret | cmd_status) - goto out; - if ((status.sig_present || status.sig_locked) && !status.sig_strength) - *strength = 0xFFFF; - else - *strength = status.sig_strength; -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - return 0; -} - -static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) -{ - *unc = 0; - return 0; -} - -static struct dvb_frontend_ops poseidon_frontend_ops = { - .delsys = { SYS_DVBT }, - .info = { - .name = "Poseidon DVB-T", - .frequency_min = 174000000, - .frequency_max = 862000000, - .frequency_stepsize = 62500,/* FIXME */ - .caps = FE_CAN_INVERSION_AUTO | - 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_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_RECOVER | - FE_CAN_HIERARCHY_AUTO, - }, - - .release = poseidon_fe_release, - - .init = poseidon_fe_init, - .sleep = poseidon_fe_sleep, - - .set_frontend = poseidon_set_fe, - .get_frontend = poseidon_get_fe, - .get_tune_settings = poseidon_fe_get_tune_settings, - - .read_status = poseidon_read_status, - .read_ber = poseidon_read_ber, - .read_signal_strength = poseidon_read_signal_strength, - .read_snr = poseidon_read_snr, - .read_ucblocks = poseidon_read_unc_blocks, - - .ts_bus_ctrl = poseidon_ts_bus_ctrl, -}; - -static void dvb_urb_irq(struct urb *urb) -{ - struct pd_dvb_adapter *pd_dvb = urb->context; - int len = urb->transfer_buffer_length; - struct dvb_demux *demux = &pd_dvb->demux; - s32 ret; - - if (!pd_dvb->is_streaming || urb->status) { - if (urb->status == -EPROTO) - goto resend; - return; - } - - if (urb->actual_length == len) - dvb_dmx_swfilter(demux, urb->transfer_buffer, len); - else if (urb->actual_length == len - 4) { - int offset; - u8 *buf = urb->transfer_buffer; - - /* - * The packet size is 512, - * last packet contains 456 bytes tsp data - */ - for (offset = 456; offset < len; offset += 512) { - if (!strncmp(buf + offset, "DVHS", 4)) { - dvb_dmx_swfilter(demux, buf, offset); - if (len > offset + 52 + 4) { - /*16 bytes trailer + 36 bytes padding */ - buf += offset + 52; - len -= offset + 52 + 4; - dvb_dmx_swfilter(demux, buf, len); - } - break; - } - } - } - -resend: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log(" usb_submit_urb failed: error %d", ret); -} - -static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb) -{ - if (pd_dvb->urb_array[0]) - return 0; - - alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM, - pd_dvb->pd_device->udev, pd_dvb->ep_addr, - DVB_URB_BUF_SIZE, GFP_KERNEL, - dvb_urb_irq, pd_dvb); - return 0; -} - -static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb) -{ - free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM); -} - -static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb) -{ - struct poseidon *pd = pd_dvb->pd_device; - int ret = 0; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mutex_lock(&pd->lock); - if (!pd_dvb->is_streaming) { - s32 i, cmd_status = 0; - /* - * Once upon a time, there was a difficult bug lying here. - * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - */ - - ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status); - if (ret | cmd_status) - goto out; - - ret = dvb_urb_init(pd_dvb); - if (ret < 0) - goto out; - - pd_dvb->is_streaming = 1; - for (i = 0; i < DVB_SBUF_NUM; i++) { - ret = usb_submit_urb(pd_dvb->urb_array[i], - GFP_KERNEL); - if (ret) { - log(" submit urb error %d", ret); - goto out; - } - } - } -out: - mutex_unlock(&pd->lock); - return ret; -} - -void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb) -{ - struct poseidon *pd = pd_dvb->pd_device; - - mutex_lock(&pd->lock); - if (pd_dvb->is_streaming) { - s32 i, ret, cmd_status = 0; - - pd_dvb->is_streaming = 0; - - for (i = 0; i < DVB_SBUF_NUM; i++) - if (pd_dvb->urb_array[i]) - usb_kill_urb(pd_dvb->urb_array[i]); - - ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - if (ret | cmd_status) - log("error"); - } - mutex_unlock(&pd->lock); -} - -static int pd_start_feed(struct dvb_demux_feed *feed) -{ - struct pd_dvb_adapter *pd_dvb = feed->demux->priv; - int ret = 0; - - if (!pd_dvb) - return -1; - if (atomic_inc_return(&pd_dvb->active_feed) == 1) - ret = dvb_start_streaming(pd_dvb); - return ret; -} - -static int pd_stop_feed(struct dvb_demux_feed *feed) -{ - struct pd_dvb_adapter *pd_dvb = feed->demux->priv; - - if (!pd_dvb) - return -1; - if (atomic_dec_and_test(&pd_dvb->active_feed)) - dvb_stop_streaming(pd_dvb); - return 0; -} - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int pd_dvb_usb_device_init(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - struct dvb_demux *dvbdemux; - int ret = 0; - - pd_dvb->ep_addr = 0x82; - atomic_set(&pd_dvb->users, 0); - atomic_set(&pd_dvb->active_feed, 0); - pd_dvb->pd_device = pd; - - ret = dvb_register_adapter(&pd_dvb->dvb_adap, - "Poseidon dvbt adapter", - THIS_MODULE, - NULL /* for hibernation correctly*/, - adapter_nr); - if (ret < 0) - goto error1; - - /* register frontend */ - pd_dvb->dvb_fe.demodulator_priv = pd; - memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops, - sizeof(struct dvb_frontend_ops)); - ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe); - if (ret < 0) - goto error2; - - /* register demux device */ - dvbdemux = &pd_dvb->demux; - dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; - dvbdemux->priv = pd_dvb; - dvbdemux->feednum = dvbdemux->filternum = 64; - dvbdemux->start_feed = pd_start_feed; - dvbdemux->stop_feed = pd_stop_feed; - dvbdemux->write_to_decoder = NULL; - - ret = dvb_dmx_init(dvbdemux); - if (ret < 0) - goto error3; - - pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum; - pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx; - pd_dvb->dmxdev.capabilities = 0; - - ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap); - if (ret < 0) - goto error3; - return 0; - -error3: - dvb_unregister_frontend(&pd_dvb->dvb_fe); -error2: - dvb_unregister_adapter(&pd_dvb->dvb_adap); -error1: - return ret; -} - -void pd_dvb_usb_device_exit(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - while (atomic_read(&pd_dvb->users) != 0 - || atomic_read(&pd_dvb->active_feed) != 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - } - dvb_dmxdev_release(&pd_dvb->dmxdev); - dvb_unregister_frontend(&pd_dvb->dvb_fe); - dvb_unregister_adapter(&pd_dvb->dvb_adap); - pd_dvb_usb_device_cleanup(pd); -} - -void pd_dvb_usb_device_cleanup(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - dvb_urb_cleanup(pd_dvb); -} - -int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb) -{ - return pd_dvb->dvb_adap.num; -} diff --git a/drivers/staging/media/tlg2300/pd-main.c b/drivers/staging/media/tlg2300/pd-main.c deleted file mode 100644 index b31f4791b8ff..000000000000 --- a/drivers/staging/media/tlg2300/pd-main.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * device driver for Telegent tlg2300 based TV cards - * - * Author : - * Kang Yong - * Zhang Xiaobing - * Huang Shijie or - * - * (c) 2009 Telegent Systems - * (c) 2010 Telegent Systems - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "vendorcmds.h" -#include "pd-common.h" - -#define VENDOR_ID 0x1B24 -#define PRODUCT_ID 0x4001 -static struct usb_device_id id_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -int debug_mode; -module_param(debug_mode, int, 0644); -MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); - -#define TLG2300_FIRMWARE "tlg2300_firmware.bin" -static const char *firmware_name = TLG2300_FIRMWARE; -static LIST_HEAD(pd_device_list); - -/* - * send set request to USB firmware. - */ -s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status) -{ - s32 ret; - s8 data[32] = {}; - u16 lower_16, upper_16; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mdelay(30); - - if (param == 0) { - upper_16 = lower_16 = 0; - } else { - /* send 32 bit param as two 16 bit param,little endian */ - lower_16 = (unsigned short)(param & 0xffff); - upper_16 = (unsigned short)((param >> 16) & 0xffff); - } - ret = usb_control_msg(pd->udev, - usb_rcvctrlpipe(pd->udev, 0), - REQ_SET_CMD | cmdid, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - lower_16, - upper_16, - &data, - sizeof(*cmd_status), - USB_CTRL_GET_TIMEOUT); - - if (!ret) { - return -ENXIO; - } else { - /* 1st 4 bytes into cmd_status */ - memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status)); - } - return 0; -} - -/* - * send get request to Poseidon firmware. - */ -s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param, - void *buf, s32 *cmd_status, s32 datalen) -{ - s32 ret; - s8 data[128] = {}; - u16 lower_16, upper_16; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mdelay(30); - if (param == 0) { - upper_16 = lower_16 = 0; - } else { - /*send 32 bit param as two 16 bit param, little endian */ - lower_16 = (unsigned short)(param & 0xffff); - upper_16 = (unsigned short)((param >> 16) & 0xffff); - } - ret = usb_control_msg(pd->udev, - usb_rcvctrlpipe(pd->udev, 0), - REQ_GET_CMD | cmdid, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - lower_16, - upper_16, - &data, - (datalen + sizeof(*cmd_status)), - USB_CTRL_GET_TIMEOUT); - - if (ret < 0) { - return -ENXIO; - } else { - /* 1st 4 bytes into cmd_status, remaining data into cmd_data */ - memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status)); - memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen); - } - return 0; -} - -static int pm_notifier_block(struct notifier_block *nb, - unsigned long event, void *dummy) -{ - struct poseidon *pd = NULL; - struct list_head *node, *next; - - switch (event) { - case PM_POST_HIBERNATION: - list_for_each_safe(node, next, &pd_device_list) { - struct usb_device *udev; - struct usb_interface *iface; - int rc = 0; - - pd = container_of(node, struct poseidon, device_list); - udev = pd->udev; - iface = pd->interface; - - /* It will cause the system to reload the firmware */ - rc = usb_lock_device_for_reset(udev, iface); - if (rc >= 0) { - usb_reset_device(udev); - usb_unlock_device(udev); - } - } - break; - default: - break; - } - log("event :%ld\n", event); - return 0; -} - -static struct notifier_block pm_notifer = { - .notifier_call = pm_notifier_block, -}; - -int set_tuner_mode(struct poseidon *pd, unsigned char mode) -{ - s32 ret, cmd_status; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status); - if (ret || cmd_status) - return -ENXIO; - return 0; -} - -void poseidon_delete(struct kref *kref) -{ - struct poseidon *pd = container_of(kref, struct poseidon, kref); - - if (!pd) - return; - list_del_init(&pd->device_list); - - pd_dvb_usb_device_cleanup(pd); - /* clean_audio_data(&pd->audio_data);*/ - - if (pd->udev) { - usb_put_dev(pd->udev); - pd->udev = NULL; - } - if (pd->interface) { - usb_put_intf(pd->interface); - pd->interface = NULL; - } - kfree(pd); - log(); -} - -static int firmware_download(struct usb_device *udev) -{ - int ret = 0, actual_length; - const struct firmware *fw = NULL; - void *fwbuf = NULL; - size_t fwlength = 0, offset; - size_t max_packet_size; - - ret = request_firmware(&fw, firmware_name, &udev->dev); - if (ret) { - log("download err : %d", ret); - return ret; - } - - fwlength = fw->size; - - fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL); - if (!fwbuf) { - ret = -ENOMEM; - goto out; - } - - max_packet_size = le16_to_cpu(udev->ep_out[0x1]->desc.wMaxPacketSize); - log("\t\t download size : %d", (int)max_packet_size); - - for (offset = 0; offset < fwlength; offset += max_packet_size) { - actual_length = 0; - ret = usb_bulk_msg(udev, - usb_sndbulkpipe(udev, 0x01), /* ep 1 */ - fwbuf + offset, - min(max_packet_size, fwlength - offset), - &actual_length, - HZ * 10); - if (ret) - break; - } - kfree(fwbuf); -out: - release_firmware(fw); - return ret; -} - -static inline struct poseidon *get_pd(struct usb_interface *intf) -{ - return usb_get_intfdata(intf); -} - -#ifdef CONFIG_PM -/* one-to-one map : poseidon{} <----> usb_device{}'s port */ -static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) -{ - pd->portnum = udev->portnum; -} - -static inline int get_autopm_ref(struct poseidon *pd) -{ - return pd->video_data.users + pd->vbi_data.users + pd->audio.users - + atomic_read(&pd->dvb_data.users) + - !list_empty(&pd->radio_data.fm_dev.fh_list); -} - -/* fixup something for poseidon */ -static inline struct poseidon *fixup(struct poseidon *pd) -{ - int count; - - /* old udev and interface have gone, so put back reference . */ - count = get_autopm_ref(pd); - log("count : %d, ref count : %d", count, get_pm_count(pd)); - while (count--) - usb_autopm_put_interface(pd->interface); - /*usb_autopm_set_interface(pd->interface); */ - - usb_put_dev(pd->udev); - usb_put_intf(pd->interface); - log("event : %d\n", pd->msg.event); - return pd; -} - -static struct poseidon *find_old_poseidon(struct usb_device *udev) -{ - struct poseidon *pd; - - list_for_each_entry(pd, &pd_device_list, device_list) { - if (pd->portnum == udev->portnum && in_hibernation(pd)) - return fixup(pd); - } - return NULL; -} - -/* Is the card working now ? */ -static inline int is_working(struct poseidon *pd) -{ - return get_pm_count(pd) > 0; -} - -static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg) -{ - struct poseidon *pd = get_pd(intf); - - if (!pd) - return 0; - if (!is_working(pd)) { - if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) { - pd->msg.event = PM_EVENT_AUTO_SUSPEND; - pd->pm_resume = NULL; /* a good guard */ - printk(KERN_DEBUG "TLG2300 auto suspend\n"); - } - return 0; - } - pd->msg = msg; /* save it here */ - logpm(pd); - return pd->pm_suspend ? pd->pm_suspend(pd) : 0; -} - -static int poseidon_resume(struct usb_interface *intf) -{ - struct poseidon *pd = get_pd(intf); - - if (!pd) - return 0; - printk(KERN_DEBUG "TLG2300 resume\n"); - - if (!is_working(pd)) { - if (PM_EVENT_AUTO_SUSPEND == pd->msg.event) - pd->msg = PMSG_ON; - return 0; - } - if (in_hibernation(pd)) { - logpm(pd); - return 0; - } - logpm(pd); - return pd->pm_resume ? pd->pm_resume(pd) : 0; -} - -static void hibernation_resume(struct work_struct *w) -{ - struct poseidon *pd = container_of(w, struct poseidon, pm_work); - int count; - - pd->msg.event = 0; /* clear it here */ - pd->state &= ~POSEIDON_STATE_DISCONNECT; - - /* set the new interface's reference */ - count = get_autopm_ref(pd); - while (count--) - usb_autopm_get_interface(pd->interface); - - /* resume the context */ - logpm(pd); - if (pd->pm_resume) - pd->pm_resume(pd); -} -#else /* CONFIG_PM is not enabled: */ -static inline struct poseidon *find_old_poseidon(struct usb_device *udev) -{ - return NULL; -} - -static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) -{ -} -#endif - -static int check_firmware(struct usb_device *udev) -{ - void *buf; - int ret; - struct cmd_firmware_vers_s *cmd_firm; - - buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL); - if (!buf) - return -ENOMEM; - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - REQ_GET_CMD | GET_FW_ID, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - 0, - buf, - sizeof(*cmd_firm) + sizeof(u32), - USB_CTRL_GET_TIMEOUT); - kfree(buf); - - if (ret < 0) - return firmware_download(udev); - return 0; -} - -static int poseidon_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct poseidon *pd = NULL; - int ret = 0; - int new_one = 0; - - /* download firmware */ - ret = check_firmware(udev); - if (ret) - return ret; - - /* Do I recovery from the hibernate ? */ - pd = find_old_poseidon(udev); - if (!pd) { - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - kref_init(&pd->kref); - set_map_flags(pd, udev); - new_one = 1; - } - - pd->udev = usb_get_dev(udev); - pd->interface = usb_get_intf(interface); - usb_set_intfdata(interface, pd); - - if (new_one) { - logpm(pd); - mutex_init(&pd->lock); - - /* register v4l2 device */ - ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev); - if (ret) - goto err_v4l2; - - /* register devices in directory /dev */ - ret = pd_video_init(pd); - if (ret) - goto err_video; - ret = poseidon_audio_init(pd); - if (ret) - goto err_audio; - ret = poseidon_fm_init(pd); - if (ret) - goto err_fm; - ret = pd_dvb_usb_device_init(pd); - if (ret) - goto err_dvb; - - INIT_LIST_HEAD(&pd->device_list); - list_add_tail(&pd->device_list, &pd_device_list); - } - - device_init_wakeup(&udev->dev, 1); -#ifdef CONFIG_PM - pm_runtime_set_autosuspend_delay(&pd->udev->dev, - 1000 * PM_SUSPEND_DELAY); - usb_enable_autosuspend(pd->udev); - - if (in_hibernation(pd)) { - INIT_WORK(&pd->pm_work, hibernation_resume); - schedule_work(&pd->pm_work); - } -#endif - return 0; -err_dvb: - poseidon_fm_exit(pd); -err_fm: - poseidon_audio_free(pd); -err_audio: - pd_video_exit(pd); -err_video: - v4l2_device_unregister(&pd->v4l2_dev); -err_v4l2: - usb_put_intf(pd->interface); - usb_put_dev(pd->udev); - kfree(pd); - return ret; -} - -static void poseidon_disconnect(struct usb_interface *interface) -{ - struct poseidon *pd = get_pd(interface); - - if (!pd) - return; - logpm(pd); - if (in_hibernation(pd)) - return; - - mutex_lock(&pd->lock); - pd->state |= POSEIDON_STATE_DISCONNECT; - mutex_unlock(&pd->lock); - - /* stop urb transferring */ - stop_all_video_stream(pd); - dvb_stop_streaming(&pd->dvb_data); - - /*unregister v4l2 device */ - v4l2_device_unregister(&pd->v4l2_dev); - - pd_dvb_usb_device_exit(pd); - poseidon_fm_exit(pd); - - poseidon_audio_free(pd); - pd_video_exit(pd); - - usb_set_intfdata(interface, NULL); - kref_put(&pd->kref, poseidon_delete); -} - -static struct usb_driver poseidon_driver = { - .name = "poseidon", - .probe = poseidon_probe, - .disconnect = poseidon_disconnect, - .id_table = id_table, -#ifdef CONFIG_PM - .suspend = poseidon_suspend, - .resume = poseidon_resume, -#endif - .supports_autosuspend = 1, -}; - -static int __init poseidon_init(void) -{ - int ret; - - ret = usb_register(&poseidon_driver); - if (ret) - return ret; - register_pm_notifier(&pm_notifer); - return ret; -} - -static void __exit poseidon_exit(void) -{ - log(); - unregister_pm_notifier(&pm_notifer); - usb_deregister(&poseidon_driver); -} - -module_init(poseidon_init); -module_exit(poseidon_exit); - -MODULE_AUTHOR("Telegent Systems"); -MODULE_DESCRIPTION("For tlg2300-based USB device"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.2"); -MODULE_FIRMWARE(TLG2300_FIRMWARE); diff --git a/drivers/staging/media/tlg2300/pd-radio.c b/drivers/staging/media/tlg2300/pd-radio.c deleted file mode 100644 index c0567b5ed363..000000000000 --- a/drivers/staging/media/tlg2300/pd-radio.c +++ /dev/null @@ -1,336 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pd-common.h" -#include "vendorcmds.h" - -static int set_frequency(struct poseidon *p, __u32 frequency); -static int poseidon_fm_close(struct file *filp); -static int poseidon_fm_open(struct file *filp); - -#define TUNER_FREQ_MIN_FM 76000000U -#define TUNER_FREQ_MAX_FM 108000000U - -#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1) -static int preemphasis[MAX_PREEMPHASIS] = { - TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */ - TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */ - TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */ -}; - -static int poseidon_check_mode_radio(struct poseidon *p) -{ - int ret; - u32 status; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); - ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE); - if (ret < 0) - goto out; - - ret = set_tuner_mode(p, TLG_MODE_FM_RADIO); - if (ret != 0) - goto out; - - ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status); - ret = send_set_req(p, TUNER_AUD_ANA_STD, - p->radio_data.pre_emphasis, &status); - ret |= send_set_req(p, TUNER_AUD_MODE, - TLG_TUNE_TVAUDIO_MODE_STEREO, &status); - ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL, - ATV_AUDIO_RATE_48K, &status); - ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status); -out: - return ret; -} - -#ifdef CONFIG_PM -static int pm_fm_suspend(struct poseidon *p) -{ - logpm(p); - pm_alsa_suspend(p); - usb_set_interface(p->udev, 0, 0); - msleep(300); - return 0; -} - -static int pm_fm_resume(struct poseidon *p) -{ - logpm(p); - poseidon_check_mode_radio(p); - set_frequency(p, p->radio_data.fm_freq); - pm_alsa_resume(p); - return 0; -} -#endif - -static int poseidon_fm_open(struct file *filp) -{ - struct poseidon *p = video_drvdata(filp); - int ret = 0; - - mutex_lock(&p->lock); - if (p->state & POSEIDON_STATE_DISCONNECT) { - ret = -ENODEV; - goto out; - } - - if (p->state && !(p->state & POSEIDON_STATE_FM)) { - ret = -EBUSY; - goto out; - } - ret = v4l2_fh_open(filp); - if (ret) - goto out; - - usb_autopm_get_interface(p->interface); - if (0 == p->state) { - /* default pre-emphasis */ - if (p->radio_data.pre_emphasis == 0) - p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; - - ret = poseidon_check_mode_radio(p); - if (ret < 0) { - usb_autopm_put_interface(p->interface); - goto out; - } - p->state |= POSEIDON_STATE_FM; - } - kref_get(&p->kref); -out: - mutex_unlock(&p->lock); - return ret; -} - -static int poseidon_fm_close(struct file *filp) -{ - struct poseidon *p = video_drvdata(filp); - struct radio_data *fm = &p->radio_data; - uint32_t status; - - mutex_lock(&p->lock); - if (v4l2_fh_is_singular_file(filp)) - p->state &= ~POSEIDON_STATE_FM; - - if (fm->is_radio_streaming && filp == p->file_for_stream) { - fm->is_radio_streaming = 0; - send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status); - } - usb_autopm_put_interface(p->interface); - mutex_unlock(&p->lock); - - kref_put(&p->kref, poseidon_delete); - return v4l2_fh_release(filp); -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct poseidon *p = video_drvdata(file); - - strlcpy(v->driver, "tele-radio", sizeof(v->driver)); - strlcpy(v->card, "Telegent Poseidon", sizeof(v->card)); - usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info)); - v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - /* Report all capabilities of the USB device */ - v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS | - V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_AUDIO | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - return 0; -} - -static const struct v4l2_file_operations poseidon_fm_fops = { - .owner = THIS_MODULE, - .open = poseidon_fm_open, - .release = poseidon_fm_close, - .poll = v4l2_ctrl_poll, - .unlocked_ioctl = video_ioctl2, -}; - -static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *vt) -{ - struct poseidon *p = video_drvdata(file); - struct tuner_fm_sig_stat_s fm_stat = {}; - int ret, status, count = 5; - - if (vt->index != 0) - return -EINVAL; - - vt->type = V4L2_TUNER_RADIO; - vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; - vt->rangelow = TUNER_FREQ_MIN_FM * 2 / 125; - vt->rangehigh = TUNER_FREQ_MAX_FM * 2 / 125; - vt->rxsubchans = V4L2_TUNER_SUB_STEREO; - vt->audmode = V4L2_TUNER_MODE_STEREO; - vt->signal = 0; - vt->afc = 0; - strlcpy(vt->name, "Radio", sizeof(vt->name)); - - mutex_lock(&p->lock); - ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, - &fm_stat, &status, sizeof(fm_stat)); - - while (fm_stat.sig_lock_busy && count-- && !ret) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, - &fm_stat, &status, sizeof(fm_stat)); - } - mutex_unlock(&p->lock); - - if (ret || status) { - vt->signal = 0; - } else if ((fm_stat.sig_present || fm_stat.sig_locked) - && fm_stat.sig_strength == 0) { - vt->signal = 0xffff; - } else - vt->signal = (fm_stat.sig_strength * 255 / 10) << 8; - - return 0; -} - -static int fm_get_freq(struct file *file, void *priv, - struct v4l2_frequency *argp) -{ - struct poseidon *p = video_drvdata(file); - - if (argp->tuner) - return -EINVAL; - argp->frequency = p->radio_data.fm_freq; - return 0; -} - -static int set_frequency(struct poseidon *p, __u32 frequency) -{ - __u32 freq ; - int ret, status; - - mutex_lock(&p->lock); - - ret = send_set_req(p, TUNER_AUD_ANA_STD, - p->radio_data.pre_emphasis, &status); - - freq = (frequency * 125) / 2; /* Hz */ - freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM); - - ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status); - if (ret < 0) - goto error ; - ret = send_set_req(p, TAKE_REQUEST, 0, &status); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - if (!p->radio_data.is_radio_streaming) { - ret = send_set_req(p, TAKE_REQUEST, 0, &status); - ret = send_set_req(p, PLAY_SERVICE, - TLG_TUNE_PLAY_SVC_START, &status); - p->radio_data.is_radio_streaming = 1; - } - p->radio_data.fm_freq = freq * 2 / 125; -error: - mutex_unlock(&p->lock); - return ret; -} - -static int fm_set_freq(struct file *file, void *priv, - const struct v4l2_frequency *argp) -{ - struct poseidon *p = video_drvdata(file); - - if (argp->tuner) - return -EINVAL; - p->file_for_stream = file; -#ifdef CONFIG_PM - p->pm_suspend = pm_fm_suspend; - p->pm_resume = pm_fm_resume; -#endif - return set_frequency(p, argp->frequency); -} - -static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct poseidon *p = container_of(ctrl->handler, struct poseidon, - radio_data.ctrl_handler); - int pre_emphasis; - u32 status; - - switch (ctrl->id) { - case V4L2_CID_TUNE_PREEMPHASIS: - pre_emphasis = preemphasis[ctrl->val]; - send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status); - p->radio_data.pre_emphasis = pre_emphasis; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) -{ - return vt->index > 0 ? -EINVAL : 0; -} - -static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = { - .s_ctrl = tlg_fm_s_ctrl, -}; - -static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_tuner = tlg_fm_vidioc_g_tuner, - .vidioc_g_frequency = fm_get_freq, - .vidioc_s_frequency = fm_set_freq, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static struct video_device poseidon_fm_template = { - .name = "Telegent-Radio", - .fops = &poseidon_fm_fops, - .minor = -1, - .release = video_device_release_empty, - .ioctl_ops = &poseidon_fm_ioctl_ops, -}; - -int poseidon_fm_init(struct poseidon *p) -{ - struct video_device *vfd = &p->radio_data.fm_dev; - struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler; - - *vfd = poseidon_fm_template; - - set_frequency(p, TUNER_FREQ_MIN_FM); - v4l2_ctrl_handler_init(hdl, 1); - v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, - V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS); - if (hdl->error) { - v4l2_ctrl_handler_free(hdl); - return hdl->error; - } - vfd->v4l2_dev = &p->v4l2_dev; - vfd->ctrl_handler = hdl; - video_set_drvdata(vfd, p); - return video_register_device(vfd, VFL_TYPE_RADIO, -1); -} - -int poseidon_fm_exit(struct poseidon *p) -{ - video_unregister_device(&p->radio_data.fm_dev); - v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler); - return 0; -} diff --git a/drivers/staging/media/tlg2300/pd-video.c b/drivers/staging/media/tlg2300/pd-video.c deleted file mode 100644 index c0c3c1c4517c..000000000000 --- a/drivers/staging/media/tlg2300/pd-video.c +++ /dev/null @@ -1,1560 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "pd-common.h" -#include "vendorcmds.h" - -#ifdef CONFIG_PM -static int pm_video_suspend(struct poseidon *pd); -static int pm_video_resume(struct poseidon *pd); -#endif -static void iso_bubble_handler(struct work_struct *w); - -static int usb_transfer_mode; -module_param(usb_transfer_mode, int, 0644); -MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); - -static const struct poseidon_format poseidon_formats[] = { - { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0}, - { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0}, -}; - -static const struct poseidon_tvnorm poseidon_tvnorms[] = { - { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D }, - { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B }, - { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G }, - { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H }, - { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I }, - { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M }, - { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO }, - { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO }, - { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M }, - { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J }, - { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B }, - { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D }, - { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G }, - { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H }, - { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K }, - { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 }, - { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L }, - { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 }, -}; -static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms); - -struct pd_audio_mode { - u32 tlg_audio_mode; - u32 v4l2_audio_sub; - u32 v4l2_audio_mode; -}; - -static const struct pd_audio_mode pd_audio_modes[] = { - { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO, - V4L2_TUNER_MODE_MONO }, - { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO, - V4L2_TUNER_MODE_STEREO }, - { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1, - V4L2_TUNER_MODE_LANG1 }, - { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2, - V4L2_TUNER_MODE_LANG2 }, - { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1, - V4L2_TUNER_MODE_LANG1_LANG2 } -}; -static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes); - -struct pd_input { - char *name; - uint32_t tlg_src; -}; - -static const struct pd_input pd_inputs[] = { - { "TV Antenna", TLG_SIG_SRC_ANTENNA }, - { "TV Cable", TLG_SIG_SRC_CABLE }, - { "TV SVideo", TLG_SIG_SRC_SVIDEO }, - { "TV Composite", TLG_SIG_SRC_COMPOSITE } -}; -static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs); - -struct video_std_to_audio_std { - v4l2_std_id video_std; - int audio_std; -}; - -static const struct video_std_to_audio_std video_to_audio_map[] = { - /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64, - 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */ - { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D | - V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM }, - - /* country : { 1, 52, 54, 55, 886 } */ - {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC}, - - /* country : { 81 } */ - { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ }, - - /* other country : TLG_TUNE_ASTD_A2 */ -}; -static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map); - -static int get_audio_std(v4l2_std_id v4l2_std) -{ - int i = 0; - - for (; i < map_size; i++) { - if (v4l2_std & video_to_audio_map[i].video_std) - return video_to_audio_map[i].audio_std; - } - return TLG_TUNE_ASTD_A2; -} - -static int vidioc_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct video_device *vdev = video_devdata(file); - struct poseidon *p = video_get_drvdata(vdev); - - strcpy(cap->driver, "tele-video"); - strcpy(cap->card, "Telegent Poseidon"); - usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - if (vdev->vfl_type == VFL_TYPE_VBI) - cap->device_caps |= V4L2_CAP_VBI_CAPTURE; - else - cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS | - V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE; - return 0; -} - -/*====================================================================*/ -static void init_copy(struct video_data *video, bool index) -{ - struct front_face *front = video->front; - - video->field_count = index; - video->lines_copied = 0; - video->prev_left = 0 ; - video->dst = (char *)videobuf_to_vmalloc(front->curr_frame) - + index * video->lines_size; - video->vbi->copied = 0; /* set it here */ -} - -static bool get_frame(struct front_face *front, int *need_init) -{ - struct videobuf_buffer *vb = front->curr_frame; - - if (vb) - return true; - - spin_lock(&front->queue_lock); - if (!list_empty(&front->active)) { - vb = list_entry(front->active.next, - struct videobuf_buffer, queue); - if (need_init) - *need_init = 1; - front->curr_frame = vb; - list_del_init(&vb->queue); - } - spin_unlock(&front->queue_lock); - - return !!vb; -} - -/* check if the video's buffer is ready */ -static bool get_video_frame(struct front_face *front, struct video_data *video) -{ - int need_init = 0; - bool ret = true; - - ret = get_frame(front, &need_init); - if (ret && need_init) - init_copy(video, 0); - return ret; -} - -static void submit_frame(struct front_face *front) -{ - struct videobuf_buffer *vb = front->curr_frame; - - if (vb == NULL) - return; - - front->curr_frame = NULL; - vb->state = VIDEOBUF_DONE; - vb->field_count++; - v4l2_get_timestamp(&vb->ts); - - wake_up(&vb->done); -} - -/* - * A frame is composed of two fields. If we receive all the two fields, - * call the submit_frame() to submit the whole frame to applications. - */ -static void end_field(struct video_data *video) -{ - if (1 == video->field_count) - submit_frame(video->front); - else - init_copy(video, 1); -} - -static void copy_video_data(struct video_data *video, char *src, - unsigned int count) -{ -#define copy_data(len) \ - do { \ - if (++video->lines_copied > video->lines_per_field) \ - goto overflow; \ - memcpy(video->dst, src, len);\ - video->dst += len + video->lines_size; \ - src += len; \ - count -= len; \ - } while (0) - - while (count && count >= video->lines_size) { - if (video->prev_left) { - copy_data(video->prev_left); - video->prev_left = 0; - continue; - } - copy_data(video->lines_size); - } - if (count && count < video->lines_size) { - memcpy(video->dst, src, count); - - video->prev_left = video->lines_size - count; - video->dst += count; - } - return; - -overflow: - end_field(video); -} - -static void check_trailer(struct video_data *video, char *src, int count) -{ - struct vbi_data *vbi = video->vbi; - int offset; /* trailer's offset */ - char *buf; - - offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2) - - (vbi->copied + video->lines_size * video->lines_copied); - if (video->prev_left) - offset -= (video->lines_size - video->prev_left); - - if (offset > count || offset <= 0) - goto short_package; - - buf = src + offset; - - /* trailer : (VFHS) + U32 + U32 + field_num */ - if (!strncmp(buf, "VFHS", 4)) { - int field_num = *((u32 *)(buf + 12)); - - if ((field_num & 1) ^ video->field_count) { - init_copy(video, video->field_count); - return; - } - copy_video_data(video, src, offset); - } -short_package: - end_field(video); -} - -/* ========== Check this more carefully! =========== */ -static inline void copy_vbi_data(struct vbi_data *vbi, - char *src, unsigned int count) -{ - struct front_face *front = vbi->front; - - if (front && get_frame(front, NULL)) { - char *buf = videobuf_to_vmalloc(front->curr_frame); - - if (vbi->video->field_count) - buf += (vbi->vbi_size / 2); - memcpy(buf + vbi->copied, src, count); - } - vbi->copied += count; -} - -/* - * Copy the normal data (VBI or VIDEO) without the trailer. - * VBI is not interlaced, while VIDEO is interlaced. - */ -static inline void copy_vbi_video_data(struct video_data *video, - char *src, unsigned int count) -{ - struct vbi_data *vbi = video->vbi; - unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied; - - if (vbi_delta >= count) { - copy_vbi_data(vbi, src, count); - } else { - if (vbi_delta) { - copy_vbi_data(vbi, src, vbi_delta); - - /* we receive the two fields of the VBI*/ - if (vbi->front && video->field_count) - submit_frame(vbi->front); - } - copy_video_data(video, src + vbi_delta, count - vbi_delta); - } -} - -static void urb_complete_bulk(struct urb *urb) -{ - struct front_face *front = urb->context; - struct video_data *video = &front->pd->video_data; - char *src = (char *)urb->transfer_buffer; - int count = urb->actual_length; - int ret = 0; - - if (!video->is_streaming || urb->status) { - if (urb->status == -EPROTO) - goto resend_it; - return; - } - if (!get_video_frame(front, video)) - goto resend_it; - - if (count == urb->transfer_buffer_length) - copy_vbi_video_data(video, src, count); - else - check_trailer(video, src, count); - -resend_it: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log(" submit failed: error %d", ret); -} - -/************************* for ISO *********************/ -#define GET_SUCCESS (0) -#define GET_TRAILER (1) -#define GET_TOO_MUCH_BUBBLE (2) -#define GET_NONE (3) -static int get_chunk(int start, struct urb *urb, - int *head, int *tail, int *bubble_err) -{ - struct usb_iso_packet_descriptor *pkt = NULL; - int ret = GET_SUCCESS; - - for (*head = *tail = -1; start < urb->number_of_packets; start++) { - pkt = &urb->iso_frame_desc[start]; - - /* handle the bubble of the Hub */ - if (-EOVERFLOW == pkt->status) { - if (++*bubble_err > urb->number_of_packets / 3) - return GET_TOO_MUCH_BUBBLE; - continue; - } - - /* This is the gap */ - if (pkt->status || pkt->actual_length <= 0 - || pkt->actual_length > ISO_PKT_SIZE) { - if (*head != -1) - break; - continue; - } - - /* a good isochronous packet */ - if (pkt->actual_length == ISO_PKT_SIZE) { - if (*head == -1) - *head = start; - *tail = start; - continue; - } - - /* trailer is here */ - if (pkt->actual_length < ISO_PKT_SIZE) { - if (*head == -1) { - *head = start; - *tail = start; - return GET_TRAILER; - } - break; - } - } - - if (*head == -1 && *tail == -1) - ret = GET_NONE; - return ret; -} - -/* - * |__|------|___|-----|_______| - * ^ ^ - * | | - * gap gap - */ -static void urb_complete_iso(struct urb *urb) -{ - struct front_face *front = urb->context; - struct video_data *video = &front->pd->video_data; - int bubble_err = 0, head = 0, tail = 0; - char *src = (char *)urb->transfer_buffer; - int ret = 0; - - if (!video->is_streaming) - return; - - do { - if (!get_video_frame(front, video)) - goto out; - - switch (get_chunk(head, urb, &head, &tail, &bubble_err)) { - case GET_SUCCESS: - copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE), - (tail - head + 1) * ISO_PKT_SIZE); - break; - case GET_TRAILER: - check_trailer(video, src + (head * ISO_PKT_SIZE), - ISO_PKT_SIZE); - break; - case GET_NONE: - goto out; - case GET_TOO_MUCH_BUBBLE: - log("\t We got too much bubble"); - schedule_work(&video->bubble_work); - return; - } - } while (head = tail + 1, head < urb->number_of_packets); - -out: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log("usb_submit_urb err : %d", ret); -} -/*============================= [ end ] =====================*/ - -static int prepare_iso_urb(struct video_data *video) -{ - struct usb_device *udev = video->pd->udev; - int i; - - if (video->urb_array[0]) - return 0; - - for (i = 0; i < SBUF_NUM; i++) { - struct urb *urb; - void *mem; - int j; - - urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL); - if (urb == NULL) - goto out; - - video->urb_array[i] = urb; - mem = usb_alloc_coherent(udev, - ISO_PKT_SIZE * PK_PER_URB, - GFP_KERNEL, - &urb->transfer_dma); - - urb->complete = urb_complete_iso; /* handler */ - urb->dev = udev; - urb->context = video->front; - urb->pipe = usb_rcvisocpipe(udev, - video->endpoint_addr); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->number_of_packets = PK_PER_URB; - urb->transfer_buffer = mem; - urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE; - - for (j = 0; j < PK_PER_URB; j++) { - urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j; - urb->iso_frame_desc[j].length = ISO_PKT_SIZE; - } - } - return 0; -out: - for (; i > 0; i--) - ; - return -ENOMEM; -} - -/* return the succeeded number of the allocation */ -int alloc_bulk_urbs_generic(struct urb **urb_array, int num, - struct usb_device *udev, u8 ep_addr, - int buf_size, gfp_t gfp_flags, - usb_complete_t complete_fn, void *context) -{ - int i = 0; - - for (; i < num; i++) { - void *mem; - struct urb *urb = usb_alloc_urb(0, gfp_flags); - if (urb == NULL) - return i; - - mem = usb_alloc_coherent(udev, buf_size, gfp_flags, - &urb->transfer_dma); - if (mem == NULL) { - usb_free_urb(urb); - return i; - } - - usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr), - mem, buf_size, complete_fn, context); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb_array[i] = urb; - } - return i; -} - -void free_all_urb_generic(struct urb **urb_array, int num) -{ - int i; - struct urb *urb; - - for (i = 0; i < num; i++) { - urb = urb_array[i]; - if (urb) { - usb_free_coherent(urb->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); - usb_free_urb(urb); - urb_array[i] = NULL; - } - } -} - -static int prepare_bulk_urb(struct video_data *video) -{ - if (video->urb_array[0]) - return 0; - - alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM, - video->pd->udev, video->endpoint_addr, - 0x2000, GFP_KERNEL, - urb_complete_bulk, video->front); - return 0; -} - -/* free the URBs */ -static void free_all_urb(struct video_data *video) -{ - free_all_urb_generic(video->urb_array, SBUF_NUM); -} - -static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - videobuf_vmalloc_free(vb); - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct front_face *front = q->priv_data; - vb->state = VIDEOBUF_QUEUED; - list_add_tail(&vb->queue, &front->active); -} - -static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct front_face *front = q->priv_data; - int rc; - - switch (front->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (VIDEOBUF_NEEDS_INIT == vb->state) { - struct v4l2_pix_format *pix; - - pix = &front->pd->video_data.context.pix; - vb->size = pix->sizeimage; /* real frame size */ - vb->width = pix->width; - vb->height = pix->height; - rc = videobuf_iolock(q, vb, NULL); - if (rc < 0) - return rc; - } - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->size = front->pd->vbi_data.vbi_size; - rc = videobuf_iolock(q, vb, NULL); - if (rc < 0) - return rc; - } - break; - default: - return -EINVAL; - } - vb->field = field; - vb->state = VIDEOBUF_PREPARED; - return 0; -} - -static int fire_all_urb(struct video_data *video) -{ - int i, ret; - - video->is_streaming = 1; - - for (i = 0; i < SBUF_NUM; i++) { - ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL); - if (ret) - log("(%d) failed: error %d", i, ret); - } - return ret; -} - -static int start_video_stream(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - s32 cmd_status; - - send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status); - - if (pd->cur_transfer_mode) { - prepare_iso_urb(video); - INIT_WORK(&video->bubble_work, iso_bubble_handler); - } else { - /* The bulk mode does not need a bubble handler */ - prepare_bulk_urb(video); - } - fire_all_urb(video); - return 0; -} - -static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) -{ - struct front_face *front = q->priv_data; - struct poseidon *pd = front->pd; - - switch (front->type) { - default: - return -EINVAL; - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct video_data *video = &pd->video_data; - struct v4l2_pix_format *pix = &video->context.pix; - - *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */ - if (*count < 4) - *count = 4; - if (1) { - /* same in different altersetting */ - video->endpoint_addr = 0x82; - video->vbi = &pd->vbi_data; - video->vbi->video = video; - video->pd = pd; - video->lines_per_field = pix->height / 2; - video->lines_size = pix->width * 2; - video->front = front; - } - return start_video_stream(pd); - } - - case V4L2_BUF_TYPE_VBI_CAPTURE: { - struct vbi_data *vbi = &pd->vbi_data; - - *size = PAGE_ALIGN(vbi->vbi_size); - log("size : %d", *size); - if (*count == 0) - *count = 4; - } - break; - } - return 0; -} - -static struct videobuf_queue_ops pd_video_qops = { - .buf_setup = pd_buf_setup, - .buf_prepare = pd_buf_prepare, - .buf_queue = pd_buf_queue, - .buf_release = pd_buf_release, -}; - -static int vidioc_enum_fmt(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - if (ARRAY_SIZE(poseidon_formats) <= f->index) - return -EINVAL; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = 0; - f->pixelformat = poseidon_formats[f->index].fourcc; - strcpy(f->description, poseidon_formats[f->index].name); - return 0; -} - -static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - - f->fmt.pix = pd->video_data.context.pix; - return 0; -} - -/* - * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while - * Mplayer calls them in the reverse order. - */ -static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix) -{ - struct video_data *video = &pd->video_data; - struct running_context *context = &video->context; - struct v4l2_pix_format *pix_def = &context->pix; - s32 ret = 0, cmd_status = 0, vid_resol; - - /* set the pixel format to firmware */ - if (pix->pixelformat == V4L2_PIX_FMT_RGB565) { - vid_resol = TLG_TUNER_VID_FORMAT_RGB_565; - } else { - pix->pixelformat = V4L2_PIX_FMT_YUYV; - vid_resol = TLG_TUNER_VID_FORMAT_YUV; - } - ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL, - vid_resol, &cmd_status); - - /* set the resolution to firmware */ - vid_resol = TLG_TUNE_VID_RES_720; - switch (pix->width) { - case 704: - vid_resol = TLG_TUNE_VID_RES_704; - break; - default: - pix->width = 720; - case 720: - break; - } - ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, - vid_resol, &cmd_status); - if (ret || cmd_status) - return -EBUSY; - - pix_def->pixelformat = pix->pixelformat; /* save it */ - pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576; - - /* Compare with the default setting */ - if ((pix_def->width != pix->width) - || (pix_def->height != pix->height)) { - pix_def->width = pix->width; - pix_def->height = pix->height; - pix_def->bytesperline = pix->width * 2; - pix_def->sizeimage = pix->width * pix->height * 2; - } - *pix = *pix_def; - - return 0; -} - -static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - - /* stop VBI here */ - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) - return -EINVAL; - - mutex_lock(&pd->lock); - if (pd->file_for_stream == NULL) - pd->file_for_stream = file; - else if (file != pd->file_for_stream) { - mutex_unlock(&pd->lock); - return -EINVAL; - } - - pd_vidioc_s_fmt(pd, &f->fmt.pix); - mutex_unlock(&pd->lock); - return 0; -} - -static int vidioc_g_fmt_vbi(struct file *file, void *fh, - struct v4l2_format *v4l2_f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi; - - vbi_fmt->samples_per_line = 720 * 2; - vbi_fmt->sampling_rate = 6750000 * 4; - vbi_fmt->sample_format = V4L2_PIX_FMT_GREY; - vbi_fmt->offset = 64 * 4; /*FIXME: why offset */ - if (pd->video_data.context.tvnormid & V4L2_STD_525_60) { - vbi_fmt->start[0] = 10; - vbi_fmt->start[1] = 264; - vbi_fmt->count[0] = V4L_NTSC_VBI_LINES; - vbi_fmt->count[1] = V4L_NTSC_VBI_LINES; - } else { - vbi_fmt->start[0] = 6; - vbi_fmt->start[1] = 314; - vbi_fmt->count[0] = V4L_PAL_VBI_LINES; - vbi_fmt->count[1] = V4L_PAL_VBI_LINES; - } - vbi_fmt->flags = V4L2_VBI_UNSYNC; - return 0; -} - -static int set_std(struct poseidon *pd, v4l2_std_id norm) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - struct running_context *context; - struct v4l2_pix_format *pix; - s32 i, ret = 0, cmd_status, param; - int height; - - for (i = 0; i < POSEIDON_TVNORMS; i++) { - if (norm & poseidon_tvnorms[i].v4l2_id) { - param = poseidon_tvnorms[i].tlg_tvnorm; - log("name : %s", poseidon_tvnorms[i].name); - goto found; - } - } - return -EINVAL; -found: - mutex_lock(&pd->lock); - ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status); - if (ret || cmd_status) - goto out; - - /* Set vbi size and check the height of the frame */ - context = &video->context; - context->tvnormid = poseidon_tvnorms[i].v4l2_id; - if (context->tvnormid & V4L2_STD_525_60) { - vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE; - height = 480; - } else { - vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE; - height = 576; - } - - pix = &context->pix; - if (pix->height != height) { - pix->height = height; - pix->sizeimage = pix->width * pix->height * 2; - } - -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm) -{ - struct front_face *front = fh; - - return set_std(front->pd, norm); -} - -static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm) -{ - struct front_face *front = fh; - - *norm = front->pd->video_data.context.tvnormid; - return 0; -} - -static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in) -{ - if (in->index >= POSEIDON_INPUTS) - return -EINVAL; - strcpy(in->name, pd_inputs[in->index].name); - in->type = V4L2_INPUT_TYPE_TUNER; - - /* - * the audio input index mixed with this video input, - * Poseidon only have one audio/video, set to "0" - */ - in->audioset = 1; - in->tuner = 0; - in->std = V4L2_STD_ALL; - in->status = 0; - return 0; -} - -static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct running_context *context = &pd->video_data.context; - - *i = context->sig_index; - return 0; -} - -/* We can support several inputs */ -static int vidioc_s_input(struct file *file, void *fh, unsigned int i) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - s32 ret, cmd_status; - - if (i >= POSEIDON_INPUTS) - return -EINVAL; - ret = send_set_req(pd, SGNL_SRC_SEL, - pd_inputs[i].tlg_src, &cmd_status); - if (ret) - return ret; - - pd->video_data.context.sig_index = i; - return 0; -} - -static int tlg_s_ctrl(struct v4l2_ctrl *c) -{ - struct poseidon *pd = container_of(c->handler, struct poseidon, - video_data.ctrl_handler); - struct tuner_custom_parameter_s param = {0}; - s32 ret = 0, cmd_status, params; - - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL; - break; - case V4L2_CID_CONTRAST: - param.param_id = CUST_PARM_ID_CONTRAST_CTRL; - break; - case V4L2_CID_HUE: - param.param_id = CUST_PARM_ID_HUE_CTRL; - break; - case V4L2_CID_SATURATION: - param.param_id = CUST_PARM_ID_SATURATION_CTRL; - break; - } - param.param_value = c->val; - params = *(s32 *)¶m; /* temp code */ - - mutex_lock(&pd->lock); - ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status); - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - mutex_unlock(&pd->lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - return ret; -} - -/* Audio ioctls */ -static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) -{ - if (0 != a->index) - return -EINVAL; - a->capability = V4L2_AUDCAP_STEREO; - strcpy(a->name, "USB audio in"); - /*Poseidon have no AVL function.*/ - a->mode = 0; - return 0; -} - -static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) -{ - a->index = 0; - a->capability = V4L2_AUDCAP_STEREO; - strcpy(a->name, "USB audio in"); - a->mode = 0; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a) -{ - return (0 == a->index) ? 0 : -EINVAL; -} - -/* Tuner ioctls */ -static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct tuner_atv_sig_stat_s atv_stat; - s32 count = 5, ret, cmd_status; - int index; - - if (0 != tuner->index) - return -EINVAL; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, - &atv_stat, &cmd_status, sizeof(atv_stat)); - - while (atv_stat.sig_lock_busy && count-- && !ret) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, - &atv_stat, &cmd_status, sizeof(atv_stat)); - } - mutex_unlock(&pd->lock); - - if (debug_mode) - log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength); - - if (ret || cmd_status) - tuner->signal = 0; - else if (atv_stat.sig_present && !atv_stat.sig_strength) - tuner->signal = 0xFFFF; - else - tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8; - - strcpy(tuner->name, "Telegent Systems"); - tuner->type = V4L2_TUNER_ANALOG_TV; - tuner->rangelow = TUNER_FREQ_MIN / 62500; - tuner->rangehigh = TUNER_FREQ_MAX / 62500; - tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - index = pd->video_data.context.audio_idx; - tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub; - tuner->audmode = pd_audio_modes[index].v4l2_audio_mode; - tuner->afc = 0; - return 0; -} - -static int pd_vidioc_s_tuner(struct poseidon *pd, int index) -{ - s32 ret = 0, cmd_status, param, audiomode; - - mutex_lock(&pd->lock); - param = pd_audio_modes[index].tlg_audio_mode; - ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status); - audiomode = get_audio_std(pd->video_data.context.tvnormid); - ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, - &cmd_status); - if (!ret) - pd->video_data.context.audio_idx = index; - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - int index; - - if (0 != a->index) - return -EINVAL; - for (index = 0; index < POSEIDON_AUDIOMODS; index++) - if (a->audmode == pd_audio_modes[index].v4l2_audio_mode) - return pd_vidioc_s_tuner(pd, index); - return -EINVAL; -} - -static int vidioc_g_frequency(struct file *file, void *fh, - struct v4l2_frequency *freq) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct running_context *context = &pd->video_data.context; - - if (0 != freq->tuner) - return -EINVAL; - freq->frequency = context->freq; - freq->type = V4L2_TUNER_ANALOG_TV; - return 0; -} - -static int set_frequency(struct poseidon *pd, u32 *frequency) -{ - s32 ret = 0, param, cmd_status; - struct running_context *context = &pd->video_data.context; - - *frequency = clamp(*frequency, - TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500); - param = (*frequency) * 62500 / 1000; - - mutex_lock(&pd->lock); - ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status); - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - - msleep(250); /* wait for a while until the hardware is ready. */ - context->freq = *frequency; - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_frequency(struct file *file, void *fh, - const struct v4l2_frequency *freq) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - u32 frequency = freq->frequency; - - if (freq->tuner) - return -EINVAL; -#ifdef CONFIG_PM - pd->pm_suspend = pm_video_suspend; - pd->pm_resume = pm_video_resume; -#endif - return set_frequency(pd, &frequency); -} - -static int vidioc_reqbufs(struct file *file, void *fh, - struct v4l2_requestbuffers *b) -{ - struct front_face *front = file->private_data; - return videobuf_reqbufs(&front->q, b); -} - -static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - return videobuf_querybuf(&front->q, b); -} - -static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - return videobuf_qbuf(&front->q, b); -} - -static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK); -} - -/* Just stop the URBs, do not free the URBs */ -static int usb_transfer_stop(struct video_data *video) -{ - if (video->is_streaming) { - int i; - s32 cmd_status; - struct poseidon *pd = video->pd; - - video->is_streaming = 0; - for (i = 0; i < SBUF_NUM; ++i) { - if (video->urb_array[i]) - usb_kill_urb(video->urb_array[i]); - } - - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - } - return 0; -} - -int stop_all_video_stream(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - - mutex_lock(&pd->lock); - if (video->is_streaming) { - struct front_face *front = video->front; - - /* stop the URBs */ - usb_transfer_stop(video); - free_all_urb(video); - - /* stop the host side of VIDEO */ - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - - /* stop the host side of VBI */ - front = vbi->front; - if (front) { - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - } - } - mutex_unlock(&pd->lock); - return 0; -} - -/* - * The bubbles can seriously damage the video's quality, - * though it occurs in very rare situation. - */ -static void iso_bubble_handler(struct work_struct *w) -{ - struct video_data *video; - struct poseidon *pd; - - video = container_of(w, struct video_data, bubble_work); - pd = video->pd; - - mutex_lock(&pd->lock); - usb_transfer_stop(video); - msleep(500); - start_video_stream(pd); - mutex_unlock(&pd->lock); -} - - -static int vidioc_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct front_face *front = fh; - - if (unlikely(type != front->type)) - return -EINVAL; - return videobuf_streamon(&front->q); -} - -static int vidioc_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct front_face *front = file->private_data; - - if (unlikely(type != front->type)) - return -EINVAL; - return videobuf_streamoff(&front->q); -} - -/* Set the firmware's default values : need altersetting */ -static int pd_video_checkmode(struct poseidon *pd) -{ - s32 ret = 0, cmd_status, audiomode; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); - - /* choose the altersetting */ - ret = usb_set_interface(pd->udev, 0, - (pd->cur_transfer_mode ? - ISO_3K_BULK_ALTERNATE_IFACE : - BULK_ALTERNATE_IFACE)); - if (ret < 0) - goto error; - - /* set default parameters for PAL-D , with the VBI enabled*/ - ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV); - ret |= send_set_req(pd, SGNL_SRC_SEL, - TLG_SIG_SRC_ANTENNA, &cmd_status); - ret |= send_set_req(pd, VIDEO_STD_SEL, - TLG_TUNE_VSTD_PAL_D, &cmd_status); - ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL, - TLG_TUNER_VID_FORMAT_YUV, &cmd_status); - ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, - TLG_TUNE_VID_RES_720, &cmd_status); - ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status); - ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */ - - /* set the audio */ - audiomode = get_audio_std(pd->video_data.context.tvnormid); - ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status); - ret |= send_set_req(pd, TUNER_AUD_MODE, - TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status); - ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL, - ATV_AUDIO_RATE_48K, &cmd_status); -error: - return ret; -} - -#ifdef CONFIG_PM -static int pm_video_suspend(struct poseidon *pd) -{ - /* stop audio */ - pm_alsa_suspend(pd); - - /* stop and free all the URBs */ - usb_transfer_stop(&pd->video_data); - free_all_urb(&pd->video_data); - - /* reset the interface */ - usb_set_interface(pd->udev, 0, 0); - msleep(300); - return 0; -} - -static int restore_v4l2_context(struct poseidon *pd, - struct running_context *context) -{ - struct front_face *front = pd->video_data.front; - - pd_video_checkmode(pd); - - set_std(pd, context->tvnormid); - vidioc_s_input(NULL, front, context->sig_index); - pd_vidioc_s_tuner(pd, context->audio_idx); - pd_vidioc_s_fmt(pd, &context->pix); - set_frequency(pd, &context->freq); - return 0; -} - -static int pm_video_resume(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - - /* resume the video */ - /* [1] restore the origin V4L2 parameters */ - restore_v4l2_context(pd, &video->context); - - /* [2] initiate video copy variables */ - if (video->front->curr_frame) - init_copy(video, 0); - - /* [3] fire urbs */ - start_video_stream(pd); - - /* resume the audio */ - pm_alsa_resume(pd); - return 0; -} -#endif - -static void init_video_context(struct running_context *context) -{ - context->sig_index = 0; - context->audio_idx = 1; /* stereo */ - context->tvnormid = V4L2_STD_PAL_D; - context->pix = (struct v4l2_pix_format) { - .width = 720, - .height = 576, - .pixelformat = V4L2_PIX_FMT_YUYV, - .field = V4L2_FIELD_INTERLACED, - .bytesperline = 720 * 2, - .sizeimage = 720 * 576 * 2, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - }; -} - -static int pd_video_open(struct file *file) -{ - struct video_device *vfd = video_devdata(file); - struct poseidon *pd = video_get_drvdata(vfd); - struct front_face *front = NULL; - int ret = -ENOMEM; - - mutex_lock(&pd->lock); - usb_autopm_get_interface(pd->interface); - - if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) { - ret = -EBUSY; - goto out; - } - front = kzalloc(sizeof(struct front_face), GFP_KERNEL); - if (!front) - goto out; - if (vfd->vfl_type == VFL_TYPE_GRABBER) { - pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */ - init_video_context(&pd->video_data.context); - - ret = pd_video_checkmode(pd); - if (ret < 0) { - kfree(front); - ret = -1; - goto out; - } - - front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - pd->video_data.users++; - - videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, - NULL, &front->queue_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED,/* video is interlacd */ - sizeof(struct videobuf_buffer),/*it's enough*/ - front, NULL); - } else { - front->type = V4L2_BUF_TYPE_VBI_CAPTURE; - pd->vbi_data.front = front; - pd->vbi_data.users++; - - videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, - NULL, &front->queue_lock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_NONE, /* vbi is NONE mode */ - sizeof(struct videobuf_buffer), - front, NULL); - } - - pd->state |= POSEIDON_STATE_ANALOG; - front->pd = pd; - front->curr_frame = NULL; - INIT_LIST_HEAD(&front->active); - spin_lock_init(&front->queue_lock); - - file->private_data = front; - kref_get(&pd->kref); - - mutex_unlock(&pd->lock); - return 0; -out: - usb_autopm_put_interface(pd->interface); - mutex_unlock(&pd->lock); - return ret; -} - -static int pd_video_release(struct file *file) -{ - struct front_face *front = file->private_data; - struct poseidon *pd = front->pd; - s32 cmd_status = 0; - - mutex_lock(&pd->lock); - - if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - /* stop the device, and free the URBs */ - usb_transfer_stop(&pd->video_data); - free_all_urb(&pd->video_data); - - /* stop the firmware */ - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - - pd->file_for_stream = NULL; - pd->video_data.users--; - } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - pd->vbi_data.front = NULL; - pd->vbi_data.users--; - } - if (!pd->vbi_data.users && !pd->video_data.users) - pd->state &= ~POSEIDON_STATE_ANALOG; - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - - usb_autopm_put_interface(pd->interface); - mutex_unlock(&pd->lock); - - kfree(front); - file->private_data = NULL; - kref_put(&pd->kref, poseidon_delete); - return 0; -} - -static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct front_face *front = file->private_data; - return videobuf_mmap_mapper(&front->q, vma); -} - -static unsigned int pd_video_poll(struct file *file, poll_table *table) -{ - struct front_face *front = file->private_data; - return videobuf_poll_stream(file, &front->q, table); -} - -static ssize_t pd_video_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct front_face *front = file->private_data; - return videobuf_read_stream(&front->q, buffer, count, ppos, - 0, file->f_flags & O_NONBLOCK); -} - -/* This struct works for both VIDEO and VBI */ -static const struct v4l2_file_operations pd_video_fops = { - .owner = THIS_MODULE, - .open = pd_video_open, - .release = pd_video_release, - .read = pd_video_read, - .poll = pd_video_poll, - .mmap = pd_video_mmap, - .ioctl = video_ioctl2, /* maybe changed in future */ -}; - -static const struct v4l2_ioctl_ops pd_video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - - /* Video format */ - .vidioc_g_fmt_vid_cap = vidioc_g_fmt, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */ - - /* Input */ - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_enum_input = vidioc_enum_input, - - /* Audio ioctls */ - .vidioc_enumaudio = vidioc_enumaudio, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - - /* Tuner ioctls */ - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - - /* Buffer handlers */ - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - - /* Stream on/off */ - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, -}; - -static struct video_device pd_video_template = { - .name = "Telegent-Video", - .fops = &pd_video_fops, - .minor = -1, - .release = video_device_release_empty, - .tvnorms = V4L2_STD_ALL, - .ioctl_ops = &pd_video_ioctl_ops, -}; - -static const struct v4l2_ctrl_ops tlg_ctrl_ops = { - .s_ctrl = tlg_s_ctrl, -}; - -void pd_video_exit(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - - video_unregister_device(&video->v_dev); - video_unregister_device(&vbi->v_dev); - v4l2_ctrl_handler_free(&video->ctrl_handler); - log(); -} - -int pd_video_init(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - struct v4l2_ctrl_handler *hdl = &video->ctrl_handler; - u32 freq = TUNER_FREQ_MIN / 62500; - int ret = -ENOMEM; - - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS, - 0, 10000, 1, 100); - v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST, - 0, 10000, 1, 100); - v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE, - 0, 10000, 1, 100); - v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION, - 0, 10000, 1, 100); - if (hdl->error) { - v4l2_ctrl_handler_free(hdl); - return hdl->error; - } - set_frequency(pd, &freq); - video->v_dev = pd_video_template; - video->v_dev.v4l2_dev = &pd->v4l2_dev; - video->v_dev.ctrl_handler = hdl; - video_set_drvdata(&video->v_dev, pd); - - ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1); - if (ret != 0) - goto out; - - /* VBI uses the same template as video */ - vbi->v_dev = pd_video_template; - vbi->v_dev.v4l2_dev = &pd->v4l2_dev; - vbi->v_dev.ctrl_handler = hdl; - video_set_drvdata(&vbi->v_dev, pd); - ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1); - if (ret != 0) - goto out; - log("register VIDEO/VBI devices"); - return 0; -out: - log("VIDEO/VBI devices register failed, : %d", ret); - pd_video_exit(pd); - return ret; -} diff --git a/drivers/staging/media/tlg2300/vendorcmds.h b/drivers/staging/media/tlg2300/vendorcmds.h deleted file mode 100644 index ba6f4ae3b2c2..000000000000 --- a/drivers/staging/media/tlg2300/vendorcmds.h +++ /dev/null @@ -1,243 +0,0 @@ -#ifndef VENDOR_CMD_H_ -#define VENDOR_CMD_H_ - -#define BULK_ALTERNATE_IFACE (2) -#define ISO_3K_BULK_ALTERNATE_IFACE (1) -#define REQ_SET_CMD (0X00) -#define REQ_GET_CMD (0X80) - -enum tlg__analog_audio_standard { - TLG_TUNE_ASTD_NONE = 0x00000000, - TLG_TUNE_ASTD_A2 = 0x00000001, - TLG_TUNE_ASTD_NICAM = 0x00000002, - TLG_TUNE_ASTD_EIAJ = 0x00000004, - TLG_TUNE_ASTD_BTSC = 0x00000008, - TLG_TUNE_ASTD_FM_US = 0x00000010, - TLG_TUNE_ASTD_FM_EUR = 0x00000020, - TLG_TUNE_ASTD_ALL = 0x0000003f -}; - -/* - * identifiers for Custom Parameter messages. - * @typedef cmd_custom_param_id_t - */ -enum cmd_custom_param_id { - CUST_PARM_ID_NONE = 0x00, - CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01, - CUST_PARM_ID_CONTRAST_CTRL = 0x02, - CUST_PARM_ID_HUE_CTRL = 0x03, - CUST_PARM_ID_SATURATION_CTRL = 0x04, - CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10, - CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11, - CUST_PARM_ID_MAX -}; - -struct tuner_custom_parameter_s { - uint16_t param_id; /* Parameter identifier */ - uint16_t param_value; /* Parameter value */ -}; - -struct tuner_ber_rate_s { - uint32_t ber_rate; /* BER sample rate in seconds */ -}; - -struct tuner_atv_sig_stat_s { - uint32_t sig_present; - uint32_t sig_locked; - uint32_t sig_lock_busy; - uint32_t sig_strength; /* milliDb */ - uint32_t tv_audio_chan; /* mono/stereo/sap*/ - uint32_t mvision_stat; /* macrovision status */ -}; - -struct tuner_dtv_sig_stat_s { - uint32_t sig_present; /* Boolean*/ - uint32_t sig_locked; /* Boolean */ - uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */ - uint32_t sig_strength; /* milliDb*/ -}; - -struct tuner_fm_sig_stat_s { - uint32_t sig_present; /* Boolean*/ - uint32_t sig_locked; /* Boolean */ - uint32_t sig_lock_busy; /* Boolean */ - uint32_t sig_stereo_mono;/* TBD*/ - uint32_t sig_strength; /* milliDb*/ -}; - -enum _tag_tlg_tune_srv_cmd { - TLG_TUNE_PLAY_SVC_START = 1, - TLG_TUNE_PLAY_SVC_STOP -}; - -enum _tag_tune_atv_audio_mode_caps { - TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001, - TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002, - TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/ - TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/ - TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040 -}; - - -enum _tag_tuner_atv_audio_rates { - ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/ - ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/ - ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/ - ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */ -}; - -enum _tag_tune_atv_vid_res_caps { - TLG_TUNE_VID_RES_NONE = 0x00000000, - TLG_TUNE_VID_RES_720 = 0x00000001, - TLG_TUNE_VID_RES_704 = 0x00000002, - TLG_TUNE_VID_RES_360 = 0x00000004 -}; - -enum _tag_tuner_analog_video_format { - TLG_TUNER_VID_FORMAT_YUV = 0x00000001, - TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002, - TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004, -}; - -enum tlg_ext_audio_support { - TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */ - TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/ -}; - -enum { - TLG_MODE_NONE = 0x00, /* No Mode specified*/ - TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/ - TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/ - TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/ - TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/ - TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/ -}; - -enum tlg_signal_sources_t { - TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */ - TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */ - TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/ - TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */ - TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */ -}; - -enum tuner_analog_video_standard { - TLG_TUNE_VSTD_NONE = 0x00000000, - TLG_TUNE_VSTD_NTSC_M = 0x00000001, - TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */ - TLG_TUNE_VSTD_PAL_B = 0x00000010, - TLG_TUNE_VSTD_PAL_D = 0x00000020, - TLG_TUNE_VSTD_PAL_G = 0x00000040, - TLG_TUNE_VSTD_PAL_H = 0x00000080, - TLG_TUNE_VSTD_PAL_I = 0x00000100, - TLG_TUNE_VSTD_PAL_M = 0x00000200, - TLG_TUNE_VSTD_PAL_N = 0x00000400, - TLG_TUNE_VSTD_SECAM_B = 0x00001000, - TLG_TUNE_VSTD_SECAM_D = 0x00002000, - TLG_TUNE_VSTD_SECAM_G = 0x00004000, - TLG_TUNE_VSTD_SECAM_H = 0x00008000, - TLG_TUNE_VSTD_SECAM_K = 0x00010000, - TLG_TUNE_VSTD_SECAM_K1 = 0x00020000, - TLG_TUNE_VSTD_SECAM_L = 0x00040000, - TLG_TUNE_VSTD_SECAM_L1 = 0x00080000, - TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000 -}; - -enum tlg_mode_caps { - TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */ - TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */ - TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/ - TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */ - TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */ -}; - -enum poseidon_vendor_cmds { - LAST_CMD_STAT = 0x00, - GET_CHIP_ID = 0x01, - GET_FW_ID = 0x02, - PRODUCT_CAPS = 0x03, - - TUNE_MODE_CAP_ATV = 0x10, - TUNE_MODE_CAP_ATVCOMP = 0X10, - TUNE_MODE_CAP_DVBT = 0x10, - TUNE_MODE_CAP_FM = 0x10, - TUNE_MODE_SELECT = 0x11, - TUNE_FREQ_SELECT = 0x12, - SGNL_SRC_SEL = 0x13, - - VIDEO_STD_SEL = 0x14, - VIDEO_STREAM_FMT_SEL = 0x15, - VIDEO_ROSOLU_AVAIL = 0x16, - VIDEO_ROSOLU_SEL = 0x17, - VIDEO_CONT_PROTECT = 0x20, - - VCR_TIMING_MODSEL = 0x21, - EXT_AUDIO_CAP = 0x22, - EXT_AUDIO_SEL = 0x23, - TEST_PATTERN_SEL = 0x24, - VBI_DATA_SEL = 0x25, - AUDIO_SAMPLE_RATE_CAP = 0x28, - AUDIO_SAMPLE_RATE_SEL = 0x29, - TUNER_AUD_MODE = 0x2a, - TUNER_AUD_MODE_AVAIL = 0x2b, - TUNER_AUD_ANA_STD = 0x2c, - TUNER_CUSTOM_PARAMETER = 0x2f, - - DVBT_TUNE_MODE_SEL = 0x30, - DVBT_BANDW_CAP = 0x31, - DVBT_BANDW_SEL = 0x32, - DVBT_GUARD_INTERV_CAP = 0x33, - DVBT_GUARD_INTERV_SEL = 0x34, - DVBT_MODULATION_CAP = 0x35, - DVBT_MODULATION_SEL = 0x36, - DVBT_INNER_FEC_RATE_CAP = 0x37, - DVBT_INNER_FEC_RATE_SEL = 0x38, - DVBT_TRANS_MODE_CAP = 0x39, - DVBT_TRANS_MODE_SEL = 0x3a, - DVBT_SEARCH_RANG = 0x3c, - - TUNER_SETUP_ANALOG = 0x40, - TUNER_SETUP_DIGITAL = 0x41, - TUNER_SETUP_FM_RADIO = 0x42, - TAKE_REQUEST = 0x43, /* Take effect of the command */ - PLAY_SERVICE = 0x44, /* Play start or Play stop */ - TUNER_STATUS = 0x45, - TUNE_PROP_DVBT = 0x46, - ERR_RATE_STATS = 0x47, - TUNER_BER_RATE = 0x48, - - SCAN_CAPS = 0x50, - SCAN_SETUP = 0x51, - SCAN_SERVICE = 0x52, - SCAN_STATS = 0x53, - - PID_SET = 0x58, - PID_UNSET = 0x59, - PID_LIST = 0x5a, - - IRD_CAP = 0x60, - IRD_MODE_SEL = 0x61, - IRD_SETUP = 0x62, - - PTM_MODE_CAP = 0x70, - PTM_MODE_SEL = 0x71, - PTM_SERVICE = 0x72, - TUNER_REG_SCRIPT = 0x73, - CMD_CHIP_RST = 0x74, -}; - -enum tlg_bw { - TLG_BW_5 = 5, - TLG_BW_6 = 6, - TLG_BW_7 = 7, - TLG_BW_8 = 8, - TLG_BW_12 = 12, - TLG_BW_15 = 15 -}; - -struct cmd_firmware_vers_s { - uint8_t fw_rev_major; - uint8_t fw_rev_minor; - uint16_t fw_patch; -}; -#endif /* VENDOR_CMD_H_ */ -- cgit v1.2.3 From 8f32df451f843df2ba88f9597a34b8dc3533dee7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2014 09:14:37 -0300 Subject: [media] vino/saa7191: remove deprecated drivers These drivers haven't been tested in a long, long time. The hardware is ancient and hopelessly obsolete. These drivers also need to be converted to newer media frameworks but due to the lack of hardware that's going to be impossible. So these drivers are a prime candidate for removal. If someone is interested in working on these drivers to prevent their removal, then please contact the linux-media mailinglist. These drivers are already deprecated, so now remove them altogether. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 2 - drivers/staging/media/vino/Kconfig | 24 - drivers/staging/media/vino/Makefile | 3 - drivers/staging/media/vino/indycam.c | 378 --- drivers/staging/media/vino/indycam.h | 93 - drivers/staging/media/vino/saa7191.c | 649 ----- drivers/staging/media/vino/saa7191.h | 245 -- drivers/staging/media/vino/vino.c | 4345 ---------------------------------- drivers/staging/media/vino/vino.h | 138 -- 10 files changed, 5879 deletions(-) delete mode 100644 drivers/staging/media/vino/Kconfig delete mode 100644 drivers/staging/media/vino/Makefile delete mode 100644 drivers/staging/media/vino/indycam.c delete mode 100644 drivers/staging/media/vino/indycam.h delete mode 100644 drivers/staging/media/vino/saa7191.c delete mode 100644 drivers/staging/media/vino/saa7191.h delete mode 100644 drivers/staging/media/vino/vino.c delete mode 100644 drivers/staging/media/vino/vino.h (limited to 'drivers') diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 61e4acb1e4ae..e633204b9685 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -35,8 +35,6 @@ source "drivers/staging/media/omap4iss/Kconfig" source "drivers/staging/media/parport/Kconfig" -source "drivers/staging/media/vino/Kconfig" - # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index b7bda1057f54..7edb567b2de6 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -7,5 +7,3 @@ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_DVB_MN88473) += mn88473/ obj-y += parport/ -obj-y += vino/ - diff --git a/drivers/staging/media/vino/Kconfig b/drivers/staging/media/vino/Kconfig deleted file mode 100644 index 03700dadafd8..000000000000 --- a/drivers/staging/media/vino/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -config VIDEO_VINO - tristate "SGI Vino Video For Linux (Deprecated)" - depends on I2C && SGI_IP22 && VIDEO_V4L2 - select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT - help - Say Y here to build in support for the Vino video input system found - on SGI Indy machines. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - -config VIDEO_SAA7191 - tristate "Philips SAA7191 video decoder (Deprecated)" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7191 video decoder. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called saa7191. diff --git a/drivers/staging/media/vino/Makefile b/drivers/staging/media/vino/Makefile deleted file mode 100644 index 914c2513687c..000000000000 --- a/drivers/staging/media/vino/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_VIDEO_VINO) += indycam.o -obj-$(CONFIG_VIDEO_VINO) += vino.o -obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o diff --git a/drivers/staging/media/vino/indycam.c b/drivers/staging/media/vino/indycam.c deleted file mode 100644 index f1d192bbcb4c..000000000000 --- a/drivers/staging/media/vino/indycam.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * indycam.c - Silicon Graphics IndyCam digital camera driver - * - * Copyright (C) 2003 Ladislav Michl - * Copyright (C) 2004,2005 Mikael Nousiainen - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* IndyCam decodes stream of photons into digital image representation ;-) */ -#include -#include -#include - -#include "indycam.h" - -#define INDYCAM_MODULE_VERSION "0.0.5" - -MODULE_DESCRIPTION("SGI IndyCam driver"); -MODULE_VERSION(INDYCAM_MODULE_VERSION); -MODULE_AUTHOR("Mikael Nousiainen "); -MODULE_LICENSE("GPL"); - - -// #define INDYCAM_DEBUG - -#ifdef INDYCAM_DEBUG -#define dprintk(x...) printk("IndyCam: " x); -#define indycam_regdump(client) indycam_regdump_debug(client) -#else -#define dprintk(x...) -#define indycam_regdump(client) -#endif - -struct indycam { - 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 */ - INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ - 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ - INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ - INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */ - INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */ - INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */ -}; - -/* IndyCam register handling */ - -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) { - dprintk("indycam_read_reg(): " - "skipping write-only register %d\n", reg); - *value = 0; - return 0; - } - - ret = i2c_smbus_read_byte_data(client, reg); - - if (ret < 0) { - printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " - "register = 0x%02x\n", reg); - return ret; - } - - *value = (u8)ret; - - return 0; -} - -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) { - dprintk("indycam_write_reg(): " - "skipping read-only register %d\n", reg); - return 0; - } - - dprintk("Writing Reg %d = 0x%02x\n", reg, value); - err = i2c_smbus_write_byte_data(client, reg, value); - - if (err) { - printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " - "register = 0x%02x, value = 0x%02x\n", reg, value); - } - return err; -} - -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(sd, reg + i, data[i]); - if (err) - return err; - } - - return 0; -} - -/* Helper functions */ - -#ifdef INDYCAM_DEBUG -static void indycam_regdump_debug(struct v4l2_subdev *sd) -{ - int i; - u8 val; - - for (i = 0; i < 9; i++) { - indycam_read_reg(sd, i, &val); - dprintk("Reg %d = 0x%02x\n", i, val); - } -} -#endif - -static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - 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(sd, INDYCAM_REG_CONTROL, ®); - if (ret) - return -EIO; - 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 V4L2_CID_EXPOSURE: - 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(sd, INDYCAM_REG_GAIN, ®); - if (ret) - return -EIO; - ctrl->value = (s32)reg; - break; - case V4L2_CID_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(sd, INDYCAM_REG_BLUE_BALANCE, ®); - if (ret) - return -EIO; - ctrl->value = (s32)reg; - break; - case INDYCAM_CONTROL_RED_SATURATION: - 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(sd, - INDYCAM_REG_BLUE_SATURATION, ®); - if (ret) - return -EIO; - ctrl->value = (s32)reg; - break; - case V4L2_CID_GAMMA: - if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_read_reg(sd, - INDYCAM_REG_GAMMA, ®); - if (ret) - return -EIO; - ctrl->value = (s32)reg; - } else { - ctrl->value = INDYCAM_GAMMA_DEFAULT; - } - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - 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(sd, INDYCAM_REG_CONTROL, ®); - if (ret) - break; - - if (ctrl->id == V4L2_CID_AUTOGAIN) { - if (ctrl->value) - reg |= INDYCAM_CONTROL_AGCENA; - else - reg &= ~INDYCAM_CONTROL_AGCENA; - } else { - if (ctrl->value) - reg |= INDYCAM_CONTROL_AWBCTL; - else - reg &= ~INDYCAM_CONTROL_AWBCTL; - } - - 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(sd, INDYCAM_REG_SHUTTER, reg); - break; - case V4L2_CID_GAIN: - ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE, - ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE, - ctrl->value); - break; - case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION, - ctrl->value); - break; - case INDYCAM_CONTROL_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(sd, INDYCAM_REG_GAMMA, - ctrl->value); - } - break; - default: - ret = -EINVAL; - } - - return ret; -} - -/* I2C-interface */ - -/* ----------------------------------------------------------------------- */ - -static const struct v4l2_subdev_core_ops indycam_core_ops = { - .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); - - camera = kzalloc(sizeof(struct indycam), GFP_KERNEL); - if (!camera) - return -ENOMEM; - - sd = &camera->sd; - v4l2_i2c_subdev_init(sd, client, &indycam_ops); - - camera->version = i2c_smbus_read_byte_data(client, - INDYCAM_REG_VERSION); - if (camera->version != CAMERA_VERSION_INDY && - camera->version != CAMERA_VERSION_MOOSE) { - kfree(camera); - return -ENODEV; - } - - printk(KERN_INFO "IndyCam v%d.%d detected\n", - INDYCAM_VERSION_MAJOR(camera->version), - INDYCAM_VERSION_MINOR(camera->version)); - - indycam_regdump(sd); - - // initialize - 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(sd); - - // white balance - 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"); - kfree(camera); - return -EIO; - } - - indycam_regdump(sd); - - printk(KERN_INFO "IndyCam initialized\n"); - - return 0; -} - -static int indycam_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - - v4l2_device_unregister_subdev(sd); - kfree(to_indycam(sd)); - return 0; -} - -static const struct i2c_device_id indycam_id[] = { - { "indycam", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, indycam_id); - -static struct i2c_driver indycam_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "indycam", - }, - .probe = indycam_probe, - .remove = indycam_remove, - .id_table = indycam_id, -}; - -module_i2c_driver(indycam_driver); diff --git a/drivers/staging/media/vino/indycam.h b/drivers/staging/media/vino/indycam.h deleted file mode 100644 index 881f21c474c4..000000000000 --- a/drivers/staging/media/vino/indycam.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * indycam.h - Silicon Graphics IndyCam digital camera driver - * - * Copyright (C) 2003 Ladislav Michl - * Copyright (C) 2004,2005 Mikael Nousiainen - * - * 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. - */ - -#ifndef _INDYCAM_H_ -#define _INDYCAM_H_ - -/* I2C address for the Guinness Camera */ -#define INDYCAM_ADDR 0x56 - -/* Camera version */ -#define CAMERA_VERSION_INDY 0x10 /* v1.0 */ -#define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */ -#define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4) -#define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) - -/* Register bus addresses */ -#define INDYCAM_REG_CONTROL 0x00 -#define INDYCAM_REG_SHUTTER 0x01 -#define INDYCAM_REG_GAIN 0x02 -#define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */ -#define INDYCAM_REG_RED_BALANCE 0x04 -#define INDYCAM_REG_BLUE_BALANCE 0x05 -#define INDYCAM_REG_RED_SATURATION 0x06 -#define INDYCAM_REG_BLUE_SATURATION 0x07 -#define INDYCAM_REG_GAMMA 0x08 -#define INDYCAM_REG_VERSION 0x0e /* read-only */ -#define INDYCAM_REG_RESET 0x0f /* write-only */ - -#define INDYCAM_REG_LED 0x46 -#define INDYCAM_REG_ORIENTATION 0x47 -#define INDYCAM_REG_BUTTON 0x48 - -/* Field definitions of registers */ -#define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ -#define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */ - /* 2-3 are reserved */ -#define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */ - -#define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */ -#define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */ -#define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */ -#define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */ -#define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */ -#define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */ -#define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */ -#define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */ -#define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */ - -#define INDYCAM_LED_ACTIVE 0x10 -#define INDYCAM_LED_INACTIVE 0x30 -#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 -#define INDYCAM_BUTTON_RELEASED 0x10 - -/* Values for controls */ -#define INDYCAM_SHUTTER_MIN 0x00 -#define INDYCAM_SHUTTER_MAX 0xff -#define INDYCAM_GAIN_MIN 0x00 -#define INDYCAM_GAIN_MAX 0xff -#define INDYCAM_RED_BALANCE_MIN 0x00 -#define INDYCAM_RED_BALANCE_MAX 0xff -#define INDYCAM_BLUE_BALANCE_MIN 0x00 -#define INDYCAM_BLUE_BALANCE_MAX 0xff -#define INDYCAM_RED_SATURATION_MIN 0x00 -#define INDYCAM_RED_SATURATION_MAX 0xff -#define INDYCAM_BLUE_SATURATION_MIN 0x00 -#define INDYCAM_BLUE_SATURATION_MAX 0xff -#define INDYCAM_GAMMA_MIN 0x00 -#define INDYCAM_GAMMA_MAX 0xff - -#define INDYCAM_AGC_DEFAULT 1 -#define INDYCAM_AWB_DEFAULT 0 -#define INDYCAM_SHUTTER_DEFAULT 0xff -#define INDYCAM_GAIN_DEFAULT 0x80 -#define INDYCAM_RED_BALANCE_DEFAULT 0x18 -#define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 -#define INDYCAM_RED_SATURATION_DEFAULT 0x80 -#define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 -#define INDYCAM_GAMMA_DEFAULT 0x80 - -/* Driver interface definitions */ - -#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0) -#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1) - -#endif diff --git a/drivers/staging/media/vino/saa7191.c b/drivers/staging/media/vino/saa7191.c deleted file mode 100644 index 8e9699268a63..000000000000 --- a/drivers/staging/media/vino/saa7191.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * saa7191.c - Philips SAA7191 video decoder driver - * - * Copyright (C) 2003 Ladislav Michl - * Copyright (C) 2004,2005 Mikael Nousiainen - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "saa7191.h" - -#define SAA7191_MODULE_VERSION "0.0.5" - -MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); -MODULE_VERSION(SAA7191_MODULE_VERSION); -MODULE_AUTHOR("Mikael Nousiainen "); -MODULE_LICENSE("GPL"); - - -// #define SAA7191_DEBUG - -#ifdef SAA7191_DEBUG -#define dprintk(x...) printk("SAA7191: " x); -#else -#define dprintk(x...) -#endif - -#define SAA7191_SYNC_COUNT 30 -#define SAA7191_SYNC_DELAY 100 /* milliseconds */ - -struct saa7191 { - struct v4l2_subdev sd; - - /* the register values are stored here as the actual - * I2C-registers are write-only */ - u8 reg[25]; - - int input; - 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 */ - - 0x50, /* (0x50) SAA7191_REG_IDEL */ - - /* 50 Hz signal timing */ - 0x30, /* (0x30) SAA7191_REG_HSYB */ - 0x00, /* (0x00) SAA7191_REG_HSYS */ - 0xe8, /* (0xe8) SAA7191_REG_HCLB */ - 0xb6, /* (0xb6) SAA7191_REG_HCLS */ - 0xf4, /* (0xf4) SAA7191_REG_HPHI */ - - /* control */ - SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */ - 0x00, /* (0x00) SAA7191_REG_HUEC */ - 0xf8, /* (0xf8) SAA7191_REG_CKTQ */ - 0xf8, /* (0xf8) SAA7191_REG_CKTS */ - 0x90, /* (0x90) SAA7191_REG_PLSE */ - 0x90, /* (0x90) SAA7191_REG_SESE */ - 0x00, /* (0x00) SAA7191_REG_GAIN */ - SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC - * - not SECAM, - * slow time constant */ - SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS - | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK - * - chroma from CVBS, GPSW1 & 2 off */ - SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS - | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3 - * - automatic field detection */ - 0x00, /* (0x00) SAA7191_REG_CTL4 */ - 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */ - 0x00, /* unused */ - 0x00, /* unused */ - - /* 60 Hz signal timing */ - 0x34, /* (0x34) SAA7191_REG_HS6B */ - 0x0a, /* (0x0a) SAA7191_REG_HS6S */ - 0xf4, /* (0xf4) SAA7191_REG_HC6B */ - 0xce, /* (0xce) SAA7191_REG_HC6S */ - 0xf4, /* (0xf4) SAA7191_REG_HP6I */ -}; - -/* SAA7191 register handling */ - -static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg) -{ - return to_saa7191(sd)->reg[reg]; -} - -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); - if (ret < 0) { - printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n"); - return ret; - } - - return 0; -} - - -static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 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 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; - - for (i = 0; i < (length - 1); i++) { - decoder->reg[data[0] + i] = data[i + 1]; - } - - ret = i2c_master_send(client, data, length); - if (ret < 0) { - printk(KERN_ERR "SAA7191: saa7191_write_block(): " - "write failed\n"); - return ret; - } - - return 0; -} - -/* Helper functions */ - -static int saa7191_s_routing(struct v4l2_subdev *sd, - u32 input, u32 output, u32 config) -{ - 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) { - case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ - iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 - | SAA7191_IOCK_GPSW2); - /* Chrominance trap active */ - luma &= ~SAA7191_LUMA_BYPS; - break; - case SAA7191_INPUT_SVIDEO: /* Set S-Video input */ - iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2; - /* Chrominance trap bypassed */ - luma |= SAA7191_LUMA_BYPS; - break; - default: - return -EINVAL; - } - - err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma); - if (err) - return -EIO; - err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock); - if (err) - return -EIO; - - decoder->input = input; - - return 0; -} - -static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) -{ - 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) { - stdc &= ~SAA7191_STDC_SECS; - ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); - chcv = SAA7191_CHCV_PAL; - } else if (norm & V4L2_STD_NTSC) { - stdc &= ~SAA7191_STDC_SECS; - ctl3 &= ~SAA7191_CTL3_AUFD; - ctl3 |= SAA7191_CTL3_FSEL; - chcv = SAA7191_CHCV_NTSC; - } else if (norm & V4L2_STD_SECAM) { - stdc |= SAA7191_STDC_SECS; - ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); - chcv = SAA7191_CHCV_PAL; - } else { - return -EINVAL; - } - - err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); - if (err) - return -EIO; - err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); - if (err) - return -EIO; - err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv); - if (err) - return -EIO; - - decoder->norm = norm; - - dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, - stdc, chcv); - dprintk("norm: %llx\n", norm); - - return 0; -} - -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(sd, status)) - return -EIO; - - if (((*status) & SAA7191_STATUS_HLCK) == 0) { - dprintk("Signal found\n"); - return 0; - } - - msleep(SAA7191_SYNC_DELAY); - } - - dprintk("No signal\n"); - - return -EBUSY; -} - -static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) -{ - 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; - - 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); - - err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); - if (err) { - err = -EIO; - goto out; - } - err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); - if (err) { - err = -EIO; - goto out; - } - - ctl3 |= SAA7191_CTL3_AUFD; - err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); - if (err) { - err = -EIO; - goto out; - } - - msleep(SAA7191_SYNC_DELAY); - - err = saa7191_wait_for_signal(sd, &status); - if (err) - goto out; - - if (status & SAA7191_STATUS_FIDT) { - /* 60Hz signal -> NTSC */ - dprintk("60Hz signal: NTSC\n"); - *norm &= V4L2_STD_NTSC; - return 0; - } - - /* 50Hz signal */ - dprintk("50Hz signal: Trying PAL...\n"); - - /* try PAL first */ - err = saa7191_s_std(sd, V4L2_STD_PAL); - if (err) - goto out; - - msleep(SAA7191_SYNC_DELAY); - - err = saa7191_wait_for_signal(sd, &status); - if (err) - goto out; - - /* not 50Hz ? */ - if (status & SAA7191_STATUS_FIDT) { - dprintk("No 50Hz signal\n"); - saa7191_s_std(sd, old_norm); - *norm = V4L2_STD_UNKNOWN; - return 0; - } - - if (status & SAA7191_STATUS_CODE) { - dprintk("PAL\n"); - *norm &= V4L2_STD_PAL; - return saa7191_s_std(sd, old_norm); - } - - dprintk("No color detected with PAL - Trying SECAM...\n"); - - /* no color detected ? -> try SECAM */ - err = saa7191_s_std(sd, V4L2_STD_SECAM); - if (err) - goto out; - - msleep(SAA7191_SYNC_DELAY); - - err = saa7191_wait_for_signal(sd, &status); - if (err) - goto out; - - /* not 50Hz ? */ - if (status & SAA7191_STATUS_FIDT) { - dprintk("No 50Hz signal\n"); - *norm = V4L2_STD_UNKNOWN; - goto out; - } - - if (status & SAA7191_STATUS_CODE) { - /* Color detected -> SECAM */ - dprintk("SECAM\n"); - *norm &= V4L2_STD_SECAM; - return saa7191_s_std(sd, old_norm); - } - - dprintk("No color detected with SECAM - Going back to PAL.\n"); - *norm = V4L2_STD_UNKNOWN; - -out: - return saa7191_s_std(sd, old_norm); -} - -static int saa7191_autodetect_norm(struct v4l2_subdev *sd) -{ - u8 status; - - dprintk("SAA7191 signal auto-detection...\n"); - - dprintk("Reading status...\n"); - - if (saa7191_read_status(sd, &status)) - return -EIO; - - dprintk("Checking for signal...\n"); - - /* no signal ? */ - if (status & SAA7191_STATUS_HLCK) { - dprintk("No signal\n"); - return -EBUSY; - } - - dprintk("Signal found\n"); - - if (status & SAA7191_STATUS_FIDT) { - /* 60hz signal -> NTSC */ - dprintk("NTSC\n"); - return saa7191_s_std(sd, V4L2_STD_NTSC); - } else { - /* 50hz signal -> PAL */ - dprintk("PAL\n"); - return saa7191_s_std(sd, V4L2_STD_PAL); - } -} - -static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - u8 reg; - int ret = 0; - - switch (ctrl->id) { - case SAA7191_CONTROL_BANDPASS: - case SAA7191_CONTROL_BANDPASS_WEIGHT: - case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); - switch (ctrl->id) { - case SAA7191_CONTROL_BANDPASS: - ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) - >> SAA7191_LUMA_BPSS_SHIFT; - break; - case SAA7191_CONTROL_BANDPASS_WEIGHT: - ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK) - >> SAA7191_LUMA_APER_SHIFT; - break; - case SAA7191_CONTROL_CORING: - ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK) - >> SAA7191_LUMA_CORI_SHIFT; - break; - } - break; - case SAA7191_CONTROL_FORCE_COLOUR: - case SAA7191_CONTROL_CHROMA_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 - ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) - >> SAA7191_GAIN_LFIS_SHIFT; - break; - case V4L2_CID_HUE: - reg = saa7191_read_reg(sd, SAA7191_REG_HUEC); - if (reg < 0x80) - reg += 0x80; - else - reg -= 0x80; - ctrl->value = (s32)reg; - break; - case SAA7191_CONTROL_VTRC: - 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(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(sd, SAA7191_REG_CTL4); - ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) - >> SAA7191_CTL4_VNOI_SHIFT; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - u8 reg; - int ret = 0; - - switch (ctrl->id) { - case SAA7191_CONTROL_BANDPASS: - case SAA7191_CONTROL_BANDPASS_WEIGHT: - case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); - switch (ctrl->id) { - case SAA7191_CONTROL_BANDPASS: - reg &= ~SAA7191_LUMA_BPSS_MASK; - reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) - & SAA7191_LUMA_BPSS_MASK; - break; - case SAA7191_CONTROL_BANDPASS_WEIGHT: - reg &= ~SAA7191_LUMA_APER_MASK; - reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT) - & SAA7191_LUMA_APER_MASK; - break; - case SAA7191_CONTROL_CORING: - reg &= ~SAA7191_LUMA_CORI_MASK; - reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT) - & SAA7191_LUMA_CORI_MASK; - break; - } - ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg); - break; - case SAA7191_CONTROL_FORCE_COLOUR: - case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); - if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { - if (ctrl->value) - reg |= SAA7191_GAIN_COLO; - else - reg &= ~SAA7191_GAIN_COLO; - } else { - reg &= ~SAA7191_GAIN_LFIS_MASK; - reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) - & SAA7191_GAIN_LFIS_MASK; - } - ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg); - break; - case V4L2_CID_HUE: - reg = ctrl->value & 0xff; - if (reg < 0x80) - reg += 0x80; - else - reg -= 0x80; - ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg); - break; - case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(sd, SAA7191_REG_STDC); - if (ctrl->value) - reg |= SAA7191_STDC_VTRC; - else - reg &= ~SAA7191_STDC_VTRC; - 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(sd, SAA7191_REG_CTL3); - reg &= ~SAA7191_CTL3_YDEL_MASK; - reg |= (value << SAA7191_CTL3_YDEL_SHIFT) - & SAA7191_CTL3_YDEL_MASK; - ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg); - break; - } - case SAA7191_CONTROL_VNR: - 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(sd, SAA7191_REG_CTL4, reg); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -/* I2C-interface */ - -static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) -{ - u8 status_reg; - int res = V4L2_IN_ST_NO_SIGNAL; - - 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; -} - - -/* ----------------------------------------------------------------------- */ - -static const struct v4l2_subdev_core_ops saa7191_core_ops = { - .g_ctrl = saa7191_g_ctrl, - .s_ctrl = saa7191_s_ctrl, -}; - -static const struct v4l2_subdev_video_ops saa7191_video_ops = { - .s_std = saa7191_s_std, - .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); - - decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); - if (!decoder) - return -ENOMEM; - - sd = &decoder->sd; - v4l2_i2c_subdev_init(sd, client, &saa7191_ops); - - err = saa7191_write_block(sd, sizeof(initseq), initseq); - if (err) { - printk(KERN_ERR "SAA7191 initialization failed\n"); - return err; - } - - printk(KERN_INFO "SAA7191 initialized\n"); - - decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = V4L2_STD_PAL; - - err = saa7191_autodetect_norm(sd); - if (err && (err != -EBUSY)) - printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); - - return 0; -} - -static int saa7191_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - - v4l2_device_unregister_subdev(sd); - return 0; -} - -static const struct i2c_device_id saa7191_id[] = { - { "saa7191", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, saa7191_id); - -static struct i2c_driver saa7191_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "saa7191", - }, - .probe = saa7191_probe, - .remove = saa7191_remove, - .id_table = saa7191_id, -}; - -module_i2c_driver(saa7191_driver); diff --git a/drivers/staging/media/vino/saa7191.h b/drivers/staging/media/vino/saa7191.h deleted file mode 100644 index 803c74d6066f..000000000000 --- a/drivers/staging/media/vino/saa7191.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * saa7191.h - Philips SAA7191 video decoder driver - * - * Copyright (C) 2003 Ladislav Michl - * Copyright (C) 2004,2005 Mikael Nousiainen - * - * 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. - */ - -#ifndef _SAA7191_H_ -#define _SAA7191_H_ - -/* Philips SAA7191 DMSD I2C bus address */ -#define SAA7191_ADDR 0x8a - -/* Register subaddresses. */ -#define SAA7191_REG_IDEL 0x00 -#define SAA7191_REG_HSYB 0x01 -#define SAA7191_REG_HSYS 0x02 -#define SAA7191_REG_HCLB 0x03 -#define SAA7191_REG_HCLS 0x04 -#define SAA7191_REG_HPHI 0x05 -#define SAA7191_REG_LUMA 0x06 -#define SAA7191_REG_HUEC 0x07 -#define SAA7191_REG_CKTQ 0x08 /* bits 3-7 */ -#define SAA7191_REG_CKTS 0x09 /* bits 3-7 */ -#define SAA7191_REG_PLSE 0x0a -#define SAA7191_REG_SESE 0x0b -#define SAA7191_REG_GAIN 0x0c -#define SAA7191_REG_STDC 0x0d -#define SAA7191_REG_IOCK 0x0e -#define SAA7191_REG_CTL3 0x0f -#define SAA7191_REG_CTL4 0x10 -#define SAA7191_REG_CHCV 0x11 -#define SAA7191_REG_HS6B 0x14 -#define SAA7191_REG_HS6S 0x15 -#define SAA7191_REG_HC6B 0x16 -#define SAA7191_REG_HC6S 0x17 -#define SAA7191_REG_HP6I 0x18 -#define SAA7191_REG_STATUS 0xff /* not really a subaddress */ - -/* Status Register definitions */ -#define SAA7191_STATUS_CODE 0x01 /* color detected flag */ -#define SAA7191_STATUS_FIDT 0x20 /* signal type 50/60 Hz */ -#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked(1)/locked(0) */ -#define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */ - -/* Luminance Control Register definitions */ -/* input mode select bit: - * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */ -#define SAA7191_LUMA_BYPS 0x80 -/* pre-filter (only when chrominance trap is active) */ -#define SAA7191_LUMA_PREF 0x40 -/* aperture bandpass to select different characteristics with maximums - * (bits 4-5) */ -#define SAA7191_LUMA_BPSS_MASK 0x30 -#define SAA7191_LUMA_BPSS_SHIFT 4 -#define SAA7191_LUMA_BPSS_3 0x30 -#define SAA7191_LUMA_BPSS_2 0x20 -#define SAA7191_LUMA_BPSS_1 0x10 -#define SAA7191_LUMA_BPSS_0 0x00 -/* coring range for high frequency components according to 8-bit luminance - * (bits 2-3) - * 0=coring off, n= (+-)n LSB */ -#define SAA7191_LUMA_CORI_MASK 0x0c -#define SAA7191_LUMA_CORI_SHIFT 2 -#define SAA7191_LUMA_CORI_3 0x0c -#define SAA7191_LUMA_CORI_2 0x08 -#define SAA7191_LUMA_CORI_1 0x04 -#define SAA7191_LUMA_CORI_0 0x00 -/* aperture bandpass filter weights high frequency components of luminance - * signal (bits 0-1) - * 0=factor 0, 1=0.25, 2=0.5, 3=1 */ -#define SAA7191_LUMA_APER_MASK 0x03 -#define SAA7191_LUMA_APER_SHIFT 0 -#define SAA7191_LUMA_APER_3 0x03 -#define SAA7191_LUMA_APER_2 0x02 -#define SAA7191_LUMA_APER_1 0x01 -#define SAA7191_LUMA_APER_0 0x00 - -/* Chrominance Gain Control Settings Register definitions */ -/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */ -#define SAA7191_GAIN_COLO 0x80 -/* chrominance gain control (AGC filter) - * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */ -#define SAA7191_GAIN_LFIS_MASK 0x60 -#define SAA7191_GAIN_LFIS_SHIFT 5 -#define SAA7191_GAIN_LFIS_3 0x60 -#define SAA7191_GAIN_LFIS_2 0x40 -#define SAA7191_GAIN_LFIS_1 0x20 -#define SAA7191_GAIN_LFIS_0 0x00 - -/* Standard/Mode Control Register definitions */ -/* tv/vtr mode bit: 0=TV mode (slow time constant), - * 1=VTR mode (fast time constant) */ -#define SAA7191_STDC_VTRC 0x80 -/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs) - * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */ -#define SAA7191_STDC_NFEN 0x08 -/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */ -#define SAA7191_STDC_HRMV 0x04 -/* general purpose switch 0 - * (not used with VINO afaik) */ -#define SAA7191_STDC_GPSW0 0x02 -/* SECAM mode bit: 0=other standards, 1=SECAM */ -#define SAA7191_STDC_SECS 0x01 - -/* I/O and Clock Control Register definitions */ -/* horizontal clock PLL: 0=PLL closed, - * 1=PLL circuit open and horizontal freq fixed */ -#define SAA7191_IOCK_HPLL 0x80 -/* colour-difference output enable (outputs UV0-UV7) */ -#define SAA7191_IOCK_OEDC 0x40 -/* H-sync output enable */ -#define SAA7191_IOCK_OEHS 0x20 -/* V-sync output enable */ -#define SAA7191_IOCK_OEVS 0x10 -/* luminance output enable (outputs Y0-Y7) */ -#define SAA7191_IOCK_OEDY 0x08 -/* S-VHS bit (chrominance from CVBS or from chrominance input): - * 0=controlled by BYPS-bit, 1=from chrominance input */ -#define SAA7191_IOCK_CHRS 0x04 -/* general purpose switch 2 - * VINO-specific: 0=used with CVBS, 1=used with S-Video */ -#define SAA7191_IOCK_GPSW2 0x02 -/* general purpose switch 1 */ -/* VINO-specific: 0=always, 1=not used!*/ -#define SAA7191_IOCK_GPSW1 0x01 - -/* Miscellaneous Control #1 Register definitions */ -/* automatic field detection (50/60Hz standard) */ -#define SAA7191_CTL3_AUFD 0x80 -/* field select: (if AUFD=0) - * 0=50Hz (625 lines), 1=60Hz (525 lines) */ -#define SAA7191_CTL3_FSEL 0x40 -/* SECAM cross-colour reduction enable */ -#define SAA7191_CTL3_SXCR 0x20 -/* sync and clamping pulse enable (HCL and HSY outputs) */ -#define SAA7191_CTL3_SCEN 0x10 -/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */ -#define SAA7191_CTL3_OFTS 0x08 -/* luminance delay compensation - * 0=0*2/LLC, 1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC, - * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC - * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */ -#define SAA7191_CTL3_YDEL_MASK 0x07 -#define SAA7191_CTL3_YDEL_SHIFT 0 -#define SAA7191_CTL3_YDEL2 0x04 -#define SAA7191_CTL3_YDEL1 0x02 -#define SAA7191_CTL3_YDEL0 0x01 - -/* Miscellaneous Control #2 Register definitions */ -/* select HREF position - * 0=normal, HREF is matched to YUV output port, - * 1=HREF is matched to CVBS input port */ -#define SAA7191_CTL4_HRFS 0x04 -/* vertical noise reduction - * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */ -#define SAA7191_CTL4_VNOI_MASK 0x03 -#define SAA7191_CTL4_VNOI_SHIFT 0 -#define SAA7191_CTL4_VNOI_3 0x03 -#define SAA7191_CTL4_VNOI_2 0x02 -#define SAA7191_CTL4_VNOI_1 0x01 -#define SAA7191_CTL4_VNOI_0 0x00 - -/* Chrominance Gain Control Register definitions - * - for QAM-modulated input signals, effects output amplitude - * (SECAM gain fixed) - * (nominal values for UV CCIR level) */ -#define SAA7191_CHCV_NTSC 0x2c -#define SAA7191_CHCV_PAL 0x59 - -/* Driver interface definitions */ -#define SAA7191_INPUT_COMPOSITE 0 -#define SAA7191_INPUT_SVIDEO 1 - -#define SAA7191_NORM_PAL 1 -#define SAA7191_NORM_NTSC 2 -#define SAA7191_NORM_SECAM 3 - -struct saa7191_status { - /* 0=no signal, 1=signal detected */ - int signal; - /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */ - int signal_60hz; - /* 0=no color detected, 1=color detected */ - int color; - - /* current SAA7191_INPUT_ */ - int input; - /* current SAA7191_NORM_ */ - int norm; -}; - -#define SAA7191_BANDPASS_MIN 0x00 -#define SAA7191_BANDPASS_MAX 0x03 -#define SAA7191_BANDPASS_DEFAULT 0x00 - -#define SAA7191_BANDPASS_WEIGHT_MIN 0x00 -#define SAA7191_BANDPASS_WEIGHT_MAX 0x03 -#define SAA7191_BANDPASS_WEIGHT_DEFAULT 0x01 - -#define SAA7191_CORING_MIN 0x00 -#define SAA7191_CORING_MAX 0x03 -#define SAA7191_CORING_DEFAULT 0x00 - -#define SAA7191_HUE_MIN 0x00 -#define SAA7191_HUE_MAX 0xff -#define SAA7191_HUE_DEFAULT 0x80 - -#define SAA7191_VTRC_MIN 0x00 -#define SAA7191_VTRC_MAX 0x01 -#define SAA7191_VTRC_DEFAULT 0x00 - -#define SAA7191_FORCE_COLOUR_MIN 0x00 -#define SAA7191_FORCE_COLOUR_MAX 0x01 -#define SAA7191_FORCE_COLOUR_DEFAULT 0x00 - -#define SAA7191_CHROMA_GAIN_MIN 0x00 -#define SAA7191_CHROMA_GAIN_MAX 0x03 -#define SAA7191_CHROMA_GAIN_DEFAULT 0x00 - -#define SAA7191_LUMA_DELAY_MIN -0x04 -#define SAA7191_LUMA_DELAY_MAX 0x03 -#define SAA7191_LUMA_DELAY_DEFAULT 0x01 - -#define SAA7191_VNR_MIN 0x00 -#define SAA7191_VNR_MAX 0x03 -#define SAA7191_VNR_DEFAULT 0x00 - -#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) - -#endif diff --git a/drivers/staging/media/vino/vino.c b/drivers/staging/media/vino/vino.c deleted file mode 100644 index 2c85357f774d..000000000000 --- a/drivers/staging/media/vino/vino.c +++ /dev/null @@ -1,4345 +0,0 @@ -/* - * Driver for the VINO (Video In No Out) system found in SGI Indys. - * - * This file is subject to the terms and conditions of the GNU General Public - * License version 2 as published by the Free Software Foundation. - * - * Copyright (C) 2004,2005 Mikael Nousiainen - * - * 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. - */ - -/* - * TODO: - * - remove "mark pages reserved-hacks" from memory allocation code - * and implement fault() - * - check decimation, calculating and reporting image size when - * using decimation - * - implement read(), user mode buffers and overlay (?) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "vino.h" -#include "saa7191.h" -#include "indycam.h" - -/* Uncomment the following line to get lots and lots of (mostly useless) - * debug info. - * Note that the debug output also slows down the driver significantly */ -// #define VINO_DEBUG -// #define VINO_DEBUG_INT - -#define VINO_MODULE_VERSION "0.0.7" - -MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); -MODULE_VERSION(VINO_MODULE_VERSION); -MODULE_AUTHOR("Mikael Nousiainen "); -MODULE_LICENSE("GPL"); - -#ifdef VINO_DEBUG -#define dprintk(x...) printk("VINO: " x); -#else -#define dprintk(x...) -#endif - -#define VINO_NO_CHANNEL 0 -#define VINO_CHANNEL_A 1 -#define VINO_CHANNEL_B 2 - -#define VINO_PAL_WIDTH 768 -#define VINO_PAL_HEIGHT 576 -#define VINO_NTSC_WIDTH 640 -#define VINO_NTSC_HEIGHT 480 - -#define VINO_MIN_WIDTH 32 -#define VINO_MIN_HEIGHT 32 - -#define VINO_CLIPPING_START_ODD_D1 1 -#define VINO_CLIPPING_START_ODD_PAL 15 -#define VINO_CLIPPING_START_ODD_NTSC 12 - -#define VINO_CLIPPING_START_EVEN_D1 2 -#define VINO_CLIPPING_START_EVEN_PAL 15 -#define VINO_CLIPPING_START_EVEN_NTSC 12 - -#define VINO_INPUT_CHANNEL_COUNT 3 - -/* the number is the index for vino_inputs */ -#define VINO_INPUT_NONE -1 -#define VINO_INPUT_COMPOSITE 0 -#define VINO_INPUT_SVIDEO 1 -#define VINO_INPUT_D1 2 - -#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE) - -#define VINO_FIFO_THRESHOLD_DEFAULT 16 - -#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \ - * VINO_PAL_HEIGHT * 4 \ - + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1)) - -#define VINO_FRAMEBUFFER_COUNT_MAX 8 - -#define VINO_FRAMEBUFFER_UNUSED 0 -#define VINO_FRAMEBUFFER_IN_USE 1 -#define VINO_FRAMEBUFFER_READY 2 - -#define VINO_QUEUE_ERROR -1 -#define VINO_QUEUE_MAGIC 0x20050125 - -#define VINO_MEMORY_NONE 0 -#define VINO_MEMORY_MMAP 1 -#define VINO_MEMORY_USERPTR 2 - -#define VINO_DUMMY_DESC_COUNT 4 -#define VINO_DESC_FETCH_DELAY 5 /* microseconds */ - -#define VINO_MAX_FRAME_SKIP_COUNT 128 - -/* the number is the index for vino_data_formats */ -#define VINO_DATA_FMT_NONE -1 -#define VINO_DATA_FMT_GREY 0 -#define VINO_DATA_FMT_RGB332 1 -#define VINO_DATA_FMT_RGB32 2 -#define VINO_DATA_FMT_YUV 3 - -#define VINO_DATA_FMT_COUNT 4 - -/* the number is the index for vino_data_norms */ -#define VINO_DATA_NORM_NONE -1 -#define VINO_DATA_NORM_NTSC 0 -#define VINO_DATA_NORM_PAL 1 -#define VINO_DATA_NORM_SECAM 2 -#define VINO_DATA_NORM_D1 3 - -#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 { - char *name; - v4l2_std_id std; -}; - -struct vino_clipping { - unsigned int left, right, top, bottom; -}; - -struct vino_data_format { - /* the description */ - char *description; - /* bytes per pixel */ - unsigned int bpp; - /* V4L2 fourcc code */ - __u32 pixelformat; - /* V4L2 colorspace (duh!) */ - enum v4l2_colorspace colorspace; -}; - -struct vino_data_norm { - char *description; - unsigned int width, height; - struct vino_clipping odd; - struct vino_clipping even; - - v4l2_std_id std; - unsigned int fps_min, fps_max; - __u32 framelines; -}; - -struct vino_descriptor_table { - /* the number of PAGE_SIZE sized pages in the buffer */ - unsigned int page_count; - /* virtual (kmalloc'd) pointers to the actual data - * (in PAGE_SIZE chunks, used with mmap streaming) */ - unsigned long *virtual; - - /* cpu address for the VINO descriptor table - * (contains DMA addresses, VINO_PAGE_SIZE chunks) */ - unsigned long *dma_cpu; - /* dma address for the VINO descriptor table - * (contains DMA addresses, VINO_PAGE_SIZE chunks) */ - dma_addr_t dma; -}; - -struct vino_framebuffer { - /* identifier nubmer */ - unsigned int id; - /* the length of the whole buffer */ - unsigned int size; - /* the length of actual data in buffer */ - unsigned int data_size; - /* the data format */ - unsigned int data_format; - /* the state of buffer data */ - unsigned int state; - /* is the buffer mapped in user space? */ - unsigned int map_count; - /* memory offset for mmap() */ - unsigned int offset; - /* frame counter */ - unsigned int frame_counter; - /* timestamp (written when image capture finishes) */ - struct timeval timestamp; - - struct vino_descriptor_table desc_table; - - spinlock_t state_lock; -}; - -struct vino_framebuffer_fifo { - unsigned int length; - - unsigned int used; - unsigned int head; - unsigned int tail; - - unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX]; -}; - -struct vino_framebuffer_queue { - unsigned int magic; - - /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */ - unsigned int type; - unsigned int length; - - /* data field of in and out contain index numbers for buffer */ - struct vino_framebuffer_fifo in; - struct vino_framebuffer_fifo out; - - struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX]; - - spinlock_t queue_lock; - struct mutex queue_mutex; - wait_queue_head_t frame_wait_queue; -}; - -struct vino_interrupt_data { - struct timeval timestamp; - unsigned int frame_counter; - unsigned int skip_count; - unsigned int skip; -}; - -struct vino_channel_settings { - unsigned int channel; - - int input; - unsigned int data_format; - unsigned int data_norm; - struct vino_clipping clipping; - unsigned int decimation; - unsigned int line_size; - unsigned int alpha; - unsigned int fps; - unsigned int framert_reg; - - unsigned int fifo_threshold; - - struct vino_framebuffer_queue fb_queue; - - /* number of the current field */ - unsigned int field; - - /* read in progress */ - int reading; - /* streaming is active */ - int streaming; - /* the driver is currently processing the queue */ - int capturing; - - struct mutex mutex; - spinlock_t capture_lock; - - unsigned int users; - - struct vino_interrupt_data int_data; - - /* V4L support */ - struct video_device *vdev; -}; - -struct vino_settings { - struct v4l2_device v4l2_dev; - struct vino_channel_settings a; - struct vino_channel_settings b; - - /* 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; - /* a lock for channel input changes */ - spinlock_t input_lock; - - unsigned long dummy_page; - struct vino_descriptor_table dummy_desc_table; -}; - -/* Module parameters */ - -/* - * Using vino_pixel_conversion the ABGR32-format pixels supplied - * by the VINO chip can be converted to more common formats - * like RGBA32 (or probably RGB24 in the future). This way we - * can give out data that can be specified correctly with - * the V4L2-definitions. - * - * The pixel format is specified as RGBA32 when no conversion - * is used. - * - * Note that this only affects the 32-bit bit depth. - * - * Use non-zero value to enable conversion. - */ -static int vino_pixel_conversion; - -module_param_named(pixelconv, vino_pixel_conversion, int, 0); - -MODULE_PARM_DESC(pixelconv, - "enable pixel conversion (non-zero value enables)"); - -/* Internal data structures */ - -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"; -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); - -DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A); -DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B); - -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, - } -}; - -static const struct vino_data_format vino_data_formats[] = { - { - .description = "8-bit greyscale", - .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? - .colorspace = V4L2_COLORSPACE_SMPTE170M, - } -}; - -static const struct vino_data_norm vino_data_norms[] = { - { - .description = "NTSC", - .std = V4L2_STD_NTSC, - .fps_min = 6, - .fps_max = 30, - .framelines = 525, - .width = VINO_NTSC_WIDTH, - .height = VINO_NTSC_HEIGHT, - .odd = { - .top = VINO_CLIPPING_START_ODD_NTSC, - .left = 0, - .bottom = VINO_CLIPPING_START_ODD_NTSC - + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, - }, - .even = { - .top = VINO_CLIPPING_START_EVEN_NTSC, - .left = 0, - .bottom = VINO_CLIPPING_START_EVEN_NTSC - + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, - }, - }, { - .description = "PAL", - .std = V4L2_STD_PAL, - .fps_min = 5, - .fps_max = 25, - .framelines = 625, - .width = VINO_PAL_WIDTH, - .height = VINO_PAL_HEIGHT, - .odd = { - .top = VINO_CLIPPING_START_ODD_PAL, - .left = 0, - .bottom = VINO_CLIPPING_START_ODD_PAL - + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, - }, - .even = { - .top = VINO_CLIPPING_START_EVEN_PAL, - .left = 0, - .bottom = VINO_CLIPPING_START_EVEN_PAL - + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, - }, - }, { - .description = "SECAM", - .std = V4L2_STD_SECAM, - .fps_min = 5, - .fps_max = 25, - .framelines = 625, - .width = VINO_PAL_WIDTH, - .height = VINO_PAL_HEIGHT, - .odd = { - .top = VINO_CLIPPING_START_ODD_PAL, - .left = 0, - .bottom = VINO_CLIPPING_START_ODD_PAL - + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, - }, - .even = { - .top = VINO_CLIPPING_START_EVEN_PAL, - .left = 0, - .bottom = VINO_CLIPPING_START_EVEN_PAL - + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, - }, - }, { - .description = "NTSC/D1", - .std = V4L2_STD_NTSC, - .fps_min = 6, - .fps_max = 30, - .framelines = 525, - .width = VINO_NTSC_WIDTH, - .height = VINO_NTSC_HEIGHT, - .odd = { - .top = VINO_CLIPPING_START_ODD_D1, - .left = 0, - .bottom = VINO_CLIPPING_START_ODD_D1 - + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, - }, - .even = { - .top = VINO_CLIPPING_START_EVEN_D1, - .left = 0, - .bottom = VINO_CLIPPING_START_EVEN_D1 - + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, - }, - } -}; - -#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9 - -struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Automatic Gain Control", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = INDYCAM_AGC_DEFAULT, - }, { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Automatic White Balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = INDYCAM_AWB_DEFAULT, - }, { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = INDYCAM_GAIN_MIN, - .maximum = INDYCAM_GAIN_MAX, - .step = 1, - .default_value = INDYCAM_GAIN_DEFAULT, - }, { - .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, - }, { - .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, - }, { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = INDYCAM_RED_BALANCE_MIN, - .maximum = INDYCAM_RED_BALANCE_MAX, - .step = 1, - .default_value = INDYCAM_RED_BALANCE_DEFAULT, - }, { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = INDYCAM_BLUE_BALANCE_MIN, - .maximum = INDYCAM_BLUE_BALANCE_MAX, - .step = 1, - .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, - }, { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Shutter Control", - .minimum = INDYCAM_SHUTTER_MIN, - .maximum = INDYCAM_SHUTTER_MAX, - .step = 1, - .default_value = INDYCAM_SHUTTER_DEFAULT, - }, { - .id = V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma", - .minimum = INDYCAM_GAMMA_MIN, - .maximum = INDYCAM_GAMMA_MAX, - .step = 1, - .default_value = INDYCAM_GAMMA_DEFAULT, - } -}; - -#define VINO_SAA7191_V4L2_CONTROL_COUNT 9 - -struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { - { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = SAA7191_HUE_MIN, - .maximum = SAA7191_HUE_MAX, - .step = 1, - .default_value = SAA7191_HUE_DEFAULT, - }, { - .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, - }, { - .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, - }, { - .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, - }, { - .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, - }, { - .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, - }, { - .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, - }, { - .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, - }, { - .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, - } -}; - -/* VINO framebuffer/DMA descriptor management */ - -static void vino_free_buffer_with_count(struct vino_framebuffer *fb, - unsigned int count) -{ - unsigned int i; - - dprintk("vino_free_buffer_with_count(): count = %d\n", count); - - for (i = 0; i < count; i++) { - ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); - dma_unmap_single(NULL, - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], - PAGE_SIZE, DMA_FROM_DEVICE); - free_page(fb->desc_table.virtual[i]); - } - - dma_free_coherent(NULL, - VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) * - sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu, - fb->desc_table.dma); - kfree(fb->desc_table.virtual); - - memset(fb, 0, sizeof(struct vino_framebuffer)); -} - -static void vino_free_buffer(struct vino_framebuffer *fb) -{ - vino_free_buffer_with_count(fb, fb->desc_table.page_count); -} - -static int vino_allocate_buffer(struct vino_framebuffer *fb, - unsigned int size) -{ - unsigned int count, i, j; - int ret = 0; - - dprintk("vino_allocate_buffer():\n"); - - if (size < 1) - return -EINVAL; - - memset(fb, 0, sizeof(struct vino_framebuffer)); - - count = ((size / PAGE_SIZE) + 4) & ~3; - - dprintk("vino_allocate_buffer(): size = %d, count = %d\n", - size, count); - - /* allocate memory for table with virtual (page) addresses */ - fb->desc_table.virtual = - kmalloc(count * sizeof(unsigned long), GFP_KERNEL); - if (!fb->desc_table.virtual) - return -ENOMEM; - - /* allocate memory for table with dma addresses - * (has space for four extra descriptors) */ - fb->desc_table.dma_cpu = - dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) * - sizeof(dma_addr_t), &fb->desc_table.dma, - GFP_KERNEL | GFP_DMA); - if (!fb->desc_table.dma_cpu) { - ret = -ENOMEM; - goto out_free_virtual; - } - - /* allocate pages for the buffer and acquire the according - * dma addresses */ - for (i = 0; i < count; i++) { - dma_addr_t dma_data_addr; - - fb->desc_table.virtual[i] = - get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!fb->desc_table.virtual[i]) { - ret = -ENOBUFS; - break; - } - - dma_data_addr = - dma_map_single(NULL, - (void *)fb->desc_table.virtual[i], - PAGE_SIZE, DMA_FROM_DEVICE); - - for (j = 0; j < VINO_PAGE_RATIO; j++) { - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] = - dma_data_addr + VINO_PAGE_SIZE * j; - } - - SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); - } - - /* page_count needs to be set anyway, because the descriptor table has - * been allocated according to this number */ - fb->desc_table.page_count = count; - - if (ret) { - /* the descriptor with index i doesn't contain - * a valid address yet */ - vino_free_buffer_with_count(fb, i); - return ret; - } - - //fb->size = size; - fb->size = count * PAGE_SIZE; - fb->data_format = VINO_DATA_FMT_NONE; - - /* set the dma stop-bit for the last (count+1)th descriptor */ - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP; - return 0; - - out_free_virtual: - kfree(fb->desc_table.virtual); - return ret; -} - -#if 0 -/* user buffers not fully implemented yet */ -static int vino_prepare_user_buffer(struct vino_framebuffer *fb, - void *user, - unsigned int size) -{ - unsigned int count, i, j; - int ret = 0; - - dprintk("vino_prepare_user_buffer():\n"); - - if (size < 1) - return -EINVAL; - - memset(fb, 0, sizeof(struct vino_framebuffer)); - - count = ((size / PAGE_SIZE)) & ~3; - - dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n", - size, count); - - /* allocate memory for table with virtual (page) addresses */ - fb->desc_table.virtual = (unsigned long *) - kmalloc(count * sizeof(unsigned long), GFP_KERNEL); - if (!fb->desc_table.virtual) - return -ENOMEM; - - /* allocate memory for table with dma addresses - * (has space for four extra descriptors) */ - fb->desc_table.dma_cpu = - dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) * - sizeof(dma_addr_t), &fb->desc_table.dma, - GFP_KERNEL | GFP_DMA); - if (!fb->desc_table.dma_cpu) { - ret = -ENOMEM; - goto out_free_virtual; - } - - /* allocate pages for the buffer and acquire the according - * dma addresses */ - for (i = 0; i < count; i++) { - dma_addr_t dma_data_addr; - - fb->desc_table.virtual[i] = - get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!fb->desc_table.virtual[i]) { - ret = -ENOBUFS; - break; - } - - dma_data_addr = - dma_map_single(NULL, - (void *)fb->desc_table.virtual[i], - PAGE_SIZE, DMA_FROM_DEVICE); - - for (j = 0; j < VINO_PAGE_RATIO; j++) { - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] = - dma_data_addr + VINO_PAGE_SIZE * j; - } - - SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); - } - - /* page_count needs to be set anyway, because the descriptor table has - * been allocated according to this number */ - fb->desc_table.page_count = count; - - if (ret) { - /* the descriptor with index i doesn't contain - * a valid address yet */ - vino_free_buffer_with_count(fb, i); - return ret; - } - - //fb->size = size; - fb->size = count * PAGE_SIZE; - - /* set the dma stop-bit for the last (count+1)th descriptor */ - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP; - return 0; - - out_free_virtual: - kfree(fb->desc_table.virtual); - return ret; -} -#endif - -static void vino_sync_buffer(struct vino_framebuffer *fb) -{ - int i; - - dprintk("vino_sync_buffer():\n"); - - for (i = 0; i < fb->desc_table.page_count; i++) - dma_sync_single_for_cpu(NULL, - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], - PAGE_SIZE, DMA_FROM_DEVICE); -} - -/* Framebuffer fifo functions (need to be locked externally) */ - -static inline void vino_fifo_init(struct vino_framebuffer_fifo *f, - unsigned int length) -{ - f->length = 0; - f->used = 0; - f->head = 0; - f->tail = 0; - - if (length > VINO_FRAMEBUFFER_COUNT_MAX) - length = VINO_FRAMEBUFFER_COUNT_MAX; - - f->length = length; -} - -/* returns true/false */ -static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f, - unsigned int id) -{ - unsigned int i; - - for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) { - if (f->data[i] == id) - return 1; - } - - return 0; -} - -#if 0 -/* returns true/false */ -static inline int vino_fifo_full(struct vino_framebuffer_fifo *f) -{ - return (f->used == f->length); -} -#endif - -static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) -{ - return f->used; -} - -static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id) -{ - if (id >= f->length) { - return VINO_QUEUE_ERROR; - } - - if (vino_fifo_has_id(f, id)) { - return VINO_QUEUE_ERROR; - } - - if (f->used < f->length) { - f->data[f->tail] = id; - f->tail = (f->tail + 1) % f->length; - f->used++; - } else { - return VINO_QUEUE_ERROR; - } - - return 0; -} - -static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id) -{ - if (f->used > 0) { - *id = f->data[f->head]; - } else { - return VINO_QUEUE_ERROR; - } - - return 0; -} - -static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id) -{ - if (f->used > 0) { - *id = f->data[f->head]; - f->head = (f->head + 1) % f->length; - f->used--; - } else { - return VINO_QUEUE_ERROR; - } - - return 0; -} - -/* Framebuffer queue functions */ - -/* execute with queue_lock locked */ -static void vino_queue_free_with_count(struct vino_framebuffer_queue *q, - unsigned int length) -{ - unsigned int i; - - q->length = 0; - memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo)); - memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo)); - for (i = 0; i < length; i++) { - dprintk("vino_queue_free_with_count(): freeing buffer %d\n", - i); - vino_free_buffer(q->buffer[i]); - kfree(q->buffer[i]); - } - - q->type = VINO_MEMORY_NONE; - q->magic = 0; -} - -static void vino_queue_free(struct vino_framebuffer_queue *q) -{ - dprintk("vino_queue_free():\n"); - - if (q->magic != VINO_QUEUE_MAGIC) - return; - if (q->type != VINO_MEMORY_MMAP) - return; - - mutex_lock(&q->queue_mutex); - - vino_queue_free_with_count(q, q->length); - - mutex_unlock(&q->queue_mutex); -} - -static int vino_queue_init(struct vino_framebuffer_queue *q, - unsigned int *length) -{ - unsigned int i; - int ret = 0; - - dprintk("vino_queue_init(): length = %d\n", *length); - - if (q->magic == VINO_QUEUE_MAGIC) { - dprintk("vino_queue_init(): queue already initialized!\n"); - return -EINVAL; - } - - if (q->type != VINO_MEMORY_NONE) { - dprintk("vino_queue_init(): queue already initialized!\n"); - return -EINVAL; - } - - if (*length < 1) - return -EINVAL; - - mutex_lock(&q->queue_mutex); - - if (*length > VINO_FRAMEBUFFER_COUNT_MAX) - *length = VINO_FRAMEBUFFER_COUNT_MAX; - - q->length = 0; - - for (i = 0; i < *length; i++) { - dprintk("vino_queue_init(): allocating buffer %d\n", i); - q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer), - GFP_KERNEL); - if (!q->buffer[i]) { - dprintk("vino_queue_init(): kmalloc() failed\n"); - ret = -ENOMEM; - break; - } - - ret = vino_allocate_buffer(q->buffer[i], - VINO_FRAMEBUFFER_SIZE); - if (ret) { - kfree(q->buffer[i]); - dprintk("vino_queue_init(): " - "vino_allocate_buffer() failed\n"); - break; - } - - q->buffer[i]->id = i; - if (i > 0) { - q->buffer[i]->offset = q->buffer[i - 1]->offset + - q->buffer[i - 1]->size; - } else { - q->buffer[i]->offset = 0; - } - - spin_lock_init(&q->buffer[i]->state_lock); - - dprintk("vino_queue_init(): buffer = %d, offset = %d, " - "size = %d\n", i, q->buffer[i]->offset, - q->buffer[i]->size); - } - - if (ret) { - vino_queue_free_with_count(q, i); - *length = 0; - } else { - q->length = *length; - vino_fifo_init(&q->in, q->length); - vino_fifo_init(&q->out, q->length); - q->type = VINO_MEMORY_MMAP; - q->magic = VINO_QUEUE_MAGIC; - } - - mutex_unlock(&q->queue_mutex); - - return ret; -} - -static struct vino_framebuffer *vino_queue_add(struct - vino_framebuffer_queue *q, - unsigned int id) -{ - struct vino_framebuffer *ret = NULL; - unsigned int total; - unsigned long flags; - - dprintk("vino_queue_add(): id = %d\n", id); - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - if (id >= q->length) - goto out; - - /* not needed?: if (vino_fifo_full(&q->out)) { - goto out; - }*/ - /* check that outgoing queue isn't already full - * (or that it won't become full) */ - total = vino_fifo_get_used(&q->in) + - vino_fifo_get_used(&q->out); - if (total >= q->length) - goto out; - - if (vino_fifo_enqueue(&q->in, id)) - goto out; - - ret = q->buffer[id]; - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static struct vino_framebuffer *vino_queue_transfer(struct - vino_framebuffer_queue *q) -{ - struct vino_framebuffer *ret = NULL; - struct vino_framebuffer *fb; - int id; - unsigned long flags; - - dprintk("vino_queue_transfer():\n"); - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - // now this actually removes an entry from the incoming queue - if (vino_fifo_dequeue(&q->in, &id)) { - goto out; - } - - dprintk("vino_queue_transfer(): id = %d\n", id); - fb = q->buffer[id]; - - // we have already checked that the outgoing queue is not full, but... - if (vino_fifo_enqueue(&q->out, id)) { - printk(KERN_ERR "vino_queue_transfer(): " - "outgoing queue is full, this shouldn't happen!\n"); - goto out; - } - - ret = fb; -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -/* returns true/false */ -static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q, - unsigned int id) -{ - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - ret = vino_fifo_has_id(&q->in, id); - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -/* returns true/false */ -static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q, - unsigned int id) -{ - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - ret = vino_fifo_has_id(&q->out, id); - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static int vino_queue_get_incoming(struct vino_framebuffer_queue *q, - unsigned int *used) -{ - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return VINO_QUEUE_ERROR; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) { - ret = VINO_QUEUE_ERROR; - goto out; - } - - *used = vino_fifo_get_used(&q->in); - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q, - unsigned int *used) -{ - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return VINO_QUEUE_ERROR; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) { - ret = VINO_QUEUE_ERROR; - goto out; - } - - *used = vino_fifo_get_used(&q->out); - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -#if 0 -static int vino_queue_get_total(struct vino_framebuffer_queue *q, - unsigned int *total) -{ - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return VINO_QUEUE_ERROR; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) { - ret = VINO_QUEUE_ERROR; - goto out; - } - - *total = vino_fifo_get_used(&q->in) + - vino_fifo_get_used(&q->out); - -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} -#endif - -static struct vino_framebuffer *vino_queue_peek(struct - vino_framebuffer_queue *q, - unsigned int *id) -{ - struct vino_framebuffer *ret = NULL; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - if (vino_fifo_peek(&q->in, id)) { - goto out; - } - - ret = q->buffer[*id]; -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static struct vino_framebuffer *vino_queue_remove(struct - vino_framebuffer_queue *q, - unsigned int *id) -{ - struct vino_framebuffer *ret = NULL; - unsigned long flags; - dprintk("vino_queue_remove():\n"); - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - if (vino_fifo_dequeue(&q->out, id)) { - goto out; - } - - dprintk("vino_queue_remove(): id = %d\n", *id); - ret = q->buffer[*id]; -out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static struct -vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q, - unsigned int id) -{ - struct vino_framebuffer *ret = NULL; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - - if (q->length == 0) - goto out; - - if (id >= q->length) - goto out; - - ret = q->buffer[id]; - out: - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q) -{ - unsigned int length = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return length; - } - - spin_lock_irqsave(&q->queue_lock, flags); - length = q->length; - spin_unlock_irqrestore(&q->queue_lock, flags); - - return length; -} - -static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q) -{ - unsigned int i; - int ret = 0; - unsigned long flags; - - if (q->magic != VINO_QUEUE_MAGIC) { - return ret; - } - - spin_lock_irqsave(&q->queue_lock, flags); - for (i = 0; i < q->length; i++) { - if (q->buffer[i]->map_count > 0) { - ret = 1; - break; - } - } - spin_unlock_irqrestore(&q->queue_lock, flags); - - return ret; -} - -/* VINO functions */ - -/* execute with input_lock locked */ -static void vino_update_line_size(struct vino_channel_settings *vcs) -{ - unsigned int w = vcs->clipping.right - vcs->clipping.left; - unsigned int d = vcs->decimation; - unsigned int bpp = vino_data_formats[vcs->data_format].bpp; - unsigned int lsize; - - dprintk("update_line_size(): before: w = %d, d = %d, " - "line_size = %d\n", w, d, vcs->line_size); - - /* line size must be multiple of 8 bytes */ - lsize = (bpp * (w / d)) & ~7; - w = (lsize / bpp) * d; - - vcs->clipping.right = vcs->clipping.left + w; - vcs->line_size = lsize; - - dprintk("update_line_size(): after: w = %d, d = %d, " - "line_size = %d\n", w, d, vcs->line_size); -} - -/* execute with input_lock locked */ -static void vino_set_clipping(struct vino_channel_settings *vcs, - unsigned int x, unsigned int y, - unsigned int w, unsigned int h) -{ - unsigned int maxwidth, maxheight; - unsigned int d; - - maxwidth = vino_data_norms[vcs->data_norm].width; - maxheight = vino_data_norms[vcs->data_norm].height; - d = vcs->decimation; - - y &= ~1; /* odd/even fields */ - - if (x > maxwidth) { - x = 0; - } - if (y > maxheight) { - y = 0; - } - - if (((w / d) < VINO_MIN_WIDTH) - || ((h / d) < VINO_MIN_HEIGHT)) { - w = VINO_MIN_WIDTH * d; - h = VINO_MIN_HEIGHT * d; - } - - if ((x + w) > maxwidth) { - w = maxwidth - x; - if ((w / d) < VINO_MIN_WIDTH) - x = maxwidth - VINO_MIN_WIDTH * d; - } - if ((y + h) > maxheight) { - h = maxheight - y; - if ((h / d) < VINO_MIN_HEIGHT) - y = maxheight - VINO_MIN_HEIGHT * d; - } - - vcs->clipping.left = x; - vcs->clipping.top = y; - vcs->clipping.right = x + w; - vcs->clipping.bottom = y + h; - - vino_update_line_size(vcs); - - dprintk("clipping %d, %d, %d, %d / %d - %d\n", - vcs->clipping.left, vcs->clipping.top, vcs->clipping.right, - vcs->clipping.bottom, vcs->decimation, vcs->line_size); -} - -/* execute with input_lock locked */ -static inline void vino_set_default_clipping(struct vino_channel_settings *vcs) -{ - vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, - vino_data_norms[vcs->data_norm].height); -} - -/* execute with input_lock locked */ -static void vino_set_scaling(struct vino_channel_settings *vcs, - unsigned int w, unsigned int h) -{ - unsigned int x, y, curw, curh, d; - - x = vcs->clipping.left; - y = vcs->clipping.top; - curw = vcs->clipping.right - vcs->clipping.left; - curh = vcs->clipping.bottom - vcs->clipping.top; - - d = max(curw / w, curh / h); - - dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n", - w, h, curw, curh, d); - - if (d < 1) { - d = 1; - } else if (d > 8) { - d = 8; - } - - vcs->decimation = d; - vino_set_clipping(vcs, x, y, w * d, h * d); - - dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left, - vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom, - vcs->decimation, vcs->line_size); -} - -/* execute with input_lock locked */ -static inline void vino_set_default_scaling(struct vino_channel_settings *vcs) -{ - vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, - vcs->clipping.bottom - vcs->clipping.top); -} - -/* execute with input_lock locked */ -static void vino_set_framerate(struct vino_channel_settings *vcs, - unsigned int fps) -{ - unsigned int mask; - - switch (vcs->data_norm) { - case VINO_DATA_NORM_NTSC: - case VINO_DATA_NORM_D1: - fps = (unsigned int)(fps / 6) * 6; // FIXME: round! - - if (fps < vino_data_norms[vcs->data_norm].fps_min) - fps = vino_data_norms[vcs->data_norm].fps_min; - if (fps > vino_data_norms[vcs->data_norm].fps_max) - fps = vino_data_norms[vcs->data_norm].fps_max; - - switch (fps) { - case 6: - mask = 0x003; - break; - case 12: - mask = 0x0c3; - break; - case 18: - mask = 0x333; - break; - case 24: - mask = 0x3ff; - break; - case 30: - mask = 0xfff; - break; - default: - mask = VINO_FRAMERT_FULL; - } - vcs->framert_reg = VINO_FRAMERT_RT(mask); - break; - case VINO_DATA_NORM_PAL: - case VINO_DATA_NORM_SECAM: - fps = (unsigned int)(fps / 5) * 5; // FIXME: round! - - if (fps < vino_data_norms[vcs->data_norm].fps_min) - fps = vino_data_norms[vcs->data_norm].fps_min; - if (fps > vino_data_norms[vcs->data_norm].fps_max) - fps = vino_data_norms[vcs->data_norm].fps_max; - - switch (fps) { - case 5: - mask = 0x003; - break; - case 10: - mask = 0x0c3; - break; - case 15: - mask = 0x333; - break; - case 20: - mask = 0x0ff; - break; - case 25: - mask = 0x3ff; - break; - default: - mask = VINO_FRAMERT_FULL; - } - vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL; - break; - } - - vcs->fps = fps; -} - -/* execute with input_lock locked */ -static inline void vino_set_default_framerate(struct - vino_channel_settings *vcs) -{ - 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", - .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) - */ -static int vino_dma_setup(struct vino_channel_settings *vcs, - struct vino_framebuffer *fb) -{ - u32 ctrl, intr; - struct sgi_vino_channel *ch; - const struct vino_data_norm *norm; - - dprintk("vino_dma_setup():\n"); - - vcs->field = 0; - fb->frame_counter = 0; - - ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b; - norm = &vino_data_norms[vcs->data_norm]; - - ch->page_index = 0; - ch->line_count = 0; - - /* VINO line size register is set 8 bytes less than actual */ - ch->line_size = vcs->line_size - 8; - - /* let VINO know where to transfer data */ - ch->start_desc_tbl = fb->desc_table.dma; - ch->next_4_desc = fb->desc_table.dma; - - /* give vino time to fetch the first four descriptors, 5 usec - * should be more than enough time */ - udelay(VINO_DESC_FETCH_DELAY); - - dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n", - ch->start_desc_tbl, ch->next_4_desc); - - /* set the alpha register */ - ch->alpha = vcs->alpha; - - /* set clipping registers */ - ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) | - VINO_CLIP_EVEN(norm->even.top + - vcs->clipping.top / 2) | - VINO_CLIP_X(vcs->clipping.left); - ch->clip_end = VINO_CLIP_ODD(norm->odd.top + - vcs->clipping.bottom / 2 - 1) | - VINO_CLIP_EVEN(norm->even.top + - vcs->clipping.bottom / 2 - 1) | - VINO_CLIP_X(vcs->clipping.right); - - /* set the size of actual content in the buffer (DECIMATION !) */ - fb->data_size = ((vcs->clipping.right - vcs->clipping.left) / - vcs->decimation) * - ((vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation) * - vino_data_formats[vcs->data_format].bpp; - - ch->frame_rate = vcs->framert_reg; - - ctrl = vino->control; - intr = vino->intr_status; - - if (vcs->channel == VINO_CHANNEL_A) { - /* All interrupt conditions for this channel was cleared - * so clear the interrupt status register and enable - * interrupts */ - intr &= ~VINO_INTSTAT_A; - ctrl |= VINO_CTRL_A_INT; - - /* enable synchronization */ - ctrl |= VINO_CTRL_A_SYNC_ENBL; - - /* enable frame assembly */ - ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL; - - /* set decimation used */ - if (vcs->decimation < 2) - ctrl &= ~VINO_CTRL_A_DEC_ENBL; - else { - ctrl |= VINO_CTRL_A_DEC_ENBL; - ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK; - ctrl |= (vcs->decimation - 1) << - VINO_CTRL_A_DEC_SCALE_SHIFT; - } - - /* select input interface */ - if (vcs->input == VINO_INPUT_D1) - ctrl |= VINO_CTRL_A_SELECT; - else - ctrl &= ~VINO_CTRL_A_SELECT; - - /* palette */ - ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB | - VINO_CTRL_A_DITHER); - } else { - intr &= ~VINO_INTSTAT_B; - ctrl |= VINO_CTRL_B_INT; - - ctrl |= VINO_CTRL_B_SYNC_ENBL; - ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL; - - if (vcs->decimation < 2) - ctrl &= ~VINO_CTRL_B_DEC_ENBL; - else { - ctrl |= VINO_CTRL_B_DEC_ENBL; - ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK; - ctrl |= (vcs->decimation - 1) << - VINO_CTRL_B_DEC_SCALE_SHIFT; - - } - if (vcs->input == VINO_INPUT_D1) - ctrl |= VINO_CTRL_B_SELECT; - else - ctrl &= ~VINO_CTRL_B_SELECT; - - ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB | - VINO_CTRL_B_DITHER); - } - - /* set palette */ - fb->data_format = vcs->data_format; - - switch (vcs->data_format) { - case VINO_DATA_FMT_GREY: - ctrl |= (vcs->channel == VINO_CHANNEL_A) ? - VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY; - break; - case VINO_DATA_FMT_RGB32: - ctrl |= (vcs->channel == VINO_CHANNEL_A) ? - VINO_CTRL_A_RGB : VINO_CTRL_B_RGB; - break; - case VINO_DATA_FMT_YUV: - /* nothing needs to be done */ - break; - case VINO_DATA_FMT_RGB332: - ctrl |= (vcs->channel == VINO_CHANNEL_A) ? - VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER : - VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER; - break; - } - - vino->intr_status = intr; - vino->control = ctrl; - - return 0; -} - -/* (execute only with vino_lock locked) */ -static inline void vino_dma_start(struct vino_channel_settings *vcs) -{ - u32 ctrl = vino->control; - - dprintk("vino_dma_start():\n"); - ctrl |= (vcs->channel == VINO_CHANNEL_A) ? - VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL; - vino->control = ctrl; -} - -/* (execute only with vino_lock locked) */ -static inline void vino_dma_stop(struct vino_channel_settings *vcs) -{ - u32 ctrl = vino->control; - - ctrl &= (vcs->channel == VINO_CHANNEL_A) ? - ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL; - ctrl &= (vcs->channel == VINO_CHANNEL_A) ? - ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT; - vino->control = ctrl; - dprintk("vino_dma_stop():\n"); -} - -/* - * Load dummy page to descriptor registers. This prevents generating of - * spurious interrupts. (execute only with vino_lock locked) - */ -static void vino_clear_interrupt(struct vino_channel_settings *vcs) -{ - struct sgi_vino_channel *ch; - - ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b; - - ch->page_index = 0; - ch->line_count = 0; - - ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma; - ch->next_4_desc = vino_drvdata->dummy_desc_table.dma; - - udelay(VINO_DESC_FETCH_DELAY); - dprintk("channel %c clear interrupt condition\n", - (vcs->channel == VINO_CHANNEL_A) ? 'A':'B'); -} - -static int vino_capture(struct vino_channel_settings *vcs, - struct vino_framebuffer *fb) -{ - int err = 0; - unsigned long flags, flags2; - - spin_lock_irqsave(&fb->state_lock, flags); - - if (fb->state == VINO_FRAMEBUFFER_IN_USE) - err = -EBUSY; - fb->state = VINO_FRAMEBUFFER_IN_USE; - - spin_unlock_irqrestore(&fb->state_lock, flags); - - if (err) - return err; - - spin_lock_irqsave(&vino_drvdata->vino_lock, flags); - spin_lock_irqsave(&vino_drvdata->input_lock, flags2); - - vino_dma_setup(vcs, fb); - vino_dma_start(vcs); - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2); - spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); - - return err; -} - -static -struct vino_framebuffer *vino_capture_enqueue(struct - vino_channel_settings *vcs, - unsigned int index) -{ - struct vino_framebuffer *fb; - unsigned long flags; - - dprintk("vino_capture_enqueue():\n"); - - spin_lock_irqsave(&vcs->capture_lock, flags); - - fb = vino_queue_add(&vcs->fb_queue, index); - if (fb == NULL) { - dprintk("vino_capture_enqueue(): vino_queue_add() failed, " - "queue full?\n"); - goto out; - } -out: - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - return fb; -} - -static int vino_capture_next(struct vino_channel_settings *vcs, int start) -{ - struct vino_framebuffer *fb; - unsigned int incoming, id; - int err = 0; - unsigned long flags; - - dprintk("vino_capture_next():\n"); - - spin_lock_irqsave(&vcs->capture_lock, flags); - - if (start) { - /* start capture only if capture isn't in progress already */ - if (vcs->capturing) { - spin_unlock_irqrestore(&vcs->capture_lock, flags); - return 0; - } - - } else { - /* capture next frame: - * stop capture if capturing is not set */ - if (!vcs->capturing) { - spin_unlock_irqrestore(&vcs->capture_lock, flags); - return 0; - } - } - - err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); - if (err) { - dprintk("vino_capture_next(): vino_queue_get_incoming() " - "failed\n"); - err = -EINVAL; - goto out; - } - if (incoming == 0) { - dprintk("vino_capture_next(): no buffers available\n"); - goto out; - } - - fb = vino_queue_peek(&vcs->fb_queue, &id); - if (fb == NULL) { - dprintk("vino_capture_next(): vino_queue_peek() failed\n"); - err = -EINVAL; - goto out; - } - - if (start) { - vcs->capturing = 1; - } - - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - err = vino_capture(vcs, fb); - - return err; - -out: - vcs->capturing = 0; - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - return err; -} - -static inline int vino_is_capturing(struct vino_channel_settings *vcs) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&vcs->capture_lock, flags); - - ret = vcs->capturing; - - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - return ret; -} - -/* waits until a frame is captured */ -static int vino_wait_for_frame(struct vino_channel_settings *vcs) -{ - wait_queue_t wait; - int err = 0; - - dprintk("vino_wait_for_frame():\n"); - - init_waitqueue_entry(&wait, current); - /* add ourselves into wait queue */ - add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait); - - /* to ensure that schedule_timeout will return immediately - * if VINO interrupt was triggered meanwhile */ - schedule_timeout_interruptible(msecs_to_jiffies(100)); - - if (signal_pending(current)) - err = -EINTR; - - remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait); - - dprintk("vino_wait_for_frame(): waiting for frame %s\n", - err ? "failed" : "ok"); - - return err; -} - -/* the function assumes that PAGE_SIZE % 4 == 0 */ -static void vino_convert_to_rgba(struct vino_framebuffer *fb) { - unsigned char *pageptr; - unsigned int page, i; - unsigned char a; - - for (page = 0; page < fb->desc_table.page_count; page++) { - pageptr = (unsigned char *)fb->desc_table.virtual[page]; - - for (i = 0; i < PAGE_SIZE; i += 4) { - a = pageptr[0]; - pageptr[0] = pageptr[3]; - pageptr[1] = pageptr[2]; - pageptr[2] = pageptr[1]; - pageptr[3] = a; - pageptr += 4; - } - } -} - -/* checks if the buffer is in correct state and syncs data */ -static int vino_check_buffer(struct vino_channel_settings *vcs, - struct vino_framebuffer *fb) -{ - int err = 0; - unsigned long flags; - - dprintk("vino_check_buffer():\n"); - - spin_lock_irqsave(&fb->state_lock, flags); - switch (fb->state) { - case VINO_FRAMEBUFFER_IN_USE: - err = -EIO; - break; - case VINO_FRAMEBUFFER_READY: - vino_sync_buffer(fb); - fb->state = VINO_FRAMEBUFFER_UNUSED; - break; - default: - err = -EINVAL; - } - spin_unlock_irqrestore(&fb->state_lock, flags); - - if (!err) { - if (vino_pixel_conversion - && (fb->data_format == VINO_DATA_FMT_RGB32)) { - vino_convert_to_rgba(fb); - } - } else if (err && (err != -EINVAL)) { - dprintk("vino_check_buffer(): buffer not ready\n"); - - spin_lock_irqsave(&vino_drvdata->vino_lock, flags); - vino_dma_stop(vcs); - vino_clear_interrupt(vcs); - spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); - } - - return err; -} - -/* forcefully terminates capture */ -static void vino_capture_stop(struct vino_channel_settings *vcs) -{ - unsigned int incoming = 0, outgoing = 0, id; - unsigned long flags, flags2; - - dprintk("vino_capture_stop():\n"); - - spin_lock_irqsave(&vcs->capture_lock, flags); - - /* unset capturing to stop queue processing */ - vcs->capturing = 0; - - spin_lock_irqsave(&vino_drvdata->vino_lock, flags2); - - vino_dma_stop(vcs); - vino_clear_interrupt(vcs); - - spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2); - - /* remove all items from the queue */ - if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) { - dprintk("vino_capture_stop(): " - "vino_queue_get_incoming() failed\n"); - goto out; - } - while (incoming > 0) { - vino_queue_transfer(&vcs->fb_queue); - - if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) { - dprintk("vino_capture_stop(): " - "vino_queue_get_incoming() failed\n"); - goto out; - } - } - - if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { - dprintk("vino_capture_stop(): " - "vino_queue_get_outgoing() failed\n"); - goto out; - } - while (outgoing > 0) { - vino_queue_remove(&vcs->fb_queue, &id); - - if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { - dprintk("vino_capture_stop(): " - "vino_queue_get_outgoing() failed\n"); - goto out; - } - } - -out: - spin_unlock_irqrestore(&vcs->capture_lock, flags); -} - -#if 0 -static int vino_capture_failed(struct vino_channel_settings *vcs) -{ - struct vino_framebuffer *fb; - unsigned long flags; - unsigned int i; - int ret; - - dprintk("vino_capture_failed():\n"); - - spin_lock_irqsave(&vino_drvdata->vino_lock, flags); - - vino_dma_stop(vcs); - vino_clear_interrupt(vcs); - - spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); - - ret = vino_queue_get_incoming(&vcs->fb_queue, &i); - if (ret == VINO_QUEUE_ERROR) { - dprintk("vino_queue_get_incoming() failed\n"); - return -EINVAL; - } - if (i == 0) { - /* no buffers to process */ - return 0; - } - - fb = vino_queue_peek(&vcs->fb_queue, &i); - if (fb == NULL) { - dprintk("vino_queue_peek() failed\n"); - return -EINVAL; - } - - spin_lock_irqsave(&fb->state_lock, flags); - if (fb->state == VINO_FRAMEBUFFER_IN_USE) { - fb->state = VINO_FRAMEBUFFER_UNUSED; - vino_queue_transfer(&vcs->fb_queue); - vino_queue_remove(&vcs->fb_queue, &i); - /* we should actually discard the newest frame, - * but who cares ... */ - } - spin_unlock_irqrestore(&fb->state_lock, flags); - - return 0; -} -#endif - -static void vino_skip_frame(struct vino_channel_settings *vcs) -{ - struct vino_framebuffer *fb; - unsigned long flags; - unsigned int id; - - spin_lock_irqsave(&vcs->capture_lock, flags); - fb = vino_queue_peek(&vcs->fb_queue, &id); - if (!fb) { - spin_unlock_irqrestore(&vcs->capture_lock, flags); - dprintk("vino_skip_frame(): vino_queue_peek() failed!\n"); - return; - } - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - spin_lock_irqsave(&fb->state_lock, flags); - fb->state = VINO_FRAMEBUFFER_UNUSED; - spin_unlock_irqrestore(&fb->state_lock, flags); - - vino_capture_next(vcs, 0); -} - -static void vino_frame_done(struct vino_channel_settings *vcs) -{ - struct vino_framebuffer *fb; - unsigned long flags; - - spin_lock_irqsave(&vcs->capture_lock, flags); - fb = vino_queue_transfer(&vcs->fb_queue); - if (!fb) { - spin_unlock_irqrestore(&vcs->capture_lock, flags); - dprintk("vino_frame_done(): vino_queue_transfer() failed!\n"); - return; - } - spin_unlock_irqrestore(&vcs->capture_lock, flags); - - fb->frame_counter = vcs->int_data.frame_counter; - memcpy(&fb->timestamp, &vcs->int_data.timestamp, - sizeof(struct timeval)); - - spin_lock_irqsave(&fb->state_lock, flags); - if (fb->state == VINO_FRAMEBUFFER_IN_USE) - fb->state = VINO_FRAMEBUFFER_READY; - spin_unlock_irqrestore(&fb->state_lock, flags); - - wake_up(&vcs->fb_queue.frame_wait_queue); - - vino_capture_next(vcs, 0); -} - -static void vino_capture_tasklet(unsigned long channel) { - struct vino_channel_settings *vcs; - - vcs = (channel == VINO_CHANNEL_A) - ? &vino_drvdata->a : &vino_drvdata->b; - - if (vcs->int_data.skip) - vcs->int_data.skip_count++; - - if (vcs->int_data.skip && (vcs->int_data.skip_count - <= VINO_MAX_FRAME_SKIP_COUNT)) { - vino_skip_frame(vcs); - } else { - vcs->int_data.skip_count = 0; - vino_frame_done(vcs); - } -} - -static irqreturn_t vino_interrupt(int irq, void *dev_id) -{ - u32 ctrl, intr; - unsigned int fc_a, fc_b; - int handled_a = 0, skip_a = 0, done_a = 0; - int handled_b = 0, skip_b = 0, done_b = 0; - -#ifdef VINO_DEBUG_INT - int loop = 0; - unsigned int line_count = vino->a.line_count, - page_index = vino->a.page_index, - field_counter = vino->a.field_counter, - start_desc_tbl = vino->a.start_desc_tbl, - next_4_desc = vino->a.next_4_desc; - unsigned int line_count_2, - page_index_2, - field_counter_2, - start_desc_tbl_2, - next_4_desc_2; -#endif - - spin_lock(&vino_drvdata->vino_lock); - - while ((intr = vino->intr_status)) { - fc_a = vino->a.field_counter >> 1; - fc_b = vino->b.field_counter >> 1; - - /* handle error-interrupts in some special way ? - * --> skips frames */ - if (intr & VINO_INTSTAT_A) { - if (intr & VINO_INTSTAT_A_EOF) { - vino_drvdata->a.field++; - if (vino_drvdata->a.field > 1) { - vino_dma_stop(&vino_drvdata->a); - vino_clear_interrupt(&vino_drvdata->a); - vino_drvdata->a.field = 0; - done_a = 1; - } else { - if (vino->a.page_index - != vino_drvdata->a.line_size) { - vino->a.line_count = 0; - vino->a.page_index = - vino_drvdata-> - a.line_size; - vino->a.next_4_desc = - vino->a.start_desc_tbl; - } - } - dprintk("channel A end-of-field " - "interrupt: %04x\n", intr); - } else { - vino_dma_stop(&vino_drvdata->a); - vino_clear_interrupt(&vino_drvdata->a); - vino_drvdata->a.field = 0; - skip_a = 1; - dprintk("channel A error interrupt: %04x\n", - intr); - } - -#ifdef VINO_DEBUG_INT - line_count_2 = vino->a.line_count; - page_index_2 = vino->a.page_index; - field_counter_2 = vino->a.field_counter; - start_desc_tbl_2 = vino->a.start_desc_tbl; - next_4_desc_2 = vino->a.next_4_desc; - - printk("intr = %04x, loop = %d, field = %d\n", - intr, loop, vino_drvdata->a.field); - printk("1- line count = %04d, page index = %04d, " - "start = %08x, next = %08x\n" - " fieldc = %d, framec = %d\n", - line_count, page_index, start_desc_tbl, - next_4_desc, field_counter, fc_a); - printk("12-line count = %04d, page index = %04d, " - " start = %08x, next = %08x\n", - line_count_2, page_index_2, start_desc_tbl_2, - next_4_desc_2); - - if (done_a) - printk("\n"); -#endif - } - - if (intr & VINO_INTSTAT_B) { - if (intr & VINO_INTSTAT_B_EOF) { - vino_drvdata->b.field++; - if (vino_drvdata->b.field > 1) { - vino_dma_stop(&vino_drvdata->b); - vino_clear_interrupt(&vino_drvdata->b); - vino_drvdata->b.field = 0; - done_b = 1; - } - dprintk("channel B end-of-field " - "interrupt: %04x\n", intr); - } else { - vino_dma_stop(&vino_drvdata->b); - vino_clear_interrupt(&vino_drvdata->b); - vino_drvdata->b.field = 0; - skip_b = 1; - dprintk("channel B error interrupt: %04x\n", - intr); - } - } - - /* Always remember to clear interrupt status. - * Disable VINO interrupts while we do this. */ - ctrl = vino->control; - vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT); - vino->intr_status = ~intr; - vino->control = ctrl; - - spin_unlock(&vino_drvdata->vino_lock); - - if ((!handled_a) && (done_a || skip_a)) { - if (!skip_a) { - v4l2_get_timestamp( - &vino_drvdata->a.int_data.timestamp); - vino_drvdata->a.int_data.frame_counter = fc_a; - } - vino_drvdata->a.int_data.skip = skip_a; - - dprintk("channel A %s, interrupt: %d\n", - skip_a ? "skipping frame" : "frame done", - intr); - tasklet_hi_schedule(&vino_tasklet_a); - handled_a = 1; - } - - if ((!handled_b) && (done_b || skip_b)) { - if (!skip_b) { - v4l2_get_timestamp( - &vino_drvdata->b.int_data.timestamp); - vino_drvdata->b.int_data.frame_counter = fc_b; - } - vino_drvdata->b.int_data.skip = skip_b; - - dprintk("channel B %s, interrupt: %d\n", - skip_b ? "skipping frame" : "frame done", - intr); - tasklet_hi_schedule(&vino_tasklet_b); - handled_b = 1; - } - -#ifdef VINO_DEBUG_INT - loop++; -#endif - spin_lock(&vino_drvdata->vino_lock); - } - - spin_unlock(&vino_drvdata->vino_lock); - - return IRQ_HANDLED; -} - -/* VINO video input management */ - -static int vino_get_saa7191_input(int input) -{ - switch (input) { - case VINO_INPUT_COMPOSITE: - return SAA7191_INPUT_COMPOSITE; - case VINO_INPUT_SVIDEO: - return SAA7191_INPUT_SVIDEO; - default: - printk(KERN_ERR "VINO: vino_get_saa7191_input(): " - "invalid input!\n"); - return -1; - } -} - -/* execute with input_lock locked */ -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; - case VINO_INPUT_D1: - return vino_drvdata->camera_owner == vcs->channel; - default: - return 0; - } -} - -static int vino_acquire_input(struct vino_channel_settings *vcs) -{ - unsigned long flags; - int ret = 0; - - dprintk("vino_acquire_input():\n"); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - /* First try D1 and then SAA7191 */ - 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 - && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) { - int input; - int data_norm = 0; - v4l2_std_id norm; - - input = VINO_INPUT_COMPOSITE; - - ret = decoder_call(video, s_routing, - vino_get_saa7191_input(input), 0, 0); - if (ret) { - ret = -EINVAL; - goto out; - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - /* Don't hold spinlocks while auto-detecting norm - * as it may take a while... */ - - 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) - break; - } - if (data_norm == 3) - data_norm = VINO_DATA_NORM_PAL; - ret = decoder_call(video, s_std, norm); - } - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if (ret) { - ret = -EINVAL; - goto out; - } - - vino_drvdata->decoder_owner = vcs->channel; - - vcs->input = input; - vcs->data_norm = data_norm; - } else { - vcs->input = (vcs->channel == VINO_CHANNEL_A) ? - vino_drvdata->b.input : vino_drvdata->a.input; - vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ? - vino_drvdata->b.data_norm : vino_drvdata->a.data_norm; - } - - if (vcs->input == VINO_INPUT_NONE) { - ret = -ENODEV; - goto out; - } - - vino_set_default_clipping(vcs); - vino_set_default_scaling(vcs); - vino_set_default_framerate(vcs); - - dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name); - -out: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static int vino_set_input(struct vino_channel_settings *vcs, int input) -{ - struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? - &vino_drvdata->b : &vino_drvdata->a; - unsigned long flags; - int ret = 0; - - dprintk("vino_set_input():\n"); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if (vcs->input == input) - goto out; - - switch (input) { - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - if (!vino_drvdata->decoder) { - ret = -EINVAL; - goto out; - } - - if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) { - vino_drvdata->decoder_owner = vcs->channel; - } - - if (vino_drvdata->decoder_owner == vcs->channel) { - int data_norm = 0; - v4l2_std_id norm; - - ret = decoder_call(video, s_routing, - vino_get_saa7191_input(input), 0, 0); - if (ret) { - vino_drvdata->decoder_owner = VINO_NO_CHANNEL; - ret = -EINVAL; - goto out; - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - /* Don't hold spinlocks while auto-detecting norm - * as it may take a while... */ - - 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) - break; - } - if (data_norm == 3) - data_norm = VINO_DATA_NORM_PAL; - ret = decoder_call(video, s_std, norm); - } - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if (ret) { - vino_drvdata->decoder_owner = VINO_NO_CHANNEL; - ret = -EINVAL; - goto out; - } - - vcs->input = input; - vcs->data_norm = data_norm; - } else { - if (input != vcs2->input) { - ret = -EBUSY; - goto out; - } - - vcs->input = input; - vcs->data_norm = vcs2->data_norm; - } - - 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; - } else { - vino_drvdata->camera_owner = VINO_NO_CHANNEL; - } - } - break; - case VINO_INPUT_D1: - if (!vino_drvdata->camera) { - ret = -EINVAL; - goto out; - } - - if (vino_drvdata->camera_owner == VINO_NO_CHANNEL) - vino_drvdata->camera_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; - } else { - vino_drvdata->decoder_owner = VINO_NO_CHANNEL; - } - } - - vcs->input = input; - vcs->data_norm = VINO_DATA_NORM_D1; - break; - default: - ret = -EINVAL; - goto out; - } - - vino_set_default_clipping(vcs); - vino_set_default_scaling(vcs); - vino_set_default_framerate(vcs); - - dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name); - -out: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static void vino_release_input(struct vino_channel_settings *vcs) -{ - struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? - &vino_drvdata->b : &vino_drvdata->a; - unsigned long flags; - - dprintk("vino_release_input():\n"); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - /* 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 (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera_owner = vcs2->channel; - } else { - vino_drvdata->camera_owner = VINO_NO_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; - } else { - vino_drvdata->decoder_owner = VINO_NO_CHANNEL; - } - } - vcs->input = VINO_INPUT_NONE; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); -} - -/* execute with input_lock locked */ -static int vino_set_data_norm(struct vino_channel_settings *vcs, - unsigned int data_norm, - unsigned long *flags) -{ - int err = 0; - - if (data_norm == vcs->data_norm) - return 0; - - switch (vcs->input) { - case VINO_INPUT_D1: - /* only one "norm" supported */ - 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)) - return -EINVAL; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); - - /* Don't hold spinlocks while setting norm - * as it may take a while... */ - - norm = vino_data_norms[data_norm].std; - err = decoder_call(video, s_std, norm); - - spin_lock_irqsave(&vino_drvdata->input_lock, *flags); - - if (err) - goto out; - - vcs->data_norm = data_norm; - - vino_set_default_clipping(vcs); - vino_set_default_scaling(vcs); - vino_set_default_framerate(vcs); - break; - } - default: - return -EINVAL; - } - -out: - return err; -} - -/* V4L2 helper functions */ - -static int vino_find_data_format(__u32 pixelformat) -{ - int i; - - for (i = 0; i < VINO_DATA_FMT_COUNT; i++) { - if (vino_data_formats[i].pixelformat == pixelformat) - return i; - } - - return VINO_DATA_FMT_NONE; -} - -static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) -{ - int input = VINO_INPUT_NONE; - unsigned long flags; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (vino_drvdata->decoder && vino_drvdata->camera) { - switch (index) { - case 0: - input = VINO_INPUT_COMPOSITE; - break; - case 1: - input = VINO_INPUT_SVIDEO; - break; - case 2: - input = VINO_INPUT_D1; - break; - } - } else if (vino_drvdata->decoder) { - switch (index) { - case 0: - input = VINO_INPUT_COMPOSITE; - break; - case 1: - input = VINO_INPUT_SVIDEO; - break; - } - } else if (vino_drvdata->camera) { - switch (index) { - case 0: - input = VINO_INPUT_D1; - break; - } - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return input; -} - -/* execute with input_lock locked */ -static __u32 vino_find_input_index(struct vino_channel_settings *vcs) -{ - __u32 index = 0; - // FIXME: detect when no inputs available - - if (vino_drvdata->decoder && vino_drvdata->camera) { - switch (vcs->input) { - case VINO_INPUT_COMPOSITE: - index = 0; - break; - case VINO_INPUT_SVIDEO: - index = 1; - break; - case VINO_INPUT_D1: - index = 2; - break; - } - } else if (vino_drvdata->decoder) { - switch (vcs->input) { - case VINO_INPUT_COMPOSITE: - index = 0; - break; - case VINO_INPUT_SVIDEO: - index = 1; - break; - } - } else if (vino_drvdata->camera) { - switch (vcs->input) { - case VINO_INPUT_D1: - index = 0; - break; - } - } - - return index; -} - -/* V4L2 ioctls */ - -static int vino_querycap(struct file *file, void *__fh, - struct v4l2_capability *cap) -{ - memset(cap, 0, sizeof(struct v4l2_capability)); - - strcpy(cap->driver, vino_driver_name); - strcpy(cap->card, vino_driver_description); - strcpy(cap->bus_info, vino_bus_name); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -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_int_enum_input(vcs, index); - if (input == VINO_INPUT_NONE) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = vino_inputs[input].std; - strcpy(i->name, vino_inputs[input].name); - - if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) - decoder_call(video, g_input_status, &i->status); - return 0; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - input = vcs->input; - index = vino_find_input_index(vcs); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - dprintk("input = %d\n", input); - - if (input == VINO_INPUT_NONE) { - return -EINVAL; - } - - *i = index; - - return 0; -} - -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); - - input = vino_int_enum_input(vcs, i); - if (input == VINO_INPUT_NONE) - return -EINVAL; - - return vino_set_input(vcs, input); -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - switch (vcs->input) { - case VINO_INPUT_D1: - *std = vino_inputs[vcs->input].std; - break; - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: { - decoder_call(video, querystd, std); - break; - } - default: - err = -EINVAL; - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return err; -} - -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); - - *std = vino_data_norms[vcs->data_norm].std; - dprintk("current standard = %d\n", vcs->data_norm); - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return 0; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if (!vino_is_input_owner(vcs)) { - ret = -EBUSY; - goto out; - } - - /* check if the standard is valid for the current input */ - if (std & vino_inputs[vcs->input].std) { - dprintk("standard accepted\n"); - - /* change the video norm for SAA7191 - * and accept NTSC for D1 (do nothing) */ - - if (vcs->input == VINO_INPUT_D1) - goto out; - - if (std & V4L2_STD_PAL) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, - &flags); - } else if (std & V4L2_STD_NTSC) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC, - &flags); - } else if (std & V4L2_STD_SECAM) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM, - &flags); - } else { - ret = -EINVAL; - } - - if (ret) { - ret = -EINVAL; - } - } else { - ret = -EINVAL; - } - -out: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, - struct v4l2_fmtdesc *fd) -{ - dprintk("format index = %d\n", fd->index); - - if (fd->index >= VINO_DATA_FMT_COUNT) - return -EINVAL; - dprintk("format name = %s\n", vino_data_formats[fd->index].description); - - fd->pixelformat = vino_data_formats[fd->index].pixelformat; - strcpy(fd->description, vino_data_formats[fd->index].description); - return 0; -} - -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; - - 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); - - 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); - - 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->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; - - return 0; -} - -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; - - 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->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); - return 0; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - data_format = vino_find_data_format(pf->pixelformat); - - 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 must be set before clipping/scaling */ - vino_set_scaling(vcs, pf->width, pf->height); - - dprintk("data format = %s\n", - vino_data_formats[vcs->data_format].description); - - pf->width = vcs->clipping.right - vcs->clipping.left; - pf->height = vcs->clipping.bottom - vcs->clipping.top; - - 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); - return 0; -} - -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; - - switch (ccap->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - norm = &vino_data_norms[vcs->data_norm]; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - ccap->bounds.left = 0; - ccap->bounds.top = 0; - ccap->bounds.width = norm->width; - ccap->bounds.height = norm->height; - memcpy(&ccap->defrect, &ccap->bounds, - sizeof(struct v4l2_rect)); - - ccap->pixelaspect.numerator = 1; - ccap->pixelaspect.denominator = 1; - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } - - return 0; -} - -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) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - c->c.left = vcs->clipping.left; - c->c.top = vcs->clipping.top; - c->c.width = vcs->clipping.right - vcs->clipping.left; - c->c.height = vcs->clipping.bottom - vcs->clipping.top; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } - - return 0; -} - -static int vino_s_crop(struct file *file, void *__fh, - const struct v4l2_crop *c) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - unsigned long flags; - - switch (c->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - vino_set_clipping(vcs, c->c.left, c->c.top, - c->c.width, c->c.height); - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } - - return 0; -} - -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; - struct v4l2_captureparm *cp = &sp->parm.capture; - - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = 1; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - cp->timeperframe.denominator = vcs->fps; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - /* TODO: cp->readbuffers = xxx; */ - - return 0; -} - -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; - struct v4l2_captureparm *cp = &sp->parm.capture; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if ((cp->timeperframe.numerator == 0) || - (cp->timeperframe.denominator == 0)) { - /* reset framerate */ - vino_set_default_framerate(vcs); - } else { - vino_set_framerate(vcs, cp->timeperframe.denominator / - cp->timeperframe.numerator); - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return 0; -} - -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; - - /* TODO: check queue type */ - if (rb->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } - - dprintk("count = %d\n", rb->count); - if (rb->count > 0) { - if (vino_is_capturing(vcs)) { - dprintk("busy, capturing\n"); - return -EBUSY; - } - - if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { - dprintk("busy, buffers still mapped\n"); - return -EBUSY; - } else { - vcs->streaming = 0; - vino_queue_free(&vcs->fb_queue); - vino_queue_init(&vcs->fb_queue, &rb->count); - } - } else { - vcs->streaming = 0; - vino_capture_stop(vcs); - vino_queue_free(&vcs->fb_queue); - } - - return 0; -} - -static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, - struct vino_framebuffer *fb, - struct v4l2_buffer *b) -{ - if (vino_queue_outgoing_contains(&vcs->fb_queue, - fb->id)) { - b->flags &= ~V4L2_BUF_FLAG_QUEUED; - b->flags |= V4L2_BUF_FLAG_DONE; - } else if (vino_queue_incoming_contains(&vcs->fb_queue, - fb->id)) { - b->flags &= ~V4L2_BUF_FLAG_DONE; - b->flags |= V4L2_BUF_FLAG_QUEUED; - } else { - b->flags &= ~(V4L2_BUF_FLAG_DONE | - V4L2_BUF_FLAG_QUEUED); - } - - b->flags &= ~(V4L2_BUF_FLAG_TIMECODE); - - if (fb->map_count > 0) - b->flags |= V4L2_BUF_FLAG_MAPPED; - - b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK; - b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - - b->index = fb->id; - b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ? - V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; - b->m.offset = fb->offset; - b->bytesused = fb->data_size; - b->length = fb->size; - b->field = V4L2_FIELD_INTERLACED; - b->sequence = fb->frame_counter; - memcpy(&b->timestamp, &fb->timestamp, - sizeof(struct timeval)); - // b->input ? - - dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n", - fb->id, fb->size, fb->data_size, fb->offset); -} - -static int vino_querybuf(struct file *file, void *__fh, - struct v4l2_buffer *b) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - struct vino_framebuffer *fb; - - if (vcs->reading) - return -EBUSY; - - /* TODO: check queue type */ - if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { - dprintk("invalid index = %d\n", - b->index); - return -EINVAL; - } - - fb = vino_queue_get_buffer(&vcs->fb_queue, - b->index); - if (fb == NULL) { - dprintk("vino_queue_get_buffer() failed"); - return -EINVAL; - } - - vino_v4l2_get_buffer_status(vcs, fb, b); - - return 0; -} - -static int vino_qbuf(struct file *file, void *__fh, - struct v4l2_buffer *b) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - struct vino_framebuffer *fb; - int ret; - - if (vcs->reading) - return -EBUSY; - - /* TODO: check queue type */ - if (b->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } - - fb = vino_capture_enqueue(vcs, b->index); - if (fb == NULL) - return -EINVAL; - - vino_v4l2_get_buffer_status(vcs, fb, b); - - if (vcs->streaming) { - ret = vino_capture_next(vcs, 1); - if (ret) - return ret; - } - - return 0; -} - -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; - struct vino_framebuffer *fb; - unsigned int incoming, outgoing; - int err; - - if (vcs->reading) - return -EBUSY; - - /* TODO: check queue type */ - - err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); - if (err) { - dprintk("vino_queue_get_incoming() failed\n"); - return -EINVAL; - } - err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); - if (err) { - dprintk("vino_queue_get_outgoing() failed\n"); - return -EINVAL; - } - - dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); - - if (outgoing == 0) { - if (incoming == 0) { - dprintk("no incoming or outgoing buffers\n"); - return -EINVAL; - } - if (nonblocking) { - dprintk("non-blocking I/O was selected and " - "there are no buffers to dequeue\n"); - return -EAGAIN; - } - - err = vino_wait_for_frame(vcs); - if (err) { - err = vino_wait_for_frame(vcs); - if (err) { - /* interrupted or no frames captured because of - * frame skipping */ - /* vino_capture_failed(vcs); */ - return -EIO; - } - } - } - - fb = vino_queue_remove(&vcs->fb_queue, &b->index); - if (fb == NULL) { - dprintk("vino_queue_remove() failed\n"); - return -EINVAL; - } - - err = vino_check_buffer(vcs, fb); - - vino_v4l2_get_buffer_status(vcs, fb, b); - - if (err) - return -EIO; - - return 0; -} - -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) - return -EBUSY; - - if (vcs->streaming) - return 0; - - // TODO: check queue type - - if (vino_queue_get_length(&vcs->fb_queue) < 1) { - dprintk("no buffers allocated\n"); - return -EINVAL; - } - - ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming); - if (ret) { - dprintk("vino_queue_get_incoming() failed\n"); - return -EINVAL; - } - - vcs->streaming = 1; - - if (incoming > 0) { - ret = vino_capture_next(vcs, 1); - if (ret) { - vcs->streaming = 0; - - dprintk("couldn't start capture\n"); - return -EINVAL; - } - } - - return 0; -} - -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; - - if (!vcs->streaming) - return 0; - - vcs->streaming = 0; - vino_capture_stop(vcs); - - return 0; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - switch (vcs->input) { - case VINO_INPUT_D1: - for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - queryctrl->id) { - memcpy(queryctrl, - &vino_indycam_v4l2_controls[i], - sizeof(struct v4l2_queryctrl)); - queryctrl->reserved[0] = 0; - goto found; - } - } - - err = -EINVAL; - break; - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - queryctrl->id) { - memcpy(queryctrl, - &vino_saa7191_v4l2_controls[i], - sizeof(struct v4l2_queryctrl)); - queryctrl->reserved[0] = 0; - goto found; - } - } - - err = -EINVAL; - break; - default: - err = -EINVAL; - } - - found: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return err; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - switch (vcs->input) { - case VINO_INPUT_D1: { - err = -EINVAL; - for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == control->id) { - err = 0; - break; - } - } - - if (err) - goto out; - - err = camera_call(core, g_ctrl, control); - if (err) - err = -EINVAL; - break; - } - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: { - err = -EINVAL; - for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == control->id) { - err = 0; - break; - } - } - - if (err) - goto out; - - err = decoder_call(core, g_ctrl, control); - if (err) - err = -EINVAL; - break; - } - default: - err = -EINVAL; - } - -out: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return err; -} - -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; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if (!vino_is_input_owner(vcs)) { - err = -EBUSY; - goto out; - } - - switch (vcs->input) { - case VINO_INPUT_D1: { - err = -EINVAL; - for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == control->id) { - err = 0; - break; - } - } - 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 = camera_call(core, s_ctrl, control); - if (err) - err = -EINVAL; - break; - } - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: { - err = -EINVAL; - for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == control->id) { - err = 0; - break; - } - } - 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 = decoder_call(core, s_ctrl, control); - if (err) - err = -EINVAL; - break; - } - default: - err = -EINVAL; - } - -out: - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return err; -} - -/* File operations */ - -static int vino_open(struct file *file) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - int ret = 0; - dprintk("open(): channel = %c\n", - (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); - - mutex_lock(&vcs->mutex); - - if (vcs->users) { - dprintk("open(): driver busy\n"); - ret = -EBUSY; - goto out; - } - - ret = vino_acquire_input(vcs); - if (ret) { - dprintk("open(): vino_acquire_input() failed\n"); - goto out; - } - - vcs->users++; - - out: - mutex_unlock(&vcs->mutex); - - dprintk("open(): %s!\n", ret ? "failed" : "complete"); - - return ret; -} - -static int vino_close(struct file *file) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - dprintk("close():\n"); - - mutex_lock(&vcs->mutex); - - vcs->users--; - - if (!vcs->users) { - vino_release_input(vcs); - - /* stop DMA and free buffers */ - vino_capture_stop(vcs); - vino_queue_free(&vcs->fb_queue); - } - - mutex_unlock(&vcs->mutex); - - return 0; -} - -static void vino_vm_open(struct vm_area_struct *vma) -{ - struct vino_framebuffer *fb = vma->vm_private_data; - - fb->map_count++; - dprintk("vino_vm_open(): count = %d\n", fb->map_count); -} - -static void vino_vm_close(struct vm_area_struct *vma) -{ - struct vino_framebuffer *fb = vma->vm_private_data; - - fb->map_count--; - dprintk("vino_vm_close(): count = %d\n", fb->map_count); -} - -static const struct vm_operations_struct vino_vm_ops = { - .open = vino_vm_open, - .close = vino_vm_close, -}; - -static int vino_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - - struct vino_framebuffer *fb = NULL; - unsigned int i, length; - int ret = 0; - - dprintk("mmap():\n"); - - // TODO: reject mmap if already mapped - - if (mutex_lock_interruptible(&vcs->mutex)) - return -EINTR; - - if (vcs->reading) { - ret = -EBUSY; - goto out; - } - - // TODO: check queue type - - if (!(vma->vm_flags & VM_WRITE)) { - dprintk("mmap(): app bug: PROT_WRITE please\n"); - ret = -EINVAL; - goto out; - } - if (!(vma->vm_flags & VM_SHARED)) { - dprintk("mmap(): app bug: MAP_SHARED please\n"); - ret = -EINVAL; - goto out; - } - - /* find the correct buffer using offset */ - length = vino_queue_get_length(&vcs->fb_queue); - if (length == 0) { - dprintk("mmap(): queue not initialized\n"); - ret = -EINVAL; - goto out; - } - - for (i = 0; i < length; i++) { - fb = vino_queue_get_buffer(&vcs->fb_queue, i); - if (fb == NULL) { - dprintk("mmap(): vino_queue_get_buffer() failed\n"); - ret = -EINVAL; - goto out; - } - - if (fb->offset == offset) - goto found; - } - - dprintk("mmap(): invalid offset = %lu\n", offset); - ret = -EINVAL; - goto out; - -found: - dprintk("mmap(): buffer = %d\n", i); - - if (size > (fb->desc_table.page_count * PAGE_SIZE)) { - dprintk("mmap(): failed: size = %lu > %lu\n", - size, fb->desc_table.page_count * PAGE_SIZE); - ret = -EINVAL; - goto out; - } - - for (i = 0; i < fb->desc_table.page_count; i++) { - unsigned long pfn = - virt_to_phys((void *)fb->desc_table.virtual[i]) >> - PAGE_SHIFT; - - if (size < PAGE_SIZE) - break; - - // protection was: PAGE_READONLY - if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, - vma->vm_page_prot)) { - dprintk("mmap(): remap_pfn_range() failed\n"); - ret = -EAGAIN; - goto out; - } - - start += PAGE_SIZE; - size -= PAGE_SIZE; - } - - fb->map_count = 1; - - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; - vma->vm_flags &= ~VM_IO; - vma->vm_private_data = fb; - vma->vm_file = file; - vma->vm_ops = &vino_vm_ops; - -out: - mutex_unlock(&vcs->mutex); - - return ret; -} - -static unsigned int vino_poll(struct file *file, poll_table *pt) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - unsigned int outgoing; - unsigned int ret = 0; - - // lock mutex (?) - // TODO: this has to be corrected for different read modes - - dprintk("poll():\n"); - - if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { - dprintk("poll(): vino_queue_get_outgoing() failed\n"); - ret = POLLERR; - goto error; - } - if (outgoing > 0) - goto over; - - poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt); - - if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { - dprintk("poll(): vino_queue_get_outgoing() failed\n"); - ret = POLLERR; - goto error; - } - -over: - dprintk("poll(): data %savailable\n", - (outgoing > 0) ? "" : "not "); - - if (outgoing > 0) - ret = POLLIN | POLLRDNORM; - -error: - return ret; -} - -static long vino_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - long ret; - - if (mutex_lock_interruptible(&vcs->mutex)) - return -EINTR; - - ret = video_ioctl2(file, cmd, arg); - - mutex_unlock(&vcs->mutex); - - return ret; -} - -/* Initialization and cleanup */ - -/* __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, - .release = vino_close, - .unlocked_ioctl = vino_ioctl, - .mmap = vino_mmap, - .poll = vino_poll, -}; - -static struct video_device vdev_template = { - .name = "NOT SET", - .fops = &vino_fops, - .ioctl_ops = &vino_ioctl_ops, - .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, -}; - -static void vino_module_cleanup(int stage) -{ - switch(stage) { - case 11: - video_unregister_device(vino_drvdata->b.vdev); - vino_drvdata->b.vdev = NULL; - case 10: - video_unregister_device(vino_drvdata->a.vdev); - vino_drvdata->a.vdev = NULL; - case 9: - i2c_del_adapter(&vino_i2c_adapter); - case 8: - free_irq(SGI_VINO_IRQ, NULL); - case 7: - if (vino_drvdata->b.vdev) { - video_device_release(vino_drvdata->b.vdev); - vino_drvdata->b.vdev = NULL; - } - case 6: - if (vino_drvdata->a.vdev) { - video_device_release(vino_drvdata->a.vdev); - vino_drvdata->a.vdev = NULL; - } - 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], - PAGE_SIZE, DMA_FROM_DEVICE); - dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT - * sizeof(dma_addr_t), - (void *)vino_drvdata-> - dummy_desc_table.dma_cpu, - vino_drvdata->dummy_desc_table.dma); - case 4: - free_page(vino_drvdata->dummy_page); - case 3: - v4l2_device_unregister(&vino_drvdata->v4l2_dev); - case 2: - kfree(vino_drvdata); - case 1: - iounmap(vino); - case 0: - break; - default: - dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n", - stage); - } -} - -static int vino_probe(void) -{ - unsigned long rev_id; - - if (ip22_is_fullhouse()) { - printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n"); - return -ENODEV; - } - - if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { - printk(KERN_ERR "VINO is not found (EISA BUS not present)\n"); - return -ENODEV; - } - - vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino)); - if (!vino) { - printk(KERN_ERR "VINO: ioremap() failed\n"); - return -EIO; - } - vino_init_stage++; - - if (get_dbe(rev_id, &(vino->rev_id))) { - printk(KERN_ERR "Failed to read VINO revision register\n"); - vino_module_cleanup(vino_init_stage); - return -ENODEV; - } - - if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) { - printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n", - rev_id); - vino_module_cleanup(vino_init_stage); - return -ENODEV; - } - - printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id)); - - return 0; -} - -static int vino_init(void) -{ - dma_addr_t dma_dummy_address; - int err; - int i; - - vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL); - if (!vino_drvdata) { - vino_module_cleanup(vino_init_stage); - 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); - if (!vino_drvdata->dummy_page) { - vino_module_cleanup(vino_init_stage); - return -ENOMEM; - } - vino_init_stage++; - - // TODO: use page_count in dummy_desc_table - - vino_drvdata->dummy_desc_table.dma_cpu = - dma_alloc_coherent(NULL, - VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t), - &vino_drvdata->dummy_desc_table.dma, - GFP_KERNEL | GFP_DMA); - if (!vino_drvdata->dummy_desc_table.dma_cpu) { - vino_module_cleanup(vino_init_stage); - return -ENOMEM; - } - vino_init_stage++; - - dma_dummy_address = dma_map_single(NULL, - (void *)vino_drvdata->dummy_page, - PAGE_SIZE, DMA_FROM_DEVICE); - for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) { - vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address; - } - - /* initialize VINO */ - - vino->control = 0; - vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma; - vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma; - udelay(VINO_DESC_FETCH_DELAY); - - vino->intr_status = 0; - - vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT; - vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT; - - return 0; -} - -static int vino_init_channel_settings(struct vino_channel_settings *vcs, - unsigned int channel, const char *name) -{ - vcs->channel = channel; - vcs->input = VINO_INPUT_NONE; - vcs->alpha = 0; - vcs->users = 0; - vcs->data_format = VINO_DATA_FMT_GREY; - vcs->data_norm = VINO_DATA_NORM_NTSC; - vcs->decimation = 1; - vino_set_default_clipping(vcs); - vino_set_default_framerate(vcs); - - vcs->capturing = 0; - - mutex_init(&vcs->mutex); - spin_lock_init(&vcs->capture_lock); - - mutex_init(&vcs->fb_queue.queue_mutex); - spin_lock_init(&vcs->fb_queue.queue_lock); - init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); - - vcs->vdev = video_device_alloc(); - if (!vcs->vdev) { - vino_module_cleanup(vino_init_stage); - return -ENOMEM; - } - vino_init_stage++; - - memcpy(vcs->vdev, &vdev_template, - 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); - - return 0; -} - -static int __init vino_module_init(void) -{ - int ret; - - printk(KERN_INFO "SGI VINO driver version %s\n", - VINO_MODULE_VERSION); - - ret = vino_probe(); - if (ret) - return ret; - - ret = vino_init(); - if (ret) - return ret; - - /* initialize data structures */ - - spin_lock_init(&vino_drvdata->vino_lock); - spin_lock_init(&vino_drvdata->input_lock); - - ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A, - vino_vdev_name_a); - if (ret) - return ret; - - ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B, - vino_vdev_name_b); - if (ret) - return ret; - - /* initialize hardware and register V4L devices */ - - ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0, - vino_driver_description, NULL); - if (ret) { - printk(KERN_ERR "VINO: requesting IRQ %02d failed\n", - SGI_VINO_IRQ); - vino_module_cleanup(vino_init_stage); - return -EAGAIN; - } - vino_init_stage++; - - ret = i2c_add_adapter(&vino_i2c_adapter); - if (ret) { - printk(KERN_ERR "VINO I2C bus registration failed\n"); - 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, - VFL_TYPE_GRABBER, -1); - if (ret < 0) { - printk(KERN_ERR "VINO channel A Video4Linux-device " - "registration failed\n"); - vino_module_cleanup(vino_init_stage); - return -EINVAL; - } - vino_init_stage++; - - ret = video_register_device(vino_drvdata->b.vdev, - VFL_TYPE_GRABBER, -1); - if (ret < 0) { - printk(KERN_ERR "VINO channel B Video4Linux-device " - "registration failed\n"); - vino_module_cleanup(vino_init_stage); - return -EINVAL; - } - vino_init_stage++; - - vino_drvdata->decoder = - v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, - "saa7191", 0, I2C_ADDRS(0x45)); - vino_drvdata->camera = - v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, - "indycam", 0, I2C_ADDRS(0x2b)); - - dprintk("init complete!\n"); - - return 0; -} - -static void __exit vino_module_exit(void) -{ - dprintk("exiting, stage = %d ...\n", vino_init_stage); - vino_module_cleanup(vino_init_stage); - dprintk("cleanup complete, exit!\n"); -} - -module_init(vino_module_init); -module_exit(vino_module_exit); diff --git a/drivers/staging/media/vino/vino.h b/drivers/staging/media/vino/vino.h deleted file mode 100644 index de2d615ae7c9..000000000000 --- a/drivers/staging/media/vino/vino.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Driver for the VINO (Video In No Out) system found in SGI Indys. - * - * This file is subject to the terms and conditions of the GNU General Public - * License version 2 as published by the Free Software Foundation. - * - * Copyright (C) 1999 Ulf Karlsson - * Copyright (C) 2003 Ladislav Michl - */ - -#ifndef _VINO_H_ -#define _VINO_H_ - -#define VINO_BASE 0x00080000 /* Vino is in the EISA address space, - * but it is not an EISA bus card */ -#define VINO_PAGE_SIZE 4096 - -struct sgi_vino_channel { - u32 _pad_alpha; - volatile u32 alpha; - -#define VINO_CLIP_X(x) ((x) & 0x3ff) /* bits 0:9 */ -#define VINO_CLIP_ODD(x) (((x) & 0x1ff) << 10) /* bits 10:18 */ -#define VINO_CLIP_EVEN(x) (((x) & 0x1ff) << 19) /* bits 19:27 */ - u32 _pad_clip_start; - volatile u32 clip_start; - u32 _pad_clip_end; - volatile u32 clip_end; - -#define VINO_FRAMERT_FULL 0xfff -#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ -#define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */ - u32 _pad_frame_rate; - volatile u32 frame_rate; - - u32 _pad_field_counter; - volatile u32 field_counter; - u32 _pad_line_size; - volatile u32 line_size; - u32 _pad_line_count; - volatile u32 line_count; - u32 _pad_page_index; - volatile u32 page_index; - u32 _pad_next_4_desc; - volatile u32 next_4_desc; - u32 _pad_start_desc_tbl; - volatile u32 start_desc_tbl; - -#define VINO_DESC_JUMP (1<<30) -#define VINO_DESC_STOP (1<<31) -#define VINO_DESC_VALID (1<<32) - u32 _pad_desc_0; - volatile u32 desc_0; - u32 _pad_desc_1; - volatile u32 desc_1; - u32 _pad_desc_2; - volatile u32 desc_2; - u32 _pad_Bdesc_3; - volatile u32 desc_3; - - u32 _pad_fifo_thres; - volatile u32 fifo_thres; - u32 _pad_fifo_read; - volatile u32 fifo_read; - u32 _pad_fifo_write; - volatile u32 fifo_write; -}; - -struct sgi_vino { -#define VINO_CHIP_ID 0xb -#define VINO_REV_NUM(x) ((x) & 0x0f) -#define VINO_ID_VALUE(x) (((x) & 0xf0) >> 4) - u32 _pad_rev_id; - volatile u32 rev_id; - -#define VINO_CTRL_LITTLE_ENDIAN (1<<0) -#define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */ -#define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */ -#define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */ -#define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \ - VINO_CTRL_A_FIFO_INT | \ - VINO_CTRL_A_EOD_INT) -#define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */ -#define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */ -#define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */ -#define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \ - VINO_CTRL_B_FIFO_INT | \ - VINO_CTRL_B_EOD_INT) -#define VINO_CTRL_A_DMA_ENBL (1<<7) -#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) -#define VINO_CTRL_A_SYNC_ENBL (1<<9) -#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ -#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ -#define VINO_CTRL_A_LUMA_ONLY (1<<12) -#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ -#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ -#define VINO_CTRL_A_DEC_SCALE_SHIFT (14) -#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ -#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ -#define VINO_CTRL_B_DMA_ENBL (1<<19) -#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) -#define VINO_CTRL_B_SYNC_ENBL (1<<21) -#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ -#define VINO_CTRL_B_RGB (1<<23) /* 1=RGB 0=YUV */ -#define VINO_CTRL_B_LUMA_ONLY (1<<24) -#define VINO_CTRL_B_DEC_ENBL (1<<25) /* Decimation */ -#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 26:28 */ -#define VINO_CTRL_B_DEC_SCALE_SHIFT (26) -#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ -#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ - u32 _pad_control; - volatile u32 control; - -#define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */ -#define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */ -#define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */ -#define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \ - VINO_INTSTAT_A_FIFO | \ - VINO_INTSTAT_A_EOD) -#define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */ -#define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */ -#define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */ -#define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \ - VINO_INTSTAT_B_FIFO | \ - VINO_INTSTAT_B_EOD) - u32 _pad_intr_status; - volatile u32 intr_status; - - u32 _pad_i2c_control; - volatile u32 i2c_control; - u32 _pad_i2c_data; - volatile u32 i2c_data; - - struct sgi_vino_channel a; - struct sgi_vino_channel b; -}; - -#endif -- cgit v1.2.3 From 51d3d4eee565a707e4053fe447cd28b2d1f4ce79 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2014 09:17:09 -0300 Subject: [media] bw/c-qcam, w9966, pms: remove deprecated staging drivers These drivers haven't been tested in a long, long time. The hardware is ancient and hopelessly obsolete. These drivers also need to be converted to newer media frameworks but due to the lack of hardware that's going to be impossible. In addition, cheaper and vastly better hardware is available today. These drivers are already deprecated, so now remove them altogether. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 16 - drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/parport/Kconfig | 69 -- drivers/staging/media/parport/Makefile | 4 - drivers/staging/media/parport/bw-qcam.c | 1177 ------------------------------- drivers/staging/media/parport/c-qcam.c | 882 ----------------------- drivers/staging/media/parport/pms.c | 1156 ------------------------------ drivers/staging/media/parport/w9966.c | 980 ------------------------- 9 files changed, 4287 deletions(-) delete mode 100644 drivers/staging/media/parport/Kconfig delete mode 100644 drivers/staging/media/parport/Makefile delete mode 100644 drivers/staging/media/parport/bw-qcam.c delete mode 100644 drivers/staging/media/parport/c-qcam.c delete mode 100644 drivers/staging/media/parport/pms.c delete mode 100644 drivers/staging/media/parport/w9966.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index f3ae573d1d4f..3db56b8f90fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6158,14 +6158,6 @@ F: include/uapi/linux/meye.h F: include/uapi/linux/ivtv* F: include/uapi/linux/uvcvideo.h -MEDIAVISION PRO MOVIE STUDIO DRIVER -M: Hans Verkuil -L: linux-media@vger.kernel.org -T: git git://linuxtv.org/media_tree.git -W: http://linuxtv.org -S: Odd Fixes -F: drivers/media/parport/pms* - MEGARAID SCSI/SAS DRIVERS M: Kashyap Desai M: Sumit Saxena @@ -7855,14 +7847,6 @@ T: git git://github.com/KrasnikovEugene/wcn36xx.git S: Supported F: drivers/net/wireless/ath/wcn36xx/ -QUICKCAM PARALLEL PORT WEBCAMS -M: Hans Verkuil -L: linux-media@vger.kernel.org -T: git git://linuxtv.org/media_tree.git -W: http://linuxtv.org -S: Odd Fixes -F: drivers/media/parport/*-qcam* - RADOS BLOCK DEVICE (RBD) M: Yehuda Sadeh M: Sage Weil diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index e633204b9685..96498b7fc20e 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -33,8 +33,6 @@ source "drivers/staging/media/mn88473/Kconfig" source "drivers/staging/media/omap4iss/Kconfig" -source "drivers/staging/media/parport/Kconfig" - # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 7edb567b2de6..a9006bcb4472 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -6,4 +6,3 @@ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_DVB_MN88473) += mn88473/ -obj-y += parport/ diff --git a/drivers/staging/media/parport/Kconfig b/drivers/staging/media/parport/Kconfig deleted file mode 100644 index 15974efdba1d..000000000000 --- a/drivers/staging/media/parport/Kconfig +++ /dev/null @@ -1,69 +0,0 @@ -menuconfig MEDIA_PARPORT_SUPPORT - bool "ISA and parallel port devices" - depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT - help - Enables drivers for ISA and parallel port bus. If you - need media drivers using those legacy buses, say Y. - -if MEDIA_PARPORT_SUPPORT -config VIDEO_BWQCAM - tristate "Quickcam BW Video For Linux (Deprecated)" - depends on PARPORT && VIDEO_V4L2 - select VIDEOBUF2_VMALLOC - help - Say Y have if you the black and white version of the QuickCam - camera. See the next option for the color version. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called bw-qcam. - -config VIDEO_CQCAM - tristate "QuickCam Colour Video For Linux (Deprecated)" - depends on PARPORT && VIDEO_V4L2 - help - This is the video4linux driver for the colour version of the - Connectix QuickCam. If you have one of these cameras, say Y here, - otherwise say N. This driver does not work with the original - monochrome QuickCam, QuickCam VC or QuickClip. It is also available - as a module (c-qcam). - Read for more information. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - -config VIDEO_PMS - tristate "Mediavision Pro Movie Studio Video For Linux (Deprecated)" - depends on ISA && VIDEO_V4L2 - help - Say Y if you have the ISA Mediavision Pro Movie Studio - capture card. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called pms. - -config VIDEO_W9966 - tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux (Deprecated)" - depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 - help - Video4linux driver for Winbond's w9966 based Webcams. - Currently tested with the LifeView FlyCam Supra. - If you have one of these cameras, say Y here - otherwise say N. - This driver is also available as a module (w9966). - - Check out for more - information. - - This driver is deprecated and will be removed soon. If you have - hardware for this and you want to work on this driver, then contact - the linux-media mailinglist. -endif diff --git a/drivers/staging/media/parport/Makefile b/drivers/staging/media/parport/Makefile deleted file mode 100644 index 4eea06d7af5b..000000000000 --- a/drivers/staging/media/parport/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o -obj-$(CONFIG_VIDEO_W9966) += w9966.o -obj-$(CONFIG_VIDEO_PMS) += pms.o diff --git a/drivers/staging/media/parport/bw-qcam.c b/drivers/staging/media/parport/bw-qcam.c deleted file mode 100644 index 67b9da1dc43f..000000000000 --- a/drivers/staging/media/parport/bw-qcam.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * QuickCam Driver For Video4Linux. - * - * Video4Linux conversion work by Alan Cox. - * Parport compatibility by Phil Blundell. - * Busy loop avoidance by Mark Cooke. - * - * Module parameters: - * - * maxpoll=<1 - 5000> - * - * When polling the QuickCam for a response, busy-wait for a - * maximum of this many loops. The default of 250 gives little - * impact on interactive response. - * - * NOTE: If this parameter is set too high, the processor - * will busy wait until this loop times out, and then - * slowly poll for a further 5 seconds before failing - * the transaction. You have been warned. - * - * yieldlines=<1 - 250> - * - * When acquiring a frame from the camera, the data gathering - * loop will yield back to the scheduler after completing - * this many lines. The default of 4 provides a trade-off - * between increased frame acquisition time and impact on - * interactive response. - */ - -/* qcam-lib.c -- Library for programming with the Connectix QuickCam. - * See the included documentation for usage instructions and details - * of the protocol involved. */ - - -/* Version 0.5, August 4, 1996 */ -/* Version 0.7, August 27, 1996 */ -/* Version 0.9, November 17, 1996 */ - - -/****************************************************************** - -Copyright (C) 1996 by Scott Laird - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* One from column A... */ -#define QC_NOTSET 0 -#define QC_UNIDIR 1 -#define QC_BIDIR 2 -#define QC_SERIAL 3 - -/* ... and one from column B */ -#define QC_ANY 0x00 -#define QC_FORCE_UNIDIR 0x10 -#define QC_FORCE_BIDIR 0x20 -#define QC_FORCE_SERIAL 0x30 -/* in the port_mode member */ - -#define QC_MODE_MASK 0x07 -#define QC_FORCE_MASK 0x70 - -#define MAX_HEIGHT 243 -#define MAX_WIDTH 336 - -/* Bit fields for status flags */ -#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ - -struct qcam { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct v4l2_ctrl_handler hdl; - struct vb2_queue vb_vidq; - struct pardevice *pdev; - struct parport *pport; - struct mutex lock; - struct mutex queue_lock; - int width, height; - int bpp; - int mode; - int contrast, brightness, whitebal; - int port_mode; - int transfer_scale; - int top, left; - int status; - unsigned int saved_bits; - unsigned long in_use; -}; - -static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ -static unsigned int yieldlines = 4; /* Yield after this many during capture */ -static int video_nr = -1; -static unsigned int force_init; /* Whether to probe aggressively */ - -module_param(maxpoll, int, 0); -module_param(yieldlines, int, 0); -module_param(video_nr, int, 0); - -/* Set force_init=1 to avoid detection by polling status register and - * immediately attempt to initialize qcam */ -module_param(force_init, int, 0); - -#define MAX_CAMS 4 -static struct qcam *qcams[MAX_CAMS]; -static unsigned int num_cams; - -static inline int read_lpstatus(struct qcam *q) -{ - return parport_read_status(q->pport); -} - -static inline int read_lpdata(struct qcam *q) -{ - return parport_read_data(q->pport); -} - -static inline void write_lpdata(struct qcam *q, int d) -{ - parport_write_data(q->pport, d); -} - -static void write_lpcontrol(struct qcam *q, int d) -{ - if (d & 0x20) { - /* Set bidirectional mode to reverse (data in) */ - parport_data_reverse(q->pport); - } else { - /* Set bidirectional mode to forward (data out) */ - parport_data_forward(q->pport); - } - - /* Now issue the regular port command, but strip out the - * direction flag */ - d &= ~0x20; - parport_write_control(q->pport, d); -} - - -/* qc_waithand busy-waits for a handshake signal from the QuickCam. - * Almost all communication with the camera requires handshaking. */ - -static int qc_waithand(struct qcam *q, int val) -{ - int status; - int runs = 0; - - if (val) { - while (!((status = read_lpstatus(q)) & 8)) { - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if (runs++ > maxpoll) - msleep_interruptible(5); - if (runs > (maxpoll + 1000)) /* 5 seconds */ - return -1; - } - } else { - while (((status = read_lpstatus(q)) & 8)) { - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if (runs++ > maxpoll) - msleep_interruptible(5); - if (runs++ > (maxpoll + 1000)) /* 5 seconds */ - return -1; - } - } - - return status; -} - -/* Waithand2 is used when the qcam is in bidirectional mode, and the - * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1 - * (bit 3 of status register). It also returns the last value read, - * since this data is useful. */ - -static unsigned int qc_waithand2(struct qcam *q, int val) -{ - unsigned int status; - int runs = 0; - - do { - status = read_lpdata(q); - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if (runs++ > maxpoll) - msleep_interruptible(5); - if (runs++ > (maxpoll + 1000)) /* 5 seconds */ - return 0; - } while ((status & 1) != val); - - return status; -} - -/* qc_command is probably a bit of a misnomer -- it's used to send - * bytes *to* the camera. Generally, these bytes are either commands - * or arguments to commands, so the name fits, but it still bugs me a - * bit. See the documentation for a list of commands. */ - -static int qc_command(struct qcam *q, int command) -{ - int n1, n2; - int cmd; - - write_lpdata(q, command); - write_lpcontrol(q, 6); - - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} - -static int qc_readparam(struct qcam *q) -{ - int n1, n2; - int cmd; - - write_lpcontrol(q, 6); - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} - - -/* Try to detect a QuickCam. It appears to flash the upper 4 bits of - the status register at 5-10 Hz. This is only used in the autoprobe - code. Be aware that this isn't the way Connectix detects the - camera (they send a reset and try to handshake), but this should be - almost completely safe, while their method screws up my printer if - I plug it in before the camera. */ - -static int qc_detect(struct qcam *q) -{ - int reg, lastreg; - int count = 0; - int i; - - if (force_init) - return 1; - - lastreg = reg = read_lpstatus(q) & 0xf0; - - for (i = 0; i < 500; i++) { - reg = read_lpstatus(q) & 0xf0; - if (reg != lastreg) - count++; - lastreg = reg; - mdelay(2); - } - - -#if 0 - /* Force camera detection during testing. Sometimes the camera - won't be flashing these bits. Possibly unloading the module - in the middle of a grab? Or some timeout condition? - I've seen this parameter as low as 19 on my 450Mhz box - mpc */ - printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); - return 1; -#endif - - /* Be (even more) liberal in what you accept... */ - - if (count > 20 && count < 400) { - return 1; /* found */ - } else { - printk(KERN_ERR "No Quickcam found on port %s\n", - q->pport->name); - printk(KERN_DEBUG "Quickcam detection counter: %u\n", count); - return 0; /* not found */ - } -} - -/* Decide which scan mode to use. There's no real requirement that - * the scanmode match the resolution in q->height and q-> width -- the - * camera takes the picture at the resolution specified in the - * "scanmode" and then returns the image at the resolution specified - * with the resolution commands. If the scan is bigger than the - * requested resolution, the upper-left hand corner of the scan is - * returned. If the scan is smaller, then the rest of the image - * returned contains garbage. */ - -static int qc_setscanmode(struct qcam *q) -{ - int old_mode = q->mode; - - switch (q->transfer_scale) { - case 1: - q->mode = 0; - break; - case 2: - q->mode = 4; - break; - case 4: - q->mode = 8; - break; - } - - switch (q->bpp) { - case 4: - break; - case 6: - q->mode += 2; - break; - } - - switch (q->port_mode & QC_MODE_MASK) { - case QC_BIDIR: - q->mode += 1; - break; - case QC_NOTSET: - case QC_UNIDIR: - break; - } - - if (q->mode != old_mode) - q->status |= QC_PARAM_CHANGE; - - return 0; -} - - -/* Reset the QuickCam. This uses the same sequence the Windows - * QuickPic program uses. Someone with a bi-directional port should - * check that bi-directional mode is detected right, and then - * implement bi-directional mode in qc_readbyte(). */ - -static void qc_reset(struct qcam *q) -{ - switch (q->port_mode & QC_FORCE_MASK) { - case QC_FORCE_UNIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; - - case QC_FORCE_BIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - break; - - case QC_ANY: - write_lpcontrol(q, 0x20); - write_lpdata(q, 0x75); - - if (read_lpdata(q) != 0x75) - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - else - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; - } - - write_lpcontrol(q, 0xb); - udelay(250); - write_lpcontrol(q, 0xe); - qc_setscanmode(q); /* in case port_mode changed */ -} - - - -/* Reset the QuickCam and program for brightness, contrast, - * white-balance, and resolution. */ - -static void qc_set(struct qcam *q) -{ - int val; - int val2; - - /* Set the brightness. Yes, this is repetitive, but it works. - * Shorter versions seem to fail subtly. Feel free to try :-). */ - /* I think the problem was in qc_command, not here -- bls */ - - qc_command(q, 0xb); - qc_command(q, q->brightness); - - val = q->height / q->transfer_scale; - qc_command(q, 0x11); - qc_command(q, val); - if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) { - /* The normal "transfers per line" calculation doesn't seem to work - as expected here (and yet it works fine in qc_scan). No idea - why this case is the odd man out. Fortunately, Laird's original - working version gives me a good way to guess at working values. - -- bls */ - val = q->width; - val2 = q->transfer_scale * 4; - } else { - val = q->width * q->bpp; - val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; - } - val = DIV_ROUND_UP(val, val2); - qc_command(q, 0x13); - qc_command(q, val); - - /* Setting top and left -- bls */ - qc_command(q, 0xd); - qc_command(q, q->top); - qc_command(q, 0xf); - qc_command(q, q->left / 2); - - qc_command(q, 0x19); - qc_command(q, q->contrast); - qc_command(q, 0x1f); - qc_command(q, q->whitebal); - - /* Clear flag that we must update the grabbing parameters on the camera - before we grab the next frame */ - q->status &= (~QC_PARAM_CHANGE); -} - -/* Qc_readbytes reads some bytes from the QC and puts them in - the supplied buffer. It returns the number of bytes read, - or -1 on error. */ - -static inline int qc_readbytes(struct qcam *q, char buffer[]) -{ - int ret = 1; - unsigned int hi, lo; - unsigned int hi2, lo2; - static int state; - - if (buffer == NULL) { - state = 0; - return 0; - } - - switch (q->port_mode & QC_MODE_MASK) { - case QC_BIDIR: /* Bi-directional Port */ - write_lpcontrol(q, 0x26); - lo = (qc_waithand2(q, 1) >> 1); - hi = (read_lpstatus(q) >> 3) & 0x1f; - write_lpcontrol(q, 0x2e); - lo2 = (qc_waithand2(q, 0) >> 1); - hi2 = (read_lpstatus(q) >> 3) & 0x1f; - switch (q->bpp) { - case 4: - buffer[0] = lo & 0xf; - buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); - buffer[2] = (hi & 0x1e) >> 1; - buffer[3] = lo2 & 0xf; - buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); - buffer[5] = (hi2 & 0x1e) >> 1; - ret = 6; - break; - case 6: - buffer[0] = lo & 0x3f; - buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); - buffer[2] = lo2 & 0x3f; - buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); - ret = 4; - break; - } - break; - - case QC_UNIDIR: /* Unidirectional Port */ - write_lpcontrol(q, 6); - lo = (qc_waithand(q, 1) & 0xf0) >> 4; - write_lpcontrol(q, 0xe); - hi = (qc_waithand(q, 0) & 0xf0) >> 4; - - switch (q->bpp) { - case 4: - buffer[0] = lo; - buffer[1] = hi; - ret = 2; - break; - case 6: - switch (state) { - case 0: - buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); - q->saved_bits = (hi & 3) << 4; - state = 1; - ret = 1; - break; - case 1: - buffer[0] = lo | q->saved_bits; - q->saved_bits = hi << 2; - state = 2; - ret = 1; - break; - case 2: - buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; - buffer[1] = ((lo & 3) << 4) | hi; - state = 0; - ret = 2; - break; - } - break; - } - break; - } - return ret; -} - -/* requests a scan from the camera. It sends the correct instructions - * to the camera and then reads back the correct number of bytes. In - * previous versions of this routine the return structure contained - * the raw output from the camera, and there was a 'qc_convertscan' - * function that converted that to a useful format. In version 0.3 I - * rolled qc_convertscan into qc_scan and now I only return the - * converted scan. The format is just an one-dimensional array of - * characters, one for each pixel, with 0=black up to n=white, where - * n=2^(bit depth)-1. Ask me for more details if you don't understand - * this. */ - -static long qc_capture(struct qcam *q, u8 *buf, unsigned long len) -{ - int i, j, k, yield; - int bytes; - int linestotrans, transperline; - int divisor; - int pixels_per_line; - int pixels_read = 0; - int got = 0; - char buffer[6]; - int shift = 8 - q->bpp; - char invert; - - if (q->mode == -1) - return -ENXIO; - - qc_command(q, 0x7); - qc_command(q, q->mode); - - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { - write_lpcontrol(q, 0x2e); /* turn port around */ - write_lpcontrol(q, 0x26); - qc_waithand(q, 1); - write_lpcontrol(q, 0x2e); - qc_waithand(q, 0); - } - - /* strange -- should be 15:63 below, but 4bpp is odd */ - invert = (q->bpp == 4) ? 16 : 63; - - linestotrans = q->height / q->transfer_scale; - pixels_per_line = q->width / q->transfer_scale; - transperline = q->width * q->bpp; - divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; - transperline = DIV_ROUND_UP(transperline, divisor); - - for (i = 0, yield = yieldlines; i < linestotrans; i++) { - for (pixels_read = j = 0; j < transperline; j++) { - bytes = qc_readbytes(q, buffer); - for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) { - int o; - if (buffer[k] == 0 && invert == 16) { - /* 4bpp is odd (again) -- inverter is 16, not 15, but output - must be 0-15 -- bls */ - buffer[k] = 16; - } - o = i * pixels_per_line + pixels_read + k; - if (o < len) { - u8 ch = invert - buffer[k]; - got++; - buf[o] = ch << shift; - } - } - pixels_read += bytes; - } - qc_readbytes(q, NULL); /* reset state machine */ - - /* Grabbing an entire frame from the quickcam is a lengthy - process. We don't (usually) want to busy-block the - processor for the entire frame. yieldlines is a module - parameter. If we yield every line, the minimum frame - time will be 240 / 200 = 1.2 seconds. The compile-time - default is to yield every 4 lines. */ - if (i >= yield) { - msleep_interruptible(5); - yield = i + yieldlines; - } - } - - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { - write_lpcontrol(q, 2); - write_lpcontrol(q, 6); - udelay(3); - write_lpcontrol(q, 0xe); - } - if (got < len) - return got; - return len; -} - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct qcam *dev = vb2_get_drv_priv(vq); - - if (0 == *nbuffers) - *nbuffers = 3; - *nplanes = 1; - mutex_lock(&dev->lock); - if (fmt) - sizes[0] = fmt->fmt.pix.width * fmt->fmt.pix.height; - else - sizes[0] = (dev->width / dev->transfer_scale) * - (dev->height / dev->transfer_scale); - mutex_unlock(&dev->lock); - return 0; -} - -static void buffer_queue(struct vb2_buffer *vb) -{ - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); -} - -static void buffer_finish(struct vb2_buffer *vb) -{ - struct qcam *qcam = vb2_get_drv_priv(vb->vb2_queue); - void *vbuf = vb2_plane_vaddr(vb, 0); - int size = vb->vb2_queue->plane_sizes[0]; - int len; - - if (!vb2_is_streaming(vb->vb2_queue)) - return; - - mutex_lock(&qcam->lock); - parport_claim_or_block(qcam->pdev); - - qc_reset(qcam); - - /* Update the camera parameters if we need to */ - if (qcam->status & QC_PARAM_CHANGE) - qc_set(qcam); - - len = qc_capture(qcam, vbuf, size); - - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - if (len != size) - vb->state = VB2_BUF_STATE_ERROR; - vb2_set_plane_payload(vb, 0, len); -} - -static struct vb2_ops qcam_video_qops = { - .queue_setup = queue_setup, - .buf_queue = buffer_queue, - .buf_finish = buffer_finish, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* - * Video4linux interfacing - */ - -static int qcam_querycap(struct file *file, void *priv, - struct v4l2_capability *vcap) -{ - struct qcam *qcam = video_drvdata(file); - - strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card)); - strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info)); - vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - if (vin->index > 0) - return -EINVAL; - strlcpy(vin->name, "Camera", sizeof(vin->name)); - vin->type = V4L2_INPUT_TYPE_CAMERA; - vin->audioset = 0; - vin->tuner = 0; - vin->std = 0; - vin->status = 0; - return 0; -} - -static int qcam_g_input(struct file *file, void *fh, unsigned int *inp) -{ - *inp = 0; - return 0; -} - -static int qcam_s_input(struct file *file, void *fh, unsigned int inp) -{ - return (inp > 0) ? -EINVAL : 0; -} - -static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct qcam *qcam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - pix->width = qcam->width / qcam->transfer_scale; - pix->height = qcam->height / qcam->transfer_scale; - pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = pix->width; - pix->sizeimage = pix->width * pix->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->height <= 60 || pix->width <= 80) { - pix->height = 60; - pix->width = 80; - } else if (pix->height <= 120 || pix->width <= 160) { - pix->height = 120; - pix->width = 160; - } else { - pix->height = 240; - pix->width = 320; - } - if (pix->pixelformat != V4L2_PIX_FMT_Y4 && - pix->pixelformat != V4L2_PIX_FMT_Y6) - pix->pixelformat = V4L2_PIX_FMT_Y4; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = pix->width; - pix->sizeimage = pix->width * pix->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct qcam *qcam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - int ret = qcam_try_fmt_vid_cap(file, fh, fmt); - - if (ret) - return ret; - if (vb2_is_busy(&qcam->vb_vidq)) - return -EBUSY; - qcam->width = 320; - qcam->height = 240; - if (pix->height == 60) - qcam->transfer_scale = 4; - else if (pix->height == 120) - qcam->transfer_scale = 2; - else - qcam->transfer_scale = 1; - if (pix->pixelformat == V4L2_PIX_FMT_Y6) - qcam->bpp = 6; - else - qcam->bpp = 4; - - qc_setscanmode(qcam); - /* We must update the camera before we grab. We could - just have changed the grab size */ - qcam->status |= QC_PARAM_CHANGE; - return 0; -} - -static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "4-Bit Monochrome", V4L2_PIX_FMT_Y4, - { 0, 0, 0, 0 } - }, - { 1, 0, 0, - "6-Bit Monochrome", V4L2_PIX_FMT_Y6, - { 0, 0, 0, 0 } - }, - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 1) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -static int qcam_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) -{ - static const struct v4l2_frmsize_discrete sizes[] = { - { 80, 60 }, - { 160, 120 }, - { 320, 240 }, - }; - - if (fsize->index > 2) - return -EINVAL; - if (fsize->pixel_format != V4L2_PIX_FMT_Y4 && - fsize->pixel_format != V4L2_PIX_FMT_Y6) - return -EINVAL; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete = sizes[fsize->index]; - return 0; -} - -static int qcam_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct qcam *qcam = - container_of(ctrl->handler, struct qcam, hdl); - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - qcam->brightness = ctrl->val; - break; - case V4L2_CID_CONTRAST: - qcam->contrast = ctrl->val; - break; - case V4L2_CID_GAMMA: - qcam->whitebal = ctrl->val; - break; - default: - ret = -EINVAL; - break; - } - if (ret == 0) - qcam->status |= QC_PARAM_CHANGE; - return ret; -} - -static const struct v4l2_file_operations qcam_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, - .read = vb2_fop_read, - .mmap = vb2_fop_mmap, -}; - -static const struct v4l2_ioctl_ops qcam_ioctl_ops = { - .vidioc_querycap = qcam_querycap, - .vidioc_g_input = qcam_g_input, - .vidioc_s_input = qcam_s_input, - .vidioc_enum_input = qcam_enum_input, - .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, - .vidioc_enum_framesizes = qcam_enum_framesizes, - .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct v4l2_ctrl_ops qcam_ctrl_ops = { - .s_ctrl = qcam_s_ctrl, -}; - -/* Initialize the QuickCam driver control structure. This is where - * defaults are set for people who don't have a config file.*/ - -static struct qcam *qcam_init(struct parport *port) -{ - struct qcam *qcam; - struct v4l2_device *v4l2_dev; - struct vb2_queue *q; - int err; - - qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL); - if (qcam == NULL) - return NULL; - - v4l2_dev = &qcam->v4l2_dev; - snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%u", num_cams); - - if (v4l2_device_register(port->dev, v4l2_dev) < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - kfree(qcam); - return NULL; - } - - v4l2_ctrl_handler_init(&qcam->hdl, 3); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 180); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 192); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_GAMMA, 0, 255, 1, 105); - if (qcam->hdl.error) { - v4l2_err(v4l2_dev, "couldn't register controls\n"); - goto exit; - } - - mutex_init(&qcam->lock); - mutex_init(&qcam->queue_lock); - - /* initialize queue */ - q = &qcam->vb_vidq; - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - q->drv_priv = qcam; - q->ops = &qcam_video_qops; - q->mem_ops = &vb2_vmalloc_memops; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - err = vb2_queue_init(q); - if (err < 0) { - v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name); - goto exit; - } - qcam->vdev.queue = q; - qcam->vdev.queue->lock = &qcam->queue_lock; - - qcam->pport = port; - qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL, - NULL, 0, NULL); - if (qcam->pdev == NULL) { - v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); - goto exit; - } - - strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name)); - qcam->vdev.v4l2_dev = v4l2_dev; - qcam->vdev.ctrl_handler = &qcam->hdl; - qcam->vdev.fops = &qcam_fops; - qcam->vdev.lock = &qcam->lock; - qcam->vdev.ioctl_ops = &qcam_ioctl_ops; - qcam->vdev.release = video_device_release_empty; - video_set_drvdata(&qcam->vdev, qcam); - - qcam->port_mode = (QC_ANY | QC_NOTSET); - qcam->width = 320; - qcam->height = 240; - qcam->bpp = 4; - qcam->transfer_scale = 2; - qcam->contrast = 192; - qcam->brightness = 180; - qcam->whitebal = 105; - qcam->top = 1; - qcam->left = 14; - qcam->mode = -1; - qcam->status = QC_PARAM_CHANGE; - return qcam; - -exit: - v4l2_ctrl_handler_free(&qcam->hdl); - kfree(qcam); - return NULL; -} - -static int qc_calibrate(struct qcam *q) -{ - /* - * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 - * The white balance is an individual value for each - * quickcam. - */ - - int value; - int count = 0; - - qc_command(q, 27); /* AutoAdjustOffset */ - qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ - - /* GetOffset (33) will read 255 until autocalibration */ - /* is finished. After that, a value of 1-254 will be */ - /* returned. */ - - do { - qc_command(q, 33); - value = qc_readparam(q); - mdelay(1); - schedule(); - count++; - } while (value == 0xff && count < 2048); - - q->whitebal = value; - return value; -} - -static int init_bwqcam(struct parport *port) -{ - struct qcam *qcam; - - if (num_cams == MAX_CAMS) { - printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); - return -ENOSPC; - } - - qcam = qcam_init(port); - if (qcam == NULL) - return -ENODEV; - - parport_claim_or_block(qcam->pdev); - - qc_reset(qcam); - - if (qc_detect(qcam) == 0) { - parport_release(qcam->pdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - qc_calibrate(qcam); - v4l2_ctrl_handler_setup(&qcam->hdl); - - parport_release(qcam->pdev); - - v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name); - - if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - qcams[num_cams++] = qcam; - - return 0; -} - -static void close_bwqcam(struct qcam *qcam) -{ - video_unregister_device(&qcam->vdev); - v4l2_ctrl_handler_free(&qcam->hdl); - parport_unregister_device(qcam->pdev); - kfree(qcam); -} - -/* The parport parameter controls which parports will be scanned. - * Scanning all parports causes some printers to print a garbage page. - * -- March 14, 1999 Billy Donahue */ -#ifdef MODULE -static char *parport[MAX_CAMS] = { NULL, }; -module_param_array(parport, charp, NULL, 0); -#endif - -static int accept_bwqcam(struct parport *port) -{ -#ifdef MODULE - int n; - - if (parport[0] && strncmp(parport[0], "auto", 4) != 0) { - /* user gave parport parameters */ - for (n = 0; n < MAX_CAMS && parport[n]; n++) { - char *ep; - unsigned long r; - r = simple_strtoul(parport[n], &ep, 0); - if (ep == parport[n]) { - printk(KERN_ERR - "bw-qcam: bad port specifier \"%s\"\n", - parport[n]); - continue; - } - if (r == port->number) - return 1; - } - return 0; - } -#endif - return 1; -} - -static void bwqcam_attach(struct parport *port) -{ - if (accept_bwqcam(port)) - init_bwqcam(port); -} - -static void bwqcam_detach(struct parport *port) -{ - int i; - for (i = 0; i < num_cams; i++) { - struct qcam *qcam = qcams[i]; - if (qcam && qcam->pdev->port == port) { - qcams[i] = NULL; - close_bwqcam(qcam); - } - } -} - -static struct parport_driver bwqcam_driver = { - .name = "bw-qcam", - .attach = bwqcam_attach, - .detach = bwqcam_detach, -}; - -static void __exit exit_bw_qcams(void) -{ - parport_unregister_driver(&bwqcam_driver); -} - -static int __init init_bw_qcams(void) -{ -#ifdef MODULE - /* Do some sanity checks on the module parameters. */ - if (maxpoll > 5000) { - printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n"); - maxpoll = 5000; - } - - if (yieldlines < 1) { - printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n"); - yieldlines = 1; - } -#endif - return parport_register_driver(&bwqcam_driver); -} - -module_init(init_bw_qcams); -module_exit(exit_bw_qcams); - -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.3"); diff --git a/drivers/staging/media/parport/c-qcam.c b/drivers/staging/media/parport/c-qcam.c deleted file mode 100644 index b9010bd3ed3e..000000000000 --- a/drivers/staging/media/parport/c-qcam.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Video4Linux Colour QuickCam driver - * Copyright 1997-2000 Philip Blundell - * - * Module parameters: - * - * parport=auto -- probe all parports (default) - * parport=0 -- parport0 becomes qcam1 - * parport=2,0,1 -- parports 2,0,1 are tried in that order - * - * probe=0 -- do no probing, assume camera is present - * probe=1 -- use IEEE-1284 autoprobe data only (default) - * probe=2 -- probe aggressively for cameras - * - * force_rgb=1 -- force data format to RGB (default is BGR) - * - * The parport parameter controls which parports will be scanned. - * Scanning all parports causes some printers to print a garbage page. - * -- March 14, 1999 Billy Donahue - * - * Fixed data format to BGR, added force_rgb parameter. Added missing - * parport_unregister_driver() on module removal. - * -- May 28, 2000 Claudio Matsuoka - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct qcam { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct v4l2_ctrl_handler hdl; - struct pardevice *pdev; - struct parport *pport; - int width, height; - int ccd_width, ccd_height; - int mode; - int contrast, brightness, whitebal; - int top, left; - unsigned int bidirectional; - struct mutex lock; -}; - -/* cameras maximum */ -#define MAX_CAMS 4 - -/* The three possible QuickCam modes */ -#define QC_MILLIONS 0x18 -#define QC_BILLIONS 0x10 -#define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */ - -/* The three possible decimations */ -#define QC_DECIMATION_1 0 -#define QC_DECIMATION_2 2 -#define QC_DECIMATION_4 4 - -#define BANNER "Colour QuickCam for Video4Linux v0.06" - -static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; -static int probe = 2; -static bool force_rgb; -static int video_nr = -1; - -/* FIXME: parport=auto would never have worked, surely? --RR */ -MODULE_PARM_DESC(parport, "parport= for port detection method\n" - "probe=<0|1|2> for camera detection method\n" - "force_rgb=<0|1> for RGB data format (default BGR)"); -module_param_array(parport, int, NULL, 0); -module_param(probe, int, 0); -module_param(force_rgb, bool, 0); -module_param(video_nr, int, 0); - -static struct qcam *qcams[MAX_CAMS]; -static unsigned int num_cams; - -static inline void qcam_set_ack(struct qcam *qcam, unsigned int i) -{ - /* note: the QC specs refer to the PCAck pin by voltage, not - software level. PC ports have builtin inverters. */ - parport_frob_control(qcam->pport, 8, i ? 8 : 0); -} - -static inline unsigned int qcam_ready1(struct qcam *qcam) -{ - return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; -} - -static inline unsigned int qcam_ready2(struct qcam *qcam) -{ - return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; -} - -static unsigned int qcam_await_ready1(struct qcam *qcam, int value) -{ - struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; - unsigned long oldjiffies = jiffies; - unsigned int i; - - for (oldjiffies = jiffies; - time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) - if (qcam_ready1(qcam) == value) - return 0; - - /* If the camera didn't respond within 1/25 second, poll slowly - for a while. */ - for (i = 0; i < 50; i++) { - if (qcam_ready1(qcam) == value) - return 0; - msleep_interruptible(100); - } - - /* Probably somebody pulled the plug out. Not much we can do. */ - v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value, - parport_read_status(qcam->pport), - parport_read_control(qcam->pport)); - return 1; -} - -static unsigned int qcam_await_ready2(struct qcam *qcam, int value) -{ - struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; - unsigned long oldjiffies = jiffies; - unsigned int i; - - for (oldjiffies = jiffies; - time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) - if (qcam_ready2(qcam) == value) - return 0; - - /* If the camera didn't respond within 1/25 second, poll slowly - for a while. */ - for (i = 0; i < 50; i++) { - if (qcam_ready2(qcam) == value) - return 0; - msleep_interruptible(100); - } - - /* Probably somebody pulled the plug out. Not much we can do. */ - v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value, - parport_read_status(qcam->pport), - parport_read_control(qcam->pport), - parport_read_data(qcam->pport)); - return 1; -} - -static int qcam_read_data(struct qcam *qcam) -{ - unsigned int idata; - - qcam_set_ack(qcam, 0); - if (qcam_await_ready1(qcam, 1)) - return -1; - idata = parport_read_status(qcam->pport) & 0xf0; - qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) - return -1; - idata |= parport_read_status(qcam->pport) >> 4; - return idata; -} - -static int qcam_write_data(struct qcam *qcam, unsigned int data) -{ - struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; - unsigned int idata; - - parport_write_data(qcam->pport, data); - idata = qcam_read_data(qcam); - if (data != idata) { - v4l2_warn(v4l2_dev, "sent %x but received %x\n", data, - idata); - return 1; - } - return 0; -} - -static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data) -{ - if (qcam_write_data(qcam, cmd)) - return -1; - if (qcam_write_data(qcam, data)) - return -1; - return 0; -} - -static inline int qcam_get(struct qcam *qcam, unsigned int cmd) -{ - if (qcam_write_data(qcam, cmd)) - return -1; - return qcam_read_data(qcam); -} - -static int qc_detect(struct qcam *qcam) -{ - unsigned int stat, ostat, i, count = 0; - - /* The probe routine below is not very reliable. The IEEE-1284 - probe takes precedence. */ - /* XXX Currently parport provides no way to distinguish between - "the IEEE probe was not done" and "the probe was done, but - no device was found". Fix this one day. */ - if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA - && qcam->pport->probe_info[0].model - && !strcmp(qcam->pdev->port->probe_info[0].model, - "Color QuickCam 2.0")) { - printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n"); - return 1; - } - - if (probe < 2) - return 0; - - parport_write_control(qcam->pport, 0xc); - - /* look for a heartbeat */ - ostat = stat = parport_read_status(qcam->pport); - for (i = 0; i < 250; i++) { - mdelay(1); - stat = parport_read_status(qcam->pport); - if (ostat != stat) { - if (++count >= 3) - return 1; - ostat = stat; - } - } - - /* Reset the camera and try again */ - parport_write_control(qcam->pport, 0xc); - parport_write_control(qcam->pport, 0x8); - mdelay(1); - parport_write_control(qcam->pport, 0xc); - mdelay(1); - count = 0; - - ostat = stat = parport_read_status(qcam->pport); - for (i = 0; i < 250; i++) { - mdelay(1); - stat = parport_read_status(qcam->pport); - if (ostat != stat) { - if (++count >= 3) - return 1; - ostat = stat; - } - } - - /* no (or flatline) camera, give up */ - return 0; -} - -static void qc_reset(struct qcam *qcam) -{ - parport_write_control(qcam->pport, 0xc); - parport_write_control(qcam->pport, 0x8); - mdelay(1); - parport_write_control(qcam->pport, 0xc); - mdelay(1); -} - -/* Reset the QuickCam and program for brightness, contrast, - * white-balance, and resolution. */ - -static void qc_setup(struct qcam *qcam) -{ - qc_reset(qcam); - - /* Set the brightness. */ - qcam_set(qcam, 11, qcam->brightness); - - /* Set the height and width. These refer to the actual - CCD area *before* applying the selected decimation. */ - qcam_set(qcam, 17, qcam->ccd_height); - qcam_set(qcam, 19, qcam->ccd_width / 2); - - /* Set top and left. */ - qcam_set(qcam, 0xd, qcam->top); - qcam_set(qcam, 0xf, qcam->left); - - /* Set contrast and white balance. */ - qcam_set(qcam, 0x19, qcam->contrast); - qcam_set(qcam, 0x1f, qcam->whitebal); - - /* Set the speed. */ - qcam_set(qcam, 45, 2); -} - -/* Read some bytes from the camera and put them in the buffer. - nbytes should be a multiple of 3, because bidirectional mode gives - us three bytes at a time. */ - -static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes) -{ - unsigned int bytes = 0; - - qcam_set_ack(qcam, 0); - if (qcam->bidirectional) { - /* It's a bidirectional port */ - while (bytes < nbytes) { - unsigned int lo1, hi1, lo2, hi2; - unsigned char r, g, b; - - if (qcam_await_ready2(qcam, 1)) - return bytes; - lo1 = parport_read_data(qcam->pport) >> 1; - hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(qcam, 1); - if (qcam_await_ready2(qcam, 0)) - return bytes; - lo2 = parport_read_data(qcam->pport) >> 1; - hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(qcam, 0); - r = lo1 | ((hi1 & 1) << 7); - g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); - b = lo2 | ((hi2 & 1) << 7); - if (force_rgb) { - buf[bytes++] = r; - buf[bytes++] = g; - buf[bytes++] = b; - } else { - buf[bytes++] = b; - buf[bytes++] = g; - buf[bytes++] = r; - } - } - } else { - /* It's a unidirectional port */ - int i = 0, n = bytes; - unsigned char rgb[3]; - - while (bytes < nbytes) { - unsigned int hi, lo; - - if (qcam_await_ready1(qcam, 1)) - return bytes; - hi = (parport_read_status(qcam->pport) & 0xf0); - qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) - return bytes; - lo = (parport_read_status(qcam->pport) & 0xf0); - qcam_set_ack(qcam, 0); - /* flip some bits */ - rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; - if (i >= 2) { -get_fragment: - if (force_rgb) { - buf[n++] = rgb[0]; - buf[n++] = rgb[1]; - buf[n++] = rgb[2]; - } else { - buf[n++] = rgb[2]; - buf[n++] = rgb[1]; - buf[n++] = rgb[0]; - } - } - } - if (i) { - i = 0; - goto get_fragment; - } - } - return bytes; -} - -#define BUFSZ 150 - -static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len) -{ - struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; - unsigned lines, pixelsperline; - unsigned int is_bi_dir = qcam->bidirectional; - size_t wantlen, outptr = 0; - char tmpbuf[BUFSZ]; - - if (!access_ok(VERIFY_WRITE, buf, len)) - return -EFAULT; - - /* Wait for camera to become ready */ - for (;;) { - int i = qcam_get(qcam, 41); - - if (i == -1) { - qc_setup(qcam); - return -EIO; - } - if ((i & 0x80) == 0) - break; - schedule(); - } - - if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1)) - return -EIO; - - lines = qcam->height; - pixelsperline = qcam->width; - - if (is_bi_dir) { - /* Turn the port around */ - parport_data_reverse(qcam->pport); - mdelay(3); - qcam_set_ack(qcam, 0); - if (qcam_await_ready1(qcam, 1)) { - qc_setup(qcam); - return -EIO; - } - qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) { - qc_setup(qcam); - return -EIO; - } - } - - wantlen = lines * pixelsperline * 24 / 8; - - while (wantlen) { - size_t t, s; - - s = (wantlen > BUFSZ) ? BUFSZ : wantlen; - t = qcam_read_bytes(qcam, tmpbuf, s); - if (outptr < len) { - size_t sz = len - outptr; - - if (sz > t) - sz = t; - if (__copy_to_user(buf + outptr, tmpbuf, sz)) - break; - outptr += sz; - } - wantlen -= t; - if (t < s) - break; - cond_resched(); - } - - len = outptr; - - if (wantlen) { - v4l2_err(v4l2_dev, "short read.\n"); - if (is_bi_dir) - parport_data_forward(qcam->pport); - qc_setup(qcam); - return len; - } - - if (is_bi_dir) { - int l; - - do { - l = qcam_read_bytes(qcam, tmpbuf, 3); - cond_resched(); - } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); - if (force_rgb) { - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - v4l2_err(v4l2_dev, "bad EOF\n"); - } else { - if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - v4l2_err(v4l2_dev, "bad EOF\n"); - } - qcam_set_ack(qcam, 0); - if (qcam_await_ready1(qcam, 1)) { - v4l2_err(v4l2_dev, "no ack after EOF\n"); - parport_data_forward(qcam->pport); - qc_setup(qcam); - return len; - } - parport_data_forward(qcam->pport); - mdelay(3); - qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) { - v4l2_err(v4l2_dev, "no ack to port turnaround\n"); - qc_setup(qcam); - return len; - } - } else { - int l; - - do { - l = qcam_read_bytes(qcam, tmpbuf, 1); - cond_resched(); - } while (l && tmpbuf[0] == 0x7e); - l = qcam_read_bytes(qcam, tmpbuf + 1, 2); - if (force_rgb) { - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - v4l2_err(v4l2_dev, "bad EOF\n"); - } else { - if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - v4l2_err(v4l2_dev, "bad EOF\n"); - } - } - - qcam_write_data(qcam, 0); - return len; -} - -/* - * Video4linux interfacing - */ - -static int qcam_querycap(struct file *file, void *priv, - struct v4l2_capability *vcap) -{ - struct qcam *qcam = video_drvdata(file); - - strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card)); - strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); - vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; - vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - if (vin->index > 0) - return -EINVAL; - strlcpy(vin->name, "Camera", sizeof(vin->name)); - vin->type = V4L2_INPUT_TYPE_CAMERA; - vin->audioset = 0; - vin->tuner = 0; - vin->std = 0; - vin->status = 0; - return 0; -} - -static int qcam_g_input(struct file *file, void *fh, unsigned int *inp) -{ - *inp = 0; - return 0; -} - -static int qcam_s_input(struct file *file, void *fh, unsigned int inp) -{ - return (inp > 0) ? -EINVAL : 0; -} - -static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct qcam *qcam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - pix->width = qcam->width; - pix->height = qcam->height; - pix->pixelformat = V4L2_PIX_FMT_RGB24; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 3 * qcam->width; - pix->sizeimage = 3 * qcam->width * qcam->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->height < 60 || pix->width < 80) { - pix->height = 60; - pix->width = 80; - } else if (pix->height < 120 || pix->width < 160) { - pix->height = 120; - pix->width = 160; - } else { - pix->height = 240; - pix->width = 320; - } - pix->pixelformat = V4L2_PIX_FMT_RGB24; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 3 * pix->width; - pix->sizeimage = 3 * pix->width * pix->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct qcam *qcam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - int ret = qcam_try_fmt_vid_cap(file, fh, fmt); - - if (ret) - return ret; - switch (pix->height) { - case 60: - qcam->mode = QC_DECIMATION_4; - break; - case 120: - qcam->mode = QC_DECIMATION_2; - break; - default: - qcam->mode = QC_DECIMATION_1; - break; - } - - mutex_lock(&qcam->lock); - qcam->mode |= QC_MILLIONS; - qcam->height = pix->height; - qcam->width = pix->width; - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return 0; -} - -static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "RGB 8:8:8", V4L2_PIX_FMT_RGB24, - { 0, 0, 0, 0 } - }, - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 0) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -static ssize_t qcam_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct qcam *qcam = video_drvdata(file); - int len; - - mutex_lock(&qcam->lock); - parport_claim_or_block(qcam->pdev); - /* Probably should have a semaphore against multiple users */ - len = qc_capture(qcam, buf, count); - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return len; -} - -static int qcam_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct qcam *qcam = - container_of(ctrl->handler, struct qcam, hdl); - int ret = 0; - - mutex_lock(&qcam->lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - qcam->brightness = ctrl->val; - break; - case V4L2_CID_CONTRAST: - qcam->contrast = ctrl->val; - break; - case V4L2_CID_GAMMA: - qcam->whitebal = ctrl->val; - break; - default: - ret = -EINVAL; - break; - } - if (ret == 0) { - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - } - mutex_unlock(&qcam->lock); - return ret; -} - -static const struct v4l2_file_operations qcam_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = v4l2_ctrl_poll, - .unlocked_ioctl = video_ioctl2, - .read = qcam_read, -}; - -static const struct v4l2_ioctl_ops qcam_ioctl_ops = { - .vidioc_querycap = qcam_querycap, - .vidioc_g_input = qcam_g_input, - .vidioc_s_input = qcam_s_input, - .vidioc_enum_input = qcam_enum_input, - .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct v4l2_ctrl_ops qcam_ctrl_ops = { - .s_ctrl = qcam_s_ctrl, -}; - -/* Initialize the QuickCam driver control structure. */ - -static struct qcam *qcam_init(struct parport *port) -{ - struct qcam *qcam; - struct v4l2_device *v4l2_dev; - - qcam = kzalloc(sizeof(*qcam), GFP_KERNEL); - if (qcam == NULL) - return NULL; - - v4l2_dev = &qcam->v4l2_dev; - strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name)); - - if (v4l2_device_register(NULL, v4l2_dev) < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - kfree(qcam); - return NULL; - } - - v4l2_ctrl_handler_init(&qcam->hdl, 3); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 240); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 192); - v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops, - V4L2_CID_GAMMA, 0, 255, 1, 128); - if (qcam->hdl.error) { - v4l2_err(v4l2_dev, "couldn't register controls\n"); - v4l2_ctrl_handler_free(&qcam->hdl); - kfree(qcam); - return NULL; - } - - qcam->pport = port; - qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL, - NULL, 0, NULL); - - qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; - - if (qcam->pdev == NULL) { - v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); - v4l2_ctrl_handler_free(&qcam->hdl); - kfree(qcam); - return NULL; - } - - strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name)); - qcam->vdev.v4l2_dev = v4l2_dev; - qcam->vdev.fops = &qcam_fops; - qcam->vdev.ioctl_ops = &qcam_ioctl_ops; - qcam->vdev.release = video_device_release_empty; - qcam->vdev.ctrl_handler = &qcam->hdl; - video_set_drvdata(&qcam->vdev, qcam); - - mutex_init(&qcam->lock); - qcam->width = qcam->ccd_width = 320; - qcam->height = qcam->ccd_height = 240; - qcam->mode = QC_MILLIONS | QC_DECIMATION_1; - qcam->contrast = 192; - qcam->brightness = 240; - qcam->whitebal = 128; - qcam->top = 1; - qcam->left = 14; - return qcam; -} - -static int init_cqcam(struct parport *port) -{ - struct qcam *qcam; - struct v4l2_device *v4l2_dev; - - if (parport[0] != -1) { - /* The user gave specific instructions */ - int i, found = 0; - - for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) { - if (parport[0] == port->number) - found = 1; - } - if (!found) - return -ENODEV; - } - - if (num_cams == MAX_CAMS) - return -ENOSPC; - - qcam = qcam_init(port); - if (qcam == NULL) - return -ENODEV; - - v4l2_dev = &qcam->v4l2_dev; - - parport_claim_or_block(qcam->pdev); - - qc_reset(qcam); - - if (probe && qc_detect(qcam) == 0) { - parport_release(qcam->pdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - qc_setup(qcam); - - parport_release(qcam->pdev); - - if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n", - qcam->pport->name); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n", - video_device_node_name(&qcam->vdev), qcam->pport->name); - - qcams[num_cams++] = qcam; - - return 0; -} - -static void close_cqcam(struct qcam *qcam) -{ - video_unregister_device(&qcam->vdev); - v4l2_ctrl_handler_free(&qcam->hdl); - parport_unregister_device(qcam->pdev); - kfree(qcam); -} - -static void cq_attach(struct parport *port) -{ - init_cqcam(port); -} - -static void cq_detach(struct parport *port) -{ - /* Write this some day. */ -} - -static struct parport_driver cqcam_driver = { - .name = "cqcam", - .attach = cq_attach, - .detach = cq_detach, -}; - -static int __init cqcam_init(void) -{ - printk(KERN_INFO BANNER "\n"); - - return parport_register_driver(&cqcam_driver); -} - -static void __exit cqcam_cleanup(void) -{ - unsigned int i; - - for (i = 0; i < num_cams; i++) - close_cqcam(qcams[i]); - - parport_unregister_driver(&cqcam_driver); -} - -MODULE_AUTHOR("Philip Blundell "); -MODULE_DESCRIPTION(BANNER); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.4"); - -module_init(cqcam_init); -module_exit(cqcam_cleanup); diff --git a/drivers/staging/media/parport/pms.c b/drivers/staging/media/parport/pms.c deleted file mode 100644 index e6b497528cea..000000000000 --- a/drivers/staging/media/parport/pms.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* - * Media Vision Pro Movie Studio - * or - * "all you need is an I2C bus some RAM and a prayer" - * - * This draws heavily on code - * - * (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994 - * Kiefernring 15 - * 14478 Potsdam, Germany - * - * Most of this code is directly derived from his userspace driver. - * His driver works so send any reports to alan@lxorguk.ukuu.org.uk - * unless the userspace driver also doesn't work for you... - * - * Changes: - * 25-11-2009 Hans Verkuil - * - converted to version 2 of the V4L API. - * 08/07/2003 Daniele Bellucci - * - pms_capture: report back -EFAULT - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.5"); - -#define MOTOROLA 1 -#define PHILIPS2 2 /* SAA7191 */ -#define PHILIPS1 3 -#define MVVMEMORYWIDTH 0x40 /* 512 bytes */ - -struct i2c_info { - u8 slave; - u8 sub; - u8 data; - u8 hits; -}; - -struct pms { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct v4l2_ctrl_handler hdl; - int height; - int width; - int depth; - int input; - struct mutex lock; - int i2c_count; - struct i2c_info i2cinfo[64]; - - int decoder; - int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ - v4l2_std_id std; - int io; - int data; - void __iomem *mem; -}; - -/* - * I/O ports and Shared Memory - */ - -static int io_port = 0x250; -module_param(io_port, int, 0); - -static int mem_base = 0xc8000; -module_param(mem_base, int, 0); - -static int video_nr = -1; -module_param(video_nr, int, 0); - - -static inline void mvv_write(struct pms *dev, u8 index, u8 value) -{ - outw(index | (value << 8), dev->io); -} - -static inline u8 mvv_read(struct pms *dev, u8 index) -{ - outb(index, dev->io); - return inb(dev->data); -} - -static int pms_i2c_stat(struct pms *dev, u8 slave) -{ - int counter = 0; - int i; - - outb(0x28, dev->io); - - while ((inb(dev->data) & 0x01) == 0) - if (counter++ == 256) - break; - - while ((inb(dev->data) & 0x01) != 0) - if (counter++ == 256) - break; - - outb(slave, dev->io); - - counter = 0; - while ((inb(dev->data) & 0x01) == 0) - if (counter++ == 256) - break; - - while ((inb(dev->data) & 0x01) != 0) - if (counter++ == 256) - break; - - for (i = 0; i < 12; i++) { - char st = inb(dev->data); - - if ((st & 2) != 0) - return -1; - if ((st & 1) == 0) - break; - } - outb(0x29, dev->io); - return inb(dev->data); -} - -static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data) -{ - int skip = 0; - int count; - int i; - - for (i = 0; i < dev->i2c_count; i++) { - if ((dev->i2cinfo[i].slave == slave) && - (dev->i2cinfo[i].sub == sub)) { - if (dev->i2cinfo[i].data == data) - skip = 1; - dev->i2cinfo[i].data = data; - i = dev->i2c_count + 1; - } - } - - if (i == dev->i2c_count && dev->i2c_count < 64) { - dev->i2cinfo[dev->i2c_count].slave = slave; - dev->i2cinfo[dev->i2c_count].sub = sub; - dev->i2cinfo[dev->i2c_count].data = data; - dev->i2c_count++; - } - - if (skip) - return 0; - - mvv_write(dev, 0x29, sub); - mvv_write(dev, 0x2A, data); - mvv_write(dev, 0x28, slave); - - outb(0x28, dev->io); - - count = 0; - while ((inb(dev->data) & 1) == 0) - if (count > 255) - break; - while ((inb(dev->data) & 1) != 0) - if (count > 255) - break; - - count = inb(dev->data); - - if (count & 2) - return -1; - return count; -} - -static int pms_i2c_read(struct pms *dev, int slave, int sub) -{ - int i; - - for (i = 0; i < dev->i2c_count; i++) { - if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub) - return dev->i2cinfo[i].data; - } - return 0; -} - - -static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or) -{ - u8 tmp; - - tmp = pms_i2c_read(dev, slave, sub); - tmp = (tmp & and) | or; - pms_i2c_write(dev, slave, sub, tmp); -} - -/* - * Control functions - */ - - -static void pms_videosource(struct pms *dev, short source) -{ - switch (dev->decoder) { - case MOTOROLA: - break; - case PHILIPS2: - pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0); - break; - case PHILIPS1: - break; - } - mvv_write(dev, 0x2E, 0x31); - /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30); - But could not make this work correctly. Only Composite input - worked for me. */ -} - -static void pms_hue(struct pms *dev, short hue) -{ - switch (dev->decoder) { - case MOTOROLA: - pms_i2c_write(dev, 0x8a, 0x00, hue); - break; - case PHILIPS2: - pms_i2c_write(dev, 0x8a, 0x07, hue); - break; - case PHILIPS1: - pms_i2c_write(dev, 0x42, 0x07, hue); - break; - } -} - -static void pms_saturation(struct pms *dev, short sat) -{ - switch (dev->decoder) { - case MOTOROLA: - pms_i2c_write(dev, 0x8a, 0x00, sat); - break; - case PHILIPS1: - pms_i2c_write(dev, 0x42, 0x12, sat); - break; - } -} - - -static void pms_contrast(struct pms *dev, short contrast) -{ - switch (dev->decoder) { - case MOTOROLA: - pms_i2c_write(dev, 0x8a, 0x00, contrast); - break; - case PHILIPS1: - pms_i2c_write(dev, 0x42, 0x13, contrast); - break; - } -} - -static void pms_brightness(struct pms *dev, short brightness) -{ - switch (dev->decoder) { - case MOTOROLA: - pms_i2c_write(dev, 0x8a, 0x00, brightness); - pms_i2c_write(dev, 0x8a, 0x00, brightness); - pms_i2c_write(dev, 0x8a, 0x00, brightness); - break; - case PHILIPS1: - pms_i2c_write(dev, 0x42, 0x19, brightness); - break; - } -} - - -static void pms_format(struct pms *dev, short format) -{ - int target; - - dev->standard = format; - - if (dev->decoder == PHILIPS1) - target = 0x42; - else if (dev->decoder == PHILIPS2) - target = 0x8a; - else - return; - - switch (format) { - case 0: /* Auto */ - pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); - pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80); - break; - case 1: /* NTSC */ - pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); - pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40); - break; - case 2: /* PAL */ - pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); - pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); - break; - case 3: /* SECAM */ - pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01); - pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); - break; - } -} - -#ifdef FOR_FUTURE_EXPANSION - -/* - * These features of the PMS card are not currently exposes. They - * could become a private v4l ioctl for PMSCONFIG or somesuch if - * people need it. We also don't yet use the PMS interrupt. - */ - -static void pms_hstart(struct pms *dev, short start) -{ - switch (dev->decoder) { - case PHILIPS1: - pms_i2c_write(dev, 0x8a, 0x05, start); - pms_i2c_write(dev, 0x8a, 0x18, start); - break; - case PHILIPS2: - pms_i2c_write(dev, 0x42, 0x05, start); - pms_i2c_write(dev, 0x42, 0x18, start); - break; - } -} - -/* - * Bandpass filters - */ - -static void pms_bandpass(struct pms *dev, short pass) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4); -} - -static void pms_antisnow(struct pms *dev, short snow) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2); -} - -static void pms_sharpness(struct pms *dev, short sharp) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03); -} - -static void pms_chromaagc(struct pms *dev, short agc) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5); -} - -static void pms_vertnoise(struct pms *dev, short noise) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3); -} - -static void pms_forcecolour(struct pms *dev, short colour) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7); -} - -static void pms_antigamma(struct pms *dev, short gamma) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7); -} - -static void pms_prefilter(struct pms *dev, short filter) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6); -} - -static void pms_hfilter(struct pms *dev, short filter) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5); -} - -static void pms_vfilter(struct pms *dev, short filter) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5); -} - -static void pms_killcolour(struct pms *dev, short colour) -{ - if (dev->decoder == PHILIPS2) { - pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3); - pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3); - } else if (dev->decoder == PHILIPS1) { - pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3); - pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3); - } -} - -static void pms_chromagain(struct pms *dev, short chroma) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_write(dev, 0x8a, 0x11, chroma); - else if (dev->decoder == PHILIPS1) - pms_i2c_write(dev, 0x42, 0x11, chroma); -} - - -static void pms_spacialcompl(struct pms *dev, short data) -{ - mvv_write(dev, 0x3b, data); -} - -static void pms_spacialcomph(struct pms *dev, short data) -{ - mvv_write(dev, 0x3a, data); -} - -static void pms_vstart(struct pms *dev, short start) -{ - mvv_write(dev, 0x16, start); - mvv_write(dev, 0x17, (start >> 8) & 0x01); -} - -#endif - -static void pms_secamcross(struct pms *dev, short cross) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5); -} - - -static void pms_swsense(struct pms *dev, short sense) -{ - if (dev->decoder == PHILIPS2) { - pms_i2c_write(dev, 0x8a, 0x0a, sense); - pms_i2c_write(dev, 0x8a, 0x0b, sense); - } else if (dev->decoder == PHILIPS1) { - pms_i2c_write(dev, 0x42, 0x0a, sense); - pms_i2c_write(dev, 0x42, 0x0b, sense); - } -} - - -static void pms_framerate(struct pms *dev, short frr) -{ - int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25; - - if (frr == 0) - return; - fps = fps/frr; - mvv_write(dev, 0x14, 0x80 | fps); - mvv_write(dev, 0x15, 1); -} - -static void pms_vert(struct pms *dev, u8 deciden, u8 decinum) -{ - mvv_write(dev, 0x1c, deciden); /* Denominator */ - mvv_write(dev, 0x1d, decinum); /* Numerator */ -} - -/* - * Turn 16bit ratios into best small ratio the chipset can grok - */ - -static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden) -{ - /* Knock it down by / 5 once */ - if (decinum % 5 == 0) { - deciden /= 5; - decinum /= 5; - } - /* - * 3's - */ - while (decinum % 3 == 0 && deciden % 3 == 0) { - deciden /= 3; - decinum /= 3; - } - /* - * 2's - */ - while (decinum % 2 == 0 && deciden % 2 == 0) { - decinum /= 2; - deciden /= 2; - } - /* - * Fudgyify - */ - while (deciden > 32) { - deciden /= 2; - decinum = (decinum + 1) / 2; - } - if (deciden == 32) - deciden--; - pms_vert(dev, deciden, decinum); -} - -static void pms_horzdeci(struct pms *dev, short decinum, short deciden) -{ - if (decinum <= 512) { - if (decinum % 5 == 0) { - decinum /= 5; - deciden /= 5; - } - } else { - decinum = 512; - deciden = 640; /* 768 would be ideal */ - } - - while (((decinum | deciden) & 1) == 0) { - decinum >>= 1; - deciden >>= 1; - } - while (deciden > 32) { - deciden >>= 1; - decinum = (decinum + 1) >> 1; - } - if (deciden == 32) - deciden--; - - mvv_write(dev, 0x24, 0x80 | deciden); - mvv_write(dev, 0x25, decinum); -} - -static void pms_resolution(struct pms *dev, short width, short height) -{ - int fg_height; - - fg_height = height; - if (fg_height > 280) - fg_height = 280; - - mvv_write(dev, 0x18, fg_height); - mvv_write(dev, 0x19, fg_height >> 8); - - if (dev->std & V4L2_STD_525_60) { - mvv_write(dev, 0x1a, 0xfc); - mvv_write(dev, 0x1b, 0x00); - if (height > fg_height) - pms_vertdeci(dev, 240, 240); - else - pms_vertdeci(dev, fg_height, 240); - } else { - mvv_write(dev, 0x1a, 0x1a); - mvv_write(dev, 0x1b, 0x01); - if (fg_height > 256) - pms_vertdeci(dev, 270, 270); - else - pms_vertdeci(dev, fg_height, 270); - } - mvv_write(dev, 0x12, 0); - mvv_write(dev, 0x13, MVVMEMORYWIDTH); - mvv_write(dev, 0x42, 0x00); - mvv_write(dev, 0x43, 0x00); - mvv_write(dev, 0x44, MVVMEMORYWIDTH); - - mvv_write(dev, 0x22, width + 8); - mvv_write(dev, 0x23, (width + 8) >> 8); - - if (dev->std & V4L2_STD_525_60) - pms_horzdeci(dev, width, 640); - else - pms_horzdeci(dev, width + 8, 768); - - mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe); - mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01); - mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd); - mvv_write(dev, 0x32, 0x00); - mvv_write(dev, 0x33, MVVMEMORYWIDTH); -} - - -/* - * Set Input - */ - -static void pms_vcrinput(struct pms *dev, short input) -{ - if (dev->decoder == PHILIPS2) - pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7); - else if (dev->decoder == PHILIPS1) - pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7); -} - - -static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) -{ - int y; - int dw = 2 * dev->width; - char *tmp; /* using a temp buffer is faster than direct */ - int cnt = 0; - int len = 0; - unsigned char r8 = 0x5; /* value for reg8 */ - - tmp = kmalloc(dw + 32, GFP_KERNEL); - if (!tmp) - return 0; - - if (rgb555) - r8 |= 0x20; /* else use untranslated rgb = 565 */ - mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */ - -/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ - - for (y = 0; y < dev->height; y++) { - writeb(0, dev->mem); /* synchronisiert neue Zeile */ - - /* - * This is in truth a fifo, be very careful as if you - * forgot this odd things will occur 8) - */ - - memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */ - cnt -= dev->height; - while (cnt <= 0) { - /* - * Don't copy too far - */ - int dt = dw; - if (dt + len > count) - dt = count - len; - cnt += dev->height; - if (copy_to_user(buf, tmp + 32, dt)) - return len ? len : -EFAULT; - buf += dt; - len += dt; - } - } - kfree(tmp); - return len; -} - - -/* - * Video4linux interfacing - */ - -static int pms_querycap(struct file *file, void *priv, - struct v4l2_capability *vcap) -{ - struct pms *dev = video_drvdata(file); - - strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), - "ISA:%s", dev->v4l2_dev.name); - vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; - vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - static const char *inputs[4] = { - "Composite", - "S-Video", - "Composite (VCR)", - "S-Video (VCR)" - }; - - if (vin->index > 3) - return -EINVAL; - strlcpy(vin->name, inputs[vin->index], sizeof(vin->name)); - vin->type = V4L2_INPUT_TYPE_CAMERA; - vin->audioset = 0; - vin->tuner = 0; - vin->std = V4L2_STD_ALL; - vin->status = 0; - return 0; -} - -static int pms_g_input(struct file *file, void *fh, unsigned int *inp) -{ - struct pms *dev = video_drvdata(file); - - *inp = dev->input; - return 0; -} - -static int pms_s_input(struct file *file, void *fh, unsigned int inp) -{ - struct pms *dev = video_drvdata(file); - - if (inp > 3) - return -EINVAL; - - dev->input = inp; - pms_videosource(dev, inp & 1); - pms_vcrinput(dev, inp >> 1); - return 0; -} - -static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std) -{ - struct pms *dev = video_drvdata(file); - - *std = dev->std; - return 0; -} - -static int pms_s_std(struct file *file, void *fh, v4l2_std_id std) -{ - struct pms *dev = video_drvdata(file); - int ret = 0; - - dev->std = std; - if (dev->std & V4L2_STD_NTSC) { - pms_framerate(dev, 30); - pms_secamcross(dev, 0); - pms_format(dev, 1); - } else if (dev->std & V4L2_STD_PAL) { - pms_framerate(dev, 25); - pms_secamcross(dev, 0); - pms_format(dev, 2); - } else if (dev->std & V4L2_STD_SECAM) { - pms_framerate(dev, 25); - pms_secamcross(dev, 1); - pms_format(dev, 2); - } else { - ret = -EINVAL; - } - /* - switch (v->mode) { - case VIDEO_MODE_AUTO: - pms_framerate(dev, 25); - pms_secamcross(dev, 0); - pms_format(dev, 0); - break; - }*/ - return ret; -} - -static int pms_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct pms *dev = container_of(ctrl->handler, struct pms, hdl); - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - pms_brightness(dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - pms_contrast(dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - pms_saturation(dev, ctrl->val); - break; - case V4L2_CID_HUE: - pms_hue(dev, ctrl->val); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct pms *dev = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - pix->width = dev->width; - pix->height = dev->height; - pix->pixelformat = dev->width == 15 ? - V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 2 * dev->width; - pix->sizeimage = 2 * dev->width * dev->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->height < 16 || pix->height > 480) - return -EINVAL; - if (pix->width < 16 || pix->width > 640) - return -EINVAL; - if (pix->pixelformat != V4L2_PIX_FMT_RGB555 && - pix->pixelformat != V4L2_PIX_FMT_RGB565) - return -EINVAL; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 2 * pix->width; - pix->sizeimage = 2 * pix->width * pix->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SRGB; - return 0; -} - -static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct pms *dev = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - int ret = pms_try_fmt_vid_cap(file, fh, fmt); - - if (ret) - return ret; - dev->width = pix->width; - dev->height = pix->height; - dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16; - pms_resolution(dev, dev->width, dev->height); - /* Ok we figured out what to use from our wide choice */ - return 0; -} - -static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "RGB 5:5:5", V4L2_PIX_FMT_RGB555, - { 0, 0, 0, 0 } - }, - { 1, 0, 0, - "RGB 5:6:5", V4L2_PIX_FMT_RGB565, - { 0, 0, 0, 0 } - }, - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 1) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -static ssize_t pms_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct pms *dev = video_drvdata(file); - int len; - - len = pms_capture(dev, buf, (dev->depth == 15), count); - return len; -} - -static unsigned int pms_poll(struct file *file, struct poll_table_struct *wait) -{ - struct v4l2_fh *fh = file->private_data; - unsigned int res = POLLIN | POLLRDNORM; - - if (v4l2_event_pending(fh)) - res |= POLLPRI; - poll_wait(file, &fh->wait, wait); - return res; -} - -static const struct v4l2_file_operations pms_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = pms_poll, - .unlocked_ioctl = video_ioctl2, - .read = pms_read, -}; - -static const struct v4l2_ioctl_ops pms_ioctl_ops = { - .vidioc_querycap = pms_querycap, - .vidioc_g_input = pms_g_input, - .vidioc_s_input = pms_s_input, - .vidioc_enum_input = pms_enum_input, - .vidioc_g_std = pms_g_std, - .vidioc_s_std = pms_s_std, - .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -/* - * Probe for and initialise the Mediavision PMS - */ - -static int init_mediavision(struct pms *dev) -{ - int idec, decst; - int i; - static const unsigned char i2c_defs[] = { - 0x4c, 0x30, 0x00, 0xe8, - 0xb6, 0xe2, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x98, - 0x00, 0x00, 0x00, 0x00, - 0x34, 0x0a, 0xf4, 0xce, - 0xe4 - }; - - dev->mem = ioremap(mem_base, 0x800); - if (!dev->mem) - return -ENOMEM; - - if (!request_region(0x9a01, 1, "Mediavision PMS config")) { - printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n"); - iounmap(dev->mem); - return -EBUSY; - } - if (!request_region(dev->io, 3, "Mediavision PMS")) { - printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io); - release_region(0x9a01, 1); - iounmap(dev->mem); - return -EBUSY; - } - outb(0xb8, 0x9a01); /* Unlock */ - outb(dev->io >> 4, 0x9a01); /* Set IO port */ - - - decst = pms_i2c_stat(dev, 0x43); - - if (decst != -1) - idec = 2; - else if (pms_i2c_stat(dev, 0xb9) != -1) - idec = 3; - else if (pms_i2c_stat(dev, 0x8b) != -1) - idec = 1; - else - idec = 0; - - printk(KERN_INFO "PMS type is %d\n", idec); - if (idec == 0) { - release_region(dev->io, 3); - release_region(0x9a01, 1); - iounmap(dev->mem); - return -ENODEV; - } - - /* - * Ok we have a PMS of some sort - */ - - mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */ - - /* Ok now load the defaults */ - - for (i = 0; i < 0x19; i++) { - if (i2c_defs[i] == 0xff) - pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00); - else - pms_i2c_write(dev, 0x8a, i, i2c_defs[i]); - } - - pms_i2c_write(dev, 0xb8, 0x00, 0x12); - pms_i2c_write(dev, 0xb8, 0x04, 0x00); - pms_i2c_write(dev, 0xb8, 0x07, 0x00); - pms_i2c_write(dev, 0xb8, 0x08, 0x00); - pms_i2c_write(dev, 0xb8, 0x09, 0xff); - pms_i2c_write(dev, 0xb8, 0x0a, 0x00); - pms_i2c_write(dev, 0xb8, 0x0b, 0x10); - pms_i2c_write(dev, 0xb8, 0x10, 0x03); - - mvv_write(dev, 0x01, 0x00); - mvv_write(dev, 0x05, 0xa0); - mvv_write(dev, 0x08, 0x25); - mvv_write(dev, 0x09, 0x00); - mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH); - - mvv_write(dev, 0x10, 0x02); - mvv_write(dev, 0x1e, 0x0c); - mvv_write(dev, 0x1f, 0x03); - mvv_write(dev, 0x26, 0x06); - - mvv_write(dev, 0x2b, 0x00); - mvv_write(dev, 0x2c, 0x20); - mvv_write(dev, 0x2d, 0x00); - mvv_write(dev, 0x2f, 0x70); - mvv_write(dev, 0x32, 0x00); - mvv_write(dev, 0x33, MVVMEMORYWIDTH); - mvv_write(dev, 0x34, 0x00); - mvv_write(dev, 0x35, 0x00); - mvv_write(dev, 0x3a, 0x80); - mvv_write(dev, 0x3b, 0x10); - mvv_write(dev, 0x20, 0x00); - mvv_write(dev, 0x21, 0x00); - mvv_write(dev, 0x30, 0x22); - return 0; -} - -/* - * Initialization and module stuff - */ - -#ifndef MODULE -static int enable; -module_param(enable, int, 0); -#endif - -static const struct v4l2_ctrl_ops pms_ctrl_ops = { - .s_ctrl = pms_s_ctrl, -}; - -static int pms_probe(struct device *pdev, unsigned int card) -{ - struct pms *dev; - struct v4l2_device *v4l2_dev; - struct v4l2_ctrl_handler *hdl; - int res; - -#ifndef MODULE - if (!enable) { - pr_err("PMS: not enabled, use pms.enable=1 to probe\n"); - return -ENODEV; - } -#endif - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; - - dev->decoder = PHILIPS2; - dev->io = io_port; - dev->data = io_port + 1; - v4l2_dev = &dev->v4l2_dev; - hdl = &dev->hdl; - - res = v4l2_device_register(pdev, v4l2_dev); - if (res < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - goto free_dev; - } - v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.05\n"); - - res = init_mediavision(dev); - if (res) { - v4l2_err(v4l2_dev, "Board not found.\n"); - goto free_io; - } - - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &pms_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 139); - v4l2_ctrl_new_std(hdl, &pms_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 70); - v4l2_ctrl_new_std(hdl, &pms_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 64); - v4l2_ctrl_new_std(hdl, &pms_ctrl_ops, - V4L2_CID_HUE, 0, 255, 1, 0); - if (hdl->error) { - res = hdl->error; - goto free_hdl; - } - - mutex_init(&dev->lock); - strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); - dev->vdev.v4l2_dev = v4l2_dev; - dev->vdev.ctrl_handler = hdl; - dev->vdev.fops = &pms_fops; - dev->vdev.ioctl_ops = &pms_ioctl_ops; - dev->vdev.release = video_device_release_empty; - dev->vdev.lock = &dev->lock; - dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; - video_set_drvdata(&dev->vdev, dev); - dev->std = V4L2_STD_NTSC_M; - dev->height = 240; - dev->width = 320; - dev->depth = 16; - pms_swsense(dev, 75); - pms_resolution(dev, 320, 240); - pms_videosource(dev, 0); - pms_vcrinput(dev, 0); - v4l2_ctrl_handler_setup(hdl); - res = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr); - if (res >= 0) - return 0; - -free_hdl: - v4l2_ctrl_handler_free(hdl); - v4l2_device_unregister(&dev->v4l2_dev); -free_io: - release_region(dev->io, 3); - release_region(0x9a01, 1); - iounmap(dev->mem); -free_dev: - kfree(dev); - return res; -} - -static int pms_remove(struct device *pdev, unsigned int card) -{ - struct pms *dev = dev_get_drvdata(pdev); - - video_unregister_device(&dev->vdev); - v4l2_ctrl_handler_free(&dev->hdl); - release_region(dev->io, 3); - release_region(0x9a01, 1); - iounmap(dev->mem); - return 0; -} - -static struct isa_driver pms_driver = { - .probe = pms_probe, - .remove = pms_remove, - .driver = { - .name = "pms", - }, -}; - -static int __init pms_init(void) -{ - return isa_register_driver(&pms_driver, 1); -} - -static void __exit pms_exit(void) -{ - isa_unregister_driver(&pms_driver); -} - -module_init(pms_init); -module_exit(pms_exit); diff --git a/drivers/staging/media/parport/w9966.c b/drivers/staging/media/parport/w9966.c deleted file mode 100644 index f7502f3a6a3c..000000000000 --- a/drivers/staging/media/parport/w9966.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - Winbond w9966cf Webcam parport driver. - - Version 0.33 - - Copyright (C) 2001 Jakob Kemi - - 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. -*/ -/* - Supported devices: - *Lifeview FlyCam Supra (using the Philips saa7111a chip) - - Does any other model using the w9966 interface chip exist ? - - Todo: - - *Add a working EPP mode, since DMA ECP read isn't implemented - in the parport drivers. (That's why it's so sloow) - - *Add support for other ccd-control chips than the saa7111 - please send me feedback on what kind of chips you have. - - *Add proper probing. I don't know what's wrong with the IEEE1284 - parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID) - and nibble read seems to be broken for some peripherals. - - *Add probing for onboard SRAM, port directions etc. (if possible) - - *Add support for the hardware compressed modes (maybe using v4l2) - - *Fix better support for the capture window (no skewed images, v4l - interface to capt. window) - - *Probably some bugs that I don't know of - - Please support me by sending feedback! - - Changes: - - Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE - and owner support for newer module locks -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*#define DEBUG*/ /* Undef me for production */ - -#ifdef DEBUG -#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a) -#else -#define DPRINTF(x...) -#endif - -/* - * Defines, simple typedefs etc. - */ - -#define W9966_DRIVERNAME "W9966CF Webcam" -#define W9966_MAXCAMS 4 /* Maximum number of cameras */ -#define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */ -#define W9966_SRAMSIZE 131072 /* 128kb */ -#define W9966_SRAMID 0x02 /* check w9966cf.pdf */ - -/* Empirically determined window limits */ -#define W9966_WND_MIN_X 16 -#define W9966_WND_MIN_Y 14 -#define W9966_WND_MAX_X 705 -#define W9966_WND_MAX_Y 253 -#define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X) -#define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y) - -/* Keep track of our current state */ -#define W9966_STATE_PDEV 0x01 -#define W9966_STATE_CLAIMED 0x02 -#define W9966_STATE_VDEV 0x04 - -#define W9966_I2C_W_ID 0x48 -#define W9966_I2C_R_ID 0x49 -#define W9966_I2C_R_DATA 0x08 -#define W9966_I2C_R_CLOCK 0x04 -#define W9966_I2C_W_DATA 0x02 -#define W9966_I2C_W_CLOCK 0x01 - -struct w9966 { - struct v4l2_device v4l2_dev; - struct v4l2_ctrl_handler hdl; - unsigned char dev_state; - unsigned char i2c_state; - unsigned short ppmode; - struct parport *pport; - struct pardevice *pdev; - struct video_device vdev; - unsigned short width; - unsigned short height; - unsigned char brightness; - signed char contrast; - signed char color; - signed char hue; - struct mutex lock; -}; - -/* - * Module specific properties - */ - -MODULE_AUTHOR("Jakob Kemi "); -MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.33.1"); - -#ifdef MODULE -static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; -#else -static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; -#endif -module_param_array(pardev, charp, NULL, 0); -MODULE_PARM_DESC(pardev, "pardev: where to search for\n" - "\teach camera. 'aggressive' means brute-force search.\n" - "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n" - "\tcam 1 to parport3 and search every parport for cam 2 etc..."); - -static int parmode; -module_param(parmode, int, 0); -MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); - -static int video_nr = -1; -module_param(video_nr, int, 0); - -static struct w9966 w9966_cams[W9966_MAXCAMS]; - -/* - * Private function defines - */ - - -/* Set camera phase flags, so we know what to uninit when terminating */ -static inline void w9966_set_state(struct w9966 *cam, int mask, int val) -{ - cam->dev_state = (cam->dev_state & ~mask) ^ val; -} - -/* Get camera phase flags */ -static inline int w9966_get_state(struct w9966 *cam, int mask, int val) -{ - return ((cam->dev_state & mask) == val); -} - -/* Claim parport for ourself */ -static void w9966_pdev_claim(struct w9966 *cam) -{ - if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) - return; - parport_claim_or_block(cam->pdev); - w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); -} - -/* Release parport for others to use */ -static void w9966_pdev_release(struct w9966 *cam) -{ - if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0)) - return; - parport_release(cam->pdev); - w9966_set_state(cam, W9966_STATE_CLAIMED, 0); -} - -/* Read register from W9966 interface-chip - Expects a claimed pdev - -1 on error, else register data (byte) */ -static int w9966_read_reg(struct w9966 *cam, int reg) -{ - /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ - const unsigned char addr = 0x80 | (reg & 0x1f); - unsigned char val; - - if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) - return -1; - if (parport_write(cam->pport, &addr, 1) != 1) - return -1; - if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0) - return -1; - if (parport_read(cam->pport, &val, 1) != 1) - return -1; - - return val; -} - -/* Write register to W9966 interface-chip - Expects a claimed pdev - -1 on error */ -static int w9966_write_reg(struct w9966 *cam, int reg, int data) -{ - /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ - const unsigned char addr = 0xc0 | (reg & 0x1f); - const unsigned char val = data; - - if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) - return -1; - if (parport_write(cam->pport, &addr, 1) != 1) - return -1; - if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0) - return -1; - if (parport_write(cam->pport, &val, 1) != 1) - return -1; - - return 0; -} - -/* - * Ugly and primitive i2c protocol functions - */ - -/* Sets the data line on the i2c bus. - Expects a claimed pdev. */ -static void w9966_i2c_setsda(struct w9966 *cam, int state) -{ - if (state) - cam->i2c_state |= W9966_I2C_W_DATA; - else - cam->i2c_state &= ~W9966_I2C_W_DATA; - - w9966_write_reg(cam, 0x18, cam->i2c_state); - udelay(5); -} - -/* Get peripheral clock line - Expects a claimed pdev. */ -static int w9966_i2c_getscl(struct w9966 *cam) -{ - const unsigned char state = w9966_read_reg(cam, 0x18); - return ((state & W9966_I2C_R_CLOCK) > 0); -} - -/* Sets the clock line on the i2c bus. - Expects a claimed pdev. -1 on error */ -static int w9966_i2c_setscl(struct w9966 *cam, int state) -{ - unsigned long timeout; - - if (state) - cam->i2c_state |= W9966_I2C_W_CLOCK; - else - cam->i2c_state &= ~W9966_I2C_W_CLOCK; - - w9966_write_reg(cam, 0x18, cam->i2c_state); - udelay(5); - - /* we go to high, we also expect the peripheral to ack. */ - if (state) { - timeout = jiffies + 100; - while (!w9966_i2c_getscl(cam)) { - if (time_after(jiffies, timeout)) - return -1; - } - } - return 0; -} - -#if 0 -/* Get peripheral data line - Expects a claimed pdev. */ -static int w9966_i2c_getsda(struct w9966 *cam) -{ - const unsigned char state = w9966_read_reg(cam, 0x18); - return ((state & W9966_I2C_R_DATA) > 0); -} -#endif - -/* Write a byte with ack to the i2c bus. - Expects a claimed pdev. -1 on error */ -static int w9966_i2c_wbyte(struct w9966 *cam, int data) -{ - int i; - - for (i = 7; i >= 0; i--) { - w9966_i2c_setsda(cam, (data >> i) & 0x01); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setscl(cam, 0); - } - - w9966_i2c_setsda(cam, 1); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setscl(cam, 0); - - return 0; -} - -/* Read a data byte with ack from the i2c-bus - Expects a claimed pdev. -1 on error */ -#if 0 -static int w9966_i2c_rbyte(struct w9966 *cam) -{ - unsigned char data = 0x00; - int i; - - w9966_i2c_setsda(cam, 1); - - for (i = 0; i < 8; i++) { - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - data = data << 1; - if (w9966_i2c_getsda(cam)) - data |= 0x01; - - w9966_i2c_setscl(cam, 0); - } - return data; -} -#endif - -/* Read a register from the i2c device. - Expects claimed pdev. -1 on error */ -#if 0 -static int w9966_read_reg_i2c(struct w9966 *cam, int reg) -{ - int data; - - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1) - return -1; - - w9966_i2c_setsda(cam, 1); - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1) - return -1; - data = w9966_i2c_rbyte(cam); - if (data == -1) - return -1; - - w9966_i2c_setsda(cam, 0); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setsda(cam, 1); - - return data; -} -#endif - -/* Write a register to the i2c device. - Expects claimed pdev. -1 on error */ -static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data) -{ - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1 || - w9966_i2c_wbyte(cam, data) == -1) - return -1; - - w9966_i2c_setsda(cam, 0); - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - - w9966_i2c_setsda(cam, 1); - - return 0; -} - -/* Find a good length for capture window (used both for W and H) - A bit ugly but pretty functional. The capture length - have to match the downscale */ -static int w9966_findlen(int near, int size, int maxlen) -{ - int bestlen = size; - int besterr = abs(near - bestlen); - int len; - - for (len = size + 1; len < maxlen; len++) { - int err; - if (((64 * size) % len) != 0) - continue; - - err = abs(near - len); - - /* Only continue as long as we keep getting better values */ - if (err > besterr) - break; - - besterr = err; - bestlen = len; - } - - return bestlen; -} - -/* Modify capture window (if necessary) - and calculate downscaling - Return -1 on error */ -static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor) -{ - int maxlen = max - min; - int len = *end - *beg + 1; - int newlen = w9966_findlen(len, size, maxlen); - int err = newlen - len; - - /* Check for bad format */ - if (newlen > maxlen || newlen < size) - return -1; - - /* Set factor (6 bit fixed) */ - *factor = (64 * size) / newlen; - if (*factor == 64) - *factor = 0x00; /* downscale is disabled */ - else - *factor |= 0x80; /* set downscale-enable bit */ - - /* Modify old beginning and end */ - *beg -= err / 2; - *end += err - (err / 2); - - /* Move window if outside borders */ - if (*beg < min) { - *end += min - *beg; - *beg += min - *beg; - } - if (*end > max) { - *beg -= *end - max; - *end -= *end - max; - } - - return 0; -} - -/* Setup the cameras capture window etc. - Expects a claimed pdev - return -1 on error */ -static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h) -{ - unsigned int i; - unsigned int enh_s, enh_e; - unsigned char scale_x, scale_y; - unsigned char regs[0x1c]; - unsigned char saa7111_regs[] = { - 0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00, - 0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00, - 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0 - }; - - - if (w * h * 2 > W9966_SRAMSIZE) { - DPRINTF("capture window exceeds SRAM size!.\n"); - w = 200; h = 160; /* Pick default values */ - } - - w &= ~0x1; - if (w < 2) - w = 2; - if (h < 1) - h = 1; - if (w > W9966_WND_MAX_W) - w = W9966_WND_MAX_W; - if (h > W9966_WND_MAX_H) - h = W9966_WND_MAX_H; - - cam->width = w; - cam->height = h; - - enh_s = 0; - enh_e = w * h * 2; - - /* Modify capture window if necessary and calculate downscaling */ - if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || - w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0) - return -1; - - DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", - w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80); - - /* Setup registers */ - regs[0x00] = 0x00; /* Set normal operation */ - regs[0x01] = 0x18; /* Capture mode */ - regs[0x02] = scale_y; /* V-scaling */ - regs[0x03] = scale_x; /* H-scaling */ - - /* Capture window */ - regs[0x04] = (x1 & 0x0ff); /* X-start (8 low bits) */ - regs[0x05] = (x1 & 0x300)>>8; /* X-start (2 high bits) */ - regs[0x06] = (y1 & 0x0ff); /* Y-start (8 low bits) */ - regs[0x07] = (y1 & 0x300)>>8; /* Y-start (2 high bits) */ - regs[0x08] = (x2 & 0x0ff); /* X-end (8 low bits) */ - regs[0x09] = (x2 & 0x300)>>8; /* X-end (2 high bits) */ - regs[0x0a] = (y2 & 0x0ff); /* Y-end (8 low bits) */ - - regs[0x0c] = W9966_SRAMID; /* SRAM-banks (1x 128kb) */ - - /* Enhancement layer */ - regs[0x0d] = (enh_s & 0x000ff); /* Enh. start (0-7) */ - regs[0x0e] = (enh_s & 0x0ff00) >> 8; /* Enh. start (8-15) */ - regs[0x0f] = (enh_s & 0x70000) >> 16; /* Enh. start (16-17/18??) */ - regs[0x10] = (enh_e & 0x000ff); /* Enh. end (0-7) */ - regs[0x11] = (enh_e & 0x0ff00) >> 8; /* Enh. end (8-15) */ - regs[0x12] = (enh_e & 0x70000) >> 16; /* Enh. end (16-17/18??) */ - - /* Misc */ - regs[0x13] = 0x40; /* VEE control (raw 4:2:2) */ - regs[0x17] = 0x00; /* ??? */ - regs[0x18] = cam->i2c_state = 0x00; /* Serial bus */ - regs[0x19] = 0xff; /* I/O port direction control */ - regs[0x1a] = 0xff; /* I/O port data register */ - regs[0x1b] = 0x10; /* ??? */ - - /* SAA7111 chip settings */ - saa7111_regs[0x0a] = cam->brightness; - saa7111_regs[0x0b] = cam->contrast; - saa7111_regs[0x0c] = cam->color; - saa7111_regs[0x0d] = cam->hue; - - /* Reset (ECP-fifo & serial-bus) */ - if (w9966_write_reg(cam, 0x00, 0x03) == -1) - return -1; - - /* Write regs to w9966cf chip */ - for (i = 0; i < 0x1c; i++) - if (w9966_write_reg(cam, i, regs[i]) == -1) - return -1; - - /* Write regs to saa7111 chip */ - for (i = 0; i < 0x20; i++) - if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1) - return -1; - - return 0; -} - -/* - * Video4linux interfacing - */ - -static int cam_querycap(struct file *file, void *priv, - struct v4l2_capability *vcap) -{ - struct w9966 *cam = video_drvdata(file); - - strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card)); - strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); - vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; - vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - if (vin->index > 0) - return -EINVAL; - strlcpy(vin->name, "Camera", sizeof(vin->name)); - vin->type = V4L2_INPUT_TYPE_CAMERA; - vin->audioset = 0; - vin->tuner = 0; - vin->std = 0; - vin->status = 0; - return 0; -} - -static int cam_g_input(struct file *file, void *fh, unsigned int *inp) -{ - *inp = 0; - return 0; -} - -static int cam_s_input(struct file *file, void *fh, unsigned int inp) -{ - return (inp > 0) ? -EINVAL : 0; -} - -static int cam_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct w9966 *cam = - container_of(ctrl->handler, struct w9966, hdl); - int ret = 0; - - mutex_lock(&cam->lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - cam->brightness = ctrl->val; - break; - case V4L2_CID_CONTRAST: - cam->contrast = ctrl->val; - break; - case V4L2_CID_SATURATION: - cam->color = ctrl->val; - break; - case V4L2_CID_HUE: - cam->hue = ctrl->val; - break; - default: - ret = -EINVAL; - break; - } - - if (ret == 0) { - w9966_pdev_claim(cam); - - if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 || - w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 || - w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 || - w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) { - ret = -EIO; - } - - w9966_pdev_release(cam); - } - mutex_unlock(&cam->lock); - return ret; -} - -static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct w9966 *cam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - pix->width = cam->width; - pix->height = cam->height; - pix->pixelformat = V4L2_PIX_FMT_YUYV; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 2 * cam->width; - pix->sizeimage = 2 * cam->width * cam->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - return 0; -} - -static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->width < 2) - pix->width = 2; - if (pix->height < 1) - pix->height = 1; - if (pix->width > W9966_WND_MAX_W) - pix->width = W9966_WND_MAX_W; - if (pix->height > W9966_WND_MAX_H) - pix->height = W9966_WND_MAX_H; - pix->pixelformat = V4L2_PIX_FMT_YUYV; - pix->field = V4L2_FIELD_NONE; - pix->bytesperline = 2 * pix->width; - pix->sizeimage = 2 * pix->width * pix->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - return 0; -} - -static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct w9966 *cam = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - int ret = cam_try_fmt_vid_cap(file, fh, fmt); - - if (ret) - return ret; - - mutex_lock(&cam->lock); - /* Update camera regs */ - w9966_pdev_claim(cam); - ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height); - w9966_pdev_release(cam); - mutex_unlock(&cam->lock); - return ret; -} - -static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "YUV 4:2:2", V4L2_PIX_FMT_YUYV, - { 0, 0, 0, 0 } - }, - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 0) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -/* Capture data */ -static ssize_t w9966_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct w9966 *cam = video_drvdata(file); - unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ - unsigned char __user *dest = (unsigned char __user *)buf; - unsigned long dleft = count; - unsigned char *tbuf; - - /* Why would anyone want more than this?? */ - if (count > cam->width * cam->height * 2) - return -EINVAL; - - mutex_lock(&cam->lock); - w9966_pdev_claim(cam); - w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ - w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */ - w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */ - - /* write special capture-addr and negotiate into data transfer */ - if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) || - (parport_write(cam->pport, &addr, 1) != 1) || - (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { - w9966_pdev_release(cam); - mutex_unlock(&cam->lock); - return -EFAULT; - } - - tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL); - if (tbuf == NULL) { - count = -ENOMEM; - goto out; - } - - while (dleft > 0) { - unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; - - if (parport_read(cam->pport, tbuf, tsize) < tsize) { - count = -EFAULT; - goto out; - } - if (copy_to_user(dest, tbuf, tsize) != 0) { - count = -EFAULT; - goto out; - } - dest += tsize; - dleft -= tsize; - } - - w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */ - -out: - kfree(tbuf); - w9966_pdev_release(cam); - mutex_unlock(&cam->lock); - - return count; -} - -static const struct v4l2_file_operations w9966_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = v4l2_ctrl_poll, - .unlocked_ioctl = video_ioctl2, - .read = w9966_v4l_read, -}; - -static const struct v4l2_ioctl_ops w9966_ioctl_ops = { - .vidioc_querycap = cam_querycap, - .vidioc_g_input = cam_g_input, - .vidioc_s_input = cam_s_input, - .vidioc_enum_input = cam_enum_input, - .vidioc_enum_fmt_vid_cap = cam_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cam_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = cam_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cam_try_fmt_vid_cap, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct v4l2_ctrl_ops cam_ctrl_ops = { - .s_ctrl = cam_s_ctrl, -}; - - -/* Initialize camera device. Setup all internal flags, set a - default video mode, setup ccd-chip, register v4l device etc.. - Also used for 'probing' of hardware. - -1 on error */ -static int w9966_init(struct w9966 *cam, struct parport *port) -{ - struct v4l2_device *v4l2_dev = &cam->v4l2_dev; - - if (cam->dev_state != 0) - return -1; - - strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name)); - - if (v4l2_device_register(NULL, v4l2_dev) < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - return -1; - } - - v4l2_ctrl_handler_init(&cam->hdl, 4); - v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops, - V4L2_CID_CONTRAST, -64, 64, 1, 64); - v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops, - V4L2_CID_SATURATION, -64, 64, 1, 64); - v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops, - V4L2_CID_HUE, -128, 127, 1, 0); - if (cam->hdl.error) { - v4l2_err(v4l2_dev, "couldn't register controls\n"); - return -1; - } - cam->pport = port; - cam->brightness = 128; - cam->contrast = 64; - cam->color = 64; - cam->hue = 0; - - /* Select requested transfer mode */ - switch (parmode) { - default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ - case 0: - if (port->modes & PARPORT_MODE_ECP) - cam->ppmode = IEEE1284_MODE_ECP; - else if (port->modes & PARPORT_MODE_EPP) - cam->ppmode = IEEE1284_MODE_EPP; - else - cam->ppmode = IEEE1284_MODE_ECP; - break; - case 1: /* hw- or sw-ecp */ - cam->ppmode = IEEE1284_MODE_ECP; - break; - case 2: /* hw- or sw-epp */ - cam->ppmode = IEEE1284_MODE_EPP; - break; - } - - /* Tell the parport driver that we exists */ - cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); - if (cam->pdev == NULL) { - DPRINTF("parport_register_device() failed\n"); - return -1; - } - w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); - - w9966_pdev_claim(cam); - - /* Setup a default capture mode */ - if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { - DPRINTF("w9966_setup() failed.\n"); - return -1; - } - - w9966_pdev_release(cam); - - /* Fill in the video_device struct and register us to v4l */ - strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name)); - cam->vdev.v4l2_dev = v4l2_dev; - cam->vdev.fops = &w9966_fops; - cam->vdev.ioctl_ops = &w9966_ioctl_ops; - cam->vdev.release = video_device_release_empty; - cam->vdev.ctrl_handler = &cam->hdl; - video_set_drvdata(&cam->vdev, cam); - - mutex_init(&cam->lock); - - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) - return -1; - - w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); - - /* All ok */ - v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n", - cam->pport->name); - return 0; -} - - -/* Terminate everything gracefully */ -static void w9966_term(struct w9966 *cam) -{ - /* Unregister from v4l */ - if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { - video_unregister_device(&cam->vdev); - w9966_set_state(cam, W9966_STATE_VDEV, 0); - } - - v4l2_ctrl_handler_free(&cam->hdl); - - /* Terminate from IEEE1284 mode and release pdev block */ - if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { - w9966_pdev_claim(cam); - parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); - w9966_pdev_release(cam); - } - - /* Unregister from parport */ - if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { - parport_unregister_device(cam->pdev); - w9966_set_state(cam, W9966_STATE_PDEV, 0); - } - memset(cam, 0, sizeof(*cam)); -} - - -/* Called once for every parport on init */ -static void w9966_attach(struct parport *port) -{ - int i; - - for (i = 0; i < W9966_MAXCAMS; i++) { - if (w9966_cams[i].dev_state != 0) /* Cam is already assigned */ - continue; - if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) { - if (w9966_init(&w9966_cams[i], port) != 0) - w9966_term(&w9966_cams[i]); - break; /* return */ - } - } -} - -/* Called once for every parport on termination */ -static void w9966_detach(struct parport *port) -{ - int i; - - for (i = 0; i < W9966_MAXCAMS; i++) - if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) - w9966_term(&w9966_cams[i]); -} - - -static struct parport_driver w9966_ppd = { - .name = W9966_DRIVERNAME, - .attach = w9966_attach, - .detach = w9966_detach, -}; - -/* Module entry point */ -static int __init w9966_mod_init(void) -{ - int i; - - for (i = 0; i < W9966_MAXCAMS; i++) - w9966_cams[i].dev_state = 0; - - return parport_register_driver(&w9966_ppd); -} - -/* Module cleanup */ -static void __exit w9966_mod_term(void) -{ - parport_unregister_driver(&w9966_ppd); -} - -module_init(w9966_mod_init); -module_exit(w9966_mod_term); -- cgit v1.2.3 From 1b880ef62cc43d049bd92a31a0612caacb5f30b2 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 15 Dec 2014 18:10:57 -0300 Subject: [media] s5p-mfc-v6+: Use display_delay_enable CID The MFC driver has two controls, DISPLAY_DELAY and DISPLAY_DELAY_ENABLE that allow forcing the decoder to return a decoded frame sooner regardless of the order. The added support for firmware version 6 and higher was not taking into account the DISPLAY_DELAY_ENABLE boolean. Instead it had a comment stating that DISPLAY_DELAY should be set to a negative value to disable it. This is not possible since the control range is from 0 to 65535. This feature was also supposed to be disabled by default in order to produce frames in display order. Signed-off-by: Nicolas Dufresne Acked-by: Kamil Debski Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 9aea179943ce..d826c58b5d53 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -1340,11 +1340,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) /* FMO_ASO_CTRL - 0: Enable, 1: Disable */ reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6); - /* When user sets desplay_delay to 0, - * It works as "display_delay enable" and delay set to 0. - * If user wants display_delay disable, It should be - * set to negative value. */ - if (ctx->display_delay >= 0) { + if (ctx->display_delay_enable) { reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); writel(ctx->display_delay, mfc_regs->d_display_delay); } -- cgit v1.2.3 From 68e77d2e6e38a1a3b95fdc358bec45e81d965ebf Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 15 Dec 2014 18:10:58 -0300 Subject: [media] s5p-mfc-dec: Don't use encoder stop command The decoder should handle V4L2_DEC_CMD_STOP to trigger drain, but it currently expecting V4L2_ENC_CMD_STOP. Signed-off-by: Nicolas Dufresne Acked-by: Kamil Debski Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 9b14827ef4b9..da80c038e86b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -813,7 +813,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, unsigned long flags; switch (cmd->cmd) { - case V4L2_ENC_CMD_STOP: + case V4L2_DEC_CMD_STOP: if (cmd->flags != 0) return -EINVAL; -- cgit v1.2.3 From ef8fab7f99eea3f9dacf498f44dc919afed707f5 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Mon, 29 Dec 2014 11:29:40 -0300 Subject: [media] s5p-g2d: remove unnecessary version.h inclusion Based on versioncheck. Signed-off-by: Fabian Frederick Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-g2d/g2d.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 47ba8fbb0426..ec3e1248923d 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From ea0944e079738415523eb248452928c0be6da981 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Mon, 29 Dec 2014 11:29:41 -0300 Subject: [media] s5p-mfc: remove unnecessary version.h inclusion Based on versioncheck. Signed-off-by: Fabian Frederick Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 - drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index da80c038e86b..aebe4fd7f03a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index ac12f653ddce..e65993f4b901 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 27d056f67f514f9f5459c41c2b72cb044c7d56df Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:15 -0300 Subject: [media] coda: fix encoder rate control parameter masks This patch fixes the ENC_SEQ_RC_PARA initial delay and bitrate masks. These bit fields are 15 bit wide, not 7 bit. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h index 8e015b8aa8fa..7d026241171b 100644 --- a/drivers/media/platform/coda/coda_regs.h +++ b/drivers/media/platform/coda/coda_regs.h @@ -304,9 +304,9 @@ #define CODA_RATECONTROL_AUTOSKIP_OFFSET 31 #define CODA_RATECONTROL_AUTOSKIP_MASK 0x01 #define CODA_RATECONTROL_INITIALDELAY_OFFSET 16 -#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7f +#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7fff #define CODA_RATECONTROL_BITRATE_OFFSET 1 -#define CODA_RATECONTROL_BITRATE_MASK 0x7f +#define CODA_RATECONTROL_BITRATE_MASK 0x7fff #define CODA_RATECONTROL_ENABLE_OFFSET 0 #define CODA_RATECONTROL_ENABLE_MASK 0x01 #define CODA_CMD_ENC_SEQ_RC_BUF_SIZE 0x1b0 -- cgit v1.2.3 From e1519e866b73ff49aaf017d8ac08eb96944ff191 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:17 -0300 Subject: [media] coda: remove context debugfs entry last Do not remove the per-context debugfs directory before the per-buffer debugfs entries contained therein. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index ea7a0dcf1530..8b4bd88af290 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1693,8 +1693,6 @@ static int coda_release(struct file *file) v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", ctx); - debugfs_remove_recursive(ctx->debugfs_entry); - if (ctx->inst_type == CODA_INST_DECODER) coda_bit_stream_end_flag(ctx); @@ -1728,6 +1726,7 @@ static int coda_release(struct file *file) clear_bit(ctx->idx, &dev->instance_mask); if (ctx->ops->release) ctx->ops->release(ctx); + debugfs_remove_recursive(ctx->debugfs_entry); kfree(ctx); return 0; -- cgit v1.2.3 From 07ba277f896ec774cb529277d6072a5611b34f18 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:18 -0300 Subject: [media] coda: move meta out of padding Handle an empty buffer metadata list without crashing. This can happen if the decoder is fed a broken stream, or multiple compressed frames in a single queued buffer. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index b4029ae293d3..f6cf337bf377 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1565,6 +1565,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx) struct vb2_buffer *dst_buf; struct coda_dev *dev = ctx->dev; struct coda_q_data *q_data_dst; + struct coda_buffer_meta *meta; u32 reg_addr, reg_stride; dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); @@ -1643,12 +1644,12 @@ static int coda_prepare_decode(struct coda_ctx *ctx) coda_write(dev, ctx->iram_info.axi_sram_use, CODA7_REG_BIT_AXI_SRAM_USE); - if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) { - struct coda_buffer_meta *meta; + meta = list_first_entry_or_null(&ctx->buffer_meta_list, + struct coda_buffer_meta, list); + + if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) { /* If this is the last buffer in the bitstream, add padding */ - meta = list_first_entry(&ctx->buffer_meta_list, - struct coda_buffer_meta, list); if (meta->end == (ctx->bitstream_fifo.kfifo.in & ctx->bitstream_fifo.kfifo.mask)) { static unsigned char buf[512]; -- cgit v1.2.3 From 83f31c8a5fc87a2bc384f33e66994d079adc2273 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 23 Jan 2015 13:51:19 -0300 Subject: [media] coda: adjust sequence offset after unexpected decoded frame If userspace doesn't properly separate the bitstream input into individual frames (which may happen for example on slightly corrupted streams) the CODA hardware may decode more frames than we expect. We already log an error in this case, but it's also necessary to adjust the sequence offset. Otherwise we spam the log with a sequence number mismatch on every frame frame after the unexpected one. Signed-off-by: Lucas Stach Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index f6cf337bf377..6b00a45e84a4 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1822,6 +1822,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) memset(&ctx->frame_metas[decoded_idx], 0, sizeof(struct coda_buffer_meta)); ctx->frame_metas[decoded_idx].sequence = val; + ctx->sequence_offset++; } mutex_unlock(&ctx->bitstream_mutex); -- cgit v1.2.3 From f77fd8a9b1a8151ae7a0e98a3b3baf8ab639d0e1 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:20 -0300 Subject: [media] coda: fix job_ready debug reporting for bitstream decoding Clarify whether job_ready returns false because the context is on hold, waiting for new input buffers, whether there are not enough input buffers to fill two into the bitstream, or whether there is not enough data in the bitstream buffer for the bitstream reader hardware to read a whole frame. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 46 +++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 8b4bd88af290..14953b4df586 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -939,15 +939,43 @@ static int coda_job_ready(void *m2m_priv) return 0; } - if (ctx->hold || - ((ctx->inst_type == CODA_INST_DECODER) && - !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) && - (coda_get_bitstream_payload(ctx) < 512) && - !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { - v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, - "%d: not ready: not enough bitstream data.\n", - ctx->idx); - return 0; + if (ctx->inst_type == CODA_INST_DECODER) { + struct list_head *meta; + bool stream_end; + int num_metas; + int src_bufs; + + if (ctx->hold && !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%d: not ready: on hold for more buffers.\n", + ctx->idx); + return 0; + } + + stream_end = ctx->bit_stream_param & + CODA_BIT_STREAM_END_FLAG; + + num_metas = 0; + list_for_each(meta, &ctx->buffer_meta_list) + num_metas++; + + src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx); + + if (!stream_end && (num_metas + src_bufs) < 2) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%d: not ready: need 2 buffers available (%d, %d)\n", + ctx->idx, num_metas, src_bufs); + return 0; + } + + + if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) && + !stream_end && (coda_get_bitstream_payload(ctx) < 512)) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%d: not ready: not enough bitstream data (%d).\n", + ctx->idx, coda_get_bitstream_payload(ctx)); + return 0; + } } if (ctx->aborting) { -- cgit v1.2.3 From 5f9826e8a759426f6fd722a80a72008bd93132af Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:21 -0300 Subject: [media] coda: fix try_fmt_vid_out colorspace setting v4l2-compliance complains about invalid colorspace settings being accepted on the output side. This patch only allows REC709 and JPEG. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 14953b4df586..ff7da3a5c4ae 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -592,7 +592,11 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv, if (ret < 0) return ret; - if (!f->fmt.pix.colorspace) { + switch (f->fmt.pix.colorspace) { + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_JPEG: + break; + default: if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; else -- cgit v1.2.3 From 1c2f6a9983a7b079c4bada2bb43c336bb7b8abb9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:22 -0300 Subject: [media] coda: properly clear f_cap in coda_s_fmt_vid_out Properly zero the structure on the stack before using it. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index ff7da3a5c4ae..d26794fa74bf 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -674,6 +674,7 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, ctx->colorspace = f->fmt.pix.colorspace; + memset(&f_cap, 0, sizeof(f_cap)); f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; coda_g_fmt(file, priv, &f_cap); f_cap.fmt.pix.width = f->fmt.pix.width; -- cgit v1.2.3 From 811a6934c22e19f2bc9b4a280e8626af1a098721 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:23 -0300 Subject: [media] coda: initialize SRAM on probe Zeroing the SRAM on probe helps with debugging SRAM contents. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index d26794fa74bf..5b3fd44ad4cc 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -2174,6 +2174,7 @@ static int coda_probe(struct platform_device *pdev) if (!dev->iram.vaddr) { dev_warn(&pdev->dev, "unable to alloc iram\n"); } else { + memset(dev->iram.vaddr, 0, dev->iram.size); dev->iram.blob.data = dev->iram.vaddr; dev->iram.blob.size = dev->iram.size; dev->iram.dentry = debugfs_create_blob("iram", 0644, -- cgit v1.2.3 From 8c9ef6b16c433fd4850ef8f9dd74af36232ed055 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:24 -0300 Subject: [media] coda: clear RET_DEC_PIC_SUCCESS flag in prepare_decode To make sure a set RET_DEC_PIC_SUCCESS flag is not a leftover from a previous successful run, clear it in prepare_decode. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 6b00a45e84a4..d81635d272de 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1666,6 +1666,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx) coda_kfifo_sync_to_device_full(ctx); + /* Clear decode success flag */ + coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS); + coda_command_async(ctx, CODA_COMMAND_PIC_RUN); return 0; -- cgit v1.2.3 From 31db5adb4ea78976c5e1c2c7aa386e494872e8c1 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 23 Jan 2015 13:51:25 -0300 Subject: [media] coda: fix width validity check when starting to decode Compare rounded up width to fit into bytesperline. Signed-off-by: Markus Pargmann Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index d81635d272de..6ecfd29b7d98 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1431,9 +1431,10 @@ static int __coda_start_decoding(struct coda_ctx *ctx) height = val & CODA7_PICHEIGHT_MASK; } - if (width > q_data_dst->width || height > q_data_dst->height) { + if (width > q_data_dst->bytesperline || height > q_data_dst->height) { v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", - width, height, q_data_dst->width, q_data_dst->height); + width, height, q_data_dst->bytesperline, + q_data_dst->height); return -EINVAL; } -- cgit v1.2.3 From 6dd5ef5bddd51258f229974a25c8a7bb5617332f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:26 -0300 Subject: [media] coda: remove unused isequence, reset qsequence in stop_streaming The isequence counter is never used, qsequence counts the buffers queued into the bit decoder bitstream ringbuffer. It needs to be reset in stop_streaming. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 2 +- drivers/media/platform/coda/coda.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 5b3fd44ad4cc..de8ad49ac6ca 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1304,7 +1304,7 @@ static void coda_stop_streaming(struct vb2_queue *q) coda_bit_stream_end_flag(ctx); - ctx->isequence = 0; + ctx->qsequence = 0; while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 5dd47e5f97c1..2ddfe51526fa 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -198,7 +198,6 @@ struct coda_ctx { int initialized; int streamon_out; int streamon_cap; - u32 isequence; u32 qsequence; u32 osequence; u32 sequence_offset; -- cgit v1.2.3 From f4706d6e6d2d174af156b56d08cfca35121ac7cc Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:27 -0300 Subject: [media] coda: issue seq_end_work during stop_streaming This patch queues seq_end_work and flushes the queue during stop_streaming and clears the ctx->initialized flag. This allows to start streaming again after stopping streaming without releasing the context. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index de8ad49ac6ca..490b933ad616 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1323,6 +1323,10 @@ static void coda_stop_streaming(struct vb2_queue *q) if (!ctx->streamon_out && !ctx->streamon_cap) { struct coda_buffer_meta *meta; + if (ctx->ops->seq_end_work) { + queue_work(dev->workqueue, &ctx->seq_end_work); + flush_work(&ctx->seq_end_work); + } mutex_lock(&ctx->bitstream_mutex); while (!list_empty(&ctx->buffer_meta_list)) { meta = list_first_entry(&ctx->buffer_meta_list, @@ -1333,6 +1337,7 @@ static void coda_stop_streaming(struct vb2_queue *q) mutex_unlock(&ctx->bitstream_mutex); kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr, ctx->bitstream.size); + ctx->initialized = 0; ctx->runcounter = 0; ctx->aborting = 0; } -- cgit v1.2.3 From e3cccff9aa93679f1b9d23080cc07197f58588f4 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:28 -0300 Subject: [media] coda: don't ever use subsampling ping-pong buffers as reconstructed reference buffers On i.MX6, two subsampling ping-pong buffers are used for motion estimation and deblocking They should not be counted as framebuffers, or they will be also used to store reconstructed frames, causing visible artifacts in P-frames. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 6ecfd29b7d98..7cdddd55d65d 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -718,6 +718,7 @@ static int coda_start_encoding(struct coda_ctx *ctx) struct vb2_buffer *buf; int gamma, ret, value; u32 dst_fourcc; + int num_fb; u32 stride; q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -983,12 +984,14 @@ static int coda_start_encoding(struct coda_ctx *ctx) v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); goto out; } + num_fb = 2; stride = q_data_src->bytesperline; } else { ctx->num_internal_frames = 0; + num_fb = 0; stride = 0; } - coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); + coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM); coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE); if (dev->devtype->product == CODA_7541) { -- cgit v1.2.3 From 8e428d5040629dbbdfd6610026cb0b15b93830e0 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:29 -0300 Subject: [media] coda: add coda_estimate_sizeimage and use it in set_defaults Call coda_estimate_sizeimage from both try_fmt and set_defaults to avoid this v4l2-compliance warning on the h.264 decoder video device: G_FMT: 1920x1088, 32315559, 1, 1920, 1048576, 3, 0, 0, feedcafe TRY/S_FMT: 1920x1088, 32315559, 1, 1920, 3133440, 3, 0, 0, feedcafe fail: v4l2-test-formats.cpp(948): Video Capture: S_FMT(G_FMT) != G_FMT Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 38 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 490b933ad616..15f4c2b91e42 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -468,6 +468,18 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f) return 0; } +static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage, + u32 width, u32 height) +{ + /* + * This is a rough estimate for sensible compressed buffer + * sizes (between 1 and 16 bits per pixel). This could be + * improved by better format specific worst case estimates. + */ + return round_up(clamp(sizeimage, width * height / 8, + width * height * 2), PAGE_SIZE); +} + static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, struct v4l2_format *f) { @@ -513,15 +525,10 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_MPEG4: f->fmt.pix.bytesperline = 0; - /* - * This is a rough estimate for sensible compressed buffer - * sizes (between 1 and 16 bits per pixel). This could be - * improved by better format specific worst case estimates. - */ - f->fmt.pix.sizeimage = round_up(clamp(f->fmt.pix.sizeimage, - f->fmt.pix.width * f->fmt.pix.height / 8, - f->fmt.pix.width * f->fmt.pix.height * 2), - PAGE_SIZE); + f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx, + f->fmt.pix.sizeimage, + f->fmt.pix.width, + f->fmt.pix.height); break; default: BUG(); @@ -1056,13 +1063,14 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type) static void set_default_params(struct coda_ctx *ctx) { - unsigned int max_w, max_h, size; + unsigned int max_w, max_h, usize, csize; ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0], ctx->cvd->dst_formats[0]); max_w = min(ctx->codec->max_w, 1920U); max_h = min(ctx->codec->max_h, 1088U); - size = max_w * max_h * 3 / 2; + usize = max_w * max_h * 3 / 2; + csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h); ctx->params.codec_mode = ctx->codec->mode; ctx->colorspace = V4L2_COLORSPACE_REC709; @@ -1077,14 +1085,14 @@ static void set_default_params(struct coda_ctx *ctx) ctx->q_data[V4L2_M2M_DST].height = max_h; if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) { ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; - ctx->q_data[V4L2_M2M_SRC].sizeimage = size; + ctx->q_data[V4L2_M2M_SRC].sizeimage = usize; ctx->q_data[V4L2_M2M_DST].bytesperline = 0; - ctx->q_data[V4L2_M2M_DST].sizeimage = round_up(size, PAGE_SIZE); + ctx->q_data[V4L2_M2M_DST].sizeimage = csize; } else { ctx->q_data[V4L2_M2M_SRC].bytesperline = 0; - ctx->q_data[V4L2_M2M_SRC].sizeimage = round_up(size, PAGE_SIZE); + ctx->q_data[V4L2_M2M_SRC].sizeimage = csize; ctx->q_data[V4L2_M2M_DST].bytesperline = max_w; - ctx->q_data[V4L2_M2M_DST].sizeimage = size; + ctx->q_data[V4L2_M2M_DST].sizeimage = usize; } ctx->q_data[V4L2_M2M_SRC].rect.width = max_w; ctx->q_data[V4L2_M2M_SRC].rect.height = max_h; -- cgit v1.2.3 From bb04aa6f7e40eb92688d5d21f15ada23924f17cb Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:30 -0300 Subject: [media] coda: switch BIT decoder source queue to vmalloc Since we have to copy from input buffers into the bitstream ringbuffer with the CPU, there is no need for contiguous DMA buffers on the decoder input side. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 1 + drivers/media/platform/coda/coda-common.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index d18a5353e4a4..250b7af66027 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -141,6 +141,7 @@ config VIDEO_CODA depends on HAS_DMA select SRAM select VIDEOBUF2_DMA_CONTIG + select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select GENERIC_ALLOCATOR ---help--- diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 15f4c2b91e42..f881e87e55d3 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "coda.h" @@ -1121,6 +1122,7 @@ static int coda_queue_setup(struct vb2_queue *vq, *nplanes = 1; sizes[0] = size; + /* Set to vb2-dma-contig allocator context, ignored by vb2-vmalloc */ alloc_ctxs[0] = ctx->dev->alloc_ctx; v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, @@ -1567,8 +1569,8 @@ int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_DMABUF | VB2_MMAP; - src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; + src_vq->mem_ops = &vb2_vmalloc_memops; ret = coda_queue_init(priv, src_vq); if (ret) -- cgit v1.2.3 From 747d7646112c461fa1a2adb6655da6c51473cf1c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:31 -0300 Subject: [media] coda: make seq_end_work optional In preparation for CODA9 JPEG support, which doesn't have to call SEQ_END on the BIT processor. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index f881e87e55d3..35a42c56dd60 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -921,7 +921,8 @@ static void coda_pic_run_work(struct work_struct *work) ctx->ops->finish_run(ctx); } - if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) + if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) && + ctx->ops->seq_end_work) queue_work(dev->workqueue, &ctx->seq_end_work); mutex_unlock(&dev->coda_mutex); @@ -1627,7 +1628,8 @@ static int coda_open(struct file *file) ctx->ops = ctx->cvd->ops; init_completion(&ctx->completion); INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); - INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); + if (ctx->ops->seq_end_work) + INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); v4l2_fh_init(&ctx->fh, video_devdata(file)); file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); @@ -1748,7 +1750,7 @@ static int coda_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); /* In case the instance was not running, we still need to call SEQ_END */ - if (ctx->initialized) { + if (ctx->initialized && ctx->ops->seq_end_work) { queue_work(dev->workqueue, &ctx->seq_end_work); flush_work(&ctx->seq_end_work); } -- cgit v1.2.3 From 540d70d577dc3c78590f480c832e85ac28e5482a Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:32 -0300 Subject: [media] coda: free context buffers under buffer mutex Make sure the buffer_mutex lock is taken in coda_bit_release while coda_free_framebuffers and coda_free_context_buffers are called. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 7cdddd55d65d..856b542b35b9 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1319,8 +1319,10 @@ static void coda_seq_end_work(struct work_struct *work) static void coda_bit_release(struct coda_ctx *ctx) { + mutex_lock(&ctx->buffer_mutex); coda_free_framebuffers(ctx); coda_free_context_buffers(ctx); + mutex_unlock(&ctx->buffer_mutex); } const struct coda_context_ops coda_bit_encode_ops = { -- cgit v1.2.3 From a22496c6628406ff7610721b6279a68a9325df63 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:33 -0300 Subject: [media] coda: add support for contexts that do not use the BIT processor In preparation for CODA9 JPEG support, allow contexts that control hardware units directly, without the BIT processor. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 42 +++++++++++++++++-------------- drivers/media/platform/coda/coda.h | 1 + 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 35a42c56dd60..9abb3214de52 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -181,6 +181,7 @@ struct coda_video_device { const char *name; enum coda_inst_type type; const struct coda_context_ops *ops; + bool direct; u32 src_formats[CODA_MAX_FORMATS]; u32 dst_formats[CODA_MAX_FORMATS]; }; @@ -953,7 +954,7 @@ static int coda_job_ready(void *m2m_priv) return 0; } - if (ctx->inst_type == CODA_INST_DECODER) { + if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { struct list_head *meta; bool stream_end; int num_metas; @@ -1161,7 +1162,7 @@ static void coda_buf_queue(struct vb2_buffer *vb) * In the decoder case, immediately try to copy the buffer into the * bitstream ringbuffer and mark it as ready to be dequeued. */ - if (ctx->inst_type == CODA_INST_DECODER && + if (ctx->use_bit && ctx->inst_type == CODA_INST_DECODER && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* * For backwards compatibility, queuing an empty buffer marks @@ -1262,7 +1263,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) return 0; /* Allow BIT decoder device_run with no new buffers queued */ - if (ctx->inst_type == CODA_INST_DECODER) + if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true); ctx->gopcounter = ctx->params.gop_size - 1; @@ -1626,6 +1627,7 @@ static int coda_open(struct file *file) ctx->cvd = to_coda_video_device(vdev); ctx->inst_type = ctx->cvd->type; ctx->ops = ctx->cvd->ops; + ctx->use_bit = !ctx->cvd->direct; init_completion(&ctx->completion); INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); if (ctx->ops->seq_end_work) @@ -1680,22 +1682,24 @@ static int coda_open(struct file *file) ctx->fh.ctrl_handler = &ctx->ctrls; - ret = coda_alloc_context_buf(ctx, &ctx->parabuf, - CODA_PARA_BUF_SIZE, "parabuf"); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); - goto err_dma_alloc; - } + if (ctx->use_bit) { + ret = coda_alloc_context_buf(ctx, &ctx->parabuf, + CODA_PARA_BUF_SIZE, "parabuf"); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); + goto err_dma_alloc; + } - ctx->bitstream.size = CODA_MAX_FRAME_SIZE; - ctx->bitstream.vaddr = dma_alloc_writecombine( - &dev->plat_dev->dev, ctx->bitstream.size, - &ctx->bitstream.paddr, GFP_KERNEL); - if (!ctx->bitstream.vaddr) { - v4l2_err(&dev->v4l2_dev, - "failed to allocate bitstream ringbuffer"); - ret = -ENOMEM; - goto err_dma_writecombine; + ctx->bitstream.size = CODA_MAX_FRAME_SIZE; + ctx->bitstream.vaddr = dma_alloc_writecombine( + &dev->plat_dev->dev, ctx->bitstream.size, + &ctx->bitstream.paddr, GFP_KERNEL); + if (!ctx->bitstream.vaddr) { + v4l2_err(&dev->v4l2_dev, + "failed to allocate bitstream ringbuffer"); + ret = -ENOMEM; + goto err_dma_writecombine; + } } kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr, ctx->bitstream.size); @@ -1743,7 +1747,7 @@ static int coda_release(struct file *file) v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", ctx); - if (ctx->inst_type == CODA_INST_DECODER) + if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) coda_bit_stream_end_flag(ctx); /* If this instance is running, call .job_abort and wait for it to end */ diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 2ddfe51526fa..0c35cd5032ff 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -235,6 +235,7 @@ struct coda_ctx { u32 frame_mem_ctrl; int display_idx; struct dentry *debugfs_entry; + bool use_bit; }; extern int coda_debug; -- cgit v1.2.3 From e55317e7080e6d746c2d8e323216a7091e25111b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:34 -0300 Subject: [media] coda: allocate bitstream ringbuffer only for BIT decoder The BIT encoder does not use a per-context bitstream ringbuffer as it encodes directly into the videobuf2 capture queue's buffers. Avoid allocation of the bitstream ringbuffer for encoder contexts. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 9abb3214de52..8bd1611cbb89 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1689,7 +1689,8 @@ static int coda_open(struct file *file) v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); goto err_dma_alloc; } - + } + if (ctx->use_bit && ctx->inst_type == CODA_INST_DECODER) { ctx->bitstream.size = CODA_MAX_FRAME_SIZE; ctx->bitstream.vaddr = dma_alloc_writecombine( &dev->plat_dev->dev, ctx->bitstream.size, -- cgit v1.2.3 From cb06b705e3eaf2e3f69e6e5e2ded8b07b2711627 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 23 Jan 2015 13:51:35 -0300 Subject: [media] coda: simplify check in coda_buf_queue Now that the bitstream buffer is only allocated for the BIT decoder case, we can use bitstream.size to check for bitstream ringbuffer operation. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 8bd1611cbb89..6f32e6d6b156 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1154,6 +1154,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb) static void coda_buf_queue(struct vb2_buffer *vb) { struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_queue *vq = vb->vb2_queue; struct coda_q_data *q_data; q_data = get_q_data(ctx, vb->vb2_queue->type); @@ -1162,8 +1163,7 @@ static void coda_buf_queue(struct vb2_buffer *vb) * In the decoder case, immediately try to copy the buffer into the * bitstream ringbuffer and mark it as ready to be dequeued. */ - if (ctx->use_bit && ctx->inst_type == CODA_INST_DECODER && - vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* * For backwards compatibility, queuing an empty buffer marks * the stream end -- cgit v1.2.3 From 976036df5e09eb0aaabbec77bcac00e6dd66422a Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Wed, 26 Nov 2014 19:42:27 -0300 Subject: [media] soc_camera: use vb2_ops_wait_prepare/finish helper This patch drops driver specific wait_prepare() and wait_finish() callbacks from vb2_ops and instead uses the the helpers vb2_ops_wait_prepare/finish() provided by the vb2 core, the lock member of the queue needs to be initalized to a mutex so that vb2 helpers vb2_ops_wait_prepare/finish() can make use of it. Signed-off-by: Lad, Prabhakar Cc: Josh Wu Cc: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/atmel-isi.c | 7 +++++-- drivers/media/platform/soc_camera/mx3_camera.c | 7 +++++-- drivers/media/platform/soc_camera/rcar_vin.c | 7 +++++-- drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 7 +++++-- drivers/media/platform/soc_camera/soc_camera.c | 16 ---------------- 5 files changed, 20 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 6d885239b16a..8526bf5c8429 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -455,8 +455,8 @@ static struct vb2_ops isi_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = soc_camera_unlock, - .wait_finish = soc_camera_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------ @@ -465,6 +465,8 @@ static struct vb2_ops isi_video_qops = { static int isi_camera_init_videobuf(struct vb2_queue *q, struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP; q->drv_priv = icd; @@ -472,6 +474,7 @@ static int isi_camera_init_videobuf(struct vb2_queue *q, q->ops = &isi_video_qops; q->mem_ops = &vb2_dma_contig_memops; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ici->host_lock; return vb2_queue_init(q); } diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 0b3299dee05d..3435fd2ca8ec 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -435,14 +435,16 @@ static struct vb2_ops mx3_videobuf_ops = { .buf_queue = mx3_videobuf_queue, .buf_cleanup = mx3_videobuf_release, .buf_init = mx3_videobuf_init, - .wait_prepare = soc_camera_unlock, - .wait_finish = soc_camera_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .stop_streaming = mx3_stop_streaming, }; static int mx3_camera_init_videobuf(struct vb2_queue *q, struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP | VB2_USERPTR; q->drv_priv = icd; @@ -450,6 +452,7 @@ static int mx3_camera_init_videobuf(struct vb2_queue *q, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct mx3_camera_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ici->host_lock; return vb2_queue_init(q); } diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 9f1473c0a0cf..9c9d5e2bd34e 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -881,8 +881,8 @@ static struct vb2_ops rcar_vin_vb2_ops = { .buf_cleanup = rcar_vin_videobuf_release, .buf_queue = rcar_vin_videobuf_queue, .stop_streaming = rcar_vin_stop_streaming, - .wait_prepare = soc_camera_unlock, - .wait_finish = soc_camera_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static irqreturn_t rcar_vin_irq(int irq, void *data) @@ -1808,6 +1808,8 @@ static int rcar_vin_querycap(struct soc_camera_host *ici, static int rcar_vin_init_videobuf2(struct vb2_queue *vq, struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vq->io_modes = VB2_MMAP | VB2_USERPTR; vq->drv_priv = icd; @@ -1815,6 +1817,7 @@ static int rcar_vin_init_videobuf2(struct vb2_queue *vq, vq->mem_ops = &vb2_dma_contig_memops; vq->buf_struct_size = sizeof(struct rcar_vin_buffer); vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vq->lock = &ici->host_lock; return vb2_queue_init(vq); } diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 71787702d4a2..9ce202f53934 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -496,8 +496,8 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = { .buf_queue = sh_mobile_ceu_videobuf_queue, .buf_cleanup = sh_mobile_ceu_videobuf_release, .buf_init = sh_mobile_ceu_videobuf_init, - .wait_prepare = soc_camera_unlock, - .wait_finish = soc_camera_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .stop_streaming = sh_mobile_ceu_stop_streaming, }; @@ -1661,6 +1661,8 @@ static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q, struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP | VB2_USERPTR; q->drv_priv = icd; @@ -1668,6 +1670,7 @@ static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ici->host_lock; return vb2_queue_init(q); } diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index b3db51c82bde..4105a9ed5f71 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -843,22 +843,6 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return res; } -void soc_camera_lock(struct vb2_queue *vq) -{ - struct soc_camera_device *icd = vb2_get_drv_priv(vq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - mutex_lock(&ici->host_lock); -} -EXPORT_SYMBOL(soc_camera_lock); - -void soc_camera_unlock(struct vb2_queue *vq) -{ - struct soc_camera_device *icd = vb2_get_drv_priv(vq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - mutex_unlock(&ici->host_lock); -} -EXPORT_SYMBOL(soc_camera_unlock); - static struct v4l2_file_operations soc_camera_fops = { .owner = THIS_MODULE, .open = soc_camera_open, -- cgit v1.2.3 From 41bc765f1e46ec7fd182573178c9ecd949c6c079 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 1 Feb 2015 12:06:17 -0300 Subject: [media] soc-camera: remove redundant code A hunk, removing this code has been lost between versions 6 and 7 of patch "soc-camera: add V4L2-async support." The code is harmless, but redundant. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 4105a9ed5f71..cee7b56f8404 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1797,8 +1797,6 @@ eadddev: mutex_unlock(&ici->clk_lock); } eadd: - video_device_release(icd->vdev); - icd->vdev = NULL; if (icd->vdev) { video_device_release(icd->vdev); icd->vdev = NULL; -- cgit v1.2.3 From 650b1815ffa7b39947cdc33568d3113134d999ec Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Tue, 25 Nov 2014 05:54:28 -0300 Subject: [media] ov2640: use the v4l2 size definitions Reuse the v4l2 size definitions from v4l2-image-sizes.h. So we can remove the rudundent definitions from ov2640.c. Signed-off-by: Josh Wu Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/ov2640.c | 82 +++++++++++++---------------------- 1 file changed, 30 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 6f2dd9093d94..1fdce2f6f880 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -25,6 +25,7 @@ #include #include #include +#include #define VAL_SET(x, mask, rshift, lshift) \ ((((x) >> rshift) & mask) << lshift) @@ -268,33 +269,10 @@ struct regval_list { u8 value; }; -/* Supported resolutions */ -enum ov2640_width { - W_QCIF = 176, - W_QVGA = 320, - W_CIF = 352, - W_VGA = 640, - W_SVGA = 800, - W_XGA = 1024, - W_SXGA = 1280, - W_UXGA = 1600, -}; - -enum ov2640_height { - H_QCIF = 144, - H_QVGA = 240, - H_CIF = 288, - H_VGA = 480, - H_SVGA = 600, - H_XGA = 768, - H_SXGA = 1024, - H_UXGA = 1200, -}; - struct ov2640_win_size { char *name; - enum ov2640_width width; - enum ov2640_height height; + u32 width; + u32 height; const struct regval_list *regs; }; @@ -495,17 +473,17 @@ static const struct regval_list ov2640_init_regs[] = { static const struct regval_list ov2640_size_change_preamble_regs[] = { { BANK_SEL, BANK_SEL_DSP }, { RESET, RESET_DVP }, - { HSIZE8, HSIZE8_SET(W_UXGA) }, - { VSIZE8, VSIZE8_SET(H_UXGA) }, + { HSIZE8, HSIZE8_SET(UXGA_WIDTH) }, + { VSIZE8, VSIZE8_SET(UXGA_HEIGHT) }, { CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN | CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN }, - { HSIZE, HSIZE_SET(W_UXGA) }, - { VSIZE, VSIZE_SET(H_UXGA) }, + { HSIZE, HSIZE_SET(UXGA_WIDTH) }, + { VSIZE, VSIZE_SET(UXGA_HEIGHT) }, { XOFFL, XOFFL_SET(0) }, { YOFFL, YOFFL_SET(0) }, - { VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) | + { VHYX, VHYX_HSIZE_SET(UXGA_WIDTH) | VHYX_VSIZE_SET(UXGA_HEIGHT) | VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)}, - { TEST, TEST_HSIZE_SET(W_UXGA) }, + { TEST, TEST_HSIZE_SET(UXGA_WIDTH) }, ENDMARKER, }; @@ -519,45 +497,45 @@ static const struct regval_list ov2640_size_change_preamble_regs[] = { { RESET, 0x00} static const struct regval_list ov2640_qcif_regs[] = { - PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4), + PER_SIZE_REG_SEQ(QCIF_WIDTH, QCIF_HEIGHT, 3, 3, 4), ENDMARKER, }; static const struct regval_list ov2640_qvga_regs[] = { - PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4), + PER_SIZE_REG_SEQ(QVGA_WIDTH, QVGA_HEIGHT, 2, 2, 4), ENDMARKER, }; static const struct regval_list ov2640_cif_regs[] = { - PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8), + PER_SIZE_REG_SEQ(CIF_WIDTH, CIF_HEIGHT, 2, 2, 8), ENDMARKER, }; static const struct regval_list ov2640_vga_regs[] = { - PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2), + PER_SIZE_REG_SEQ(VGA_WIDTH, VGA_HEIGHT, 0, 0, 2), ENDMARKER, }; static const struct regval_list ov2640_svga_regs[] = { - PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2), + PER_SIZE_REG_SEQ(SVGA_WIDTH, SVGA_HEIGHT, 1, 1, 2), ENDMARKER, }; static const struct regval_list ov2640_xga_regs[] = { - PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2), + PER_SIZE_REG_SEQ(XGA_WIDTH, XGA_HEIGHT, 0, 0, 2), { CTRLI, 0x00}, ENDMARKER, }; static const struct regval_list ov2640_sxga_regs[] = { - PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2), + PER_SIZE_REG_SEQ(SXGA_WIDTH, SXGA_HEIGHT, 0, 0, 2), { CTRLI, 0x00}, { R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE }, ENDMARKER, }; static const struct regval_list ov2640_uxga_regs[] = { - PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0), + PER_SIZE_REG_SEQ(UXGA_WIDTH, UXGA_HEIGHT, 0, 0, 0), { CTRLI, 0x00}, { R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE }, ENDMARKER, @@ -567,14 +545,14 @@ static const struct regval_list ov2640_uxga_regs[] = { {.name = n, .width = w , .height = h, .regs = r } static const struct ov2640_win_size ov2640_supported_win_sizes[] = { - OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs), - OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs), - OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs), - OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs), - OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs), - OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs), - OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs), - OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs), + OV2640_SIZE("QCIF", QCIF_WIDTH, QCIF_HEIGHT, ov2640_qcif_regs), + OV2640_SIZE("QVGA", QVGA_WIDTH, QVGA_HEIGHT, ov2640_qvga_regs), + OV2640_SIZE("CIF", CIF_WIDTH, CIF_HEIGHT, ov2640_cif_regs), + OV2640_SIZE("VGA", VGA_WIDTH, VGA_HEIGHT, ov2640_vga_regs), + OV2640_SIZE("SVGA", SVGA_WIDTH, SVGA_HEIGHT, ov2640_svga_regs), + OV2640_SIZE("XGA", XGA_WIDTH, XGA_HEIGHT, ov2640_xga_regs), + OV2640_SIZE("SXGA", SXGA_WIDTH, SXGA_HEIGHT, ov2640_sxga_regs), + OV2640_SIZE("UXGA", UXGA_WIDTH, UXGA_HEIGHT, ov2640_uxga_regs), }; /* @@ -867,7 +845,7 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd, struct ov2640_priv *priv = to_ov2640(client); if (!priv->win) { - u32 width = W_SVGA, height = H_SVGA; + u32 width = SVGA_WIDTH, height = SVGA_HEIGHT; priv->win = ov2640_select_win(&width, &height); priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8; } @@ -954,8 +932,8 @@ static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { a->c.left = 0; a->c.top = 0; - a->c.width = W_UXGA; - a->c.height = H_UXGA; + a->c.width = UXGA_WIDTH; + a->c.height = UXGA_HEIGHT; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0; @@ -965,8 +943,8 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { a->bounds.left = 0; a->bounds.top = 0; - a->bounds.width = W_UXGA; - a->bounds.height = H_UXGA; + a->bounds.width = UXGA_WIDTH; + a->bounds.height = UXGA_HEIGHT; a->defrect = a->bounds; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; -- cgit v1.2.3 From 4abec46833c923c1be8dfee1d4eb1fff12cceb21 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Mon, 26 Jan 2015 14:08:39 -0300 Subject: [media] rcar_vin: helper function for streaming stop The code that tests that capture from a stream has stopped is presently insufficient and the potential for a race condition exists where frame capture may generate an interrupt between requesting the capture process halt and freeing buffers. This patch refactors code out of rcar_vin_videobuf_release() and into rcar_vin_wait_stop_streaming(), and ensures there are calls in places where we need to know that capturing has finished. Signed-off-by: Ian Molton Signed-off-by: William Towle Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/rcar_vin.c | 41 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 9c9d5e2bd34e..30dc707b7946 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -804,6 +804,28 @@ error: vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); } +/* + * Wait for capture to stop and all in-flight buffers to be finished with by + * the video hardware. This must be called under &priv->lock + * + */ +static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) +{ + while (priv->state != STOPPED) { + /* issue stop if running */ + if (priv->state == RUNNING) + rcar_vin_request_capture_stop(priv); + + /* wait until capturing has been stopped */ + if (priv->state == STOPPING) { + priv->request_to_stop = true; + spin_unlock_irq(&priv->lock); + wait_for_completion(&priv->capture_stop); + spin_lock_irq(&priv->lock); + } + } +} + static void rcar_vin_videobuf_release(struct vb2_buffer *vb) { struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); @@ -823,20 +845,8 @@ static void rcar_vin_videobuf_release(struct vb2_buffer *vb) } if (buf_in_use) { - while (priv->state != STOPPED) { - - /* issue stop if running */ - if (priv->state == RUNNING) - rcar_vin_request_capture_stop(priv); - - /* wait until capturing has been stopped */ - if (priv->state == STOPPING) { - priv->request_to_stop = true; - spin_unlock_irq(&priv->lock); - wait_for_completion(&priv->capture_stop); - spin_lock_irq(&priv->lock); - } - } + rcar_vin_wait_stop_streaming(priv); + /* * Capturing has now stopped. The buffer we have been asked * to release could be any of the current buffers in use, so @@ -870,8 +880,11 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq) struct list_head *buf_head, *tmp; spin_lock_irq(&priv->lock); + + rcar_vin_wait_stop_streaming(priv); list_for_each_safe(buf_head, tmp, &priv->capture) list_del_init(buf_head); + spin_unlock_irq(&priv->lock); } -- cgit v1.2.3 From e99f0115e56ce4c4cda269cd21b25f7e14fa548f Mon Sep 17 00:00:00 2001 From: William Towle Date: Mon, 26 Jan 2015 14:08:40 -0300 Subject: [media] rcar_vin: move buffer management to .stop_streaming handler This commit moves the "buffer in use" logic from the .buf_cleanup handler into .stop_streaming, based on advice that this is its proper logical home. By ensuring the list of pointers in priv->queue_buf[] is managed as soon as possible, we avoid warnings concerning buffers in ACTIVE state when the system cleans up after streaming stops. This fixes a problem with modification of buffers after their content has been cleared for passing to userspace. After the refactoring, the buf_init and buf_cleanup functions were found to contain only initialisation/release steps as are carried out elsewhere if omitted; these functions and references were removed. Signed-off-by: William Towle Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/rcar_vin.c | 62 ++++++---------------------- 1 file changed, 13 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 30dc707b7946..279ab9f6ae38 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -826,72 +826,36 @@ static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) } } -static void rcar_vin_videobuf_release(struct vb2_buffer *vb) +static void rcar_vin_stop_streaming(struct vb2_queue *vq) { - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct rcar_vin_priv *priv = ici->priv; - unsigned int i; - int buf_in_use = 0; + struct list_head *buf_head, *tmp; + int i; spin_lock_irq(&priv->lock); + rcar_vin_wait_stop_streaming(priv); - /* Is the buffer in use by the VIN hardware? */ for (i = 0; i < MAX_BUFFER_NUM; i++) { - if (priv->queue_buf[i] == vb) { - buf_in_use = 1; - break; - } - } - - if (buf_in_use) { - rcar_vin_wait_stop_streaming(priv); - - /* - * Capturing has now stopped. The buffer we have been asked - * to release could be any of the current buffers in use, so - * release all buffers that are in use by HW - */ - for (i = 0; i < MAX_BUFFER_NUM; i++) { - if (priv->queue_buf[i]) { - vb2_buffer_done(priv->queue_buf[i], + if (priv->queue_buf[i]) { + vb2_buffer_done(priv->queue_buf[i], VB2_BUF_STATE_ERROR); - priv->queue_buf[i] = NULL; - } + priv->queue_buf[i] = NULL; } - } else { - list_del_init(to_buf_list(vb)); } - spin_unlock_irq(&priv->lock); -} - -static int rcar_vin_videobuf_init(struct vb2_buffer *vb) -{ - INIT_LIST_HEAD(to_buf_list(vb)); - return 0; -} - -static void rcar_vin_stop_streaming(struct vb2_queue *vq) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(vq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct rcar_vin_priv *priv = ici->priv; - struct list_head *buf_head, *tmp; - - spin_lock_irq(&priv->lock); - - rcar_vin_wait_stop_streaming(priv); - list_for_each_safe(buf_head, tmp, &priv->capture) + list_for_each_safe(buf_head, tmp, &priv->capture) { + vb2_buffer_done(&list_entry(buf_head, + struct rcar_vin_buffer, list)->vb, + VB2_BUF_STATE_ERROR); list_del_init(buf_head); - + } spin_unlock_irq(&priv->lock); } static struct vb2_ops rcar_vin_vb2_ops = { .queue_setup = rcar_vin_videobuf_setup, - .buf_init = rcar_vin_videobuf_init, - .buf_cleanup = rcar_vin_videobuf_release, .buf_queue = rcar_vin_videobuf_queue, .stop_streaming = rcar_vin_stop_streaming, .wait_prepare = vb2_ops_wait_prepare, -- cgit v1.2.3 From 5eeb3014827f44ea7de43c865118cb2095ad030e Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 16 Jan 2015 19:55:26 -0300 Subject: [media] cx231xx: fix usbdev leak on failure paths in cx231xx_usb_probe() Commit b7085c086475 ("cx231xx: convert from pr_foo to dev_foo") moves usb_get_dev(interface_to_usbdev(interface)) to the beginning of cx231xx_usb_probe() to use udev->dev in dev_err(), but it does not make sure usbdev is put on all failure paths. Later dev_err(udev->dev) was replaced by dev_err(d). So the patch moves usb_get_dev() below (before the first use) and fixes another failure path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-cards.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index ae05d591f228..33c2fa2e7596 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1403,7 +1403,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, struct usb_interface_assoc_descriptor *assoc_desc; ifnum = interface->altsetting[0].desc.bInterfaceNumber; - udev = usb_get_dev(interface_to_usbdev(interface)); /* * Interface number 0 - IR interface (handled by mceusb driver) @@ -1424,11 +1423,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface, } } while (test_and_set_bit(nr, &cx231xx_devused)); + udev = usb_get_dev(interface_to_usbdev(interface)); + /* allocate memory for our device state and initialize it */ dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - clear_bit(nr, &cx231xx_devused); - return -ENOMEM; + retval = -ENOMEM; + goto err_if; } snprintf(dev->name, 29, "cx231xx #%d", nr); -- cgit v1.2.3 From b5603a943d11cd4c74e90fdd68296ffdc8f6749c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Feb 2015 10:52:26 -0200 Subject: [media] cx231xx: don't use dev it not allocated changeset 5eeb3014827f added a fixup at the error check code. However, it introduced a new error: drivers/media/usb/cx231xx/cx231xx-cards.c:1586 cx231xx_usb_probe() error: we previously assumed 'dev' could be null (see line 1430) This happens when dev = kmalloc() fails. So, instead of relying on it to succeed, just change the parameter of clear_bit() from 'dev->devno' to 'nr'. Cc: Alexey Khoroshilov Cc: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 33c2fa2e7596..da03733690bd 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1583,7 +1583,7 @@ err_v4l2: usb_set_intfdata(interface, NULL); err_if: usb_put_dev(udev); - clear_bit(dev->devno, &cx231xx_devused); + clear_bit(nr, &cx231xx_devused); return retval; } -- cgit v1.2.3 From 3edf7eb83b693d5062ddd1c22c6996dce71ba2a6 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Thu, 22 Jan 2015 07:39:11 -0300 Subject: [media] pvrusb2: use msecs_to_jiffies for conversion This is only an API consolidation and should make things more readable Signed-off-by: Nicholas Mc Guire Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index ff73f4036b7b..930593d7028d 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -4290,9 +4290,8 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw) the encoder. */ if (!hdw->state_encoder_waitok) { hdw->encoder_wait_timer.expires = - jiffies + - (HZ * TIME_MSEC_ENCODER_WAIT - / 1000); + jiffies + msecs_to_jiffies( + TIME_MSEC_ENCODER_WAIT); add_timer(&hdw->encoder_wait_timer); } } @@ -4415,8 +4414,8 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw) if (pvr2_encoder_start(hdw) < 0) return !0; hdw->state_encoder_run = !0; if (!hdw->state_encoder_runok) { - hdw->encoder_run_timer.expires = - jiffies + (HZ * TIME_MSEC_ENCODER_OK / 1000); + hdw->encoder_run_timer.expires = jiffies + + msecs_to_jiffies(TIME_MSEC_ENCODER_OK); add_timer(&hdw->encoder_run_timer); } } @@ -4507,9 +4506,8 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) but before we did the pending check. */ if (!hdw->state_decoder_quiescent) { hdw->quiescent_timer.expires = - jiffies + - (HZ * TIME_MSEC_DECODER_WAIT - / 1000); + jiffies + msecs_to_jiffies( + TIME_MSEC_DECODER_WAIT); add_timer(&hdw->quiescent_timer); } } @@ -4533,9 +4531,8 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) hdw->state_decoder_run = !0; if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) { hdw->decoder_stabilization_timer.expires = - jiffies + - (HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / - 1000); + jiffies + msecs_to_jiffies( + TIME_MSEC_DECODER_STABILIZATION_WAIT); add_timer(&hdw->decoder_stabilization_timer); } else { hdw->state_decoder_ready = !0; -- cgit v1.2.3 From 42fd3638fa61eb01aad7fcedc7df0eddd5f57b86 Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Mon, 26 Jan 2015 11:50:15 -0300 Subject: [media] media: am437x: fix sparse warnings This patch fixes following spare warnings: drivers/media/platform/am437x/am437x-vpfe.c:66:28: warning: symbol 'vpfe_standards' was not declared. Should it be static? drivers/media/platform/am437x/am437x-vpfe.c:2202:57: warning: incorrect type in argument 2 (different address spaces) drivers/media/platform/am437x/am437x-vpfe.c:2202:57: expected void [noderef] *params drivers/media/platform/am437x/am437x-vpfe.c:2202:57: got void *param include/linux/spinlock.h:364:9: warning: context imbalance in 'vpfe_start_streaming' - unexpected unlock Reported-by: Fengguang Wu Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index e01ac22d6244..349bd060f5a4 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -63,7 +63,7 @@ struct vpfe_standard { int frame_format; }; -const struct vpfe_standard vpfe_standards[] = { +static const struct vpfe_standard vpfe_standards[] = { {V4L2_STD_525_60, 720, 480, {11, 10}, 1}, {V4L2_STD_625_50, 720, 576, {54, 59}, 1}, }; @@ -2024,7 +2024,6 @@ err: list_del(&buf->list); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); } - spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags); return ret; } @@ -2199,7 +2198,7 @@ static long vpfe_ioctl_default(struct file *file, void *priv, switch (cmd) { case VIDIOC_AM437X_CCDC_CFG: - ret = vpfe_ccdc_set_params(&vpfe->ccdc, param); + ret = vpfe_ccdc_set_params(&vpfe->ccdc, (void __user *)param); if (ret) { vpfe_dbg(2, vpfe, "Error setting parameters in CCDC\n"); -- cgit v1.2.3 From 244829226f47ffb4d6009a2ccd2771cd149d8114 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 28 Jan 2015 18:17:41 -0300 Subject: [media] timberdale: do not select TIMB_DMA The timberdale media driver requires the use of the respective dma engine driver, but that may not be enabled, causing a Kconfig warning: warning: (VIDEO_TIMBERDALE) selects TIMB_DMA which has unmet direct dependencies (DMADEVICES && MFD_TIMBERDALE) This fixes the dependency by removing the inappropriate 'select' statement and replacing it with a direct dependency on the drivers that provide the services this needs. Fixes: 7155043c2d027 ("[media] enable COMPILE_TEST for media drivers") Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 250b7af66027..663f7580a5da 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -56,10 +56,8 @@ config VIDEO_VIU config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES - depends on MFD_TIMBERDALE || COMPILE_TEST - select DMA_ENGINE - select TIMB_DMA + depends on VIDEO_V4L2 && I2C + depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST select VIDEO_ADV7180 select VIDEOBUF_DMA_CONTIG ---help--- -- cgit v1.2.3 From cc287f7c404216b0b680f78963e3fcd766df6484 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 28 Jan 2015 18:17:42 -0300 Subject: [media] radio/aimslab: use mdelay instead of udelay Large udelay values are not allowed on the ARM architecture and result in a build error like ERROR: "__bad_udelay" [drivers/media/radio/radio-aimslab.ko] undefined! This changes the aimslab radio driver to use an equivalent mdelay statement. Signed-off-by: Arnd Bergmann Cc: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-aimslab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index a739ad492e7b..ea9308796741 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -129,11 +129,11 @@ static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) } else if (curvol < vol) { outb(0x98, isa->io); /* volume up + sigstr + on */ for (; curvol < vol; curvol++) - udelay(3000); + mdelay(3); } else if (curvol > vol) { outb(0x58, isa->io); /* volume down + sigstr + on */ for (; curvol > vol; curvol--) - udelay(3000); + mdelay(3); } outb(0xd8, isa->io); /* volume steady + sigstr + on */ rt->curvol = vol; -- cgit v1.2.3 From 68998ea253862a23c530fe0c2b1a0715ace517c7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 28 Jan 2015 18:17:44 -0300 Subject: [media] siano: fix Kconfig dependencies The USB and MMC front-ends to the siano driver both only make sense when combined with the SMS_SIANO_MDTV driver. That driver already requires RC_CORE to not be a module, so we also need to add that dependency here. drivers/built-in.o: In function `smssdio_remove': :(.text+0x155bd8): undefined reference to `smscore_putbuffer' :(.text+0x155bdc): undefined reference to `smscore_unregister_device' drivers/built-in.o: In function `smssdio_interrupt': :(.text+0x155e4c): undefined reference to `smsendian_handle_rx_message' :(.text+0x155e50): undefined reference to `smscore_onresponse' :(.text+0x155e54): undefined reference to `smscore_getbuffer' :(.text+0x155e58): undefined reference to `smscore_putbuffer' drivers/built-in.o: In function `smssdio_sendrequest': :(.text+0x155f20): undefined reference to `smsendian_handle_tx_message' drivers/built-in.o: In function `smssdio_probe': :(.text+0x15610c): undefined reference to `sms_get_board' :(.text+0x156114): undefined reference to `smscore_register_device' :(.text+0x156118): undefined reference to `smscore_set_board_id' :(.text+0x156128): undefined reference to `smscore_unregister_device' :(.text+0x156140): undefined reference to `smscore_start_device' Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/mmc/siano/Kconfig | 2 ++ drivers/media/usb/siano/Kconfig | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig index aa05ad3c1ccb..7693487e2f63 100644 --- a/drivers/media/mmc/siano/Kconfig +++ b/drivers/media/mmc/siano/Kconfig @@ -6,6 +6,8 @@ config SMS_SDIO_DRV tristate "Siano SMS1xxx based MDTV via SDIO interface" depends on DVB_CORE && HAS_DMA depends on MMC + depends on !RC_CORE || RC_CORE select MEDIA_COMMON_OPTIONS + select SMS_SIANO_MDTV ---help--- Choose if you would like to have Siano's support for SDIO interface diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig index 5afbd9a4b55c..d37b742d4f7a 100644 --- a/drivers/media/usb/siano/Kconfig +++ b/drivers/media/usb/siano/Kconfig @@ -5,7 +5,9 @@ config SMS_USB_DRV tristate "Siano SMS1xxx based MDTV receiver" depends on DVB_CORE && HAS_DMA + depends on !RC_CORE || RC_CORE select MEDIA_COMMON_OPTIONS + select SMS_SIANO_MDTV ---help--- Choose if you would like to have Siano's support for USB interface -- cgit v1.2.3 From eb79dbf6c2b4d091bc358074ff39795e4054db5c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2015 08:22:37 -0300 Subject: [media] vivid: use consistent colorspace/Y'CbCr Encoding strings Keep the colorspace and encoding names consistent with what is used elsewhere (primarily the utilities in v4l-utils.git). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-ctrls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index 857e7866e8bc..32a798f2d953 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -689,7 +689,7 @@ static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = { static const char * const vivid_ctrl_colorspace_strings[] = { "SMPTE 170M", - "REC 709", + "Rec. 709", "sRGB", "AdobeRGB", "BT.2020", @@ -716,7 +716,7 @@ static const char * const vivid_ctrl_ycbcr_enc_strings[] = { "xvYCC 601", "xvYCC 709", "sYCC", - "BT.2020 Non-Constant Luminance", + "BT.2020", "BT.2020 Constant Luminance", "SMPTE 240M", NULL, -- cgit v1.2.3 From 24692801a4d03dabb64e38b10d089beb3710be9d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 29 Jan 2015 13:12:05 -0300 Subject: [media] davinci: add V4L2 dependencies The davinci media drivers use videobuf2, which they enable through a 'select' statement. If one of these drivers is built-in, but the v4l2 core is a loadable modules, we end up with a link error: drivers/built-in.o: In function `vb2_fop_mmap': :(.text+0x113e84): undefined reference to `video_devdata' drivers/built-in.o: In function `vb2_ioctl_create_bufs': :(.text+0x114710): undefined reference to `video_devdata' drivers/built-in.o: In function `vb2_ioctl_reqbufs': :(.text+0x114ed8): undefined reference to `video_devdata' drivers/built-in.o: In function `vb2_ioctl_querybuf': :(.text+0x115530): undefined reference to `video_devdata' To solve this, we need to add a dependency on VIDEO_V4L2, which enforces that the davinci drivers themselves can only be loadable modules if V4L2 is not built-in, and they do not cause the videobuf2 code to be built-in. Signed-off-by: Arnd Bergmann Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig index d9e1ddb586b1..469e9d28cec0 100644 --- a/drivers/media/platform/davinci/Kconfig +++ b/drivers/media/platform/davinci/Kconfig @@ -1,6 +1,6 @@ config VIDEO_DAVINCI_VPIF_DISPLAY tristate "TI DaVinci VPIF V4L2-Display driver" - depends on VIDEO_DEV + depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG @@ -16,7 +16,7 @@ config VIDEO_DAVINCI_VPIF_DISPLAY config VIDEO_DAVINCI_VPIF_CAPTURE tristate "TI DaVinci VPIF video capture driver" - depends on VIDEO_DEV + depends on VIDEO_V4L2 depends on ARCH_DAVINCI || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG @@ -75,7 +75,7 @@ config VIDEO_DM365_ISIF config VIDEO_DAVINCI_VPBE_DISPLAY tristate "TI DaVinci VPBE V4L2-Display driver" - depends on ARCH_DAVINCI + depends on VIDEO_V4L2 && ARCH_DAVINCI depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG help -- cgit v1.2.3 From fa5721d159bb1da086d85c34f358282d4ae07093 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:20 -0300 Subject: [media] adv7180: Do not request the IRQ again during resume Currently the IRQ is requested from within the init_device() function. This function is not only called during device probe, but also during resume causing the driver to try to request the IRQ again. Move requesting the IRQ from init_device() to the probe function to make sure that it is only requested once. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 94a3341b091b..7666d10d3f16 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -553,11 +553,6 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) /* register for interrupts */ if (state->irq > 0) { - ret = request_threaded_irq(state->irq, NULL, adv7180_irq, - IRQF_ONESHOT, KBUILD_MODNAME, state); - if (ret) - return ret; - ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, ADV7180_ADI_CTRL_IRQ_SPACE); if (ret < 0) @@ -597,7 +592,6 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) return 0; err: - free_irq(state->irq, state); return ret; } @@ -634,6 +628,13 @@ static int adv7180_probe(struct i2c_client *client, if (ret) goto err_free_ctrl; + if (state->irq) { + ret = request_threaded_irq(client->irq, NULL, adv7180_irq, + IRQF_ONESHOT, KBUILD_MODNAME, state); + if (ret) + goto err_free_ctrl; + } + ret = v4l2_async_register_subdev(sd); if (ret) goto err_free_irq; -- cgit v1.2.3 From f3e991d418c7ee2890b1956c32f8b31639249ade Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:21 -0300 Subject: [media] adv7180: Pass correct flags to request_threaded_irq() Most IRQ controllers support different types of interrupts. The adv7180 generates falling edge interrupts, so make sure to pass IRQF_TRIGGER_FALLING to request_threaded_irq() so the IRQ controller is configured for the correct mode. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 7666d10d3f16..15deaad1c6eb 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -630,7 +630,8 @@ static int adv7180_probe(struct i2c_client *client, if (state->irq) { ret = request_threaded_irq(client->irq, NULL, adv7180_irq, - IRQF_ONESHOT, KBUILD_MODNAME, state); + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + KBUILD_MODNAME, state); if (ret) goto err_free_ctrl; } -- cgit v1.2.3 From 029d61779189a488d5649dab43c83cc6497e8843 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:23 -0300 Subject: [media] adv7180: Cleanup register define naming Consistently prefix register defines with ADV7180_REG. Also remove the "ADI" from register names, the ADV7180 prefix should provide enough of a namespace separation. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 105 ++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 15deaad1c6eb..a3ea3bbd16c6 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -31,7 +31,7 @@ #include #include -#define ADV7180_INPUT_CONTROL_REG 0x00 +#define ADV7180_REG_INPUT_CONTROL 0x00 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 #define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 @@ -50,36 +50,36 @@ #define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 #define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f -#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG 0x04 +#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x04 #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 -#define ADV7180_AUTODETECT_ENABLE_REG 0x07 +#define ADV7180_REG_AUTODETECT_ENABLE 0x07 #define ADV7180_AUTODETECT_DEFAULT 0x7f /* Contrast */ -#define ADV7180_CON_REG 0x08 /*Unsigned */ +#define ADV7180_REG_CON 0x08 /*Unsigned */ #define ADV7180_CON_MIN 0 #define ADV7180_CON_DEF 128 #define ADV7180_CON_MAX 255 /* Brightness*/ -#define ADV7180_BRI_REG 0x0a /*Signed */ +#define ADV7180_REG_BRI 0x0a /*Signed */ #define ADV7180_BRI_MIN -128 #define ADV7180_BRI_DEF 0 #define ADV7180_BRI_MAX 127 /* Hue */ -#define ADV7180_HUE_REG 0x0b /*Signed, inverted */ +#define ADV7180_REG_HUE 0x0b /*Signed, inverted */ #define ADV7180_HUE_MIN -127 #define ADV7180_HUE_DEF 0 #define ADV7180_HUE_MAX 128 -#define ADV7180_ADI_CTRL_REG 0x0e -#define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 +#define ADV7180_REG_CTRL 0x0e +#define ADV7180_CTRL_IRQ_SPACE 0x20 -#define ADV7180_PWR_MAN_REG 0x0f +#define ADV7180_REG_PWR_MAN 0x0f #define ADV7180_PWR_MAN_ON 0x04 #define ADV7180_PWR_MAN_OFF 0x24 #define ADV7180_PWR_MAN_RES 0x80 -#define ADV7180_STATUS1_REG 0x10 +#define ADV7180_REG_STATUS1 0x10 #define ADV7180_STATUS1_IN_LOCK 0x01 #define ADV7180_STATUS1_AUTOD_MASK 0x70 #define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 @@ -91,33 +91,33 @@ #define ADV7180_STATUS1_AUTOD_PAL_COMB 0x60 #define ADV7180_STATUS1_AUTOD_SECAM_525 0x70 -#define ADV7180_IDENT_REG 0x11 +#define ADV7180_REG_IDENT 0x11 #define ADV7180_ID_7180 0x18 -#define ADV7180_ICONF1_ADI 0x40 +#define ADV7180_REG_ICONF1 0x40 #define ADV7180_ICONF1_ACTIVE_LOW 0x01 #define ADV7180_ICONF1_PSYNC_ONLY 0x10 #define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 /* Saturation */ -#define ADV7180_SD_SAT_CB_REG 0xe3 /*Unsigned */ -#define ADV7180_SD_SAT_CR_REG 0xe4 /*Unsigned */ +#define ADV7180_REG_SD_SAT_CB 0xe3 /*Unsigned */ +#define ADV7180_REG_SD_SAT_CR 0xe4 /*Unsigned */ #define ADV7180_SAT_MIN 0 #define ADV7180_SAT_DEF 128 #define ADV7180_SAT_MAX 255 #define ADV7180_IRQ1_LOCK 0x01 #define ADV7180_IRQ1_UNLOCK 0x02 -#define ADV7180_ISR1_ADI 0x42 -#define ADV7180_ICR1_ADI 0x43 -#define ADV7180_IMR1_ADI 0x44 -#define ADV7180_IMR2_ADI 0x48 +#define ADV7180_REG_ISR1 0x42 +#define ADV7180_REG_ICR1 0x43 +#define ADV7180_REG_IMR1 0x44 +#define ADV7180_REG_IMR2 0x48 #define ADV7180_IRQ3_AD_CHANGE 0x08 -#define ADV7180_ISR3_ADI 0x4A -#define ADV7180_ICR3_ADI 0x4B -#define ADV7180_IMR3_ADI 0x4C -#define ADV7180_IMR4_ADI 0x50 +#define ADV7180_REG_ISR3 0x4A +#define ADV7180_REG_ICR3 0x4B +#define ADV7180_REG_IMR3 0x4C +#define ADV7180_REG_IMR4 0x50 -#define ADV7180_NTSC_V_BIT_END_REG 0xE6 +#define ADV7180_REG_NTSC_V_BIT_END 0xE6 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F struct adv7180_state { @@ -196,7 +196,7 @@ static u32 adv7180_status_to_v4l2(u8 status1) static int __adv7180_status(struct i2c_client *client, u32 *status, v4l2_std_id *std) { - int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); + int status1 = i2c_smbus_read_byte_data(client, ADV7180_REG_STATUS1); if (status1 < 0) return status1; @@ -247,14 +247,13 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) goto out; - ret = i2c_smbus_read_byte_data(client, ADV7180_INPUT_CONTROL_REG); - + ret = i2c_smbus_read_byte_data(client, ADV7180_REG_INPUT_CONTROL); if (ret < 0) goto out; ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; ret = i2c_smbus_write_byte_data(client, - ADV7180_INPUT_CONTROL_REG, ret | input); + ADV7180_REG_INPUT_CONTROL, ret | input); state->input = input; out: mutex_unlock(&state->mutex); @@ -284,7 +283,7 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* all standards -> autodetect */ if (std == V4L2_STD_ALL) { ret = - i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, + i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->input); if (ret < 0) @@ -298,7 +297,7 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) goto out; ret = i2c_smbus_write_byte_data(client, - ADV7180_INPUT_CONTROL_REG, + ADV7180_REG_INPUT_CONTROL, ret | state->input); if (ret < 0) goto out; @@ -322,7 +321,7 @@ static int adv7180_set_power(struct adv7180_state *state, else val = ADV7180_PWR_MAN_OFF; - return i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, val); + return i2c_smbus_write_byte_data(client, ADV7180_REG_PWR_MAN, val); } static int adv7180_s_power(struct v4l2_subdev *sd, int on) @@ -356,25 +355,25 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_BRI, val); break; case V4L2_CID_HUE: /*Hue is inverted according to HSL chart */ - ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_HUE, -val); break; case V4L2_CID_CONTRAST: - ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CON, val); break; case V4L2_CID_SATURATION: /* *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE *Let's not confuse the user, everybody understands saturation */ - ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG, + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_SD_SAT_CB, val); if (ret < 0) break; - ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG, + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_SD_SAT_CR, val); break; default: @@ -488,12 +487,12 @@ static irqreturn_t adv7180_irq(int irq, void *devid) u8 isr3; mutex_lock(&state->mutex); - i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, - ADV7180_ADI_CTRL_IRQ_SPACE); - isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI); + i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, + ADV7180_CTRL_IRQ_SPACE); + isr3 = i2c_smbus_read_byte_data(client, ADV7180_REG_ISR3); /* clear */ - i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3); - i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0); + i2c_smbus_write_byte_data(client, ADV7180_REG_ICR3, isr3); + i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, 0); if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) __adv7180_status(client, NULL, &state->curr_norm); @@ -510,7 +509,7 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) /* Enable autodetection */ if (state->autodetect) { ret = - i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, + i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->input); if (ret < 0) @@ -518,7 +517,7 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) ret = i2c_smbus_write_byte_data(client, - ADV7180_AUTODETECT_ENABLE_REG, + ADV7180_REG_AUTODETECT_ENABLE, ADV7180_AUTODETECT_DEFAULT); if (ret < 0) return ret; @@ -528,7 +527,7 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) return ret; ret = - i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, + i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, ret | state->input); if (ret < 0) return ret; @@ -536,14 +535,14 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) } /* ITU-R BT.656-4 compatible */ ret = i2c_smbus_write_byte_data(client, - ADV7180_EXTENDED_OUTPUT_CONTROL_REG, + ADV7180_REG_EXTENDED_OUTPUT_CONTROL, ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); if (ret < 0) return ret; /* Manually set V bit end position in NTSC mode */ ret = i2c_smbus_write_byte_data(client, - ADV7180_NTSC_V_BIT_END_REG, + ADV7180_REG_NTSC_V_BIT_END, ADV7180_NTSC_V_BIT_END_MANUAL_NVEND); if (ret < 0) return ret; @@ -553,37 +552,37 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state) /* register for interrupts */ if (state->irq > 0) { - ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, - ADV7180_ADI_CTRL_IRQ_SPACE); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, + ADV7180_CTRL_IRQ_SPACE); if (ret < 0) goto err; /* config the Interrupt pin to be active low */ - ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI, + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_ICONF1, ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY); if (ret < 0) goto err; - ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR1, 0); if (ret < 0) goto err; - ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR2, 0); if (ret < 0) goto err; /* enable AD change interrupts interrupts */ - ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI, + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR3, ADV7180_IRQ3_AD_CHANGE); if (ret < 0) goto err; - ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0); + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR4, 0); if (ret < 0) goto err; - ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, + ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, 0); if (ret < 0) goto err; -- cgit v1.2.3 From 3999e5d01da74f1a22afbb0b61b3992fea301478 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:24 -0300 Subject: [media] adv7180: Do implicit register paging The ad7180 has multiple register pages which can be switched between by writing to a register. Currently the driver manually switches between pages whenever a register outside of the default register map is accessed and switches back after it has been accessed. This is a bit tedious and also potential source for bugs. This patch adds two helper functions that take care of switching between pages and reading/writing the register. The register numbers for registers are updated to encode both the page (in the upper 8-bits) and the register (in the lower 8-bits) numbers. Having multiple pages means that a register access is not a single atomic i2c_smbus_write_byte_data() or i2c_smbus_read_byte_data() call and we need to make sure that concurrent register access does not race against each other. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 206 ++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index a3ea3bbd16c6..432a756f8e1d 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -31,7 +31,7 @@ #include #include -#define ADV7180_REG_INPUT_CONTROL 0x00 +#define ADV7180_REG_INPUT_CONTROL 0x0000 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 #define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 @@ -50,28 +50,28 @@ #define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 #define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f -#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x04 +#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004 #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 #define ADV7180_REG_AUTODETECT_ENABLE 0x07 #define ADV7180_AUTODETECT_DEFAULT 0x7f /* Contrast */ -#define ADV7180_REG_CON 0x08 /*Unsigned */ +#define ADV7180_REG_CON 0x0008 /*Unsigned */ #define ADV7180_CON_MIN 0 #define ADV7180_CON_DEF 128 #define ADV7180_CON_MAX 255 /* Brightness*/ -#define ADV7180_REG_BRI 0x0a /*Signed */ +#define ADV7180_REG_BRI 0x000a /*Signed */ #define ADV7180_BRI_MIN -128 #define ADV7180_BRI_DEF 0 #define ADV7180_BRI_MAX 127 /* Hue */ -#define ADV7180_REG_HUE 0x0b /*Signed, inverted */ +#define ADV7180_REG_HUE 0x000b /*Signed, inverted */ #define ADV7180_HUE_MIN -127 #define ADV7180_HUE_DEF 0 #define ADV7180_HUE_MAX 128 -#define ADV7180_REG_CTRL 0x0e +#define ADV7180_REG_CTRL 0x000e #define ADV7180_CTRL_IRQ_SPACE 0x20 #define ADV7180_REG_PWR_MAN 0x0f @@ -79,7 +79,7 @@ #define ADV7180_PWR_MAN_OFF 0x24 #define ADV7180_PWR_MAN_RES 0x80 -#define ADV7180_REG_STATUS1 0x10 +#define ADV7180_REG_STATUS1 0x0010 #define ADV7180_STATUS1_IN_LOCK 0x01 #define ADV7180_STATUS1_AUTOD_MASK 0x70 #define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 @@ -91,33 +91,33 @@ #define ADV7180_STATUS1_AUTOD_PAL_COMB 0x60 #define ADV7180_STATUS1_AUTOD_SECAM_525 0x70 -#define ADV7180_REG_IDENT 0x11 +#define ADV7180_REG_IDENT 0x0011 #define ADV7180_ID_7180 0x18 -#define ADV7180_REG_ICONF1 0x40 +#define ADV7180_REG_ICONF1 0x0040 #define ADV7180_ICONF1_ACTIVE_LOW 0x01 #define ADV7180_ICONF1_PSYNC_ONLY 0x10 #define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 /* Saturation */ -#define ADV7180_REG_SD_SAT_CB 0xe3 /*Unsigned */ -#define ADV7180_REG_SD_SAT_CR 0xe4 /*Unsigned */ +#define ADV7180_REG_SD_SAT_CB 0x00e3 /*Unsigned */ +#define ADV7180_REG_SD_SAT_CR 0x00e4 /*Unsigned */ #define ADV7180_SAT_MIN 0 #define ADV7180_SAT_DEF 128 #define ADV7180_SAT_MAX 255 #define ADV7180_IRQ1_LOCK 0x01 #define ADV7180_IRQ1_UNLOCK 0x02 -#define ADV7180_REG_ISR1 0x42 -#define ADV7180_REG_ICR1 0x43 -#define ADV7180_REG_IMR1 0x44 -#define ADV7180_REG_IMR2 0x48 +#define ADV7180_REG_ISR1 0x0042 +#define ADV7180_REG_ICR1 0x0043 +#define ADV7180_REG_IMR1 0x0044 +#define ADV7180_REG_IMR2 0x0048 #define ADV7180_IRQ3_AD_CHANGE 0x08 -#define ADV7180_REG_ISR3 0x4A -#define ADV7180_REG_ICR3 0x4B -#define ADV7180_REG_IMR3 0x4C +#define ADV7180_REG_ISR3 0x004A +#define ADV7180_REG_ICR3 0x004B +#define ADV7180_REG_IMR3 0x004C #define ADV7180_REG_IMR4 0x50 -#define ADV7180_REG_NTSC_V_BIT_END 0xE6 +#define ADV7180_REG_NTSC_V_BIT_END 0x00E6 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F struct adv7180_state { @@ -129,11 +129,41 @@ struct adv7180_state { bool autodetect; bool powered; u8 input; + + struct i2c_client *client; + unsigned int register_page; }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ struct adv7180_state, \ ctrl_hdl)->sd) +static int adv7180_select_page(struct adv7180_state *state, unsigned int page) +{ + if (state->register_page != page) { + i2c_smbus_write_byte_data(state->client, ADV7180_REG_CTRL, + page); + state->register_page = page; + } + + return 0; +} + +static int adv7180_write(struct adv7180_state *state, unsigned int reg, + unsigned int value) +{ + lockdep_assert_held(&state->mutex); + adv7180_select_page(state, reg >> 8); + return i2c_smbus_write_byte_data(state->client, reg & 0xff, value); +} + +static int adv7180_read(struct adv7180_state *state, unsigned int reg) +{ + lockdep_assert_held(&state->mutex); + adv7180_select_page(state, reg >> 8); + return i2c_smbus_read_byte_data(state->client, reg & 0xff); +} + + static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { /* in case V4L2_IN_ST_NO_SIGNAL */ @@ -193,10 +223,10 @@ static u32 adv7180_status_to_v4l2(u8 status1) return 0; } -static int __adv7180_status(struct i2c_client *client, u32 *status, +static int __adv7180_status(struct adv7180_state *state, u32 *status, v4l2_std_id *std) { - int status1 = i2c_smbus_read_byte_data(client, ADV7180_REG_STATUS1); + int status1 = adv7180_read(state, ADV7180_REG_STATUS1); if (status1 < 0) return status1; @@ -225,7 +255,7 @@ static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) if (!state->autodetect || state->irq > 0) *std = state->curr_norm; else - err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); + err = __adv7180_status(state, NULL, std); mutex_unlock(&state->mutex); return err; @@ -236,7 +266,6 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, { struct adv7180_state *state = to_state(sd); int ret = mutex_lock_interruptible(&state->mutex); - struct i2c_client *client = v4l2_get_subdevdata(sd); if (ret) return ret; @@ -247,13 +276,12 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) goto out; - ret = i2c_smbus_read_byte_data(client, ADV7180_REG_INPUT_CONTROL); + ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL); if (ret < 0) goto out; ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; - ret = i2c_smbus_write_byte_data(client, - ADV7180_REG_INPUT_CONTROL, ret | input); + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret | input); state->input = input; out: mutex_unlock(&state->mutex); @@ -267,7 +295,7 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) if (ret) return ret; - ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); + ret = __adv7180_status(state, status, NULL); mutex_unlock(&state->mutex); return ret; } @@ -275,30 +303,27 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7180_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = mutex_lock_interruptible(&state->mutex); if (ret) return ret; /* all standards -> autodetect */ if (std == V4L2_STD_ALL) { - ret = - i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, - ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM - | state->input); + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, + ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM + | state->input); if (ret < 0) goto out; - __adv7180_status(client, NULL, &state->curr_norm); + __adv7180_status(state, NULL, &state->curr_norm); state->autodetect = true; } else { ret = v4l2_std_to_adv7180(std); if (ret < 0) goto out; - ret = i2c_smbus_write_byte_data(client, - ADV7180_REG_INPUT_CONTROL, - ret | state->input); + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, + ret | state->input); if (ret < 0) goto out; @@ -311,8 +336,7 @@ out: return ret; } -static int adv7180_set_power(struct adv7180_state *state, - struct i2c_client *client, bool on) +static int adv7180_set_power(struct adv7180_state *state, bool on) { u8 val; @@ -321,20 +345,19 @@ static int adv7180_set_power(struct adv7180_state *state, else val = ADV7180_PWR_MAN_OFF; - return i2c_smbus_write_byte_data(client, ADV7180_REG_PWR_MAN, val); + return adv7180_write(state, ADV7180_REG_PWR_MAN, val); } static int adv7180_s_power(struct v4l2_subdev *sd, int on) { struct adv7180_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; ret = mutex_lock_interruptible(&state->mutex); if (ret) return ret; - ret = adv7180_set_power(state, client, on); + ret = adv7180_set_power(state, on); if (ret == 0) state->powered = on; @@ -346,7 +369,6 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_adv7180_sd(ctrl); struct adv7180_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = mutex_lock_interruptible(&state->mutex); int val; @@ -355,26 +377,24 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_BRI, val); + ret = adv7180_write(state, ADV7180_REG_BRI, val); break; case V4L2_CID_HUE: /*Hue is inverted according to HSL chart */ - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_HUE, -val); + ret = adv7180_write(state, ADV7180_REG_HUE, -val); break; case V4L2_CID_CONTRAST: - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CON, val); + ret = adv7180_write(state, ADV7180_REG_CON, val); break; case V4L2_CID_SATURATION: /* *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE *Let's not confuse the user, everybody understands saturation */ - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_SD_SAT_CB, - val); + ret = adv7180_write(state, ADV7180_REG_SD_SAT_CB, val); if (ret < 0) break; - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_SD_SAT_CR, - val); + ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val); break; default: ret = -EINVAL; @@ -483,114 +503,96 @@ static const struct v4l2_subdev_ops adv7180_ops = { static irqreturn_t adv7180_irq(int irq, void *devid) { struct adv7180_state *state = devid; - struct i2c_client *client = v4l2_get_subdevdata(&state->sd); u8 isr3; mutex_lock(&state->mutex); - i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, - ADV7180_CTRL_IRQ_SPACE); - isr3 = i2c_smbus_read_byte_data(client, ADV7180_REG_ISR3); + isr3 = adv7180_read(state, ADV7180_REG_ISR3); /* clear */ - i2c_smbus_write_byte_data(client, ADV7180_REG_ICR3, isr3); - i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, 0); + adv7180_write(state, ADV7180_REG_ICR3, isr3); if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) - __adv7180_status(client, NULL, &state->curr_norm); + __adv7180_status(state, NULL, &state->curr_norm); mutex_unlock(&state->mutex); return IRQ_HANDLED; } -static int init_device(struct i2c_client *client, struct adv7180_state *state) +static int init_device(struct adv7180_state *state) { int ret; + mutex_lock(&state->mutex); + /* Initialize adv7180 */ /* Enable autodetection */ if (state->autodetect) { - ret = - i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->input); if (ret < 0) - return ret; + goto out_unlock; - ret = - i2c_smbus_write_byte_data(client, - ADV7180_REG_AUTODETECT_ENABLE, + ret = adv7180_write(state, ADV7180_REG_AUTODETECT_ENABLE, ADV7180_AUTODETECT_DEFAULT); if (ret < 0) - return ret; + goto out_unlock; } else { ret = v4l2_std_to_adv7180(state->curr_norm); if (ret < 0) - return ret; + goto out_unlock; - ret = - i2c_smbus_write_byte_data(client, ADV7180_REG_INPUT_CONTROL, + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret | state->input); if (ret < 0) - return ret; + goto out_unlock; } /* ITU-R BT.656-4 compatible */ - ret = i2c_smbus_write_byte_data(client, - ADV7180_REG_EXTENDED_OUTPUT_CONTROL, + ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); if (ret < 0) - return ret; + goto out_unlock; /* Manually set V bit end position in NTSC mode */ - ret = i2c_smbus_write_byte_data(client, - ADV7180_REG_NTSC_V_BIT_END, + ret = adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END, ADV7180_NTSC_V_BIT_END_MANUAL_NVEND); if (ret < 0) - return ret; + goto out_unlock; /* read current norm */ - __adv7180_status(client, NULL, &state->curr_norm); + __adv7180_status(state, NULL, &state->curr_norm); /* register for interrupts */ if (state->irq > 0) { - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, - ADV7180_CTRL_IRQ_SPACE); - if (ret < 0) - goto err; - /* config the Interrupt pin to be active low */ - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_ICONF1, + ret = adv7180_write(state, ADV7180_REG_ICONF1, ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY); if (ret < 0) - goto err; + goto out_unlock; - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR1, 0); + ret = adv7180_write(state, ADV7180_REG_IMR1, 0); if (ret < 0) - goto err; + goto out_unlock; - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR2, 0); + ret = adv7180_write(state, ADV7180_REG_IMR2, 0); if (ret < 0) - goto err; + goto out_unlock; /* enable AD change interrupts interrupts */ - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR3, + ret = adv7180_write(state, ADV7180_REG_IMR3, ADV7180_IRQ3_AD_CHANGE); if (ret < 0) - goto err; - - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_IMR4, 0); - if (ret < 0) - goto err; + goto out_unlock; - ret = i2c_smbus_write_byte_data(client, ADV7180_REG_CTRL, - 0); + ret = adv7180_write(state, ADV7180_REG_IMR4, 0); if (ret < 0) - goto err; + goto out_unlock; } - return 0; +out_unlock: + mutex_unlock(&state->mutex); -err: return ret; } @@ -612,6 +614,8 @@ static int adv7180_probe(struct i2c_client *client, if (state == NULL) return -ENOMEM; + state->client = client; + state->irq = client->irq; mutex_init(&state->mutex); state->autodetect = true; @@ -623,7 +627,7 @@ static int adv7180_probe(struct i2c_client *client, ret = adv7180_init_controls(state); if (ret) goto err_unreg_subdev; - ret = init_device(client, state); + ret = init_device(state); if (ret) goto err_free_ctrl; @@ -678,7 +682,7 @@ static int adv7180_suspend(struct device *dev) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct adv7180_state *state = to_state(sd); - return adv7180_set_power(state, client, false); + return adv7180_set_power(state, false); } static int adv7180_resume(struct device *dev) @@ -689,11 +693,11 @@ static int adv7180_resume(struct device *dev) int ret; if (state->powered) { - ret = adv7180_set_power(state, client, true); + ret = adv7180_set_power(state, true); if (ret) return ret; } - ret = init_device(client, state); + ret = init_device(state); if (ret < 0) return ret; return 0; -- cgit v1.2.3 From c18818e99067ea084e07cbb9a590389180252b7e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:25 -0300 Subject: [media] adv7180: Reset the device before initialization Reset the device when initializing it so it is in a good known state and the assumed register settings matches the actual register settings. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 432a756f8e1d..44a2832d8d11 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -30,6 +30,7 @@ #include #include #include +#include #define ADV7180_REG_INPUT_CONTROL 0x0000 #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 @@ -523,6 +524,9 @@ static int init_device(struct adv7180_state *state) mutex_lock(&state->mutex); + adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); + usleep_range(2000, 10000); + /* Initialize adv7180 */ /* Enable autodetection */ if (state->autodetect) { @@ -692,14 +696,14 @@ static int adv7180_resume(struct device *dev) struct adv7180_state *state = to_state(sd); int ret; - if (state->powered) { - ret = adv7180_set_power(state, true); - if (ret) - return ret; - } ret = init_device(state); if (ret < 0) return ret; + + ret = adv7180_set_power(state, state->powered); + if (ret) + return ret; + return 0; } -- cgit v1.2.3 From d5d51a827bb86103d4874a864f72674b281408ac Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:26 -0300 Subject: [media] adv7180: Add media controller support Add media controller support to the adv7180 driver by registering a media entity instance for it as well as implementing pad ops for configuring the format. As there currently don't seem to be any users of the video ops format operations those are removed as well in this patch. Also set the V4L2_SUBDEV_FL_HAS_DEVNODE flag for the subdevice so it is possible to create a subdevice device node. Since the driver now depends on VIDEO_V4L2_SUBDEV_API all drivers which select the driver need to depend on that symbol as well. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 2 +- drivers/media/i2c/adv7180.c | 50 +++++++++++++++++++++++++++++++-------- drivers/media/pci/sta2x11/Kconfig | 1 + drivers/media/platform/Kconfig | 2 +- 4 files changed, 43 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 0828b6b28fa4..da58c9bb67c2 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -177,7 +177,7 @@ comment "Video decoders" config VIDEO_ADV7180 tristate "Analog Devices ADV7180 decoder" - depends on VIDEO_V4L2 && I2C + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API ---help--- Support for the Analog Devices ADV7180 video decoder. diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 44a2832d8d11..5193596b68ff 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -124,6 +124,7 @@ struct adv7180_state { struct v4l2_ctrl_handler ctrl_hdl; struct v4l2_subdev sd; + struct media_pad pad; struct mutex mutex; /* mutual excl. when accessing chip */ int irq; v4l2_std_id curr_norm; @@ -441,13 +442,14 @@ static void adv7180_exit_controls(struct adv7180_state *state) v4l2_ctrl_handler_free(&state->ctrl_hdl); } -static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, - u32 *code) +static int adv7180_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) { - if (index > 0) + if (code->index != 0) return -EINVAL; - *code = MEDIA_BUS_FMT_YUYV8_2X8; + code->code = MEDIA_BUS_FMT_YUYV8_2X8; return 0; } @@ -466,6 +468,20 @@ static int adv7180_mbus_fmt(struct v4l2_subdev *sd, return 0; } +static int adv7180_get_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format) +{ + return adv7180_mbus_fmt(sd, &format->format); +} + +static int adv7180_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format) +{ + return adv7180_mbus_fmt(sd, &format->format); +} + static int adv7180_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { @@ -485,10 +501,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, - .enum_mbus_fmt = adv7180_enum_mbus_fmt, - .try_mbus_fmt = adv7180_mbus_fmt, - .g_mbus_fmt = adv7180_mbus_fmt, - .s_mbus_fmt = adv7180_mbus_fmt, .g_mbus_config = adv7180_g_mbus_config, }; @@ -496,9 +508,16 @@ static const struct v4l2_subdev_core_ops adv7180_core_ops = { .s_power = adv7180_s_power, }; +static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { + .enum_mbus_code = adv7180_enum_mbus_code, + .set_fmt = adv7180_set_pad_format, + .get_fmt = adv7180_get_pad_format, +}; + static const struct v4l2_subdev_ops adv7180_ops = { .core = &adv7180_core_ops, .video = &adv7180_video_ops, + .pad = &adv7180_pad_ops, }; static irqreturn_t adv7180_irq(int irq, void *devid) @@ -627,20 +646,28 @@ static int adv7180_probe(struct i2c_client *client, state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); + sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ret = adv7180_init_controls(state); if (ret) goto err_unreg_subdev; - ret = init_device(state); + + state->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; + ret = media_entity_init(&sd->entity, 1, &state->pad, 0); if (ret) goto err_free_ctrl; + ret = init_device(state); + if (ret) + goto err_media_entity_cleanup; + if (state->irq) { ret = request_threaded_irq(client->irq, NULL, adv7180_irq, IRQF_ONESHOT | IRQF_TRIGGER_FALLING, KBUILD_MODNAME, state); if (ret) - goto err_free_ctrl; + goto err_media_entity_cleanup; } ret = v4l2_async_register_subdev(sd); @@ -652,6 +679,8 @@ static int adv7180_probe(struct i2c_client *client, err_free_irq: if (state->irq > 0) free_irq(client->irq, state); +err_media_entity_cleanup: + media_entity_cleanup(&sd->entity); err_free_ctrl: adv7180_exit_controls(state); err_unreg_subdev: @@ -669,6 +698,7 @@ static int adv7180_remove(struct i2c_client *client) if (state->irq > 0) free_irq(client->irq, state); + media_entity_cleanup(&sd->entity); adv7180_exit_controls(state); mutex_destroy(&state->mutex); return 0; diff --git a/drivers/media/pci/sta2x11/Kconfig b/drivers/media/pci/sta2x11/Kconfig index f6f30abc088b..e03587b1af71 100644 --- a/drivers/media/pci/sta2x11/Kconfig +++ b/drivers/media/pci/sta2x11/Kconfig @@ -5,6 +5,7 @@ config STA2X11_VIP select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT select VIDEOBUF2_DMA_CONTIG depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS + depends on VIDEO_V4L2_SUBDEV_API depends on I2C help Say Y for support for STA2X11 VIP (Video Input Port) capture diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 663f7580a5da..d9b872b9285a 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -56,7 +56,7 @@ config VIDEO_VIU config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST select VIDEO_ADV7180 select VIDEOBUF_DMA_CONTIG -- cgit v1.2.3 From 3e35e33c086ca81e0576ad1ace22ca058d071b2c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:27 -0300 Subject: [media] adv7180: Consolidate video mode setting We have basically the same code to set the video standard in init_device() and adv7180_s_std(). Factor this out into a common helper function. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 67 ++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 5193596b68ff..363d8d98914c 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -302,37 +302,54 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) return ret; } -static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +static int adv7180_program_std(struct adv7180_state *state) { - struct adv7180_state *state = to_state(sd); - int ret = mutex_lock_interruptible(&state->mutex); - if (ret) - return ret; + int ret; - /* all standards -> autodetect */ - if (std == V4L2_STD_ALL) { + if (state->autodetect) { ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->input); if (ret < 0) - goto out; + return ret; __adv7180_status(state, NULL, &state->curr_norm); - state->autodetect = true; } else { - ret = v4l2_std_to_adv7180(std); + ret = v4l2_std_to_adv7180(state->curr_norm); if (ret < 0) - goto out; + return ret; ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret | state->input); + if (ret < 0) + return ret; + } + + return 0; +} + +static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7180_state *state = to_state(sd); + int ret = mutex_lock_interruptible(&state->mutex); + + if (ret) + return ret; + + /* all standards -> autodetect */ + if (std == V4L2_STD_ALL) { + state->autodetect = true; + } else { + /* Make sure we can support this std */ + ret = v4l2_std_to_adv7180(std); if (ret < 0) goto out; state->curr_norm = std; state->autodetect = false; } - ret = 0; + + ret = adv7180_program_std(state); out: mutex_unlock(&state->mutex); return ret; @@ -546,30 +563,10 @@ static int init_device(struct adv7180_state *state) adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); usleep_range(2000, 10000); - /* Initialize adv7180 */ - /* Enable autodetection */ - if (state->autodetect) { - ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, - ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM - | state->input); - if (ret < 0) - goto out_unlock; - - ret = adv7180_write(state, ADV7180_REG_AUTODETECT_ENABLE, - ADV7180_AUTODETECT_DEFAULT); - if (ret < 0) - goto out_unlock; - } else { - ret = v4l2_std_to_adv7180(state->curr_norm); - if (ret < 0) - goto out_unlock; - - ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, - ret | state->input); - if (ret < 0) - goto out_unlock; + ret = adv7180_program_std(state); + if (ret) + goto out_unlock; - } /* ITU-R BT.656-4 compatible */ ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); -- cgit v1.2.3 From f5dde49b8f362bdc53dbdbd3a579fac5e66d878d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:28 -0300 Subject: [media] adv7180: Prepare for multi-chip support The adv7180 is part of a larger family of device, which have all a very similar register map layout. This patch prepares the adv7180 driver for support for multiple different devices. For now the only difference we care about is the number of input channel configurations. Also the way the input format is configured slightly differs between some devices. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 187 ++++++++++++++++++++++++++++++-------------- 1 file changed, 130 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 363d8d98914c..170c2fcceb00 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -32,23 +32,24 @@ #include #include +#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM 0x0 +#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM_PED 0x1 +#define ADV7180_STD_AD_PAL_N_NTSC_J_SECAM 0x2 +#define ADV7180_STD_AD_PAL_N_NTSC_M_SECAM 0x3 +#define ADV7180_STD_NTSC_J 0x4 +#define ADV7180_STD_NTSC_M 0x5 +#define ADV7180_STD_PAL60 0x6 +#define ADV7180_STD_NTSC_443 0x7 +#define ADV7180_STD_PAL_BG 0x8 +#define ADV7180_STD_PAL_N 0x9 +#define ADV7180_STD_PAL_M 0xa +#define ADV7180_STD_PAL_M_PED 0xb +#define ADV7180_STD_PAL_COMB_N 0xc +#define ADV7180_STD_PAL_COMB_N_PED 0xd +#define ADV7180_STD_PAL_SECAM 0xe +#define ADV7180_STD_PAL_SECAM_PED 0xf + #define ADV7180_REG_INPUT_CONTROL 0x0000 -#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 -#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 -#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 -#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM 0x30 -#define ADV7180_INPUT_CONTROL_NTSC_J 0x40 -#define ADV7180_INPUT_CONTROL_NTSC_M 0x50 -#define ADV7180_INPUT_CONTROL_PAL60 0x60 -#define ADV7180_INPUT_CONTROL_NTSC_443 0x70 -#define ADV7180_INPUT_CONTROL_PAL_BG 0x80 -#define ADV7180_INPUT_CONTROL_PAL_N 0x90 -#define ADV7180_INPUT_CONTROL_PAL_M 0xa0 -#define ADV7180_INPUT_CONTROL_PAL_M_PED 0xb0 -#define ADV7180_INPUT_CONTROL_PAL_COMB_N 0xc0 -#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0 -#define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0 -#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 #define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f #define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004 @@ -121,6 +122,30 @@ #define ADV7180_REG_NTSC_V_BIT_END 0x00E6 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F +#define ADV7180_INPUT_CVBS_AIN1 0x00 +#define ADV7180_INPUT_CVBS_AIN2 0x01 +#define ADV7180_INPUT_CVBS_AIN3 0x02 +#define ADV7180_INPUT_CVBS_AIN4 0x03 +#define ADV7180_INPUT_CVBS_AIN5 0x04 +#define ADV7180_INPUT_CVBS_AIN6 0x05 +#define ADV7180_INPUT_SVIDEO_AIN1_AIN2 0x06 +#define ADV7180_INPUT_SVIDEO_AIN3_AIN4 0x07 +#define ADV7180_INPUT_SVIDEO_AIN5_AIN6 0x08 +#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09 +#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a + +struct adv7180_state; + +#define ADV7180_FLAG_RESET_POWERED BIT(0) + +struct adv7180_chip_info { + unsigned int flags; + unsigned int valid_input_mask; + int (*set_std)(struct adv7180_state *st, unsigned int std); + int (*select_input)(struct adv7180_state *st, unsigned int input); + int (*init)(struct adv7180_state *state); +}; + struct adv7180_state { struct v4l2_ctrl_handler ctrl_hdl; struct v4l2_subdev sd; @@ -134,6 +159,7 @@ struct adv7180_state { struct i2c_client *client; unsigned int register_page; + const struct adv7180_chip_info *chip_info; }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ struct adv7180_state, \ @@ -165,6 +191,11 @@ static int adv7180_read(struct adv7180_state *state, unsigned int reg) return i2c_smbus_read_byte_data(state->client, reg & 0xff); } +static int adv7180_set_video_standard(struct adv7180_state *state, + unsigned int std) +{ + return state->chip_info->set_std(state, std); +} static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { @@ -197,22 +228,22 @@ static v4l2_std_id adv7180_std_to_v4l2(u8 status1) static int v4l2_std_to_adv7180(v4l2_std_id std) { if (std == V4L2_STD_PAL_60) - return ADV7180_INPUT_CONTROL_PAL60; + return ADV7180_STD_PAL60; if (std == V4L2_STD_NTSC_443) - return ADV7180_INPUT_CONTROL_NTSC_443; + return ADV7180_STD_NTSC_443; if (std == V4L2_STD_PAL_N) - return ADV7180_INPUT_CONTROL_PAL_N; + return ADV7180_STD_PAL_N; if (std == V4L2_STD_PAL_M) - return ADV7180_INPUT_CONTROL_PAL_M; + return ADV7180_STD_PAL_M; if (std == V4L2_STD_PAL_Nc) - return ADV7180_INPUT_CONTROL_PAL_COMB_N; + return ADV7180_STD_PAL_COMB_N; if (std & V4L2_STD_PAL) - return ADV7180_INPUT_CONTROL_PAL_BG; + return ADV7180_STD_PAL_BG; if (std & V4L2_STD_NTSC) - return ADV7180_INPUT_CONTROL_NTSC_M; + return ADV7180_STD_NTSC_M; if (std & V4L2_STD_SECAM) - return ADV7180_INPUT_CONTROL_PAL_SECAM; + return ADV7180_STD_PAL_SECAM; return -EINVAL; } @@ -272,19 +303,15 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, if (ret) return ret; - /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept - * all inputs and let the card driver take care of validation - */ - if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) + if (input > 31 || !(BIT(input) & state->chip_info->valid_input_mask)) { + ret = -EINVAL; goto out; + } - ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL); - if (ret < 0) - goto out; + ret = state->chip_info->select_input(state, input); - ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; - ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret | input); - state->input = input; + if (ret == 0) + state->input = input; out: mutex_unlock(&state->mutex); return ret; @@ -307,9 +334,8 @@ static int adv7180_program_std(struct adv7180_state *state) int ret; if (state->autodetect) { - ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, - ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM - | state->input); + ret = adv7180_set_video_standard(state, + ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); if (ret < 0) return ret; @@ -319,8 +345,7 @@ static int adv7180_program_std(struct adv7180_state *state) if (ret < 0) return ret; - ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, - ret | state->input); + ret = adv7180_set_video_standard(state, ret); if (ret < 0) return ret; } @@ -521,6 +546,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { .g_mbus_config = adv7180_g_mbus_config, }; + static const struct v4l2_subdev_core_ops adv7180_core_ops = { .s_power = adv7180_s_power, }; @@ -554,33 +580,77 @@ static irqreturn_t adv7180_irq(int irq, void *devid) return IRQ_HANDLED; } -static int init_device(struct adv7180_state *state) +static int adv7180_init(struct adv7180_state *state) { int ret; - mutex_lock(&state->mutex); - - adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); - usleep_range(2000, 10000); - - ret = adv7180_program_std(state); - if (ret) - goto out_unlock; - /* ITU-R BT.656-4 compatible */ ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); if (ret < 0) - goto out_unlock; + return ret; /* Manually set V bit end position in NTSC mode */ - ret = adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END, + return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END, ADV7180_NTSC_V_BIT_END_MANUAL_NVEND); +} + +static int adv7180_set_std(struct adv7180_state *state, unsigned int std) +{ + return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, + (std << 4) | state->input); +} + +static int adv7180_select_input(struct adv7180_state *state, unsigned int input) +{ + int ret; + + ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL); if (ret < 0) + return ret; + + ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; + ret |= input; + return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret); +} + +static const struct adv7180_chip_info adv7180_info = { + .flags = ADV7180_FLAG_RESET_POWERED, + /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept + * all inputs and let the card driver take care of validation + */ + .valid_input_mask = BIT(ADV7180_INPUT_CVBS_AIN1) | + BIT(ADV7180_INPUT_CVBS_AIN2) | + BIT(ADV7180_INPUT_CVBS_AIN3) | + BIT(ADV7180_INPUT_CVBS_AIN4) | + BIT(ADV7180_INPUT_CVBS_AIN5) | + BIT(ADV7180_INPUT_CVBS_AIN6) | + BIT(ADV7180_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7180_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7180_INPUT_SVIDEO_AIN5_AIN6) | + BIT(ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3) | + BIT(ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6), + .init = adv7180_init, + .set_std = adv7180_set_std, + .select_input = adv7180_select_input, +}; + +static int init_device(struct adv7180_state *state) +{ + int ret; + + mutex_lock(&state->mutex); + + adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); + usleep_range(2000, 10000); + + ret = state->chip_info->init(state); + if (ret) goto out_unlock; - /* read current norm */ - __adv7180_status(state, NULL, &state->curr_norm); + ret = adv7180_program_std(state); + if (ret) + goto out_unlock; /* register for interrupts */ if (state->irq > 0) { @@ -635,11 +705,15 @@ static int adv7180_probe(struct i2c_client *client, return -ENOMEM; state->client = client; + state->chip_info = (struct adv7180_chip_info *)id->driver_data; state->irq = client->irq; mutex_init(&state->mutex); state->autodetect = true; - state->powered = true; + if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) + state->powered = true; + else + state->powered = false; state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); @@ -702,9 +776,10 @@ static int adv7180_remove(struct i2c_client *client) } static const struct i2c_device_id adv7180_id[] = { - {KBUILD_MODNAME, 0}, + { "adv7180", (kernel_ulong_t)&adv7180_info }, {}, }; +MODULE_DEVICE_TABLE(i2c, adv7180_id); #ifdef CONFIG_PM_SLEEP static int adv7180_suspend(struct device *dev) @@ -741,8 +816,6 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); #define ADV7180_PM_OPS NULL #endif -MODULE_DEVICE_TABLE(i2c, adv7180_id); - static struct i2c_driver adv7180_driver = { .driver = { .owner = THIS_MODULE, -- cgit v1.2.3 From c5ef8f8c5d502a7a918737a05170399ed028f17a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:29 -0300 Subject: [media] adv7180: Add support for the adv7182 This patch adds support for the adv7182 to the adv7180 driver. The adv7182 is similar to the adv7180, the main difference from the driver's point of view is how the video input and how the input format are selected. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 149 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 170c2fcceb00..84d3b782a2a7 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -52,6 +52,8 @@ #define ADV7180_REG_INPUT_CONTROL 0x0000 #define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f +#define ADV7182_REG_INPUT_VIDSEL 0x0002 + #define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004 #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 @@ -134,6 +136,25 @@ #define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09 #define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a +#define ADV7182_INPUT_CVBS_AIN1 0x00 +#define ADV7182_INPUT_CVBS_AIN2 0x01 +#define ADV7182_INPUT_CVBS_AIN3 0x02 +#define ADV7182_INPUT_CVBS_AIN4 0x03 +#define ADV7182_INPUT_CVBS_AIN5 0x04 +#define ADV7182_INPUT_CVBS_AIN6 0x05 +#define ADV7182_INPUT_CVBS_AIN7 0x06 +#define ADV7182_INPUT_CVBS_AIN8 0x07 +#define ADV7182_INPUT_SVIDEO_AIN1_AIN2 0x08 +#define ADV7182_INPUT_SVIDEO_AIN3_AIN4 0x09 +#define ADV7182_INPUT_SVIDEO_AIN5_AIN6 0x0a +#define ADV7182_INPUT_SVIDEO_AIN7_AIN8 0x0b +#define ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3 0x0c +#define ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0d +#define ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2 0x0e +#define ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4 0x0f +#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10 +#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11 + struct adv7180_state; #define ADV7180_FLAG_RESET_POWERED BIT(0) @@ -614,6 +635,118 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input) return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret); } +static int adv7182_init(struct adv7180_state *state) +{ + /* ADI required writes */ + adv7180_write(state, 0x0003, 0x0c); + adv7180_write(state, 0x0004, 0x07); + adv7180_write(state, 0x0013, 0x00); + adv7180_write(state, 0x001d, 0x40); + + return 0; +} + +static int adv7182_set_std(struct adv7180_state *state, unsigned int std) +{ + return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4); +} + +enum adv7182_input_type { + ADV7182_INPUT_TYPE_CVBS, + ADV7182_INPUT_TYPE_DIFF_CVBS, + ADV7182_INPUT_TYPE_SVIDEO, + ADV7182_INPUT_TYPE_YPBPR, +}; + +static enum adv7182_input_type adv7182_get_input_type(unsigned int input) +{ + switch (input) { + case ADV7182_INPUT_CVBS_AIN1: + case ADV7182_INPUT_CVBS_AIN2: + case ADV7182_INPUT_CVBS_AIN3: + case ADV7182_INPUT_CVBS_AIN4: + case ADV7182_INPUT_CVBS_AIN5: + case ADV7182_INPUT_CVBS_AIN6: + case ADV7182_INPUT_CVBS_AIN7: + case ADV7182_INPUT_CVBS_AIN8: + return ADV7182_INPUT_TYPE_CVBS; + case ADV7182_INPUT_SVIDEO_AIN1_AIN2: + case ADV7182_INPUT_SVIDEO_AIN3_AIN4: + case ADV7182_INPUT_SVIDEO_AIN5_AIN6: + case ADV7182_INPUT_SVIDEO_AIN7_AIN8: + return ADV7182_INPUT_TYPE_SVIDEO; + case ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3: + case ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6: + return ADV7182_INPUT_TYPE_YPBPR; + case ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2: + case ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4: + case ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6: + case ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8: + return ADV7182_INPUT_TYPE_DIFF_CVBS; + default: /* Will never happen */ + return 0; + } +} + +/* ADI recommended writes to registers 0x52, 0x53, 0x54 */ +static unsigned int adv7182_lbias_settings[][3] = { + [ADV7182_INPUT_TYPE_CVBS] = { 0xCB, 0x4E, 0x80 }, + [ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 }, + [ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 }, + [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 }, +}; + +static int adv7182_select_input(struct adv7180_state *state, unsigned int input) +{ + enum adv7182_input_type input_type; + unsigned int *lbias; + unsigned int i; + int ret; + + ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input); + if (ret) + return ret; + + /* Reset clamp circuitry - ADI recommended writes */ + adv7180_write(state, 0x809c, 0x00); + adv7180_write(state, 0x809c, 0xff); + + input_type = adv7182_get_input_type(input); + + switch (input_type) { + case ADV7182_INPUT_TYPE_CVBS: + case ADV7182_INPUT_TYPE_DIFF_CVBS: + /* ADI recommends to use the SH1 filter */ + adv7180_write(state, 0x0017, 0x41); + break; + default: + adv7180_write(state, 0x0017, 0x01); + break; + } + + lbias = adv7182_lbias_settings[input_type]; + + for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++) + adv7180_write(state, 0x0052 + i, lbias[i]); + + if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) { + /* ADI required writes to make differential CVBS work */ + adv7180_write(state, 0x005f, 0xa8); + adv7180_write(state, 0x005a, 0x90); + adv7180_write(state, 0x0060, 0xb0); + adv7180_write(state, 0x80b6, 0x08); + adv7180_write(state, 0x80c0, 0xa0); + } else { + adv7180_write(state, 0x005f, 0xf0); + adv7180_write(state, 0x005a, 0xd0); + adv7180_write(state, 0x0060, 0x10); + adv7180_write(state, 0x80b6, 0x9c); + adv7180_write(state, 0x80c0, 0x00); + } + + return 0; +} + static const struct adv7180_chip_info adv7180_info = { .flags = ADV7180_FLAG_RESET_POWERED, /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept @@ -635,6 +768,21 @@ static const struct adv7180_chip_info adv7180_info = { .select_input = adv7180_select_input, }; +static const struct adv7180_chip_info adv7182_info = { + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + static int init_device(struct adv7180_state *state) { int ret; @@ -777,6 +925,7 @@ static int adv7180_remove(struct i2c_client *client) static const struct i2c_device_id adv7180_id[] = { { "adv7180", (kernel_ulong_t)&adv7180_info }, + { "adv7182", (kernel_ulong_t)&adv7182_info }, {}, }; MODULE_DEVICE_TABLE(i2c, adv7180_id); -- cgit v1.2.3 From bf7dcb8067ed5c3b40768b071d93bd7676e36620 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:30 -0300 Subject: [media] adv7180: Add support for the adv7280/adv7281/adv7282 This patch adds support for the adv7280/adv7281/adv7282 devices to the adv7180 driver. They are very similar to the adv7182, the main difference from the drivers point of view are some different tuning constants for improved video performance. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 56 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 84d3b782a2a7..f55364ff2582 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -158,6 +158,7 @@ struct adv7180_state; #define ADV7180_FLAG_RESET_POWERED BIT(0) +#define ADV7180_FLAG_V2 BIT(1) struct adv7180_chip_info { unsigned int flags; @@ -637,9 +638,18 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input) static int adv7182_init(struct adv7180_state *state) { + if (state->chip_info->flags & ADV7180_FLAG_V2) { + /* ADI recommended writes for improved video quality */ + adv7180_write(state, 0x0080, 0x51); + adv7180_write(state, 0x0081, 0x51); + adv7180_write(state, 0x0082, 0x68); + adv7180_write(state, 0x0004, 0x17); + } else { + adv7180_write(state, 0x0004, 0x07); + } + /* ADI required writes */ adv7180_write(state, 0x0003, 0x0c); - adv7180_write(state, 0x0004, 0x07); adv7180_write(state, 0x0013, 0x00); adv7180_write(state, 0x001d, 0x40); @@ -696,6 +706,13 @@ static unsigned int adv7182_lbias_settings[][3] = { [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 }, }; +static unsigned int adv7280_lbias_settings[][3] = { + [ADV7182_INPUT_TYPE_CVBS] = { 0xCD, 0x4E, 0x80 }, + [ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 }, + [ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 }, + [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 }, +}; + static int adv7182_select_input(struct adv7180_state *state, unsigned int input) { enum adv7182_input_type input_type; @@ -724,7 +741,10 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input) break; } - lbias = adv7182_lbias_settings[input_type]; + if (state->chip_info->flags & ADV7180_FLAG_V2) + lbias = adv7280_lbias_settings[input_type]; + else + lbias = adv7182_lbias_settings[input_type]; for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++) adv7180_write(state, 0x0052 + i, lbias[i]); @@ -783,6 +803,35 @@ static const struct adv7180_chip_info adv7182_info = { .select_input = adv7182_select_input, }; +static const struct adv7180_chip_info adv7280_info = { + .flags = ADV7180_FLAG_V2, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + +static const struct adv7180_chip_info adv7281_info = { + .flags = ADV7180_FLAG_V2, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + static int init_device(struct adv7180_state *state) { int ret; @@ -926,6 +975,9 @@ static int adv7180_remove(struct i2c_client *client) static const struct i2c_device_id adv7180_id[] = { { "adv7180", (kernel_ulong_t)&adv7180_info }, { "adv7182", (kernel_ulong_t)&adv7182_info }, + { "adv7280", (kernel_ulong_t)&adv7280_info }, + { "adv7281", (kernel_ulong_t)&adv7281_info }, + { "adv7282", (kernel_ulong_t)&adv7281_info }, {}, }; MODULE_DEVICE_TABLE(i2c, adv7180_id); -- cgit v1.2.3 From b37135e395c37a8d63defafcb567d55220a672f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:31 -0300 Subject: [media] adv7180: Add support for the adv7280-m/adv7281-m/adv7281-ma/adv7282-m This patch adds support for the adv7280-m/adv2781-m/adv7281-ma/adv7282-m devices to the adv7180 driver. They are very similar to the adv7280/adv7281/adv7282 but instead of parallel video out they feature a MIPI CSI2 transmitter. The CSI2 transmitter is configured via a separate I2C address, so we need to register a dummy device for it. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 170 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 154 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index f55364ff2582..195d28f48c30 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -124,6 +124,11 @@ #define ADV7180_REG_NTSC_V_BIT_END 0x00E6 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F +#define ADV7180_REG_CSI_SLAVE_ADDR 0xFE + +#define ADV7180_CSI_REG_PWRDN 0x00 +#define ADV7180_CSI_PWRDN 0x80 + #define ADV7180_INPUT_CVBS_AIN1 0x00 #define ADV7180_INPUT_CVBS_AIN2 0x01 #define ADV7180_INPUT_CVBS_AIN3 0x02 @@ -155,10 +160,13 @@ #define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10 #define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11 +#define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44 + struct adv7180_state; #define ADV7180_FLAG_RESET_POWERED BIT(0) #define ADV7180_FLAG_V2 BIT(1) +#define ADV7180_FLAG_MIPI_CSI2 BIT(2) struct adv7180_chip_info { unsigned int flags; @@ -181,6 +189,7 @@ struct adv7180_state { struct i2c_client *client; unsigned int register_page; + struct i2c_client *csi_client; const struct adv7180_chip_info *chip_info; }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ @@ -213,6 +222,12 @@ static int adv7180_read(struct adv7180_state *state, unsigned int reg) return i2c_smbus_read_byte_data(state->client, reg & 0xff); } +static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg, + unsigned int value) +{ + return i2c_smbus_write_byte_data(state->csi_client, reg, value); +} + static int adv7180_set_video_standard(struct adv7180_state *state, unsigned int std) { @@ -405,13 +420,31 @@ out: static int adv7180_set_power(struct adv7180_state *state, bool on) { u8 val; + int ret; if (on) val = ADV7180_PWR_MAN_ON; else val = ADV7180_PWR_MAN_OFF; - return adv7180_write(state, ADV7180_REG_PWR_MAN, val); + ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val); + if (ret) + return ret; + + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + if (on) { + adv7180_csi_write(state, 0xDE, 0x02); + adv7180_csi_write(state, 0xD2, 0xF7); + adv7180_csi_write(state, 0xD8, 0x65); + adv7180_csi_write(state, 0xE0, 0x09); + adv7180_csi_write(state, 0x2C, 0x00); + adv7180_csi_write(state, 0x00, 0x00); + } else { + adv7180_csi_write(state, 0x00, 0x80); + } + } + + return 0; } static int adv7180_s_power(struct v4l2_subdev *sd, int on) @@ -549,13 +582,22 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd, static int adv7180_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - /* - * The ADV7180 sensor supports BT.601/656 output modes. - * The BT.656 is default and not yet configurable by s/w. - */ - cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | - V4L2_MBUS_DATA_ACTIVE_HIGH; - cfg->type = V4L2_MBUS_BT656; + struct adv7180_state *state = to_state(sd); + + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + cfg->type = V4L2_MBUS_CSI2; + cfg->flags = V4L2_MBUS_CSI2_1_LANE | + V4L2_MBUS_CSI2_CHANNEL_0 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + } else { + /* + * The ADV7180 sensor supports BT.601/656 output modes. + * The BT.656 is default and not yet configurable by s/w. + */ + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_BT656; + } return 0; } @@ -638,20 +680,32 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input) static int adv7182_init(struct adv7180_state *state) { + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) + adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR, + ADV7180_DEFAULT_CSI_I2C_ADDR << 1); + if (state->chip_info->flags & ADV7180_FLAG_V2) { /* ADI recommended writes for improved video quality */ adv7180_write(state, 0x0080, 0x51); adv7180_write(state, 0x0081, 0x51); adv7180_write(state, 0x0082, 0x68); - adv7180_write(state, 0x0004, 0x17); - } else { - adv7180_write(state, 0x0004, 0x07); } /* ADI required writes */ - adv7180_write(state, 0x0003, 0x0c); + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + adv7180_write(state, 0x0003, 0x4e); + adv7180_write(state, 0x0004, 0x57); + adv7180_write(state, 0x001d, 0xc0); + } else { + if (state->chip_info->flags & ADV7180_FLAG_V2) + adv7180_write(state, 0x0004, 0x17); + else + adv7180_write(state, 0x0004, 0x07); + adv7180_write(state, 0x0003, 0x0c); + adv7180_write(state, 0x001d, 0x40); + } + adv7180_write(state, 0x0013, 0x00); - adv7180_write(state, 0x001d, 0x40); return 0; } @@ -817,15 +871,81 @@ static const struct adv7180_chip_info adv7280_info = { .select_input = adv7182_select_input, }; +static const struct adv7180_chip_info adv7280_m_info = { + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_CVBS_AIN5) | + BIT(ADV7182_INPUT_CVBS_AIN6) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) | + BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + static const struct adv7180_chip_info adv7281_info = { - .flags = ADV7180_FLAG_V2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + +static const struct adv7180_chip_info adv7281_m_info = { + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + +static const struct adv7180_chip_info adv7281_ma_info = { + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_CVBS_AIN5) | + BIT(ADV7182_INPUT_CVBS_AIN6) | BIT(ADV7182_INPUT_CVBS_AIN7) | BIT(ADV7182_INPUT_CVBS_AIN8) | BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) | BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) | + BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6) | BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6) | BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), .init = adv7182_init, .set_std = adv7182_set_std, @@ -904,6 +1024,13 @@ static int adv7180_probe(struct i2c_client *client, state->client = client; state->chip_info = (struct adv7180_chip_info *)id->driver_data; + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + state->csi_client = i2c_new_dummy(client->adapter, + ADV7180_DEFAULT_CSI_I2C_ADDR); + if (!state->csi_client) + return -ENOMEM; + } + state->irq = client->irq; mutex_init(&state->mutex); state->autodetect = true; @@ -918,7 +1045,7 @@ static int adv7180_probe(struct i2c_client *client, ret = adv7180_init_controls(state); if (ret) - goto err_unreg_subdev; + goto err_unregister_csi_client; state->pad.flags = MEDIA_PAD_FL_SOURCE; sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; @@ -951,7 +1078,9 @@ err_media_entity_cleanup: media_entity_cleanup(&sd->entity); err_free_ctrl: adv7180_exit_controls(state); -err_unreg_subdev: +err_unregister_csi_client: + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) + i2c_unregister_device(state->csi_client); mutex_destroy(&state->mutex); return ret; } @@ -968,7 +1097,12 @@ static int adv7180_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); adv7180_exit_controls(state); + + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) + i2c_unregister_device(state->csi_client); + mutex_destroy(&state->mutex); + return 0; } @@ -976,8 +1110,12 @@ static const struct i2c_device_id adv7180_id[] = { { "adv7180", (kernel_ulong_t)&adv7180_info }, { "adv7182", (kernel_ulong_t)&adv7182_info }, { "adv7280", (kernel_ulong_t)&adv7280_info }, + { "adv7280-m", (kernel_ulong_t)&adv7280_m_info }, { "adv7281", (kernel_ulong_t)&adv7281_info }, + { "adv7281-m", (kernel_ulong_t)&adv7281_m_info }, + { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info }, { "adv7282", (kernel_ulong_t)&adv7281_info }, + { "adv7282-m", (kernel_ulong_t)&adv7281_m_info }, {}, }; MODULE_DEVICE_TABLE(i2c, adv7180_id); -- cgit v1.2.3 From 851a54effbd808daf8b961f1dc6156c06a96d5f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:32 -0300 Subject: [media] adv7180: Add I2P support Some of the devices supported by this driver have a interlaced-to- progressive converter which can optionally be enabled. This patch adds support for enabling and disabling the I2P converter on such devices. I2P mode can be enabled by selecting V4L2_FIELD_NONE instead of V4L2_FIELD_INTERLACED for the format. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 156 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 195d28f48c30..3c1c866d1e3c 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -124,6 +124,7 @@ #define ADV7180_REG_NTSC_V_BIT_END 0x00E6 #define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F +#define ADV7180_REG_VPP_SLAVE_ADDR 0xFD #define ADV7180_REG_CSI_SLAVE_ADDR 0xFE #define ADV7180_CSI_REG_PWRDN 0x00 @@ -161,12 +162,14 @@ #define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11 #define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44 +#define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42 struct adv7180_state; #define ADV7180_FLAG_RESET_POWERED BIT(0) #define ADV7180_FLAG_V2 BIT(1) #define ADV7180_FLAG_MIPI_CSI2 BIT(2) +#define ADV7180_FLAG_I2P BIT(3) struct adv7180_chip_info { unsigned int flags; @@ -190,7 +193,9 @@ struct adv7180_state { struct i2c_client *client; unsigned int register_page; struct i2c_client *csi_client; + struct i2c_client *vpp_client; const struct adv7180_chip_info *chip_info; + enum v4l2_field field; }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ struct adv7180_state, \ @@ -234,6 +239,12 @@ static int adv7180_set_video_standard(struct adv7180_state *state, return state->chip_info->set_std(state, std); } +static int adv7180_vpp_write(struct adv7180_state *state, unsigned int reg, + unsigned int value) +{ + return i2c_smbus_write_byte_data(state->vpp_client, reg, value); +} + static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { /* in case V4L2_IN_ST_NO_SIGNAL */ @@ -438,6 +449,8 @@ static int adv7180_set_power(struct adv7180_state *state, bool on) adv7180_csi_write(state, 0xD8, 0x65); adv7180_csi_write(state, 0xE0, 0x09); adv7180_csi_write(state, 0x2C, 0x00); + if (state->field == V4L2_FIELD_NONE) + adv7180_csi_write(state, 0x1D, 0x80); adv7180_csi_write(state, 0x00, 0x00); } else { adv7180_csi_write(state, 0x00, 0x80); @@ -558,25 +571,97 @@ static int adv7180_mbus_fmt(struct v4l2_subdev *sd, fmt->code = MEDIA_BUS_FMT_YUYV8_2X8; fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - fmt->field = V4L2_FIELD_INTERLACED; fmt->width = 720; fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576; return 0; } +static int adv7180_set_field_mode(struct adv7180_state *state) +{ + if (!(state->chip_info->flags & ADV7180_FLAG_I2P)) + return 0; + + if (state->field == V4L2_FIELD_NONE) { + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + adv7180_csi_write(state, 0x01, 0x20); + adv7180_csi_write(state, 0x02, 0x28); + adv7180_csi_write(state, 0x03, 0x38); + adv7180_csi_write(state, 0x04, 0x30); + adv7180_csi_write(state, 0x05, 0x30); + adv7180_csi_write(state, 0x06, 0x80); + adv7180_csi_write(state, 0x07, 0x70); + adv7180_csi_write(state, 0x08, 0x50); + } + adv7180_vpp_write(state, 0xa3, 0x00); + adv7180_vpp_write(state, 0x5b, 0x00); + adv7180_vpp_write(state, 0x55, 0x80); + } else { + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + adv7180_csi_write(state, 0x01, 0x18); + adv7180_csi_write(state, 0x02, 0x18); + adv7180_csi_write(state, 0x03, 0x30); + adv7180_csi_write(state, 0x04, 0x20); + adv7180_csi_write(state, 0x05, 0x28); + adv7180_csi_write(state, 0x06, 0x40); + adv7180_csi_write(state, 0x07, 0x58); + adv7180_csi_write(state, 0x08, 0x30); + } + adv7180_vpp_write(state, 0xa3, 0x70); + adv7180_vpp_write(state, 0x5b, 0x80); + adv7180_vpp_write(state, 0x55, 0x00); + } + + return 0; +} + static int adv7180_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format) { - return adv7180_mbus_fmt(sd, &format->format); + struct adv7180_state *state = to_state(sd); + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + format->format = *v4l2_subdev_get_try_format(fh, 0); + } else { + adv7180_mbus_fmt(sd, &format->format); + format->format.field = state->field; + } + + return 0; } static int adv7180_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format) { - return adv7180_mbus_fmt(sd, &format->format); + struct adv7180_state *state = to_state(sd); + struct v4l2_mbus_framefmt *framefmt; + + switch (format->format.field) { + case V4L2_FIELD_NONE: + if (!(state->chip_info->flags & ADV7180_FLAG_I2P)) + format->format.field = V4L2_FIELD_INTERLACED; + break; + default: + format->format.field = V4L2_FIELD_INTERLACED; + break; + } + + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + framefmt = &format->format; + if (state->field != format->format.field) { + state->field = format->format.field; + adv7180_set_power(state, false); + adv7180_set_field_mode(state); + adv7180_set_power(state, true); + } + } else { + framefmt = v4l2_subdev_get_try_format(fh, 0); + *framefmt = format->format; + } + + return adv7180_mbus_fmt(sd, framefmt); } static int adv7180_g_mbus_config(struct v4l2_subdev *sd, @@ -684,6 +769,10 @@ static int adv7182_init(struct adv7180_state *state) adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR, ADV7180_DEFAULT_CSI_I2C_ADDR << 1); + if (state->chip_info->flags & ADV7180_FLAG_I2P) + adv7180_write(state, ADV7180_REG_VPP_SLAVE_ADDR, + ADV7180_DEFAULT_VPP_I2C_ADDR << 1); + if (state->chip_info->flags & ADV7180_FLAG_V2) { /* ADI recommended writes for improved video quality */ adv7180_write(state, 0x0080, 0x51); @@ -858,7 +947,7 @@ static const struct adv7180_chip_info adv7182_info = { }; static const struct adv7180_chip_info adv7280_info = { - .flags = ADV7180_FLAG_V2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -872,7 +961,7 @@ static const struct adv7180_chip_info adv7280_info = { }; static const struct adv7180_chip_info adv7280_m_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -952,6 +1041,40 @@ static const struct adv7180_chip_info adv7281_ma_info = { .select_input = adv7182_select_input, }; +static const struct adv7180_chip_info adv7282_info = { + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + +static const struct adv7180_chip_info adv7282_m_info = { + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | + BIT(ADV7182_INPUT_CVBS_AIN4) | + BIT(ADV7182_INPUT_CVBS_AIN7) | + BIT(ADV7182_INPUT_CVBS_AIN8) | + BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | + BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | + BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) | + BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), + .init = adv7182_init, + .set_std = adv7182_set_std, + .select_input = adv7182_select_input, +}; + static int init_device(struct adv7180_state *state) { int ret; @@ -969,6 +1092,8 @@ static int init_device(struct adv7180_state *state) if (ret) goto out_unlock; + adv7180_set_field_mode(state); + /* register for interrupts */ if (state->irq > 0) { /* config the Interrupt pin to be active low */ @@ -1022,6 +1147,7 @@ static int adv7180_probe(struct i2c_client *client, return -ENOMEM; state->client = client; + state->field = V4L2_FIELD_INTERLACED; state->chip_info = (struct adv7180_chip_info *)id->driver_data; if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { @@ -1031,6 +1157,15 @@ static int adv7180_probe(struct i2c_client *client, return -ENOMEM; } + if (state->chip_info->flags & ADV7180_FLAG_I2P) { + state->vpp_client = i2c_new_dummy(client->adapter, + ADV7180_DEFAULT_VPP_I2C_ADDR); + if (!state->vpp_client) { + ret = -ENOMEM; + goto err_unregister_csi_client; + } + } + state->irq = client->irq; mutex_init(&state->mutex); state->autodetect = true; @@ -1045,7 +1180,7 @@ static int adv7180_probe(struct i2c_client *client, ret = adv7180_init_controls(state); if (ret) - goto err_unregister_csi_client; + goto err_unregister_vpp_client; state->pad.flags = MEDIA_PAD_FL_SOURCE; sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; @@ -1078,6 +1213,9 @@ err_media_entity_cleanup: media_entity_cleanup(&sd->entity); err_free_ctrl: adv7180_exit_controls(state); +err_unregister_vpp_client: + if (state->chip_info->flags & ADV7180_FLAG_I2P) + i2c_unregister_device(state->vpp_client); err_unregister_csi_client: if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) i2c_unregister_device(state->csi_client); @@ -1098,6 +1236,8 @@ static int adv7180_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); adv7180_exit_controls(state); + if (state->chip_info->flags & ADV7180_FLAG_I2P) + i2c_unregister_device(state->vpp_client); if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) i2c_unregister_device(state->csi_client); @@ -1114,8 +1254,8 @@ static const struct i2c_device_id adv7180_id[] = { { "adv7281", (kernel_ulong_t)&adv7281_info }, { "adv7281-m", (kernel_ulong_t)&adv7281_m_info }, { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info }, - { "adv7282", (kernel_ulong_t)&adv7281_info }, - { "adv7282-m", (kernel_ulong_t)&adv7281_m_info }, + { "adv7282", (kernel_ulong_t)&adv7282_info }, + { "adv7282-m", (kernel_ulong_t)&adv7282_m_info }, {}, }; MODULE_DEVICE_TABLE(i2c, adv7180_id); -- cgit v1.2.3 From 08b717c2ae8b7e23e1d018dad601fdf12bde3a96 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Jan 2015 12:52:33 -0300 Subject: [media] adv7180: Add fast switch support In fast switch mode the adv7180 (and similar) can lock onto a new signal faster when switching between different inputs. As a downside though it is no longer able to auto-detect the incoming format. The fast switch mode is exposed as a boolean v4l control that allows userspace applications to either enable or disable fast switch mode. Signed-off-by: Lars-Peter Clausen Acked-by: Federico Vaga Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 29 +++++++++++++++++++++++++++++ include/uapi/linux/v4l2-controls.h | 4 ++++ 2 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 3c1c866d1e3c..b75878c27c2a 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -127,6 +127,9 @@ #define ADV7180_REG_VPP_SLAVE_ADDR 0xFD #define ADV7180_REG_CSI_SLAVE_ADDR 0xFE +#define ADV7180_REG_FLCONTROL 0x40e0 +#define ADV7180_FLCONTROL_FL_ENABLE 0x1 + #define ADV7180_CSI_REG_PWRDN 0x00 #define ADV7180_CSI_PWRDN 0x80 @@ -164,6 +167,8 @@ #define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44 #define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42 +#define V4L2_CID_ADV_FAST_SWITCH (V4L2_CID_USER_ADV7180_BASE + 0x00) + struct adv7180_state; #define ADV7180_FLAG_RESET_POWERED BIT(0) @@ -508,6 +513,18 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) break; ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val); break; + case V4L2_CID_ADV_FAST_SWITCH: + if (ctrl->val) { + /* ADI required write */ + adv7180_write(state, 0x80d9, 0x44); + adv7180_write(state, ADV7180_REG_FLCONTROL, + ADV7180_FLCONTROL_FL_ENABLE); + } else { + /* ADI required write */ + adv7180_write(state, 0x80d9, 0xc4); + adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00); + } + break; default: ret = -EINVAL; } @@ -520,6 +537,16 @@ static const struct v4l2_ctrl_ops adv7180_ctrl_ops = { .s_ctrl = adv7180_s_ctrl, }; +static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = { + .ops = &adv7180_ctrl_ops, + .id = V4L2_CID_ADV_FAST_SWITCH, + .name = "Fast Switching", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .min = 0, + .max = 1, + .step = 1, +}; + static int adv7180_init_controls(struct adv7180_state *state) { v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); @@ -536,6 +563,8 @@ static int adv7180_init_controls(struct adv7180_state *state) v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, V4L2_CID_HUE, ADV7180_HUE_MIN, ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); + v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL); + state->sd.ctrl_handler = &state->ctrl_hdl; if (state->ctrl_hdl.error) { int err = state->ctrl_hdl.error; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 661f119a51b8..9f6e108ff4a0 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -170,6 +170,10 @@ enum v4l2_colorfx { * We reserve 16 controls for this driver. */ #define V4L2_CID_USER_SAA7134_BASE (V4L2_CID_USER_BASE + 0x1060) +/* The base for the adv7180 driver controls. + * We reserve 16 controls for this driver. */ +#define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070) + /* MPEG-class control IDs */ /* The MPEG controls are applicable to all codec controls * and the 'MPEG' part of the define is historical */ -- cgit v1.2.3 From 7559d13ccf9fc4be9fb6ed21aaa4e105b6789ce8 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sun, 21 Dec 2014 00:24:48 -0300 Subject: [media] media: fix au0828_analog_register() to not free au0828_dev au0828_analog_register() frees au0828_dev when it fails to locate isoc endpoint. au0828_usb_probe() continues with dvb and rc probe and registration assuming dev is still valid. When au0828_analog_register() fails to locate isoc endpoint, it should return without free'ing au0828_dev. Otherwise, the probe will fail as dev is null when au0828_dvb_register() is called. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 60a684600456..98abfd620624 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -2029,7 +2029,6 @@ int au0828_analog_register(struct au0828_dev *dev, } if (!(dev->isoc_in_endpointaddr)) { pr_info("Could not locate isoc endpoint\n"); - kfree(dev); return -ENODEV; } -- cgit v1.2.3 From 9bc1022f51e20af7e2aab58aae108fe976a5d00a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 12 Jan 2015 23:56:55 -0300 Subject: [media] media: fix au0828 compile error from au0828_boards initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit au0828 picked up UNSET from videobuf-core.h and fails to compile if videobuf-core.h isn't included. Change it to use -1U instead to fix the problem. drivers/media/usb/au0828/au0828-cards.c:47:17: error: ‘UNSET’ undeclared here (not in a function) .tuner_type = UNSET, Signed-off-by: Shuah Khan Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index da87f1cc31a9..edc27355f271 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -44,7 +44,7 @@ static void hvr950q_cs5340_audio(void *priv, int enable) struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { .name = "Unknown board", - .tuner_type = UNSET, + .tuner_type = -1U, .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_HAUPPAUGE_HVR850] = { -- cgit v1.2.3 From 05439b1a36935992785c4f28f6693e73820321cb Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 29 Jan 2015 13:41:32 -0300 Subject: [media] media: au0828 - convert to use videobuf2 Convert au0828 to use videobuf2. Tested with NTSC. Tested video and vbi devices with xawtv, tvtime, and vlc. Ran v4l2-compliance to ensure there are no failures. Video compliance test results summary: Total: 75, Succeeded: 75, Failed: 0, Warnings: 18 Vbi compliance test results summary: Total: 75, Succeeded: 75, Failed: 0, Warnings: 0 Signed-off-by: Shuah Khan Reviewed-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/Kconfig | 2 +- drivers/media/usb/au0828/au0828-vbi.c | 122 ++-- drivers/media/usb/au0828/au0828-video.c | 963 ++++++++++++-------------------- drivers/media/usb/au0828/au0828.h | 61 +- 4 files changed, 442 insertions(+), 706 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig index 1d410ac8f9a8..78b797e0b434 100644 --- a/drivers/media/usb/au0828/Kconfig +++ b/drivers/media/usb/au0828/Kconfig @@ -4,7 +4,7 @@ config VIDEO_AU0828 depends on I2C && INPUT && DVB_CORE && USB select I2C_ALGOBIT select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC + select VIDEOBUF2_VMALLOC select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index 932d24f42b24..f67247cf1a5a 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -28,111 +28,67 @@ #include #include -static unsigned int vbibufs = 5; -module_param(vbibufs, int, 0644); -MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); - /* ------------------------------------------------------------------ */ -static void -free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) +static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vbi_buf == buf) - dev->isoc_ctl.vbi_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); + struct au0828_dev *dev = vb2_get_drv_priv(vq); + unsigned long img_size = dev->vbi_width * dev->vbi_height * 2; + unsigned long size; - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; + size = fmt ? (fmt->fmt.vbi.samples_per_line * + (fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size; + if (size < img_size) + return -EINVAL; - *size = dev->vbi_width * dev->vbi_height * 2; + *nplanes = 1; + sizes[0] = size; - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; return 0; } -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) +static int vbi_buffer_prepare(struct vb2_buffer *vb) { - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - int rc = 0; + unsigned long size; - buf->vb.size = dev->vbi_width * dev->vbi_height * 2; + size = dev->vbi_width * dev->vbi_height * 2; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (vb2_plane_size(vb, 0) < size) { + pr_err("%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), size); return -EINVAL; - - buf->vb.width = dev->vbi_width; - buf->vb.height = dev->vbi_height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; } + vb2_set_plane_payload(&buf->vb, 0, size); - buf->vb.state = VIDEOBUF_PREPARED; return 0; - -fail: - free_buffer(q, buf); - return rc; } static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_dmaqueue *vbiq = &dev->vbiq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vbiq->active); -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +vbi_buffer_queue(struct vb2_buffer *vb) { + struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - free_buffer(q, buf); + struct au0828_dmaqueue *vbiq = &dev->vbiq; + unsigned long flags = 0; + + buf->mem = vb2_plane_vaddr(vb, 0); + buf->length = vb2_plane_size(vb, 0); + + spin_lock_irqsave(&dev->slock, flags); + list_add_tail(&buf->list, &vbiq->active); + spin_unlock_irqrestore(&dev->slock, flags); } -struct videobuf_queue_ops au0828_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, +struct vb2_ops au0828_vbi_qops = { + .queue_setup = vbi_queue_setup, + .buf_prepare = vbi_buffer_prepare, + .buf_queue = vbi_buffer_queue, + .start_streaming = au0828_start_analog_streaming, + .stop_streaming = au0828_stop_vbi_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 98abfd620624..a27cb5fcdef8 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -218,9 +218,6 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets, au0828_isocdbg("au0828: called au0828_prepare_isoc\n"); - /* De-allocates all pending stuff */ - au0828_uninit_isoc(dev); - dev->isoc_ctl.isoc_copy = isoc_copy; dev->isoc_ctl.num_bufs = num_bufs; @@ -284,8 +281,6 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets, } } - init_waitqueue_head(&dma_q->wq); - /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); @@ -308,16 +303,12 @@ static inline void buffer_filled(struct au0828_dev *dev, struct au0828_buffer *buf) { /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - v4l2_get_timestamp(&buf->vb.ts); + au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field); - dev->isoc_ctl.buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + buf->vb.v4l2_buf.sequence = dev->frame_count++; + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); } static inline void vbi_buffer_filled(struct au0828_dev *dev, @@ -325,16 +316,12 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev, struct au0828_buffer *buf) { /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - v4l2_get_timestamp(&buf->vb.ts); + au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field); - dev->isoc_ctl.vbi_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + buf->vb.v4l2_buf.sequence = dev->vbi_frame_count++; + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); } /* @@ -353,8 +340,8 @@ static void au0828_copy_video(struct au0828_dev *dev, if (len == 0) return; - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; + if (dma_q->pos + len > buf->length) + len = buf->length - dma_q->pos; startread = p; remain = len; @@ -372,11 +359,11 @@ static void au0828_copy_video(struct au0828_dev *dev, lencopy = bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { + if ((char *)startwrite + lencopy > (char *)outp + buf->length) { au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n", ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - remain = (char *)outp + buf->vb.size - (char *)startwrite; + ((char *)outp + buf->length)); + remain = (char *)outp + buf->length - (char *)startwrite; lencopy = remain; } if (lencopy <= 0) @@ -394,11 +381,11 @@ static void au0828_copy_video(struct au0828_dev *dev, lencopy = bytesperline; if ((char *)startwrite + lencopy > (char *)outp + - buf->vb.size) { + buf->length) { au0828_isocdbg("Overflow %zi bytes past buf end (2)\n", ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - + ((char *)outp + buf->length)); + lencopy = remain = (char *)outp + buf->length - (char *)startwrite; } if (lencopy <= 0) @@ -434,7 +421,11 @@ static inline void get_next_buf(struct au0828_dmaqueue *dma_q, } /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); + *buf = list_entry(dma_q->active.next, struct au0828_buffer, list); + /* Cleans up buffer - Useful for testing for frame/URB loss */ + list_del(&(*buf)->list); + dma_q->pos = 0; + (*buf)->vb_buf = (*buf)->mem; dev->isoc_ctl.buf = *buf; return; @@ -472,8 +463,8 @@ static void au0828_copy_vbi(struct au0828_dev *dev, bytesperline = dev->vbi_width; - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; + if (dma_q->pos + len > buf->length) + len = buf->length - dma_q->pos; startread = p; startwrite = outp + (dma_q->pos / 2); @@ -496,7 +487,6 @@ static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, struct au0828_buffer **buf) { struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq); - char *outp; if (list_empty(&dma_q->active)) { au0828_isocdbg("No active queue to serve\n"); @@ -506,13 +496,12 @@ static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, } /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); + *buf = list_entry(dma_q->active.next, struct au0828_buffer, list); /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0x00, (*buf)->vb.size); - + list_del(&(*buf)->list); + dma_q->pos = 0; + (*buf)->vb_buf = (*buf)->mem; dev->isoc_ctl.vbi_buf = *buf; - return; } @@ -548,11 +537,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) buf = dev->isoc_ctl.buf; if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); + outp = vb2_plane_vaddr(&buf->vb, 0); vbi_buf = dev->isoc_ctl.vbi_buf; if (vbi_buf != NULL) - vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); + vbioutp = vb2_plane_vaddr(&vbi_buf->vb, 0); for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -592,8 +581,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (vbi_buf == NULL) vbioutp = NULL; else - vbioutp = videobuf_to_vmalloc( - &vbi_buf->vb); + vbioutp = vb2_plane_vaddr( + &vbi_buf->vb, 0); /* Video */ if (buf != NULL) @@ -602,7 +591,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (buf == NULL) outp = NULL; else - outp = videobuf_to_vmalloc(&buf->vb); + outp = vb2_plane_vaddr(&buf->vb, 0); /* As long as isoc traffic is arriving, keep resetting the timer */ @@ -656,130 +645,59 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) return rc; } -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { - struct au0828_fh *fh = vq->priv_data; - *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + struct au0828_dev *dev = vb2_get_drv_priv(vq); + unsigned long img_size = dev->height * dev->bytesperline; + unsigned long size; - if (0 == *count) - *count = AU0828_DEF_BUF; + size = fmt ? fmt->fmt.pix.sizeimage : img_size; + if (size < img_size) + return -EINVAL; - if (*count < AU0828_MIN_BUF) - *count = AU0828_MIN_BUF; - return 0; -} + *nplanes = 1; + sizes[0] = size; -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.buf == buf) - dev->isoc_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; + return 0; } static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) +buffer_prepare(struct vb2_buffer *vb) { - struct au0828_fh *fh = vq->priv_data; struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - struct au0828_dev *dev = fh->dev; - int rc = 0, urb_init = 0; + struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + buf->length = dev->height * dev->bytesperline; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (vb2_plane_size(vb, 0) < buf->length) { + pr_err("%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), buf->length); return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) { - pr_info("videobuf_iolock failed\n"); - goto fail; - } } - - if (!dev->isoc_ctl.num_bufs) - urb_init = 1; - - if (urb_init) { - rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, - AU0828_MAX_ISO_BUFS, dev->max_pkt_size, - au0828_isoc_copy); - if (rc < 0) { - pr_info("au0828_init_isoc failed\n"); - goto fail; - } - } - - buf->vb.state = VIDEOBUF_PREPARED; + vb2_set_plane_payload(&buf->vb, 0, buf->length); return 0; - -fail: - free_buffer(vq, buf); - return rc; } static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +buffer_queue(struct vb2_buffer *vb) { struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct au0828_dmaqueue *vidq = &dev->vidq; + unsigned long flags = 0; - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); + buf->mem = vb2_plane_vaddr(vb, 0); + buf->length = vb2_plane_size(vb, 0); - free_buffer(vq, buf); + spin_lock_irqsave(&dev->slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&dev->slock, flags); } -static struct videobuf_queue_ops au0828_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ - V4L2 interface - ------------------------------------------------------------------*/ - static int au0828_i2s_init(struct au0828_dev *dev) { /* Enable i2s mode */ @@ -828,7 +746,7 @@ static int au0828_analog_stream_enable(struct au0828_dev *d) return 0; } -int au0828_analog_stream_disable(struct au0828_dev *d) +static int au0828_analog_stream_disable(struct au0828_dev *d) { dprintk(1, "au0828_analog_stream_disable called\n"); au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0); @@ -861,78 +779,133 @@ static int au0828_stream_interrupt(struct au0828_dev *dev) return 0; } -/* - * au0828_release_resources - * unregister v4l2 devices - */ -void au0828_analog_unregister(struct au0828_dev *dev) +int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count) { - dprintk(1, "au0828_release_resources called\n"); - mutex_lock(&au0828_sysfs_lock); + struct au0828_dev *dev = vb2_get_drv_priv(vq); + int rc = 0; - if (dev->vdev) - video_unregister_device(dev->vdev); - if (dev->vbi_dev) - video_unregister_device(dev->vbi_dev); + dprintk(1, "au0828_start_analog_streaming called %d\n", + dev->streaming_users); - mutex_unlock(&au0828_sysfs_lock); -} + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + dev->frame_count = 0; + else + dev->vbi_frame_count = 0; + + if (dev->streaming_users == 0) { + /* If we were doing ac97 instead of i2s, it would go here...*/ + au0828_i2s_init(dev); + rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, + AU0828_MAX_ISO_BUFS, dev->max_pkt_size, + au0828_isoc_copy); + if (rc < 0) { + pr_info("au0828_init_isoc failed\n"); + return rc; + } + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + v4l2_device_call_all(&dev->v4l2_dev, 0, video, + s_stream, 1); + dev->vid_timeout_running = 1; + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + } else if (vq->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } + } + dev->streaming_users++; + return rc; +} -/* Usage lock check functions */ -static int res_get(struct au0828_fh *fh, unsigned int bit) +static void au0828_stop_streaming(struct vb2_queue *vq) { - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = vb2_get_drv_priv(vq); + struct au0828_dmaqueue *vidq = &dev->vidq; + unsigned long flags = 0; - if (fh->resources & bit) - /* have it already allocated */ - return 1; + dprintk(1, "au0828_stop_streaming called %d\n", dev->streaming_users); - /* is it free? */ - if (dev->resources & bit) { - /* no, someone else uses it */ - return 0; + if (dev->streaming_users-- == 1) + au0828_uninit_isoc(dev); + + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.buf != NULL) { + vb2_buffer_done(&dev->isoc_ctl.buf->vb, VB2_BUF_STATE_ERROR); + dev->isoc_ctl.buf = NULL; } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - dprintk(1, "res: get %d\n", bit); + while (!list_empty(&vidq->active)) { + struct au0828_buffer *buf; - return 1; + buf = list_entry(vidq->active.next, struct au0828_buffer, list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + list_del(&buf->list); + } + spin_unlock_irqrestore(&dev->slock, flags); } -static int res_check(struct au0828_fh *fh, unsigned int bit) +void au0828_stop_vbi_streaming(struct vb2_queue *vq) { - return fh->resources & bit; -} + struct au0828_dev *dev = vb2_get_drv_priv(vq); + struct au0828_dmaqueue *vbiq = &dev->vbiq; + unsigned long flags = 0; -static int res_locked(struct au0828_dev *dev, unsigned int bit) -{ - return dev->resources & bit; -} + dprintk(1, "au0828_stop_vbi_streaming called %d\n", + dev->streaming_users); -static void res_free(struct au0828_fh *fh, unsigned int bits) -{ - struct au0828_dev *dev = fh->dev; + if (dev->streaming_users-- == 1) + au0828_uninit_isoc(dev); - BUG_ON((fh->resources & bits) != bits); + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.vbi_buf != NULL) { + vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb, + VB2_BUF_STATE_ERROR); + dev->isoc_ctl.vbi_buf = NULL; + } + while (!list_empty(&vbiq->active)) { + struct au0828_buffer *buf; + + buf = list_entry(vbiq->active.next, struct au0828_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } + spin_unlock_irqrestore(&dev->slock, flags); - fh->resources &= ~bits; - dev->resources &= ~bits; - dprintk(1, "res: put %d\n", bits); + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); } -static int get_ressource(struct au0828_fh *fh) +static struct vb2_ops au0828_video_qops = { + .queue_setup = queue_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .start_streaming = au0828_start_analog_streaming, + .stop_streaming = au0828_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +/* ------------------------------------------------------------------ + V4L2 interface + ------------------------------------------------------------------*/ +/* + * au0828_analog_unregister + * unregister v4l2 devices + */ +void au0828_analog_unregister(struct au0828_dev *dev) { - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return AU0828_RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return AU0828_RESOURCE_VBI; - default: - BUG(); - return 0; - } + dprintk(1, "au0828_analog_unregister called\n"); + mutex_lock(&au0828_sysfs_lock); + + if (dev->vdev) + video_unregister_device(dev->vdev); + if (dev->vbi_dev) + video_unregister_device(dev->vbi_dev); + + mutex_unlock(&au0828_sysfs_lock); } /* This function ensures that video frames continue to be delivered even if @@ -950,8 +923,8 @@ static void au0828_vid_buffer_timeout(unsigned long data) buf = dev->isoc_ctl.buf; if (buf != NULL) { - vid_data = videobuf_to_vmalloc(&buf->vb); - memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ + vid_data = vb2_plane_vaddr(&buf->vb, 0); + memset(vid_data, 0x00, buf->length); /* Blank green frame */ buffer_filled(dev, dma_q, buf); } get_next_buf(dma_q, &buf); @@ -974,8 +947,8 @@ static void au0828_vbi_buffer_timeout(unsigned long data) buf = dev->isoc_ctl.vbi_buf; if (buf != NULL) { - vbi_data = videobuf_to_vmalloc(&buf->vb); - memset(vbi_data, 0x00, buf->vb.size); + vbi_data = vb2_plane_vaddr(&buf->vb, 0); + memset(vbi_data, 0x00, buf->length); vbi_buffer_filled(dev, dma_q, buf); } vbi_get_next_buf(dma_q, &buf); @@ -985,105 +958,65 @@ static void au0828_vbi_buffer_timeout(unsigned long data) spin_unlock_irqrestore(&dev->slock, flags); } - static int au0828_v4l2_open(struct file *filp) { - int ret = 0; - struct video_device *vdev = video_devdata(filp); struct au0828_dev *dev = video_drvdata(filp); - struct au0828_fh *fh; - int type; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - default: - return -EINVAL; - } - - fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); - if (NULL == fh) { - dprintk(1, "Failed allocate au0828_fh struct!\n"); - return -ENOMEM; - } + int ret; - fh->type = type; - fh->dev = dev; - v4l2_fh_init(&fh->fh, vdev); - filp->private_data = fh; + dprintk(1, + "%s called std_set %d dev_state %d stream users %d users %d\n", + __func__, dev->std_set_in_tuner_core, dev->dev_state, + dev->streaming_users, dev->users); - if (mutex_lock_interruptible(&dev->lock)) { - kfree(fh); + if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; + + ret = v4l2_fh_open(filp); + if (ret) { + au0828_isocdbg("%s: v4l2_fh_open() returned error %d\n", + __func__, ret); + mutex_unlock(&dev->lock); + return ret; } + if (dev->users == 0) { au0828_analog_stream_enable(dev); au0828_analog_stream_reset(dev); - - /* If we were doing ac97 instead of i2s, it would go here...*/ - au0828_i2s_init(dev); - dev->stream_state = STREAM_OFF; dev->dev_state |= DEV_INITIALIZED; } - dev->users++; mutex_unlock(&dev->lock); - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct au0828_buffer), fh, - &dev->lock); - - /* VBI Setup */ - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct au0828_buffer), fh, - &dev->lock); - v4l2_fh_add(&fh->fh); return ret; } static int au0828_v4l2_close(struct file *filp) { int ret; - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(filp); + struct video_device *vdev = video_devdata(filp); + + dprintk(1, + "%s called std_set %d dev_state %d stream users %d users %d\n", + __func__, dev->std_set_in_tuner_core, dev->dev_state, + dev->streaming_users, dev->users); - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); mutex_lock(&dev->lock); - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + if (vdev->vfl_type == VFL_TYPE_GRABBER && dev->vid_timeout_running) { /* Cancel timeout thread in case they didn't call streamoff */ dev->vid_timeout_running = 0; del_timer_sync(&dev->vid_timeout); - - videobuf_stop(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - - if (res_check(fh, AU0828_RESOURCE_VBI)) { + } else if (vdev->vfl_type == VFL_TYPE_VBI && + dev->vbi_timeout_running) { /* Cancel timeout thread in case they didn't call streamoff */ dev->vbi_timeout_running = 0; del_timer_sync(&dev->vbi_timeout); - - videobuf_stop(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); } - if (dev->users == 1 && video_is_registered(video_devdata(filp))) { - au0828_analog_stream_disable(dev); - - au0828_uninit_isoc(dev); + if (dev->dev_state == DEV_DISCONNECTED) + goto end; + if (dev->users == 1) { /* Save some power by putting tuner to sleep */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); dev->std_set_in_tuner_core = 0; @@ -1094,13 +1027,10 @@ static int au0828_v4l2_close(struct file *filp) if (ret < 0) pr_info("Au0828 can't set alternate to 0!\n"); } - mutex_unlock(&dev->lock); - - videobuf_mmap_free(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vbiq); - kfree(fh); +end: + _vb2_fop_release(filp, NULL); dev->users--; - wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); return 0; } @@ -1112,6 +1042,9 @@ static void au0828_init_tuner(struct au0828_dev *dev) .type = V4L2_TUNER_ANALOG_TV, }; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + if (dev->std_set_in_tuner_core) return; dev->std_set_in_tuner_core = 1; @@ -1124,98 +1057,6 @@ static void au0828_init_tuner(struct au0828_dev *dev) i2c_gate_ctrl(dev, 0); } -static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - au0828_init_tuner(dev); - mutex_unlock(&dev->lock); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_locked(dev, AU0828_RESOURCE_VIDEO)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return -EBUSY; - - if (dev->vbi_timeout_running == 0) { - /* Handle case where caller tries to read without - calling streamon first */ - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - return 0; -} - -static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - unsigned long req_events = poll_requested_events(wait); - unsigned int res; - - if (check_dev(dev) < 0) - return POLLERR; - - res = v4l2_ctrl_poll(filp, wait); - if (!(req_events & (POLLIN | POLLRDNORM))) - return res; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - au0828_init_tuner(dev); - mutex_unlock(&dev->lock); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VIDEO)) - return POLLERR; - return res | videobuf_poll_stream(filp, &fh->vb_vidq, wait); - } - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return POLLERR; - return res | videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - } - return POLLERR; -} - -static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); - - return rc; -} - static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, struct v4l2_format *format) { @@ -1267,13 +1108,14 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, return 0; } - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct video_device *vdev = video_devdata(file); - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->card, dev->board.name, sizeof(cap->card)); @@ -1299,6 +1141,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index) return -EINVAL; + dprintk(1, "%s called\n", __func__); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(f->description, "Packed YUV2"); @@ -1311,8 +1155,10 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; @@ -1328,8 +1174,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); return au0828_set_format(dev, VIDIOC_TRY_FMT, f); } @@ -1337,15 +1185,17 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); int rc; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + rc = check_dev(dev); if (rc < 0) return rc; - if (videobuf_queue_is_busy(&fh->vb_vidq)) { + if (vb2_is_busy(&dev->vb_vidq)) { pr_info("%s queue busy\n", __func__); rc = -EBUSY; goto out; @@ -1358,8 +1208,16 @@ out: static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + + if (norm == dev->std) + return 0; + + if (dev->streaming_users > 0) + return -EBUSY; dev->std = norm; @@ -1382,8 +1240,10 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); *norm = dev->std; return 0; @@ -1392,8 +1252,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); unsigned int tmp; static const char *inames[] = { @@ -1406,6 +1265,9 @@ static int vidioc_enum_input(struct file *file, void *priv, [AU0828_VMUX_DEBUG] = "tv debug" }; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + tmp = input->index; if (tmp >= AU0828_MAX_INPUT) @@ -1431,8 +1293,11 @@ static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + *i = dev->ctrl_input; return 0; } @@ -1441,6 +1306,9 @@ static void au0828_s_input(struct au0828_dev *dev, int index) { int i; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + switch (AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: dev->input_type = AU0828_VMUX_SVIDEO; @@ -1490,8 +1358,7 @@ static void au0828_s_input(struct au0828_dev *dev, int index) static int vidioc_s_input(struct file *file, void *priv, unsigned int index) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, index); @@ -1509,6 +1376,8 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a) if (a->index > 1) return -EINVAL; + dprintk(1, "%s called\n", __func__); + if (a->index == 0) strcpy(a->name, "Television"); else @@ -1520,8 +1389,10 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a) static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); a->index = dev->ctrl_ainput; if (a->index == 0) @@ -1535,22 +1406,26 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); if (a->index != dev->ctrl_ainput) return -EINVAL; + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); if (t->index != 0) return -EINVAL; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + strcpy(t->name, "Auvitek tuner"); au0828_init_tuner(dev); @@ -1563,12 +1438,14 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); if (t->index != 0) return -EINVAL; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + au0828_init_tuner(dev); i2c_gate_ctrl(dev, 1); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); @@ -1584,11 +1461,12 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); if (freq->tuner != 0) return -EINVAL; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); freq->frequency = dev->ctrl_freq; return 0; } @@ -1596,13 +1474,15 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *freq) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); struct v4l2_frequency new_freq = *freq; if (freq->tuner != 0) return -EINVAL; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + au0828_init_tuner(dev); i2c_gate_ctrl(dev, 1); @@ -1624,8 +1504,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *format) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); format->fmt.vbi.samples_per_line = dev->vbi_width; format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; @@ -1645,12 +1527,14 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cc) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); + cc->bounds.left = 0; cc->bounds.top = 0; cc->bounds.width = dev->width; @@ -1664,105 +1548,14 @@ static int vidioc_cropcap(struct file *file, void *priv, return 0; } -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc = -EINVAL; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (unlikely(type != fh->type)) - return -EINVAL; - - dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (unlikely(!res_get(fh, get_ressource(fh)))) - return -EBUSY; - - au0828_init_tuner(dev); - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - au0828_analog_stream_enable(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vidq); - dev->vid_timeout_running = 1; - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vbiq); - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - int i; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); - - au0828_analog_stream_disable(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); - rc = au0828_stream_interrupt(dev); - if (rc != 0) - return rc; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).audio_setup == NULL) - continue; - (AUVI_INPUT(i).audio_setup)(dev, 0); - } - - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); - - if (res_check(fh, AU0828_RESOURCE_VBI)) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); - } - } - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); reg->val = au0828_read(dev, reg->reg); reg->size = 1; @@ -1772,8 +1565,10 @@ static int vidioc_g_register(struct file *file, void *priv, static int vidioc_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; + struct au0828_dev *dev = video_drvdata(file); + + dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dev->std_set_in_tuner_core, dev->dev_state); return au0828_writereg(dev, reg->reg, reg->val); } @@ -1783,93 +1578,13 @@ static int vidioc_log_status(struct file *file, void *fh) { struct video_device *vdev = video_devdata(file); + dprintk(1, "%s called\n", __func__); + v4l2_ctrl_log_status(file, fh); v4l2_device_call_all(vdev->v4l2_dev, 0, core, log_status); return 0; } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vidq, rb); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vbiq, rb); - - return rc; -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - /* Workaround for a bug in the au0828 hardware design that sometimes - results in the colorspace being inverted */ - if (dev->greenscreen_detected == 1) { - dprintk(1, "Detected green frame. Resetting stream...\n"); - au0828_analog_stream_reset(dev); - dev->greenscreen_detected = 0; - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK); - - return rc; -} - void au0828_v4l2_suspend(struct au0828_dev *dev) { struct urb *urb; @@ -1937,9 +1652,9 @@ static struct v4l2_file_operations au0828_v4l_fops = { .owner = THIS_MODULE, .open = au0828_v4l2_open, .release = au0828_v4l2_close, - .read = au0828_v4l2_read, - .poll = au0828_v4l2_poll, - .mmap = au0828_v4l2_mmap, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; @@ -1956,17 +1671,24 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, @@ -1987,6 +1709,42 @@ static const struct video_device au0828_video_template = { .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL_M, }; +static int au0828_vb2_setup(struct au0828_dev *dev) +{ + int rc; + struct vb2_queue *q; + + /* Setup Videobuf2 for Video capture */ + q = &dev->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct au0828_buffer); + q->ops = &au0828_video_qops; + q->mem_ops = &vb2_vmalloc_memops; + + rc = vb2_queue_init(q); + if (rc < 0) + return rc; + + /* Setup Videobuf2 for VBI capture */ + q = &dev->vb_vbiq; + q->type = V4L2_BUF_TYPE_VBI_CAPTURE; + q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct au0828_buffer); + q->ops = &au0828_vbi_qops; + q->mem_ops = &vb2_vmalloc_memops; + + rc = vb2_queue_init(q); + if (rc < 0) + return rc; + + return 0; +} + /**************************************************************************/ int au0828_analog_register(struct au0828_dev *dev, @@ -2037,9 +1795,7 @@ int au0828_analog_register(struct au0828_dev *dev, /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); INIT_LIST_HEAD(&dev->vbiq.active); - INIT_LIST_HEAD(&dev->vbiq.queued); setup_timer(&dev->vid_timeout, au0828_vid_buffer_timeout, (unsigned long)dev); @@ -2073,18 +1829,34 @@ int au0828_analog_register(struct au0828_dev *dev, goto err_vdev; } + mutex_init(&dev->vb_queue_lock); + mutex_init(&dev->vb_vbi_queue_lock); + /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; dev->vdev->v4l2_dev = &dev->v4l2_dev; dev->vdev->lock = &dev->lock; + dev->vdev->queue = &dev->vb_vidq; + dev->vdev->queue->lock = &dev->vb_queue_lock; strcpy(dev->vdev->name, "au0828a video"); /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->v4l2_dev = &dev->v4l2_dev; dev->vbi_dev->lock = &dev->lock; + dev->vbi_dev->queue = &dev->vb_vbiq; + dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock; strcpy(dev->vbi_dev->name, "au0828a vbi"); + /* initialize videobuf2 stuff */ + retval = au0828_vb2_setup(dev); + if (retval != 0) { + dprintk(1, "unable to setup videobuf2 queues (error = %d).\n", + retval); + ret = -ENODEV; + goto err_vbi_dev; + } + /* Register the v4l2 device */ video_set_drvdata(dev->vdev, dev); retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); @@ -2092,7 +1864,7 @@ int au0828_analog_register(struct au0828_dev *dev, dprintk(1, "unable to register video device (error = %d).\n", retval); ret = -ENODEV; - goto err_vbi_dev; + goto err_reg_vdev; } /* Register the vbi device */ @@ -2102,13 +1874,18 @@ int au0828_analog_register(struct au0828_dev *dev, dprintk(1, "unable to register vbi device (error = %d).\n", retval); ret = -ENODEV; - goto err_vbi_dev; + goto err_reg_vbi_dev; } dprintk(1, "%s completed!\n", __func__); return 0; +err_reg_vbi_dev: + video_unregister_device(dev->vdev); +err_reg_vdev: + vb2_queue_release(&dev->vb_vidq); + vb2_queue_release(&dev->vb_vbiq); err_vbi_dev: video_device_release(dev->vbi_dev); err_vdev: diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 36815a369c68..eb1518742ae6 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -28,7 +28,7 @@ /* Analog */ #include -#include +#include #include #include #include @@ -126,17 +126,7 @@ enum au0828_dev_state { DEV_MISCONFIGURED = 0x04 }; -struct au0828_fh { - /* must be the first field of this struct! */ - struct v4l2_fh fh; - - struct au0828_dev *dev; - unsigned int resources; - - struct videobuf_queue vb_vidq; - struct videobuf_queue vb_vbiq; - enum v4l2_buf_type type; -}; +struct au0828_dev; struct au0828_usb_isoc_ctl { /* max packet size of isoc transaction */ @@ -177,21 +167,20 @@ struct au0828_usb_isoc_ctl { /* buffer for one video frame */ struct au0828_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; + struct vb2_buffer vb; + struct list_head list; - struct list_head frame; + void *mem; + unsigned long length; int top_field; - int receiving; + /* pointer to vmalloc memory address in vb */ + char *vb_buf; }; struct au0828_dmaqueue { struct list_head active; - struct list_head queued; - - wait_queue_head_t wq; - /* Counters to control buffer fill */ - int pos; + int pos; }; struct au0828_dev { @@ -220,14 +209,26 @@ struct au0828_dev { struct au0828_rc *ir; #endif - int users; - unsigned int resources; /* resources in use */ struct video_device *vdev; struct video_device *vbi_dev; + + /* Videobuf2 */ + struct vb2_queue vb_vidq; + struct vb2_queue vb_vbiq; + struct mutex vb_queue_lock; + struct mutex vb_vbi_queue_lock; + + unsigned int frame_count; + unsigned int vbi_frame_count; + struct timer_list vid_timeout; int vid_timeout_running; struct timer_list vbi_timeout; int vbi_timeout_running; + + int users; + int streaming_users; + int width; int height; int vbi_width; @@ -242,7 +243,6 @@ struct au0828_dev { __u8 isoc_in_endpointaddr; u8 isoc_init_ok; int greenscreen_detected; - unsigned int frame_count; int ctrl_freq; int input_type; int std_set_in_tuner_core; @@ -277,6 +277,7 @@ struct au0828_dev { char *dig_transfer_buffer[URB_COUNT]; }; + /* ----------------------------------------------------------- */ #define au0828_read(dev, reg) au0828_readreg(dev, reg) #define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value) @@ -309,13 +310,15 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev); /* ----------------------------------------------------------- */ /* au0828-video.c */ -int au0828_analog_register(struct au0828_dev *dev, +extern int au0828_analog_register(struct au0828_dev *dev, struct usb_interface *interface); -int au0828_analog_stream_disable(struct au0828_dev *d); -void au0828_analog_unregister(struct au0828_dev *dev); +extern void au0828_analog_unregister(struct au0828_dev *dev); +extern int au0828_start_analog_streaming(struct vb2_queue *vq, + unsigned int count); +extern void au0828_stop_vbi_streaming(struct vb2_queue *vq); #ifdef CONFIG_VIDEO_AU0828_V4L2 -void au0828_v4l2_suspend(struct au0828_dev *dev); -void au0828_v4l2_resume(struct au0828_dev *dev); +extern void au0828_v4l2_suspend(struct au0828_dev *dev); +extern void au0828_v4l2_resume(struct au0828_dev *dev); #else static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { }; static inline void au0828_v4l2_resume(struct au0828_dev *dev) { }; @@ -329,7 +332,7 @@ void au0828_dvb_suspend(struct au0828_dev *dev); void au0828_dvb_resume(struct au0828_dev *dev); /* au0828-vbi.c */ -extern struct videobuf_queue_ops au0828_vbi_qops; +extern struct vb2_ops au0828_vbi_qops; #define dprintk(level, fmt, arg...)\ do { if (au0828_debug & level)\ -- cgit v1.2.3 From 2b0aac3011bc7a9db27791bed4978554263ef079 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2014 13:48:07 -0200 Subject: [media] cx23885: move CI/MAC registration to a separate function As reported by smatch: drivers/media/pci/cx23885/cx23885-dvb.c:2080 dvb_register() Function too hairy. Giving up. This is indeed a too complex function, with lots of stuff inside. Breaking this into two functions makes it a little bit less hairy. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 272 ++++++++++++++++---------------- 1 file changed, 135 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 351fa952f210..45fbe1e4d2d0 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1069,6 +1069,116 @@ static struct dib7000p_config dib7070p_dib7000p_config = { .hostbus_diversity = 1, }; +static int dvb_register_ci_mac(struct cx23885_tsport *port) +{ + struct cx23885_dev *dev = port->dev; + struct i2c_client *client_ci = NULL; + struct vb2_dvb_frontend *fe0; + + fe0 = vb2_dvb_get_frontend(&port->frontends, 1); + if (!fe0) + return -EINVAL; + + 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=%pM\n", + port->nr, port->frontends.adapter.proposed_mac); + + netup_ci_init(port); + return 0; + } + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { + struct altera_ci_config netup_ci_cfg = { + .dev = dev,/* magic number to identify*/ + .adapter = &port->frontends.adapter,/* for CI */ + .demux = &fe0->dvb.demux,/* for hw pid filter */ + .fpga_rw = netup_altera_fpga_rw, + }; + + altera_ci_init(&netup_ci_cfg, port->nr); + return 0; + } + case CX23885_BOARD_TEVII_S470: { + u8 eeprom[256]; /* 24C02 i2c eeprom */ + + if (port->nr != 1) + return 0; + + /* Read entire EEPROM */ + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); + printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0); + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); + return 0; + } + case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_DVBSKY_S950: + case CX23885_BOARD_DVBSKY_S952: + case CX23885_BOARD_DVBSKY_T982: { + u8 eeprom[256]; /* 24C02 i2c eeprom */ + + if (port->nr > 2) + return 0; + + /* Read entire EEPROM */ + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, + sizeof(eeprom)); + printk(KERN_INFO "%s port %d MAC address: %pM\n", + cx23885_boards[dev->board].name, port->nr, + eeprom + 0xc0 + (port->nr-1) * 8); + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + + (port->nr-1) * 8, 6); + return 0; + } + case CX23885_BOARD_DVBSKY_S950C: + case CX23885_BOARD_DVBSKY_T980C: + case CX23885_BOARD_TT_CT2_4500_CI: { + u8 eeprom[256]; /* 24C02 i2c eeprom */ + struct sp2_config sp2_config; + struct i2c_board_info info; + struct cx23885_i2c *i2c_bus2 = &dev->i2c_bus[1]; + + /* attach CI */ + memset(&sp2_config, 0, sizeof(sp2_config)); + sp2_config.dvb_adap = &port->frontends.adapter; + sp2_config.priv = port; + sp2_config.ci_control = cx23885_sp2_ci_ctrl; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "sp2", I2C_NAME_SIZE); + info.addr = 0x40; + info.platform_data = &sp2_config; + request_module(info.type); + client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info); + if (client_ci == NULL || client_ci->dev.driver == NULL) + return -ENODEV; + if (!try_module_get(client_ci->dev.driver->owner)) { + i2c_unregister_device(client_ci); + return -ENODEV; + } + port->i2c_client_ci = client_ci; + + if (port->nr != 1) + return 0; + + /* Read entire EEPROM */ + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, + sizeof(eeprom)); + printk(KERN_INFO "%s MAC address: %pM\n", + cx23885_boards[dev->board].name, eeprom + 0xc0); + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6); + return 0; + } + } + return 0; +} + static int dvb_register(struct cx23885_tsport *port) { struct dib7000p_ops dib7000p_ops; @@ -1077,11 +1187,10 @@ static int dvb_register(struct cx23885_tsport *port) struct vb2_dvb_frontend *fe0, *fe1 = NULL; struct si2168_config si2168_config; struct si2157_config si2157_config; - struct sp2_config sp2_config; struct m88ts2022_config m88ts2022_config; struct i2c_board_info info; struct i2c_adapter *adapter; - struct i2c_client *client_demod = NULL, *client_tuner = NULL, *client_ci = NULL; + struct i2c_client *client_demod = NULL, *client_tuner = NULL; const struct m88ds3103_config *p_m88ds3103_config = NULL; int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL; int mfe_shared = 0; /* bus not shared by default */ @@ -1812,17 +1921,11 @@ static int dvb_register(struct cx23885_tsport *port) request_module(info.type); client_tuner = i2c_new_device(adapter, &info); if (client_tuner == NULL || - client_tuner->dev.driver == NULL) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; + client_tuner->dev.driver == NULL) goto frontend_detach; - } + if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; goto frontend_detach; } port->i2c_client_tuner = client_tuner; @@ -1862,17 +1965,11 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2157_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || client_tuner->dev.driver == NULL) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; + if (client_tuner == NULL || + client_tuner->dev.driver == NULL) goto frontend_detach; - } if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; goto frontend_detach; } port->i2c_client_tuner = client_tuner; @@ -2006,17 +2103,11 @@ static int dvb_register(struct cx23885_tsport *port) info.platform_data = &si2157_config; request_module(info.type); client_tuner = i2c_new_device(adapter, &info); - if (client_tuner == NULL || client_tuner->dev.driver == NULL) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; + if (client_tuner == NULL || + client_tuner->dev.driver == NULL) goto frontend_detach; - } if (!try_module_get(client_tuner->dev.driver->owner)) { i2c_unregister_device(client_tuner); - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - port->i2c_client_demod = NULL; goto frontend_detach; } port->i2c_client_tuner = client_tuner; @@ -2144,122 +2235,29 @@ static int dvb_register(struct cx23885_tsport *port) if (ret) goto frontend_detach; - /* 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=%pM\n", - port->nr, port->frontends.adapter.proposed_mac); - - netup_ci_init(port); - break; - } - case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { - struct altera_ci_config netup_ci_cfg = { - .dev = dev,/* magic number to identify*/ - .adapter = &port->frontends.adapter,/* for CI */ - .demux = &fe0->dvb.demux,/* for hw pid filter */ - .fpga_rw = netup_altera_fpga_rw, - }; - - altera_ci_init(&netup_ci_cfg, port->nr); - break; - } - case CX23885_BOARD_TEVII_S470: { - u8 eeprom[256]; /* 24C02 i2c eeprom */ - - if (port->nr != 1) - break; - - /* Read entire EEPROM */ - dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); - printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0); - memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); - break; - } - case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_DVBSKY_S950: - case CX23885_BOARD_DVBSKY_S952: - case CX23885_BOARD_DVBSKY_T982: { - u8 eeprom[256]; /* 24C02 i2c eeprom */ - - if (port->nr > 2) - break; - - /* Read entire EEPROM */ - dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, - sizeof(eeprom)); - printk(KERN_INFO "%s port %d MAC address: %pM\n", - cx23885_boards[dev->board].name, port->nr, - eeprom + 0xc0 + (port->nr-1) * 8); - memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + - (port->nr-1) * 8, 6); - break; - } - case CX23885_BOARD_DVBSKY_S950C: - case CX23885_BOARD_DVBSKY_T980C: - case CX23885_BOARD_TT_CT2_4500_CI: { - u8 eeprom[256]; /* 24C02 i2c eeprom */ - - /* attach CI */ - memset(&sp2_config, 0, sizeof(sp2_config)); - sp2_config.dvb_adap = &port->frontends.adapter; - sp2_config.priv = port; - sp2_config.ci_control = cx23885_sp2_ci_ctrl; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "sp2", I2C_NAME_SIZE); - info.addr = 0x40; - info.platform_data = &sp2_config; - request_module(info.type); - client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info); - if (client_ci == NULL || client_ci->dev.driver == NULL) { - if (client_tuner) { - module_put(client_tuner->dev.driver->owner); - i2c_unregister_device(client_tuner); - } - if (client_demod) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - } - goto frontend_detach; - } - if (!try_module_get(client_ci->dev.driver->owner)) { - i2c_unregister_device(client_ci); - if (client_tuner) { - module_put(client_tuner->dev.driver->owner); - i2c_unregister_device(client_tuner); - } - if (client_demod) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); - } - goto frontend_detach; - } - port->i2c_client_ci = client_ci; + ret = dvb_register_ci_mac(port); + if (ret) + goto frontend_detach; - if (port->nr != 1) - break; + return 0; - /* Read entire EEPROM */ - dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, - sizeof(eeprom)); - printk(KERN_INFO "%s MAC address: %pM\n", - cx23885_boards[dev->board].name, eeprom + 0xc0); - memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6); - break; - } +frontend_detach: + /* remove I2C client for tuner */ + client_tuner = port->i2c_client_tuner; + if (client_tuner) { + module_put(client_tuner->dev.driver->owner); + i2c_unregister_device(client_tuner); + port->i2c_client_tuner = NULL; } - return ret; + /* remove I2C client for demodulator */ + client_demod = port->i2c_client_demod; + if (client_demod) { + module_put(client_demod->dev.driver->owner); + i2c_unregister_device(client_demod); + port->i2c_client_demod = NULL; + } -frontend_detach: port->gate_ctrl = NULL; vb2_dvb_dealloc_frontends(&port->frontends); return -EINVAL; -- cgit v1.2.3 From 901c4ad64c53f4d29d7bd96f33d1d5aae55ad8d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2014 11:21:12 -0300 Subject: [media] dib8000: upd_demod_gain_period should be u32 X-Patchwork-Delegate: m.chehab@samsung.com As shown at the code, upd_demod_gain_period is used to write to two 16-bit registers: dib8000_write_word(state, 1946, upd_demod_gain_period & 0xFFFF); dib8000_write_word(state, 1947, reg | (1<<14) | ((upd_demod_gain_period >> 16) & 0xFF)); So, it should be declared as u32. This fixes the following smatch warning: drivers/media/dvb-frontends/dib8000.c:1282 dib8000_agc_startup() warn: right shifting more than type allows Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib8000.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 61e31f2d2f71..8c6663b6399d 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -1263,7 +1263,8 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) struct dib8000_state *state = fe->demodulator_priv; enum frontend_tune_state *tune_state = &state->tune_state; int ret = 0; - u16 reg, upd_demod_gain_period = 0x8000; + u16 reg; + u32 upd_demod_gain_period = 0x8000; switch (*tune_state) { case CT_AGC_START: -- cgit v1.2.3 From 47e604c5ddf128b5102cfd5d88cd5e2f243e1c2f Mon Sep 17 00:00:00 2001 From: Prabhakar Lad Date: Fri, 19 Dec 2014 10:52:04 -0300 Subject: [media] media: ti-vpe: Use mem-to-mem ioctl helpers 1: Simplify the vpe mem-to-mem driver by using the m2m ioctl and vb2 helpers. 2: Align and arranged the v4l2_ioctl_ops. 3: Fixes a typo. 4: Use of_match_ptr() instead of explicitly defining the macro to NULL in case CONFIG_OF is not defined. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpe.c | 157 ++++++++++++------------------------ 1 file changed, 50 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 968fb63caf94..c44760b705da 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -74,7 +75,7 @@ #define VPE_DEF_BUFS_PER_JOB 1 /* default one buffer per batch job */ /* - * each VPE context can need up to 3 config desciptors, 7 input descriptors, + * each VPE context can need up to 3 config descriptors, 7 input descriptors, * 3 output descriptors, and 10 control descriptors */ #define VPE_DESC_LIST_SIZE (10 * VPDMA_DTD_DESC_SIZE + \ @@ -373,7 +374,6 @@ struct vpe_dev { struct vpe_ctx { struct v4l2_fh fh; struct vpe_dev *dev; - struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl_handler hdl; unsigned int field; /* current field */ @@ -887,10 +887,10 @@ static int job_ready(void *priv) if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) needed += 2; /* need additional two most recent fields */ - if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < needed) + if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < needed) return 0; - if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < needed) + if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < needed) return 0; return 1; @@ -1100,15 +1100,15 @@ static void device_run(void *priv) struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) { - ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); WARN_ON(ctx->src_vbs[2] == NULL); - ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); WARN_ON(ctx->src_vbs[1] == NULL); } - ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); WARN_ON(ctx->src_vbs[0] == NULL); - ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); WARN_ON(ctx->dst_vb == NULL); /* config descriptors */ @@ -1334,7 +1334,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) finished: vpe_dbg(ctx->dev, "finishing transaction\n"); ctx->bufs_completed = 0; - v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); + v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx); handled: return IRQ_HANDLED; } @@ -1395,7 +1395,7 @@ static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) struct vpe_q_data *q_data; int i; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -1527,7 +1527,7 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f) struct vb2_queue *vq; int i; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -1739,52 +1739,6 @@ static int vpe_s_selection(struct file *file, void *fh, return set_srcdst_params(ctx); } -static int vpe_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct vpe_ctx *ctx = file2ctx(file); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int vpe_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct vpe_ctx *ctx = file2ctx(file); - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int vpe_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct vpe_ctx *ctx = file2ctx(file); - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vpe_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct vpe_ctx *ctx = file2ctx(file); - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int vpe_streamon(struct file *file, void *priv, enum v4l2_buf_type type) -{ - struct vpe_ctx *ctx = file2ctx(file); - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int vpe_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) -{ - struct vpe_ctx *ctx = file2ctx(file); - - vpe_dump_regs(ctx->dev); - vpdma_dump_regs(ctx->dev->vpdma); - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - /* * defines number of buffers/frames a context can process with VPE before * switching to a different context. default value is 1 buffer per context @@ -1814,14 +1768,14 @@ static const struct v4l2_ctrl_ops vpe_ctrl_ops = { }; static const struct v4l2_ioctl_ops vpe_ioctl_ops = { - .vidioc_querycap = vpe_querycap, + .vidioc_querycap = vpe_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt, + .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt, .vidioc_g_fmt_vid_cap_mplane = vpe_g_fmt, .vidioc_try_fmt_vid_cap_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_cap_mplane = vpe_s_fmt, - .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt, + .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt, .vidioc_g_fmt_vid_out_mplane = vpe_g_fmt, .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, @@ -1829,16 +1783,15 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_g_selection = vpe_g_selection, .vidioc_s_selection = vpe_s_selection, - .vidioc_reqbufs = vpe_reqbufs, - .vidioc_querybuf = vpe_querybuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_qbuf = vpe_qbuf, - .vidioc_dqbuf = vpe_dqbuf, - - .vidioc_streamon = vpe_streamon, - .vidioc_streamoff = vpe_streamoff, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* @@ -1910,7 +1863,23 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) static void vpe_buf_queue(struct vb2_buffer *vb) { struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); +} + +static int vpe_start_streaming(struct vb2_queue *q, unsigned int count) +{ + /* currently we do nothing here */ + + return 0; +} + +static void vpe_stop_streaming(struct vb2_queue *q) +{ + struct vpe_ctx *ctx = vb2_get_drv_priv(q); + + vpe_dump_regs(ctx->dev); + vpdma_dump_regs(ctx->dev->vpdma); } static struct vb2_ops vpe_qops = { @@ -1919,6 +1888,8 @@ static struct vb2_ops vpe_qops = { .buf_queue = vpe_buf_queue, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, + .start_streaming = vpe_start_streaming, + .stop_streaming = vpe_stop_streaming, }; static int queue_init(void *priv, struct vb2_queue *src_vq, @@ -1972,9 +1943,9 @@ static const struct v4l2_ctrl_config vpe_bufs_per_job = { static int vpe_open(struct file *file) { struct vpe_dev *dev = video_drvdata(file); - struct vpe_ctx *ctx = NULL; struct vpe_q_data *s_q_data; struct v4l2_ctrl_handler *hdl; + struct vpe_ctx *ctx; int ret; vpe_dbg(dev, "vpe_open\n"); @@ -2047,10 +2018,10 @@ static int vpe_open(struct file *file) if (ret) goto exit_fh; - ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - ret = PTR_ERR(ctx->m2m_ctx); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); goto exit_fh; } @@ -2069,7 +2040,7 @@ static int vpe_open(struct file *file) ctx->load_mmrs = true; vpe_dbg(dev, "created instance %p, m2m_ctx: %p\n", - ctx, ctx->m2m_ctx); + ctx, ctx->fh.m2m_ctx); mutex_unlock(&dev->dev_mutex); @@ -2107,7 +2078,7 @@ static int vpe_release(struct file *file) v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); kfree(ctx); @@ -2124,39 +2095,13 @@ static int vpe_release(struct file *file) return 0; } -static unsigned int vpe_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct vpe_ctx *ctx = file2ctx(file); - struct vpe_dev *dev = ctx->dev; - int ret; - - mutex_lock(&dev->dev_mutex); - ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&dev->dev_mutex); - return ret; -} - -static int vpe_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vpe_ctx *ctx = file2ctx(file); - struct vpe_dev *dev = ctx->dev; - int ret; - - if (mutex_lock_interruptible(&dev->dev_mutex)) - return -ERESTARTSYS; - ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&dev->dev_mutex); - return ret; -} - static const struct v4l2_file_operations vpe_fops = { .owner = THIS_MODULE, .open = vpe_open, .release = vpe_release, - .poll = vpe_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = vpe_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static struct video_device vpe_videodev = { @@ -2358,8 +2303,6 @@ static const struct of_device_id vpe_of_match[] = { }, {}, }; -#else -#define vpe_of_match NULL #endif static struct platform_driver vpe_pdrv = { @@ -2367,7 +2310,7 @@ static struct platform_driver vpe_pdrv = { .remove = vpe_remove, .driver = { .name = VPE_MODULE_NAME, - .of_match_table = vpe_of_match, + .of_match_table = of_match_ptr(vpe_of_match), }, }; -- cgit v1.2.3 From a1408379ba9d87d66691835c7cdc2645793e311a Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 2 Feb 2015 09:20:23 -0300 Subject: [media] staging: bcm2048: Delete an unnecessary check before the function call "video_unregister_device" The video_unregister_device() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/bcm2048/radio-bcm2048.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 4d5e2f400ff6..538250667918 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2684,9 +2684,7 @@ static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client) vd = bdev->videodev; bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs)); - - if (vd) - video_unregister_device(vd); + video_unregister_device(vd); if (bdev->power_state) bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); -- cgit v1.2.3 From caaee5f83291086f5e5003635b77536b18aae5f7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 28 Jan 2015 19:11:20 -0300 Subject: [media] marvell-ccic: MMP_CAMERA no longer builds The mmp ccic driver expects a platform_data structure that does not exist in the mainline kernel and presumably was changed in a kernel fork, which leads to build errors now: media/platform/marvell-ccic/mmp-driver.c: In function 'mmpcam_calc_dphy': media/platform/marvell-ccic/mmp-driver.c:252:15: error: 'struct mmp_camera_platform_data' has no member named 'dphy3_algo' switch (pdata->dphy3_algo) { ^ media/platform/marvell-ccic/mmp-driver.c:253:7: error: 'DPHY3_ALGO_PXA910' undeclared (first use in this function) case DPHY3_ALGO_PXA910: ^ media/platform/marvell-ccic/mmp-driver.c:253:7: note: each undeclared identifier is reported only once for each function it appears in media/platform/marvell-ccic/mmp-driver.c:257:8: error: 'struct mmp_camera_platform_data' has no member named 'dphy' This marks the driver as 'BROKEN' but keeps the code around. Alternatively it could be removed entirely. Fixes: 05fed81625bf75 ("[media] marvell-ccic: add MIPI support for marvell-ccic driver") Signed-off-by: Arnd Bergmann Acked-by: Jonathan Corbet Cc: Libin Yang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig index 3d166568bd69..4bf5bd1e90d6 100644 --- a/drivers/media/platform/marvell-ccic/Kconfig +++ b/drivers/media/platform/marvell-ccic/Kconfig @@ -14,7 +14,7 @@ config VIDEO_CAFE_CCIC config VIDEO_MMP_CAMERA tristate "Marvell Armada 610 integrated camera controller support" depends on ARCH_MMP && I2C && VIDEO_V4L2 - depends on HAS_DMA + depends on HAS_DMA && BROKEN select VIDEO_OV7670 select I2C_GPIO select VIDEOBUF2_DMA_SG -- cgit v1.2.3 From 93d8db803a6477d3b075b971b10c2bb3ef164a44 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Thu, 29 Jan 2015 23:26:10 -0300 Subject: [media] media: platform: fix platform_no_drv_owner.cocci warnings drivers/media/platform/am437x/am437x-vpfe.c:2767:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci CC: Benoit Parrot Signed-off-by: Fengguang Wu Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/am437x/am437x-vpfe.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 349bd060f5a4..56a5cb0d2152 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2763,7 +2763,6 @@ static struct platform_driver vpfe_driver = { .remove = vpfe_remove, .driver = { .name = VPFE_MODULE_NAME, - .owner = THIS_MODULE, .pm = &vpfe_pm_ops, .of_match_table = of_match_ptr(vpfe_of_match), }, -- cgit v1.2.3 From ab98180ac2e6e41058f8829c0961aa306c610c16 Mon Sep 17 00:00:00 2001 From: Nibble Max Date: Thu, 25 Dec 2014 05:18:31 -0300 Subject: [media] smipcie: return more proper value in interrupt handler Although IRQ_HANDLED is "safe" value to return, it is better to let the kernel know whether the driver handle the interrupt or not. Signed-off-by: Nibble Max Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/smipcie/smipcie.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c index f773350e67b9..36c8ed77309c 100644 --- a/drivers/media/pci/smipcie/smipcie.c +++ b/drivers/media/pci/smipcie/smipcie.c @@ -448,16 +448,19 @@ static void smi_port_exit(struct smi_port *port) port->enable = 0; } -static void smi_port_irq(struct smi_port *port, u32 int_status) +static int smi_port_irq(struct smi_port *port, u32 int_status) { u32 port_req_irq = port->_dmaInterruptCH0 | port->_dmaInterruptCH1; + int handled = 0; if (int_status & port_req_irq) { smi_port_disableInterrupt(port); port->_int_status = int_status; smi_port_clearInterrupt(port); tasklet_schedule(&port->tasklet); + handled = 1; } + return handled; } static irqreturn_t smi_irq_handler(int irq, void *dev_id) @@ -465,18 +468,19 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id) struct smi_dev *dev = dev_id; struct smi_port *port0 = &dev->ts_port[0]; struct smi_port *port1 = &dev->ts_port[1]; + int handled = 0; u32 intr_status = smi_read(MSI_INT_STATUS); /* ts0 interrupt.*/ if (dev->info->ts_0) - smi_port_irq(port0, intr_status); + handled += smi_port_irq(port0, intr_status); /* ts1 interrupt.*/ if (dev->info->ts_1) - smi_port_irq(port1, intr_status); + handled += smi_port_irq(port1, intr_status); - return IRQ_HANDLED; + return IRQ_RETVAL(handled); } static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter, -- cgit v1.2.3 From ac5361a8c8ab29d2a6d849fed05326304e9d1ef8 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 17 Dec 2014 08:10:49 -0300 Subject: [media] dvb-usb-v2: add pointer to 'struct usb_interface' for driver usage Top level pointer on USB probe is struct usb_interface *. Add that pointer to struct dvb_usb_device that drivers could use it, for dev_* logging and more. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 ++ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 14e111e13e54..41c6363dff08 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -354,6 +354,7 @@ struct dvb_usb_adapter { * @name: device name * @rc_map: name of rc codes table * @rc_polling_active: set when RC polling is active + * @intf: pointer to the device's struct usb_interface * @udev: pointer to the device's struct usb_device * @rc: remote controller configuration * @powered: indicated whether the device is power or not @@ -370,6 +371,7 @@ struct dvb_usb_device { const char *name; const char *rc_map; bool rc_polling_active; + struct usb_interface *intf; struct usb_device *udev; struct dvb_usb_rc rc; int powered; diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 1950f37df835..9913e0f59485 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -868,6 +868,7 @@ int dvb_usbv2_probe(struct usb_interface *intf, goto err; } + d->intf = intf; d->name = driver_info->name; d->rc_map = driver_info->rc_map; d->udev = udev; -- cgit v1.2.3 From 28c08799390befbf0821ad6dcc3a38ade454cef9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 7 Dec 2014 04:07:29 -0300 Subject: [media] rtl2830: convert driver to kernel I2C model Convert driver to kernel I2C model. Old DVB proprietary model is still left there also. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/Kconfig | 2 +- drivers/media/dvb-frontends/rtl2830.c | 167 +++++++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2830.h | 31 ++++++ drivers/media/dvb-frontends/rtl2830_priv.h | 2 + 4 files changed, 201 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 6c75418222e2..e8827fc1ca11 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -443,7 +443,7 @@ config DVB_CXD2820R config DVB_RTL2830 tristate "Realtek RTL2830 DVB-T" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && I2C_MUX default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 50e8b63e5169..ec4a19c63090 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -767,6 +767,173 @@ static struct dvb_frontend_ops rtl2830_ops = { .read_signal_strength = rtl2830_read_signal_strength, }; +/* + * I2C gate/repeater logic + * We must use unlocked i2c_transfer() here because I2C lock is already taken + * by tuner driver. Gate is closed automatically after single I2C xfer. + */ +static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) +{ + struct i2c_client *client = mux_priv; + struct rtl2830_priv *priv = i2c_get_clientdata(client); + struct i2c_msg select_reg_page_msg[1] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = 2, + .buf = "\x00\x01", + } + }; + struct i2c_msg gate_open_msg[1] = { + { + .addr = priv->cfg.i2c_addr, + .flags = 0, + .len = 2, + .buf = "\x01\x08", + } + }; + int ret; + + /* select register page */ + ret = __i2c_transfer(adap, select_reg_page_msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + goto err; + } + + priv->page = 1; + + /* open tuner I2C repeater for 1 xfer, closes automatically */ + ret = __i2c_transfer(adap, gate_open_msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + goto err; + } + + return 0; + +err: + dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) +{ + struct rtl2830_priv *priv = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + return &priv->fe; +} + +static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) +{ + struct rtl2830_priv *priv = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + return priv->adapter; +} + +static int rtl2830_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rtl2830_platform_data *pdata = client->dev.platform_data; + struct i2c_adapter *i2c = client->adapter; + struct rtl2830_priv *priv; + int ret; + u8 u8tmp; + + dev_dbg(&client->dev, "\n"); + + if (pdata == NULL) { + ret = -EINVAL; + goto err; + } + + /* allocate memory for the internal state */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + ret = -ENOMEM; + goto err; + } + + /* setup the state */ + i2c_set_clientdata(client, priv); + priv->i2c = i2c; + priv->sleeping = true; + priv->cfg.i2c_addr = client->addr; + priv->cfg.xtal = pdata->clk; + priv->cfg.spec_inv = pdata->spec_inv; + priv->cfg.vtop = pdata->vtop; + priv->cfg.krf = pdata->krf; + priv->cfg.agc_targ_val = pdata->agc_targ_val; + + /* check if the demod is there */ + ret = rtl2830_rd_reg(priv, 0x000, &u8tmp); + if (ret) + goto err_kfree; + + /* create muxed i2c adapter for tuner */ + priv->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, + client, 0, 0, 0, rtl2830_select, NULL); + if (priv->adapter == NULL) { + ret = -ENODEV; + goto err_kfree; + } + + /* create dvb frontend */ + memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(priv->fe.ops)); + priv->fe.ops.release = NULL; + priv->fe.demodulator_priv = priv; + + /* setup callbacks */ + pdata->get_dvb_frontend = rtl2830_get_dvb_frontend; + pdata->get_i2c_adapter = rtl2830_get_i2c_adapter; + + dev_info(&client->dev, "Realtek RTL2830 successfully attached\n"); + return 0; + +err_kfree: + kfree(priv); +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int rtl2830_remove(struct i2c_client *client) +{ + struct rtl2830_priv *priv = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + i2c_del_mux_adapter(priv->adapter); + kfree(priv); + return 0; +} + +static const struct i2c_device_id rtl2830_id_table[] = { + {"rtl2830", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, rtl2830_id_table); + +static struct i2c_driver rtl2830_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "rtl2830", + }, + .probe = rtl2830_probe, + .remove = rtl2830_remove, + .id_table = rtl2830_id_table, +}; + +module_i2c_driver(rtl2830_driver); + MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 3313847fb0be..b925ea5147e6 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -24,6 +24,37 @@ #include #include +struct rtl2830_platform_data { + /* + * Clock frequency. + * Hz + * 4000000, 16000000, 25000000, 28800000 + */ + u32 clk; + + /* + * Spectrum inversion. + */ + bool spec_inv; + + /* + */ + u8 vtop; + + /* + */ + u8 krf; + + /* + */ + u8 agc_targ_val; + + /* + */ + struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); + struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); +}; + struct rtl2830_config { /* * Demodulator I2C address. diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index fab10ecb3c3b..1a78351fe693 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -24,8 +24,10 @@ #include "dvb_frontend.h" #include "dvb_math.h" #include "rtl2830.h" +#include struct rtl2830_priv { + struct i2c_adapter *adapter; struct i2c_adapter *i2c; struct dvb_frontend fe; struct rtl2830_config cfg; -- cgit v1.2.3 From c0ceac97d2846af16f6fd1e6bdbbce54639ef125 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 7 Dec 2014 22:02:23 -0300 Subject: [media] rtl28xxu: use I2C binding for RTL2830 demod driver rtl2830 driver supports now I2C model too. Start using it. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 80 +++++++++++++++------------------ drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 17 +++++++ 2 files changed, 54 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 705c6c30acb7..fcb5c36bc1ea 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -22,23 +22,6 @@ #include "rtl28xxu.h" -#include "rtl2830.h" -#include "rtl2832.h" -#include "rtl2832_sdr.h" -#include "mn88472.h" -#include "mn88473.h" - -#include "qt1010.h" -#include "mt2060.h" -#include "mxl5005s.h" -#include "fc0012.h" -#include "fc0013.h" -#include "e4000.h" -#include "fc2580.h" -#include "tua9001.h" -#include "r820t.h" - - #ifdef CONFIG_MEDIA_ATTACH #define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ void *__r = NULL; \ @@ -572,10 +555,8 @@ err: return ret; } -static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, +static const struct rtl2830_platform_data rtl2830_mt2060_platform_data = { + .clk = 28800000, .spec_inv = 1, .vtop = 0x20, .krf = 0x04, @@ -583,20 +564,16 @@ static const struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { }; -static const struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, +static const struct rtl2830_platform_data rtl2830_qt1010_platform_data = { + .clk = 28800000, .spec_inv = 1, .vtop = 0x20, .krf = 0x04, .agc_targ_val = 0x2d, }; -static const struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, +static const struct rtl2830_platform_data rtl2830_mxl5005s_platform_data = { + .clk = 28800000, .spec_inv = 0, .vtop = 0x3f, .krf = 0x04, @@ -607,20 +584,22 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - const struct rtl2830_config *rtl2830_config; + struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + struct i2c_board_info board_info; + struct i2c_client *client; int ret; dev_dbg(&d->udev->dev, "%s:\n", __func__); switch (priv->tuner) { case TUNER_RTL2830_QT1010: - rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; + *pdata = rtl2830_qt1010_platform_data; break; case TUNER_RTL2830_MT2060: - rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; + *pdata = rtl2830_mt2060_platform_data; break; case TUNER_RTL2830_MXL5005S: - rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; + *pdata = rtl2830_mxl5005s_platform_data; break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", @@ -630,12 +609,28 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) } /* attach demodulator */ - adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap); - if (!adap->fe[0]) { + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "rtl2830", I2C_NAME_SIZE); + board_info.addr = 0x10; + board_info.platform_data = pdata; + request_module("%s", board_info.type); + client = i2c_new_device(&d->i2c_adap, &board_info); + if (client == NULL || client->dev.driver == NULL) { ret = -ENODEV; goto err; } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + ret = -ENODEV; + goto err; + } + + adap->fe[0] = pdata->get_dvb_frontend(client); + priv->demod_i2c_adapter = pdata->get_i2c_adapter(client); + + priv->i2c_client_demod = client; + return 0; err: dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); @@ -973,27 +968,25 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct i2c_adapter *rtl2830_tuner_i2c; struct dvb_frontend *fe; dev_dbg(&d->udev->dev, "%s:\n", __func__); - /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ - rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); - switch (priv->tuner) { case TUNER_RTL2830_QT1010: fe = dvb_attach(qt1010_attach, adap->fe[0], - rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); + priv->demod_i2c_adapter, + &rtl28xxu_qt1010_config); break; case TUNER_RTL2830_MT2060: fe = dvb_attach(mt2060_attach, adap->fe[0], - rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, - 1220); + priv->demod_i2c_adapter, + &rtl28xxu_mt2060_config, 1220); break; case TUNER_RTL2830_MXL5005S: fe = dvb_attach(mxl5005s_attach, adap->fe[0], - rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); + priv->demod_i2c_adapter, + &rtl28xxu_mxl5005s_config); break; default: fe = NULL; @@ -1586,6 +1579,7 @@ static const struct dvb_usb_device_properties rtl2831u_props = { .i2c_algo = &rtl28xxu_i2c_algo, .read_config = rtl2831u_read_config, .frontend_attach = rtl2831u_frontend_attach, + .frontend_detach = rtl2832u_frontend_detach, .tuner_attach = rtl2831u_tuner_attach, .init = rtl28xxu_init, .get_rc_config = rtl2831u_get_rc_config, diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index e52a2b731b92..3f630c842949 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -24,6 +24,22 @@ #include "dvb_usb.h" +#include "rtl2830.h" +#include "rtl2832.h" +#include "rtl2832_sdr.h" +#include "mn88472.h" +#include "mn88473.h" + +#include "qt1010.h" +#include "mt2060.h" +#include "mxl5005s.h" +#include "fc0012.h" +#include "fc0013.h" +#include "e4000.h" +#include "fc2580.h" +#include "tua9001.h" +#include "r820t.h" + /* * USB commands * (usb_control_msg() index parameter) @@ -64,6 +80,7 @@ struct rtl28xxu_priv { #define SLAVE_DEMOD_MN88472 1 #define SLAVE_DEMOD_MN88473 2 unsigned int slave_demod:2; + struct rtl2830_platform_data rtl2830_platform_data; }; enum rtl28xxu_chip_id { -- cgit v1.2.3 From aba4e34a788d10a9578969ae836627400d2d21a2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 8 Dec 2014 22:20:55 -0300 Subject: [media] rtl2830: get rid of legacy DVB driver binding Remove legacy DVB binding as all users are using I2C binding. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 101 ----------------------------- drivers/media/dvb-frontends/rtl2830.h | 63 ------------------ drivers/media/dvb-frontends/rtl2830_priv.h | 9 +++ 3 files changed, 9 insertions(+), 164 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index ec4a19c63090..541e24496163 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -631,104 +631,6 @@ err: return ret; } -static struct dvb_frontend_ops rtl2830_ops; - -static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msg[], int num) -{ - struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap); - int ret; - - /* open i2c-gate */ - ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08); - if (ret) - goto err; - - ret = i2c_transfer(priv->i2c, msg, num); - if (ret < 0) - dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n", - KBUILD_MODNAME, ret); - - return ret; -err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; -} - -static struct i2c_algorithm rtl2830_tuner_i2c_algo = { - .master_xfer = rtl2830_tuner_i2c_xfer, - .functionality = rtl2830_tuner_i2c_func, -}; - -struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe) -{ - struct rtl2830_priv *priv = fe->demodulator_priv; - return &priv->tuner_i2c_adapter; -} -EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter); - -static void rtl2830_release(struct dvb_frontend *fe) -{ - struct rtl2830_priv *priv = fe->demodulator_priv; - - i2c_del_adapter(&priv->tuner_i2c_adapter); - kfree(priv); -} - -struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, - struct i2c_adapter *i2c) -{ - struct rtl2830_priv *priv = NULL; - int ret = 0; - u8 tmp; - - /* allocate memory for the internal state */ - priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL); - if (priv == NULL) - goto err; - - /* setup the priv */ - priv->i2c = i2c; - memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config)); - - /* check if the demod is there */ - ret = rtl2830_rd_reg(priv, 0x000, &tmp); - if (ret) - goto err; - - /* create dvb_frontend */ - memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops)); - priv->fe.demodulator_priv = priv; - - /* create tuner i2c adapter */ - strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter", - sizeof(priv->tuner_i2c_adapter.name)); - priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; - priv->tuner_i2c_adapter.algo_data = NULL; - priv->tuner_i2c_adapter.dev.parent = &i2c->dev; - i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); - if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { - dev_err(&i2c->dev, - "%s: tuner i2c bus could not be initialized\n", - KBUILD_MODNAME); - goto err; - } - - priv->sleeping = true; - - return &priv->fe; -err: - dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); - kfree(priv); - return NULL; -} -EXPORT_SYMBOL(rtl2830_attach); - static struct dvb_frontend_ops rtl2830_ops = { .delsys = { SYS_DVBT }, .info = { @@ -750,8 +652,6 @@ static struct dvb_frontend_ops rtl2830_ops = { FE_CAN_MUTE_TS }, - .release = rtl2830_release, - .init = rtl2830_init, .sleep = rtl2830_sleep, @@ -888,7 +788,6 @@ static int rtl2830_probe(struct i2c_client *client, /* create dvb frontend */ memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(priv->fe.ops)); - priv->fe.ops.release = NULL; priv->fe.demodulator_priv = priv; /* setup callbacks */ diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index b925ea5147e6..1d7784de9c7a 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -55,67 +55,4 @@ struct rtl2830_platform_data { struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); }; -struct rtl2830_config { - /* - * Demodulator I2C address. - */ - u8 i2c_addr; - - /* - * Xtal frequency. - * Hz - * 4000000, 16000000, 25000000, 28800000 - */ - u32 xtal; - - /* - * TS output mode. - */ - u8 ts_mode; - - /* - * Spectrum inversion. - */ - bool spec_inv; - - /* - */ - u8 vtop; - - /* - */ - u8 krf; - - /* - */ - u8 agc_targ_val; -}; - -#if IS_ENABLED(CONFIG_DVB_RTL2830) -extern struct dvb_frontend *rtl2830_attach( - const struct rtl2830_config *config, - struct i2c_adapter *i2c -); - -extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( - struct dvb_frontend *fe -); -#else -static inline struct dvb_frontend *rtl2830_attach( - const struct rtl2830_config *config, - struct i2c_adapter *i2c -) -{ - pr_warn("%s: driver disabled by Kconfig\n", __func__); - return NULL; -} - -static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( - struct dvb_frontend *fe -) -{ - return NULL; -} -#endif - #endif /* RTL2830_H */ diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 1a78351fe693..545907a3583e 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -26,6 +26,15 @@ #include "rtl2830.h" #include +struct rtl2830_config { + u8 i2c_addr; + u32 xtal; + bool spec_inv; + u8 vtop; + u8 krf; + u8 agc_targ_val; +}; + struct rtl2830_priv { struct i2c_adapter *adapter; struct i2c_adapter *i2c; -- cgit v1.2.3 From f544f100ac5f62ef288940bdfd3421ba7a22789b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 8 Dec 2014 22:31:28 -0300 Subject: [media] rtl2830: rename 'priv' to 'dev' Use name 'dev' for device state instance as it is more common and also one letter shorter. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 212 ++++++++++++++--------------- drivers/media/dvb-frontends/rtl2830_priv.h | 2 +- 2 files changed, 107 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 541e24496163..44643d9b4322 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -31,13 +31,13 @@ #define MAX_XFER_SIZE 64 /* write multiple hardware registers */ -static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) +static int rtl2830_wr(struct rtl2830_dev *dev, u8 reg, const u8 *val, int len) { int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 1 + len, .buf = buf, @@ -45,7 +45,7 @@ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) }; if (1 + len > sizeof(buf)) { - dev_warn(&priv->i2c->dev, + dev_warn(&dev->i2c->dev, "%s: i2c wr reg=%04x: len=%d is too big!\n", KBUILD_MODNAME, reg, len); return -EINVAL; @@ -54,11 +54,11 @@ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) buf[0] = reg; memcpy(&buf[1], val, len); - ret = i2c_transfer(priv->i2c, msg, 1); + ret = i2c_transfer(dev->i2c, msg, 1); if (ret == 1) { ret = 0; } else { - dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + dev_warn(&dev->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -66,28 +66,28 @@ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) } /* read multiple hardware registers */ -static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) +static int rtl2830_rd(struct rtl2830_dev *dev, u8 reg, u8 *val, int len) { int ret; struct i2c_msg msg[2] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 1, .buf = ®, }, { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = I2C_M_RD, .len = len, .buf = val, } }; - ret = i2c_transfer(priv->i2c, msg, 2); + ret = i2c_transfer(dev->i2c, msg, 2); if (ret == 2) { ret = 0; } else { - dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + dev_warn(&dev->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -95,7 +95,7 @@ static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) } /* write multiple registers */ -static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val, +static int rtl2830_wr_regs(struct rtl2830_dev *dev, u16 reg, const u8 *val, int len) { int ret; @@ -103,51 +103,51 @@ static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val, u8 page = (reg >> 8) & 0xff; /* switch bank if needed */ - if (page != priv->page) { - ret = rtl2830_wr(priv, 0x00, &page, 1); + if (page != dev->page) { + ret = rtl2830_wr(dev, 0x00, &page, 1); if (ret) return ret; - priv->page = page; + dev->page = page; } - return rtl2830_wr(priv, reg2, val, len); + return rtl2830_wr(dev, reg2, val, len); } /* read multiple registers */ -static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +static int rtl2830_rd_regs(struct rtl2830_dev *dev, u16 reg, u8 *val, int len) { int ret; u8 reg2 = (reg >> 0) & 0xff; u8 page = (reg >> 8) & 0xff; /* switch bank if needed */ - if (page != priv->page) { - ret = rtl2830_wr(priv, 0x00, &page, 1); + if (page != dev->page) { + ret = rtl2830_wr(dev, 0x00, &page, 1); if (ret) return ret; - priv->page = page; + dev->page = page; } - return rtl2830_rd(priv, reg2, val, len); + return rtl2830_rd(dev, reg2, val, len); } /* read single register */ -static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) +static int rtl2830_rd_reg(struct rtl2830_dev *dev, u16 reg, u8 *val) { - return rtl2830_rd_regs(priv, reg, val, 1); + return rtl2830_rd_regs(dev, reg, val, 1); } /* write single register with mask */ -static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask) +static int rtl2830_wr_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 val, u8 mask) { int ret; u8 tmp; /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = rtl2830_rd_regs(priv, reg, &tmp, 1); + ret = rtl2830_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -156,16 +156,16 @@ static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 ma val |= tmp; } - return rtl2830_wr_regs(priv, reg, &val, 1); + return rtl2830_wr_regs(dev, reg, &val, 1); } /* read single register with mask */ -static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask) +static int rtl2830_rd_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 *val, u8 mask) { int ret, i; u8 tmp; - ret = rtl2830_rd_regs(priv, reg, &tmp, 1); + ret = rtl2830_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -183,7 +183,7 @@ static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 m static int rtl2830_init(struct dvb_frontend *fe) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; int ret, i; struct rtl2830_reg_val_mask tab[] = { { 0x00d, 0x01, 0x03 }, @@ -204,10 +204,10 @@ static int rtl2830_init(struct dvb_frontend *fe) { 0x2f1, 0x20, 0xf8 }, { 0x16d, 0x00, 0x01 }, { 0x1a6, 0x00, 0x80 }, - { 0x106, priv->cfg.vtop, 0x3f }, - { 0x107, priv->cfg.krf, 0x3f }, + { 0x106, dev->cfg.vtop, 0x3f }, + { 0x107, dev->cfg.krf, 0x3f }, { 0x112, 0x28, 0xff }, - { 0x103, priv->cfg.agc_targ_val, 0xff }, + { 0x103, dev->cfg.agc_targ_val, 0xff }, { 0x00a, 0x02, 0x07 }, { 0x140, 0x0c, 0x3c }, { 0x140, 0x40, 0xc0 }, @@ -215,7 +215,7 @@ static int rtl2830_init(struct dvb_frontend *fe) { 0x15b, 0x28, 0x38 }, { 0x15c, 0x05, 0x07 }, { 0x15c, 0x28, 0x38 }, - { 0x115, priv->cfg.spec_inv, 0x01 }, + { 0x115, dev->cfg.spec_inv, 0x01 }, { 0x16f, 0x01, 0x07 }, { 0x170, 0x18, 0x38 }, { 0x172, 0x0f, 0x0f }, @@ -225,17 +225,17 @@ static int rtl2830_init(struct dvb_frontend *fe) }; for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val, + ret = rtl2830_wr_reg_mask(dev, tab[i].reg, tab[i].val, tab[i].mask); if (ret) goto err; } - ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2); + ret = rtl2830_wr_regs(dev, 0x18f, "\x28\x00", 2); if (ret) goto err; - ret = rtl2830_wr_regs(priv, 0x195, + ret = rtl2830_wr_regs(dev, 0x195, "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); if (ret) goto err; @@ -243,26 +243,26 @@ static int rtl2830_init(struct dvb_frontend *fe) /* TODO: spec init */ /* soft reset */ - ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04); + ret = rtl2830_wr_reg_mask(dev, 0x101, 0x04, 0x04); if (ret) goto err; - ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04); + ret = rtl2830_wr_reg_mask(dev, 0x101, 0x00, 0x04); if (ret) goto err; - priv->sleeping = false; + dev->sleeping = false; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2830_sleep(struct dvb_frontend *fe) { - struct rtl2830_priv *priv = fe->demodulator_priv; - priv->sleeping = true; + struct rtl2830_dev *dev = fe->demodulator_priv; + dev->sleeping = true; return 0; } @@ -278,7 +278,7 @@ static int rtl2830_get_tune_settings(struct dvb_frontend *fe, static int rtl2830_set_frontend(struct dvb_frontend *fe) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u64 num; @@ -308,7 +308,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */ }; - dev_dbg(&priv->i2c->dev, + dev_dbg(&dev->i2c->dev, "%s: frequency=%d bandwidth_hz=%d inversion=%d\n", __func__, c->frequency, c->bandwidth_hz, c->inversion); @@ -327,11 +327,11 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) i = 2; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__); + dev_dbg(&dev->i2c->dev, "%s: invalid bandwidth\n", __func__); return -EINVAL; } - ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06); + ret = rtl2830_wr_reg_mask(dev, 0x008, i << 1, 0x06); if (ret) goto err; @@ -344,15 +344,15 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) if (ret < 0) goto err; - num = if_frequency % priv->cfg.xtal; + num = if_frequency % dev->cfg.xtal; num *= 0x400000; - num = div_u64(num, priv->cfg.xtal); + num = div_u64(num, dev->cfg.xtal); num = -num; if_ctl = num & 0x3fffff; - dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n", + dev_dbg(&dev->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n", __func__, if_frequency, if_ctl); - ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ + ret = rtl2830_rd_reg_mask(dev, 0x119, &tmp, 0xc0); /* b[7:6] */ if (ret) goto err; @@ -361,49 +361,49 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) buf[1] = (if_ctl >> 8) & 0xff; buf[2] = (if_ctl >> 0) & 0xff; - ret = rtl2830_wr_regs(priv, 0x119, buf, 3); + ret = rtl2830_wr_regs(dev, 0x119, buf, 3); if (ret) goto err; /* 1/2 split I2C write */ - ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); + ret = rtl2830_wr_regs(dev, 0x11c, &bw_params1[i][0], 17); if (ret) goto err; /* 2/2 split I2C write */ - ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17); + ret = rtl2830_wr_regs(dev, 0x12d, &bw_params1[i][17], 17); if (ret) goto err; - ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6); + ret = rtl2830_wr_regs(dev, 0x19d, bw_params2[i], 6); if (ret) goto err; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2830_get_frontend(struct dvb_frontend *fe) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; - if (priv->sleeping) + if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(priv, 0x33c, buf, 2); + ret = rtl2830_rd_regs(dev, 0x33c, buf, 2); if (ret) goto err; - ret = rtl2830_rd_reg(priv, 0x351, &buf[2]); + ret = rtl2830_rd_reg(dev, 0x351, &buf[2]); if (ret) goto err; - dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); + dev_dbg(&dev->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); switch ((buf[0] >> 2) & 3) { case 0: @@ -493,21 +493,21 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; int ret; u8 tmp; *status = 0; - if (priv->sleeping) + if (dev->sleeping) return 0; - ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ + ret = rtl2830_rd_reg_mask(dev, 0x351, &tmp, 0x78); /* [6:3] */ if (ret) goto err; @@ -521,13 +521,13 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; int ret, hierarchy, constellation; u8 buf[2], tmp; u16 tmp16; @@ -539,12 +539,12 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) { 92888734, 92888734, 95487525, 99770748 }, }; - if (priv->sleeping) + if (dev->sleeping) return 0; /* reports SNR in resolution of 0.1 dB */ - ret = rtl2830_rd_reg(priv, 0x33c, &tmp); + ret = rtl2830_rd_reg(dev, 0x33c, &tmp); if (ret) goto err; @@ -556,7 +556,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) if (hierarchy > HIERARCHY_NUM - 1) goto err; - ret = rtl2830_rd_regs(priv, 0x40c, buf, 2); + ret = rtl2830_rd_regs(dev, 0x40c, buf, 2); if (ret) goto err; @@ -570,20 +570,20 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; int ret; u8 buf[2]; - if (priv->sleeping) + if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(priv, 0x34e, buf, 2); + ret = rtl2830_rd_regs(dev, 0x34e, buf, 2); if (ret) goto err; @@ -591,7 +591,7 @@ static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -603,15 +603,15 @@ static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct rtl2830_priv *priv = fe->demodulator_priv; + struct rtl2830_dev *dev = fe->demodulator_priv; int ret; u8 buf[2]; u16 if_agc_raw, if_agc; - if (priv->sleeping) + if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(priv, 0x359, buf, 2); + ret = rtl2830_rd_regs(dev, 0x359, buf, 2); if (ret) goto err; @@ -627,7 +627,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -675,10 +675,10 @@ static struct dvb_frontend_ops rtl2830_ops = { static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { struct i2c_client *client = mux_priv; - struct rtl2830_priv *priv = i2c_get_clientdata(client); + struct rtl2830_dev *dev = i2c_get_clientdata(client); struct i2c_msg select_reg_page_msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 2, .buf = "\x00\x01", @@ -686,7 +686,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; struct i2c_msg gate_open_msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 2, .buf = "\x01\x08", @@ -703,7 +703,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) goto err; } - priv->page = 1; + dev->page = 1; /* open tuner I2C repeater for 1 xfer, closes automatically */ ret = __i2c_transfer(adap, gate_open_msg, 1); @@ -723,20 +723,20 @@ err: static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) { - struct rtl2830_priv *priv = i2c_get_clientdata(client); + struct rtl2830_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - return &priv->fe; + return &dev->fe; } static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) { - struct rtl2830_priv *priv = i2c_get_clientdata(client); + struct rtl2830_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - return priv->adapter; + return dev->adapter; } static int rtl2830_probe(struct i2c_client *client, @@ -744,7 +744,7 @@ static int rtl2830_probe(struct i2c_client *client, { struct rtl2830_platform_data *pdata = client->dev.platform_data; struct i2c_adapter *i2c = client->adapter; - struct rtl2830_priv *priv; + struct rtl2830_dev *dev; int ret; u8 u8tmp; @@ -756,39 +756,39 @@ static int rtl2830_probe(struct i2c_client *client, } /* allocate memory for the internal state */ - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { ret = -ENOMEM; goto err; } /* setup the state */ - i2c_set_clientdata(client, priv); - priv->i2c = i2c; - priv->sleeping = true; - priv->cfg.i2c_addr = client->addr; - priv->cfg.xtal = pdata->clk; - priv->cfg.spec_inv = pdata->spec_inv; - priv->cfg.vtop = pdata->vtop; - priv->cfg.krf = pdata->krf; - priv->cfg.agc_targ_val = pdata->agc_targ_val; + i2c_set_clientdata(client, dev); + dev->i2c = i2c; + dev->sleeping = true; + dev->cfg.i2c_addr = client->addr; + dev->cfg.xtal = pdata->clk; + dev->cfg.spec_inv = pdata->spec_inv; + dev->cfg.vtop = pdata->vtop; + dev->cfg.krf = pdata->krf; + dev->cfg.agc_targ_val = pdata->agc_targ_val; /* check if the demod is there */ - ret = rtl2830_rd_reg(priv, 0x000, &u8tmp); + ret = rtl2830_rd_reg(dev, 0x000, &u8tmp); if (ret) goto err_kfree; /* create muxed i2c adapter for tuner */ - priv->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, + dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, client, 0, 0, 0, rtl2830_select, NULL); - if (priv->adapter == NULL) { + if (dev->adapter == NULL) { ret = -ENODEV; goto err_kfree; } /* create dvb frontend */ - memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(priv->fe.ops)); - priv->fe.demodulator_priv = priv; + memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops)); + dev->fe.demodulator_priv = dev; /* setup callbacks */ pdata->get_dvb_frontend = rtl2830_get_dvb_frontend; @@ -798,7 +798,7 @@ static int rtl2830_probe(struct i2c_client *client, return 0; err_kfree: - kfree(priv); + kfree(dev); err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -806,12 +806,12 @@ err: static int rtl2830_remove(struct i2c_client *client) { - struct rtl2830_priv *priv = i2c_get_clientdata(client); + struct rtl2830_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - i2c_del_mux_adapter(priv->adapter); - kfree(priv); + i2c_del_mux_adapter(dev->adapter); + kfree(dev); return 0; } diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 545907a3583e..9e7bd4264ac1 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -35,7 +35,7 @@ struct rtl2830_config { u8 agc_targ_val; }; -struct rtl2830_priv { +struct rtl2830_dev { struct i2c_adapter *adapter; struct i2c_adapter *i2c; struct dvb_frontend fe; -- cgit v1.2.3 From 1f153c4d88dd3e35900440608229c0d0335a83fb Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 8 Dec 2014 22:47:21 -0300 Subject: [media] rtl2830: carry pointer to I2C client for every function As a I2C driver struct i2c_client is top level structure representing the driver. Use it as parameter to carry all needed information for each function in order to simplify things. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 97 +++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 44643d9b4322..e7ba6658ac8f 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -31,8 +31,9 @@ #define MAX_XFER_SIZE 64 /* write multiple hardware registers */ -static int rtl2830_wr(struct rtl2830_dev *dev, u8 reg, const u8 *val, int len) +static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) { + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { @@ -66,8 +67,9 @@ static int rtl2830_wr(struct rtl2830_dev *dev, u8 reg, const u8 *val, int len) } /* read multiple hardware registers */ -static int rtl2830_rd(struct rtl2830_dev *dev, u8 reg, u8 *val, int len) +static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) { + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg msg[2] = { { @@ -95,59 +97,60 @@ static int rtl2830_rd(struct rtl2830_dev *dev, u8 reg, u8 *val, int len) } /* write multiple registers */ -static int rtl2830_wr_regs(struct rtl2830_dev *dev, u16 reg, const u8 *val, - int len) +static int rtl2830_wr_regs(struct i2c_client *client, u16 reg, const u8 *val, int len) { + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 reg2 = (reg >> 0) & 0xff; u8 page = (reg >> 8) & 0xff; /* switch bank if needed */ if (page != dev->page) { - ret = rtl2830_wr(dev, 0x00, &page, 1); + ret = rtl2830_wr(client, 0x00, &page, 1); if (ret) return ret; dev->page = page; } - return rtl2830_wr(dev, reg2, val, len); + return rtl2830_wr(client, reg2, val, len); } /* read multiple registers */ -static int rtl2830_rd_regs(struct rtl2830_dev *dev, u16 reg, u8 *val, int len) +static int rtl2830_rd_regs(struct i2c_client *client, u16 reg, u8 *val, int len) { + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 reg2 = (reg >> 0) & 0xff; u8 page = (reg >> 8) & 0xff; /* switch bank if needed */ if (page != dev->page) { - ret = rtl2830_wr(dev, 0x00, &page, 1); + ret = rtl2830_wr(client, 0x00, &page, 1); if (ret) return ret; dev->page = page; } - return rtl2830_rd(dev, reg2, val, len); + return rtl2830_rd(client, reg2, val, len); } /* read single register */ -static int rtl2830_rd_reg(struct rtl2830_dev *dev, u16 reg, u8 *val) +static int rtl2830_rd_reg(struct i2c_client *client, u16 reg, u8 *val) { - return rtl2830_rd_regs(dev, reg, val, 1); + return rtl2830_rd_regs(client, reg, val, 1); } /* write single register with mask */ -static int rtl2830_wr_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 val, u8 mask) +static int rtl2830_wr_reg_mask(struct i2c_client *client, u16 reg, u8 val, u8 mask) { int ret; u8 tmp; /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = rtl2830_rd_regs(dev, reg, &tmp, 1); + ret = rtl2830_rd_regs(client, reg, &tmp, 1); if (ret) return ret; @@ -156,16 +159,16 @@ static int rtl2830_wr_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 val, u8 mask val |= tmp; } - return rtl2830_wr_regs(dev, reg, &val, 1); + return rtl2830_wr_regs(client, reg, &val, 1); } /* read single register with mask */ -static int rtl2830_rd_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 *val, u8 mask) +static int rtl2830_rd_reg_mask(struct i2c_client *client, u16 reg, u8 *val, u8 mask) { int ret, i; u8 tmp; - ret = rtl2830_rd_regs(dev, reg, &tmp, 1); + ret = rtl2830_rd_regs(client, reg, &tmp, 1); if (ret) return ret; @@ -183,7 +186,8 @@ static int rtl2830_rd_reg_mask(struct rtl2830_dev *dev, u16 reg, u8 *val, u8 mas static int rtl2830_init(struct dvb_frontend *fe) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret, i; struct rtl2830_reg_val_mask tab[] = { { 0x00d, 0x01, 0x03 }, @@ -225,17 +229,17 @@ static int rtl2830_init(struct dvb_frontend *fe) }; for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = rtl2830_wr_reg_mask(dev, tab[i].reg, tab[i].val, + ret = rtl2830_wr_reg_mask(client, tab[i].reg, tab[i].val, tab[i].mask); if (ret) goto err; } - ret = rtl2830_wr_regs(dev, 0x18f, "\x28\x00", 2); + ret = rtl2830_wr_regs(client, 0x18f, "\x28\x00", 2); if (ret) goto err; - ret = rtl2830_wr_regs(dev, 0x195, + ret = rtl2830_wr_regs(client, 0x195, "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); if (ret) goto err; @@ -243,11 +247,11 @@ static int rtl2830_init(struct dvb_frontend *fe) /* TODO: spec init */ /* soft reset */ - ret = rtl2830_wr_reg_mask(dev, 0x101, 0x04, 0x04); + ret = rtl2830_wr_reg_mask(client, 0x101, 0x04, 0x04); if (ret) goto err; - ret = rtl2830_wr_reg_mask(dev, 0x101, 0x00, 0x04); + ret = rtl2830_wr_reg_mask(client, 0x101, 0x00, 0x04); if (ret) goto err; @@ -261,7 +265,8 @@ err: static int rtl2830_sleep(struct dvb_frontend *fe) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); dev->sleeping = true; return 0; } @@ -278,7 +283,8 @@ static int rtl2830_get_tune_settings(struct dvb_frontend *fe, static int rtl2830_set_frontend(struct dvb_frontend *fe) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u64 num; @@ -331,7 +337,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) return -EINVAL; } - ret = rtl2830_wr_reg_mask(dev, 0x008, i << 1, 0x06); + ret = rtl2830_wr_reg_mask(client, 0x008, i << 1, 0x06); if (ret) goto err; @@ -352,7 +358,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) dev_dbg(&dev->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n", __func__, if_frequency, if_ctl); - ret = rtl2830_rd_reg_mask(dev, 0x119, &tmp, 0xc0); /* b[7:6] */ + ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */ if (ret) goto err; @@ -361,21 +367,21 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) buf[1] = (if_ctl >> 8) & 0xff; buf[2] = (if_ctl >> 0) & 0xff; - ret = rtl2830_wr_regs(dev, 0x119, buf, 3); + ret = rtl2830_wr_regs(client, 0x119, buf, 3); if (ret) goto err; /* 1/2 split I2C write */ - ret = rtl2830_wr_regs(dev, 0x11c, &bw_params1[i][0], 17); + ret = rtl2830_wr_regs(client, 0x11c, &bw_params1[i][0], 17); if (ret) goto err; /* 2/2 split I2C write */ - ret = rtl2830_wr_regs(dev, 0x12d, &bw_params1[i][17], 17); + ret = rtl2830_wr_regs(client, 0x12d, &bw_params1[i][17], 17); if (ret) goto err; - ret = rtl2830_wr_regs(dev, 0x19d, bw_params2[i], 6); + ret = rtl2830_wr_regs(client, 0x19d, bw_params2[i], 6); if (ret) goto err; @@ -387,7 +393,8 @@ err: static int rtl2830_get_frontend(struct dvb_frontend *fe) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; @@ -395,11 +402,11 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(dev, 0x33c, buf, 2); + ret = rtl2830_rd_regs(client, 0x33c, buf, 2); if (ret) goto err; - ret = rtl2830_rd_reg(dev, 0x351, &buf[2]); + ret = rtl2830_rd_reg(client, 0x351, &buf[2]); if (ret) goto err; @@ -499,6 +506,7 @@ err: static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) { + struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = fe->demodulator_priv; int ret; u8 tmp; @@ -507,7 +515,7 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) if (dev->sleeping) return 0; - ret = rtl2830_rd_reg_mask(dev, 0x351, &tmp, 0x78); /* [6:3] */ + ret = rtl2830_rd_reg_mask(client, 0x351, &tmp, 0x78); /* [6:3] */ if (ret) goto err; @@ -527,7 +535,8 @@ err: static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret, hierarchy, constellation; u8 buf[2], tmp; u16 tmp16; @@ -544,7 +553,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) /* reports SNR in resolution of 0.1 dB */ - ret = rtl2830_rd_reg(dev, 0x33c, &tmp); + ret = rtl2830_rd_reg(client, 0x33c, &tmp); if (ret) goto err; @@ -556,7 +565,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) if (hierarchy > HIERARCHY_NUM - 1) goto err; - ret = rtl2830_rd_regs(dev, 0x40c, buf, 2); + ret = rtl2830_rd_regs(client, 0x40c, buf, 2); if (ret) goto err; @@ -576,14 +585,15 @@ err: static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 buf[2]; if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(dev, 0x34e, buf, 2); + ret = rtl2830_rd_regs(client, 0x34e, buf, 2); if (ret) goto err; @@ -603,7 +613,8 @@ static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct rtl2830_dev *dev = fe->demodulator_priv; + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 buf[2]; u16 if_agc_raw, if_agc; @@ -611,7 +622,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(dev, 0x359, buf, 2); + ret = rtl2830_rd_regs(client, 0x359, buf, 2); if (ret) goto err; @@ -774,7 +785,7 @@ static int rtl2830_probe(struct i2c_client *client, dev->cfg.agc_targ_val = pdata->agc_targ_val; /* check if the demod is there */ - ret = rtl2830_rd_reg(dev, 0x000, &u8tmp); + ret = rtl2830_rd_reg(client, 0x000, &u8tmp); if (ret) goto err_kfree; @@ -788,7 +799,7 @@ static int rtl2830_probe(struct i2c_client *client, /* create dvb frontend */ memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops)); - dev->fe.demodulator_priv = dev; + dev->fe.demodulator_priv = client; /* setup callbacks */ pdata->get_dvb_frontend = rtl2830_get_dvb_frontend; -- cgit v1.2.3 From 7cc39328898151e92eb4ff052150737558bf7887 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 8 Dec 2014 23:32:19 -0300 Subject: [media] rtl2830: fix logging Pass correct device for dev_foo() logging in order to print logs correctly. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 43 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index e7ba6658ac8f..fa73575a6692 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -46,9 +46,8 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) }; if (1 + len > sizeof(buf)) { - dev_warn(&dev->i2c->dev, - "%s: i2c wr reg=%04x: len=%d is too big!\n", - KBUILD_MODNAME, reg, len); + dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n", + reg, len); return -EINVAL; } @@ -59,8 +58,8 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) if (ret == 1) { ret = 0; } else { - dev_warn(&dev->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ - "len=%d\n", KBUILD_MODNAME, ret, reg, len); + dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -89,8 +88,8 @@ static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - dev_warn(&dev->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ - "len=%d\n", KBUILD_MODNAME, ret, reg, len); + dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -259,7 +258,7 @@ static int rtl2830_init(struct dvb_frontend *fe) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -314,9 +313,8 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */ }; - dev_dbg(&dev->i2c->dev, - "%s: frequency=%d bandwidth_hz=%d inversion=%d\n", - __func__, c->frequency, c->bandwidth_hz, c->inversion); + dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n", + c->frequency, c->bandwidth_hz, c->inversion); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -333,7 +331,8 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) i = 2; break; default: - dev_dbg(&dev->i2c->dev, "%s: invalid bandwidth\n", __func__); + dev_err(&client->dev, "invalid bandwidth_hz %u\n", + c->bandwidth_hz); return -EINVAL; } @@ -355,8 +354,8 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) num = div_u64(num, dev->cfg.xtal); num = -num; if_ctl = num & 0x3fffff; - dev_dbg(&dev->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n", - __func__, if_frequency, if_ctl); + dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n", + if_frequency, if_ctl); ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */ if (ret) @@ -387,7 +386,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -410,7 +409,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) if (ret) goto err; - dev_dbg(&dev->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); + dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf); switch ((buf[0] >> 2) & 3) { case 0: @@ -500,7 +499,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -529,7 +528,7 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -579,7 +578,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -601,7 +600,7 @@ static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -638,7 +637,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -728,7 +727,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) return 0; err: - dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } -- cgit v1.2.3 From b8cb50d237ff1590e2b39031e5d7d3e1bcd49c5b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 00:24:13 -0300 Subject: [media] rtl2830: get rid of internal config data Remove internal config and use configuration values directly from the platform data. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 43 ++++++++++++------------------ drivers/media/dvb-frontends/rtl2830_priv.h | 15 +---------- 2 files changed, 18 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index fa73575a6692..ea68c7ef2a71 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -33,12 +33,11 @@ /* write multiple hardware registers */ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) { - struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 1 + len, .buf = buf, @@ -54,7 +53,7 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) buf[0] = reg; memcpy(&buf[1], val, len); - ret = i2c_transfer(dev->i2c, msg, 1); + ret = i2c_transfer(client->adapter, msg, 1); if (ret == 1) { ret = 0; } else { @@ -68,23 +67,22 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) /* read multiple hardware registers */ static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) { - struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; struct i2c_msg msg[2] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 1, .buf = ®, }, { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = I2C_M_RD, .len = len, .buf = val, } }; - ret = i2c_transfer(dev->i2c, msg, 2); + ret = i2c_transfer(client->adapter, msg, 2); if (ret == 2) { ret = 0; } else { @@ -207,10 +205,10 @@ static int rtl2830_init(struct dvb_frontend *fe) { 0x2f1, 0x20, 0xf8 }, { 0x16d, 0x00, 0x01 }, { 0x1a6, 0x00, 0x80 }, - { 0x106, dev->cfg.vtop, 0x3f }, - { 0x107, dev->cfg.krf, 0x3f }, + { 0x106, dev->pdata->vtop, 0x3f }, + { 0x107, dev->pdata->krf, 0x3f }, { 0x112, 0x28, 0xff }, - { 0x103, dev->cfg.agc_targ_val, 0xff }, + { 0x103, dev->pdata->agc_targ_val, 0xff }, { 0x00a, 0x02, 0x07 }, { 0x140, 0x0c, 0x3c }, { 0x140, 0x40, 0xc0 }, @@ -218,7 +216,7 @@ static int rtl2830_init(struct dvb_frontend *fe) { 0x15b, 0x28, 0x38 }, { 0x15c, 0x05, 0x07 }, { 0x15c, 0x28, 0x38 }, - { 0x115, dev->cfg.spec_inv, 0x01 }, + { 0x115, dev->pdata->spec_inv, 0x01 }, { 0x16f, 0x01, 0x07 }, { 0x170, 0x18, 0x38 }, { 0x172, 0x0f, 0x0f }, @@ -349,9 +347,9 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) if (ret < 0) goto err; - num = if_frequency % dev->cfg.xtal; + num = if_frequency % dev->pdata->clk; num *= 0x400000; - num = div_u64(num, dev->cfg.xtal); + num = div_u64(num, dev->pdata->clk); num = -num; if_ctl = num & 0x3fffff; dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n", @@ -506,7 +504,7 @@ err: static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct i2c_client *client = fe->demodulator_priv; - struct rtl2830_dev *dev = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 tmp; *status = 0; @@ -688,7 +686,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) struct rtl2830_dev *dev = i2c_get_clientdata(client); struct i2c_msg select_reg_page_msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 2, .buf = "\x00\x01", @@ -696,7 +694,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; struct i2c_msg gate_open_msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 2, .buf = "\x01\x08", @@ -705,7 +703,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) int ret; /* select register page */ - ret = __i2c_transfer(adap, select_reg_page_msg, 1); + ret = __i2c_transfer(client->adapter, select_reg_page_msg, 1); if (ret != 1) { dev_warn(&client->dev, "i2c write failed %d\n", ret); if (ret >= 0) @@ -716,7 +714,7 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) dev->page = 1; /* open tuner I2C repeater for 1 xfer, closes automatically */ - ret = __i2c_transfer(adap, gate_open_msg, 1); + ret = __i2c_transfer(client->adapter, gate_open_msg, 1); if (ret != 1) { dev_warn(&client->dev, "i2c write failed %d\n", ret); if (ret >= 0) @@ -753,7 +751,6 @@ static int rtl2830_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct rtl2830_platform_data *pdata = client->dev.platform_data; - struct i2c_adapter *i2c = client->adapter; struct rtl2830_dev *dev; int ret; u8 u8tmp; @@ -774,14 +771,8 @@ static int rtl2830_probe(struct i2c_client *client, /* setup the state */ i2c_set_clientdata(client, dev); - dev->i2c = i2c; + dev->pdata = client->dev.platform_data; dev->sleeping = true; - dev->cfg.i2c_addr = client->addr; - dev->cfg.xtal = pdata->clk; - dev->cfg.spec_inv = pdata->spec_inv; - dev->cfg.vtop = pdata->vtop; - dev->cfg.krf = pdata->krf; - dev->cfg.agc_targ_val = pdata->agc_targ_val; /* check if the demod is there */ ret = rtl2830_rd_reg(client, 0x000, &u8tmp); diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 9e7bd4264ac1..5276fb210990 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -26,24 +26,11 @@ #include "rtl2830.h" #include -struct rtl2830_config { - u8 i2c_addr; - u32 xtal; - bool spec_inv; - u8 vtop; - u8 krf; - u8 agc_targ_val; -}; - struct rtl2830_dev { + struct rtl2830_platform_data *pdata; struct i2c_adapter *adapter; - struct i2c_adapter *i2c; struct dvb_frontend fe; - struct rtl2830_config cfg; - struct i2c_adapter tuner_i2c_adapter; - bool sleeping; - u8 page; /* active register page */ }; -- cgit v1.2.3 From 947debb4f2e8aba1d1678b7b5d4753258a0b1513 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 02:31:53 -0300 Subject: [media] rtl2830: style related changes Trivial changes proposed by checkpatch.pl and some more. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 125 ++++++++++++++--------------- drivers/media/dvb-frontends/rtl2830.h | 4 - drivers/media/dvb-frontends/rtl2830_priv.h | 3 - 3 files changed, 60 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index ea68c7ef2a71..8025b19ac36d 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -13,16 +13,6 @@ * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - - -/* - * Driver implements own I2C-adapter for tuner I2C access. That's since chip - * have unusual I2C-gate control which closes gate automatically after each - * I2C transfer. Using own I2C adapter we can workaround that. */ #include "rtl2830_priv.h" @@ -46,7 +36,7 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) if (1 + len > sizeof(buf)) { dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n", - reg, len); + reg, len); return -EINVAL; } @@ -58,9 +48,10 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) ret = 0; } else { dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n", - ret, reg, len); + ret, reg, len); ret = -EREMOTEIO; } + return ret; } @@ -87,9 +78,10 @@ static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) ret = 0; } else { dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n", - ret, reg, len); + ret, reg, len); ret = -EREMOTEIO; } + return ret; } @@ -187,47 +179,47 @@ static int rtl2830_init(struct dvb_frontend *fe) struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret, i; struct rtl2830_reg_val_mask tab[] = { - { 0x00d, 0x01, 0x03 }, - { 0x00d, 0x10, 0x10 }, - { 0x104, 0x00, 0x1e }, - { 0x105, 0x80, 0x80 }, - { 0x110, 0x02, 0x03 }, - { 0x110, 0x08, 0x0c }, - { 0x17b, 0x00, 0x40 }, - { 0x17d, 0x05, 0x0f }, - { 0x17d, 0x50, 0xf0 }, - { 0x18c, 0x08, 0x0f }, - { 0x18d, 0x00, 0xc0 }, - { 0x188, 0x05, 0x0f }, - { 0x189, 0x00, 0xfc }, - { 0x2d5, 0x02, 0x02 }, - { 0x2f1, 0x02, 0x06 }, - { 0x2f1, 0x20, 0xf8 }, - { 0x16d, 0x00, 0x01 }, - { 0x1a6, 0x00, 0x80 }, - { 0x106, dev->pdata->vtop, 0x3f }, - { 0x107, dev->pdata->krf, 0x3f }, - { 0x112, 0x28, 0xff }, - { 0x103, dev->pdata->agc_targ_val, 0xff }, - { 0x00a, 0x02, 0x07 }, - { 0x140, 0x0c, 0x3c }, - { 0x140, 0x40, 0xc0 }, - { 0x15b, 0x05, 0x07 }, - { 0x15b, 0x28, 0x38 }, - { 0x15c, 0x05, 0x07 }, - { 0x15c, 0x28, 0x38 }, - { 0x115, dev->pdata->spec_inv, 0x01 }, - { 0x16f, 0x01, 0x07 }, - { 0x170, 0x18, 0x38 }, - { 0x172, 0x0f, 0x0f }, - { 0x173, 0x08, 0x38 }, - { 0x175, 0x01, 0x07 }, - { 0x176, 0x00, 0xc0 }, + {0x00d, 0x01, 0x03}, + {0x00d, 0x10, 0x10}, + {0x104, 0x00, 0x1e}, + {0x105, 0x80, 0x80}, + {0x110, 0x02, 0x03}, + {0x110, 0x08, 0x0c}, + {0x17b, 0x00, 0x40}, + {0x17d, 0x05, 0x0f}, + {0x17d, 0x50, 0xf0}, + {0x18c, 0x08, 0x0f}, + {0x18d, 0x00, 0xc0}, + {0x188, 0x05, 0x0f}, + {0x189, 0x00, 0xfc}, + {0x2d5, 0x02, 0x02}, + {0x2f1, 0x02, 0x06}, + {0x2f1, 0x20, 0xf8}, + {0x16d, 0x00, 0x01}, + {0x1a6, 0x00, 0x80}, + {0x106, dev->pdata->vtop, 0x3f}, + {0x107, dev->pdata->krf, 0x3f}, + {0x112, 0x28, 0xff}, + {0x103, dev->pdata->agc_targ_val, 0xff}, + {0x00a, 0x02, 0x07}, + {0x140, 0x0c, 0x3c}, + {0x140, 0x40, 0xc0}, + {0x15b, 0x05, 0x07}, + {0x15b, 0x28, 0x38}, + {0x15c, 0x05, 0x07}, + {0x15c, 0x28, 0x38}, + {0x115, dev->pdata->spec_inv, 0x01}, + {0x16f, 0x01, 0x07}, + {0x170, 0x18, 0x38}, + {0x172, 0x0f, 0x0f}, + {0x173, 0x08, 0x38}, + {0x175, 0x01, 0x07}, + {0x176, 0x00, 0xc0}, }; for (i = 0; i < ARRAY_SIZE(tab); i++) { ret = rtl2830_wr_reg_mask(client, tab[i].reg, tab[i].val, - tab[i].mask); + tab[i].mask); if (ret) goto err; } @@ -237,7 +229,7 @@ static int rtl2830_init(struct dvb_frontend *fe) goto err; ret = rtl2830_wr_regs(client, 0x195, - "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); + "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); if (ret) goto err; @@ -264,12 +256,14 @@ static int rtl2830_sleep(struct dvb_frontend *fe) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); + dev->sleeping = true; + return 0; } static int rtl2830_get_tune_settings(struct dvb_frontend *fe, - struct dvb_frontend_tune_settings *s) + struct dvb_frontend_tune_settings *s) { s->min_delay_ms = 500; s->step_size = fe->ops.info.frequency_stepsize * 2; @@ -312,7 +306,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) }; dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n", - c->frequency, c->bandwidth_hz, c->inversion); + c->frequency, c->bandwidth_hz, c->inversion); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -330,7 +324,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) break; default: dev_err(&client->dev, "invalid bandwidth_hz %u\n", - c->bandwidth_hz); + c->bandwidth_hz); return -EINVAL; } @@ -343,8 +337,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); else ret = -EINVAL; - - if (ret < 0) + if (ret) goto err; num = if_frequency % dev->pdata->clk; @@ -353,7 +346,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) num = -num; if_ctl = num & 0x3fffff; dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n", - if_frequency, if_ctl); + if_frequency, if_ctl); ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */ if (ret) @@ -507,6 +500,7 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; u8 tmp; + *status = 0; if (dev->sleeping) @@ -540,9 +534,9 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) #define CONSTELLATION_NUM 3 #define HIERARCHY_NUM 4 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { - { 70705899, 70705899, 70705899, 70705899 }, - { 82433173, 82433173, 87483115, 94445660 }, - { 92888734, 92888734, 95487525, 99770748 }, + {70705899, 70705899, 70705899, 70705899}, + {82433173, 82433173, 87483115, 94445660}, + {92888734, 92888734, 95487525, 99770748}, }; if (dev->sleeping) @@ -605,6 +599,7 @@ err: static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { *ucblocks = 0; + return 0; } @@ -630,7 +625,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) else if_agc = if_agc_raw; - *strength = (u8) (55 - if_agc / 182); + *strength = (u8)(55 - if_agc / 182); *strength |= *strength << 8; return 0; @@ -640,7 +635,7 @@ err: } static struct dvb_frontend_ops rtl2830_ops = { - .delsys = { SYS_DVBT }, + .delsys = {SYS_DVBT}, .info = { .name = "Realtek RTL2830 (DVB-T)", .caps = FE_CAN_FEC_1_2 | @@ -723,7 +718,6 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) } return 0; - err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -748,7 +742,7 @@ static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) } static int rtl2830_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct rtl2830_platform_data *pdata = client->dev.platform_data; struct rtl2830_dev *dev; @@ -796,8 +790,8 @@ static int rtl2830_probe(struct i2c_client *client, pdata->get_i2c_adapter = rtl2830_get_i2c_adapter; dev_info(&client->dev, "Realtek RTL2830 successfully attached\n"); - return 0; + return 0; err_kfree: kfree(dev); err: @@ -813,6 +807,7 @@ static int rtl2830_remove(struct i2c_client *client) i2c_del_mux_adapter(dev->adapter); kfree(dev); + return 0; } diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 1d7784de9c7a..61f784c935be 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -13,15 +13,11 @@ * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef RTL2830_H #define RTL2830_H -#include #include struct rtl2830_platform_data { diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 5276fb210990..5f9973a07fcd 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -13,9 +13,6 @@ * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef RTL2830_PRIV_H -- cgit v1.2.3 From 47b4dbfff1f31686ac74aae7c69dec23b36005d9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 06:14:36 -0300 Subject: [media] rtl2830: implement DVBv5 CNR statistic DVBv5 CNR. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 74 ++++++++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2830_priv.h | 3 ++ 2 files changed, 77 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 8025b19ac36d..c484634a9fc9 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -177,6 +177,7 @@ static int rtl2830_init(struct dvb_frontend *fe) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; int ret, i; struct rtl2830_reg_val_mask tab[] = { {0x00d, 0x01, 0x03}, @@ -244,6 +245,12 @@ static int rtl2830_init(struct dvb_frontend *fe) if (ret) goto err; + /* init stats here in order signal app which stats are supported */ + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + /* start statistics polling */ + schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); + dev->sleeping = false; return ret; @@ -258,6 +265,9 @@ static int rtl2830_sleep(struct dvb_frontend *fe) struct rtl2830_dev *dev = i2c_get_clientdata(client); dev->sleeping = true; + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + dev->fe_status = 0; return 0; } @@ -518,6 +528,8 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) FE_HAS_VITERBI; } + dev->fe_status = *status; + return ret; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -670,6 +682,66 @@ static struct dvb_frontend_ops rtl2830_ops = { .read_signal_strength = rtl2830_read_signal_strength, }; +static void rtl2830_stat_work(struct work_struct *work) +{ + struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work); + struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; + int ret, tmp; + u8 u8tmp, buf[2]; + u16 u16tmp; + + dev_dbg(&client->dev, "\n"); + + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + unsigned hierarchy, constellation; + #define CONSTELLATION_NUM 3 + #define HIERARCHY_NUM 4 + static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { + {70705899, 70705899, 70705899, 70705899}, + {82433173, 82433173, 87483115, 94445660}, + {92888734, 92888734, 95487525, 99770748}, + }; + + ret = rtl2830_rd_reg(client, 0x33c, &u8tmp); + if (ret) + goto err; + + constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ + if (constellation > CONSTELLATION_NUM - 1) + goto err_schedule_delayed_work; + + hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ + if (hierarchy > HIERARCHY_NUM - 1) + goto err_schedule_delayed_work; + + ret = rtl2830_rd_regs(client, 0x40c, buf, 2); + if (ret) + goto err; + + u16tmp = buf[0] << 8 | buf[1] << 0; + if (u16tmp) + tmp = (constant[constellation][hierarchy] - + intlog10(u16tmp)) / ((1 << 24) / 10000); + else + tmp = 0; + + dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp); + + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = tmp; + } else { + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + +err_schedule_delayed_work: + schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); + return; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); +} + /* * I2C gate/repeater logic * We must use unlocked i2c_transfer() here because I2C lock is already taken @@ -765,8 +837,10 @@ static int rtl2830_probe(struct i2c_client *client, /* setup the state */ i2c_set_clientdata(client, dev); + dev->client = client; dev->pdata = client->dev.platform_data; dev->sleeping = true; + INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work); /* check if the demod is there */ ret = rtl2830_rd_reg(client, 0x000, &u8tmp); diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 5f9973a07fcd..7cf316d0d149 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -25,10 +25,13 @@ struct rtl2830_dev { struct rtl2830_platform_data *pdata; + struct i2c_client *client; struct i2c_adapter *adapter; struct dvb_frontend fe; bool sleeping; u8 page; /* active register page */ + struct delayed_work stat_work; + fe_status_t fe_status; }; struct rtl2830_reg_val_mask { -- cgit v1.2.3 From 871f70252b6fef738cda1834200d25e343ce4825 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 08:49:44 -0300 Subject: [media] rtl2830: implement DVBv5 signal strength statistics Estimate signal strength from IF AGC. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index c484634a9fc9..641047b89e05 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -246,6 +246,8 @@ static int rtl2830_init(struct dvb_frontend *fe) goto err; /* init stats here in order signal app which stats are supported */ + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->cnr.len = 1; c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; /* start statistics polling */ @@ -693,6 +695,28 @@ static void rtl2830_stat_work(struct work_struct *work) dev_dbg(&client->dev, "\n"); + /* signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + struct {signed int x:14; } s; + + /* read IF AGC */ + ret = rtl2830_rd_regs(client, 0x359, buf, 2); + if (ret) + goto err; + + u16tmp = buf[0] << 8 | buf[1] << 0; + u16tmp &= 0x3fff; /* [13:0] */ + tmp = s.x = u16tmp; /* 14-bit bin to 2 complement */ + u16tmp = clamp_val(-4 * tmp + 32767, 0x0000, 0xffff); + + dev_dbg(&client->dev, "IF AGC=%d\n", tmp); + + c->strength.stat[0].scale = FE_SCALE_RELATIVE; + c->strength.stat[0].uvalue = u16tmp; + } else { + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + /* CNR */ if (dev->fe_status & FE_HAS_VITERBI) { unsigned hierarchy, constellation; -- cgit v1.2.3 From 5bb11ca5864a2d4a91b0aa972bae7011314fdffc Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 09:45:16 -0300 Subject: [media] rtl2830: implement DVBv5 BER statistic DVBv5 BER. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 25 +++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2830_priv.h | 2 ++ 2 files changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 641047b89e05..147b3a6898e1 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -250,6 +250,10 @@ static int rtl2830_init(struct dvb_frontend *fe) c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->cnr.len = 1; c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.len = 1; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; /* start statistics polling */ schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); @@ -759,6 +763,27 @@ static void rtl2830_stat_work(struct work_struct *work) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } + /* BER */ + if (dev->fe_status & FE_HAS_LOCK) { + ret = rtl2830_rd_regs(client, 0x34e, buf, 2); + if (ret) + goto err; + + u16tmp = buf[0] << 8 | buf[1] << 0; + dev->post_bit_error += u16tmp; + dev->post_bit_count += 1000000; + + dev_dbg(&client->dev, "BER errors=%u total=1000000\n", u16tmp); + + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue = dev->post_bit_count; + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + err_schedule_delayed_work: schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); return; diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 7cf316d0d149..cdcaacfa89c8 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -32,6 +32,8 @@ struct rtl2830_dev { u8 page; /* active register page */ struct delayed_work stat_work; fe_status_t fe_status; + u64 post_bit_error; + u64 post_bit_count; }; struct rtl2830_reg_val_mask { -- cgit v1.2.3 From d512e286512c38e8921317c3a2c772559a91a636 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 10:20:01 -0300 Subject: [media] rtl2830: wrap DVBv5 signal strength to DVBv3 Change legacy DVBv3 signal strength to return values calculated by DVBv5 statistics. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 147b3a6898e1..a02ccdf2fda0 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -623,33 +623,14 @@ static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct i2c_client *client = fe->demodulator_priv; - struct rtl2830_dev *dev = i2c_get_clientdata(client); - int ret; - u8 buf[2]; - u16 if_agc_raw, if_agc; - - if (dev->sleeping) - return 0; - - ret = rtl2830_rd_regs(client, 0x359, buf, 2); - if (ret) - goto err; - - if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - if (if_agc_raw & (1 << 9)) - if_agc = -(~(if_agc_raw - 1) & 0x1ff); + if (c->strength.stat[0].scale == FE_SCALE_RELATIVE) + *strength = c->strength.stat[0].uvalue; else - if_agc = if_agc_raw; - - *strength = (u8)(55 - if_agc / 182); - *strength |= *strength << 8; + *strength = 0; return 0; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static struct dvb_frontend_ops rtl2830_ops = { -- cgit v1.2.3 From f491391cc331921524aed578075e93f622a5e533 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 10:27:32 -0300 Subject: [media] rtl2830: wrap DVBv5 BER to DVBv3 Change legacy DVBv3 read BER to return values calculated by DVBv5 statistics. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 15 ++------------- drivers/media/dvb-frontends/rtl2830_priv.h | 1 + 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index a02ccdf2fda0..0112b3f13a4b 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -596,22 +596,11 @@ static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - int ret; - u8 buf[2]; - - if (dev->sleeping) - return 0; - - ret = rtl2830_rd_regs(client, 0x34e, buf, 2); - if (ret) - goto err; - *ber = buf[0] << 8 | buf[1]; + *ber = (dev->post_bit_error - dev->post_bit_error_prev); + dev->post_bit_error_prev = dev->post_bit_error; return 0; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index cdcaacfa89c8..6636834baf20 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -32,6 +32,7 @@ struct rtl2830_dev { u8 page; /* active register page */ struct delayed_work stat_work; fe_status_t fe_status; + u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ u64 post_bit_error; u64 post_bit_count; }; -- cgit v1.2.3 From 6dcfe3cc2e33ecd04987828ccbf56d6eda9a833f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 10:48:10 -0300 Subject: [media] rtl2830: wrap DVBv5 CNR to DVBv3 SNR Change legacy DVBv3 read SNR to return values calculated by DVBv5 statistics. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 44 ++---------------------------- drivers/media/dvb-frontends/rtl2830_priv.h | 1 + 2 files changed, 4 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 0112b3f13a4b..f1f1cfb6cb16 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -544,52 +544,14 @@ err: static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct i2c_client *client = fe->demodulator_priv; - struct rtl2830_dev *dev = i2c_get_clientdata(client); - int ret, hierarchy, constellation; - u8 buf[2], tmp; - u16 tmp16; -#define CONSTELLATION_NUM 3 -#define HIERARCHY_NUM 4 - static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { - {70705899, 70705899, 70705899, 70705899}, - {82433173, 82433173, 87483115, 94445660}, - {92888734, 92888734, 95487525, 99770748}, - }; - - if (dev->sleeping) - return 0; - - /* reports SNR in resolution of 0.1 dB */ - - ret = rtl2830_rd_reg(client, 0x33c, &tmp); - if (ret) - goto err; - - constellation = (tmp >> 2) & 0x03; /* [3:2] */ - if (constellation > CONSTELLATION_NUM - 1) - goto err; - - hierarchy = (tmp >> 4) & 0x07; /* [6:4] */ - if (hierarchy > HIERARCHY_NUM - 1) - goto err; - - ret = rtl2830_rd_regs(client, 0x40c, buf, 2); - if (ret) - goto err; - - tmp16 = buf[0] << 8 | buf[1]; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - if (tmp16) - *snr = (snr_constant[constellation][hierarchy] - - intlog10(tmp16)) / ((1 << 24) / 100); + if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) + *snr = div_s64(c->cnr.stat[0].svalue, 100); else *snr = 0; return 0; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 6636834baf20..6a0e982584f3 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -22,6 +22,7 @@ #include "dvb_math.h" #include "rtl2830.h" #include +#include struct rtl2830_dev { struct rtl2830_platform_data *pdata; -- cgit v1.2.3 From df70ddad81b47c57bcccffc805fbd75f2f1b2dc6 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 16:08:44 -0300 Subject: [media] rtl2830: implement PID filter Implement PID filter. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 67 ++++++++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2830.h | 2 + drivers/media/dvb-frontends/rtl2830_priv.h | 1 + 3 files changed, 70 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index f1f1cfb6cb16..8abaca66e132 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -723,6 +723,71 @@ err: dev_dbg(&client->dev, "failed=%d\n", ret); } +static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct i2c_client *client = fe->demodulator_priv; + int ret; + u8 u8tmp; + + dev_dbg(&client->dev, "onoff=%d\n", onoff); + + /* enable / disable PID filter */ + if (onoff) + u8tmp = 0x80; + else + u8tmp = 0x00; + + ret = rtl2830_wr_reg_mask(client, 0x061, u8tmp, 0x80); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int onoff) +{ + struct i2c_client *client = fe->demodulator_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); + int ret; + u8 buf[4]; + + dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n", + index, pid, onoff); + + /* skip invalid PIDs (0x2000) */ + if (pid > 0x1fff || index > 32) + return 0; + + if (onoff) + set_bit(index, &dev->filters); + else + clear_bit(index, &dev->filters); + + /* enable / disable PIDs */ + buf[0] = (dev->filters >> 0) & 0xff; + buf[1] = (dev->filters >> 8) & 0xff; + buf[2] = (dev->filters >> 16) & 0xff; + buf[3] = (dev->filters >> 24) & 0xff; + ret = rtl2830_wr_regs(client, 0x062, buf, 4); + if (ret) + goto err; + + /* add PID */ + buf[0] = (pid >> 8) & 0xff; + buf[1] = (pid >> 0) & 0xff; + ret = rtl2830_wr_regs(client, 0x066 + 2 * index, buf, 2); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + /* * I2C gate/repeater logic * We must use unlocked i2c_transfer() here because I2C lock is already taken @@ -843,6 +908,8 @@ static int rtl2830_probe(struct i2c_client *client, /* setup callbacks */ pdata->get_dvb_frontend = rtl2830_get_dvb_frontend; pdata->get_i2c_adapter = rtl2830_get_i2c_adapter; + pdata->pid_filter = rtl2830_pid_filter; + pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl; dev_info(&client->dev, "Realtek RTL2830 successfully attached\n"); diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 61f784c935be..156edf714f9f 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -49,6 +49,8 @@ struct rtl2830_platform_data { */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); + int (*pid_filter)(struct dvb_frontend *, u8, u16, int); + int (*pid_filter_ctrl)(struct dvb_frontend *, int); }; #endif /* RTL2830_H */ diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 6a0e982584f3..293188924f51 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -31,6 +31,7 @@ struct rtl2830_dev { struct dvb_frontend fe; bool sleeping; u8 page; /* active register page */ + unsigned long filters; struct delayed_work stat_work; fe_status_t fe_status; u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ -- cgit v1.2.3 From d9bd3fa6ec9efbfb0dadc7ba86848604fbebfc4b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 16:10:14 -0300 Subject: [media] rtl28xxu: add support for RTL2831U/RTL2830 PID filter RTL2830 demod integrated to RTL2831U has PID filter. PID filtering is provided by rtl2830 demod driver. Add support for it. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index fcb5c36bc1ea..fa76ad2ac214 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1569,6 +1569,24 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, #define rtl2832u_get_rc_config NULL #endif +static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + + return pdata->pid_filter_ctrl(adap->fe[0], onoff); +} + +static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + + return pdata->pid_filter(adap->fe[0], index, pid, onoff); +} + static const struct dvb_usb_device_properties rtl2831u_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, @@ -1587,6 +1605,13 @@ static const struct dvb_usb_device_properties rtl2831u_props = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl, + .pid_filter = rtl28xxu_pid_filter, + .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, }, -- cgit v1.2.3 From fd4cfa8bb1bc0cdd385f33303b5058674ea8e24c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 9 Dec 2014 16:14:41 -0300 Subject: [media] rtl2830: implement own I2C locking Own I2C locking is needed due to two special reasons: 1) Chips uses multiple register pages/banks on single I2C slave. Page is changed via I2C register access. 2) Chip offers muxed/gated I2C adapter for tuner. Gate/mux is controlled by I2C register access. Due to these reasons, I2C locking did not fit very well. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 45 +++++++++++++++++++++++++----- drivers/media/dvb-frontends/rtl2830_priv.h | 1 + 2 files changed, 39 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 8abaca66e132..3a9e4e986fc2 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -43,7 +43,7 @@ static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) buf[0] = reg; memcpy(&buf[1], val, len); - ret = i2c_transfer(client->adapter, msg, 1); + ret = __i2c_transfer(client->adapter, msg, 1); if (ret == 1) { ret = 0; } else { @@ -73,7 +73,7 @@ static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) } }; - ret = i2c_transfer(client->adapter, msg, 2); + ret = __i2c_transfer(client->adapter, msg, 2); if (ret == 2) { ret = 0; } else { @@ -93,16 +93,23 @@ static int rtl2830_wr_regs(struct i2c_client *client, u16 reg, const u8 *val, in u8 reg2 = (reg >> 0) & 0xff; u8 page = (reg >> 8) & 0xff; + mutex_lock(&dev->i2c_mutex); + /* switch bank if needed */ if (page != dev->page) { ret = rtl2830_wr(client, 0x00, &page, 1); if (ret) - return ret; + goto err_mutex_unlock; dev->page = page; } - return rtl2830_wr(client, reg2, val, len); + ret = rtl2830_wr(client, reg2, val, len); + +err_mutex_unlock: + mutex_unlock(&dev->i2c_mutex); + + return ret; } /* read multiple registers */ @@ -113,16 +120,23 @@ static int rtl2830_rd_regs(struct i2c_client *client, u16 reg, u8 *val, int len) u8 reg2 = (reg >> 0) & 0xff; u8 page = (reg >> 8) & 0xff; + mutex_lock(&dev->i2c_mutex); + /* switch bank if needed */ if (page != dev->page) { ret = rtl2830_wr(client, 0x00, &page, 1); if (ret) - return ret; + goto err_mutex_unlock; dev->page = page; } - return rtl2830_rd(client, reg2, val, len); + ret = rtl2830_rd(client, reg2, val, len); + +err_mutex_unlock: + mutex_unlock(&dev->i2c_mutex); + + return ret; } /* read single register */ @@ -815,6 +829,10 @@ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; int ret; + dev_dbg(&client->dev, "\n"); + + mutex_lock(&dev->i2c_mutex); + /* select register page */ ret = __i2c_transfer(client->adapter, select_reg_page_msg, 1); if (ret != 1) { @@ -841,6 +859,18 @@ err: return ret; } +static int rtl2830_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) +{ + struct i2c_client *client = mux_priv; + struct rtl2830_dev *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + + mutex_unlock(&dev->i2c_mutex); + + return 0; +} + static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) { struct rtl2830_dev *dev = i2c_get_clientdata(client); @@ -886,6 +916,7 @@ static int rtl2830_probe(struct i2c_client *client, dev->client = client; dev->pdata = client->dev.platform_data; dev->sleeping = true; + mutex_init(&dev->i2c_mutex); INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work); /* check if the demod is there */ @@ -895,7 +926,7 @@ static int rtl2830_probe(struct i2c_client *client, /* create muxed i2c adapter for tuner */ dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, - client, 0, 0, 0, rtl2830_select, NULL); + client, 0, 0, 0, rtl2830_select, rtl2830_deselect); if (dev->adapter == NULL) { ret = -ENODEV; goto err_kfree; diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 293188924f51..517758ab687a 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -30,6 +30,7 @@ struct rtl2830_dev { struct i2c_adapter *adapter; struct dvb_frontend fe; bool sleeping; + struct mutex i2c_mutex; u8 page; /* active register page */ unsigned long filters; struct delayed_work stat_work; -- cgit v1.2.3 From 15d37f382469b1f35a9fb97f839eb3122ef7bc98 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 12 Dec 2014 01:03:51 -0300 Subject: [media] rtl2830: convert to regmap API Use regmap to cover register access routines. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/Kconfig | 1 + drivers/media/dvb-frontends/rtl2830.c | 415 +++++++++++++---------------- drivers/media/dvb-frontends/rtl2830_priv.h | 4 +- 3 files changed, 182 insertions(+), 238 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index e8827fc1ca11..0e1263456922 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -444,6 +444,7 @@ config DVB_CXD2820R config DVB_RTL2830 tristate "Realtek RTL2830 DVB-T" depends on DVB_CORE && I2C && I2C_MUX + select REGMAP default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 3a9e4e986fc2..a90f155daadf 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -17,176 +17,43 @@ #include "rtl2830_priv.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 - -/* write multiple hardware registers */ -static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len) +/* Our regmap is bypassing I2C adapter lock, thus we do it! */ +int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, + const void *val, size_t val_count) { + struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; - u8 buf[MAX_XFER_SIZE]; - struct i2c_msg msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = 1 + len, - .buf = buf, - } - }; - - if (1 + len > sizeof(buf)) { - dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n", - reg, len); - return -EINVAL; - } - - buf[0] = reg; - memcpy(&buf[1], val, len); - - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret == 1) { - ret = 0; - } else { - dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n", - ret, reg, len); - ret = -EREMOTEIO; - } + i2c_lock_adapter(client->adapter); + ret = regmap_bulk_write(dev->regmap, reg, val, val_count); + i2c_unlock_adapter(client->adapter); return ret; } -/* read multiple hardware registers */ -static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len) -{ - int ret; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = ®, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = len, - .buf = val, - } - }; - - ret = __i2c_transfer(client->adapter, msg, 2); - if (ret == 2) { - ret = 0; - } else { - dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n", - ret, reg, len); - ret = -EREMOTEIO; - } - - return ret; -} - -/* write multiple registers */ -static int rtl2830_wr_regs(struct i2c_client *client, u16 reg, const u8 *val, int len) +int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, + unsigned int mask, unsigned int val) { struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 page = (reg >> 8) & 0xff; - - mutex_lock(&dev->i2c_mutex); - - /* switch bank if needed */ - if (page != dev->page) { - ret = rtl2830_wr(client, 0x00, &page, 1); - if (ret) - goto err_mutex_unlock; - - dev->page = page; - } - - ret = rtl2830_wr(client, reg2, val, len); - -err_mutex_unlock: - mutex_unlock(&dev->i2c_mutex); + i2c_lock_adapter(client->adapter); + ret = regmap_update_bits(dev->regmap, reg, mask, val); + i2c_unlock_adapter(client->adapter); return ret; } -/* read multiple registers */ -static int rtl2830_rd_regs(struct i2c_client *client, u16 reg, u8 *val, int len) +int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg, void *val, + size_t val_count) { struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 page = (reg >> 8) & 0xff; - - mutex_lock(&dev->i2c_mutex); - - /* switch bank if needed */ - if (page != dev->page) { - ret = rtl2830_wr(client, 0x00, &page, 1); - if (ret) - goto err_mutex_unlock; - - dev->page = page; - } - - ret = rtl2830_rd(client, reg2, val, len); - -err_mutex_unlock: - mutex_unlock(&dev->i2c_mutex); + i2c_lock_adapter(client->adapter); + ret = regmap_bulk_read(dev->regmap, reg, val, val_count); + i2c_unlock_adapter(client->adapter); return ret; } -/* read single register */ -static int rtl2830_rd_reg(struct i2c_client *client, u16 reg, u8 *val) -{ - return rtl2830_rd_regs(client, reg, val, 1); -} - -/* write single register with mask */ -static int rtl2830_wr_reg_mask(struct i2c_client *client, u16 reg, u8 val, u8 mask) -{ - int ret; - u8 tmp; - - /* no need for read if whole reg is written */ - if (mask != 0xff) { - ret = rtl2830_rd_regs(client, reg, &tmp, 1); - if (ret) - return ret; - - val &= mask; - tmp &= ~mask; - val |= tmp; - } - - return rtl2830_wr_regs(client, reg, &val, 1); -} - -/* read single register with mask */ -static int rtl2830_rd_reg_mask(struct i2c_client *client, u16 reg, u8 *val, u8 mask) -{ - int ret, i; - u8 tmp; - - ret = rtl2830_rd_regs(client, reg, &tmp, 1); - if (ret) - return ret; - - tmp &= mask; - - /* find position of the first bit */ - for (i = 0; i < 8; i++) { - if ((mask >> i) & 0x01) - break; - } - *val = tmp >> i; - - return 0; -} - static int rtl2830_init(struct dvb_frontend *fe) { struct i2c_client *client = fe->demodulator_priv; @@ -233,29 +100,29 @@ static int rtl2830_init(struct dvb_frontend *fe) }; for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = rtl2830_wr_reg_mask(client, tab[i].reg, tab[i].val, - tab[i].mask); + ret = rtl2830_update_bits(client, tab[i].reg, tab[i].mask, + tab[i].val); if (ret) goto err; } - ret = rtl2830_wr_regs(client, 0x18f, "\x28\x00", 2); + ret = rtl2830_bulk_write(client, 0x18f, "\x28\x00", 2); if (ret) goto err; - ret = rtl2830_wr_regs(client, 0x195, - "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); + ret = rtl2830_bulk_write(client, 0x195, + "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); if (ret) goto err; /* TODO: spec init */ /* soft reset */ - ret = rtl2830_wr_reg_mask(client, 0x101, 0x04, 0x04); + ret = rtl2830_update_bits(client, 0x101, 0x04, 0x04); if (ret) goto err; - ret = rtl2830_wr_reg_mask(client, 0x101, 0x00, 0x04); + ret = rtl2830_update_bits(client, 0x101, 0x04, 0x00); if (ret) goto err; @@ -309,7 +176,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u64 num; - u8 buf[3], tmp; + u8 buf[3], u8tmp; u32 if_ctl, if_frequency; static const u8 bw_params1[3][34] = { { @@ -358,7 +225,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) return -EINVAL; } - ret = rtl2830_wr_reg_mask(client, 0x008, i << 1, 0x06); + ret = rtl2830_update_bits(client, 0x008, 0x06, i << 1); if (ret) goto err; @@ -378,30 +245,31 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n", if_frequency, if_ctl); - ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */ + buf[0] = (if_ctl >> 16) & 0x3f; + buf[1] = (if_ctl >> 8) & 0xff; + buf[2] = (if_ctl >> 0) & 0xff; + + ret = rtl2830_bulk_read(client, 0x119, &u8tmp, 1); if (ret) goto err; - buf[0] = tmp << 6; - buf[0] |= (if_ctl >> 16) & 0x3f; - buf[1] = (if_ctl >> 8) & 0xff; - buf[2] = (if_ctl >> 0) & 0xff; + buf[0] |= u8tmp & 0xc0; /* [7:6] */ - ret = rtl2830_wr_regs(client, 0x119, buf, 3); + ret = rtl2830_bulk_write(client, 0x119, buf, 3); if (ret) goto err; /* 1/2 split I2C write */ - ret = rtl2830_wr_regs(client, 0x11c, &bw_params1[i][0], 17); + ret = rtl2830_bulk_write(client, 0x11c, &bw_params1[i][0], 17); if (ret) goto err; /* 2/2 split I2C write */ - ret = rtl2830_wr_regs(client, 0x12d, &bw_params1[i][17], 17); + ret = rtl2830_bulk_write(client, 0x12d, &bw_params1[i][17], 17); if (ret) goto err; - ret = rtl2830_wr_regs(client, 0x19d, bw_params2[i], 6); + ret = rtl2830_bulk_write(client, 0x19d, bw_params2[i], 6); if (ret) goto err; @@ -422,11 +290,11 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) if (dev->sleeping) return 0; - ret = rtl2830_rd_regs(client, 0x33c, buf, 2); + ret = rtl2830_bulk_read(client, 0x33c, buf, 2); if (ret) goto err; - ret = rtl2830_rd_reg(client, 0x351, &buf[2]); + ret = rtl2830_bulk_read(client, 0x351, &buf[2], 1); if (ret) goto err; @@ -529,21 +397,22 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; - u8 tmp; + u8 u8tmp; *status = 0; if (dev->sleeping) return 0; - ret = rtl2830_rd_reg_mask(client, 0x351, &tmp, 0x78); /* [6:3] */ + ret = rtl2830_bulk_read(client, 0x351, &u8tmp, 1); if (ret) goto err; - if (tmp == 11) { + u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */ + if (u8tmp == 11) { *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - } else if (tmp == 10) { + } else if (u8tmp == 10) { *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI; } @@ -650,7 +519,7 @@ static void rtl2830_stat_work(struct work_struct *work) struct {signed int x:14; } s; /* read IF AGC */ - ret = rtl2830_rd_regs(client, 0x359, buf, 2); + ret = rtl2830_bulk_read(client, 0x359, buf, 2); if (ret) goto err; @@ -678,7 +547,7 @@ static void rtl2830_stat_work(struct work_struct *work) {92888734, 92888734, 95487525, 99770748}, }; - ret = rtl2830_rd_reg(client, 0x33c, &u8tmp); + ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1); if (ret) goto err; @@ -690,7 +559,7 @@ static void rtl2830_stat_work(struct work_struct *work) if (hierarchy > HIERARCHY_NUM - 1) goto err_schedule_delayed_work; - ret = rtl2830_rd_regs(client, 0x40c, buf, 2); + ret = rtl2830_bulk_read(client, 0x40c, buf, 2); if (ret) goto err; @@ -711,7 +580,7 @@ static void rtl2830_stat_work(struct work_struct *work) /* BER */ if (dev->fe_status & FE_HAS_LOCK) { - ret = rtl2830_rd_regs(client, 0x34e, buf, 2); + ret = rtl2830_bulk_read(client, 0x34e, buf, 2); if (ret) goto err; @@ -751,7 +620,7 @@ static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) else u8tmp = 0x00; - ret = rtl2830_wr_reg_mask(client, 0x061, u8tmp, 0x80); + ret = rtl2830_update_bits(client, 0x061, 0x80, u8tmp); if (ret) goto err; @@ -785,14 +654,14 @@ static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int on buf[1] = (dev->filters >> 8) & 0xff; buf[2] = (dev->filters >> 16) & 0xff; buf[3] = (dev->filters >> 24) & 0xff; - ret = rtl2830_wr_regs(client, 0x062, buf, 4); + ret = rtl2830_bulk_write(client, 0x062, buf, 4); if (ret) goto err; /* add PID */ buf[0] = (pid >> 8) & 0xff; buf[1] = (pid >> 0) & 0xff; - ret = rtl2830_wr_regs(client, 0x066 + 2 * index, buf, 2); + ret = rtl2830_bulk_write(client, 0x066 + 2 * index, buf, 2); if (ret) goto err; @@ -803,55 +672,24 @@ err: } /* - * I2C gate/repeater logic - * We must use unlocked i2c_transfer() here because I2C lock is already taken - * by tuner driver. Gate is closed automatically after single I2C xfer. + * I2C gate/mux/repeater logic + * We must use unlocked __i2c_transfer() here (through regmap) because of I2C + * adapter lock is already taken by tuner driver. + * Gate is closed automatically after single I2C transfer. */ static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { struct i2c_client *client = mux_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - struct i2c_msg select_reg_page_msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = 2, - .buf = "\x00\x01", - } - }; - struct i2c_msg gate_open_msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = 2, - .buf = "\x01\x08", - } - }; int ret; dev_dbg(&client->dev, "\n"); - mutex_lock(&dev->i2c_mutex); - - /* select register page */ - ret = __i2c_transfer(client->adapter, select_reg_page_msg, 1); - if (ret != 1) { - dev_warn(&client->dev, "i2c write failed %d\n", ret); - if (ret >= 0) - ret = -EREMOTEIO; + /* open I2C repeater for 1 transfer, closes automatically */ + /* XXX: regmap_update_bits() does not lock I2C adapter */ + ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08); + if (ret) goto err; - } - - dev->page = 1; - - /* open tuner I2C repeater for 1 xfer, closes automatically */ - ret = __i2c_transfer(client->adapter, gate_open_msg, 1); - if (ret != 1) { - dev_warn(&client->dev, "i2c write failed %d\n", ret); - if (ret >= 0) - ret = -EREMOTEIO; - goto err; - } return 0; err: @@ -859,34 +697,107 @@ err: return ret; } -static int rtl2830_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) +static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) { - struct i2c_client *client = mux_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - mutex_unlock(&dev->i2c_mutex); - - return 0; + return &dev->fe; } -static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) +static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) { struct rtl2830_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - return &dev->fe; + return dev->adapter; } -static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) +/* + * We implement own I2C access routines for regmap in order to get manual access + * to I2C adapter lock, which is needed for I2C mux adapter. + */ +static int rtl2830_regmap_read(void *context, const void *reg_buf, + size_t reg_size, void *val_buf, size_t val_size) { - struct rtl2830_dev *dev = i2c_get_clientdata(client); + struct i2c_client *client = context; + int ret; + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = reg_size, + .buf = (u8 *)reg_buf, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = val_size, + .buf = val_buf, + } + }; - dev_dbg(&client->dev, "\n"); + ret = __i2c_transfer(client->adapter, msg, 2); + if (ret != 2) { + dev_warn(&client->dev, "i2c reg read failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; +} - return dev->adapter; +static int rtl2830_regmap_write(void *context, const void *data, size_t count) +{ + struct i2c_client *client = context; + int ret; + struct i2c_msg msg[1] = { + { + .addr = client->addr, + .flags = 0, + .len = count, + .buf = (u8 *)data, + } + }; + + ret = __i2c_transfer(client->adapter, msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; +} + +static int rtl2830_regmap_gather_write(void *context, const void *reg, + size_t reg_len, const void *val, + size_t val_len) +{ + struct i2c_client *client = context; + int ret; + u8 buf[256]; + struct i2c_msg msg[1] = { + { + .addr = client->addr, + .flags = 0, + .len = 1 + val_len, + .buf = buf, + } + }; + + buf[0] = *(u8 const *)reg; + memcpy(&buf[1], val, val_len); + + ret = __i2c_transfer(client->adapter, msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; } static int rtl2830_probe(struct i2c_client *client, @@ -896,6 +807,30 @@ static int rtl2830_probe(struct i2c_client *client, struct rtl2830_dev *dev; int ret; u8 u8tmp; + static const struct regmap_bus regmap_bus = { + .read = rtl2830_regmap_read, + .write = rtl2830_regmap_write, + .gather_write = rtl2830_regmap_gather_write, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, + }; + static const struct regmap_range_cfg regmap_range_cfg[] = { + { + .selector_reg = 0x00, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + .range_min = 0 * 0x100, + .range_max = 5 * 0x100, + }, + }; + static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 5 * 0x100, + .ranges = regmap_range_cfg, + .num_ranges = ARRAY_SIZE(regmap_range_cfg), + }; dev_dbg(&client->dev, "\n"); @@ -916,20 +851,25 @@ static int rtl2830_probe(struct i2c_client *client, dev->client = client; dev->pdata = client->dev.platform_data; dev->sleeping = true; - mutex_init(&dev->i2c_mutex); INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work); + dev->regmap = regmap_init(&client->dev, ®map_bus, client, + ®map_config); + if (IS_ERR(dev->regmap)) { + ret = PTR_ERR(dev->regmap); + goto err_kfree; + } /* check if the demod is there */ - ret = rtl2830_rd_reg(client, 0x000, &u8tmp); + ret = rtl2830_bulk_read(client, 0x000, &u8tmp, 1); if (ret) - goto err_kfree; + goto err_regmap_exit; /* create muxed i2c adapter for tuner */ dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, - client, 0, 0, 0, rtl2830_select, rtl2830_deselect); + client, 0, 0, 0, rtl2830_select, NULL); if (dev->adapter == NULL) { ret = -ENODEV; - goto err_kfree; + goto err_regmap_exit; } /* create dvb frontend */ @@ -945,6 +885,8 @@ static int rtl2830_probe(struct i2c_client *client, dev_info(&client->dev, "Realtek RTL2830 successfully attached\n"); return 0; +err_regmap_exit: + regmap_exit(dev->regmap); err_kfree: kfree(dev); err: @@ -959,6 +901,7 @@ static int rtl2830_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); i2c_del_mux_adapter(dev->adapter); + regmap_exit(dev->regmap); kfree(dev); return 0; diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 517758ab687a..d50d5376c9c5 100644 --- a/drivers/media/dvb-frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -23,15 +23,15 @@ #include "rtl2830.h" #include #include +#include struct rtl2830_dev { struct rtl2830_platform_data *pdata; struct i2c_client *client; + struct regmap *regmap; struct i2c_adapter *adapter; struct dvb_frontend fe; bool sleeping; - struct mutex i2c_mutex; - u8 page; /* active register page */ unsigned long filters; struct delayed_work stat_work; fe_status_t fe_status; -- cgit v1.2.3 From 6f5f6ee24ea3a27f0ed3655c2051691bceb8beec Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 12 Dec 2014 23:16:19 -0300 Subject: [media] rtl2832: add platform data callbacks for exported resources Add callback for all of those functions which are currently exported using EXPORT_SYMBOL. That allows us convert every user to callbacks and eventually all exported symbols could be removed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 90 +++++++++++++++++++++++++++++++---- drivers/media/dvb-frontends/rtl2832.h | 7 +++ 2 files changed, 89 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 53b446afe030..8c36a8415c4c 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1183,6 +1183,80 @@ static struct dvb_frontend_ops rtl2832_ops = { .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, }; +static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) +{ + struct rtl2832_priv *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + return &dev->fe; +} + +static struct i2c_adapter *rtl2832_get_i2c_adapter_(struct i2c_client *client) +{ + struct rtl2832_priv *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + return dev->i2c_adapter_tuner; +} + +static struct i2c_adapter *rtl2832_get_private_i2c_adapter_(struct i2c_client *client) +{ + struct rtl2832_priv *dev = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "\n"); + return dev->i2c_adapter; +} + +static int rtl2832_enable_slave_ts(struct i2c_client *client) +{ + struct rtl2832_priv *dev = i2c_get_clientdata(client); + int ret; + + dev_dbg(&client->dev, "setting PIP mode\n"); + + ret = rtl2832_wr_regs(dev, 0x0c, 1, "\x5f\xff", 2); + if (ret) + goto err; + + ret = rtl2832_wr_demod_reg(dev, DVBT_PIP_ON, 0x1); + if (ret) + goto err; + + ret = rtl2832_wr_reg(dev, 0xbc, 0, 0x18); + if (ret) + goto err; + + ret = rtl2832_wr_reg(dev, 0x22, 0, 0x01); + if (ret) + goto err; + + ret = rtl2832_wr_reg(dev, 0x26, 0, 0x1f); + if (ret) + goto err; + + ret = rtl2832_wr_reg(dev, 0x27, 0, 0xff); + if (ret) + goto err; + + ret = rtl2832_wr_regs(dev, 0x92, 1, "\x7f\xf7\xff", 3); + if (ret) + goto err; + + /* soft reset */ + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1); + if (ret) + goto err; + + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + static int rtl2832_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1195,13 +1269,6 @@ static int rtl2832_probe(struct i2c_client *client, dev_dbg(&client->dev, "\n"); - /* Caller really need to provide pointer for frontend we create. */ - if (pdata->dvb_frontend == NULL) { - dev_err(&client->dev, "frontend pointer not defined\n"); - ret = -EINVAL; - goto err; - } - /* allocate memory for the internal state */ priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); if (priv == NULL) { @@ -1243,7 +1310,14 @@ static int rtl2832_probe(struct i2c_client *client, priv->fe.ops.release = NULL; priv->fe.demodulator_priv = priv; i2c_set_clientdata(client, priv); - *pdata->dvb_frontend = &priv->fe; + if (pdata->dvb_frontend) + *pdata->dvb_frontend = &priv->fe; + + /* setup callbacks */ + pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; + pdata->get_i2c_adapter = rtl2832_get_i2c_adapter_; + pdata->get_private_i2c_adapter = rtl2832_get_private_i2c_adapter_; + pdata->enable_slave_ts = rtl2832_enable_slave_ts; dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); return 0; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index cfd69d8a9a81..dbc4d3ca5d37 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -58,6 +58,13 @@ struct rtl2832_platform_data { * returned by driver */ struct dvb_frontend **dvb_frontend; + + /* + */ + struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); + struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); + struct i2c_adapter* (*get_private_i2c_adapter)(struct i2c_client *); + int (*enable_slave_ts)(struct i2c_client *); }; #if IS_ENABLED(CONFIG_DVB_RTL2832) -- cgit v1.2.3 From 77a2e76b8505c2ed00db4925c22bfcde2be701a4 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 00:09:57 -0300 Subject: [media] rtl28xxu: use rtl2832 demod callbacks accessing its resources Switch demod resource use from exported symbols to callbacks its provides. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 39 +++++++++++++++++---------------- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 5 ++++- 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index fa76ad2ac214..3d619def7066 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -782,36 +782,35 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) { - int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_platform_data platform_data; - const struct rtl2832_config *rtl2832_config; - struct i2c_board_info board_info = {}; + struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + struct i2c_board_info board_info; struct i2c_client *client; + int ret; dev_dbg(&d->udev->dev, "%s:\n", __func__); switch (priv->tuner) { case TUNER_RTL2832_FC0012: - rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; + pdata->config = &rtl28xxu_rtl2832_fc0012_config; break; case TUNER_RTL2832_FC0013: - rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; + pdata->config = &rtl28xxu_rtl2832_fc0013_config; break; case TUNER_RTL2832_FC2580: /* FIXME: do not abuse fc0012 settings */ - rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; + pdata->config = &rtl28xxu_rtl2832_fc0012_config; break; case TUNER_RTL2832_TUA9001: - rtl2832_config = &rtl28xxu_rtl2832_tua9001_config; + pdata->config = &rtl28xxu_rtl2832_tua9001_config; break; case TUNER_RTL2832_E4000: - rtl2832_config = &rtl28xxu_rtl2832_e4000_config; + pdata->config = &rtl28xxu_rtl2832_e4000_config; break; case TUNER_RTL2832_R820T: case TUNER_RTL2832_R828D: - rtl2832_config = &rtl28xxu_rtl2832_r820t_config; + pdata->config = &rtl28xxu_rtl2832_r820t_config; break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", @@ -821,11 +820,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) } /* attach demodulator */ - platform_data.config = rtl2832_config; - platform_data.dvb_frontend = &adap->fe[0]; + memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE); board_info.addr = 0x10; - board_info.platform_data = &platform_data; + board_info.platform_data = pdata; request_module("%s", board_info.type); client = i2c_new_device(&d->i2c_adap, &board_info); if (client == NULL || client->dev.driver == NULL) { @@ -839,10 +837,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) goto err; } - priv->i2c_client_demod = client; + adap->fe[0] = pdata->get_dvb_frontend(client); + priv->demod_i2c_adapter = pdata->get_i2c_adapter(client); - /* RTL2832 I2C repeater */ - priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]); + priv->i2c_client_demod = client; /* set fe callback */ adap->fe[0]->callback = rtl2832u_frontend_callback; @@ -1038,6 +1036,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; struct dvb_frontend *fe = NULL; struct i2c_board_info info; struct i2c_client *client; @@ -1075,7 +1074,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) case TUNER_RTL2832_E4000: { struct v4l2_subdev *sd; struct i2c_adapter *i2c_adap_internal = - rtl2832_get_private_i2c_adapter(adap->fe[0]); + pdata->get_private_i2c_adapter(priv->i2c_client_demod); + struct e4000_config e4000_config = { .fe = adap->fe[0], .clock = 28800000, @@ -1346,7 +1346,8 @@ err: static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_device *d = fe_to_d(fe); - struct dvb_usb_adapter *adap = fe_to_adap(fe); + struct rtl28xxu_priv *priv = fe_to_priv(fe); + struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; int ret; u8 val; @@ -1364,7 +1365,7 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) /* bypass slave demod TS through master demod */ if (fe->id == 1 && onoff) { - ret = rtl2832_enable_external_ts_if(adap->fe[0]); + ret = pdata->enable_slave_ts(priv->i2c_client_demod); if (ret) goto err; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 3f630c842949..cb3fc6595332 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -80,7 +80,10 @@ struct rtl28xxu_priv { #define SLAVE_DEMOD_MN88472 1 #define SLAVE_DEMOD_MN88473 2 unsigned int slave_demod:2; - struct rtl2830_platform_data rtl2830_platform_data; + union { + struct rtl2830_platform_data rtl2830_platform_data; + struct rtl2832_platform_data rtl2832_platform_data; + }; }; enum rtl28xxu_chip_id { -- cgit v1.2.3 From ac32ee42cc880e62ab6dcb05372767f31ba4a19b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 00:21:04 -0300 Subject: [media] rtl2832: remove exported resources Exported resources are not needed anymore as all users are using callbacks carried via platform data. Due to that we will remove those. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 138 ---------------------------------- drivers/media/dvb-frontends/rtl2832.h | 60 --------------- 2 files changed, 198 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 8c36a8415c4c..2316a2ad410a 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -886,19 +886,6 @@ err: return ret; } -static struct dvb_frontend_ops rtl2832_ops; - -static void rtl2832_release(struct dvb_frontend *fe) -{ - struct rtl2832_priv *priv = fe->demodulator_priv; - - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); - cancel_delayed_work_sync(&priv->i2c_gate_work); - i2c_del_mux_adapter(priv->i2c_adapter_tuner); - i2c_del_mux_adapter(priv->i2c_adapter); - kfree(priv); -} - /* * Delay mechanism to avoid unneeded I2C gate open / close. Gate close is * delayed here a little bit in order to see if there is sequence of I2C @@ -1022,126 +1009,6 @@ static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, return 0; } -int rtl2832_enable_external_ts_if(struct dvb_frontend *fe) -{ - struct rtl2832_priv *priv = fe->demodulator_priv; - int ret; - - dev_dbg(&priv->i2c->dev, "%s: setting PIP mode\n", __func__); - - ret = rtl2832_wr_regs(priv, 0x0c, 1, "\x5f\xff", 2); - if (ret) - goto err; - - ret = rtl2832_wr_demod_reg(priv, DVBT_PIP_ON, 0x1); - if (ret) - goto err; - - ret = rtl2832_wr_reg(priv, 0xbc, 0, 0x18); - if (ret) - goto err; - - ret = rtl2832_wr_reg(priv, 0x22, 0, 0x01); - if (ret) - goto err; - - ret = rtl2832_wr_reg(priv, 0x26, 0, 0x1f); - if (ret) - goto err; - - ret = rtl2832_wr_reg(priv, 0x27, 0, 0xff); - if (ret) - goto err; - - ret = rtl2832_wr_regs(priv, 0x92, 1, "\x7f\xf7\xff", 3); - if (ret) - goto err; - - /* soft reset */ - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); - if (ret) - goto err; - - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); - if (ret) - goto err; - - return 0; -err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); - return ret; - -} -EXPORT_SYMBOL(rtl2832_enable_external_ts_if); - -struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe) -{ - struct rtl2832_priv *priv = fe->demodulator_priv; - return priv->i2c_adapter_tuner; -} -EXPORT_SYMBOL(rtl2832_get_i2c_adapter); - -struct i2c_adapter *rtl2832_get_private_i2c_adapter(struct dvb_frontend *fe) -{ - struct rtl2832_priv *priv = fe->demodulator_priv; - return priv->i2c_adapter; -} -EXPORT_SYMBOL(rtl2832_get_private_i2c_adapter); - -struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, - struct i2c_adapter *i2c) -{ - struct rtl2832_priv *priv = NULL; - int ret = 0; - u8 tmp; - - dev_dbg(&i2c->dev, "%s:\n", __func__); - - /* allocate memory for the internal state */ - priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); - if (priv == NULL) - goto err; - - /* setup the priv */ - priv->i2c = i2c; - priv->tuner = cfg->tuner; - memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); - INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work); - - /* create muxed i2c adapter for demod itself */ - priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, - rtl2832_select, NULL); - if (priv->i2c_adapter == NULL) - goto err; - - /* check if the demod is there */ - ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); - if (ret) - goto err; - - /* create muxed i2c adapter for demod tuner bus */ - priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv, - 0, 1, 0, rtl2832_select, rtl2832_deselect); - if (priv->i2c_adapter_tuner == NULL) - goto err; - - /* create dvb_frontend */ - memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); - priv->fe.demodulator_priv = priv; - - /* TODO implement sleep mode */ - priv->sleeping = true; - - return &priv->fe; -err: - dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); - if (priv && priv->i2c_adapter) - i2c_del_mux_adapter(priv->i2c_adapter); - kfree(priv); - return NULL; -} -EXPORT_SYMBOL(rtl2832_attach); - static struct dvb_frontend_ops rtl2832_ops = { .delsys = { SYS_DVBT }, .info = { @@ -1166,8 +1033,6 @@ static struct dvb_frontend_ops rtl2832_ops = { FE_CAN_MUTE_TS }, - .release = rtl2832_release, - .init = rtl2832_init, .sleep = rtl2832_sleep, @@ -1307,11 +1172,8 @@ static int rtl2832_probe(struct i2c_client *client, /* create dvb_frontend */ memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); - priv->fe.ops.release = NULL; priv->fe.demodulator_priv = priv; i2c_set_clientdata(client, priv); - if (pdata->dvb_frontend) - *pdata->dvb_frontend = &priv->fe; /* setup callbacks */ pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index dbc4d3ca5d37..983d5a1f3340 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -21,7 +21,6 @@ #ifndef RTL2832_H #define RTL2832_H -#include #include struct rtl2832_config { @@ -53,12 +52,6 @@ struct rtl2832_config { struct rtl2832_platform_data { const struct rtl2832_config *config; - /* - * frontend - * returned by driver - */ - struct dvb_frontend **dvb_frontend; - /* */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); @@ -67,57 +60,4 @@ struct rtl2832_platform_data { int (*enable_slave_ts)(struct i2c_client *); }; -#if IS_ENABLED(CONFIG_DVB_RTL2832) -struct dvb_frontend *rtl2832_attach( - const struct rtl2832_config *cfg, - struct i2c_adapter *i2c -); - -extern struct i2c_adapter *rtl2832_get_i2c_adapter( - struct dvb_frontend *fe -); - -extern struct i2c_adapter *rtl2832_get_private_i2c_adapter( - struct dvb_frontend *fe -); - -extern int rtl2832_enable_external_ts_if( - struct dvb_frontend *fe -); - -#else - -static inline struct dvb_frontend *rtl2832_attach( - const struct rtl2832_config *config, - struct i2c_adapter *i2c -) -{ - pr_warn("%s: driver disabled by Kconfig\n", __func__); - return NULL; -} - -static inline struct i2c_adapter *rtl2832_get_i2c_adapter( - struct dvb_frontend *fe -) -{ - return NULL; -} - -static inline struct i2c_adapter *rtl2832_get_private_i2c_adapter( - struct dvb_frontend *fe -) -{ - return NULL; -} - -static inline int rtl2832_enable_external_ts_if( - struct dvb_frontend *fe -) -{ - return -ENODEV; -} - -#endif - - #endif /* RTL2832_H */ -- cgit v1.2.3 From 038c6f240e02d3c497b5ab741402d28b3871d23c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 00:37:43 -0300 Subject: [media] rtl2832: rename driver state variable from 'priv' to 'dev' Rename it device state variable to dev. Both priv and dev are very common terms for such variable in kernel, but I like use dev in order to keep drivers consistent. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 272 ++++++++++++++--------------- drivers/media/dvb-frontends/rtl2832_priv.h | 2 +- 2 files changed, 137 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 2316a2ad410a..065c5fe16fe1 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -157,13 +157,13 @@ static const struct rtl2832_reg_entry registers[] = { }; /* write multiple hardware registers */ -static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) +static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) { int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 1 + len, .buf = buf, @@ -171,7 +171,7 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) }; if (1 + len > sizeof(buf)) { - dev_warn(&priv->i2c->dev, + dev_warn(&dev->i2c->dev, "%s: i2c wr reg=%04x: len=%d is too big!\n", KBUILD_MODNAME, reg, len); return -EINVAL; @@ -180,11 +180,11 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) buf[0] = reg; memcpy(&buf[1], val, len); - ret = i2c_transfer(priv->i2c_adapter, msg, 1); + ret = i2c_transfer(dev->i2c_adapter, msg, 1); if (ret == 1) { ret = 0; } else { - dev_warn(&priv->i2c->dev, + dev_warn(&dev->i2c->dev, "%s: i2c wr failed=%d reg=%02x len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; @@ -193,28 +193,28 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) } /* read multiple hardware registers */ -static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) +static int rtl2832_rd(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) { int ret; struct i2c_msg msg[2] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 1, .buf = ®, }, { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = I2C_M_RD, .len = len, .buf = val, } }; - ret = i2c_transfer(priv->i2c_adapter, msg, 2); + ret = i2c_transfer(dev->i2c_adapter, msg, 2); if (ret == 2) { ret = 0; } else { - dev_warn(&priv->i2c->dev, + dev_warn(&dev->i2c->dev, "%s: i2c rd failed=%d reg=%02x len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; @@ -223,54 +223,54 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) } /* write multiple registers */ -static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, +static int rtl2832_wr_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) { int ret; /* switch bank if needed */ - if (page != priv->page) { - ret = rtl2832_wr(priv, 0x00, &page, 1); + if (page != dev->page) { + ret = rtl2832_wr(dev, 0x00, &page, 1); if (ret) return ret; - priv->page = page; + dev->page = page; } -return rtl2832_wr(priv, reg, val, len); +return rtl2832_wr(dev, reg, val, len); } /* read multiple registers */ -static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, +static int rtl2832_rd_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) { int ret; /* switch bank if needed */ - if (page != priv->page) { - ret = rtl2832_wr(priv, 0x00, &page, 1); + if (page != dev->page) { + ret = rtl2832_wr(dev, 0x00, &page, 1); if (ret) return ret; - priv->page = page; + dev->page = page; } - return rtl2832_rd(priv, reg, val, len); + return rtl2832_rd(dev, reg, val, len); } /* write single register */ -static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val) +static int rtl2832_wr_reg(struct rtl2832_dev *dev, u8 reg, u8 page, u8 val) { - return rtl2832_wr_regs(priv, reg, page, &val, 1); + return rtl2832_wr_regs(dev, reg, page, &val, 1); } /* read single register */ -static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val) +static int rtl2832_rd_reg(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val) { - return rtl2832_rd_regs(priv, reg, page, val, 1); + return rtl2832_rd_regs(dev, reg, page, val, 1); } -static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) +static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) { int ret; @@ -292,7 +292,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) len = (msb >> 3) + 1; mask = REG_MASK(msb - lsb); - ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); + ret = rtl2832_rd_regs(dev, reg_start_addr, page, &reading[0], len); if (ret) goto err; @@ -305,12 +305,12 @@ static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) +static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) { int ret, i; u8 len; @@ -335,7 +335,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) mask = REG_MASK(msb - lsb); - ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len); + ret = rtl2832_rd_regs(dev, reg_start_addr, page, &reading[0], len); if (ret) goto err; @@ -350,14 +350,14 @@ static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) for (i = 0; i < len; i++) writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff; - ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len); + ret = rtl2832_wr_regs(dev, reg_start_addr, page, &writing[0], len); if (ret) goto err; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -365,30 +365,30 @@ err: static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { int ret; - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; - dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable); + dev_dbg(&dev->i2c->dev, "%s: enable=%d\n", __func__, enable); /* gate already open or close */ - if (priv->i2c_gate_state == enable) + if (dev->i2c_gate_state == enable) return 0; - ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); + ret = rtl2832_wr_demod_reg(dev, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); if (ret) goto err; - priv->i2c_gate_state = enable; + dev->i2c_gate_state = enable; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; int ret; u64 pset_iffreq; u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0); @@ -398,26 +398,26 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) * / CrystalFreqHz) */ - pset_iffreq = if_freq % priv->cfg.xtal; + pset_iffreq = if_freq % dev->cfg.xtal; pset_iffreq *= 0x400000; - pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); + pset_iffreq = div_u64(pset_iffreq, dev->cfg.xtal); pset_iffreq = -pset_iffreq; pset_iffreq = pset_iffreq & 0x3fffff; - dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n", + dev_dbg(&dev->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n", __func__, if_freq, (unsigned)pset_iffreq); - ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); + ret = rtl2832_wr_demod_reg(dev, DVBT_EN_BBIN, en_bbin); if (ret) return ret; - ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); + ret = rtl2832_wr_demod_reg(dev, DVBT_PSET_IFFREQ, pset_iffreq); return ret; } static int rtl2832_init(struct dvb_frontend *fe) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; const struct rtl2832_reg_value *init; int i, ret, len; @@ -467,19 +467,19 @@ static int rtl2832_init(struct dvb_frontend *fe) {DVBT_CR_THD_SET2, 0x1}, }; - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + dev_dbg(&dev->i2c->dev, "%s:\n", __func__); for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { - ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg, + ret = rtl2832_wr_demod_reg(dev, rtl2832_initial_regs[i].reg, rtl2832_initial_regs[i].value); if (ret) goto err; } /* load tuner specific settings */ - dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n", - __func__, priv->cfg.tuner); - switch (priv->cfg.tuner) { + dev_dbg(&dev->i2c->dev, "%s: load settings for tuner=%02x\n", + __func__, dev->cfg.tuner); + switch (dev->cfg.tuner) { case RTL2832_TUNER_FC0012: case RTL2832_TUNER_FC0013: len = ARRAY_SIZE(rtl2832_tuner_init_fc0012); @@ -504,7 +504,7 @@ static int rtl2832_init(struct dvb_frontend *fe) } for (i = 0; i < len; i++) { - ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value); + ret = rtl2832_wr_demod_reg(dev, init[i].reg, init[i].value); if (ret) goto err; } @@ -516,39 +516,39 @@ static int rtl2832_init(struct dvb_frontend *fe) */ #if 1 /* soft reset */ - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1); if (ret) goto err; - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0); if (ret) goto err; #endif - priv->sleeping = false; + dev->sleeping = false; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_sleep(struct dvb_frontend *fe) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); - priv->sleeping = true; + dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + dev->sleeping = true; return 0; } static int rtl2832_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + dev_dbg(&dev->i2c->dev, "%s:\n", __func__); s->min_delay_ms = 1000; s->step_size = fe->ops.info.frequency_stepsize * 2; s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; @@ -557,7 +557,7 @@ static int rtl2832_get_tune_settings(struct dvb_frontend *fe, static int rtl2832_set_frontend(struct dvb_frontend *fe) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i, j; u64 bw_mode, num, num2; @@ -589,7 +589,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) }; - dev_dbg(&priv->i2c->dev, + dev_dbg(&dev->i2c->dev, "%s: frequency=%d bandwidth_hz=%d inversion=%d\n", __func__, c->frequency, c->bandwidth_hz, c->inversion); @@ -598,7 +598,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) fe->ops.tuner_ops.set_params(fe); /* PIP mode related */ - ret = rtl2832_wr_regs(priv, 0x92, 1, "\x00\x0f\xff", 3); + ret = rtl2832_wr_regs(dev, 0x92, 1, "\x00\x0f\xff", 3); if (ret) goto err; @@ -629,12 +629,12 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) bw_mode = 64000000; break; default: - dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__); + dev_dbg(&dev->i2c->dev, "%s: invalid bandwidth\n", __func__); return -EINVAL; } for (j = 0; j < sizeof(bw_params[0]); j++) { - ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1); + ret = rtl2832_wr_regs(dev, 0x1c+j, 1, &bw_params[i][j], 1); if (ret) goto err; } @@ -643,11 +643,11 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) * / ConstWithBandwidthMode) */ - num = priv->cfg.xtal * 7; + num = dev->cfg.xtal * 7; num *= 0x400000; num = div_u64(num, bw_mode); resamp_ratio = num & 0x3ffffff; - ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio); + ret = rtl2832_wr_demod_reg(dev, DVBT_RSAMP_RATIO, resamp_ratio); if (ret) goto err; @@ -656,48 +656,48 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) * / (CrystalFreqHz * 7)) */ num = bw_mode << 20; - num2 = priv->cfg.xtal * 7; + num2 = dev->cfg.xtal * 7; num = div_u64(num, num2); num = -num; cfreq_off_ratio = num & 0xfffff; - ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio); + ret = rtl2832_wr_demod_reg(dev, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio); if (ret) goto err; /* soft reset */ - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1); if (ret) goto err; - ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0); if (ret) goto err; return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_get_frontend(struct dvb_frontend *fe) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; - if (priv->sleeping) + if (dev->sleeping) return 0; - ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2); + ret = rtl2832_rd_regs(dev, 0x3c, 3, buf, 2); if (ret) goto err; - ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]); + ret = rtl2832_rd_reg(dev, 0x51, 3, &buf[2]); if (ret) goto err; - dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); + dev_dbg(&dev->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); switch ((buf[0] >> 2) & 3) { case 0: @@ -787,22 +787,22 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; int ret; u32 tmp; *status = 0; - dev_dbg(&priv->i2c->dev, "%s:\n", __func__); - if (priv->sleeping) + dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + if (dev->sleeping) return 0; - ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp); + ret = rtl2832_rd_demod_reg(dev, DVBT_FSM_STAGE, &tmp); if (ret) goto err; @@ -818,13 +818,13 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; int ret, hierarchy, constellation; u8 buf[2], tmp; u16 tmp16; @@ -838,7 +838,7 @@ static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) /* reports SNR in resolution of 0.1 dB */ - ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp); + ret = rtl2832_rd_reg(dev, 0x3c, 3, &tmp); if (ret) goto err; @@ -850,7 +850,7 @@ static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) if (hierarchy > HIERARCHY_NUM - 1) goto err; - ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2); + ret = rtl2832_rd_regs(dev, 0x0c, 4, buf, 2); if (ret) goto err; @@ -864,17 +864,17 @@ static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct rtl2832_priv *priv = fe->demodulator_priv; + struct rtl2832_dev *dev = fe->demodulator_priv; int ret; u8 buf[2]; - ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2); + ret = rtl2832_rd_regs(dev, 0x4e, 3, buf, 2); if (ret) goto err; @@ -882,7 +882,7 @@ static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -895,14 +895,14 @@ err: */ static void rtl2832_i2c_gate_work(struct work_struct *work) { - struct rtl2832_priv *priv = container_of(work, - struct rtl2832_priv, i2c_gate_work.work); - struct i2c_adapter *adap = priv->i2c; + struct rtl2832_dev *dev = container_of(work, + struct rtl2832_dev, i2c_gate_work.work); + struct i2c_adapter *adap = dev->i2c; int ret; u8 buf[2]; struct i2c_msg msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = sizeof(buf), .buf = buf, @@ -916,7 +916,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) if (ret != 1) goto err; - priv->page = 1; + dev->page = 1; /* close I2C repeater gate */ buf[0] = 0x01; @@ -925,23 +925,23 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) if (ret != 1) goto err; - priv->i2c_gate_state = false; + dev->i2c_gate_state = false; return; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return; } static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { - struct rtl2832_priv *priv = mux_priv; + struct rtl2832_dev *dev = mux_priv; int ret; u8 buf[2], val; struct i2c_msg msg[1] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = sizeof(buf), .buf = buf, @@ -949,12 +949,12 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; struct i2c_msg msg_rd[2] = { { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = 0, .len = 1, .buf = "\x01", }, { - .addr = priv->cfg.i2c_addr, + .addr = dev->cfg.i2c_addr, .flags = I2C_M_RD, .len = 1, .buf = &val, @@ -962,9 +962,9 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; /* terminate possible gate closing */ - cancel_delayed_work_sync(&priv->i2c_gate_work); + cancel_delayed_work_sync(&dev->i2c_gate_work); - if (priv->i2c_gate_state == chan_id) + if (dev->i2c_gate_state == chan_id) return 0; /* select reg bank 1 */ @@ -974,7 +974,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) if (ret != 1) goto err; - priv->page = 1; + dev->page = 1; /* we must read that register, otherwise there will be errors */ ret = __i2c_transfer(adap, msg_rd, 2); @@ -992,11 +992,11 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) if (ret != 1) goto err; - priv->i2c_gate_state = chan_id; + dev->i2c_gate_state = chan_id; return 0; err: - dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); return -EREMOTEIO; } @@ -1004,8 +1004,8 @@ err: static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { - struct rtl2832_priv *priv = mux_priv; - schedule_delayed_work(&priv->i2c_gate_work, usecs_to_jiffies(100)); + struct rtl2832_dev *dev = mux_priv; + schedule_delayed_work(&dev->i2c_gate_work, usecs_to_jiffies(100)); return 0; } @@ -1050,7 +1050,7 @@ static struct dvb_frontend_ops rtl2832_ops = { static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) { - struct rtl2832_priv *dev = i2c_get_clientdata(client); + struct rtl2832_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); return &dev->fe; @@ -1058,7 +1058,7 @@ static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) static struct i2c_adapter *rtl2832_get_i2c_adapter_(struct i2c_client *client) { - struct rtl2832_priv *dev = i2c_get_clientdata(client); + struct rtl2832_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); return dev->i2c_adapter_tuner; @@ -1066,7 +1066,7 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter_(struct i2c_client *client) static struct i2c_adapter *rtl2832_get_private_i2c_adapter_(struct i2c_client *client) { - struct rtl2832_priv *dev = i2c_get_clientdata(client); + struct rtl2832_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); return dev->i2c_adapter; @@ -1074,7 +1074,7 @@ static struct i2c_adapter *rtl2832_get_private_i2c_adapter_(struct i2c_client *c static int rtl2832_enable_slave_ts(struct i2c_client *client) { - struct rtl2832_priv *dev = i2c_get_clientdata(client); + struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; dev_dbg(&client->dev, "setting PIP mode\n"); @@ -1128,52 +1128,52 @@ static int rtl2832_probe(struct i2c_client *client, struct rtl2832_platform_data *pdata = client->dev.platform_data; const struct rtl2832_config *config = pdata->config; struct i2c_adapter *i2c = client->adapter; - struct rtl2832_priv *priv; + struct rtl2832_dev *dev; int ret; u8 tmp; dev_dbg(&client->dev, "\n"); /* allocate memory for the internal state */ - priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); - if (priv == NULL) { + dev = kzalloc(sizeof(struct rtl2832_dev), GFP_KERNEL); + if (dev == NULL) { ret = -ENOMEM; goto err; } - /* setup the priv */ - priv->client = client; - priv->i2c = i2c; - priv->tuner = config->tuner; - priv->sleeping = true; - memcpy(&priv->cfg, config, sizeof(struct rtl2832_config)); - INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work); + /* setup the state */ + dev->client = client; + dev->i2c = i2c; + dev->tuner = config->tuner; + dev->sleeping = true; + memcpy(&dev->cfg, config, sizeof(struct rtl2832_config)); + INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); /* create muxed i2c adapter for demod itself */ - priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, + dev->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, dev, 0, 0, 0, rtl2832_select, NULL); - if (priv->i2c_adapter == NULL) { + if (dev->i2c_adapter == NULL) { ret = -ENODEV; goto err_kfree; } /* check if the demod is there */ - ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); + ret = rtl2832_rd_reg(dev, 0x00, 0x0, &tmp); if (ret) goto err_i2c_del_mux_adapter; /* create muxed i2c adapter for demod tuner bus */ - priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv, + dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev, 0, 1, 0, rtl2832_select, rtl2832_deselect); - if (priv->i2c_adapter_tuner == NULL) { + if (dev->i2c_adapter_tuner == NULL) { ret = -ENODEV; goto err_i2c_del_mux_adapter; } /* create dvb_frontend */ - memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); - priv->fe.demodulator_priv = priv; - i2c_set_clientdata(client, priv); + memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); + dev->fe.demodulator_priv = dev; + i2c_set_clientdata(client, dev); /* setup callbacks */ pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; @@ -1184,9 +1184,9 @@ static int rtl2832_probe(struct i2c_client *client, dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); return 0; err_i2c_del_mux_adapter: - i2c_del_mux_adapter(priv->i2c_adapter); + i2c_del_mux_adapter(dev->i2c_adapter); err_kfree: - kfree(priv); + kfree(dev); err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -1194,17 +1194,17 @@ err: static int rtl2832_remove(struct i2c_client *client) { - struct rtl2832_priv *priv = i2c_get_clientdata(client); + struct rtl2832_dev *dev = i2c_get_clientdata(client); dev_dbg(&client->dev, "\n"); - cancel_delayed_work_sync(&priv->i2c_gate_work); + cancel_delayed_work_sync(&dev->i2c_gate_work); - i2c_del_mux_adapter(priv->i2c_adapter_tuner); + i2c_del_mux_adapter(dev->i2c_adapter_tuner); - i2c_del_mux_adapter(priv->i2c_adapter); + i2c_del_mux_adapter(dev->i2c_adapter); - kfree(priv); + kfree(dev); return 0; } diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 05b2b62634c1..58feb27b253f 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -25,7 +25,7 @@ #include "rtl2832.h" #include -struct rtl2832_priv { +struct rtl2832_dev { struct i2c_client *client; struct i2c_adapter *i2c; struct i2c_adapter *i2c_adapter; -- cgit v1.2.3 From 6e6aac6525c8db5181cdd43cbe0343960c484e82 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 02:28:33 -0300 Subject: [media] rtl2832: enhance / fix logging Pass correct device pointer to dev_* logging functions in order print logs correctly. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 102 +++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 065c5fe16fe1..6c324aa88c97 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -159,6 +159,7 @@ static const struct rtl2832_reg_entry registers[] = { /* write multiple hardware registers */ static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) { + struct i2c_client *client = dev->client; int ret; u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { @@ -171,9 +172,8 @@ static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) }; if (1 + len > sizeof(buf)) { - dev_warn(&dev->i2c->dev, - "%s: i2c wr reg=%04x: len=%d is too big!\n", - KBUILD_MODNAME, reg, len); + dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n", + reg, len); return -EINVAL; } @@ -184,9 +184,8 @@ static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) if (ret == 1) { ret = 0; } else { - dev_warn(&dev->i2c->dev, - "%s: i2c wr failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); + dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -195,6 +194,7 @@ static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) /* read multiple hardware registers */ static int rtl2832_rd(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) { + struct i2c_client *client = dev->client; int ret; struct i2c_msg msg[2] = { { @@ -214,9 +214,8 @@ static int rtl2832_rd(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - dev_warn(&dev->i2c->dev, - "%s: i2c rd failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); + dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n", + ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -235,9 +234,8 @@ static int rtl2832_wr_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, return ret; dev->page = page; -} - -return rtl2832_wr(dev, reg, val, len); + } + return rtl2832_wr(dev, reg, val, len); } /* read multiple registers */ @@ -254,7 +252,6 @@ static int rtl2832_rd_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, dev->page = page; } - return rtl2832_rd(dev, reg, val, len); } @@ -272,6 +269,7 @@ static int rtl2832_rd_reg(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val) static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) { + struct i2c_client *client = dev->client; int ret; u8 reg_start_addr; @@ -305,13 +303,14 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) { + struct i2c_client *client = dev->client; int ret, i; u8 len; u8 reg_start_addr; @@ -357,17 +356,18 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { - int ret; struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; + int ret; - dev_dbg(&dev->i2c->dev, "%s: enable=%d\n", __func__, enable); + dev_dbg(&client->dev, "enable=%d\n", enable); /* gate already open or close */ if (dev->i2c_gate_state == enable) @@ -381,7 +381,7 @@ static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -389,6 +389,7 @@ err: static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; int ret; u64 pset_iffreq; u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0); @@ -403,8 +404,8 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) pset_iffreq = div_u64(pset_iffreq, dev->cfg.xtal); pset_iffreq = -pset_iffreq; pset_iffreq = pset_iffreq & 0x3fffff; - dev_dbg(&dev->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n", - __func__, if_freq, (unsigned)pset_iffreq); + dev_dbg(&client->dev, "if_frequency=%d pset_iffreq=%08x\n", + if_freq, (unsigned)pset_iffreq); ret = rtl2832_wr_demod_reg(dev, DVBT_EN_BBIN, en_bbin); if (ret) @@ -418,9 +419,9 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) static int rtl2832_init(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; const struct rtl2832_reg_value *init; int i, ret, len; - /* initialization values for the demodulator registers */ struct rtl2832_reg_value rtl2832_initial_regs[] = { {DVBT_AD_EN_REG, 0x1}, @@ -467,7 +468,7 @@ static int rtl2832_init(struct dvb_frontend *fe) {DVBT_CR_THD_SET2, 0x1}, }; - dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { ret = rtl2832_wr_demod_reg(dev, rtl2832_initial_regs[i].reg, @@ -477,8 +478,7 @@ static int rtl2832_init(struct dvb_frontend *fe) } /* load tuner specific settings */ - dev_dbg(&dev->i2c->dev, "%s: load settings for tuner=%02x\n", - __func__, dev->cfg.tuner); + dev_dbg(&client->dev, "load settings for tuner=%02x\n", dev->cfg.tuner); switch (dev->cfg.tuner) { case RTL2832_TUNER_FC0012: case RTL2832_TUNER_FC0013: @@ -530,15 +530,16 @@ static int rtl2832_init(struct dvb_frontend *fe) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_sleep(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; - dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); dev->sleeping = true; return 0; } @@ -547,8 +548,9 @@ static int rtl2832_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; - dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); s->min_delay_ms = 1000; s->step_size = fe->ops.info.frequency_stepsize * 2; s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; @@ -558,6 +560,7 @@ static int rtl2832_get_tune_settings(struct dvb_frontend *fe, static int rtl2832_set_frontend(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i, j; u64 bw_mode, num, num2; @@ -589,9 +592,8 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) }; - dev_dbg(&dev->i2c->dev, - "%s: frequency=%d bandwidth_hz=%d inversion=%d\n", - __func__, c->frequency, c->bandwidth_hz, c->inversion); + dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n", + c->frequency, c->bandwidth_hz, c->inversion); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -629,8 +631,10 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) bw_mode = 64000000; break; default: - dev_dbg(&dev->i2c->dev, "%s: invalid bandwidth\n", __func__); - return -EINVAL; + dev_err(&client->dev, "invalid bandwidth_hz %u\n", + c->bandwidth_hz); + ret = -EINVAL; + goto err; } for (j = 0; j < sizeof(bw_params[0]); j++) { @@ -675,13 +679,14 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_get_frontend(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; @@ -697,7 +702,7 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe) if (ret) goto err; - dev_dbg(&dev->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); + dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf); switch ((buf[0] >> 2) & 3) { case 0: @@ -787,18 +792,20 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; int ret; u32 tmp; - *status = 0; - dev_dbg(&dev->i2c->dev, "%s:\n", __func__); + dev_dbg(&client->dev, "\n"); + + *status = 0; if (dev->sleeping) return 0; @@ -818,13 +825,14 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; int ret, hierarchy, constellation; u8 buf[2], tmp; u16 tmp16; @@ -864,13 +872,14 @@ static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) { struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; int ret; u8 buf[2]; @@ -882,7 +891,7 @@ static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -897,6 +906,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) { struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work); + struct i2c_client *client = dev->client; struct i2c_adapter *adap = dev->i2c; int ret; u8 buf[2]; @@ -909,6 +919,8 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) } }; + dev_dbg(&client->dev, "\n"); + /* select reg bank 1 */ buf[0] = 0x00; buf[1] = 0x01; @@ -929,14 +941,14 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) return; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); - + dev_dbg(&client->dev, "failed=%d\n", ret); return; } static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { struct rtl2832_dev *dev = mux_priv; + struct i2c_client *client = dev->client; int ret; u8 buf[2], val; struct i2c_msg msg[1] = { @@ -996,8 +1008,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) return 0; err: - dev_dbg(&dev->i2c->dev, "%s: failed=%d\n", __func__, ret); - + dev_dbg(&client->dev, "failed=%d\n", ret); return -EREMOTEIO; } @@ -1005,6 +1016,7 @@ static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) { struct rtl2832_dev *dev = mux_priv; + schedule_delayed_work(&dev->i2c_gate_work, usecs_to_jiffies(100)); return 0; } @@ -1077,7 +1089,7 @@ static int rtl2832_enable_slave_ts(struct i2c_client *client) struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; - dev_dbg(&client->dev, "setting PIP mode\n"); + dev_dbg(&client->dev, "\n"); ret = rtl2832_wr_regs(dev, 0x0c, 1, "\x5f\xff", 2); if (ret) -- cgit v1.2.3 From e1174d788aa2f4f21160860fe2be1ead8ee90851 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 05:26:27 -0300 Subject: [media] rtl2832: move all configuration to platform data struct Move all needed configuration values to platform data structure and remove old configuration code where possible. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 48 +++++++++++++++--------------- drivers/media/dvb-frontends/rtl2832.h | 20 +++++++++++++ drivers/media/dvb-frontends/rtl2832_priv.h | 4 +-- 3 files changed, 45 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 6c324aa88c97..31240bbce8ff 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -164,7 +164,7 @@ static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 1 + len, .buf = buf, @@ -198,12 +198,12 @@ static int rtl2832_rd(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) int ret; struct i2c_msg msg[2] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 1, .buf = ®, }, { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = I2C_M_RD, .len = len, .buf = val, @@ -399,9 +399,9 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) * / CrystalFreqHz) */ - pset_iffreq = if_freq % dev->cfg.xtal; + pset_iffreq = if_freq % dev->pdata->clk; pset_iffreq *= 0x400000; - pset_iffreq = div_u64(pset_iffreq, dev->cfg.xtal); + pset_iffreq = div_u64(pset_iffreq, dev->pdata->clk); pset_iffreq = -pset_iffreq; pset_iffreq = pset_iffreq & 0x3fffff; dev_dbg(&client->dev, "if_frequency=%d pset_iffreq=%08x\n", @@ -478,8 +478,9 @@ static int rtl2832_init(struct dvb_frontend *fe) } /* load tuner specific settings */ - dev_dbg(&client->dev, "load settings for tuner=%02x\n", dev->cfg.tuner); - switch (dev->cfg.tuner) { + dev_dbg(&client->dev, "load settings for tuner=%02x\n", + dev->pdata->tuner); + switch (dev->pdata->tuner) { case RTL2832_TUNER_FC0012: case RTL2832_TUNER_FC0013: len = ARRAY_SIZE(rtl2832_tuner_init_fc0012); @@ -647,7 +648,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) * / ConstWithBandwidthMode) */ - num = dev->cfg.xtal * 7; + num = dev->pdata->clk * 7; num *= 0x400000; num = div_u64(num, bw_mode); resamp_ratio = num & 0x3ffffff; @@ -660,7 +661,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) * / (CrystalFreqHz * 7)) */ num = bw_mode << 20; - num2 = dev->cfg.xtal * 7; + num2 = dev->pdata->clk * 7; num = div_u64(num, num2); num = -num; cfreq_off_ratio = num & 0xfffff; @@ -907,12 +908,11 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work); struct i2c_client *client = dev->client; - struct i2c_adapter *adap = dev->i2c; int ret; u8 buf[2]; struct i2c_msg msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = sizeof(buf), .buf = buf, @@ -924,7 +924,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) /* select reg bank 1 */ buf[0] = 0x00; buf[1] = 0x01; - ret = __i2c_transfer(adap, msg, 1); + ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) goto err; @@ -933,7 +933,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) /* close I2C repeater gate */ buf[0] = 0x01; buf[1] = 0x10; - ret = __i2c_transfer(adap, msg, 1); + ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) goto err; @@ -953,7 +953,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) u8 buf[2], val; struct i2c_msg msg[1] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = sizeof(buf), .buf = buf, @@ -961,12 +961,12 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) }; struct i2c_msg msg_rd[2] = { { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = 0, .len = 1, .buf = "\x01", }, { - .addr = dev->cfg.i2c_addr, + .addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = &val, @@ -982,14 +982,14 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) /* select reg bank 1 */ buf[0] = 0x00; buf[1] = 0x01; - ret = __i2c_transfer(adap, msg, 1); + ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) goto err; dev->page = 1; /* we must read that register, otherwise there will be errors */ - ret = __i2c_transfer(adap, msg_rd, 2); + ret = __i2c_transfer(client->adapter, msg_rd, 2); if (ret != 2) goto err; @@ -1000,7 +1000,7 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) else buf[1] = 0x10; /* close */ - ret = __i2c_transfer(adap, msg, 1); + ret = __i2c_transfer(client->adapter, msg, 1); if (ret != 1) goto err; @@ -1138,7 +1138,6 @@ static int rtl2832_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct rtl2832_platform_data *pdata = client->dev.platform_data; - const struct rtl2832_config *config = pdata->config; struct i2c_adapter *i2c = client->adapter; struct rtl2832_dev *dev; int ret; @@ -1155,12 +1154,13 @@ static int rtl2832_probe(struct i2c_client *client, /* setup the state */ dev->client = client; - dev->i2c = i2c; - dev->tuner = config->tuner; + dev->pdata = client->dev.platform_data; + if (pdata->config) { + dev->pdata->clk = pdata->config->xtal; + dev->pdata->tuner = pdata->config->tuner; + } dev->sleeping = true; - memcpy(&dev->cfg, config, sizeof(struct rtl2832_config)); INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); - /* create muxed i2c adapter for demod itself */ dev->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, dev, 0, 0, 0, rtl2832_select, NULL); diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 983d5a1f3340..35e86e6bc751 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -53,6 +53,26 @@ struct rtl2832_platform_data { const struct rtl2832_config *config; /* + * Clock frequency. + * Hz + * 4000000, 16000000, 25000000, 28800000 + */ + u32 clk; + + /* + * Tuner. + * XXX: This must be keep sync with dvb_usb_rtl28xxu USB IF driver. + */ +#define RTL2832_TUNER_TUA9001 0x24 +#define RTL2832_TUNER_FC0012 0x26 +#define RTL2832_TUNER_E4000 0x27 +#define RTL2832_TUNER_FC0013 0x29 +#define RTL2832_TUNER_R820T 0x2a +#define RTL2832_TUNER_R828D 0x2b + u8 tuner; + + /* + * Callbacks. */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 58feb27b253f..899533241925 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -26,17 +26,15 @@ #include struct rtl2832_dev { + struct rtl2832_platform_data *pdata; struct i2c_client *client; - struct i2c_adapter *i2c; struct i2c_adapter *i2c_adapter; struct i2c_adapter *i2c_adapter_tuner; struct dvb_frontend fe; - struct rtl2832_config cfg; bool i2c_gate_state; bool sleeping; - u8 tuner; u8 page; /* active register page */ struct delayed_work i2c_gate_work; }; -- cgit v1.2.3 From de0a5f1132458331148b23731d063417c3bac910 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 13 Dec 2014 05:44:05 -0300 Subject: [media] rtl28xxu: use platform data config for rtl2832 demod Use platform data configuration for rtl2832 demod driver. Old configuration are still left as it is used for rtl2832_sdr driver. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 3d619def7066..25c885fda252 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -637,6 +637,32 @@ err: return ret; } +static const struct rtl2832_platform_data rtl2832_fc0012_platform_data = { + .clk = 28800000, + .tuner = TUNER_RTL2832_FC0012 +}; + +static const struct rtl2832_platform_data rtl2832_fc0013_platform_data = { + .clk = 28800000, + .tuner = TUNER_RTL2832_FC0013 +}; + +static const struct rtl2832_platform_data rtl2832_tua9001_platform_data = { + .clk = 28800000, + .tuner = TUNER_RTL2832_TUA9001, +}; + +static const struct rtl2832_platform_data rtl2832_e4000_platform_data = { + .clk = 28800000, + .tuner = TUNER_RTL2832_E4000, +}; + +static const struct rtl2832_platform_data rtl2832_r820t_platform_data = { + .clk = 28800000, + .tuner = TUNER_RTL2832_R820T, +}; + +/* TODO: these are redundant information for rtl2832_sdr driver */ static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { .i2c_addr = 0x10, /* 0x20 */ .xtal = 28800000, @@ -793,24 +819,24 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) switch (priv->tuner) { case TUNER_RTL2832_FC0012: - pdata->config = &rtl28xxu_rtl2832_fc0012_config; + *pdata = rtl2832_fc0012_platform_data; break; case TUNER_RTL2832_FC0013: - pdata->config = &rtl28xxu_rtl2832_fc0013_config; + *pdata = rtl2832_fc0013_platform_data; break; case TUNER_RTL2832_FC2580: /* FIXME: do not abuse fc0012 settings */ - pdata->config = &rtl28xxu_rtl2832_fc0012_config; + *pdata = rtl2832_fc0012_platform_data; break; case TUNER_RTL2832_TUA9001: - pdata->config = &rtl28xxu_rtl2832_tua9001_config; + *pdata = rtl2832_tua9001_platform_data; break; case TUNER_RTL2832_E4000: - pdata->config = &rtl28xxu_rtl2832_e4000_config; + *pdata = rtl2832_e4000_platform_data; break; case TUNER_RTL2832_R820T: case TUNER_RTL2832_R828D: - pdata->config = &rtl28xxu_rtl2832_r820t_config; + *pdata = rtl2832_r820t_platform_data; break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", -- cgit v1.2.3 From d10165815b5a319b12554a2ad83f3e1598a9ea8f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 04:45:57 -0300 Subject: [media] rtl2832: convert to regmap API Use regmap to cover register access routines. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/Kconfig | 1 + drivers/media/dvb-frontends/rtl2832.c | 329 +++++++++++++++-------------- drivers/media/dvb-frontends/rtl2832_priv.h | 4 +- 3 files changed, 173 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 0e1263456922..bb76727d924e 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -452,6 +452,7 @@ config DVB_RTL2830 config DVB_RTL2832 tristate "Realtek RTL2832 DVB-T" depends on DVB_CORE && I2C && I2C_MUX + select REGMAP default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 31240bbce8ff..5d7ea23f02f7 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -22,8 +22,6 @@ #include "dvb_math.h" #include -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE 64 #define REG_MASK(b) (BIT(b + 1) - 1) static const struct rtl2832_reg_entry registers[] = { @@ -156,103 +154,53 @@ static const struct rtl2832_reg_entry registers[] = { [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, }; -/* write multiple hardware registers */ -static int rtl2832_wr(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) +/* Our regmap is bypassing I2C adapter lock, thus we do it! */ +int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg, + const void *val, size_t val_count) { - struct i2c_client *client = dev->client; + struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; - u8 buf[MAX_XFER_SIZE]; - struct i2c_msg msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = 1 + len, - .buf = buf, - } - }; - if (1 + len > sizeof(buf)) { - dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n", - reg, len); - return -EINVAL; - } - - buf[0] = reg; - memcpy(&buf[1], val, len); - - ret = i2c_transfer(dev->i2c_adapter, msg, 1); - if (ret == 1) { - ret = 0; - } else { - dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n", - ret, reg, len); - ret = -EREMOTEIO; - } + i2c_lock_adapter(client->adapter); + ret = regmap_bulk_write(dev->regmap, reg, val, val_count); + i2c_unlock_adapter(client->adapter); return ret; } -/* read multiple hardware registers */ -static int rtl2832_rd(struct rtl2832_dev *dev, u8 reg, u8 *val, int len) +int rtl2832_update_bits(struct i2c_client *client, unsigned int reg, + unsigned int mask, unsigned int val) { - struct i2c_client *client = dev->client; + struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = ®, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = len, - .buf = val, - } - }; - ret = i2c_transfer(dev->i2c_adapter, msg, 2); - if (ret == 2) { - ret = 0; - } else { - dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n", - ret, reg, len); - ret = -EREMOTEIO; - } + i2c_lock_adapter(client->adapter); + ret = regmap_update_bits(dev->regmap, reg, mask, val); + i2c_unlock_adapter(client->adapter); return ret; } -/* write multiple registers */ -static int rtl2832_wr_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, - int len) +int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, void *val, + size_t val_count) { + struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; - /* switch bank if needed */ - if (page != dev->page) { - ret = rtl2832_wr(dev, 0x00, &page, 1); - if (ret) - return ret; + i2c_lock_adapter(client->adapter); + ret = regmap_bulk_read(dev->regmap, reg, val, val_count); + i2c_unlock_adapter(client->adapter); + return ret; +} - dev->page = page; - } - return rtl2832_wr(dev, reg, val, len); +/* write multiple registers */ +static int rtl2832_wr_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) +{ + return rtl2832_bulk_write(dev->client, page << 8 | reg, val, len); } /* read multiple registers */ -static int rtl2832_rd_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, - int len) +static int rtl2832_rd_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) { - int ret; - - /* switch bank if needed */ - if (page != dev->page) { - ret = rtl2832_wr(dev, 0x00, &page, 1); - if (ret) - return ret; - - dev->page = page; - } - return rtl2832_rd(dev, reg, val, len); + return rtl2832_bulk_read(dev->client, page << 8 | reg, val, len); } /* write single register */ @@ -385,7 +333,6 @@ err: return ret; } - static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) { struct rtl2832_dev *dev = fe->demodulator_priv; @@ -897,44 +844,22 @@ err: } /* - * Delay mechanism to avoid unneeded I2C gate open / close. Gate close is - * delayed here a little bit in order to see if there is sequence of I2C + * I2C gate/mux/repeater logic + * We must use unlocked __i2c_transfer() here (through regmap) because of I2C + * adapter lock is already taken by tuner driver. + * There is delay mechanism to avoid unneeded I2C gate open / close. Gate close + * is delayed here a little bit in order to see if there is sequence of I2C * messages sent to same I2C bus. - * We must use unlocked version of __i2c_transfer() in order to avoid deadlock - * as lock is already taken by calling muxed i2c_transfer(). */ static void rtl2832_i2c_gate_work(struct work_struct *work) { - struct rtl2832_dev *dev = container_of(work, - struct rtl2832_dev, i2c_gate_work.work); + struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work); struct i2c_client *client = dev->client; int ret; - u8 buf[2]; - struct i2c_msg msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = sizeof(buf), - .buf = buf, - } - }; - - dev_dbg(&client->dev, "\n"); - /* select reg bank 1 */ - buf[0] = 0x00; - buf[1] = 0x01; - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret != 1) - goto err; - - dev->page = 1; - - /* close I2C repeater gate */ - buf[0] = 0x01; - buf[1] = 0x10; - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret != 1) + /* close gate */ + ret = rtl2832_update_bits(dev->client, 0x101, 0x08, 0x00); + if (ret) goto err; dev->i2c_gate_state = false; @@ -950,58 +875,24 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) struct rtl2832_dev *dev = mux_priv; struct i2c_client *client = dev->client; int ret; - u8 buf[2], val; - struct i2c_msg msg[1] = { - { - .addr = client->addr, - .flags = 0, - .len = sizeof(buf), - .buf = buf, - } - }; - struct i2c_msg msg_rd[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = "\x01", - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 1, - .buf = &val, - } - }; /* terminate possible gate closing */ - cancel_delayed_work_sync(&dev->i2c_gate_work); + cancel_delayed_work(&dev->i2c_gate_work); if (dev->i2c_gate_state == chan_id) return 0; - /* select reg bank 1 */ - buf[0] = 0x00; - buf[1] = 0x01; - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret != 1) - goto err; - - dev->page = 1; - - /* we must read that register, otherwise there will be errors */ - ret = __i2c_transfer(client->adapter, msg_rd, 2); - if (ret != 2) - goto err; - - /* open or close I2C repeater gate */ - buf[0] = 0x01; + /* + * chan_id 1 is muxed adapter demod provides and chan_id 0 is demod + * itself. We need open gate when request is for chan_id 1. On that case + * I2C adapter lock is already taken and due to that we will use + * regmap_update_bits() which does not lock again I2C adapter. + */ if (chan_id == 1) - buf[1] = 0x18; /* open */ + ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08); else - buf[1] = 0x10; /* close */ - - ret = __i2c_transfer(client->adapter, msg, 1); - if (ret != 1) + ret = rtl2832_update_bits(dev->client, 0x101, 0x08, 0x00); + if (ret) goto err; dev->i2c_gate_state = chan_id; @@ -1009,11 +900,11 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); - return -EREMOTEIO; + return ret; } static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, - u32 chan_id) + u32 chan_id) { struct rtl2832_dev *dev = mux_priv; @@ -1060,6 +951,91 @@ static struct dvb_frontend_ops rtl2832_ops = { .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, }; +/* + * We implement own I2C access routines for regmap in order to get manual access + * to I2C adapter lock, which is needed for I2C mux adapter. + */ +static int rtl2832_regmap_read(void *context, const void *reg_buf, + size_t reg_size, void *val_buf, size_t val_size) +{ + struct i2c_client *client = context; + int ret; + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = reg_size, + .buf = (u8 *)reg_buf, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = val_size, + .buf = val_buf, + } + }; + + ret = __i2c_transfer(client->adapter, msg, 2); + if (ret != 2) { + dev_warn(&client->dev, "i2c reg read failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; +} + +static int rtl2832_regmap_write(void *context, const void *data, size_t count) +{ + struct i2c_client *client = context; + int ret; + struct i2c_msg msg[1] = { + { + .addr = client->addr, + .flags = 0, + .len = count, + .buf = (u8 *)data, + } + }; + + ret = __i2c_transfer(client->adapter, msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; +} + +static int rtl2832_regmap_gather_write(void *context, const void *reg, + size_t reg_len, const void *val, + size_t val_len) +{ + struct i2c_client *client = context; + int ret; + u8 buf[256]; + struct i2c_msg msg[1] = { + { + .addr = client->addr, + .flags = 0, + .len = 1 + val_len, + .buf = buf, + } + }; + + buf[0] = *(u8 const *)reg; + memcpy(&buf[1], val, val_len); + + ret = __i2c_transfer(client->adapter, msg, 1); + if (ret != 1) { + dev_warn(&client->dev, "i2c reg write failed %d\n", ret); + if (ret >= 0) + ret = -EREMOTEIO; + return ret; + } + return 0; +} + static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) { struct rtl2832_dev *dev = i2c_get_clientdata(client); @@ -1142,6 +1118,30 @@ static int rtl2832_probe(struct i2c_client *client, struct rtl2832_dev *dev; int ret; u8 tmp; + static const struct regmap_bus regmap_bus = { + .read = rtl2832_regmap_read, + .write = rtl2832_regmap_write, + .gather_write = rtl2832_regmap_gather_write, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, + }; + static const struct regmap_range_cfg regmap_range_cfg[] = { + { + .selector_reg = 0x00, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + .range_min = 0 * 0x100, + .range_max = 5 * 0x100, + }, + }; + static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 5 * 0x100, + .ranges = regmap_range_cfg, + .num_ranges = ARRAY_SIZE(regmap_range_cfg), + }; dev_dbg(&client->dev, "\n"); @@ -1153,6 +1153,7 @@ static int rtl2832_probe(struct i2c_client *client, } /* setup the state */ + i2c_set_clientdata(client, dev); dev->client = client; dev->pdata = client->dev.platform_data; if (pdata->config) { @@ -1161,12 +1162,19 @@ static int rtl2832_probe(struct i2c_client *client, } dev->sleeping = true; INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); + /* create regmap */ + dev->regmap = regmap_init(&client->dev, ®map_bus, client, + ®map_config); + if (IS_ERR(dev->regmap)) { + ret = PTR_ERR(dev->regmap); + goto err_kfree; + } /* create muxed i2c adapter for demod itself */ dev->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, dev, 0, 0, 0, rtl2832_select, NULL); if (dev->i2c_adapter == NULL) { ret = -ENODEV; - goto err_kfree; + goto err_regmap_exit; } /* check if the demod is there */ @@ -1185,7 +1193,6 @@ static int rtl2832_probe(struct i2c_client *client, /* create dvb_frontend */ memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); dev->fe.demodulator_priv = dev; - i2c_set_clientdata(client, dev); /* setup callbacks */ pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; @@ -1197,6 +1204,8 @@ static int rtl2832_probe(struct i2c_client *client, return 0; err_i2c_del_mux_adapter: i2c_del_mux_adapter(dev->i2c_adapter); +err_regmap_exit: + regmap_exit(dev->regmap); err_kfree: kfree(dev); err: @@ -1216,6 +1225,8 @@ static int rtl2832_remove(struct i2c_client *client) i2c_del_mux_adapter(dev->i2c_adapter); + regmap_exit(dev->regmap); + kfree(dev); return 0; diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 899533241925..eacd4e4d8ea3 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -24,18 +24,18 @@ #include "dvb_frontend.h" #include "rtl2832.h" #include +#include struct rtl2832_dev { struct rtl2832_platform_data *pdata; struct i2c_client *client; + struct regmap *regmap; struct i2c_adapter *i2c_adapter; struct i2c_adapter *i2c_adapter_tuner; struct dvb_frontend fe; bool i2c_gate_state; bool sleeping; - - u8 page; /* active register page */ struct delayed_work i2c_gate_work; }; -- cgit v1.2.3 From 19d273d63552ac99d171fd68018a41f496248513 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 06:55:43 -0300 Subject: [media] rtl2832: implement DVBv5 CNR statistic DVBv5 CNR. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 73 +++++++++++++++++++++++++++++- drivers/media/dvb-frontends/rtl2832_priv.h | 3 +- 2 files changed, 73 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 5d7ea23f02f7..239472b4ce72 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -367,6 +367,7 @@ static int rtl2832_init(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; const struct rtl2832_reg_value *init; int i, ret, len; /* initialization values for the demodulator registers */ @@ -472,11 +473,14 @@ static int rtl2832_init(struct dvb_frontend *fe) if (ret) goto err; #endif - + /* init stats here in order signal app which stats are supported */ + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + /* start statistics polling */ + schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); dev->sleeping = false; return ret; - err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -489,6 +493,9 @@ static int rtl2832_sleep(struct dvb_frontend *fe) dev_dbg(&client->dev, "\n"); dev->sleeping = true; + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + dev->fe_status = 0; return 0; } @@ -771,6 +778,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) FE_HAS_VITERBI; }*/ + dev->fe_status = *status; return ret; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -843,6 +851,66 @@ err: return ret; } +static void rtl2832_stat_work(struct work_struct *work) +{ + struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, stat_work.work); + struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; + int ret, tmp; + u8 u8tmp, buf[2]; + u16 u16tmp; + + dev_dbg(&client->dev, "\n"); + + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + unsigned hierarchy, constellation; + #define CONSTELLATION_NUM 3 + #define HIERARCHY_NUM 4 + static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { + {85387325, 85387325, 85387325, 85387325}, + {86676178, 86676178, 87167949, 87795660}, + {87659938, 87659938, 87885178, 88241743}, + }; + + ret = rtl2832_bulk_read(client, 0x33c, &u8tmp, 1); + if (ret) + goto err; + + constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ + if (constellation > CONSTELLATION_NUM - 1) + goto err_schedule_delayed_work; + + hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ + if (hierarchy > HIERARCHY_NUM - 1) + goto err_schedule_delayed_work; + + ret = rtl2832_bulk_read(client, 0x40c, buf, 2); + if (ret) + goto err; + + u16tmp = buf[0] << 8 | buf[1] << 0; + if (u16tmp) + tmp = (constant[constellation][hierarchy] - + intlog10(u16tmp)) / ((1 << 24) / 10000); + else + tmp = 0; + + dev_dbg(&client->dev, "cnr raw=%u\n", u16tmp); + + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = tmp; + } else { + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + +err_schedule_delayed_work: + schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); + return; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); +} + /* * I2C gate/mux/repeater logic * We must use unlocked __i2c_transfer() here (through regmap) because of I2C @@ -1162,6 +1230,7 @@ static int rtl2832_probe(struct i2c_client *client, } dev->sleeping = true; INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); + INIT_DELAYED_WORK(&dev->stat_work, rtl2832_stat_work); /* create regmap */ dev->regmap = regmap_init(&client->dev, ®map_bus, client, ®map_config); diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index eacd4e4d8ea3..3c44983b95a0 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -33,7 +33,8 @@ struct rtl2832_dev { struct i2c_adapter *i2c_adapter; struct i2c_adapter *i2c_adapter_tuner; struct dvb_frontend fe; - + struct delayed_work stat_work; + fe_status_t fe_status; bool i2c_gate_state; bool sleeping; struct delayed_work i2c_gate_work; -- cgit v1.2.3 From 6b4fd01804ced75fb1385df5f6b9cf830cbe15d9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 09:59:20 -0300 Subject: [media] rtl2832: implement DVBv5 BER statistic DVBv5 BER. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 25 +++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2832_priv.h | 2 ++ 2 files changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 239472b4ce72..0a0899d2a6b2 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -476,6 +476,10 @@ static int rtl2832_init(struct dvb_frontend *fe) /* init stats here in order signal app which stats are supported */ c->cnr.len = 1; c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.len = 1; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; /* start statistics polling */ schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); dev->sleeping = false; @@ -904,6 +908,27 @@ static void rtl2832_stat_work(struct work_struct *work) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } + /* BER */ + if (dev->fe_status & FE_HAS_LOCK) { + ret = rtl2832_bulk_read(client, 0x34e, buf, 2); + if (ret) + goto err; + + u16tmp = buf[0] << 8 | buf[1] << 0; + dev->post_bit_error += u16tmp; + dev->post_bit_count += 1000000; + + dev_dbg(&client->dev, "ber errors=%u total=1000000\n", u16tmp); + + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue = dev->post_bit_count; + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + err_schedule_delayed_work: schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); return; diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 3c44983b95a0..a5f5ccdf10d8 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -35,6 +35,8 @@ struct rtl2832_dev { struct dvb_frontend fe; struct delayed_work stat_work; fe_status_t fe_status; + u64 post_bit_error; + u64 post_bit_count; bool i2c_gate_state; bool sleeping; struct delayed_work i2c_gate_work; -- cgit v1.2.3 From f7caf93fb8ed299c1f9a3d2713c8d588c938316e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 10:05:49 -0300 Subject: [media] rtl2832: wrap DVBv5 CNR to DVBv3 SNR Change legacy DVBv3 read SNR to return values calculated by DVBv5 statistics. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 42 +++--------------------------- drivers/media/dvb-frontends/rtl2832_priv.h | 1 + 2 files changed, 5 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 0a0899d2a6b2..18f150105438 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -791,49 +791,15 @@ err: static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct rtl2832_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - int ret, hierarchy, constellation; - u8 buf[2], tmp; - u16 tmp16; -#define CONSTELLATION_NUM 3 -#define HIERARCHY_NUM 4 - static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { - { 85387325, 85387325, 85387325, 85387325 }, - { 86676178, 86676178, 87167949, 87795660 }, - { 87659938, 87659938, 87885178, 88241743 }, - }; - - /* reports SNR in resolution of 0.1 dB */ - - ret = rtl2832_rd_reg(dev, 0x3c, 3, &tmp); - if (ret) - goto err; - - constellation = (tmp >> 2) & 0x03; /* [3:2] */ - if (constellation > CONSTELLATION_NUM - 1) - goto err; - - hierarchy = (tmp >> 4) & 0x07; /* [6:4] */ - if (hierarchy > HIERARCHY_NUM - 1) - goto err; - - ret = rtl2832_rd_regs(dev, 0x0c, 4, buf, 2); - if (ret) - goto err; - - tmp16 = buf[0] << 8 | buf[1]; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - if (tmp16) - *snr = (snr_constant[constellation][hierarchy] - - intlog10(tmp16)) / ((1 << 24) / 100); + /* report SNR in resolution of 0.1 dB */ + if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) + *snr = div_s64(c->cnr.stat[0].svalue, 100); else *snr = 0; return 0; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index a5f5ccdf10d8..5e90cd49d780 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -25,6 +25,7 @@ #include "rtl2832.h" #include #include +#include struct rtl2832_dev { struct rtl2832_platform_data *pdata; -- cgit v1.2.3 From 084330b746d9fb369cc6df17fdbc9dc8952249bf Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 10:10:22 -0300 Subject: [media] rtl2832: wrap DVBv5 BER to DVBv3 Change legacy DVBv3 read BER to return values calculated by DVBv5 statistics. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 13 ++----------- drivers/media/dvb-frontends/rtl2832_priv.h | 1 + 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 18f150105438..90d4f45d9958 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -805,20 +805,11 @@ static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) { struct rtl2832_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - int ret; - u8 buf[2]; - - ret = rtl2832_rd_regs(dev, 0x4e, 3, buf, 2); - if (ret) - goto err; - *ber = buf[0] << 8 | buf[1]; + *ber = (dev->post_bit_error - dev->post_bit_error_prev); + dev->post_bit_error_prev = dev->post_bit_error; return 0; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static void rtl2832_stat_work(struct work_struct *work) diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 5e90cd49d780..a44614c7af21 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -36,6 +36,7 @@ struct rtl2832_dev { struct dvb_frontend fe; struct delayed_work stat_work; fe_status_t fe_status; + u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ u64 post_bit_error; u64 post_bit_count; bool i2c_gate_state; -- cgit v1.2.3 From 25ef9f554713bc329523b615861db7cbc443106a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 11:00:50 -0300 Subject: [media] rtl2832: implement DVBv5 signal strength statistics Estimate signal strength from IF digital AGC. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 90d4f45d9958..6aaaec2a40c2 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -474,6 +474,8 @@ static int rtl2832_init(struct dvb_frontend *fe) goto err; #endif /* init stats here in order signal app which stats are supported */ + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->cnr.len = 1; c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; c->post_bit_error.len = 1; @@ -823,6 +825,24 @@ static void rtl2832_stat_work(struct work_struct *work) dev_dbg(&client->dev, "\n"); + /* signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + /* read digital AGC */ + ret = rtl2832_bulk_read(client, 0x305, &u8tmp, 1); + if (ret) + goto err; + + dev_dbg(&client->dev, "digital agc=%02x", u8tmp); + + u8tmp = ~u8tmp; + u16tmp = u8tmp << 8 | u8tmp << 0; + + c->strength.stat[0].scale = FE_SCALE_RELATIVE; + c->strength.stat[0].uvalue = u16tmp; + } else { + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + /* CNR */ if (dev->fe_status & FE_HAS_VITERBI) { unsigned hierarchy, constellation; -- cgit v1.2.3 From 164f3d2a83311b1e6b8f67231b4cd3dc111a6fa2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 11:45:55 -0300 Subject: [media] rtl28xxu: use demod mux I2C adapter for every tuner Tuners are connected to demod I2C adapter. Use that muxed adapter for each tuner. That allows us to get rid of hackish FE gate control solution. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 25c885fda252..ef27ad09384c 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1074,7 +1074,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) switch (priv->tuner) { case TUNER_RTL2832_FC0012: fe = dvb_attach(fc0012_attach, adap->fe[0], - &d->i2c_adap, &rtl2832u_fc0012_config); + priv->demod_i2c_adapter, &rtl2832u_fc0012_config); /* since fc0012 includs reading the signal strength delegate * that to the tuner driver */ @@ -1087,7 +1087,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; case TUNER_RTL2832_FC0013: fe = dvb_attach(fc0013_attach, adap->fe[0], - &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + priv->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); /* fc0013 also supports signal strength reading */ adap->fe[0]->ops.read_signal_strength = @@ -1132,7 +1132,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) } break; case TUNER_RTL2832_FC2580: - fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap, + fe = dvb_attach(fc2580_attach, adap->fe[0], + priv->demod_i2c_adapter, &rtl2832u_fc2580_config); break; case TUNER_RTL2832_TUA9001: @@ -1145,11 +1146,13 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) if (ret) goto err; - fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap, + fe = dvb_attach(tua9001_attach, adap->fe[0], + priv->demod_i2c_adapter, &rtl2832u_tua9001_config); break; case TUNER_RTL2832_R820T: - fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, + fe = dvb_attach(r820t_attach, adap->fe[0], + priv->demod_i2c_adapter, &rtl2832u_r820t_config); /* Use tuner to get the signal strength */ -- cgit v1.2.3 From c65dbf652da7e4d390c676c4542e1331b52f4989 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 11:56:08 -0300 Subject: [media] rtl2832: drop FE i2c gate control support We don't need it anymore as all users are using muxed I2C adapter. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 33 ------------------------------ drivers/media/dvb-frontends/rtl2832_priv.h | 1 - 2 files changed, 34 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 6aaaec2a40c2..3040502c9649 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -309,30 +309,6 @@ err: } -static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct rtl2832_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - int ret; - - dev_dbg(&client->dev, "enable=%d\n", enable); - - /* gate already open or close */ - if (dev->i2c_gate_state == enable) - return 0; - - ret = rtl2832_wr_demod_reg(dev, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0)); - if (ret) - goto err; - - dev->i2c_gate_state = enable; - - return ret; -err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; -} - static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) { struct rtl2832_dev *dev = fe->demodulator_priv; @@ -932,8 +908,6 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) if (ret) goto err; - dev->i2c_gate_state = false; - return; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -949,9 +923,6 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) /* terminate possible gate closing */ cancel_delayed_work(&dev->i2c_gate_work); - if (dev->i2c_gate_state == chan_id) - return 0; - /* * chan_id 1 is muxed adapter demod provides and chan_id 0 is demod * itself. We need open gate when request is for chan_id 1. On that case @@ -965,8 +936,6 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) if (ret) goto err; - dev->i2c_gate_state = chan_id; - return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); @@ -1017,8 +986,6 @@ static struct dvb_frontend_ops rtl2832_ops = { .read_status = rtl2832_read_status, .read_snr = rtl2832_read_snr, .read_ber = rtl2832_read_ber, - - .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, }; /* diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index a44614c7af21..6f3fe77e8ec5 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -39,7 +39,6 @@ struct rtl2832_dev { u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */ u64 post_bit_error; u64 post_bit_count; - bool i2c_gate_state; bool sleeping; struct delayed_work i2c_gate_work; }; -- cgit v1.2.3 From 1c7da405c6f7def830258349bccdfb96eebcdc61 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 12:15:55 -0300 Subject: [media] rtl2832: define more demod lock statuses Demod lock flags are derived from demod state machine states. States are running from 1 to 11, where highest state 11 means demod is fully locked and streaming. Naturally smaller state numbers means there is some partial locks. Define now state 10 as missing synch and lock. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 3040502c9649..6bcec7506064 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -753,12 +753,10 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) if (tmp == 11) { *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - } - /* TODO find out if this is also true for rtl2832? */ - /*else if (tmp == 10) { + } else if (tmp == 10) { *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI; - }*/ + } dev->fe_status = *status; return ret; -- cgit v1.2.3 From 4b01e01a81b6629878344430531ced347cc2ed5b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 14:07:35 -0300 Subject: [media] rtl2832: implement PID filter Implement PID filter. This demod has PID filter size of 32 PIDs. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 69 ++++++++++++++++++++++++++++++ drivers/media/dvb-frontends/rtl2832.h | 2 + drivers/media/dvb-frontends/rtl2832_priv.h | 1 + 3 files changed, 72 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 6bcec7506064..e59765fa8e7c 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1145,6 +1145,73 @@ err: return ret; } +static int rtl2832_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; + int ret; + u8 u8tmp; + + dev_dbg(&client->dev, "onoff=%d\n", onoff); + + /* enable / disable PID filter */ + if (onoff) + u8tmp = 0x80; + else + u8tmp = 0x00; + + ret = rtl2832_update_bits(client, 0x061, 0xc0, u8tmp); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + +static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, + int onoff) +{ + struct rtl2832_dev *dev = fe->demodulator_priv; + struct i2c_client *client = dev->client; + int ret; + u8 buf[4]; + + dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n", + index, pid, onoff); + + /* skip invalid PIDs (0x2000) */ + if (pid > 0x1fff || index > 32) + return 0; + + if (onoff) + set_bit(index, &dev->filters); + else + clear_bit(index, &dev->filters); + + /* enable / disable PIDs */ + buf[0] = (dev->filters >> 0) & 0xff; + buf[1] = (dev->filters >> 8) & 0xff; + buf[2] = (dev->filters >> 16) & 0xff; + buf[3] = (dev->filters >> 24) & 0xff; + ret = rtl2832_bulk_write(client, 0x062, buf, 4); + if (ret) + goto err; + + /* add PID */ + buf[0] = (pid >> 8) & 0xff; + buf[1] = (pid >> 0) & 0xff; + ret = rtl2832_bulk_write(client, 0x066 + 2 * index, buf, 2); + if (ret) + goto err; + + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; +} + static int rtl2832_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1235,6 +1302,8 @@ static int rtl2832_probe(struct i2c_client *client, pdata->get_i2c_adapter = rtl2832_get_i2c_adapter_; pdata->get_private_i2c_adapter = rtl2832_get_private_i2c_adapter_; pdata->enable_slave_ts = rtl2832_enable_slave_ts; + pdata->pid_filter = rtl2832_pid_filter; + pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl; dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); return 0; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 35e86e6bc751..e79c479d6127 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -78,6 +78,8 @@ struct rtl2832_platform_data { struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); struct i2c_adapter* (*get_private_i2c_adapter)(struct i2c_client *); int (*enable_slave_ts)(struct i2c_client *); + int (*pid_filter)(struct dvb_frontend *, u8, u16, int); + int (*pid_filter_ctrl)(struct dvb_frontend *, int); }; #endif /* RTL2832_H */ diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 6f3fe77e8ec5..216e905763d4 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -41,6 +41,7 @@ struct rtl2832_dev { u64 post_bit_count; bool sleeping; struct delayed_work i2c_gate_work; + unsigned long filters; /* PID filter */ }; struct rtl2832_reg_entry { -- cgit v1.2.3 From e20b0cf2f394304577df86417f37f02e26caa9fa Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 14:10:47 -0300 Subject: [media] rtl28xxu: add support for RTL2832U/RTL2832 PID filter RTL2832 demod integrated into RTL2832U has PID filter. PID filtering is provided by rtl2832 demod driver. Add support for it. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index ef27ad09384c..c64b5ed60ab9 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1599,7 +1599,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, #define rtl2832u_get_rc_config NULL #endif -static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int rtl2831u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); @@ -1608,7 +1608,16 @@ static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) return pdata->pid_filter_ctrl(adap->fe[0], onoff); } -static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +static int rtl2832u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + + return pdata->pid_filter_ctrl(adap->fe[0], onoff); +} + +static int rtl2831u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); @@ -1617,6 +1626,15 @@ static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, return pdata->pid_filter(adap->fe[0], index, pid, onoff); } +static int rtl2832u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + + return pdata->pid_filter(adap->fe[0], index, pid, onoff); +} + static const struct dvb_usb_device_properties rtl2831u_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, @@ -1639,8 +1657,8 @@ static const struct dvb_usb_device_properties rtl2831u_props = { DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl, - .pid_filter = rtl28xxu_pid_filter, + .pid_filter_ctrl = rtl2831u_pid_filter_ctrl, + .pid_filter = rtl2831u_pid_filter, .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, @@ -1667,6 +1685,13 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter_ctrl = rtl2832u_pid_filter_ctrl, + .pid_filter = rtl2832u_pid_filter, + .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, }, -- cgit v1.2.3 From dcadb82a7a1d844f79c83578b5d2840fdb2a3ddd Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 16:23:28 -0300 Subject: [media] rtl2832: use regmap reg cache Enable regmap register cache in order to reduce IO. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index e59765fa8e7c..66f915dd24a6 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -986,6 +986,22 @@ static struct dvb_frontend_ops rtl2832_ops = { .read_ber = rtl2832_read_ber, }; +static bool rtl2832_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x305: + case 0x33c: + case 0x34e: + case 0x351: + case 0x40c ... 0x40d: + return true; + default: + break; + } + + return false; +} + /* * We implement own I2C access routines for regmap in order to get manual access * to I2C adapter lock, which is needed for I2C mux adapter. @@ -1240,9 +1256,11 @@ static int rtl2832_probe(struct i2c_client *client, static const struct regmap_config regmap_config = { .reg_bits = 8, .val_bits = 8, + .volatile_reg = rtl2832_volatile_reg, .max_register = 5 * 0x100, .ranges = regmap_range_cfg, .num_ranges = ARRAY_SIZE(regmap_range_cfg), + .cache_type = REGCACHE_RBTREE, }; dev_dbg(&client->dev, "\n"); -- cgit v1.2.3 From 5e5d52a00fe8b114551a05379ac446497738df7d Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 14 Dec 2014 16:39:37 -0300 Subject: [media] rtl2832: remove unneeded software reset from init() There is no need to do software reset on init() as it is done a bit later on end of set_frontend(). Software reset usually means restarting (resetting to starting point) chip internal state machine (FSM). Naturally it is done after all parameters are programmed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 66f915dd24a6..db0178717f2d 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -434,21 +434,6 @@ static int rtl2832_init(struct dvb_frontend *fe) goto err; } - /* - * r820t NIM code does a software reset here at the demod - - * may not be needed, as there's already a software reset at - * set_params() - */ -#if 1 - /* soft reset */ - ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1); - if (ret) - goto err; - - ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0); - if (ret) - goto err; -#endif /* init stats here in order signal app which stats are supported */ c->strength.len = 1; c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; -- cgit v1.2.3 From eec21beb35a0d45a555ab6ac0a99257a2e7e726a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Dec 2014 01:17:25 -0300 Subject: [media] rtl2832: merge reg page as a part of reg address Chips uses 8-bit register addresses with 5 pages. Extend register address by using register page as a first byte of address, defining virtual register addresses. That is common method of handling register pages and regmap also uses it. Remove page + address conversion glue which was there for regmap. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 314 +++++++++++++---------------- drivers/media/dvb-frontends/rtl2832_priv.h | 3 +- 2 files changed, 144 insertions(+), 173 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index db0178717f2d..f86e9ab8b901 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -25,133 +25,133 @@ #define REG_MASK(b) (BIT(b + 1) - 1) static const struct rtl2832_reg_entry registers[] = { - [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2}, - [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3}, - [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2}, - [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0}, - [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7}, - [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7}, - [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6}, - [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0}, - [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0}, - [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0}, - [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0}, - [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0}, - [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0}, - [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0}, - [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0}, - [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0}, - [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4}, - [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0}, - [DVBT_REG_PI] = {0x0, 0xa, 2, 0}, - [DVBT_PIP_ON] = {0x0, 0x21, 3, 3}, - [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0}, - [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0}, - [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0}, - [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0}, - [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0}, - [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0}, - [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0}, - [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0}, - [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0}, - [DVBT_KB_P1] = {0x1, 0x64, 3, 1}, - [DVBT_KB_P2] = {0x1, 0x64, 6, 4}, - [DVBT_KB_P3] = {0x1, 0x65, 2, 0}, - [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4}, - [DVBT_AD_AVI] = {0x0, 0x9, 1, 0}, - [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2}, - [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4}, - [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0}, - [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3}, - [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0}, - [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3}, - [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0}, - [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6}, - [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0}, - [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0}, - [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2}, - [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4}, - [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3}, - [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2}, - [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4}, - [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0}, - [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3}, - [DVBT_GI_IDX] = {0x3, 0x51, 1, 0}, - [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2}, - [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0}, - [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0}, - [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0}, - [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0}, - [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0}, - [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0}, - [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0}, - [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1}, - [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0}, - [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5}, - [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6}, - [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7}, - [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0}, - [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0}, - [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0}, - [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0}, - [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6}, - [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0}, - [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6}, - [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0}, - [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0}, - [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0}, - [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0}, - [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1}, - [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1}, - [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7}, - [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0}, - [DVBT_VTOP1] = {0x1, 0x6, 5, 0}, - [DVBT_VTOP2] = {0x1, 0xc9, 5, 0}, - [DVBT_VTOP3] = {0x1, 0xca, 5, 0}, - [DVBT_KRF1] = {0x1, 0xcb, 7, 0}, - [DVBT_KRF2] = {0x1, 0x7, 7, 0}, - [DVBT_KRF3] = {0x1, 0xcd, 7, 0}, - [DVBT_KRF4] = {0x1, 0xce, 7, 0}, - [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0}, - [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0}, - [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0}, - [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0}, - [DVBT_THD_DW1] = {0x1, 0xde, 7, 0}, - [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0}, - [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3}, - [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0}, - [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5}, - [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6}, - [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7}, - [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0}, - [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1}, - [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2}, - [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3}, - [DVBT_SERIAL] = {0x1, 0x7c, 4, 4}, - [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5}, - [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0}, - [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4}, - [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7}, - [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6}, - [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4}, - [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3}, - [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2}, - [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1}, - [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0}, - [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4}, - [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3}, - [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2}, - [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1}, - [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0}, - [DVBT_SM_PASS] = {0x1, 0x93, 11, 0}, - [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0}, - [DVBT_RSSI_R] = {0x3, 0x1, 6, 0}, - [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0}, - [DVBT_REG_MON] = {0x0, 0xd, 1, 0}, - [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2}, - [DVBT_REG_GPE] = {0x0, 0xd, 7, 7}, - [DVBT_REG_GPO] = {0x0, 0x10, 0, 0}, - [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0}, + [DVBT_SOFT_RST] = {0x101, 2, 2}, + [DVBT_IIC_REPEAT] = {0x101, 3, 3}, + [DVBT_TR_WAIT_MIN_8K] = {0x188, 11, 2}, + [DVBT_RSD_BER_FAIL_VAL] = {0x18f, 15, 0}, + [DVBT_EN_BK_TRK] = {0x1a6, 7, 7}, + [DVBT_AD_EN_REG] = {0x008, 7, 7}, + [DVBT_AD_EN_REG1] = {0x008, 6, 6}, + [DVBT_EN_BBIN] = {0x1b1, 0, 0}, + [DVBT_MGD_THD0] = {0x195, 7, 0}, + [DVBT_MGD_THD1] = {0x196, 7, 0}, + [DVBT_MGD_THD2] = {0x197, 7, 0}, + [DVBT_MGD_THD3] = {0x198, 7, 0}, + [DVBT_MGD_THD4] = {0x199, 7, 0}, + [DVBT_MGD_THD5] = {0x19a, 7, 0}, + [DVBT_MGD_THD6] = {0x19b, 7, 0}, + [DVBT_MGD_THD7] = {0x19c, 7, 0}, + [DVBT_EN_CACQ_NOTCH] = {0x161, 4, 4}, + [DVBT_AD_AV_REF] = {0x009, 6, 0}, + [DVBT_REG_PI] = {0x00a, 2, 0}, + [DVBT_PIP_ON] = {0x021, 3, 3}, + [DVBT_SCALE1_B92] = {0x292, 7, 0}, + [DVBT_SCALE1_B93] = {0x293, 7, 0}, + [DVBT_SCALE1_BA7] = {0x2a7, 7, 0}, + [DVBT_SCALE1_BA9] = {0x2a9, 7, 0}, + [DVBT_SCALE1_BAA] = {0x2aa, 7, 0}, + [DVBT_SCALE1_BAB] = {0x2ab, 7, 0}, + [DVBT_SCALE1_BAC] = {0x2ac, 7, 0}, + [DVBT_SCALE1_BB0] = {0x2b0, 7, 0}, + [DVBT_SCALE1_BB1] = {0x2b1, 7, 0}, + [DVBT_KB_P1] = {0x164, 3, 1}, + [DVBT_KB_P2] = {0x164, 6, 4}, + [DVBT_KB_P3] = {0x165, 2, 0}, + [DVBT_OPT_ADC_IQ] = {0x006, 5, 4}, + [DVBT_AD_AVI] = {0x009, 1, 0}, + [DVBT_AD_AVQ] = {0x009, 3, 2}, + [DVBT_K1_CR_STEP12] = {0x2ad, 9, 4}, + [DVBT_TRK_KS_P2] = {0x16f, 2, 0}, + [DVBT_TRK_KS_I2] = {0x170, 5, 3}, + [DVBT_TR_THD_SET2] = {0x172, 3, 0}, + [DVBT_TRK_KC_P2] = {0x173, 5, 3}, + [DVBT_TRK_KC_I2] = {0x175, 2, 0}, + [DVBT_CR_THD_SET2] = {0x176, 7, 6}, + [DVBT_PSET_IFFREQ] = {0x119, 21, 0}, + [DVBT_SPEC_INV] = {0x115, 0, 0}, + [DVBT_RSAMP_RATIO] = {0x19f, 27, 2}, + [DVBT_CFREQ_OFF_RATIO] = {0x19d, 23, 4}, + [DVBT_FSM_STAGE] = {0x351, 6, 3}, + [DVBT_RX_CONSTEL] = {0x33c, 3, 2}, + [DVBT_RX_HIER] = {0x33c, 6, 4}, + [DVBT_RX_C_RATE_LP] = {0x33d, 2, 0}, + [DVBT_RX_C_RATE_HP] = {0x33d, 5, 3}, + [DVBT_GI_IDX] = {0x351, 1, 0}, + [DVBT_FFT_MODE_IDX] = {0x351, 2, 2}, + [DVBT_RSD_BER_EST] = {0x34e, 15, 0}, + [DVBT_CE_EST_EVM] = {0x40c, 15, 0}, + [DVBT_RF_AGC_VAL] = {0x35b, 13, 0}, + [DVBT_IF_AGC_VAL] = {0x359, 13, 0}, + [DVBT_DAGC_VAL] = {0x305, 7, 0}, + [DVBT_SFREQ_OFF] = {0x318, 13, 0}, + [DVBT_CFREQ_OFF] = {0x35f, 17, 0}, + [DVBT_POLAR_RF_AGC] = {0x00e, 1, 1}, + [DVBT_POLAR_IF_AGC] = {0x00e, 0, 0}, + [DVBT_AAGC_HOLD] = {0x104, 5, 5}, + [DVBT_EN_RF_AGC] = {0x104, 6, 6}, + [DVBT_EN_IF_AGC] = {0x104, 7, 7}, + [DVBT_IF_AGC_MIN] = {0x108, 7, 0}, + [DVBT_IF_AGC_MAX] = {0x109, 7, 0}, + [DVBT_RF_AGC_MIN] = {0x10a, 7, 0}, + [DVBT_RF_AGC_MAX] = {0x10b, 7, 0}, + [DVBT_IF_AGC_MAN] = {0x10c, 6, 6}, + [DVBT_IF_AGC_MAN_VAL] = {0x10c, 13, 0}, + [DVBT_RF_AGC_MAN] = {0x10e, 6, 6}, + [DVBT_RF_AGC_MAN_VAL] = {0x10e, 13, 0}, + [DVBT_DAGC_TRG_VAL] = {0x112, 7, 0}, + [DVBT_AGC_TARG_VAL_0] = {0x102, 0, 0}, + [DVBT_AGC_TARG_VAL_8_1] = {0x103, 7, 0}, + [DVBT_AAGC_LOOP_GAIN] = {0x1c7, 5, 1}, + [DVBT_LOOP_GAIN2_3_0] = {0x104, 4, 1}, + [DVBT_LOOP_GAIN2_4] = {0x105, 7, 7}, + [DVBT_LOOP_GAIN3] = {0x1c8, 4, 0}, + [DVBT_VTOP1] = {0x106, 5, 0}, + [DVBT_VTOP2] = {0x1c9, 5, 0}, + [DVBT_VTOP3] = {0x1ca, 5, 0}, + [DVBT_KRF1] = {0x1cb, 7, 0}, + [DVBT_KRF2] = {0x107, 7, 0}, + [DVBT_KRF3] = {0x1cd, 7, 0}, + [DVBT_KRF4] = {0x1ce, 7, 0}, + [DVBT_EN_GI_PGA] = {0x1e5, 0, 0}, + [DVBT_THD_LOCK_UP] = {0x1d9, 8, 0}, + [DVBT_THD_LOCK_DW] = {0x1db, 8, 0}, + [DVBT_THD_UP1] = {0x1dd, 7, 0}, + [DVBT_THD_DW1] = {0x1de, 7, 0}, + [DVBT_INTER_CNT_LEN] = {0x1d8, 3, 0}, + [DVBT_GI_PGA_STATE] = {0x1e6, 3, 3}, + [DVBT_EN_AGC_PGA] = {0x1d7, 0, 0}, + [DVBT_CKOUTPAR] = {0x17b, 5, 5}, + [DVBT_CKOUT_PWR] = {0x17b, 6, 6}, + [DVBT_SYNC_DUR] = {0x17b, 7, 7}, + [DVBT_ERR_DUR] = {0x17c, 0, 0}, + [DVBT_SYNC_LVL] = {0x17c, 1, 1}, + [DVBT_ERR_LVL] = {0x17c, 2, 2}, + [DVBT_VAL_LVL] = {0x17c, 3, 3}, + [DVBT_SERIAL] = {0x17c, 4, 4}, + [DVBT_SER_LSB] = {0x17c, 5, 5}, + [DVBT_CDIV_PH0] = {0x17d, 3, 0}, + [DVBT_CDIV_PH1] = {0x17d, 7, 4}, + [DVBT_MPEG_IO_OPT_2_2] = {0x006, 7, 7}, + [DVBT_MPEG_IO_OPT_1_0] = {0x007, 7, 6}, + [DVBT_CKOUTPAR_PIP] = {0x0b7, 4, 4}, + [DVBT_CKOUT_PWR_PIP] = {0x0b7, 3, 3}, + [DVBT_SYNC_LVL_PIP] = {0x0b7, 2, 2}, + [DVBT_ERR_LVL_PIP] = {0x0b7, 1, 1}, + [DVBT_VAL_LVL_PIP] = {0x0b7, 0, 0}, + [DVBT_CKOUTPAR_PID] = {0x0b9, 4, 4}, + [DVBT_CKOUT_PWR_PID] = {0x0b9, 3, 3}, + [DVBT_SYNC_LVL_PID] = {0x0b9, 2, 2}, + [DVBT_ERR_LVL_PID] = {0x0b9, 1, 1}, + [DVBT_VAL_LVL_PID] = {0x0b9, 0, 0}, + [DVBT_SM_PASS] = {0x193, 11, 0}, + [DVBT_AD7_SETTING] = {0x011, 15, 0}, + [DVBT_RSSI_R] = {0x301, 6, 0}, + [DVBT_ACI_DET_IND] = {0x312, 0, 0}, + [DVBT_REG_MON] = {0x00d, 1, 0}, + [DVBT_REG_MONSEL] = {0x00d, 2, 2}, + [DVBT_REG_GPE] = {0x00d, 7, 7}, + [DVBT_REG_GPO] = {0x010, 0, 0}, + [DVBT_REG_4MSEL] = {0x013, 0, 0}, }; /* Our regmap is bypassing I2C adapter lock, thus we do it! */ @@ -191,38 +191,13 @@ int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, void *val, return ret; } -/* write multiple registers */ -static int rtl2832_wr_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) -{ - return rtl2832_bulk_write(dev->client, page << 8 | reg, val, len); -} - -/* read multiple registers */ -static int rtl2832_rd_regs(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val, int len) -{ - return rtl2832_bulk_read(dev->client, page << 8 | reg, val, len); -} - -/* write single register */ -static int rtl2832_wr_reg(struct rtl2832_dev *dev, u8 reg, u8 page, u8 val) -{ - return rtl2832_wr_regs(dev, reg, page, &val, 1); -} - -/* read single register */ -static int rtl2832_rd_reg(struct rtl2832_dev *dev, u8 reg, u8 page, u8 *val) -{ - return rtl2832_rd_regs(dev, reg, page, val, 1); -} - static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) { struct i2c_client *client = dev->client; int ret; - u8 reg_start_addr; + u16 reg_start_addr; u8 msb, lsb; - u8 page; u8 reading[4]; u32 reading_tmp; int i; @@ -233,12 +208,11 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) reg_start_addr = registers[reg].start_address; msb = registers[reg].msb; lsb = registers[reg].lsb; - page = registers[reg].page; len = (msb >> 3) + 1; mask = REG_MASK(msb - lsb); - ret = rtl2832_rd_regs(dev, reg_start_addr, page, &reading[0], len); + ret = rtl2832_bulk_read(client, reg_start_addr, reading, len); if (ret) goto err; @@ -261,9 +235,8 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) struct i2c_client *client = dev->client; int ret, i; u8 len; - u8 reg_start_addr; + u16 reg_start_addr; u8 msb, lsb; - u8 page; u32 mask; @@ -276,13 +249,12 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) reg_start_addr = registers[reg].start_address; msb = registers[reg].msb; lsb = registers[reg].lsb; - page = registers[reg].page; len = (msb >> 3) + 1; mask = REG_MASK(msb - lsb); - ret = rtl2832_rd_regs(dev, reg_start_addr, page, &reading[0], len); + ret = rtl2832_bulk_read(client, reg_start_addr, reading, len); if (ret) goto err; @@ -297,7 +269,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) for (i = 0; i < len; i++) writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff; - ret = rtl2832_wr_regs(dev, reg_start_addr, page, &writing[0], len); + ret = rtl2832_bulk_write(client, reg_start_addr, writing, len); if (ret) goto err; @@ -522,7 +494,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) fe->ops.tuner_ops.set_params(fe); /* PIP mode related */ - ret = rtl2832_wr_regs(dev, 0x92, 1, "\x00\x0f\xff", 3); + ret = rtl2832_bulk_write(client, 0x192, "\x00\x0f\xff", 3); if (ret) goto err; @@ -560,7 +532,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) } for (j = 0; j < sizeof(bw_params[0]); j++) { - ret = rtl2832_wr_regs(dev, 0x1c+j, 1, &bw_params[i][j], 1); + ret = rtl2832_bulk_write(client, 0x11c + j, &bw_params[i][j], 1); if (ret) goto err; } @@ -616,11 +588,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe) if (dev->sleeping) return 0; - ret = rtl2832_rd_regs(dev, 0x3c, 3, buf, 2); + ret = rtl2832_bulk_read(client, 0x33c, buf, 2); if (ret) goto err; - ret = rtl2832_rd_reg(dev, 0x51, 3, &buf[2]); + ret = rtl2832_bulk_read(client, 0x351, &buf[2], 1); if (ret) goto err; @@ -1103,7 +1075,7 @@ static int rtl2832_enable_slave_ts(struct i2c_client *client) dev_dbg(&client->dev, "\n"); - ret = rtl2832_wr_regs(dev, 0x0c, 1, "\x5f\xff", 2); + ret = rtl2832_bulk_write(client, 0x10c, "\x5f\xff", 2); if (ret) goto err; @@ -1111,23 +1083,23 @@ static int rtl2832_enable_slave_ts(struct i2c_client *client) if (ret) goto err; - ret = rtl2832_wr_reg(dev, 0xbc, 0, 0x18); + ret = rtl2832_bulk_write(client, 0x0bc, "\x18", 1); if (ret) goto err; - ret = rtl2832_wr_reg(dev, 0x22, 0, 0x01); + ret = rtl2832_bulk_write(client, 0x022, "\x01", 1); if (ret) goto err; - ret = rtl2832_wr_reg(dev, 0x26, 0, 0x1f); + ret = rtl2832_bulk_write(client, 0x026, "\x1f", 1); if (ret) goto err; - ret = rtl2832_wr_reg(dev, 0x27, 0, 0xff); + ret = rtl2832_bulk_write(client, 0x027, "\xff", 1); if (ret) goto err; - ret = rtl2832_wr_regs(dev, 0x92, 1, "\x7f\xf7\xff", 3); + ret = rtl2832_bulk_write(client, 0x192, "\x7f\xf7\xff", 3); if (ret) goto err; @@ -1284,7 +1256,7 @@ static int rtl2832_probe(struct i2c_client *client, } /* check if the demod is there */ - ret = rtl2832_rd_reg(dev, 0x00, 0x0, &tmp); + ret = rtl2832_bulk_read(client, 0x000, &tmp, 1); if (ret) goto err_i2c_del_mux_adapter; diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 216e905763d4..973892afb916 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -45,8 +45,7 @@ struct rtl2832_dev { }; struct rtl2832_reg_entry { - u8 page; - u8 start_address; + u16 start_address; u8 msb; u8 lsb; }; -- cgit v1.2.3 From 0aa32ef9b38f9683b4ddaab9ac9bee8f75d872d2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Dec 2014 13:34:13 -0300 Subject: [media] rtl2832: provide register IO callbacks Provide register read and write callbacks for SDR module. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 3 +++ drivers/media/dvb-frontends/rtl2832.h | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index f86e9ab8b901..7070713775e8 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1279,6 +1279,9 @@ static int rtl2832_probe(struct i2c_client *client, pdata->enable_slave_ts = rtl2832_enable_slave_ts; pdata->pid_filter = rtl2832_pid_filter; pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl; + pdata->bulk_read = rtl2832_bulk_read; + pdata->bulk_write = rtl2832_bulk_write; + pdata->update_bits = rtl2832_update_bits; dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); return 0; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index e79c479d6127..f86af6f3b370 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -80,6 +80,10 @@ struct rtl2832_platform_data { int (*enable_slave_ts)(struct i2c_client *); int (*pid_filter)(struct dvb_frontend *, u8, u16, int); int (*pid_filter_ctrl)(struct dvb_frontend *, int); + /* Register access for SDR module */ + int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t); + int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t); + int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int); }; #endif /* RTL2832_H */ -- cgit v1.2.3 From 725b7f30463ab54b453a7113e7fb7148cfe636a2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 15 Dec 2014 14:30:02 -0300 Subject: [media] rtl2832_sdr: rename state variable from 's' to 'dev' 'dev' sounds better than 's' for such variable. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 858 +++++++++++++++--------------- 1 file changed, 429 insertions(+), 429 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 2896b47c29d8..3af869c5497d 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -107,7 +107,7 @@ struct rtl2832_sdr_frame_buf { struct list_head list; }; -struct rtl2832_sdr_state { +struct rtl2832_sdr_dev { #define POWER_ON (1 << 1) #define URB_BUF (1 << 2) unsigned long flags; @@ -161,7 +161,7 @@ struct rtl2832_sdr_state { }; /* write multiple hardware registers */ -static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val, +static int rtl2832_sdr_wr(struct rtl2832_sdr_dev *dev, u8 reg, const u8 *val, int len) { int ret; @@ -170,7 +170,7 @@ static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val, u8 buf[MAX_WR_XFER_LEN]; struct i2c_msg msg[1] = { { - .addr = s->cfg->i2c_addr, + .addr = dev->cfg->i2c_addr, .flags = 0, .len = 1 + len, .buf = buf, @@ -183,11 +183,11 @@ static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val, buf[0] = reg; memcpy(&buf[1], val, len); - ret = i2c_transfer(s->i2c, msg, 1); + ret = i2c_transfer(dev->i2c, msg, 1); if (ret == 1) { ret = 0; } else { - dev_err(&s->i2c->dev, + dev_err(&dev->i2c->dev, "%s: I2C wr failed=%d reg=%02x len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; @@ -196,28 +196,28 @@ static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val, } /* read multiple hardware registers */ -static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len) +static int rtl2832_sdr_rd(struct rtl2832_sdr_dev *dev, u8 reg, u8 *val, int len) { int ret; struct i2c_msg msg[2] = { { - .addr = s->cfg->i2c_addr, + .addr = dev->cfg->i2c_addr, .flags = 0, .len = 1, .buf = ®, }, { - .addr = s->cfg->i2c_addr, + .addr = dev->cfg->i2c_addr, .flags = I2C_M_RD, .len = len, .buf = val, } }; - ret = i2c_transfer(s->i2c, msg, 2); + ret = i2c_transfer(dev->i2c, msg, 2); if (ret == 2) { ret = 0; } else { - dev_err(&s->i2c->dev, + dev_err(&dev->i2c->dev, "%s: I2C rd failed=%d reg=%02x len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; @@ -226,7 +226,7 @@ static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len) } /* write multiple registers */ -static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg, +static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg, const u8 *val, int len) { int ret; @@ -234,19 +234,19 @@ static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg, u8 bank = (reg >> 8) & 0xff; /* switch bank if needed */ - if (bank != s->bank) { - ret = rtl2832_sdr_wr(s, 0x00, &bank, 1); + if (bank != dev->bank) { + ret = rtl2832_sdr_wr(dev, 0x00, &bank, 1); if (ret) return ret; - s->bank = bank; + dev->bank = bank; } - return rtl2832_sdr_wr(s, reg2, val, len); + return rtl2832_sdr_wr(dev, reg2, val, len); } /* read multiple registers */ -static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val, +static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val, int len) { int ret; @@ -254,33 +254,33 @@ static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val, u8 bank = (reg >> 8) & 0xff; /* switch bank if needed */ - if (bank != s->bank) { - ret = rtl2832_sdr_wr(s, 0x00, &bank, 1); + if (bank != dev->bank) { + ret = rtl2832_sdr_wr(dev, 0x00, &bank, 1); if (ret) return ret; - s->bank = bank; + dev->bank = bank; } - return rtl2832_sdr_rd(s, reg2, val, len); + return rtl2832_sdr_rd(dev, reg2, val, len); } /* write single register */ -static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val) +static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val) { - return rtl2832_sdr_wr_regs(s, reg, &val, 1); + return rtl2832_sdr_wr_regs(dev, reg, &val, 1); } #if 0 /* read single register */ -static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val) +static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val) { - return rtl2832_sdr_rd_regs(s, reg, val, 1); + return rtl2832_sdr_rd_regs(dev, reg, val, 1); } #endif /* write single register with mask */ -static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg, +static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg, u8 val, u8 mask) { int ret; @@ -288,7 +288,7 @@ static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg, /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1); + ret = rtl2832_sdr_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -297,18 +297,18 @@ static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg, val |= tmp; } - return rtl2832_sdr_wr_regs(s, reg, &val, 1); + return rtl2832_sdr_wr_regs(dev, reg, &val, 1); } #if 0 /* read single register with mask */ -static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg, +static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val, u8 mask) { int ret, i; u8 tmp; - ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1); + ret = rtl2832_sdr_rd_regs(dev, reg, &tmp, 1); if (ret) return ret; @@ -327,33 +327,33 @@ static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg, /* Private functions */ static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( - struct rtl2832_sdr_state *s) + struct rtl2832_sdr_dev *dev) { unsigned long flags; struct rtl2832_sdr_frame_buf *buf = NULL; - spin_lock_irqsave(&s->queued_bufs_lock, flags); - if (list_empty(&s->queued_bufs)) + spin_lock_irqsave(&dev->queued_bufs_lock, flags); + if (list_empty(&dev->queued_bufs)) goto leave; - buf = list_entry(s->queued_bufs.next, + buf = list_entry(dev->queued_bufs.next, struct rtl2832_sdr_frame_buf, list); list_del(&buf->list); leave: - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); + spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); return buf; } -static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, +static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev, void *dst, const u8 *src, unsigned int src_len) { unsigned int dst_len; - if (s->pixelformat == V4L2_SDR_FMT_CU8) { + if (dev->pixelformat == V4L2_SDR_FMT_CU8) { /* native stream, no need to convert */ memcpy(dst, src, src_len); dst_len = src_len; - } else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) { + } else if (dev->pixelformat == V4L2_SDR_FMT_CU16LE) { /* convert u8 to u16 */ unsigned int i; u16 *u16dst = dst; @@ -366,22 +366,22 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, } /* calculate sample rate and output it in 10 seconds intervals */ - if (unlikely(time_is_before_jiffies(s->jiffies_next))) { + if (unlikely(time_is_before_jiffies(dev->jiffies_next))) { #define MSECS 10000UL unsigned int msecs = jiffies_to_msecs(jiffies - - s->jiffies_next + msecs_to_jiffies(MSECS)); - unsigned int samples = s->sample - s->sample_measured; + dev->jiffies_next + msecs_to_jiffies(MSECS)); + unsigned int samples = dev->sample - dev->sample_measured; - s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); - s->sample_measured = s->sample; - dev_dbg(&s->udev->dev, + dev->jiffies_next = jiffies + msecs_to_jiffies(MSECS); + dev->sample_measured = dev->sample; + dev_dbg(&dev->udev->dev, "slen=%u samples=%u msecs=%u sample rate=%lu\n", src_len, samples, msecs, samples * 1000UL / msecs); } /* total number of I+Q pairs */ - s->sample += src_len / 2; + dev->sample += src_len / 2; return dst_len; } @@ -392,10 +392,10 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, */ static void rtl2832_sdr_urb_complete(struct urb *urb) { - struct rtl2832_sdr_state *s = urb->context; + struct rtl2832_sdr_dev *dev = urb->context; struct rtl2832_sdr_frame_buf *fbuf; - dev_dbg_ratelimited(&s->udev->dev, + dev_dbg_ratelimited(&dev->udev->dev, "status=%d length=%d/%d errors=%d\n", urb->status, urb->actual_length, urb->transfer_buffer_length, urb->error_count); @@ -409,7 +409,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) case -ESHUTDOWN: return; default: /* error */ - dev_err_ratelimited(&s->udev->dev, "urb failed=%d\n", + dev_err_ratelimited(&dev->udev->dev, "urb failed=%d\n", urb->status); break; } @@ -418,190 +418,190 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) void *ptr; unsigned int len; /* get free framebuffer */ - fbuf = rtl2832_sdr_get_next_fill_buf(s); + fbuf = rtl2832_sdr_get_next_fill_buf(dev); if (unlikely(fbuf == NULL)) { - s->vb_full++; - dev_notice_ratelimited(&s->udev->dev, + dev->vb_full++; + dev_notice_ratelimited(&dev->udev->dev, "videobuf is full, %d packets dropped\n", - s->vb_full); + dev->vb_full); goto skip; } /* fill framebuffer */ ptr = vb2_plane_vaddr(&fbuf->vb, 0); - len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer, + len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer, urb->actual_length); vb2_set_plane_payload(&fbuf->vb, 0, len); v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); - fbuf->vb.v4l2_buf.sequence = s->sequence++; + fbuf->vb.v4l2_buf.sequence = dev->sequence++; vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); } skip: usb_submit_urb(urb, GFP_ATOMIC); } -static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_dev *dev) { int i; - for (i = s->urbs_submitted - 1; i >= 0; i--) { - dev_dbg(&s->udev->dev, "kill urb=%d\n", i); + for (i = dev->urbs_submitted - 1; i >= 0; i--) { + dev_dbg(&dev->udev->dev, "kill urb=%d\n", i); /* stop the URB */ - usb_kill_urb(s->urb_list[i]); + usb_kill_urb(dev->urb_list[i]); } - s->urbs_submitted = 0; + dev->urbs_submitted = 0; return 0; } -static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev) { int i, ret; - for (i = 0; i < s->urbs_initialized; i++) { - dev_dbg(&s->udev->dev, "submit urb=%d\n", i); - ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); + for (i = 0; i < dev->urbs_initialized; i++) { + dev_dbg(&dev->udev->dev, "submit urb=%d\n", i); + ret = usb_submit_urb(dev->urb_list[i], GFP_ATOMIC); if (ret) { - dev_err(&s->udev->dev, + dev_err(&dev->udev->dev, "Could not submit urb no. %d - get them all back\n", i); - rtl2832_sdr_kill_urbs(s); + rtl2832_sdr_kill_urbs(dev); return ret; } - s->urbs_submitted++; + dev->urbs_submitted++; } return 0; } -static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev) { - if (s->flags & USB_STATE_URB_BUF) { - while (s->buf_num) { - s->buf_num--; - dev_dbg(&s->udev->dev, "free buf=%d\n", s->buf_num); - usb_free_coherent(s->udev, s->buf_size, - s->buf_list[s->buf_num], - s->dma_addr[s->buf_num]); + if (dev->flags & USB_STATE_URB_BUF) { + while (dev->buf_num) { + dev->buf_num--; + dev_dbg(&dev->udev->dev, "free buf=%d\n", dev->buf_num); + usb_free_coherent(dev->udev, dev->buf_size, + dev->buf_list[dev->buf_num], + dev->dma_addr[dev->buf_num]); } } - s->flags &= ~USB_STATE_URB_BUF; + dev->flags &= ~USB_STATE_URB_BUF; return 0; } -static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev) { - s->buf_num = 0; - s->buf_size = BULK_BUFFER_SIZE; + dev->buf_num = 0; + dev->buf_size = BULK_BUFFER_SIZE; - dev_dbg(&s->udev->dev, "all in all I will use %u bytes for streaming\n", + dev_dbg(&dev->udev->dev, "all in all I will use %u bytes for streaming\n", MAX_BULK_BUFS * BULK_BUFFER_SIZE); - for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { - s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, + for (dev->buf_num = 0; dev->buf_num < MAX_BULK_BUFS; dev->buf_num++) { + dev->buf_list[dev->buf_num] = usb_alloc_coherent(dev->udev, BULK_BUFFER_SIZE, GFP_ATOMIC, - &s->dma_addr[s->buf_num]); - if (!s->buf_list[s->buf_num]) { - dev_dbg(&s->udev->dev, "alloc buf=%d failed\n", - s->buf_num); - rtl2832_sdr_free_stream_bufs(s); + &dev->dma_addr[dev->buf_num]); + if (!dev->buf_list[dev->buf_num]) { + dev_dbg(&dev->udev->dev, "alloc buf=%d failed\n", + dev->buf_num); + rtl2832_sdr_free_stream_bufs(dev); return -ENOMEM; } - dev_dbg(&s->udev->dev, "alloc buf=%d %p (dma %llu)\n", - s->buf_num, s->buf_list[s->buf_num], - (long long)s->dma_addr[s->buf_num]); - s->flags |= USB_STATE_URB_BUF; + dev_dbg(&dev->udev->dev, "alloc buf=%d %p (dma %llu)\n", + dev->buf_num, dev->buf_list[dev->buf_num], + (long long)dev->dma_addr[dev->buf_num]); + dev->flags |= USB_STATE_URB_BUF; } return 0; } -static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_dev *dev) { int i; - rtl2832_sdr_kill_urbs(s); + rtl2832_sdr_kill_urbs(dev); - for (i = s->urbs_initialized - 1; i >= 0; i--) { - if (s->urb_list[i]) { - dev_dbg(&s->udev->dev, "free urb=%d\n", i); + for (i = dev->urbs_initialized - 1; i >= 0; i--) { + if (dev->urb_list[i]) { + dev_dbg(&dev->udev->dev, "free urb=%d\n", i); /* free the URBs */ - usb_free_urb(s->urb_list[i]); + usb_free_urb(dev->urb_list[i]); } } - s->urbs_initialized = 0; + dev->urbs_initialized = 0; return 0; } -static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev) { int i, j; /* allocate the URBs */ for (i = 0; i < MAX_BULK_BUFS; i++) { - dev_dbg(&s->udev->dev, "alloc urb=%d\n", i); - s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); - if (!s->urb_list[i]) { - dev_dbg(&s->udev->dev, "failed\n"); + dev_dbg(&dev->udev->dev, "alloc urb=%d\n", i); + dev->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); + if (!dev->urb_list[i]) { + dev_dbg(&dev->udev->dev, "failed\n"); for (j = 0; j < i; j++) - usb_free_urb(s->urb_list[j]); + usb_free_urb(dev->urb_list[j]); return -ENOMEM; } - usb_fill_bulk_urb(s->urb_list[i], - s->udev, - usb_rcvbulkpipe(s->udev, 0x81), - s->buf_list[i], + usb_fill_bulk_urb(dev->urb_list[i], + dev->udev, + usb_rcvbulkpipe(dev->udev, 0x81), + dev->buf_list[i], BULK_BUFFER_SIZE, - rtl2832_sdr_urb_complete, s); + rtl2832_sdr_urb_complete, dev); - s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - s->urb_list[i]->transfer_dma = s->dma_addr[i]; - s->urbs_initialized++; + dev->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + dev->urb_list[i]->transfer_dma = dev->dma_addr[i]; + dev->urbs_initialized++; } return 0; } /* Must be called with vb_queue_lock hold */ -static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) +static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev) { unsigned long flags; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - spin_lock_irqsave(&s->queued_bufs_lock, flags); - while (!list_empty(&s->queued_bufs)) { + spin_lock_irqsave(&dev->queued_bufs_lock, flags); + while (!list_empty(&dev->queued_bufs)) { struct rtl2832_sdr_frame_buf *buf; - buf = list_entry(s->queued_bufs.next, + buf = list_entry(dev->queued_bufs.next, struct rtl2832_sdr_frame_buf, list); list_del(&buf->list); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); + spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); } /* The user yanked out the cable... */ static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) { - struct rtl2832_sdr_state *s = fe->sec_priv; + struct rtl2832_sdr_dev *dev = fe->sec_priv; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - mutex_lock(&s->vb_queue_lock); - mutex_lock(&s->v4l2_lock); + mutex_lock(&dev->vb_queue_lock); + mutex_lock(&dev->v4l2_lock); /* No need to keep the urbs around after disconnection */ - s->udev = NULL; + dev->udev = NULL; - v4l2_device_disconnect(&s->v4l2_dev); - video_unregister_device(&s->vdev); - mutex_unlock(&s->v4l2_lock); - mutex_unlock(&s->vb_queue_lock); + v4l2_device_disconnect(&dev->v4l2_dev); + video_unregister_device(&dev->vdev); + mutex_unlock(&dev->v4l2_lock); + mutex_unlock(&dev->vb_queue_lock); - v4l2_device_put(&s->v4l2_dev); + v4l2_device_put(&dev->v4l2_dev); fe->sec_priv = NULL; } @@ -609,13 +609,13 @@ static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) static int rtl2832_sdr_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); - usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); + strlcpy(cap->card, dev->vdev.name, sizeof(cap->card)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -627,26 +627,26 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); + struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "nbuffers=%d\n", *nbuffers); + dev_dbg(&dev->udev->dev, "nbuffers=%d\n", *nbuffers); /* Need at least 8 buffers */ if (vq->num_buffers + *nbuffers < 8) *nbuffers = 8 - vq->num_buffers; *nplanes = 1; - sizes[0] = PAGE_ALIGN(s->buffersize); - dev_dbg(&s->udev->dev, "nbuffers=%d sizes[0]=%d\n", + sizes[0] = PAGE_ALIGN(dev->buffersize); + dev_dbg(&dev->udev->dev, "nbuffers=%d sizes[0]=%d\n", *nbuffers, sizes[0]); return 0; } static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb) { - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); + struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue); /* Don't allow queing new buffers after device disconnection */ - if (!s->udev) + if (!dev->udev) return -ENODEV; return 0; @@ -654,46 +654,46 @@ static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb) static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) { - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); + struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct rtl2832_sdr_frame_buf *buf = container_of(vb, struct rtl2832_sdr_frame_buf, vb); unsigned long flags; /* Check the device has not disconnected between prep and queuing */ - if (!s->udev) { + if (!dev->udev) { vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); return; } - spin_lock_irqsave(&s->queued_bufs_lock, flags); - list_add_tail(&buf->list, &s->queued_bufs); - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); + spin_lock_irqsave(&dev->queued_bufs_lock, flags); + list_add_tail(&buf->list, &dev->queued_bufs); + spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); } -static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) { - struct dvb_frontend *fe = s->fe; + struct dvb_frontend *fe = dev->fe; int ret; unsigned int f_sr, f_if; u8 buf[4], u8tmp1, u8tmp2; u64 u64tmp; u32 u32tmp; - dev_dbg(&s->udev->dev, "f_adc=%u\n", s->f_adc); + dev_dbg(&dev->udev->dev, "f_adc=%u\n", dev->f_adc); - if (!test_bit(POWER_ON, &s->flags)) + if (!test_bit(POWER_ON, &dev->flags)) return 0; - if (s->f_adc == 0) + if (dev->f_adc == 0) return 0; - f_sr = s->f_adc; + f_sr = dev->f_adc; - ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2); + ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4); + ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4); if (ret) goto err; @@ -707,19 +707,19 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) goto err; /* program IF */ - u64tmp = f_if % s->cfg->xtal; + u64tmp = f_if % dev->cfg->xtal; u64tmp *= 0x400000; - u64tmp = div_u64(u64tmp, s->cfg->xtal); + u64tmp = div_u64(u64tmp, dev->cfg->xtal); u64tmp = -u64tmp; u32tmp = u64tmp & 0x3fffff; - dev_dbg(&s->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); + dev_dbg(&dev->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); buf[0] = (u32tmp >> 16) & 0xff; buf[1] = (u32tmp >> 8) & 0xff; buf[2] = (u32tmp >> 0) & 0xff; - ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3); + ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3); if (ret) goto err; @@ -733,208 +733,208 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) u8tmp2 = 0xcd; /* enable ADC I, ADC Q */ } - ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1); + ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1); if (ret) goto err; - ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2); + ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2); if (ret) goto err; - ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80); + ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80); if (ret) goto err; /* program sampling rate (resampling down) */ - u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U); + u32tmp = div_u64(dev->cfg->xtal * 0x400000ULL, f_sr * 4U); u32tmp <<= 2; buf[0] = (u32tmp >> 24) & 0xff; buf[1] = (u32tmp >> 16) & 0xff; buf[2] = (u32tmp >> 8) & 0xff; buf[3] = (u32tmp >> 0) & 0xff; - ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4); + ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4); if (ret) goto err; /* low-pass filter */ - ret = rtl2832_sdr_wr_regs(s, 0x11c, + ret = rtl2832_sdr_wr_regs(dev, 0x11c, "\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5", 20); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2); + ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2); if (ret) goto err; /* mode */ - ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6); + ret = rtl2832_sdr_wr_regs(dev, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6); if (ret) goto err; /* FSM */ - ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3); + ret = rtl2832_sdr_wr_regs(dev, 0x192, "\x00\xf0\x0f", 3); if (ret) goto err; /* PID filter */ - ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x061, "\x60", 1); if (ret) goto err; /* used RF tuner based settings */ - switch (s->cfg->tuner) { + switch (dev->cfg->tuner) { case RTL2832_TUNER_E4000: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1); - ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1); - ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x30", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xd0", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x18", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xd4", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1e5, "\xf0", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d9, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1db, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1dd, "\x14", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1de, "\xec", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d8, "\x0c", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1e6, "\x02", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d7, "\x09", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x83", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x010, "\x49", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x87", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x85", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x013, "\x02", 1); break; case RTL2832_TUNER_FC0012: case RTL2832_TUNER_FC0013: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2); - ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x2c", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x16", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xe9\xbf", 2); + ret = rtl2832_sdr_wr_regs(dev, 0x1e5, "\xf0", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d9, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1db, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1dd, "\x11", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1de, "\xef", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d8, "\x0c", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1e6, "\x02", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1d7, "\x09", 1); break; case RTL2832_TUNER_R820T: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x01", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c7, "\x24", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x104, "\xcc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x105, "\xbe", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c8, "\x14", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x106, "\x35", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1c9, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ca, "\x21", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cb, "\x00", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x107, "\x40", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1cd, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x1ce, "\x10", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x108, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x109, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10a, "\x80", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x10b, "\x7f", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x00e, "\xfc", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1); break; default: - dev_notice(&s->udev->dev, "Unsupported tuner\n"); + dev_notice(&dev->udev->dev, "Unsupported tuner\n"); } /* software reset */ - ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04); + ret = rtl2832_sdr_wr_reg_mask(dev, 0x101, 0x04, 0x04); if (ret) goto err; - ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04); + ret = rtl2832_sdr_wr_reg_mask(dev, 0x101, 0x00, 0x04); if (ret) goto err; err: return ret; }; -static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s) +static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_dev *dev) { int ret; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); /* PID filter */ - ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x061, "\xe0", 1); if (ret) goto err; /* mode */ - ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1); + ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x20", 1); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2); + ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2); if (ret) goto err; /* FSM */ - ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3); + ret = rtl2832_sdr_wr_regs(dev, 0x192, "\x00\x0f\xff", 3); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2); + ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x40\x00", 2); if (ret) goto err; - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4); + ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x06\x3f\xce\xcc", 4); if (ret) goto err; err: return; }; -static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) { - struct dvb_frontend *fe = s->fe; + struct dvb_frontend *fe = dev->fe; struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct v4l2_ctrl *bandwidth_auto; struct v4l2_ctrl *bandwidth; @@ -942,29 +942,29 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) /* * tuner RF (Hz) */ - if (s->f_tuner == 0) + if (dev->f_tuner == 0) return 0; /* * bandwidth (Hz) */ - bandwidth_auto = v4l2_ctrl_find(&s->hdl, + bandwidth_auto = v4l2_ctrl_find(&dev->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); - bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH); + bandwidth = v4l2_ctrl_find(&dev->hdl, V4L2_CID_RF_TUNER_BANDWIDTH); if (v4l2_ctrl_g_ctrl(bandwidth_auto)) { - c->bandwidth_hz = s->f_adc; - v4l2_ctrl_s_ctrl(bandwidth, s->f_adc); + c->bandwidth_hz = dev->f_adc; + v4l2_ctrl_s_ctrl(bandwidth, dev->f_adc); } else { c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth); } - c->frequency = s->f_tuner; + c->frequency = dev->f_tuner; c->delivery_system = SYS_DVBT; - dev_dbg(&s->udev->dev, "frequency=%u bandwidth=%d\n", + dev_dbg(&dev->udev->dev, "frequency=%u bandwidth=%d\n", c->frequency, c->bandwidth_hz); - if (!test_bit(POWER_ON, &s->flags)) + if (!test_bit(POWER_ON, &dev->flags)) return 0; if (fe->ops.tuner_ops.set_params) @@ -973,11 +973,11 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) return 0; }; -static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s) +static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev) { - struct dvb_frontend *fe = s->fe; + struct dvb_frontend *fe = dev->fe; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); if (fe->ops.tuner_ops.init) fe->ops.tuner_ops.init(fe); @@ -985,11 +985,11 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s) return 0; }; -static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s) +static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev) { - struct dvb_frontend *fe = s->fe; + struct dvb_frontend *fe = dev->fe; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); if (fe->ops.tuner_ops.sleep) fe->ops.tuner_ops.sleep(fe); @@ -999,83 +999,83 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s) static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) { - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); + struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); int ret; - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - if (!s->udev) + if (!dev->udev) return -ENODEV; - if (mutex_lock_interruptible(&s->v4l2_lock)) + if (mutex_lock_interruptible(&dev->v4l2_lock)) return -ERESTARTSYS; - if (s->d->props->power_ctrl) - s->d->props->power_ctrl(s->d, 1); + if (dev->d->props->power_ctrl) + dev->d->props->power_ctrl(dev->d, 1); /* enable ADC */ - if (s->d->props->frontend_ctrl) - s->d->props->frontend_ctrl(s->fe, 1); + if (dev->d->props->frontend_ctrl) + dev->d->props->frontend_ctrl(dev->fe, 1); - set_bit(POWER_ON, &s->flags); + set_bit(POWER_ON, &dev->flags); - ret = rtl2832_sdr_set_tuner(s); + ret = rtl2832_sdr_set_tuner(dev); if (ret) goto err; - ret = rtl2832_sdr_set_tuner_freq(s); + ret = rtl2832_sdr_set_tuner_freq(dev); if (ret) goto err; - ret = rtl2832_sdr_set_adc(s); + ret = rtl2832_sdr_set_adc(dev); if (ret) goto err; - ret = rtl2832_sdr_alloc_stream_bufs(s); + ret = rtl2832_sdr_alloc_stream_bufs(dev); if (ret) goto err; - ret = rtl2832_sdr_alloc_urbs(s); + ret = rtl2832_sdr_alloc_urbs(dev); if (ret) goto err; - s->sequence = 0; + dev->sequence = 0; - ret = rtl2832_sdr_submit_urbs(s); + ret = rtl2832_sdr_submit_urbs(dev); if (ret) goto err; err: - mutex_unlock(&s->v4l2_lock); + mutex_unlock(&dev->v4l2_lock); return ret; } static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) { - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); + struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - mutex_lock(&s->v4l2_lock); + mutex_lock(&dev->v4l2_lock); - rtl2832_sdr_kill_urbs(s); - rtl2832_sdr_free_urbs(s); - rtl2832_sdr_free_stream_bufs(s); - rtl2832_sdr_cleanup_queued_bufs(s); - rtl2832_sdr_unset_adc(s); - rtl2832_sdr_unset_tuner(s); + rtl2832_sdr_kill_urbs(dev); + rtl2832_sdr_free_urbs(dev); + rtl2832_sdr_free_stream_bufs(dev); + rtl2832_sdr_cleanup_queued_bufs(dev); + rtl2832_sdr_unset_adc(dev); + rtl2832_sdr_unset_tuner(dev); - clear_bit(POWER_ON, &s->flags); + clear_bit(POWER_ON, &dev->flags); /* disable ADC */ - if (s->d->props->frontend_ctrl) - s->d->props->frontend_ctrl(s->fe, 0); + if (dev->d->props->frontend_ctrl) + dev->d->props->frontend_ctrl(dev->fe, 0); - if (s->d->props->power_ctrl) - s->d->props->power_ctrl(s->d, 0); + if (dev->d->props->power_ctrl) + dev->d->props->power_ctrl(dev->d, 0); - mutex_unlock(&s->v4l2_lock); + mutex_unlock(&dev->v4l2_lock); } static struct vb2_ops rtl2832_sdr_vb2_ops = { @@ -1091,9 +1091,9 @@ static struct vb2_ops rtl2832_sdr_vb2_ops = { static int rtl2832_sdr_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "index=%d type=%d\n", v->index, v->type); + dev_dbg(&dev->udev->dev, "index=%d type=%d\n", v->index, v->type); if (v->index == 0) { strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); @@ -1117,9 +1117,9 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, static int rtl2832_sdr_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *v) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); if (v->index > 1) return -EINVAL; @@ -1129,9 +1129,9 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv, static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "tuner=%d type=%d index=%d\n", + dev_dbg(&dev->udev->dev, "tuner=%d type=%d index=%d\n", band->tuner, band->type, band->index); if (band->tuner == 0) { @@ -1154,17 +1154,17 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, static int rtl2832_sdr_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); int ret = 0; - dev_dbg(&s->udev->dev, "tuner=%d type=%d\n", + dev_dbg(&dev->udev->dev, "tuner=%d type=%d\n", f->tuner, f->type); if (f->tuner == 0) { - f->frequency = s->f_adc; + f->frequency = dev->f_adc; f->type = V4L2_TUNER_ADC; } else if (f->tuner == 1) { - f->frequency = s->f_tuner; + f->frequency = dev->f_tuner; f->type = V4L2_TUNER_RF; } else { return -EINVAL; @@ -1176,10 +1176,10 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv, static int rtl2832_sdr_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); int ret, band; - dev_dbg(&s->udev->dev, "tuner=%d type=%d frequency=%u\n", + dev_dbg(&dev->udev->dev, "tuner=%d type=%d frequency=%u\n", f->tuner, f->type, f->frequency); /* ADC band midpoints */ @@ -1194,19 +1194,19 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, else band = 2; - s->f_adc = clamp_t(unsigned int, f->frequency, + dev->f_adc = clamp_t(unsigned int, f->frequency, bands_adc[band].rangelow, bands_adc[band].rangehigh); - dev_dbg(&s->udev->dev, "ADC frequency=%u Hz\n", s->f_adc); - ret = rtl2832_sdr_set_adc(s); + dev_dbg(&dev->udev->dev, "ADC frequency=%u Hz\n", dev->f_adc); + ret = rtl2832_sdr_set_adc(dev); } else if (f->tuner == 1) { - s->f_tuner = clamp_t(unsigned int, f->frequency, + dev->f_tuner = clamp_t(unsigned int, f->frequency, bands_fm[0].rangelow, bands_fm[0].rangehigh); - dev_dbg(&s->udev->dev, "RF frequency=%u Hz\n", f->frequency); + dev_dbg(&dev->udev->dev, "RF frequency=%u Hz\n", f->frequency); - ret = rtl2832_sdr_set_tuner_freq(s); + ret = rtl2832_sdr_set_tuner_freq(dev); } else { ret = -EINVAL; } @@ -1217,11 +1217,11 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - if (f->index >= s->num_formats) + if (f->index >= dev->num_formats) return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); @@ -1233,12 +1233,12 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); - dev_dbg(&s->udev->dev, "\n"); + dev_dbg(&dev->udev->dev, "\n"); - f->fmt.sdr.pixelformat = s->pixelformat; - f->fmt.sdr.buffersize = s->buffersize; + f->fmt.sdr.pixelformat = dev->pixelformat; + f->fmt.sdr.buffersize = dev->buffersize; memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); @@ -1248,28 +1248,28 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); - struct vb2_queue *q = &s->vb_queue; + struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct vb2_queue *q = &dev->vb_queue; int i; - dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", + dev_dbg(&dev->udev->dev, "pixelformat fourcc %4.4s\n", (char *)&f->fmt.sdr.pixelformat); if (vb2_is_busy(q)) return -EBUSY; memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < s->num_formats; i++) { + for (i = 0; i < dev->num_formats; i++) { if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { - s->pixelformat = formats[i].pixelformat; - s->buffersize = formats[i].buffersize; + dev->pixelformat = formats[i].pixelformat; + dev->buffersize = formats[i].buffersize; f->fmt.sdr.buffersize = formats[i].buffersize; return 0; } } - s->pixelformat = formats[0].pixelformat; - s->buffersize = formats[0].buffersize; + dev->pixelformat = formats[0].pixelformat; + dev->buffersize = formats[0].buffersize; f->fmt.sdr.pixelformat = formats[0].pixelformat; f->fmt.sdr.buffersize = formats[0].buffersize; @@ -1279,14 +1279,14 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct rtl2832_sdr_state *s = video_drvdata(file); + struct rtl2832_sdr_dev *dev = video_drvdata(file); int i; - dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", + dev_dbg(&dev->udev->dev, "pixelformat fourcc %4.4s\n", (char *)&f->fmt.sdr.pixelformat); memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < s->num_formats; i++) { + for (i = 0; i < dev->num_formats; i++) { if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { f->fmt.sdr.buffersize = formats[i].buffersize; return 0; @@ -1348,14 +1348,14 @@ static struct video_device rtl2832_sdr_template = { static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) { - struct rtl2832_sdr_state *s = - container_of(ctrl->handler, struct rtl2832_sdr_state, + struct rtl2832_sdr_dev *dev = + container_of(ctrl->handler, struct rtl2832_sdr_dev, hdl); - struct dvb_frontend *fe = s->fe; + struct dvb_frontend *fe = dev->fe; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; - dev_dbg(&s->udev->dev, + dev_dbg(&dev->udev->dev, "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum, ctrl->step); @@ -1364,21 +1364,21 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: case V4L2_CID_RF_TUNER_BANDWIDTH: /* TODO: these controls should be moved to tuner drivers */ - if (s->bandwidth_auto->val) { + if (dev->bandwidth_auto->val) { /* Round towards the closest legal value */ - s32 val = s->f_adc + div_u64(s->bandwidth->step, 2); + s32 val = dev->f_adc + div_u64(dev->bandwidth->step, 2); u32 offset; - val = clamp_t(s32, val, s->bandwidth->minimum, - s->bandwidth->maximum); - offset = val - s->bandwidth->minimum; - offset = s->bandwidth->step * - div_u64(offset, s->bandwidth->step); - s->bandwidth->val = s->bandwidth->minimum + offset; + val = clamp_t(s32, val, dev->bandwidth->minimum, + dev->bandwidth->maximum); + offset = val - dev->bandwidth->minimum; + offset = dev->bandwidth->step * + div_u64(offset, dev->bandwidth->step); + dev->bandwidth->val = dev->bandwidth->minimum + offset; } - c->bandwidth_hz = s->bandwidth->val; + c->bandwidth_hz = dev->bandwidth->val; - if (!test_bit(POWER_ON, &s->flags)) + if (!test_bit(POWER_ON, &dev->flags)) return 0; if (fe->ops.tuner_ops.set_params) @@ -1399,12 +1399,12 @@ static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = { static void rtl2832_sdr_video_release(struct v4l2_device *v) { - struct rtl2832_sdr_state *s = - container_of(v, struct rtl2832_sdr_state, v4l2_dev); + struct rtl2832_sdr_dev *dev = + container_of(v, struct rtl2832_sdr_dev, v4l2_dev); - v4l2_ctrl_handler_free(&s->hdl); - v4l2_device_unregister(&s->v4l2_dev); - kfree(s); + v4l2_ctrl_handler_free(&dev->hdl); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); } struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, @@ -1412,138 +1412,138 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, struct v4l2_subdev *sd) { int ret; - struct rtl2832_sdr_state *s; + struct rtl2832_sdr_dev *dev; const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops; struct dvb_usb_device *d = i2c_get_adapdata(i2c); - s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL); - if (s == NULL) { + dev = kzalloc(sizeof(struct rtl2832_sdr_dev), GFP_KERNEL); + if (dev == NULL) { dev_err(&d->udev->dev, - "Could not allocate memory for rtl2832_sdr_state\n"); + "Could not allocate memory for rtl2832_sdr_dev\n"); return NULL; } /* setup the state */ - s->fe = fe; - s->d = d; - s->udev = d->udev; - s->i2c = i2c; - s->cfg = cfg; - s->f_adc = bands_adc[0].rangelow; - s->f_tuner = bands_fm[0].rangelow; - s->pixelformat = formats[0].pixelformat; - s->buffersize = formats[0].buffersize; - s->num_formats = NUM_FORMATS; + dev->fe = fe; + dev->d = d; + dev->udev = d->udev; + dev->i2c = i2c; + dev->cfg = cfg; + dev->f_adc = bands_adc[0].rangelow; + dev->f_tuner = bands_fm[0].rangelow; + dev->pixelformat = formats[0].pixelformat; + dev->buffersize = formats[0].buffersize; + dev->num_formats = NUM_FORMATS; if (!rtl2832_sdr_emulated_fmt) - s->num_formats -= 1; + dev->num_formats -= 1; - mutex_init(&s->v4l2_lock); - mutex_init(&s->vb_queue_lock); - spin_lock_init(&s->queued_bufs_lock); - INIT_LIST_HEAD(&s->queued_bufs); + mutex_init(&dev->v4l2_lock); + mutex_init(&dev->vb_queue_lock); + spin_lock_init(&dev->queued_bufs_lock); + INIT_LIST_HEAD(&dev->queued_bufs); /* Init videobuf2 queue structure */ - s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; - s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - s->vb_queue.drv_priv = s; - s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf); - s->vb_queue.ops = &rtl2832_sdr_vb2_ops; - s->vb_queue.mem_ops = &vb2_vmalloc_memops; - s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - ret = vb2_queue_init(&s->vb_queue); + dev->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; + dev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; + dev->vb_queue.drv_priv = dev; + dev->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf); + dev->vb_queue.ops = &rtl2832_sdr_vb2_ops; + dev->vb_queue.mem_ops = &vb2_vmalloc_memops; + dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + ret = vb2_queue_init(&dev->vb_queue); if (ret) { - dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); + dev_err(&dev->udev->dev, "Could not initialize vb2 queue\n"); goto err_free_mem; } /* Register controls */ - switch (s->cfg->tuner) { + switch (dev->cfg->tuner) { case RTL2832_TUNER_E4000: - v4l2_ctrl_handler_init(&s->hdl, 9); + v4l2_ctrl_handler_init(&dev->hdl, 9); if (sd) - v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL); + v4l2_ctrl_add_handler(&dev->hdl, sd->ctrl_handler, NULL); break; case RTL2832_TUNER_R820T: - v4l2_ctrl_handler_init(&s->hdl, 2); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, + v4l2_ctrl_handler_init(&dev->hdl, 2); + dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, + dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0); - v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); + v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); break; case RTL2832_TUNER_FC0012: case RTL2832_TUNER_FC0013: - v4l2_ctrl_handler_init(&s->hdl, 2); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, + v4l2_ctrl_handler_init(&dev->hdl, 2); + dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, + dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000); - v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); + v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); break; default: - v4l2_ctrl_handler_init(&s->hdl, 0); - dev_notice(&s->udev->dev, "%s: Unsupported tuner\n", + v4l2_ctrl_handler_init(&dev->hdl, 0); + dev_notice(&dev->udev->dev, "%s: Unsupported tuner\n", KBUILD_MODNAME); goto err_free_controls; } - if (s->hdl.error) { - ret = s->hdl.error; - dev_err(&s->udev->dev, "Could not initialize controls\n"); + if (dev->hdl.error) { + ret = dev->hdl.error; + dev_err(&dev->udev->dev, "Could not initialize controls\n"); goto err_free_controls; } /* Init video_device structure */ - s->vdev = rtl2832_sdr_template; - s->vdev.queue = &s->vb_queue; - s->vdev.queue->lock = &s->vb_queue_lock; - video_set_drvdata(&s->vdev, s); + dev->vdev = rtl2832_sdr_template; + dev->vdev.queue = &dev->vb_queue; + dev->vdev.queue->lock = &dev->vb_queue_lock; + video_set_drvdata(&dev->vdev, dev); /* Register the v4l2_device structure */ - s->v4l2_dev.release = rtl2832_sdr_video_release; - ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev); + dev->v4l2_dev.release = rtl2832_sdr_video_release; + ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); if (ret) { - dev_err(&s->udev->dev, + dev_err(&dev->udev->dev, "Failed to register v4l2-device (%d)\n", ret); goto err_free_controls; } - s->v4l2_dev.ctrl_handler = &s->hdl; - s->vdev.v4l2_dev = &s->v4l2_dev; - s->vdev.lock = &s->v4l2_lock; - s->vdev.vfl_dir = VFL_DIR_RX; + dev->v4l2_dev.ctrl_handler = &dev->hdl; + dev->vdev.v4l2_dev = &dev->v4l2_dev; + dev->vdev.lock = &dev->v4l2_lock; + dev->vdev.vfl_dir = VFL_DIR_RX; - ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); + ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1); if (ret) { - dev_err(&s->udev->dev, + dev_err(&dev->udev->dev, "Failed to register as video device (%d)\n", ret); goto err_unregister_v4l2_dev; } - dev_info(&s->udev->dev, "Registered as %s\n", - video_device_node_name(&s->vdev)); + dev_info(&dev->udev->dev, "Registered as %s\n", + video_device_node_name(&dev->vdev)); - fe->sec_priv = s; + fe->sec_priv = dev; fe->ops.release_sec = rtl2832_sdr_release_sec; - dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n", + dev_info(&dev->i2c->dev, "%s: Realtek RTL2832 SDR attached\n", KBUILD_MODNAME); - dev_notice(&s->udev->dev, + dev_notice(&dev->udev->dev, "%s: SDR API is still slightly experimental and functionality changes may follow\n", KBUILD_MODNAME); return fe; err_unregister_v4l2_dev: - v4l2_device_unregister(&s->v4l2_dev); + v4l2_device_unregister(&dev->v4l2_dev); err_free_controls: - v4l2_ctrl_handler_free(&s->hdl); + v4l2_ctrl_handler_free(&dev->hdl); err_free_mem: - kfree(s); + kfree(dev); return NULL; } EXPORT_SYMBOL(rtl2832_sdr_attach); -- cgit v1.2.3 From 63bdab5d31b987c5ccb81c3c6662016d07cbb5b7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 10:09:20 -0300 Subject: [media] rtl2832_sdr: convert to platform driver That SDR driver module was abusing DVB frontend SEC (satellite equipment controller) device and due to that it was also using legacy DVB binding. Platform bus is pseudo-bus provided by kernel driver model and it fits cases like that, where any other busses are not suitable. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 355 +++++++++++------------------- drivers/media/dvb-frontends/rtl2832_sdr.h | 42 +++- 2 files changed, 156 insertions(+), 241 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 3af869c5497d..6c5b2944ecb2 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -112,7 +113,7 @@ struct rtl2832_sdr_dev { #define URB_BUF (1 << 2) unsigned long flags; - const struct rtl2832_config *cfg; + struct platform_device *pdev; struct dvb_frontend *fe; struct dvb_usb_device *d; struct i2c_adapter *i2c; @@ -160,110 +161,29 @@ struct rtl2832_sdr_dev { unsigned long jiffies_next; }; -/* write multiple hardware registers */ -static int rtl2832_sdr_wr(struct rtl2832_sdr_dev *dev, u8 reg, const u8 *val, - int len) -{ - int ret; -#define MAX_WR_LEN 24 -#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1) - u8 buf[MAX_WR_XFER_LEN]; - struct i2c_msg msg[1] = { - { - .addr = dev->cfg->i2c_addr, - .flags = 0, - .len = 1 + len, - .buf = buf, - } - }; - - if (WARN_ON(len > MAX_WR_LEN)) - return -EINVAL; - - buf[0] = reg; - memcpy(&buf[1], val, len); - - ret = i2c_transfer(dev->i2c, msg, 1); - if (ret == 1) { - ret = 0; - } else { - dev_err(&dev->i2c->dev, - "%s: I2C wr failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - -/* read multiple hardware registers */ -static int rtl2832_sdr_rd(struct rtl2832_sdr_dev *dev, u8 reg, u8 *val, int len) -{ - int ret; - struct i2c_msg msg[2] = { - { - .addr = dev->cfg->i2c_addr, - .flags = 0, - .len = 1, - .buf = ®, - }, { - .addr = dev->cfg->i2c_addr, - .flags = I2C_M_RD, - .len = len, - .buf = val, - } - }; - - ret = i2c_transfer(dev->i2c, msg, 2); - if (ret == 2) { - ret = 0; - } else { - dev_err(&dev->i2c->dev, - "%s: I2C rd failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - /* write multiple registers */ static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg, const u8 *val, int len) { - int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 bank = (reg >> 8) & 0xff; - - /* switch bank if needed */ - if (bank != dev->bank) { - ret = rtl2832_sdr_wr(dev, 0x00, &bank, 1); - if (ret) - return ret; + struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct i2c_client *client = pdata->i2c_client; - dev->bank = bank; - } - - return rtl2832_sdr_wr(dev, reg2, val, len); + return pdata->bulk_write(client, reg, val, len); } +#if 0 /* read multiple registers */ static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val, int len) { - int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 bank = (reg >> 8) & 0xff; - - /* switch bank if needed */ - if (bank != dev->bank) { - ret = rtl2832_sdr_wr(dev, 0x00, &bank, 1); - if (ret) - return ret; + struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct i2c_client *client = pdata->i2c_client; - dev->bank = bank; - } - - return rtl2832_sdr_rd(dev, reg2, val, len); + return pdata->bulk_read(client, reg, val, len); } +#endif /* write single register */ static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val) @@ -271,59 +191,16 @@ static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val) return rtl2832_sdr_wr_regs(dev, reg, &val, 1); } -#if 0 -/* read single register */ -static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val) -{ - return rtl2832_sdr_rd_regs(dev, reg, val, 1); -} -#endif - /* write single register with mask */ static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg, u8 val, u8 mask) { - int ret; - u8 tmp; - - /* no need for read if whole reg is written */ - if (mask != 0xff) { - ret = rtl2832_sdr_rd_regs(dev, reg, &tmp, 1); - if (ret) - return ret; - - val &= mask; - tmp &= ~mask; - val |= tmp; - } - - return rtl2832_sdr_wr_regs(dev, reg, &val, 1); -} - -#if 0 -/* read single register with mask */ -static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg, - u8 *val, u8 mask) -{ - int ret, i; - u8 tmp; - - ret = rtl2832_sdr_rd_regs(dev, reg, &tmp, 1); - if (ret) - return ret; - - tmp &= mask; - - /* find position of the first bit */ - for (i = 0; i < 8; i++) { - if ((mask >> i) & 0x01) - break; - } - *val = tmp >> i; + struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct i2c_client *client = pdata->i2c_client; - return 0; + return pdata->update_bits(client, reg, mask, val); } -#endif /* Private functions */ static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( @@ -584,28 +461,6 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev) spin_unlock_irqrestore(&dev->queued_bufs_lock, flags); } -/* The user yanked out the cable... */ -static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) -{ - struct rtl2832_sdr_dev *dev = fe->sec_priv; - - dev_dbg(&dev->udev->dev, "\n"); - - mutex_lock(&dev->vb_queue_lock); - mutex_lock(&dev->v4l2_lock); - /* No need to keep the urbs around after disconnection */ - dev->udev = NULL; - - v4l2_device_disconnect(&dev->v4l2_dev); - video_unregister_device(&dev->vdev); - mutex_unlock(&dev->v4l2_lock); - mutex_unlock(&dev->vb_queue_lock); - - v4l2_device_put(&dev->v4l2_dev); - - fe->sec_priv = NULL; -} - static int rtl2832_sdr_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { @@ -672,6 +527,8 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; struct dvb_frontend *fe = dev->fe; int ret; unsigned int f_sr, f_if; @@ -707,9 +564,9 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) goto err; /* program IF */ - u64tmp = f_if % dev->cfg->xtal; + u64tmp = f_if % pdata->clk; u64tmp *= 0x400000; - u64tmp = div_u64(u64tmp, dev->cfg->xtal); + u64tmp = div_u64(u64tmp, pdata->clk); u64tmp = -u64tmp; u32tmp = u64tmp & 0x3fffff; @@ -746,7 +603,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) goto err; /* program sampling rate (resampling down) */ - u32tmp = div_u64(dev->cfg->xtal * 0x400000ULL, f_sr * 4U); + u32tmp = div_u64(pdata->clk * 0x400000ULL, f_sr * 4U); u32tmp <<= 2; buf[0] = (u32tmp >> 24) & 0xff; buf[1] = (u32tmp >> 16) & 0xff; @@ -787,8 +644,8 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) goto err; /* used RF tuner based settings */ - switch (dev->cfg->tuner) { - case RTL2832_TUNER_E4000: + switch (pdata->tuner) { + case RTL2832_SDR_TUNER_E4000: ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1); @@ -824,8 +681,8 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) ret = rtl2832_sdr_wr_regs(dev, 0x00d, "\x85", 1); ret = rtl2832_sdr_wr_regs(dev, 0x013, "\x02", 1); break; - case RTL2832_TUNER_FC0012: - case RTL2832_TUNER_FC0013: + case RTL2832_SDR_TUNER_FC0012: + case RTL2832_SDR_TUNER_FC0013: ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); ret = rtl2832_sdr_wr_regs(dev, 0x103, "\x5a", 1); @@ -856,7 +713,8 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) ret = rtl2832_sdr_wr_regs(dev, 0x1e6, "\x02", 1); ret = rtl2832_sdr_wr_regs(dev, 0x1d7, "\x09", 1); break; - case RTL2832_TUNER_R820T: + case RTL2832_SDR_TUNER_R820T: + case RTL2832_SDR_TUNER_R828D: ret = rtl2832_sdr_wr_regs(dev, 0x112, "\x5a", 1); ret = rtl2832_sdr_wr_regs(dev, 0x102, "\x40", 1); ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x01", 1); @@ -1401,34 +1259,46 @@ static void rtl2832_sdr_video_release(struct v4l2_device *v) { struct rtl2832_sdr_dev *dev = container_of(v, struct rtl2832_sdr_dev, v4l2_dev); + struct platform_device *pdev = dev->pdev; + + dev_dbg(&pdev->dev, "\n"); v4l2_ctrl_handler_free(&dev->hdl); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); } -struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd) +/* Platform driver interface */ +static int rtl2832_sdr_probe(struct platform_device *pdev) { - int ret; struct rtl2832_sdr_dev *dev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops; - struct dvb_usb_device *d = i2c_get_adapdata(i2c); + struct v4l2_subdev *subdev; + int ret; - dev = kzalloc(sizeof(struct rtl2832_sdr_dev), GFP_KERNEL); + dev_dbg(&pdev->dev, "\n"); + + if (!pdata) { + dev_err(&pdev->dev, "Cannot proceed without platform data\n"); + ret = -EINVAL; + goto err; + } + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - dev_err(&d->udev->dev, - "Could not allocate memory for rtl2832_sdr_dev\n"); - return NULL; + dev_err(&pdev->dev, + "Could not allocate memory for rtl2832_sdr_dev\n"); + ret = -ENOMEM; + goto err; } /* setup the state */ - dev->fe = fe; - dev->d = d; - dev->udev = d->udev; - dev->i2c = i2c; - dev->cfg = cfg; + subdev = pdata->v4l2_subdev; + dev->pdev = pdev; + dev->fe = pdata->dvb_frontend; + dev->d = pdata->dvb_usb_device; + dev->udev = pdata->dvb_usb_device->udev; + dev->i2c = pdata->i2c_client->adapter; dev->f_adc = bands_adc[0].rangelow; dev->f_tuner = bands_fm[0].rangelow; dev->pixelformat = formats[0].pixelformat; @@ -1452,50 +1322,49 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ret = vb2_queue_init(&dev->vb_queue); if (ret) { - dev_err(&dev->udev->dev, "Could not initialize vb2 queue\n"); - goto err_free_mem; + dev_err(&pdev->dev, "Could not initialize vb2 queue\n"); + goto err_kfree; } /* Register controls */ - switch (dev->cfg->tuner) { - case RTL2832_TUNER_E4000: + switch (pdata->tuner) { + case RTL2832_SDR_TUNER_E4000: v4l2_ctrl_handler_init(&dev->hdl, 9); - if (sd) - v4l2_ctrl_add_handler(&dev->hdl, sd->ctrl_handler, NULL); + if (subdev) + v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, NULL); break; - case RTL2832_TUNER_R820T: + case RTL2832_SDR_TUNER_R820T: + case RTL2832_SDR_TUNER_R828D: v4l2_ctrl_handler_init(&dev->hdl, 2); dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops, - V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, - 0, 1, 1, 1); + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 1, 1); dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops, - V4L2_CID_RF_TUNER_BANDWIDTH, - 0, 8000000, 100000, 0); + V4L2_CID_RF_TUNER_BANDWIDTH, + 0, 8000000, 100000, 0); v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); break; - case RTL2832_TUNER_FC0012: - case RTL2832_TUNER_FC0013: + case RTL2832_SDR_TUNER_FC0012: + case RTL2832_SDR_TUNER_FC0013: v4l2_ctrl_handler_init(&dev->hdl, 2); dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, ops, - V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, - 0, 1, 1, 1); + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, + 0, 1, 1, 1); dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, ops, - V4L2_CID_RF_TUNER_BANDWIDTH, - 6000000, 8000000, 1000000, - 6000000); + V4L2_CID_RF_TUNER_BANDWIDTH, + 6000000, 8000000, 1000000, + 6000000); v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); break; default: v4l2_ctrl_handler_init(&dev->hdl, 0); - dev_notice(&dev->udev->dev, "%s: Unsupported tuner\n", - KBUILD_MODNAME); - goto err_free_controls; + dev_err(&pdev->dev, "Unsupported tuner\n"); + goto err_v4l2_ctrl_handler_free; } - if (dev->hdl.error) { ret = dev->hdl.error; - dev_err(&dev->udev->dev, "Could not initialize controls\n"); - goto err_free_controls; + dev_err(&pdev->dev, "Could not initialize controls\n"); + goto err_v4l2_ctrl_handler_free; } /* Init video_device structure */ @@ -1508,9 +1377,8 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, dev->v4l2_dev.release = rtl2832_sdr_video_release; ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); if (ret) { - dev_err(&dev->udev->dev, - "Failed to register v4l2-device (%d)\n", ret); - goto err_free_controls; + dev_err(&pdev->dev, "Failed to register v4l2-device %d\n", ret); + goto err_v4l2_ctrl_handler_free; } dev->v4l2_dev.ctrl_handler = &dev->hdl; @@ -1520,33 +1388,56 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1); if (ret) { - dev_err(&dev->udev->dev, - "Failed to register as video device (%d)\n", - ret); - goto err_unregister_v4l2_dev; + dev_err(&pdev->dev, "Failed to register as video device %d\n", + ret); + goto err_v4l2_device_unregister; } - dev_info(&dev->udev->dev, "Registered as %s\n", - video_device_node_name(&dev->vdev)); - - fe->sec_priv = dev; - fe->ops.release_sec = rtl2832_sdr_release_sec; - - dev_info(&dev->i2c->dev, "%s: Realtek RTL2832 SDR attached\n", - KBUILD_MODNAME); - dev_notice(&dev->udev->dev, - "%s: SDR API is still slightly experimental and functionality changes may follow\n", - KBUILD_MODNAME); - return fe; - -err_unregister_v4l2_dev: + dev_info(&pdev->dev, "Registered as %s\n", + video_device_node_name(&dev->vdev)); + dev_info(&pdev->dev, "Realtek RTL2832 SDR attached\n"); + dev_notice(&pdev->dev, + "SDR API is still slightly experimental and functionality changes may follow\n"); + platform_set_drvdata(pdev, dev); + return 0; +err_v4l2_device_unregister: v4l2_device_unregister(&dev->v4l2_dev); -err_free_controls: +err_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(&dev->hdl); -err_free_mem: +err_kfree: kfree(dev); - return NULL; +err: + return ret; } -EXPORT_SYMBOL(rtl2832_sdr_attach); + +static int rtl2832_sdr_remove(struct platform_device *pdev) +{ + struct rtl2832_sdr_dev *dev = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "\n"); + + mutex_lock(&dev->vb_queue_lock); + mutex_lock(&dev->v4l2_lock); + /* No need to keep the urbs around after disconnection */ + dev->udev = NULL; + v4l2_device_disconnect(&dev->v4l2_dev); + video_unregister_device(&dev->vdev); + mutex_unlock(&dev->v4l2_lock); + mutex_unlock(&dev->vb_queue_lock); + + v4l2_device_put(&dev->v4l2_dev); + + return 0; +} + +static struct platform_driver rtl2832_sdr_driver = { + .driver = { + .name = "rtl2832_sdr", + .owner = THIS_MODULE, + }, + .probe = rtl2832_sdr_probe, + .remove = rtl2832_sdr_remove, +}; +module_platform_driver(rtl2832_sdr_driver); MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("Realtek RTL2832 SDR driver"); diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h index b865fadf184f..5efe609abd20 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.h +++ b/drivers/media/dvb-frontends/rtl2832_sdr.h @@ -32,23 +32,47 @@ #define RTL2832_SDR_H #include +#include #include - -/* for config struct */ +#include "dvb_frontend.h" #include "rtl2832.h" -#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR) -extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd); -#else +struct rtl2832_sdr_platform_data { + /* + * Clock frequency. + * Hz + * 4000000, 16000000, 25000000, 28800000 + */ + u32 clk; + + /* + * Tuner. + * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver. + */ +#define RTL2832_SDR_TUNER_TUA9001 0x24 +#define RTL2832_SDR_TUNER_FC0012 0x26 +#define RTL2832_SDR_TUNER_E4000 0x27 +#define RTL2832_SDR_TUNER_FC0013 0x29 +#define RTL2832_SDR_TUNER_R820T 0x2a +#define RTL2832_SDR_TUNER_R828D 0x2b + u8 tuner; + + struct i2c_client *i2c_client; + int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t); + int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t); + int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int); + struct dvb_frontend *dvb_frontend; + struct v4l2_subdev *v4l2_subdev; + struct dvb_usb_device *dvb_usb_device; +}; + + static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct rtl2832_config *cfg, struct v4l2_subdev *sd) { - dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); + dev_warn(&i2c->dev, "%s: driver disabled!\n", __func__); return NULL; } -#endif #endif /* RTL2832_SDR_H */ -- cgit v1.2.3 From a2f7f220df5edf7cbe17ec89f49676a7b4b64d34 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 10:50:54 -0300 Subject: [media] rtl28xxu: switch SDR module to platform driver RTL2832 SDR module implements kernel platform driver. Change old binding to that one. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 126 ++++++++++++-------------------- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 3 + 2 files changed, 50 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index c64b5ed60ab9..c2d377fa193a 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -22,25 +22,6 @@ #include "rtl28xxu.h" -#ifdef CONFIG_MEDIA_ATTACH -#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ - void *__r = NULL; \ - typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ - if (__a) { \ - __r = (void *) __a(ARGS); \ - if (__r == NULL) \ - symbol_put(FUNCTION); \ - } \ - __r; \ -}) - -#else -#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ - FUNCTION(ARGS); \ -}) - -#endif - static int rtl28xxu_disable_rc; module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644); MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller"); @@ -662,37 +643,6 @@ static const struct rtl2832_platform_data rtl2832_r820t_platform_data = { .tuner = TUNER_RTL2832_R820T, }; -/* TODO: these are redundant information for rtl2832_sdr driver */ -static const struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_FC0012 -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_FC0013 -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_TUA9001, -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .tuner = TUNER_RTL2832_E4000, -}; - -static const struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { - .i2c_addr = 0x10, - .xtal = 28800000, - .tuner = TUNER_RTL2832_R820T, -}; - static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { @@ -1062,10 +1012,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) int ret; struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; struct dvb_frontend *fe = NULL; struct i2c_board_info info; struct i2c_client *client; + struct v4l2_subdev *subdev = NULL; dev_dbg(&d->udev->dev, "%s:\n", __func__); @@ -1080,10 +1030,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) * that to the tuner driver */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_fc0012_config, NULL); break; case TUNER_RTL2832_FC0013: fe = dvb_attach(fc0013_attach, adap->fe[0], @@ -1092,16 +1038,8 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* fc0013 also supports signal strength reading */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_fc0013_config, NULL); break; case TUNER_RTL2832_E4000: { - struct v4l2_subdev *sd; - struct i2c_adapter *i2c_adap_internal = - pdata->get_private_i2c_adapter(priv->i2c_client_demod); - struct e4000_config e4000_config = { .fe = adap->fe[0], .clock = 28800000, @@ -1122,13 +1060,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) } priv->i2c_client_tuner = client; - sd = i2c_get_clientdata(client); - i2c_set_adapdata(i2c_adap_internal, d); - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], - i2c_adap_internal, - &rtl28xxu_rtl2832_e4000_config, sd); + subdev = i2c_get_clientdata(client); } break; case TUNER_RTL2832_FC2580: @@ -1158,10 +1090,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* Use tuner to get the signal strength */ adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_r820t_config, NULL); break; case TUNER_RTL2832_R828D: fe = dvb_attach(r820t_attach, adap->fe[0], @@ -1177,21 +1105,53 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[1]->ops.read_signal_strength = adap->fe[1]->ops.tuner_ops.get_rf_strength; } - - /* attach SDR */ - dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, - &rtl28xxu_rtl2832_r820t_config, NULL); break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, priv->tuner); } - if (fe == NULL && priv->i2c_client_tuner == NULL) { ret = -ENODEV; goto err; } + /* register SDR */ + switch (priv->tuner) { + struct platform_device *pdev; + struct rtl2832_sdr_platform_data pdata = {}; + + case TUNER_RTL2832_FC0012: + case TUNER_RTL2832_FC0013: + case TUNER_RTL2832_E4000: + case TUNER_RTL2832_R820T: + case TUNER_RTL2832_R828D: + pdata.clk = priv->rtl2832_platform_data.clk; + pdata.tuner = priv->tuner; + pdata.i2c_client = priv->i2c_client_demod; + pdata.bulk_read = priv->rtl2832_platform_data.bulk_read; + pdata.bulk_write = priv->rtl2832_platform_data.bulk_write; + pdata.update_bits = priv->rtl2832_platform_data.update_bits; + pdata.dvb_frontend = adap->fe[0]; + pdata.dvb_usb_device = d; + pdata.v4l2_subdev = subdev; + + request_module("%s", "rtl2832_sdr"); + pdev = platform_device_register_data(&priv->i2c_client_demod->dev, + "rtl2832_sdr", + PLATFORM_DEVID_AUTO, + &pdata, sizeof(pdata)); + if (pdev == NULL || pdev->dev.driver == NULL) + break; + if (!try_module_get(pdev->dev.driver->owner)) { + platform_device_unregister(pdev); + break; + } + priv->platform_device_sdr = pdev; + break; + default: + dev_dbg(&d->udev->dev, "no SDR for tuner=%d\n", priv->tuner); + } + return 0; err: dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); @@ -1203,9 +1163,17 @@ static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_priv *priv = d_to_priv(d); struct i2c_client *client; + struct platform_device *pdev; dev_dbg(&d->udev->dev, "%s:\n", __func__); + /* remove platform SDR */ + pdev = priv->platform_device_sdr; + if (pdev) { + module_put(pdev->dev.driver->owner); + platform_device_unregister(pdev); + } + /* remove I2C tuner */ client = priv->i2c_client_tuner; if (client) { diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index cb3fc6595332..62d32491fbe4 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -22,6 +22,8 @@ #ifndef RTL28XXU_H #define RTL28XXU_H +#include + #include "dvb_usb.h" #include "rtl2830.h" @@ -76,6 +78,7 @@ struct rtl28xxu_priv { struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_tuner; struct i2c_client *i2c_client_slave_demod; + struct platform_device *platform_device_sdr; #define SLAVE_DEMOD_NONE 0 #define SLAVE_DEMOD_MN88472 1 #define SLAVE_DEMOD_MN88473 2 -- cgit v1.2.3 From 488be13a5e7cb0d497b1c7cb79021b4d88b82b57 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 11:05:08 -0300 Subject: [media] rtl28xxu: use master I2C adapter for slave demods Both mn88472 and mn88473 slave demods are connected to master I2C bus, not the bus behind master demod I2C gate like tuners. Use correct bus. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index c2d377fa193a..0d37d0c06d79 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -841,7 +841,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) info.addr = 0x18; info.platform_data = &mn88472_config; request_module(info.type); - client = i2c_new_device(priv->demod_i2c_adapter, &info); + client = i2c_new_device(&d->i2c_adap, &info); if (client == NULL || client->dev.driver == NULL) { priv->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; @@ -863,7 +863,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) info.addr = 0x18; info.platform_data = &mn88473_config; request_module(info.type); - client = i2c_new_device(priv->demod_i2c_adapter, &info); + client = i2c_new_device(&d->i2c_adap, &info); if (client == NULL || client->dev.driver == NULL) { priv->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; -- cgit v1.2.3 From e4e78693a18aa6dfc1388def09d5c73006d7c742 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 12:18:01 -0300 Subject: [media] rtl2832_sdr: fix logging Pass correct device, platform device, for logging system in order to format printouts correctly. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 151 +++++++++++++++++------------- 1 file changed, 86 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 6c5b2944ecb2..361b1eb7cbb7 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -224,6 +224,7 @@ leave: static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev, void *dst, const u8 *src, unsigned int src_len) { + struct platform_device *pdev = dev->pdev; unsigned int dst_len; if (dev->pixelformat == V4L2_SDR_FMT_CU8) { @@ -251,10 +252,9 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev, dev->jiffies_next = jiffies + msecs_to_jiffies(MSECS); dev->sample_measured = dev->sample; - dev_dbg(&dev->udev->dev, - "slen=%u samples=%u msecs=%u sample rate=%lu\n", - src_len, samples, msecs, - samples * 1000UL / msecs); + dev_dbg(&pdev->dev, + "slen=%u samples=%u msecs=%u sample rate=%lu\n", + src_len, samples, msecs, samples * 1000UL / msecs); } /* total number of I+Q pairs */ @@ -270,12 +270,12 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_dev *dev, static void rtl2832_sdr_urb_complete(struct urb *urb) { struct rtl2832_sdr_dev *dev = urb->context; + struct platform_device *pdev = dev->pdev; struct rtl2832_sdr_frame_buf *fbuf; - dev_dbg_ratelimited(&dev->udev->dev, - "status=%d length=%d/%d errors=%d\n", - urb->status, urb->actual_length, - urb->transfer_buffer_length, urb->error_count); + dev_dbg_ratelimited(&pdev->dev, "status=%d length=%d/%d errors=%d\n", + urb->status, urb->actual_length, + urb->transfer_buffer_length, urb->error_count); switch (urb->status) { case 0: /* success */ @@ -286,8 +286,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) case -ESHUTDOWN: return; default: /* error */ - dev_err_ratelimited(&dev->udev->dev, "urb failed=%d\n", - urb->status); + dev_err_ratelimited(&pdev->dev, "urb failed=%d\n", urb->status); break; } @@ -298,9 +297,9 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) fbuf = rtl2832_sdr_get_next_fill_buf(dev); if (unlikely(fbuf == NULL)) { dev->vb_full++; - dev_notice_ratelimited(&dev->udev->dev, - "videobuf is full, %d packets dropped\n", - dev->vb_full); + dev_notice_ratelimited(&pdev->dev, + "videobuf is full, %d packets dropped\n", + dev->vb_full); goto skip; } @@ -319,10 +318,11 @@ skip: static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; int i; for (i = dev->urbs_submitted - 1; i >= 0; i--) { - dev_dbg(&dev->udev->dev, "kill urb=%d\n", i); + dev_dbg(&pdev->dev, "kill urb=%d\n", i); /* stop the URB */ usb_kill_urb(dev->urb_list[i]); } @@ -333,15 +333,16 @@ static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; int i, ret; for (i = 0; i < dev->urbs_initialized; i++) { - dev_dbg(&dev->udev->dev, "submit urb=%d\n", i); + dev_dbg(&pdev->dev, "submit urb=%d\n", i); ret = usb_submit_urb(dev->urb_list[i], GFP_ATOMIC); if (ret) { - dev_err(&dev->udev->dev, - "Could not submit urb no. %d - get them all back\n", - i); + dev_err(&pdev->dev, + "Could not submit urb no. %d - get them all back\n", + i); rtl2832_sdr_kill_urbs(dev); return ret; } @@ -353,10 +354,11 @@ static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; if (dev->flags & USB_STATE_URB_BUF) { while (dev->buf_num) { dev->buf_num--; - dev_dbg(&dev->udev->dev, "free buf=%d\n", dev->buf_num); + dev_dbg(&pdev->dev, "free buf=%d\n", dev->buf_num); usb_free_coherent(dev->udev, dev->buf_size, dev->buf_list[dev->buf_num], dev->dma_addr[dev->buf_num]); @@ -369,26 +371,27 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; dev->buf_num = 0; dev->buf_size = BULK_BUFFER_SIZE; - dev_dbg(&dev->udev->dev, "all in all I will use %u bytes for streaming\n", - MAX_BULK_BUFS * BULK_BUFFER_SIZE); + dev_dbg(&pdev->dev, "all in all I will use %u bytes for streaming\n", + MAX_BULK_BUFS * BULK_BUFFER_SIZE); for (dev->buf_num = 0; dev->buf_num < MAX_BULK_BUFS; dev->buf_num++) { dev->buf_list[dev->buf_num] = usb_alloc_coherent(dev->udev, BULK_BUFFER_SIZE, GFP_ATOMIC, &dev->dma_addr[dev->buf_num]); if (!dev->buf_list[dev->buf_num]) { - dev_dbg(&dev->udev->dev, "alloc buf=%d failed\n", - dev->buf_num); + dev_dbg(&pdev->dev, "alloc buf=%d failed\n", + dev->buf_num); rtl2832_sdr_free_stream_bufs(dev); return -ENOMEM; } - dev_dbg(&dev->udev->dev, "alloc buf=%d %p (dma %llu)\n", - dev->buf_num, dev->buf_list[dev->buf_num], - (long long)dev->dma_addr[dev->buf_num]); + dev_dbg(&pdev->dev, "alloc buf=%d %p (dma %llu)\n", + dev->buf_num, dev->buf_list[dev->buf_num], + (long long)dev->dma_addr[dev->buf_num]); dev->flags |= USB_STATE_URB_BUF; } @@ -397,13 +400,14 @@ static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; int i; rtl2832_sdr_kill_urbs(dev); for (i = dev->urbs_initialized - 1; i >= 0; i--) { if (dev->urb_list[i]) { - dev_dbg(&dev->udev->dev, "free urb=%d\n", i); + dev_dbg(&pdev->dev, "free urb=%d\n", i); /* free the URBs */ usb_free_urb(dev->urb_list[i]); } @@ -415,14 +419,15 @@ static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; int i, j; /* allocate the URBs */ for (i = 0; i < MAX_BULK_BUFS; i++) { - dev_dbg(&dev->udev->dev, "alloc urb=%d\n", i); + dev_dbg(&pdev->dev, "alloc urb=%d\n", i); dev->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); if (!dev->urb_list[i]) { - dev_dbg(&dev->udev->dev, "failed\n"); + dev_dbg(&pdev->dev, "failed\n"); for (j = 0; j < i; j++) usb_free_urb(dev->urb_list[j]); return -ENOMEM; @@ -445,9 +450,10 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev) /* Must be called with vb_queue_lock hold */ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; unsigned long flags; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); spin_lock_irqsave(&dev->queued_bufs_lock, flags); while (!list_empty(&dev->queued_bufs)) { @@ -465,8 +471,9 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); strlcpy(cap->card, dev->vdev.name, sizeof(cap->card)); @@ -483,16 +490,16 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "nbuffers=%d\n", *nbuffers); + dev_dbg(&pdev->dev, "nbuffers=%d\n", *nbuffers); /* Need at least 8 buffers */ if (vq->num_buffers + *nbuffers < 8) *nbuffers = 8 - vq->num_buffers; *nplanes = 1; sizes[0] = PAGE_ALIGN(dev->buffersize); - dev_dbg(&dev->udev->dev, "nbuffers=%d sizes[0]=%d\n", - *nbuffers, sizes[0]); + dev_dbg(&pdev->dev, "nbuffers=%d sizes[0]=%d\n", *nbuffers, sizes[0]); return 0; } @@ -536,7 +543,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) u64 u64tmp; u32 u32tmp; - dev_dbg(&dev->udev->dev, "f_adc=%u\n", dev->f_adc); + dev_dbg(&pdev->dev, "f_adc=%u\n", dev->f_adc); if (!test_bit(POWER_ON, &dev->flags)) return 0; @@ -570,7 +577,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) u64tmp = -u64tmp; u32tmp = u64tmp & 0x3fffff; - dev_dbg(&dev->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); + dev_dbg(&pdev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); buf[0] = (u32tmp >> 16) & 0xff; buf[1] = (u32tmp >> 8) & 0xff; @@ -739,7 +746,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) ret = rtl2832_sdr_wr_regs(dev, 0x011, "\xf4", 1); break; default: - dev_notice(&dev->udev->dev, "Unsupported tuner\n"); + dev_notice(&pdev->dev, "Unsupported tuner\n"); } /* software reset */ @@ -756,9 +763,10 @@ err: static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; int ret; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); /* PID filter */ ret = rtl2832_sdr_wr_regs(dev, 0x061, "\xe0", 1); @@ -792,6 +800,7 @@ err: static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; struct dvb_frontend *fe = dev->fe; struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct v4l2_ctrl *bandwidth_auto; @@ -819,8 +828,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) c->frequency = dev->f_tuner; c->delivery_system = SYS_DVBT; - dev_dbg(&dev->udev->dev, "frequency=%u bandwidth=%d\n", - c->frequency, c->bandwidth_hz); + dev_dbg(&pdev->dev, "frequency=%u bandwidth=%d\n", + c->frequency, c->bandwidth_hz); if (!test_bit(POWER_ON, &dev->flags)) return 0; @@ -833,9 +842,10 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; struct dvb_frontend *fe = dev->fe; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); if (fe->ops.tuner_ops.init) fe->ops.tuner_ops.init(fe); @@ -845,9 +855,10 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev) static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev) { + struct platform_device *pdev = dev->pdev; struct dvb_frontend *fe = dev->fe; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); if (fe->ops.tuner_ops.sleep) fe->ops.tuner_ops.sleep(fe); @@ -858,9 +869,10 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); + struct platform_device *pdev = dev->pdev; int ret; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); if (!dev->udev) return -ENODEV; @@ -912,8 +924,9 @@ err: static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); mutex_lock(&dev->v4l2_lock); @@ -950,8 +963,9 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "index=%d type=%d\n", v->index, v->type); + dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type); if (v->index == 0) { strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); @@ -976,8 +990,9 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *v) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); if (v->index > 1) return -EINVAL; @@ -988,9 +1003,10 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "tuner=%d type=%d index=%d\n", - band->tuner, band->type, band->index); + dev_dbg(&pdev->dev, "tuner=%d type=%d index=%d\n", + band->tuner, band->type, band->index); if (band->tuner == 0) { if (band->index >= ARRAY_SIZE(bands_adc)) @@ -1013,10 +1029,10 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; int ret = 0; - dev_dbg(&dev->udev->dev, "tuner=%d type=%d\n", - f->tuner, f->type); + dev_dbg(&pdev->dev, "tuner=%d type=%d\n", f->tuner, f->type); if (f->tuner == 0) { f->frequency = dev->f_adc; @@ -1035,10 +1051,11 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; int ret, band; - dev_dbg(&dev->udev->dev, "tuner=%d type=%d frequency=%u\n", - f->tuner, f->type, f->frequency); + dev_dbg(&pdev->dev, "tuner=%d type=%d frequency=%u\n", + f->tuner, f->type, f->frequency); /* ADC band midpoints */ #define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2) @@ -1056,13 +1073,13 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, bands_adc[band].rangelow, bands_adc[band].rangehigh); - dev_dbg(&dev->udev->dev, "ADC frequency=%u Hz\n", dev->f_adc); + dev_dbg(&pdev->dev, "ADC frequency=%u Hz\n", dev->f_adc); ret = rtl2832_sdr_set_adc(dev); } else if (f->tuner == 1) { dev->f_tuner = clamp_t(unsigned int, f->frequency, bands_fm[0].rangelow, bands_fm[0].rangehigh); - dev_dbg(&dev->udev->dev, "RF frequency=%u Hz\n", f->frequency); + dev_dbg(&pdev->dev, "RF frequency=%u Hz\n", f->frequency); ret = rtl2832_sdr_set_tuner_freq(dev); } else { @@ -1076,8 +1093,9 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); if (f->index >= dev->num_formats) return -EINVAL; @@ -1092,8 +1110,9 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; - dev_dbg(&dev->udev->dev, "\n"); + dev_dbg(&pdev->dev, "\n"); f->fmt.sdr.pixelformat = dev->pixelformat; f->fmt.sdr.buffersize = dev->buffersize; @@ -1107,11 +1126,12 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; struct vb2_queue *q = &dev->vb_queue; int i; - dev_dbg(&dev->udev->dev, "pixelformat fourcc %4.4s\n", - (char *)&f->fmt.sdr.pixelformat); + dev_dbg(&pdev->dev, "pixelformat fourcc %4.4s\n", + (char *)&f->fmt.sdr.pixelformat); if (vb2_is_busy(q)) return -EBUSY; @@ -1138,10 +1158,11 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { struct rtl2832_sdr_dev *dev = video_drvdata(file); + struct platform_device *pdev = dev->pdev; int i; - dev_dbg(&dev->udev->dev, "pixelformat fourcc %4.4s\n", - (char *)&f->fmt.sdr.pixelformat); + dev_dbg(&pdev->dev, "pixelformat fourcc %4.4s\n", + (char *)&f->fmt.sdr.pixelformat); memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); for (i = 0; i < dev->num_formats; i++) { @@ -1210,13 +1231,13 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) container_of(ctrl->handler, struct rtl2832_sdr_dev, hdl); struct dvb_frontend *fe = dev->fe; + struct platform_device *pdev = dev->pdev; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; - dev_dbg(&dev->udev->dev, - "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", - ctrl->id, ctrl->name, ctrl->val, - ctrl->minimum, ctrl->maximum, ctrl->step); + dev_dbg(&pdev->dev, "id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", + ctrl->id, ctrl->name, ctrl->val, ctrl->minimum, ctrl->maximum, + ctrl->step); switch (ctrl->id) { case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: @@ -1375,7 +1396,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) /* Register the v4l2_device structure */ dev->v4l2_dev.release = rtl2832_sdr_video_release; - ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) { dev_err(&pdev->dev, "Failed to register v4l2-device %d\n", ret); goto err_v4l2_ctrl_handler_free; -- cgit v1.2.3 From 3bda2bf1f85f94f6a76f0260cd2fbe6ded71104b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 12:49:14 -0300 Subject: [media] rtl2832_sdr: cleanups Small cleanups. Remove unneeded variables. Some checkpatch issues. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 46 +++++++++++++++---------------- drivers/media/dvb-frontends/rtl2832_sdr.h | 17 ------------ 2 files changed, 23 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 361b1eb7cbb7..62e85a3b2234 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -22,7 +22,6 @@ * */ -#include "dvb_frontend.h" #include "rtl2832_sdr.h" #include "dvb_usb.h" @@ -114,10 +113,6 @@ struct rtl2832_sdr_dev { unsigned long flags; struct platform_device *pdev; - struct dvb_frontend *fe; - struct dvb_usb_device *d; - struct i2c_adapter *i2c; - u8 bank; struct video_device vdev; struct v4l2_device v4l2_dev; @@ -355,6 +350,7 @@ static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; + if (dev->flags & USB_STATE_URB_BUF) { while (dev->buf_num) { dev->buf_num--; @@ -372,6 +368,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; + dev->buf_num = 0; dev->buf_size = BULK_BUFFER_SIZE; @@ -536,7 +533,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; - struct dvb_frontend *fe = dev->fe; + struct dvb_frontend *fe = pdata->dvb_frontend; int ret; unsigned int f_sr, f_if; u8 buf[4], u8tmp1, u8tmp2; @@ -801,7 +798,8 @@ err: static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; - struct dvb_frontend *fe = dev->fe; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_frontend *fe = pdata->dvb_frontend; struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct v4l2_ctrl *bandwidth_auto; struct v4l2_ctrl *bandwidth; @@ -843,7 +841,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_dev *dev) static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; - struct dvb_frontend *fe = dev->fe; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_frontend *fe = pdata->dvb_frontend; dev_dbg(&pdev->dev, "\n"); @@ -856,7 +855,8 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_dev *dev) static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_dev *dev) { struct platform_device *pdev = dev->pdev; - struct dvb_frontend *fe = dev->fe; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_frontend *fe = pdata->dvb_frontend; dev_dbg(&pdev->dev, "\n"); @@ -870,6 +870,8 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_usb_device *d = pdata->dvb_usb_device; int ret; dev_dbg(&pdev->dev, "\n"); @@ -880,12 +882,12 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) if (mutex_lock_interruptible(&dev->v4l2_lock)) return -ERESTARTSYS; - if (dev->d->props->power_ctrl) - dev->d->props->power_ctrl(dev->d, 1); + if (d->props->power_ctrl) + d->props->power_ctrl(d, 1); /* enable ADC */ - if (dev->d->props->frontend_ctrl) - dev->d->props->frontend_ctrl(dev->fe, 1); + if (d->props->frontend_ctrl) + d->props->frontend_ctrl(pdata->dvb_frontend, 1); set_bit(POWER_ON, &dev->flags); @@ -925,6 +927,8 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) { struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq); struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_usb_device *d = pdata->dvb_usb_device; dev_dbg(&pdev->dev, "\n"); @@ -940,11 +944,11 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) clear_bit(POWER_ON, &dev->flags); /* disable ADC */ - if (dev->d->props->frontend_ctrl) - dev->d->props->frontend_ctrl(dev->fe, 0); + if (d->props->frontend_ctrl) + d->props->frontend_ctrl(pdata->dvb_frontend, 0); - if (dev->d->props->power_ctrl) - dev->d->props->power_ctrl(dev->d, 0); + if (d->props->power_ctrl) + d->props->power_ctrl(d, 0); mutex_unlock(&dev->v4l2_lock); } @@ -1230,8 +1234,9 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) struct rtl2832_sdr_dev *dev = container_of(ctrl->handler, struct rtl2832_sdr_dev, hdl); - struct dvb_frontend *fe = dev->fe; struct platform_device *pdev = dev->pdev; + struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data; + struct dvb_frontend *fe = pdata->dvb_frontend; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; @@ -1307,8 +1312,6 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) } dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - dev_err(&pdev->dev, - "Could not allocate memory for rtl2832_sdr_dev\n"); ret = -ENOMEM; goto err; } @@ -1316,10 +1319,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) /* setup the state */ subdev = pdata->v4l2_subdev; dev->pdev = pdev; - dev->fe = pdata->dvb_frontend; - dev->d = pdata->dvb_usb_device; dev->udev = pdata->dvb_usb_device->udev; - dev->i2c = pdata->i2c_client->adapter; dev->f_adc = bands_adc[0].rangelow; dev->f_tuner = bands_fm[0].rangelow; dev->pixelformat = formats[0].pixelformat; diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h index 5efe609abd20..dd22e421162b 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.h +++ b/drivers/media/dvb-frontends/rtl2832_sdr.h @@ -20,22 +20,14 @@ * GNU Radio plugin "gr-kernel" for device usage will be on: * http://git.linuxtv.org/anttip/gr-kernel.git * - * TODO: - * Help is very highly welcome for these + all the others you could imagine: - * - move controls to V4L2 API - * - use libv4l2 for stream format conversions - * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu) - * - SDRSharp support */ #ifndef RTL2832_SDR_H #define RTL2832_SDR_H -#include #include #include #include "dvb_frontend.h" -#include "rtl2832.h" struct rtl2832_sdr_platform_data { /* @@ -66,13 +58,4 @@ struct rtl2832_sdr_platform_data { struct dvb_usb_device *dvb_usb_device; }; - -static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd) -{ - dev_warn(&i2c->dev, "%s: driver disabled!\n", __func__); - return NULL; -} - #endif /* RTL2832_SDR_H */ -- cgit v1.2.3 From cd559e0b13156a34e5ddf662f44cacd43b484583 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 13:37:18 -0300 Subject: [media] rtl2832: cleanups and minor changes Remove all the stuff that is not needed anymore. Rename variable. Remove extra new lines. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 72 ++++++++---------------------- drivers/media/dvb-frontends/rtl2832.h | 32 +------------ drivers/media/dvb-frontends/rtl2832_priv.h | 9 ++-- 3 files changed, 25 insertions(+), 88 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 7070713775e8..bc3a3589efe2 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -19,8 +19,6 @@ */ #include "rtl2832_priv.h" -#include "dvb_math.h" -#include #define REG_MASK(b) (BIT(b + 1) - 1) @@ -194,21 +192,14 @@ int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, void *val, static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) { struct i2c_client *client = dev->client; - int ret; - + int ret, i; u16 reg_start_addr; - u8 msb, lsb; - u8 reading[4]; - u32 reading_tmp; - int i; - - u8 len; - u32 mask; + u8 msb, lsb, reading[4], len; + u32 reading_tmp, mask; reg_start_addr = registers[reg].start_address; msb = registers[reg].msb; lsb = registers[reg].lsb; - len = (msb >> 3) + 1; mask = REG_MASK(msb - lsb); @@ -222,38 +213,26 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) *val = (reading_tmp >> lsb) & mask; - return ret; - + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; - } static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) { struct i2c_client *client = dev->client; int ret, i; - u8 len; u16 reg_start_addr; - u8 msb, lsb; - u32 mask; - - - u8 reading[4]; - u8 writing[4]; - u32 reading_tmp; - u32 writing_tmp; - + u8 msb, lsb, reading[4], writing[4], len; + u32 reading_tmp, writing_tmp, mask; reg_start_addr = registers[reg].start_address; msb = registers[reg].msb; lsb = registers[reg].lsb; - len = (msb >> 3) + 1; mask = REG_MASK(msb - lsb); - ret = rtl2832_bulk_read(client, reg_start_addr, reading, len); if (ret) goto err; @@ -265,7 +244,6 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) writing_tmp = reading_tmp & ~(mask << lsb); writing_tmp |= ((val & mask) << lsb); - for (i = 0; i < len; i++) writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff; @@ -273,12 +251,10 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) if (ret) goto err; - return ret; - + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; - } static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) @@ -293,7 +269,6 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) * / CrystalFreqHz) */ - pset_iffreq = if_freq % dev->pdata->clk; pset_iffreq *= 0x400000; pset_iffreq = div_u64(pset_iffreq, dev->pdata->clk); @@ -304,10 +279,15 @@ static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) ret = rtl2832_wr_demod_reg(dev, DVBT_EN_BBIN, en_bbin); if (ret) - return ret; + goto err; ret = rtl2832_wr_demod_reg(dev, DVBT_PSET_IFFREQ, pset_iffreq); + if (ret) + goto err; + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -419,7 +399,7 @@ static int rtl2832_init(struct dvb_frontend *fe) schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); dev->sleeping = false; - return ret; + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -485,7 +465,6 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) }, }; - dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n", c->frequency, c->bandwidth_hz, c->inversion); @@ -571,7 +550,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - return ret; + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -716,7 +695,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) } dev->fe_status = *status; - return ret; + return 0; err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; @@ -866,7 +845,6 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) return; err: dev_dbg(&client->dev, "failed=%d\n", ret); - return; } static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) @@ -1052,7 +1030,7 @@ static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) return &dev->fe; } -static struct i2c_adapter *rtl2832_get_i2c_adapter_(struct i2c_client *client) +static struct i2c_adapter *rtl2832_get_i2c_adapter(struct i2c_client *client) { struct rtl2832_dev *dev = i2c_get_clientdata(client); @@ -1060,14 +1038,6 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter_(struct i2c_client *client) return dev->i2c_adapter_tuner; } -static struct i2c_adapter *rtl2832_get_private_i2c_adapter_(struct i2c_client *client) -{ - struct rtl2832_dev *dev = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "\n"); - return dev->i2c_adapter; -} - static int rtl2832_enable_slave_ts(struct i2c_client *client) { struct rtl2832_dev *dev = i2c_get_clientdata(client); @@ -1233,10 +1203,6 @@ static int rtl2832_probe(struct i2c_client *client, i2c_set_clientdata(client, dev); dev->client = client; dev->pdata = client->dev.platform_data; - if (pdata->config) { - dev->pdata->clk = pdata->config->xtal; - dev->pdata->tuner = pdata->config->tuner; - } dev->sleeping = true; INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); INIT_DELAYED_WORK(&dev->stat_work, rtl2832_stat_work); @@ -1274,8 +1240,7 @@ static int rtl2832_probe(struct i2c_client *client, /* setup callbacks */ pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; - pdata->get_i2c_adapter = rtl2832_get_i2c_adapter_; - pdata->get_private_i2c_adapter = rtl2832_get_private_i2c_adapter_; + pdata->get_i2c_adapter = rtl2832_get_i2c_adapter; pdata->enable_slave_ts = rtl2832_enable_slave_ts; pdata->pid_filter = rtl2832_pid_filter; pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl; @@ -1336,4 +1301,3 @@ module_i2c_driver(rtl2832_driver); MODULE_AUTHOR("Thomas Mair "); MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.5"); diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index f86af6f3b370..73e271733065 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -22,36 +22,9 @@ #define RTL2832_H #include - -struct rtl2832_config { - /* - * Demodulator I2C address. - */ - u8 i2c_addr; - - /* - * Xtal frequency. - * Hz - * 4000000, 16000000, 25000000, 28800000 - */ - u32 xtal; - - /* - * tuner - * XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver. - */ -#define RTL2832_TUNER_TUA9001 0x24 -#define RTL2832_TUNER_FC0012 0x26 -#define RTL2832_TUNER_E4000 0x27 -#define RTL2832_TUNER_FC0013 0x29 -#define RTL2832_TUNER_R820T 0x2a -#define RTL2832_TUNER_R828D 0x2b - u8 tuner; -}; +#include struct rtl2832_platform_data { - const struct rtl2832_config *config; - /* * Clock frequency. * Hz @@ -61,7 +34,7 @@ struct rtl2832_platform_data { /* * Tuner. - * XXX: This must be keep sync with dvb_usb_rtl28xxu USB IF driver. + * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver. */ #define RTL2832_TUNER_TUA9001 0x24 #define RTL2832_TUNER_FC0012 0x26 @@ -76,7 +49,6 @@ struct rtl2832_platform_data { */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); - struct i2c_adapter* (*get_private_i2c_adapter)(struct i2c_client *); int (*enable_slave_ts)(struct i2c_client *); int (*pid_filter)(struct dvb_frontend *, u8, u16, int); int (*pid_filter_ctrl)(struct dvb_frontend *, int); diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 973892afb916..9edab5d1aea1 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -21,11 +21,13 @@ #ifndef RTL2832_PRIV_H #define RTL2832_PRIV_H -#include "dvb_frontend.h" -#include "rtl2832.h" -#include #include #include +#include + +#include "dvb_frontend.h" +#include "dvb_math.h" +#include "rtl2832.h" struct rtl2832_dev { struct rtl2832_platform_data *pdata; @@ -55,7 +57,6 @@ struct rtl2832_reg_value { u32 value; }; - /* Demod register bit names */ enum DVBT_REG_BIT_NAME { DVBT_SOFT_RST, -- cgit v1.2.3 From 75c24005eeec0613c319a577c613182ead017cff Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 13:54:23 -0300 Subject: [media] rtl2832: claim copyright and module author I have implemented tons of things for that driver, more than anyone else, so lets claim copyright and module authorship. Cc: Thomas Mair Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 2 ++ drivers/media/dvb-frontends/rtl2832.h | 1 + drivers/media/dvb-frontends/rtl2832_priv.h | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index bc3a3589efe2..e5f7d7925c85 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -2,6 +2,7 @@ * Realtek RTL2832 DVB-T demodulator driver * * Copyright (C) 2012 Thomas Mair + * Copyright (C) 2012-2014 Antti Palosaari * * 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 @@ -1299,5 +1300,6 @@ static struct i2c_driver rtl2832_driver = { module_i2c_driver(rtl2832_driver); MODULE_AUTHOR("Thomas Mair "); +MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 73e271733065..e5f67cf0a65b 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -2,6 +2,7 @@ * Realtek RTL2832 DVB-T demodulator driver * * Copyright (C) 2012 Thomas Mair + * Copyright (C) 2012-2014 Antti Palosaari * * 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 diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 9edab5d1aea1..e25d7487ec06 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -2,6 +2,7 @@ * Realtek RTL2832 DVB-T demodulator driver * * Copyright (C) 2012 Thomas Mair + * Copyright (C) 2012-2014 Antti Palosaari * * 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 -- cgit v1.2.3 From a08c3781194142cce39bbb739373efc8dacaa1fa Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 16 Dec 2014 14:51:33 -0300 Subject: [media] rtl2832: implement sleep Put demod to soft reset in order to save power when sleep. That drops power usage ~30mA @5V on USB dongle I tested. In real life it does not matter much as USB IF powers off demod too, but now it is done twice - demod and USB IF. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index e5f7d7925c85..e80c6b974f4c 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -410,13 +410,23 @@ static int rtl2832_sleep(struct dvb_frontend *fe) { struct rtl2832_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; + int ret; dev_dbg(&client->dev, "\n"); + dev->sleeping = true; /* stop statistics polling */ cancel_delayed_work_sync(&dev->stat_work); dev->fe_status = 0; + + ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1); + if (ret) + goto err; + return 0; +err: + dev_dbg(&client->dev, "failed=%d\n", ret); + return ret; } static int rtl2832_get_tune_settings(struct dvb_frontend *fe, -- cgit v1.2.3 From 1dbbdceeb63e9039ce0545e5e21cf9a8c4d4ffc4 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 17 Dec 2014 02:55:41 -0300 Subject: [media] rtl28xxu: fix DVB FE callback DVB FE callback functionality went broken after I moved tuners to demod muxed I2C adapter. That happens because driver state was carried by I2C adapter and when mux is used there is one adapter more in a chain. USB adapter <-> I2C adapter <-> muxed I2C adapter Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 0d37d0c06d79..1f29307b9d72 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -740,8 +740,23 @@ static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) static int rtl2832u_frontend_callback(void *adapter_priv, int component, int cmd, int arg) { - struct i2c_adapter *adap = adapter_priv; - struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct i2c_adapter *adapter = adapter_priv; + struct device *parent = adapter->dev.parent; + struct i2c_adapter *parent_adapter; + struct dvb_usb_device *d; + + /* + * All tuners are connected to demod muxed I2C adapter. We have to + * resolve its parent adapter in order to get handle for this driver + * private data. That is a bit hackish solution, GPIO or direct driver + * callback would be better... + */ + if (parent != NULL && parent->type == &i2c_adapter_type) + parent_adapter = to_i2c_adapter(parent); + else + return -EINVAL; + + d = i2c_get_adapdata(parent_adapter); dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", __func__, component, cmd, arg); -- cgit v1.2.3 From a6f62431a0c166c171b6b7a62d6cad79fbbdc5da Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 17 Dec 2014 03:09:32 -0300 Subject: [media] rtl28xxu: simplify FE callback handling Logic is so simple that there is no idea to separate tuner selection to own function, instead do it in a callback and get rid of one function. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 1f29307b9d72..f4750189e948 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -721,22 +721,6 @@ err: return ret; } -static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) -{ - struct rtl28xxu_priv *priv = d->priv; - - switch (priv->tuner) { - case TUNER_RTL2832_FC0012: - return rtl2832u_fc0012_tuner_callback(d, cmd, arg); - case TUNER_RTL2832_TUA9001: - return rtl2832u_tua9001_tuner_callback(d, cmd, arg); - default: - break; - } - - return 0; -} - static int rtl2832u_frontend_callback(void *adapter_priv, int component, int cmd, int arg) { @@ -744,6 +728,7 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, struct device *parent = adapter->dev.parent; struct i2c_adapter *parent_adapter; struct dvb_usb_device *d; + struct rtl28xxu_priv *priv; /* * All tuners are connected to demod muxed I2C adapter. We have to @@ -757,15 +742,21 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, return -EINVAL; d = i2c_get_adapdata(parent_adapter); + priv = d->priv; dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", __func__, component, cmd, arg); switch (component) { case DVB_FRONTEND_COMPONENT_TUNER: - return rtl2832u_tuner_callback(d, cmd, arg); + switch (priv->tuner) { + case TUNER_RTL2832_FC0012: + return rtl2832u_fc0012_tuner_callback(d, cmd, arg); + case TUNER_RTL2832_TUA9001: + return rtl2832u_tua9001_tuner_callback(d, cmd, arg); + } default: - break; + return -EINVAL; } return 0; -- cgit v1.2.3 From 6a53fa2350f724ca84b0a1946f3046855e1efd41 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 17 Dec 2014 08:16:10 -0300 Subject: [media] rtl28xxu: do not refcount rtl2832_sdr module This driver, rtl28xxu, offers frontend service for rtl2832_sdr module, thus we are producer and rtl2832_sdr module is consumer. Due to that, reference counting should be done in way rtl2832_sdr takes refrence to rtl28xxu. Remove wrong refcount. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index f4750189e948..27cf3419d4f1 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1142,16 +1142,12 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) pdata.v4l2_subdev = subdev; request_module("%s", "rtl2832_sdr"); - pdev = platform_device_register_data(&priv->i2c_client_demod->dev, + pdev = platform_device_register_data(&d->intf->dev, "rtl2832_sdr", PLATFORM_DEVID_AUTO, &pdata, sizeof(pdata)); if (pdev == NULL || pdev->dev.driver == NULL) break; - if (!try_module_get(pdev->dev.driver->owner)) { - platform_device_unregister(pdev); - break; - } priv->platform_device_sdr = pdev; break; default: @@ -1175,10 +1171,8 @@ static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) /* remove platform SDR */ pdev = priv->platform_device_sdr; - if (pdev) { - module_put(pdev->dev.driver->owner); + if (pdev) platform_device_unregister(pdev); - } /* remove I2C tuner */ client = priv->i2c_client_tuner; -- cgit v1.2.3 From d5eec231becd745c8a943dcac27c681dabb013d7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 17 Dec 2014 08:25:03 -0300 Subject: [media] rtl2832_sdr: refcount to rtl28xxu We are consumer of DVB frontend provided by rtl28xxu module. Due to that we must use refcount to ensure none could remove rtl28xxu when we are alive (or when we are streaming, if more fine-grained refcounting is wanted). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 62e85a3b2234..3ff8806ca584 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -1310,10 +1310,21 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) ret = -EINVAL; goto err; } + if (!pdev->dev.parent->driver) { + dev_dbg(&pdev->dev, "No parent device\n"); + ret = -EINVAL; + goto err; + } + /* try to refcount host drv since we are the consumer */ + if (!try_module_get(pdev->dev.parent->driver->owner)) { + dev_err(&pdev->dev, "Refcount fail"); + ret = -EINVAL; + goto err; + } dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { ret = -ENOMEM; - goto err; + goto err_module_put; } /* setup the state */ @@ -1426,6 +1437,8 @@ err_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(&dev->hdl); err_kfree: kfree(dev); +err_module_put: + module_put(pdev->dev.parent->driver->owner); err: return ret; } @@ -1444,8 +1457,8 @@ static int rtl2832_sdr_remove(struct platform_device *pdev) video_unregister_device(&dev->vdev); mutex_unlock(&dev->v4l2_lock); mutex_unlock(&dev->vb_queue_lock); - v4l2_device_put(&dev->v4l2_dev); + module_put(pdev->dev.parent->driver->owner); return 0; } -- cgit v1.2.3 From 0d117901b6ecb67f863345d283dcc09a479232ab Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 18 Dec 2014 06:30:32 -0300 Subject: [media] rtl2832: remove internal mux I2C adapter There was 2 muxed I2C adapters, one for demod tuner bus and one for internal use. Idea of internal I2C adapter was to force I2C repeater close when demod access its registers. Driver has also delayed work queue based method to close I2C repeater. After regmap conversion internal I2C adapter based repeater close left unused - only work queue method was in use. We could not use internal mux adapter method with regmap as it makes recursive regmap call, which causes deadlock as regmap has own locking. Due to that remove whole method totally. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 24 ++++-------------------- drivers/media/dvb-frontends/rtl2832_priv.h | 1 - 2 files changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index e80c6b974f4c..eaa74b0c8609 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -868,15 +868,10 @@ static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id) cancel_delayed_work(&dev->i2c_gate_work); /* - * chan_id 1 is muxed adapter demod provides and chan_id 0 is demod - * itself. We need open gate when request is for chan_id 1. On that case * I2C adapter lock is already taken and due to that we will use * regmap_update_bits() which does not lock again I2C adapter. */ - if (chan_id == 1) - ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08); - else - ret = rtl2832_update_bits(dev->client, 0x101, 0x08, 0x00); + ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08); if (ret) goto err; @@ -1224,25 +1219,18 @@ static int rtl2832_probe(struct i2c_client *client, ret = PTR_ERR(dev->regmap); goto err_kfree; } - /* create muxed i2c adapter for demod itself */ - dev->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, dev, 0, 0, 0, - rtl2832_select, NULL); - if (dev->i2c_adapter == NULL) { - ret = -ENODEV; - goto err_regmap_exit; - } /* check if the demod is there */ ret = rtl2832_bulk_read(client, 0x000, &tmp, 1); if (ret) - goto err_i2c_del_mux_adapter; + goto err_regmap_exit; /* create muxed i2c adapter for demod tuner bus */ dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, dev, - 0, 1, 0, rtl2832_select, rtl2832_deselect); + 0, 0, 0, rtl2832_select, rtl2832_deselect); if (dev->i2c_adapter_tuner == NULL) { ret = -ENODEV; - goto err_i2c_del_mux_adapter; + goto err_regmap_exit; } /* create dvb_frontend */ @@ -1261,8 +1249,6 @@ static int rtl2832_probe(struct i2c_client *client, dev_info(&client->dev, "Realtek RTL2832 successfully attached\n"); return 0; -err_i2c_del_mux_adapter: - i2c_del_mux_adapter(dev->i2c_adapter); err_regmap_exit: regmap_exit(dev->regmap); err_kfree: @@ -1282,8 +1268,6 @@ static int rtl2832_remove(struct i2c_client *client) i2c_del_mux_adapter(dev->i2c_adapter_tuner); - i2c_del_mux_adapter(dev->i2c_adapter); - regmap_exit(dev->regmap); kfree(dev); diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index e25d7487ec06..9ff4f6530346 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -34,7 +34,6 @@ struct rtl2832_dev { struct rtl2832_platform_data *pdata; struct i2c_client *client; struct regmap *regmap; - struct i2c_adapter *i2c_adapter; struct i2c_adapter *i2c_adapter_tuner; struct dvb_frontend fe; struct delayed_work stat_work; -- cgit v1.2.3 From 9a02e8fdef53f80010de5b9dccaac0fff49c4992 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 18 Dec 2014 08:05:23 -0300 Subject: [media] rtl28xxu: rename state variable 'priv' to 'dev' I prefer dev over priv and I want keep all my drivers in line with that. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 238 ++++++++++++++++---------------- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 2 +- 2 files changed, 120 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 27cf3419d4f1..57afcbabadef 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -147,7 +147,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], { int ret; struct dvb_usb_device *d = i2c_get_adapdata(adap); - struct rtl28xxu_priv *priv = d->priv; + struct rtl28xxu_dev *dev = d->priv; struct rtl28xxu_req req; /* @@ -184,7 +184,7 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } else if (msg[0].addr == 0x10) { /* method 1 - integrated demod */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); - req.index = CMD_DEMOD_RD | priv->page; + req.index = CMD_DEMOD_RD | dev->page; req.size = msg[1].len; req.data = &msg[1].buf[0]; ret = rtl28xxu_ctrl_msg(d, &req); @@ -220,12 +220,12 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], /* method 1 - integrated demod */ if (msg[0].buf[0] == 0x00) { /* save demod page for later demod access */ - priv->page = msg[0].buf[1]; + dev->page = msg[0].buf[1]; ret = 0; } else { req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); - req.index = CMD_DEMOD_WR | priv->page; + req.index = CMD_DEMOD_WR | dev->page; req.size = msg[0].len-1; req.data = &msg[0].buf[1]; ret = rtl28xxu_ctrl_msg(d, &req); @@ -267,7 +267,7 @@ static struct i2c_algorithm rtl28xxu_i2c_algo = { static int rtl2831u_read_config(struct dvb_usb_device *d) { - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); int ret; u8 buf[1]; /* open RTL2831U/RTL2830 I2C gate */ @@ -304,7 +304,7 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) /* demod needs some time to wake up */ msleep(20); - priv->tuner_name = "NONE"; + dev->tuner_name = "NONE"; /* open demod I2C gate */ ret = rtl28xxu_ctrl_msg(d, &req_gate_open); @@ -314,8 +314,8 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) /* check QT1010 ID(?) register; reg=0f val=2c */ ret = rtl28xxu_ctrl_msg(d, &req_qt1010); if (ret == 0 && buf[0] == 0x2c) { - priv->tuner = TUNER_RTL2830_QT1010; - priv->tuner_name = "QT1010"; + dev->tuner = TUNER_RTL2830_QT1010; + dev->tuner_name = "QT1010"; goto found; } @@ -327,18 +327,18 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) /* check MT2060 ID register; reg=00 val=63 */ ret = rtl28xxu_ctrl_msg(d, &req_mt2060); if (ret == 0 && buf[0] == 0x63) { - priv->tuner = TUNER_RTL2830_MT2060; - priv->tuner_name = "MT2060"; + dev->tuner = TUNER_RTL2830_MT2060; + dev->tuner_name = "MT2060"; goto found; } /* assume MXL5005S */ - priv->tuner = TUNER_RTL2830_MXL5005S; - priv->tuner_name = "MXL5005S"; + dev->tuner = TUNER_RTL2830_MXL5005S; + dev->tuner_name = "MXL5005S"; goto found; found: - dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); + dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, dev->tuner_name); return 0; err: @@ -348,7 +348,7 @@ err: static int rtl2832u_read_config(struct dvb_usb_device *d) { - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); int ret; u8 buf[2]; /* open RTL2832U/RTL2832 I2C gate */ @@ -392,109 +392,109 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) if (ret) goto err; - priv->tuner_name = "NONE"; + dev->tuner_name = "NONE"; /* check FC0012 ID register; reg=00 val=a1 */ ret = rtl28xxu_ctrl_msg(d, &req_fc0012); if (ret == 0 && buf[0] == 0xa1) { - priv->tuner = TUNER_RTL2832_FC0012; - priv->tuner_name = "FC0012"; + dev->tuner = TUNER_RTL2832_FC0012; + dev->tuner_name = "FC0012"; goto tuner_found; } /* check FC0013 ID register; reg=00 val=a3 */ ret = rtl28xxu_ctrl_msg(d, &req_fc0013); if (ret == 0 && buf[0] == 0xa3) { - priv->tuner = TUNER_RTL2832_FC0013; - priv->tuner_name = "FC0013"; + dev->tuner = TUNER_RTL2832_FC0013; + dev->tuner_name = "FC0013"; goto tuner_found; } /* check MT2266 ID register; reg=00 val=85 */ ret = rtl28xxu_ctrl_msg(d, &req_mt2266); if (ret == 0 && buf[0] == 0x85) { - priv->tuner = TUNER_RTL2832_MT2266; - priv->tuner_name = "MT2266"; + dev->tuner = TUNER_RTL2832_MT2266; + dev->tuner_name = "MT2266"; goto tuner_found; } /* check FC2580 ID register; reg=01 val=56 */ ret = rtl28xxu_ctrl_msg(d, &req_fc2580); if (ret == 0 && buf[0] == 0x56) { - priv->tuner = TUNER_RTL2832_FC2580; - priv->tuner_name = "FC2580"; + dev->tuner = TUNER_RTL2832_FC2580; + dev->tuner_name = "FC2580"; goto tuner_found; } /* check MT2063 ID register; reg=00 val=9e || 9c */ ret = rtl28xxu_ctrl_msg(d, &req_mt2063); if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { - priv->tuner = TUNER_RTL2832_MT2063; - priv->tuner_name = "MT2063"; + dev->tuner = TUNER_RTL2832_MT2063; + dev->tuner_name = "MT2063"; goto tuner_found; } /* check MAX3543 ID register; reg=00 val=38 */ ret = rtl28xxu_ctrl_msg(d, &req_max3543); if (ret == 0 && buf[0] == 0x38) { - priv->tuner = TUNER_RTL2832_MAX3543; - priv->tuner_name = "MAX3543"; + dev->tuner = TUNER_RTL2832_MAX3543; + dev->tuner_name = "MAX3543"; goto tuner_found; } /* check TUA9001 ID register; reg=7e val=2328 */ ret = rtl28xxu_ctrl_msg(d, &req_tua9001); if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { - priv->tuner = TUNER_RTL2832_TUA9001; - priv->tuner_name = "TUA9001"; + dev->tuner = TUNER_RTL2832_TUA9001; + dev->tuner_name = "TUA9001"; goto tuner_found; } /* check MXL5007R ID register; reg=d9 val=14 */ ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t); if (ret == 0 && buf[0] == 0x14) { - priv->tuner = TUNER_RTL2832_MXL5007T; - priv->tuner_name = "MXL5007T"; + dev->tuner = TUNER_RTL2832_MXL5007T; + dev->tuner_name = "MXL5007T"; goto tuner_found; } /* check E4000 ID register; reg=02 val=40 */ ret = rtl28xxu_ctrl_msg(d, &req_e4000); if (ret == 0 && buf[0] == 0x40) { - priv->tuner = TUNER_RTL2832_E4000; - priv->tuner_name = "E4000"; + dev->tuner = TUNER_RTL2832_E4000; + dev->tuner_name = "E4000"; goto tuner_found; } /* check TDA18272 ID register; reg=00 val=c760 */ ret = rtl28xxu_ctrl_msg(d, &req_tda18272); if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { - priv->tuner = TUNER_RTL2832_TDA18272; - priv->tuner_name = "TDA18272"; + dev->tuner = TUNER_RTL2832_TDA18272; + dev->tuner_name = "TDA18272"; goto tuner_found; } /* check R820T ID register; reg=00 val=69 */ ret = rtl28xxu_ctrl_msg(d, &req_r820t); if (ret == 0 && buf[0] == 0x69) { - priv->tuner = TUNER_RTL2832_R820T; - priv->tuner_name = "R820T"; + dev->tuner = TUNER_RTL2832_R820T; + dev->tuner_name = "R820T"; goto tuner_found; } /* check R828D ID register; reg=00 val=69 */ ret = rtl28xxu_ctrl_msg(d, &req_r828d); if (ret == 0 && buf[0] == 0x69) { - priv->tuner = TUNER_RTL2832_R828D; - priv->tuner_name = "R828D"; + dev->tuner = TUNER_RTL2832_R828D; + dev->tuner_name = "R828D"; goto tuner_found; } tuner_found: - dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); + dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, dev->tuner_name); /* probe slave demod */ - if (priv->tuner == TUNER_RTL2832_R828D) { + if (dev->tuner == TUNER_RTL2832_R828D) { /* power on MN88472 demod on GPIO0 */ ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01); if (ret) @@ -512,14 +512,14 @@ tuner_found: ret = rtl28xxu_ctrl_msg(d, &req_mn88472); if (ret == 0 && buf[0] == 0x02) { dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__); - priv->slave_demod = SLAVE_DEMOD_MN88472; + dev->slave_demod = SLAVE_DEMOD_MN88472; goto demod_found; } ret = rtl28xxu_ctrl_msg(d, &req_mn88473); if (ret == 0 && buf[0] == 0x03) { dev_dbg(&d->udev->dev, "%s: MN88473 found\n", __func__); - priv->slave_demod = SLAVE_DEMOD_MN88473; + dev->slave_demod = SLAVE_DEMOD_MN88473; goto demod_found; } } @@ -564,15 +564,15 @@ static const struct rtl2830_platform_data rtl2830_mxl5005s_platform_data = { static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; struct i2c_board_info board_info; struct i2c_client *client; int ret; dev_dbg(&d->udev->dev, "%s:\n", __func__); - switch (priv->tuner) { + switch (dev->tuner) { case TUNER_RTL2830_QT1010: *pdata = rtl2830_qt1010_platform_data; break; @@ -584,7 +584,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", - KBUILD_MODNAME, priv->tuner_name); + KBUILD_MODNAME, dev->tuner_name); ret = -ENODEV; goto err; } @@ -608,9 +608,9 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) } adap->fe[0] = pdata->get_dvb_frontend(client); - priv->demod_i2c_adapter = pdata->get_i2c_adapter(client); + dev->demod_i2c_adapter = pdata->get_i2c_adapter(client); - priv->i2c_client_demod = client; + dev->i2c_client_demod = client; return 0; err: @@ -728,7 +728,7 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, struct device *parent = adapter->dev.parent; struct i2c_adapter *parent_adapter; struct dvb_usb_device *d; - struct rtl28xxu_priv *priv; + struct rtl28xxu_dev *dev; /* * All tuners are connected to demod muxed I2C adapter. We have to @@ -742,14 +742,14 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, return -EINVAL; d = i2c_get_adapdata(parent_adapter); - priv = d->priv; + dev = d->priv; dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", __func__, component, cmd, arg); switch (component) { case DVB_FRONTEND_COMPONENT_TUNER: - switch (priv->tuner) { + switch (dev->tuner) { case TUNER_RTL2832_FC0012: return rtl2832u_fc0012_tuner_callback(d, cmd, arg); case TUNER_RTL2832_TUA9001: @@ -765,15 +765,15 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; struct i2c_board_info board_info; struct i2c_client *client; int ret; dev_dbg(&d->udev->dev, "%s:\n", __func__); - switch (priv->tuner) { + switch (dev->tuner) { case TUNER_RTL2832_FC0012: *pdata = rtl2832_fc0012_platform_data; break; @@ -796,7 +796,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", - KBUILD_MODNAME, priv->tuner_name); + KBUILD_MODNAME, dev->tuner_name); ret = -ENODEV; goto err; } @@ -820,14 +820,14 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) } adap->fe[0] = pdata->get_dvb_frontend(client); - priv->demod_i2c_adapter = pdata->get_i2c_adapter(client); + dev->demod_i2c_adapter = pdata->get_i2c_adapter(client); - priv->i2c_client_demod = client; + dev->i2c_client_demod = client; /* set fe callback */ adap->fe[0]->callback = rtl2832u_frontend_callback; - if (priv->slave_demod) { + if (dev->slave_demod) { struct i2c_board_info info = {}; /* @@ -837,7 +837,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) ret = 0; /* attach slave demodulator */ - if (priv->slave_demod == SLAVE_DEMOD_MN88472) { + if (dev->slave_demod == SLAVE_DEMOD_MN88472) { struct mn88472_config mn88472_config = {}; mn88472_config.fe = &adap->fe[1]; @@ -849,17 +849,17 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) request_module(info.type); client = i2c_new_device(&d->i2c_adap, &info); if (client == NULL || client->dev.driver == NULL) { - priv->slave_demod = SLAVE_DEMOD_NONE; + dev->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; } if (!try_module_get(client->dev.driver->owner)) { i2c_unregister_device(client); - priv->slave_demod = SLAVE_DEMOD_NONE; + dev->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; } - priv->i2c_client_slave_demod = client; + dev->i2c_client_slave_demod = client; } else { struct mn88473_config mn88473_config = {}; @@ -871,17 +871,17 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) request_module(info.type); client = i2c_new_device(&d->i2c_adap, &info); if (client == NULL || client->dev.driver == NULL) { - priv->slave_demod = SLAVE_DEMOD_NONE; + dev->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; } if (!try_module_get(client->dev.driver->owner)) { i2c_unregister_device(client); - priv->slave_demod = SLAVE_DEMOD_NONE; + dev->slave_demod = SLAVE_DEMOD_NONE; goto err_slave_demod_failed; } - priv->i2c_client_slave_demod = client; + dev->i2c_client_slave_demod = client; } } @@ -895,20 +895,20 @@ err: static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); struct i2c_client *client; dev_dbg(&d->udev->dev, "%s:\n", __func__); /* remove I2C slave demod */ - client = priv->i2c_client_slave_demod; + client = dev->i2c_client_slave_demod; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); } /* remove I2C demod */ - client = priv->i2c_client_demod; + client = dev->i2c_client_demod; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); @@ -947,31 +947,31 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); struct dvb_frontend *fe; dev_dbg(&d->udev->dev, "%s:\n", __func__); - switch (priv->tuner) { + switch (dev->tuner) { case TUNER_RTL2830_QT1010: fe = dvb_attach(qt1010_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl28xxu_qt1010_config); break; case TUNER_RTL2830_MT2060: fe = dvb_attach(mt2060_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl28xxu_mt2060_config, 1220); break; case TUNER_RTL2830_MXL5005S: fe = dvb_attach(mxl5005s_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl28xxu_mxl5005s_config); break; default: fe = NULL; dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, - priv->tuner); + dev->tuner); } if (fe == NULL) { @@ -1017,7 +1017,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); struct dvb_frontend *fe = NULL; struct i2c_board_info info; struct i2c_client *client; @@ -1027,10 +1027,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) memset(&info, 0, sizeof(struct i2c_board_info)); - switch (priv->tuner) { + switch (dev->tuner) { case TUNER_RTL2832_FC0012: fe = dvb_attach(fc0012_attach, adap->fe[0], - priv->demod_i2c_adapter, &rtl2832u_fc0012_config); + dev->demod_i2c_adapter, &rtl2832u_fc0012_config); /* since fc0012 includs reading the signal strength delegate * that to the tuner driver */ @@ -1039,7 +1039,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; case TUNER_RTL2832_FC0013: fe = dvb_attach(fc0013_attach, adap->fe[0], - priv->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + dev->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); /* fc0013 also supports signal strength reading */ adap->fe[0]->ops.read_signal_strength = @@ -1056,7 +1056,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) info.platform_data = &e4000_config; request_module(info.type); - client = i2c_new_device(priv->demod_i2c_adapter, &info); + client = i2c_new_device(dev->demod_i2c_adapter, &info); if (client == NULL || client->dev.driver == NULL) break; @@ -1065,13 +1065,13 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; } - priv->i2c_client_tuner = client; + dev->i2c_client_tuner = client; subdev = i2c_get_clientdata(client); } break; case TUNER_RTL2832_FC2580: fe = dvb_attach(fc2580_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl2832u_fc2580_config); break; case TUNER_RTL2832_TUA9001: @@ -1085,12 +1085,12 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) goto err; fe = dvb_attach(tua9001_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl2832u_tua9001_config); break; case TUNER_RTL2832_R820T: fe = dvb_attach(r820t_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl2832u_r820t_config); /* Use tuner to get the signal strength */ @@ -1099,14 +1099,14 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; case TUNER_RTL2832_R828D: fe = dvb_attach(r820t_attach, adap->fe[0], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl2832u_r828d_config); adap->fe[0]->ops.read_signal_strength = adap->fe[0]->ops.tuner_ops.get_rf_strength; if (adap->fe[1]) { fe = dvb_attach(r820t_attach, adap->fe[1], - priv->demod_i2c_adapter, + dev->demod_i2c_adapter, &rtl2832u_r828d_config); adap->fe[1]->ops.read_signal_strength = adap->fe[1]->ops.tuner_ops.get_rf_strength; @@ -1114,15 +1114,15 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; default: dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, - priv->tuner); + dev->tuner); } - if (fe == NULL && priv->i2c_client_tuner == NULL) { + if (fe == NULL && dev->i2c_client_tuner == NULL) { ret = -ENODEV; goto err; } /* register SDR */ - switch (priv->tuner) { + switch (dev->tuner) { struct platform_device *pdev; struct rtl2832_sdr_platform_data pdata = {}; @@ -1131,12 +1131,12 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) case TUNER_RTL2832_E4000: case TUNER_RTL2832_R820T: case TUNER_RTL2832_R828D: - pdata.clk = priv->rtl2832_platform_data.clk; - pdata.tuner = priv->tuner; - pdata.i2c_client = priv->i2c_client_demod; - pdata.bulk_read = priv->rtl2832_platform_data.bulk_read; - pdata.bulk_write = priv->rtl2832_platform_data.bulk_write; - pdata.update_bits = priv->rtl2832_platform_data.update_bits; + pdata.clk = dev->rtl2832_platform_data.clk; + pdata.tuner = dev->tuner; + pdata.i2c_client = dev->i2c_client_demod; + pdata.bulk_read = dev->rtl2832_platform_data.bulk_read; + pdata.bulk_write = dev->rtl2832_platform_data.bulk_write; + pdata.update_bits = dev->rtl2832_platform_data.update_bits; pdata.dvb_frontend = adap->fe[0]; pdata.dvb_usb_device = d; pdata.v4l2_subdev = subdev; @@ -1148,10 +1148,10 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) &pdata, sizeof(pdata)); if (pdev == NULL || pdev->dev.driver == NULL) break; - priv->platform_device_sdr = pdev; + dev->platform_device_sdr = pdev; break; default: - dev_dbg(&d->udev->dev, "no SDR for tuner=%d\n", priv->tuner); + dev_dbg(&d->udev->dev, "no SDR for tuner=%d\n", dev->tuner); } return 0; @@ -1163,19 +1163,19 @@ err: static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl28xxu_dev *dev = d_to_priv(d); struct i2c_client *client; struct platform_device *pdev; dev_dbg(&d->udev->dev, "%s:\n", __func__); /* remove platform SDR */ - pdev = priv->platform_device_sdr; + pdev = dev->platform_device_sdr; if (pdev) platform_device_unregister(pdev); /* remove I2C tuner */ - client = priv->i2c_client_tuner; + client = dev->i2c_client_tuner; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); @@ -1343,8 +1343,8 @@ err: static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_device *d = fe_to_d(fe); - struct rtl28xxu_priv *priv = fe_to_priv(fe); - struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + struct rtl28xxu_dev *dev = fe_to_priv(fe); + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; int ret; u8 val; @@ -1362,7 +1362,7 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) /* bypass slave demod TS through master demod */ if (fe->id == 1 && onoff) { - ret = pdata->enable_slave_ts(priv->i2c_client_demod); + ret = pdata->enable_slave_ts(dev->i2c_client_demod); if (ret) goto err; } @@ -1377,7 +1377,7 @@ err: static int rtl2831u_rc_query(struct dvb_usb_device *d) { int ret, i; - struct rtl28xxu_priv *priv = d->priv; + struct rtl28xxu_dev *dev = d->priv; u8 buf[5]; u32 rc_code; struct rtl28xxu_reg_val rc_nec_tab[] = { @@ -1398,14 +1398,14 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) }; /* init remote controller */ - if (!priv->rc_active) { + if (!dev->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); if (ret) goto err; } - priv->rc_active = true; + dev->rc_active = true; } ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); @@ -1460,7 +1460,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, static int rtl2832u_rc_query(struct dvb_usb_device *d) { int ret, i, len; - struct rtl28xxu_priv *priv = d->priv; + struct rtl28xxu_dev *dev = d->priv; struct ir_raw_event ev; u8 buf[128]; static const struct rtl28xxu_reg_val_mask refresh_tab[] = { @@ -1470,7 +1470,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) }; /* init remote controller */ - if (!priv->rc_active) { + if (!dev->rc_active) { static const struct rtl28xxu_reg_val_mask init_tab[] = { {SYS_DEMOD_CTL1, 0x00, 0x04}, {SYS_DEMOD_CTL1, 0x00, 0x08}, @@ -1497,7 +1497,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; } - priv->rc_active = true; + dev->rc_active = true; } ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]); @@ -1570,8 +1570,8 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, static int rtl2831u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; return pdata->pid_filter_ctrl(adap->fe[0], onoff); } @@ -1579,8 +1579,8 @@ static int rtl2831u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) static int rtl2832u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; return pdata->pid_filter_ctrl(adap->fe[0], onoff); } @@ -1588,8 +1588,8 @@ static int rtl2832u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) static int rtl2831u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2830_platform_data *pdata = &priv->rtl2830_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; return pdata->pid_filter(adap->fe[0], index, pid, onoff); } @@ -1597,8 +1597,8 @@ static int rtl2831u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, static int rtl2832u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_priv *priv = d_to_priv(d); - struct rtl2832_platform_data *pdata = &priv->rtl2832_platform_data; + struct rtl28xxu_dev *dev = d_to_priv(d); + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; return pdata->pid_filter(adap->fe[0], index, pid, onoff); } @@ -1607,7 +1607,7 @@ static const struct dvb_usb_device_properties rtl2831u_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct rtl28xxu_priv), + .size_of_priv = sizeof(struct rtl28xxu_dev), .power_ctrl = rtl2831u_power_ctrl, .i2c_algo = &rtl28xxu_i2c_algo, @@ -1637,7 +1637,7 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct rtl28xxu_priv), + .size_of_priv = sizeof(struct rtl28xxu_dev), .power_ctrl = rtl2832u_power_ctrl, .frontend_ctrl = rtl2832u_frontend_ctrl, diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 62d32491fbe4..abf0111a3fda 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -68,7 +68,7 @@ #define CMD_I2C_DA_WR 0x0610 -struct rtl28xxu_priv { +struct rtl28xxu_dev { u8 chip_id; u8 tuner; char *tuner_name; -- cgit v1.2.3 From 5ba4ca1a14c3cf62064c7edc30f05c40dd7ecee2 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 21 Dec 2014 11:25:57 -0300 Subject: [media] rtl28xxu: fix logging Pass correct device pointer to dev_* logging in order to print module name and bus id correctly. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 90 +++++++++++++++------------------ 1 file changed, 42 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 57afcbabadef..e3312a21a090 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -71,7 +71,7 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -276,7 +276,7 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); /* * RTL2831U GPIOs @@ -338,11 +338,11 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) goto found; found: - dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, dev->tuner_name); + dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name); return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -371,7 +371,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf}; struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf}; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); /* enable GPIO3 and GPIO6 as output */ ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40); @@ -491,7 +491,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) } tuner_found: - dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, dev->tuner_name); + dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name); /* probe slave demod */ if (dev->tuner == TUNER_RTL2832_R828D) { @@ -511,14 +511,14 @@ tuner_found: /* check MN88472 answers */ ret = rtl28xxu_ctrl_msg(d, &req_mn88472); if (ret == 0 && buf[0] == 0x02) { - dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__); + dev_dbg(&d->intf->dev, "MN88472 found\n"); dev->slave_demod = SLAVE_DEMOD_MN88472; goto demod_found; } ret = rtl28xxu_ctrl_msg(d, &req_mn88473); if (ret == 0 && buf[0] == 0x03) { - dev_dbg(&d->udev->dev, "%s: MN88473 found\n", __func__); + dev_dbg(&d->intf->dev, "MN88473 found\n"); dev->slave_demod = SLAVE_DEMOD_MN88473; goto demod_found; } @@ -532,7 +532,7 @@ demod_found: return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -570,7 +570,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) struct i2c_client *client; int ret; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); switch (dev->tuner) { case TUNER_RTL2830_QT1010: @@ -583,8 +583,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) *pdata = rtl2830_mxl5005s_platform_data; break; default: - dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", - KBUILD_MODNAME, dev->tuner_name); + dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name); ret = -ENODEV; goto err; } @@ -614,7 +613,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -649,7 +648,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, int ret; u8 val; - dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); + dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg); switch (cmd) { case FC_FE_CALLBACK_VHF_ENABLE: @@ -674,7 +673,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, } return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -684,7 +683,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, int ret; u8 val; - dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); + dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg); /* * CEN always enabled by hardware wiring @@ -717,7 +716,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -744,8 +743,8 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component, d = i2c_get_adapdata(parent_adapter); dev = d->priv; - dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", - __func__, component, cmd, arg); + dev_dbg(&d->intf->dev, "component=%d cmd=%d arg=%d\n", + component, cmd, arg); switch (component) { case DVB_FRONTEND_COMPONENT_TUNER: @@ -771,7 +770,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) struct i2c_client *client; int ret; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); switch (dev->tuner) { case TUNER_RTL2832_FC0012: @@ -795,8 +794,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) *pdata = rtl2832_r820t_platform_data; break; default: - dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", - KBUILD_MODNAME, dev->tuner_name); + dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name); ret = -ENODEV; goto err; } @@ -888,7 +886,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) return 0; err_slave_demod_failed: err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -898,7 +896,7 @@ static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap) struct rtl28xxu_dev *dev = d_to_priv(d); struct i2c_client *client; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); /* remove I2C slave demod */ client = dev->i2c_client_slave_demod; @@ -950,7 +948,7 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) struct rtl28xxu_dev *dev = d_to_priv(d); struct dvb_frontend *fe; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); switch (dev->tuner) { case TUNER_RTL2830_QT1010: @@ -970,8 +968,7 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) break; default: fe = NULL; - dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, - dev->tuner); + dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner); } if (fe == NULL) { @@ -981,7 +978,7 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1023,7 +1020,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) struct i2c_client *client; struct v4l2_subdev *subdev = NULL; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); memset(&info, 0, sizeof(struct i2c_board_info)); @@ -1113,8 +1110,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) } break; default: - dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, - dev->tuner); + dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner); } if (fe == NULL && dev->i2c_client_tuner == NULL) { ret = -ENODEV; @@ -1151,12 +1147,12 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) dev->platform_device_sdr = pdev; break; default: - dev_dbg(&d->udev->dev, "no SDR for tuner=%d\n", dev->tuner); + dev_dbg(&d->intf->dev, "no SDR for tuner=%d\n", dev->tuner); } return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1167,7 +1163,7 @@ static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) struct i2c_client *client; struct platform_device *pdev; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); /* remove platform SDR */ pdev = dev->platform_device_sdr; @@ -1189,7 +1185,7 @@ static int rtl28xxu_init(struct dvb_usb_device *d) int ret; u8 val; - dev_dbg(&d->udev->dev, "%s:\n", __func__); + dev_dbg(&d->intf->dev, "\n"); /* init USB endpoints */ ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); @@ -1214,7 +1210,7 @@ static int rtl28xxu_init(struct dvb_usb_device *d) return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1223,7 +1219,7 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) int ret; u8 gpio, sys0, epa_ctl[2]; - dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); + dev_dbg(&d->intf->dev, "onoff=%d\n", onoff); /* demod adc */ ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); @@ -1235,8 +1231,7 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; - dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, - sys0, gpio); + dev_dbg(&d->intf->dev, "RD SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio); if (onoff) { gpio |= 0x01; /* GPIO0 = 1 */ @@ -1255,8 +1250,7 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) epa_ctl[1] = 0x02; /* set reset */ } - dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, - sys0, gpio); + dev_dbg(&d->intf->dev, "WR SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio); /* demod adc */ ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); @@ -1278,7 +1272,7 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1286,7 +1280,7 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); + dev_dbg(&d->intf->dev, "onoff=%d\n", onoff); if (onoff) { /* GPIO3=1, GPIO4=0 */ @@ -1336,7 +1330,7 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1348,7 +1342,7 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) int ret; u8 val; - dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + dev_dbg(&d->intf->dev, "fe=%d onoff=%d\n", fe->id, onoff); /* control internal demod ADC */ if (fe->id == 0 && onoff) @@ -1369,7 +1363,7 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) return 0; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1442,7 +1436,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } @@ -1541,7 +1535,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) exit: return ret; err: - dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; } -- cgit v1.2.3 From c56222a6b25c24f211ecefd6ecc1003a7cb075d4 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 21 Dec 2014 18:33:14 -0300 Subject: [media] rtl28xxu: move usb buffers to state Buffer needed for USB control message is small so move it to state and get rid of alloc/free used for each control message. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 31 +++++++++---------------------- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 1 + 2 files changed, 10 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index e3312a21a090..b0d2467398f2 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -29,20 +29,14 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) { + struct rtl28xxu_dev *dev = d->priv; int ret; unsigned int pipe; u8 requesttype; - u8 *buf; - - buf = kmalloc(req->size, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto err; - } if (req->index & CMD_WR_FLAG) { /* write */ - memcpy(buf, req->data, req->size); + memcpy(dev->buf, req->data, req->size); requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); pipe = usb_sndctrlpipe(d->udev, 0); } else { @@ -52,24 +46,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) } ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, - req->index, buf, req->size, 1000); - + req->index, dev->buf, req->size, 1000); dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value, - req->index, buf, req->size); - - if (ret > 0) - ret = 0; + req->index, dev->buf, req->size); + if (ret < 0) + goto err; /* read request, copy returned data to return buf */ - if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) - memcpy(req->data, buf, req->size); - - kfree(buf); + if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) + memcpy(req->data, dev->buf, req->size); - if (ret) - goto err; - - return ret; + return 0; err: dev_dbg(&d->intf->dev, "failed=%d\n", ret); return ret; diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index abf0111a3fda..1b5d7ffb685e 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -69,6 +69,7 @@ struct rtl28xxu_dev { + u8 buf[28]; u8 chip_id; u8 tuner; char *tuner_name; -- cgit v1.2.3 From d0f232e823af54a2554e371b5c96189facb1434b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 23 Dec 2014 13:14:36 -0300 Subject: [media] rtl28xxu: add heuristic to detect chip type Detect automatically whether chip is old RTL2831U or newer RTL2832U/RTL2832P. Detection is based I2C command that is found only from newer RTL2832U models. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index b0d2467398f2..5bc77745b737 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -523,6 +523,35 @@ err: return ret; } +static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name) +{ + struct rtl28xxu_dev *dev = d_to_priv(d); + int ret; + struct rtl28xxu_req req_demod_i2c = {0x0020, CMD_I2C_DA_RD, 0, NULL}; + + dev_dbg(&d->intf->dev, "\n"); + + /* + * Detect chip type using I2C command that is not supported + * by old RTL2831U. + */ + ret = rtl28xxu_ctrl_msg(d, &req_demod_i2c); + if (ret == -EPIPE) { + dev->chip_id = CHIP_ID_RTL2831U; + } else if (ret == 0) { + dev->chip_id = CHIP_ID_RTL2832U; + } else { + dev_err(&d->intf->dev, "chip type detection failed %d\n", ret); + goto err; + } + dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id); + + return WARM; +err: + dev_dbg(&d->intf->dev, "failed=%d\n", ret); + return ret; +} + static const struct rtl2830_platform_data rtl2830_mt2060_platform_data = { .clk = 28800000, .spec_inv = 1, @@ -1590,6 +1619,7 @@ static const struct dvb_usb_device_properties rtl2831u_props = { .adapter_nr = adapter_nr, .size_of_priv = sizeof(struct rtl28xxu_dev), + .identify_state = rtl28xxu_identify_state, .power_ctrl = rtl2831u_power_ctrl, .i2c_algo = &rtl28xxu_i2c_algo, .read_config = rtl2831u_read_config, @@ -1620,6 +1650,7 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .adapter_nr = adapter_nr, .size_of_priv = sizeof(struct rtl28xxu_dev), + .identify_state = rtl28xxu_identify_state, .power_ctrl = rtl2832u_power_ctrl, .frontend_ctrl = rtl2832u_frontend_ctrl, .i2c_algo = &rtl28xxu_i2c_algo, -- cgit v1.2.3 From de701f0ff14456204ad0077856c12f35070e5405 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 23 Dec 2014 14:09:13 -0300 Subject: [media] rtl28xxu: merge chip type specific all callbacks Merge all chip type specific prefixed (rtl2831u_ and rtl2832u_) callback to top level callback prefixed as rtl28xxu_. rtl2831u_foo() => rtl28xxu_foo() rtl2832u_foo() => rtl28xxu_foo() Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 140 +++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 5bc77745b737..821dcbaba4ff 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -523,6 +523,16 @@ err: return ret; } +static int rtl28xxu_read_config(struct dvb_usb_device *d) +{ + struct rtl28xxu_dev *dev = d_to_priv(d); + + if (dev->chip_id == CHIP_ID_RTL2831U) + return rtl2831u_read_config(d); + else + return rtl2832u_read_config(d); +} + static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name) { struct rtl28xxu_dev *dev = d_to_priv(d); @@ -906,7 +916,17 @@ err: return ret; } -static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap) +static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct rtl28xxu_dev *dev = adap_to_priv(adap); + + if (dev->chip_id == CHIP_ID_RTL2831U) + return rtl2831u_frontend_attach(adap); + else + return rtl2832u_frontend_attach(adap); +} + +static int rtl28xxu_frontend_detach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_dev *dev = d_to_priv(d); @@ -1172,7 +1192,17 @@ err: return ret; } -static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap) +static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct rtl28xxu_dev *dev = adap_to_priv(adap); + + if (dev->chip_id == CHIP_ID_RTL2831U) + return rtl2831u_tuner_attach(adap); + else + return rtl2832u_tuner_attach(adap); +} + +static int rtl28xxu_tuner_detach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_dev *dev = d_to_priv(d); @@ -1350,7 +1380,17 @@ err: return ret; } -static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) +static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + struct rtl28xxu_dev *dev = d_to_priv(d); + + if (dev->chip_id == CHIP_ID_RTL2831U) + return rtl2831u_power_ctrl(d, onoff); + else + return rtl2832u_power_ctrl(d, onoff); +} + +static int rtl28xxu_frontend_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_device *d = fe_to_d(fe); struct rtl28xxu_dev *dev = fe_to_priv(fe); @@ -1360,6 +1400,9 @@ static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff) dev_dbg(&d->intf->dev, "fe=%d onoff=%d\n", fe->id, onoff); + if (dev->chip_id == CHIP_ID_RTL2831U) + return 0; + /* control internal demod ADC */ if (fe->id == 0 && onoff) val = 0x48; /* enable ADC */ @@ -1572,45 +1615,50 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, return 0; } -#else -#define rtl2831u_get_rc_config NULL -#define rtl2832u_get_rc_config NULL -#endif -static int rtl2831u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int rtl28xxu_get_rc_config(struct dvb_usb_device *d, + struct dvb_usb_rc *rc) { - struct dvb_usb_device *d = adap_to_d(adap); struct rtl28xxu_dev *dev = d_to_priv(d); - struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; - return pdata->pid_filter_ctrl(adap->fe[0], onoff); + if (dev->chip_id == CHIP_ID_RTL2831U) + return rtl2831u_get_rc_config(d, rc); + else + return rtl2832u_get_rc_config(d, rc); } +#else +#define rtl28xxu_get_rc_config NULL +#endif -static int rtl2832u_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_dev *dev = d_to_priv(d); - struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; + struct rtl28xxu_dev *dev = adap_to_priv(adap); - return pdata->pid_filter_ctrl(adap->fe[0], onoff); -} + if (dev->chip_id == CHIP_ID_RTL2831U) { + struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; -static int rtl2831u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) -{ - struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_dev *dev = d_to_priv(d); - struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; + return pdata->pid_filter_ctrl(adap->fe[0], onoff); + } else { + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; - return pdata->pid_filter(adap->fe[0], index, pid, onoff); + return pdata->pid_filter_ctrl(adap->fe[0], onoff); + } } -static int rtl2832u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index, + u16 pid, int onoff) { - struct dvb_usb_device *d = adap_to_d(adap); - struct rtl28xxu_dev *dev = d_to_priv(d); - struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; + struct rtl28xxu_dev *dev = adap_to_priv(adap); + + if (dev->chip_id == CHIP_ID_RTL2831U) { + struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data; - return pdata->pid_filter(adap->fe[0], index, pid, onoff); + return pdata->pid_filter(adap->fe[0], index, pid, onoff); + } else { + struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data; + + return pdata->pid_filter(adap->fe[0], index, pid, onoff); + } } static const struct dvb_usb_device_properties rtl2831u_props = { @@ -1620,14 +1668,14 @@ static const struct dvb_usb_device_properties rtl2831u_props = { .size_of_priv = sizeof(struct rtl28xxu_dev), .identify_state = rtl28xxu_identify_state, - .power_ctrl = rtl2831u_power_ctrl, + .power_ctrl = rtl28xxu_power_ctrl, .i2c_algo = &rtl28xxu_i2c_algo, - .read_config = rtl2831u_read_config, - .frontend_attach = rtl2831u_frontend_attach, - .frontend_detach = rtl2832u_frontend_detach, - .tuner_attach = rtl2831u_tuner_attach, + .read_config = rtl28xxu_read_config, + .frontend_attach = rtl28xxu_frontend_attach, + .frontend_detach = rtl28xxu_frontend_detach, + .tuner_attach = rtl28xxu_tuner_attach, .init = rtl28xxu_init, - .get_rc_config = rtl2831u_get_rc_config, + .get_rc_config = rtl28xxu_get_rc_config, .num_adapters = 1, .adapter = { @@ -1636,8 +1684,8 @@ static const struct dvb_usb_device_properties rtl2831u_props = { DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter_ctrl = rtl2831u_pid_filter_ctrl, - .pid_filter = rtl2831u_pid_filter, + .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl, + .pid_filter = rtl28xxu_pid_filter, .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, @@ -1651,16 +1699,16 @@ static const struct dvb_usb_device_properties rtl2832u_props = { .size_of_priv = sizeof(struct rtl28xxu_dev), .identify_state = rtl28xxu_identify_state, - .power_ctrl = rtl2832u_power_ctrl, - .frontend_ctrl = rtl2832u_frontend_ctrl, + .power_ctrl = rtl28xxu_power_ctrl, + .frontend_ctrl = rtl28xxu_frontend_ctrl, .i2c_algo = &rtl28xxu_i2c_algo, - .read_config = rtl2832u_read_config, - .frontend_attach = rtl2832u_frontend_attach, - .frontend_detach = rtl2832u_frontend_detach, - .tuner_attach = rtl2832u_tuner_attach, - .tuner_detach = rtl2832u_tuner_detach, + .read_config = rtl28xxu_read_config, + .frontend_attach = rtl28xxu_frontend_attach, + .frontend_detach = rtl28xxu_frontend_detach, + .tuner_attach = rtl28xxu_tuner_attach, + .tuner_detach = rtl28xxu_tuner_detach, .init = rtl28xxu_init, - .get_rc_config = rtl2832u_get_rc_config, + .get_rc_config = rtl28xxu_get_rc_config, .num_adapters = 1, .adapter = { @@ -1669,8 +1717,8 @@ static const struct dvb_usb_device_properties rtl2832u_props = { DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter_ctrl = rtl2832u_pid_filter_ctrl, - .pid_filter = rtl2832u_pid_filter, + .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl, + .pid_filter = rtl28xxu_pid_filter, .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, -- cgit v1.2.3 From 723abfd787f7cccaff89036b8aa14f56a2f7a11a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 23 Dec 2014 14:21:10 -0300 Subject: [media] rtl28xxu: merge rtl2831u and rtl2832u properties As all the callbacks are already same we could merge device properties struct too and save space. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 93 +++++++++++---------------------- 1 file changed, 31 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 821dcbaba4ff..23ded778053e 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1661,38 +1661,7 @@ static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index, } } -static const struct dvb_usb_device_properties rtl2831u_props = { - .driver_name = KBUILD_MODNAME, - .owner = THIS_MODULE, - .adapter_nr = adapter_nr, - .size_of_priv = sizeof(struct rtl28xxu_dev), - - .identify_state = rtl28xxu_identify_state, - .power_ctrl = rtl28xxu_power_ctrl, - .i2c_algo = &rtl28xxu_i2c_algo, - .read_config = rtl28xxu_read_config, - .frontend_attach = rtl28xxu_frontend_attach, - .frontend_detach = rtl28xxu_frontend_detach, - .tuner_attach = rtl28xxu_tuner_attach, - .init = rtl28xxu_init, - .get_rc_config = rtl28xxu_get_rc_config, - - .num_adapters = 1, - .adapter = { - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - - .pid_filter_count = 32, - .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl, - .pid_filter = rtl28xxu_pid_filter, - - .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), - }, - }, -}; - -static const struct dvb_usb_device_properties rtl2832u_props = { +static const struct dvb_usb_device_properties rtl28xxu_props = { .driver_name = KBUILD_MODNAME, .owner = THIS_MODULE, .adapter_nr = adapter_nr, @@ -1728,69 +1697,69 @@ static const struct dvb_usb_device_properties rtl2832u_props = { static const struct usb_device_id rtl28xxu_id_table[] = { /* RTL2831U devices: */ { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, - &rtl2831u_props, "Realtek RTL2831U reference design", NULL) }, + &rtl28xxu_props, "Realtek RTL2831U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT, - &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, + &rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) }, { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2, - &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, + &rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) }, /* RTL2832U devices: */ { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832, - &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, + &rtl28xxu_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, - &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, + &rtl28xxu_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, - &rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, + &rtl28xxu_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, - &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, + &rtl28xxu_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, - &rtl2832u_props, "TerraTec NOXON DAB Stick", NULL) }, + &rtl28xxu_props, "TerraTec NOXON DAB Stick", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2, - &rtl2832u_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) }, + &rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV3, - &rtl2832u_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) }, + &rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0, - &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) }, + &rtl28xxu_props, "Trekstor DVB-T Stick Terres 2.0", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101, - &rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) }, + &rtl28xxu_props, "Dexatek DK DVB-T Dongle", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680, - &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, + &rtl28xxu_props, "DigitalNow Quad DVB-T Receiver", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID, - &rtl2832u_props, "Leadtek Winfast DTV Dongle Mini D", NULL) }, + &rtl28xxu_props, "Leadtek Winfast DTV Dongle Mini D", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, - &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, + &rtl28xxu_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102, - &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) }, + &rtl28xxu_props, "Dexatek DK mini DVB-T Dongle", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7, - &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) }, + &rtl28xxu_props, "TerraTec Cinergy T Stick+", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd3a8, - &rtl2832u_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) }, + &rtl28xxu_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393, - &rtl2832u_props, "GIGABYTE U7300", NULL) }, + &rtl28xxu_props, "GIGABYTE U7300", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104, - &rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) }, + &rtl28xxu_props, "MSI DIGIVOX Micro HD", NULL) }, { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, - &rtl2832u_props, "Compro VideoMate U620F", NULL) }, + &rtl28xxu_props, "Compro VideoMate U620F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, - &rtl2832u_props, "MaxMedia HU394-T", NULL) }, + &rtl28xxu_props, "MaxMedia HU394-T", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, - &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, + &rtl28xxu_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, - &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, + &rtl28xxu_props, "Crypto ReDi PC 50 A", NULL) }, { DVB_USB_DEVICE(USB_VID_KYE, 0x707f, - &rtl2832u_props, "Genius TVGo DVB-T03", NULL) }, + &rtl28xxu_props, "Genius TVGo DVB-T03", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd395, - &rtl2832u_props, "Peak DVB-T USB", NULL) }, + &rtl28xxu_props, "Peak DVB-T USB", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U, - &rtl2832u_props, "Sveon STV20", NULL) }, + &rtl28xxu_props, "Sveon STV20", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21, - &rtl2832u_props, "Sveon STV21", NULL) }, + &rtl28xxu_props, "Sveon STV21", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27, - &rtl2832u_props, "Sveon STV27", NULL) }, + &rtl28xxu_props, "Sveon STV27", NULL) }, /* RTL2832P devices: */ { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, - &rtl2832u_props, "Astrometa DVB-T2", NULL) }, + &rtl28xxu_props, "Astrometa DVB-T2", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); -- cgit v1.2.3 From 670ef05f829bcbab1548f6cdc93d522723c56fd3 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 23 Dec 2014 14:32:35 -0300 Subject: [media] rtl28xxu: correct reg access routine name prefixes Use rtl28xxu_ prefix for all register access routine names. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 100 ++++++++++++++++---------------- 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 23ded778053e..d88f7994bc7c 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -62,7 +62,7 @@ err: return ret; } -static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) +static int rtl28xxu_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) { struct rtl28xxu_req req; @@ -80,7 +80,7 @@ static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) return rtl28xxu_ctrl_msg(d, &req); } -static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) +static int rtl28xxu_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) { struct rtl28xxu_req req; @@ -98,17 +98,17 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) return rtl28xxu_ctrl_msg(d, &req); } -static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) +static int rtl28xxu_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) { - return rtl28xx_wr_regs(d, reg, &val, 1); + return rtl28xxu_wr_regs(d, reg, &val, 1); } -static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) +static int rtl28xxu_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) { - return rtl2831_rd_regs(d, reg, val, 1); + return rtl28xxu_rd_regs(d, reg, val, 1); } -static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, +static int rtl28xxu_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, u8 mask) { int ret; @@ -116,7 +116,7 @@ static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, /* no need for read if whole reg is written */ if (mask != 0xff) { - ret = rtl28xx_rd_reg(d, reg, &tmp); + ret = rtl28xxu_rd_reg(d, reg, &tmp); if (ret) return ret; @@ -125,7 +125,7 @@ static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, val |= tmp; } - return rtl28xx_wr_reg(d, reg, val); + return rtl28xxu_wr_reg(d, reg, val); } /* I2C */ @@ -274,12 +274,12 @@ static int rtl2831u_read_config(struct dvb_usb_device *d) */ /* GPIO direction */ - ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a); + ret = rtl28xxu_wr_reg(d, SYS_GPIO_DIR, 0x0a); if (ret) goto err; /* enable as output GPIO0, GPIO2, GPIO4 */ - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15); + ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_EN, 0x15); if (ret) goto err; @@ -361,11 +361,11 @@ static int rtl2832u_read_config(struct dvb_usb_device *d) dev_dbg(&d->intf->dev, "\n"); /* enable GPIO3 and GPIO6 as output */ - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40); if (ret) goto err; - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48); if (ret) goto err; @@ -483,15 +483,15 @@ tuner_found: /* probe slave demod */ if (dev->tuner == TUNER_RTL2832_R828D) { /* power on MN88472 demod on GPIO0 */ - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01); if (ret) goto err; - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); if (ret) goto err; - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); if (ret) goto err; @@ -679,7 +679,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, switch (cmd) { case FC_FE_CALLBACK_VHF_ENABLE: /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) goto err; @@ -689,7 +689,7 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, val |= 0x40; /* set GPIO6 high */ - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, val); if (ret) goto err; break; @@ -724,7 +724,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, else val = (0 << 4); - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10); if (ret) goto err; break; @@ -734,7 +734,7 @@ static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, else val = (0 << 1); - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02); if (ret) goto err; break; @@ -1109,11 +1109,11 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) break; case TUNER_RTL2832_TUA9001: /* enable GPIO1 and GPIO4 as output */ - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12); if (ret) goto err; - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12); if (ret) goto err; @@ -1234,23 +1234,23 @@ static int rtl28xxu_init(struct dvb_usb_device *d) dev_dbg(&d->intf->dev, "\n"); /* init USB endpoints */ - ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); + ret = rtl28xxu_rd_reg(d, USB_SYSCTL_0, &val); if (ret) goto err; /* enable DMA and Full Packet Mode*/ val |= 0x09; - ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); + ret = rtl28xxu_wr_reg(d, USB_SYSCTL_0, val); if (ret) goto err; /* set EPA maximum packet size to 0x0200 */ - ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); + ret = rtl28xxu_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); if (ret) goto err; /* change EPA FIFO length */ - ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); + ret = rtl28xxu_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); if (ret) goto err; @@ -1268,12 +1268,12 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) dev_dbg(&d->intf->dev, "onoff=%d\n", onoff); /* demod adc */ - ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); + ret = rtl28xxu_rd_reg(d, SYS_SYS0, &sys0); if (ret) goto err; /* tuner power, read GPIOs */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); + ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); if (ret) goto err; @@ -1299,17 +1299,17 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) dev_dbg(&d->intf->dev, "WR SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio); /* demod adc */ - ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); + ret = rtl28xxu_wr_reg(d, SYS_SYS0, sys0); if (ret) goto err; /* tuner power, write GPIOs */ - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); + ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); if (ret) goto err; /* streaming EP: stall & reset */ - ret = rtl28xx_wr_regs(d, USB_EPA_CTL, epa_ctl, 2); + ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, epa_ctl, 2); if (ret) goto err; @@ -1330,27 +1330,27 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (onoff) { /* GPIO3=1, GPIO4=0 */ - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); if (ret) goto err; /* suspend? */ - ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); + ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); if (ret) goto err; /* enable PLL */ - ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); + ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); if (ret) goto err; /* disable reset */ - ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); + ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); if (ret) goto err; /* streaming EP: clear stall & reset */ - ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2); + ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2); if (ret) goto err; @@ -1359,17 +1359,17 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) goto err; } else { /* GPIO4=1 */ - ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); + ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); if (ret) goto err; /* disable PLL */ - ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); + ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); if (ret) goto err; /* streaming EP: set stall & reset */ - ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2); + ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2); if (ret) goto err; } @@ -1409,7 +1409,7 @@ static int rtl28xxu_frontend_ctrl(struct dvb_frontend *fe, int onoff) else val = 0x00; /* disable ADC */ - ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48); + ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48); if (ret) goto err; @@ -1453,7 +1453,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) /* init remote controller */ if (!dev->rc_active) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, + ret = rtl28xxu_wr_reg(d, rc_nec_tab[i].reg, rc_nec_tab[i].val); if (ret) goto err; @@ -1461,7 +1461,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) dev->rc_active = true; } - ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); + ret = rtl28xxu_rd_regs(d, SYS_IRRC_RP, buf, 5); if (ret) goto err; @@ -1483,12 +1483,12 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0); - ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); + ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1); if (ret) goto err; /* repeated intentionally to avoid extra keypress */ - ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); + ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1); if (ret) goto err; } @@ -1544,7 +1544,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) }; for (i = 0; i < ARRAY_SIZE(init_tab); i++) { - ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, + ret = rtl28xxu_wr_reg_mask(d, init_tab[i].reg, init_tab[i].val, init_tab[i].mask); if (ret) goto err; @@ -1553,27 +1553,27 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) dev->rc_active = true; } - ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]); + ret = rtl28xxu_rd_reg(d, IR_RX_IF, &buf[0]); if (ret) goto err; if (buf[0] != 0x83) goto exit; - ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); + ret = rtl28xxu_rd_reg(d, IR_RX_BC, &buf[0]); if (ret) goto err; len = buf[0]; /* read raw code from hw */ - ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + ret = rtl28xxu_rd_regs(d, IR_RX_BUF, buf, len); if (ret) goto err; /* let hw receive new code */ for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { - ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, + ret = rtl28xxu_wr_reg_mask(d, refresh_tab[i].reg, refresh_tab[i].val, refresh_tab[i].mask); if (ret) goto err; @@ -1603,7 +1603,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, { /* disable IR interrupts in order to avoid SDR sample loss */ if (rtl28xxu_disable_rc) - return rtl28xx_wr_reg(d, IR_RX_IE, 0x00); + return rtl28xxu_wr_reg(d, IR_RX_IE, 0x00); /* load empty to enable rc */ if (!rc->map_name) -- cgit v1.2.3 From b410dae43cd0dc9aa07f9ada54a7b78d0fd75566 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 18 Dec 2014 07:22:46 -0300 Subject: [media] rtl2832: implement own lock for regmap Introduce own lock to silence lockdep warning. lockdep validator makes wrong decision when two similar (&map->mutex) locks were taken recursively, even those are different mutexes in a two different drivers. After that patch, functionality remains same, but mutex names are different. That is a temporary hack, proper solution is make regmap aware of locked nested locking rules. ============================================= [ INFO: possible recursive locking detected ] 3.18.0-rc4+ #4 Tainted: G O --------------------------------------------- kdvb-ad-0-fe-0/2814 is trying to acquire lock: (&map->mutex){+.+.+.}, at: [] regmap_lock_mutex+0x2f/0x40 but task is already holding lock: (&map->mutex){+.+.+.}, at: [] regmap_lock_mutex+0x2f/0x40 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&map->mutex); lock(&map->mutex); *** DEADLOCK *** May be due to missing lock nesting notation 1 lock held by kdvb-ad-0-fe-0/2814: #0: (&map->mutex){+.+.+.}, at: [] regmap_lock_mutex+0x2f/0x40 stack backtrace: CPU: 3 PID: 2814 Comm: kdvb-ad-0-fe-0 Tainted: G O 3.18.0-rc4+ #4 Hardware name: System manufacturer System Product Name/M5A78L-M/USB3, BIOS 2001 09/11/2014 0000000000000000 00000000410c8772 ffff880293af3868 ffffffff817a6f82 0000000000000000 ffff8800b3462be0 ffff880293af3968 ffffffff810e7f94 ffff880293af3888 00000000410c8772 ffffffff82dfee60 ffffffff81ab8f89 Call Trace: [] dump_stack+0x4e/0x68 [] __lock_acquire+0x1ea4/0x1f50 [] ? trace_hardirqs_off+0xd/0x10 [] ? _raw_spin_lock_irqsave+0x83/0xa0 [] ? up+0x16/0x50 [] ? trace_hardirqs_off+0xd/0x10 [] ? _raw_spin_unlock_irqrestore+0x5f/0x70 [] lock_acquire+0xc9/0x170 [] ? regmap_lock_mutex+0x2f/0x40 [] mutex_lock_nested+0x7e/0x430 [] ? regmap_lock_mutex+0x2f/0x40 [] ? regmap_lock_mutex+0x2f/0x40 [] ? printk+0x70/0x86 [] ? mod_timer+0x168/0x240 [] regmap_lock_mutex+0x2f/0x40 [] regmap_update_bits+0x29/0x60 [] rtl2832_select+0x38/0x70 [rtl2832] [] i2c_mux_master_xfer+0x3d/0x90 [i2c_mux] [] __i2c_transfer+0x73/0x2e0 [] i2c_transfer+0x5a/0xc0 [] i2c_master_send+0x4e/0x70 [] regmap_i2c_write+0x1a/0x50 [regmap_i2c] [] ? mutex_lock_nested+0x283/0x430 [] _regmap_raw_write+0x862/0x880 [] ? regmap_lock_mutex+0x2f/0x40 [] _regmap_bus_raw_write+0x74/0xa0 [] _regmap_write+0x92/0x140 [] regmap_write+0x4b/0x70 [] ? dvb_frontend_release+0x110/0x110 [dvb_core] [] e4000_init+0x34/0x210 [e4000] [] dvb_frontend_init+0x59/0xc0 [dvb_core] [] ? finish_task_switch+0x80/0x180 [] ? finish_task_switch+0x42/0x180 [] dvb_frontend_thread+0x86/0x7b0 [dvb_core] [] ? __schedule+0x343/0x930 [] ? dvb_frontend_release+0x110/0x110 [dvb_core] [] kthread+0x10b/0x130 [] ? sched_clock+0x9/0x10 [] ? kthread_create_on_node+0x250/0x250 [] ret_from_fork+0x7c/0xb0 [] ? kthread_create_on_node+0x250/0x250 Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 48 +++++++++++++++++++++++------- drivers/media/dvb-frontends/rtl2832_priv.h | 2 ++ 2 files changed, 40 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index eaa74b0c8609..0f2a743bb195 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1028,6 +1028,32 @@ static int rtl2832_regmap_gather_write(void *context, const void *reg, return 0; } +/* + * FIXME: Hack. Implement own regmap locking in order to silence lockdep + * recursive lock warning. That happens when regmap I2C client calls I2C mux + * adapter, which leads demod I2C repeater enable via demod regmap. Operation + * takes two regmap locks recursively - but those are different regmap instances + * in a two different I2C drivers, so it is not deadlock. Proper fix is to make + * regmap aware of lockdep. + */ +static void rtl2832_regmap_lock(void *__dev) +{ + struct rtl2832_dev *dev = __dev; + struct i2c_client *client = dev->client; + + dev_dbg(&client->dev, "\n"); + mutex_lock(&dev->regmap_mutex); +} + +static void rtl2832_regmap_unlock(void *__dev) +{ + struct rtl2832_dev *dev = __dev; + struct i2c_client *client = dev->client; + + dev_dbg(&client->dev, "\n"); + mutex_unlock(&dev->regmap_mutex); +} + static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) { struct rtl2832_dev *dev = i2c_get_clientdata(client); @@ -1186,15 +1212,6 @@ static int rtl2832_probe(struct i2c_client *client, .range_max = 5 * 0x100, }, }; - static const struct regmap_config regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .volatile_reg = rtl2832_volatile_reg, - .max_register = 5 * 0x100, - .ranges = regmap_range_cfg, - .num_ranges = ARRAY_SIZE(regmap_range_cfg), - .cache_type = REGCACHE_RBTREE, - }; dev_dbg(&client->dev, "\n"); @@ -1213,8 +1230,19 @@ static int rtl2832_probe(struct i2c_client *client, INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); INIT_DELAYED_WORK(&dev->stat_work, rtl2832_stat_work); /* create regmap */ + mutex_init(&dev->regmap_mutex); + dev->regmap_config.reg_bits = 8, + dev->regmap_config.val_bits = 8, + dev->regmap_config.lock = rtl2832_regmap_lock, + dev->regmap_config.unlock = rtl2832_regmap_unlock, + dev->regmap_config.lock_arg = dev, + dev->regmap_config.volatile_reg = rtl2832_volatile_reg, + dev->regmap_config.max_register = 5 * 0x100, + dev->regmap_config.ranges = regmap_range_cfg, + dev->regmap_config.num_ranges = ARRAY_SIZE(regmap_range_cfg), + dev->regmap_config.cache_type = REGCACHE_RBTREE, dev->regmap = regmap_init(&client->dev, ®map_bus, client, - ®map_config); + &dev->regmap_config); if (IS_ERR(dev->regmap)) { ret = PTR_ERR(dev->regmap); goto err_kfree; diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 9ff4f6530346..c3a922c37903 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -33,6 +33,8 @@ struct rtl2832_dev { struct rtl2832_platform_data *pdata; struct i2c_client *client; + struct mutex regmap_mutex; + struct regmap_config regmap_config; struct regmap *regmap; struct i2c_adapter *i2c_adapter_tuner; struct dvb_frontend fe; -- cgit v1.2.3 From 61c309ffcdc09c5fc7a13371fcf178a334eb36b7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 2 Feb 2015 13:53:38 -0300 Subject: [media] rtl2830: add kernel-doc comments for platform_data Add kernel-doc comments for platform_data configuration structure. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.h | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 156edf714f9f..0cde151e6608 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -20,33 +20,26 @@ #include +/** + * struct rtl2830_platform_data - Platform data for the rtl2830 driver + * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000). + * @spec_inv: Spectrum inversion. + * @vtop: AGC take-over point. + * @krf: AGC ratio. + * @agc_targ_val: AGC. + * @get_dvb_frontend: Get DVB frontend. + * @get_i2c_adapter: Get I2C adapter. + * @pid_filter: Set PID to PID filter. + * @pid_filter_ctrl: Control PID filter. + */ + struct rtl2830_platform_data { - /* - * Clock frequency. - * Hz - * 4000000, 16000000, 25000000, 28800000 - */ u32 clk; - - /* - * Spectrum inversion. - */ bool spec_inv; - - /* - */ u8 vtop; - - /* - */ u8 krf; - - /* - */ u8 agc_targ_val; - /* - */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); int (*pid_filter)(struct dvb_frontend *, u8, u16, int); -- cgit v1.2.3 From 2f74b7c2f818c7b0c86e1073c2dd49a95078844f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 2 Feb 2015 14:20:01 -0300 Subject: [media] rtl2832: add kernel-doc comments for platform_data Add kernel-doc comments for platform_data configuration structure. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index e5f67cf0a65b..a8e912e679a5 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -25,16 +25,20 @@ #include #include +/** + * struct rtl2832_platform_data - Platform data for the rtl2832 driver + * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000). + * @tuner: Used tuner model. + * @get_dvb_frontend: Get DVB frontend. + * @get_i2c_adapter: Get I2C adapter. + * @enable_slave_ts: Enable slave TS IF. + * @pid_filter: Set PID to PID filter. + * @pid_filter_ctrl: Control PID filter. + */ + struct rtl2832_platform_data { - /* - * Clock frequency. - * Hz - * 4000000, 16000000, 25000000, 28800000 - */ u32 clk; - /* - * Tuner. * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver. */ #define RTL2832_TUNER_TUA9001 0x24 @@ -45,15 +49,12 @@ struct rtl2832_platform_data { #define RTL2832_TUNER_R828D 0x2b u8 tuner; - /* - * Callbacks. - */ struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *); struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *); int (*enable_slave_ts)(struct i2c_client *); int (*pid_filter)(struct dvb_frontend *, u8, u16, int); int (*pid_filter_ctrl)(struct dvb_frontend *, int); - /* Register access for SDR module */ +/* private: Register access for SDR module use only */ int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t); int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t); int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int); -- cgit v1.2.3 From cecc58962014995db02dbfa9778523177b14fd6e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 2 Feb 2015 14:35:48 -0300 Subject: [media] rtl2832_sdr: add kernel-doc comments for platform_data Add kernel-doc comments for platform_data configuration structure. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832_sdr.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h index dd22e421162b..d2594768bff2 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.h +++ b/drivers/media/dvb-frontends/rtl2832_sdr.h @@ -29,16 +29,22 @@ #include #include "dvb_frontend.h" +/** + * struct rtl2832_sdr_platform_data - Platform data for the rtl2832_sdr driver + * @clk: Clock frequency (4000000, 16000000, 25000000, 28800000). + * @tuner: Used tuner model. + * @i2c_client: rtl2832 demod driver I2C client. + * @bulk_read: rtl2832 driver private I/O interface. + * @bulk_write: rtl2832 driver private I/O interface. + * @update_bits: rtl2832 driver private I/O interface. + * @dvb_frontend: rtl2832 DVB frontend. + * @v4l2_subdev: Tuner v4l2 controls. + * @dvb_usb_device: DVB USB interface for USB streaming. + */ + struct rtl2832_sdr_platform_data { - /* - * Clock frequency. - * Hz - * 4000000, 16000000, 25000000, 28800000 - */ u32 clk; - /* - * Tuner. * XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver. */ #define RTL2832_SDR_TUNER_TUA9001 0x24 -- cgit v1.2.3 From d858b0e787a8eef66457bcbbd9a758a327102b94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Feb 2015 16:32:34 -0200 Subject: [media] rtl2830: declare functions as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb-frontends/rtl2830.c:21:5: warning: no previous prototype for ‘rtl2830_bulk_write’ [-Wmissing-prototypes] int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, ^ drivers/media/dvb-frontends/rtl2830.c:33:5: warning: no previous prototype for ‘rtl2830_update_bits’ [-Wmissing-prototypes] int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, ^ drivers/media/dvb-frontends/rtl2830.c:45:5: warning: no previous prototype for ‘rtl2830_bulk_read’ [-Wmissing-prototypes] int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg, void *val, ^ Cc: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index a90f155daadf..e1b8df62bd59 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -18,8 +18,8 @@ #include "rtl2830_priv.h" /* Our regmap is bypassing I2C adapter lock, thus we do it! */ -int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, - const void *val, size_t val_count) +static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, + const void *val, size_t val_count) { struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; @@ -30,8 +30,8 @@ int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, return ret; } -int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, - unsigned int mask, unsigned int val) +static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, + unsigned int mask, unsigned int val) { struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; @@ -42,8 +42,8 @@ int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, return ret; } -int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg, void *val, - size_t val_count) +static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg, + void *val, size_t val_count) { struct rtl2830_dev *dev = i2c_get_clientdata(client); int ret; -- cgit v1.2.3 From bda977b7318a4ec10648fe5f80b6ecb42edea7bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Feb 2015 16:34:29 -0200 Subject: [media] rtl2832: declare functions as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb-frontends/rtl2832.c:157:5: warning: no previous prototype for ‘rtl2832_bulk_write’ [-Wmissing-prototypes] int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg, ^ drivers/media/dvb-frontends/rtl2832.c:169:5: warning: no previous prototype for ‘rtl2832_update_bits’ [-Wmissing-prototypes] int rtl2832_update_bits(struct i2c_client *client, unsigned int reg, ^ drivers/media/dvb-frontends/rtl2832.c:181:5: warning: no previous prototype for ‘rtl2832_bulk_read’ [-Wmissing-prototypes] int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, void *val, Cc: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2832.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 0f2a743bb195..5d2d8f45b4b6 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -154,8 +154,8 @@ static const struct rtl2832_reg_entry registers[] = { }; /* Our regmap is bypassing I2C adapter lock, thus we do it! */ -int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg, - const void *val, size_t val_count) +static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg, + const void *val, size_t val_count) { struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; @@ -166,8 +166,8 @@ int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg, return ret; } -int rtl2832_update_bits(struct i2c_client *client, unsigned int reg, - unsigned int mask, unsigned int val) +static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg, + unsigned int mask, unsigned int val) { struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; @@ -178,8 +178,8 @@ int rtl2832_update_bits(struct i2c_client *client, unsigned int reg, return ret; } -int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, void *val, - size_t val_count) +static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg, + void *val, size_t val_count) { struct rtl2832_dev *dev = i2c_get_clientdata(client); int ret; -- cgit v1.2.3 From e181b1f19045a5843aefafa561207fbea8bd2973 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Feb 2015 16:36:28 -0200 Subject: [media] rtl28xxu: properly initialize pdata As complained by smatch: drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1159 rtl2832u_tuner_attach() info: 'pdata' is not actually initialized (unreached code). Cc: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index d88f7994bc7c..77dcfdf547ac 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1055,10 +1055,13 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) struct i2c_board_info info; struct i2c_client *client; struct v4l2_subdev *subdev = NULL; + struct platform_device *pdev; + struct rtl2832_sdr_platform_data pdata; dev_dbg(&d->intf->dev, "\n"); memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&pdata, 0, sizeof(pdata)); switch (dev->tuner) { case TUNER_RTL2832_FC0012: @@ -1155,9 +1158,6 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) /* register SDR */ switch (dev->tuner) { - struct platform_device *pdev; - struct rtl2832_sdr_platform_data pdata = {}; - case TUNER_RTL2832_FC0012: case TUNER_RTL2832_FC0013: case TUNER_RTL2832_E4000: -- cgit v1.2.3 From 86c330fa599a44b6da3bfa83dd71a665dddde5ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2014 13:47:47 -0300 Subject: [media] cx88-dvb: whitespace cleanup X-Patchwork-Delegate: m.chehab@samsung.com Fix the following smatch warning: drivers/media/pci/cx88//cx88-dvb.c:1508 dvb_register() warn: if statement not indented Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx88/cx88-dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index 5780e2f013b4..1b2ed238cdb6 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1504,8 +1504,8 @@ static int dvb_register(struct cx8802_dev *dev) fe0->dvb.frontend = dvb_attach(stv0288_attach, &tevii_tuner_earda_config, &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap)) goto frontend_detach; core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; -- cgit v1.2.3 From cfcd7b825892cb498c6bcb13257f2141f7eacb76 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Jan 2015 10:56:27 -0300 Subject: [media] lmedm04: Increase Interupt due time to 200 msec Ocassionally the device fails to report back an interrupt urb status which results in false no lock trigger on the RS2000 demodulator. Increase time from 60 msecs to 200 msecs. Signed-off-by: Malcolm Priestley Cc: # v3.17+ Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 994de53a574b..f1edb299c2f2 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -344,9 +344,10 @@ static void lme2510_int_response(struct urb *lme_urb) usb_submit_urb(lme_urb, GFP_ATOMIC); - /* interrupt urb is due every 48 msecs while streaming - * add 12msecs for system lag */ - st->int_urb_due = jiffies + msecs_to_jiffies(60); + /* Interrupt urb is due every 48 msecs while streaming the buffer + * stores up to 4 periods if missed. Allow 200 msec for next interrupt. + */ + st->int_urb_due = jiffies + msecs_to_jiffies(200); } static int lme2510_int_read(struct dvb_usb_adapter *adap) -- cgit v1.2.3 From 15e1ce33182d1d5dbd8efe8d382b9352dc857527 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Jan 2015 10:56:28 -0300 Subject: [media] lmedm04: Fix usb_submit_urb BOGUS urb xfer, pipe 1 != type 3 in interrupt urb A quirk of some older firmwares that report endpoint pipe type as PIPE_BULK but the endpoint otheriwse functions as interrupt. Check if usb_endpoint_type is USB_ENDPOINT_XFER_BULK and set as usb_rcvbulkpipe. Signed-off-by: Malcolm Priestley Cc: Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index f1edb299c2f2..15db9f67f4d1 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -354,6 +354,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *lme_int = adap_to_priv(adap); + struct usb_host_endpoint *ep; lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); @@ -375,6 +376,12 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) adap, 8); + /* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */ + ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe); + + if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) + lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa), + lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); -- cgit v1.2.3 From d8bad1e2abdf09def76ff9736443d25ad1ea67eb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Jan 2015 10:56:29 -0300 Subject: [media] lmedm04: create frontend callbacks for signal/snr/ber/ucblocks Create call backs dm04_read_signal_strength, dm04_read_snr and move dm04_read_ber and dm04_read_ucblocks for all frontends Removing the I2C filtering from lme2510_msg and the old rs2000 callbacks. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 93 ++++++++++++---------------------- 1 file changed, 33 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 15db9f67f4d1..55d76904131f 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -515,21 +515,6 @@ static int lme2510_msg(struct dvb_usb_device *d, rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; - case 0x43: - rbuf[0] = 0x55; - rbuf[1] = st->signal_level; - break; - case 0x1c: - rbuf[0] = 0x55; - rbuf[1] = st->signal_sn; - break; - case 0x15: - case 0x16: - case 0x17: - case 0x18: - rbuf[0] = 0x55; - rbuf[1] = 0x00; - break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; @@ -538,25 +523,10 @@ static int lme2510_msg(struct dvb_usb_device *d, break; case TUNER_S7395: switch (wbuf[3]) { - case 0x10: - rbuf[0] = 0x55; - rbuf[1] = (st->signal_level & 0x80) - ? 0 : (st->signal_level * 2); - break; - case 0x2d: - rbuf[0] = 0x55; - rbuf[1] = st->signal_sn; - break; case 0x24: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; - case 0x2e: - case 0x26: - case 0x27: - rbuf[0] = 0x55; - rbuf[1] = 0x00; - break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; @@ -565,26 +535,10 @@ static int lme2510_msg(struct dvb_usb_device *d, break; case TUNER_S0194: switch (wbuf[3]) { - case 0x18: - rbuf[0] = 0x55; - rbuf[1] = (st->signal_level & 0x80) - ? 0 : (st->signal_level * 2); - break; - case 0x24: - rbuf[0] = 0x55; - rbuf[1] = st->signal_sn; - break; case 0x1b: rbuf[0] = 0x55; rbuf[1] = st->signal_lock; break; - case 0x19: - case 0x25: - case 0x1e: - case 0x1d: - rbuf[0] = 0x55; - rbuf[1] = 0x00; - break; default: lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); st->i2c_talk_onoff = 1; @@ -1006,21 +960,44 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, return (ret < 0) ? -ENODEV : 0; } -static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, - u16 *strength) +static int dm04_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct lme2510_state *st = fe_to_priv(fe); - *strength = (u16)((u32)st->signal_level * 0xffff / 0xff); + switch (st->tuner_config) { + case TUNER_LG: + *strength = 0xff - st->signal_level; + *strength |= *strength << 8; + break; + /* fall through */ + case TUNER_S7395: + case TUNER_S0194: + *strength = 0xffff - (((st->signal_level * 2) << 8) * 5 / 4); + break; + case TUNER_RS2000: + *strength = (u16)((u32)st->signal_level * 0xffff / 0xff); + } return 0; } -static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) +static int dm04_read_snr(struct dvb_frontend *fe, u16 *snr) { struct lme2510_state *st = fe_to_priv(fe); - *snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f); + switch (st->tuner_config) { + case TUNER_LG: + *snr = 0xff - st->signal_sn; + *snr |= *snr << 8; + break; + /* fall through */ + case TUNER_S7395: + case TUNER_S0194: + *snr = (u16)((0xff - st->signal_sn - 0xa1) * 3) << 8; + break; + case TUNER_RS2000: + *snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f); + } return 0; } @@ -1127,15 +1104,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) st->tuner_config = TUNER_RS2000; st->fe_set_voltage = adap->fe[0]->ops.set_voltage; - - adap->fe[0]->ops.read_signal_strength = - dm04_rs2000_read_signal_strength; - adap->fe[0]->ops.read_snr = - dm04_rs2000_read_snr; - adap->fe[0]->ops.read_ber = - dm04_read_ber; - adap->fe[0]->ops.read_ucblocks = - dm04_read_ucblocks; } break; } @@ -1154,7 +1122,12 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) return -ENODEV; } + adap->fe[0]->ops.read_signal_strength = dm04_read_signal_strength; + adap->fe[0]->ops.read_snr = dm04_read_snr; + adap->fe[0]->ops.read_ber = dm04_read_ber; + adap->fe[0]->ops.read_ucblocks = dm04_read_ucblocks; adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage; + ret = lme_name(adap); return ret; } -- cgit v1.2.3 From 743ab6a1ccafaa55b8ce00804ce4f9cc2fda8394 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Jan 2015 10:56:30 -0300 Subject: [media] lmedm04: Create frontend call back for read status Create dm04_read_status to check lock through either interrupt values or directly by the call back. When the device is not streaming the frontends original call back is used. When streaming has started it turns off I2C messaging by setting st->i2c_talk_onoff to zero. I2C can only be turn on again by one of the other allowed frontend calls. All old code is removed from lme2510_msg and this function only needs to set st->i2c_talk_onoff to 1. The lock status is saved and when the frondend is locked is maintained by lme2510_int_response who will now just kill the lock. The call back for rs2000 tuner is nologer required. All frontend types have been tested. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 205 ++++++++++----------------------- 1 file changed, 60 insertions(+), 145 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 55d76904131f..a9c7fd0fa086 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -126,9 +126,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct lme2510_state { unsigned long int_urb_due; + fe_status_t lock_status; u8 id; u8 tuner_config; - u8 signal_lock; u8 signal_level; u8 signal_sn; u8 time_key; @@ -143,6 +143,8 @@ struct lme2510_state { void *buffer; struct urb *lme_urb; void *usb_buffer; + /* Frontend original calls */ + int (*fe_read_status)(struct dvb_frontend *, fe_status_t *); int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t); u8 dvb_usb_lme2510_firmware; }; @@ -258,6 +260,7 @@ static void lme2510_int_response(struct urb *lme_urb) static u8 *ibuf, *rbuf; int i = 0, offset; u32 key; + u8 signal_lock = 0; switch (lme_urb->status) { case 0: @@ -298,8 +301,7 @@ static void lme2510_int_response(struct urb *lme_urb) case 0xbb: switch (st->tuner_config) { case TUNER_LG: - if (ibuf[2] > 0) - st->signal_lock = ibuf[2]; + signal_lock = ibuf[2] & BIT(5); st->signal_level = ibuf[4]; st->signal_sn = ibuf[3]; st->time_key = ibuf[7]; @@ -308,29 +310,29 @@ static void lme2510_int_response(struct urb *lme_urb) case TUNER_S0194: /* Tweak for earlier firmware*/ if (ibuf[1] == 0x03) { - if (ibuf[2] > 1) - st->signal_lock = ibuf[2]; + signal_lock = ibuf[2] & BIT(4); st->signal_level = ibuf[3]; st->signal_sn = ibuf[4]; } else { st->signal_level = ibuf[4]; st->signal_sn = ibuf[5]; - st->signal_lock = - (st->signal_lock & 0xf7) + - ((ibuf[2] & 0x01) << 0x03); } break; case TUNER_RS2000: - if (ibuf[2] & 0x1) - st->signal_lock = 0xff; - else - st->signal_lock = 0x00; + signal_lock = ibuf[2] & 0xee; st->signal_level = ibuf[5]; st->signal_sn = ibuf[4]; st->time_key = ibuf[7]; default: break; } + + /* Interrupt will also throw just BIT 0 as lock */ + signal_lock |= ibuf[2] & BIT(0); + + if (!signal_lock) + st->lock_status &= ~FE_HAS_LOCK; + debug_data_snipet(5, "INT Remote data snipet in", ibuf); break; case 0xcc: @@ -457,124 +459,13 @@ static int lme2510_return_status(struct dvb_usb_device *d) static int lme2510_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { - int ret = 0; struct lme2510_state *st = d->priv; - if (st->i2c_talk_onoff == 1) { - - ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); - - switch (st->tuner_config) { - case TUNER_LG: - if (wbuf[2] == 0x1c) { - if (wbuf[3] == 0x0e) { - st->signal_lock = rbuf[1]; - if ((st->stream_on & 1) && - (st->signal_lock & 0x10)) { - lme2510_stream_restart(d); - st->i2c_talk_onoff = 0; - } - msleep(80); - } - } - break; - case TUNER_S7395: - if (wbuf[2] == 0xd0) { - if (wbuf[3] == 0x24) { - st->signal_lock = rbuf[1]; - if ((st->stream_on & 1) && - (st->signal_lock & 0x8)) { - lme2510_stream_restart(d); - st->i2c_talk_onoff = 0; - } - } - } - break; - case TUNER_S0194: - if (wbuf[2] == 0xd0) { - if (wbuf[3] == 0x1b) { - st->signal_lock = rbuf[1]; - if ((st->stream_on & 1) && - (st->signal_lock & 0x8)) { - lme2510_stream_restart(d); - st->i2c_talk_onoff = 0; - } - } - } - break; - case TUNER_RS2000: - default: - break; - } - } else { - /* TODO rewrite this section */ - switch (st->tuner_config) { - case TUNER_LG: - switch (wbuf[3]) { - case 0x0e: - rbuf[0] = 0x55; - rbuf[1] = st->signal_lock; - break; - default: - lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); - st->i2c_talk_onoff = 1; - break; - } - break; - case TUNER_S7395: - switch (wbuf[3]) { - case 0x24: - rbuf[0] = 0x55; - rbuf[1] = st->signal_lock; - break; - default: - lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); - st->i2c_talk_onoff = 1; - break; - } - break; - case TUNER_S0194: - switch (wbuf[3]) { - case 0x1b: - rbuf[0] = 0x55; - rbuf[1] = st->signal_lock; - break; - default: - lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); - st->i2c_talk_onoff = 1; - break; - } - break; - case TUNER_RS2000: - switch (wbuf[3]) { - case 0x8c: - rbuf[0] = 0x55; - rbuf[1] = st->signal_lock; - - /* If int_urb_due overdue - * set rbuf[1] to 0 to clear lock */ - if (time_after(jiffies, st->int_urb_due)) - rbuf[1] = 0; - - break; - default: - lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); - st->i2c_talk_onoff = 1; - break; - } - default: - break; - } - - deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)", - wbuf[3], rbuf[1]); - - } + st->i2c_talk_onoff = 1; - return ret; + return lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); } - static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { @@ -897,26 +788,8 @@ static struct stv0299_config sharp_z0194_config = { .set_symbol_rate = sharp_z0194a_set_symbol_rate, }; -static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, - int caller) -{ - struct dvb_usb_adapter *adap = fe_to_adap(fe); - struct dvb_usb_device *d = adap_to_d(adap); - struct lme2510_state *st = d->priv; - - mutex_lock(&d->i2c_mutex); - if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { - st->i2c_talk_onoff = 0; - lme2510_stream_restart(d); - } - mutex_unlock(&d->i2c_mutex); - - return 0; -} - static struct m88rs2000_config m88rs2000_config = { - .demod_addr = 0x68, - .set_ts_params = dm04_rs2000_set_ts_param, + .demod_addr = 0x68 }; static struct ts2020_config ts2020_config = { @@ -960,6 +833,46 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, return (ret < 0) ? -ENODEV : 0; } +static int dm04_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct dvb_usb_device *d = fe_to_d(fe); + struct lme2510_state *st = d->priv; + int ret = 0; + + if (st->i2c_talk_onoff) { + if (st->fe_read_status) { + ret = st->fe_read_status(fe, status); + if (ret < 0) + return ret; + } + + st->lock_status = *status; + + if (*status & FE_HAS_LOCK && st->stream_on) { + mutex_lock(&d->i2c_mutex); + + st->i2c_talk_onoff = 0; + ret = lme2510_stream_restart(d); + + mutex_unlock(&d->i2c_mutex); + } + + return ret; + } + + /* Timeout of interrupt reached on RS2000 */ + if (st->tuner_config == TUNER_RS2000 && + time_after(jiffies, st->int_urb_due)) + st->lock_status &= ~FE_HAS_LOCK; + + *status = st->lock_status; + + if (!(*status & FE_HAS_LOCK)) + st->i2c_talk_onoff = 1; + + return ret; +} + static int dm04_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct lme2510_state *st = fe_to_priv(fe); @@ -1122,6 +1035,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) return -ENODEV; } + st->fe_read_status = adap->fe[0]->ops.read_status; + + adap->fe[0]->ops.read_status = dm04_read_status; adap->fe[0]->ops.read_signal_strength = dm04_read_signal_strength; adap->fe[0]->ops.read_snr = dm04_read_snr; adap->fe[0]->ops.read_ber = dm04_read_ber; @@ -1269,7 +1185,6 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) if (st->usb_buffer != NULL) { st->i2c_talk_onoff = 1; - st->signal_lock = 0; st->signal_level = 0; st->signal_sn = 0; buffer = st->usb_buffer; -- cgit v1.2.3 From 87169013841d96555edf383e446313de47d813fd Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Fri, 2 Jan 2015 10:56:31 -0300 Subject: [media] lmedm04: add read snr, signal strength and ber call backs This allows calling the original functions providing the streaming is off. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index a9c7fd0fa086..5de6f7c04d09 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -145,6 +145,10 @@ struct lme2510_state { void *usb_buffer; /* Frontend original calls */ int (*fe_read_status)(struct dvb_frontend *, fe_status_t *); + int (*fe_read_signal_strength)(struct dvb_frontend *, u16 *); + int (*fe_read_snr)(struct dvb_frontend *, u16 *); + int (*fe_read_ber)(struct dvb_frontend *, u32 *); + int (*fe_read_ucblocks)(struct dvb_frontend *, u32 *); int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t); u8 dvb_usb_lme2510_firmware; }; @@ -877,6 +881,9 @@ static int dm04_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct lme2510_state *st = fe_to_priv(fe); + if (st->fe_read_signal_strength && !st->stream_on) + return st->fe_read_signal_strength(fe, strength); + switch (st->tuner_config) { case TUNER_LG: *strength = 0xff - st->signal_level; @@ -898,6 +905,9 @@ static int dm04_read_snr(struct dvb_frontend *fe, u16 *snr) { struct lme2510_state *st = fe_to_priv(fe); + if (st->fe_read_snr && !st->stream_on) + return st->fe_read_snr(fe, snr); + switch (st->tuner_config) { case TUNER_LG: *snr = 0xff - st->signal_sn; @@ -917,6 +927,11 @@ static int dm04_read_snr(struct dvb_frontend *fe, u16 *snr) static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber) { + struct lme2510_state *st = fe_to_priv(fe); + + if (st->fe_read_ber && !st->stream_on) + return st->fe_read_ber(fe, ber); + *ber = 0; return 0; @@ -924,6 +939,11 @@ static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber) static int dm04_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { + struct lme2510_state *st = fe_to_priv(fe); + + if (st->fe_read_ucblocks && !st->stream_on) + return st->fe_read_ucblocks(fe, ucblocks); + *ucblocks = 0; return 0; @@ -1036,6 +1056,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) } st->fe_read_status = adap->fe[0]->ops.read_status; + st->fe_read_signal_strength = adap->fe[0]->ops.read_signal_strength; + st->fe_read_snr = adap->fe[0]->ops.read_snr; + st->fe_read_ber = adap->fe[0]->ops.read_ber; + st->fe_read_ucblocks = adap->fe[0]->ops.read_ucblocks; adap->fe[0]->ops.read_status = dm04_read_status; adap->fe[0]->ops.read_signal_strength = dm04_read_signal_strength; -- cgit v1.2.3 From e6010442128a4b7d2ef9444bd224f69096ba0308 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Fri, 26 Dec 2014 07:42:52 -0300 Subject: [media] dvb: tc90522: re-add symbol-rate report symbol-rate report was wrongly removed off by the commit:906aaf5a . Signed-off-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/tc90522.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index b35d65c9cc05..dce22ce35d20 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -214,6 +214,7 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe) state = fe->demodulator_priv; c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBS; + c->symbol_rate = 28860000; layers = 0; ret = reg_read(state, 0xe6, val, 5); -- cgit v1.2.3 From 5ee803a20f4a6569290c1cd20dcb7e795c8dba21 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Fri, 2 Jan 2015 21:50:44 -0300 Subject: [media] mn88472: simplify bandwidth registers setting code Signed-off-by: Benjamin Larsson Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/mn88472/mn88472.c | 41 +++++++++++---------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c index b6b015c2b516..6eebe564e557 100644 --- a/drivers/staging/media/mn88472/mn88472.c +++ b/drivers/staging/media/mn88472/mn88472.c @@ -58,35 +58,22 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) goto err; } - switch (c->delivery_system) { - case SYS_DVBT: - case SYS_DVBT2: - if (c->bandwidth_hz <= 5000000) { - memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7); - bw_val2 = 0x03; - } else if (c->bandwidth_hz <= 6000000) { - /* IF 3570000 Hz, BW 6000000 Hz */ - memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7); - bw_val2 = 0x02; - } else if (c->bandwidth_hz <= 7000000) { - /* IF 4570000 Hz, BW 7000000 Hz */ - memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7); - bw_val2 = 0x01; - } else if (c->bandwidth_hz <= 8000000) { - /* IF 4570000 Hz, BW 8000000 Hz */ - memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7); - bw_val2 = 0x00; - } else { - ret = -EINVAL; - goto err; - } - break; - case SYS_DVBC_ANNEX_A: - /* IF 5070000 Hz, BW 8000000 Hz */ + if (c->bandwidth_hz <= 5000000) { + memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7); + bw_val2 = 0x03; + } else if (c->bandwidth_hz <= 6000000) { + /* IF 3570000 Hz, BW 6000000 Hz */ + memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7); + bw_val2 = 0x02; + } else if (c->bandwidth_hz <= 7000000) { + /* IF 4570000 Hz, BW 7000000 Hz */ + memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7); + bw_val2 = 0x01; + } else if (c->bandwidth_hz <= 8000000) { + /* IF 4570000 Hz, BW 8000000 Hz */ memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7); bw_val2 = 0x00; - break; - default: + } else { ret = -EINVAL; goto err; } -- cgit v1.2.3 From 3656cddd50018d562d2df87c4698783898732914 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 6 Jan 2015 22:53:37 -0300 Subject: [media] lirc_dev: avoid potential null-dereference We have to check pointer for NULL and then dereference it. Signed-off-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 1e0545a67959..4de0e85af805 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -553,14 +553,14 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) if (!ir->attached) return POLLERR; - poll_wait(file, &ir->buf->wait_poll, wait); + if (ir->buf) { + poll_wait(file, &ir->buf->wait_poll, wait); - if (ir->buf) if (lirc_buffer_empty(ir->buf)) ret = 0; else ret = POLLIN | POLLRDNORM; - else + } else ret = POLLERR; dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", -- cgit v1.2.3 From 683e98b6029155949d7373ba854283770b4a16ef Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Fri, 16 Jan 2015 09:35:19 -0300 Subject: [media] si2168: return error if set_frontend is called with invalid parameters This patch should is based on Antti's silabs branch. According to dvb-frontend.h set_frontend may be called with bandwidth_hz set to 0 if automatic bandwidth is required. Si2168 does not support automatic bandwidth and does not declare FE_CAN_BANDWIDTH_AUTO in caps. This patch will change the behaviour in a way that EINVAL is returned if bandwidth_hz is 0. Signed-off-by: Olli Salonen Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 63341f485f9f..5b5fd5db7b2c 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -180,7 +180,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) goto err; } - if (c->bandwidth_hz <= 5000000) + if (c->bandwidth_hz == 0) { + ret = -EINVAL; + goto err; + } else if (c->bandwidth_hz <= 5000000) bandwidth = 0x05; else if (c->bandwidth_hz <= 6000000) bandwidth = 0x06; -- cgit v1.2.3 From 17d4d6ae09f7b556eb13d4f708f810a1ef99733e Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Fri, 16 Jan 2015 09:35:20 -0300 Subject: [media] si2168: add support for 1.7MHz bandwidth This patch is based on Antti's silabs branch. Add support for 1.7 MHz bandwidth. Supported in all versions of Si2168 according to short data sheets. [mchehab@osg.samsung.com: Fix CodingStyle] Signed-off-by: Olli Salonen Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 5b5fd5db7b2c..5db588ebfc24 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -183,7 +183,9 @@ static int si2168_set_frontend(struct dvb_frontend *fe) if (c->bandwidth_hz == 0) { ret = -EINVAL; goto err; - } else if (c->bandwidth_hz <= 5000000) + } else if (c->bandwidth_hz <= 2000000) + bandwidth = 0x02; + else if (c->bandwidth_hz <= 5000000) bandwidth = 0x05; else if (c->bandwidth_hz <= 6000000) bandwidth = 0x06; -- cgit v1.2.3 From 2948c01c2b686f03aa50a3a87323604f7ad39578 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sun, 25 Jan 2015 11:51:35 -0300 Subject: [media] stb0899: use sign_extend32() for sign extension Instead of implement its own logic, use the already-defined one. Signed-off-by: Martin Kepplinger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 93596e0e640b..3012f196e9bd 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "stb0899_drv.h" #include "stb0899_priv.h" #include "stb0899_reg.h" @@ -1490,9 +1491,7 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) /* Store signal parameters */ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - /* sign extend 30 bit value before using it in calculations */ - if (offsetfreq & (1 << 29)) - offsetfreq |= -1 << 30; + offsetfreq = sign_extend32(offsetfreq, 29); offsetfreq = offsetfreq / ((1 << 30) / 1000); offsetfreq *= (internal->master_clk / 1000000); -- cgit v1.2.3 From f3a9d7ef7990ccb543b3441d9964b9ebc9bae046 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Mon, 26 Jan 2015 10:21:09 -0300 Subject: [media] staging: lirc_serial: adjust boolean assignments Adjusts boolean assignments from 0/1 to false/true. And accordingly, it also adjusts the if conditions. Signed-off-by: Heba Aamer Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_serial.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index eb4ccb8d2a93..19628d0104ab 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -107,7 +107,7 @@ static int io; static int irq; static bool iommap; static int ioshift; -static bool softcarrier = 1; +static bool softcarrier = true; static bool share_irq; static bool debug; static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ @@ -266,7 +266,7 @@ static unsigned long space_width; /* fetch serial input packet (1 byte) from register offset */ static u8 sinp(int offset) { - if (iommap != 0) + if (iommap) /* the register is memory-mapped */ offset <<= ioshift; @@ -276,7 +276,7 @@ static u8 sinp(int offset) /* write serial output packet (1 byte) of value to register offset */ static void soutp(int offset, u8 value) { - if (iommap != 0) + if (iommap) /* the register is memory-mapped */ offset <<= ioshift; @@ -799,10 +799,10 @@ static int lirc_serial_probe(struct platform_device *dev) * For memory mapped I/O you *might* need to use ioremap() first, * for the NSLU2 it's done in boot code. */ - if (((iommap != 0) + if (((iommap) && (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift, LIRC_DRIVER_NAME) == NULL)) - || ((iommap == 0) + || ((!iommap) && (devm_request_region(&dev->dev, io, 8, LIRC_DRIVER_NAME) == NULL))) { dev_err(&dev->dev, "port %04x already in use\n", io); -- cgit v1.2.3 From be87b90f8c70bd1f28c5680a4f9f88b4ac3b0503 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 28 Jan 2015 15:05:50 -0300 Subject: [media] dvb_net: Use vsprintf %pM extension to print Ethernet addresses No need for more macros, so remove them and use the kernel extension. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_net.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index e4041f074909..ff79b0b82354 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -90,9 +90,6 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) #ifdef ULE_DEBUG -#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" -#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5] - #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) static void hexdump( const unsigned char *buf, unsigned short len ) @@ -700,8 +697,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (drop) { #ifdef ULE_DEBUG - dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n", - MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr)); + dprintk("Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n", + priv->ule_skb->data, dev->dev_addr); #endif dev_kfree_skb(priv->ule_skb); goto sndu_done; -- cgit v1.2.3 From 5c7c0ca02f01df4345fcf6c0b60281928d3e775e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 28 Jan 2015 15:05:51 -0300 Subject: [media] dvb_net: Use standard debugging facilities Convert dprintk to netdev_dbg where appropriate. Remove dvb_net_debug module_param. Remove __func__ from output as that can be added by dynamic_debug. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_net.c | 57 +++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index ff79b0b82354..0b0f97af65d2 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -68,13 +68,6 @@ #include "dvb_demux.h" #include "dvb_net.h" -static int dvb_net_debug; -module_param(dvb_net_debug, int, 0444); -MODULE_PARM_DESC(dvb_net_debug, "enable debug messages"); - -#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0) - - static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) { unsigned int j; @@ -312,9 +305,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p ) return l; /* Stop extension header processing and discard SNDU. */ total_ext_len += l; #ifdef ULE_DEBUG - dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, " - "l=%i, total_ext_len=%i\n", p->ule_next_hdr, - (int) p->ule_sndu_type, l, total_ext_len); + pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n", + p->ule_next_hdr, (int)p->ule_sndu_type, + l, total_ext_len); #endif } while (p->ule_sndu_type < ETH_P_802_3_MIN); @@ -697,8 +690,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (drop) { #ifdef ULE_DEBUG - dprintk("Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n", - priv->ule_skb->data, dev->dev_addr); + netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n", + priv->ule_skb->data, dev->dev_addr); #endif dev_kfree_skb(priv->ule_skb); goto sndu_done; @@ -961,8 +954,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev, (*secfilter)->filter_mask[10] = mac_mask[1]; (*secfilter)->filter_mask[11]=mac_mask[0]; - dprintk("%s: filter mac=%pM\n", dev->name, mac); - dprintk("%s: filter mask=%pM\n", dev->name, mac_mask); + netdev_dbg(dev, "filter mac=%pM mask=%pM\n", mac, mac_mask); return 0; } @@ -974,7 +966,7 @@ static int dvb_net_feed_start(struct net_device *dev) struct dmx_demux *demux = priv->demux; unsigned char *mac = (unsigned char *) dev->dev_addr; - dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode); + netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode); mutex_lock(&priv->mutex); if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) printk("%s: BUG %d\n", __func__, __LINE__); @@ -984,7 +976,7 @@ static int dvb_net_feed_start(struct net_device *dev) priv->tsfeed = NULL; if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { - dprintk("%s: alloc secfeed\n", __func__); + netdev_dbg(dev, "alloc secfeed\n"); ret=demux->allocate_section_feed(demux, &priv->secfeed, dvb_net_sec_callback); if (ret<0) { @@ -1002,38 +994,38 @@ static int dvb_net_feed_start(struct net_device *dev) } if (priv->rx_mode != RX_MODE_PROMISC) { - dprintk("%s: set secfilter\n", __func__); + netdev_dbg(dev, "set secfilter\n"); dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal); } switch (priv->rx_mode) { case RX_MODE_MULTI: for (i = 0; i < priv->multi_num; i++) { - dprintk("%s: set multi_secfilter[%d]\n", __func__, i); + netdev_dbg(dev, "set multi_secfilter[%d]\n", i); dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i], priv->multi_macs[i], mask_normal); } break; case RX_MODE_ALL_MULTI: priv->multi_num=1; - dprintk("%s: set multi_secfilter[0]\n", __func__); + netdev_dbg(dev, "set multi_secfilter[0]\n"); dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti); break; case RX_MODE_PROMISC: priv->multi_num=0; - dprintk("%s: set secfilter\n", __func__); + netdev_dbg(dev, "set secfilter\n"); dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc); break; } - dprintk("%s: start filtering\n", __func__); + netdev_dbg(dev, "start filtering\n"); priv->secfeed->start_filtering(priv->secfeed); } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { struct timespec timeout = { 0, 10000000 }; // 10 msec /* we have payloads encapsulated in TS */ - dprintk("%s: alloc tsfeed\n", __func__); + netdev_dbg(dev, "alloc tsfeed\n"); ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback); if (ret < 0) { printk("%s: could not allocate ts feed\n", dev->name); @@ -1057,7 +1049,7 @@ static int dvb_net_feed_start(struct net_device *dev) goto error; } - dprintk("%s: start filtering\n", __func__); + netdev_dbg(dev, "start filtering\n"); priv->tsfeed->start_filtering(priv->tsfeed); } else ret = -EINVAL; @@ -1072,17 +1064,16 @@ static int dvb_net_feed_stop(struct net_device *dev) struct dvb_net_priv *priv = netdev_priv(dev); int i, ret = 0; - dprintk("%s\n", __func__); mutex_lock(&priv->mutex); if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { if (priv->secfeed) { if (priv->secfeed->is_filtering) { - dprintk("%s: stop secfeed\n", __func__); + netdev_dbg(dev, "stop secfeed\n"); priv->secfeed->stop_filtering(priv->secfeed); } if (priv->secfilter) { - dprintk("%s: release secfilter\n", __func__); + netdev_dbg(dev, "release secfilter\n"); priv->secfeed->release_filter(priv->secfeed, priv->secfilter); priv->secfilter=NULL; @@ -1090,8 +1081,8 @@ static int dvb_net_feed_stop(struct net_device *dev) for (i=0; imulti_num; i++) { if (priv->multi_secfilter[i]) { - dprintk("%s: release multi_filter[%d]\n", - __func__, i); + netdev_dbg(dev, "release multi_filter[%d]\n", + i); priv->secfeed->release_filter(priv->secfeed, priv->multi_secfilter[i]); priv->multi_secfilter[i] = NULL; @@ -1105,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev) } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { if (priv->tsfeed) { if (priv->tsfeed->is_filtering) { - dprintk("%s: stop tsfeed\n", __func__); + netdev_dbg(dev, "stop tsfeed\n"); priv->tsfeed->stop_filtering(priv->tsfeed); } priv->demux->release_ts_feed(priv->demux, priv->tsfeed); @@ -1145,16 +1136,16 @@ static void wq_set_multicast_list (struct work_struct *work) netif_addr_lock_bh(dev); if (dev->flags & IFF_PROMISC) { - dprintk("%s: promiscuous mode\n", dev->name); + netdev_dbg(dev, "promiscuous mode\n"); priv->rx_mode = RX_MODE_PROMISC; } else if ((dev->flags & IFF_ALLMULTI)) { - dprintk("%s: allmulti mode\n", dev->name); + netdev_dbg(dev, "allmulti mode\n"); priv->rx_mode = RX_MODE_ALL_MULTI; } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; - dprintk("%s: set_mc_list, %d entries\n", - dev->name, netdev_mc_count(dev)); + netdev_dbg(dev, "set_mc_list, %d entries\n", + netdev_mc_count(dev)); priv->rx_mode = RX_MODE_MULTI; priv->multi_num = 0; -- cgit v1.2.3 From 4bad5d2d25099a42e146d7b18d2b98950ed287f5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 28 Jan 2015 15:05:52 -0300 Subject: [media] dvb_net: Convert local hex dump to print_hex_dump_debug Use the generic facility instead of a home-grown one. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_net.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 0b0f97af65d2..686d3277dad1 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -83,33 +83,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) #ifdef ULE_DEBUG -#define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) - -static void hexdump( const unsigned char *buf, unsigned short len ) +static void hexdump(const unsigned char *buf, unsigned short len) { - char str[80], octet[10]; - int ofs, i, l; - - for (ofs = 0; ofs < len; ofs += 16) { - sprintf( str, "%03d: ", ofs ); - - for (i = 0; i < 16; i++) { - if ((i + ofs) < len) - sprintf( octet, "%02x ", buf[ofs + i] ); - else - strcpy( octet, " " ); - - strcat( str, octet ); - } - strcat( str, " " ); - l = strlen( str ); - - for (i = 0; (i < 16) && ((i + ofs) < len); i++) - str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.'; - - str[l] = '\0'; - printk( KERN_WARNING "%s\n", str ); - } + print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true); } #endif -- cgit v1.2.3