aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/coda
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2015-07-16 12:13:24 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-07-17 10:26:43 -0400
commitcde29ef313de391ec9a1e461458274623ab1eb87 (patch)
tree59b9ffdf4d4520d66711b269e746154d5f00593e /drivers/media/platform/coda
parentda2b3b3e115d2793b5475039ca4d7f364135fcf4 (diff)
[media] coda: Use S_PARM to set nominal framerate for h.264 encoder
The encoder needs to know the nominal framerate for the constant bitrate control mechanism to work. Currently the only way to set the framerate is by using VIDIOC_S_PARM on the output queue. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/platform/coda')
-rw-r--r--drivers/media/platform/coda/coda-common.c102
-rw-r--r--drivers/media/platform/coda/coda_regs.h4
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 24737f1a1a1b..a7cab14d10c9 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -15,6 +15,7 @@
15#include <linux/debugfs.h> 15#include <linux/debugfs.h>
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/firmware.h> 17#include <linux/firmware.h>
18#include <linux/gcd.h>
18#include <linux/genalloc.h> 19#include <linux/genalloc.h>
19#include <linux/interrupt.h> 20#include <linux/interrupt.h>
20#include <linux/io.h> 21#include <linux/io.h>
@@ -770,6 +771,104 @@ static int coda_decoder_cmd(struct file *file, void *fh,
770 return 0; 771 return 0;
771} 772}
772 773
774static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
775{
776 struct coda_ctx *ctx = fh_to_ctx(fh);
777 struct v4l2_fract *tpf;
778
779 if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
780 return -EINVAL;
781
782 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
783 tpf = &a->parm.output.timeperframe;
784 tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK;
785 tpf->numerator = 1 + (ctx->params.framerate >>
786 CODA_FRATE_DIV_OFFSET);
787
788 return 0;
789}
790
791/*
792 * Approximate timeperframe v4l2_fract with values that can be written
793 * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields.
794 */
795static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe)
796{
797 struct v4l2_fract s = *timeperframe;
798 struct v4l2_fract f0;
799 struct v4l2_fract f1 = { 1, 0 };
800 struct v4l2_fract f2 = { 0, 1 };
801 unsigned int i, div, s_denominator;
802
803 /* Lower bound is 1/65535 */
804 if (s.numerator == 0 || s.denominator / s.numerator > 65535) {
805 timeperframe->numerator = 1;
806 timeperframe->denominator = 65535;
807 return;
808 }
809
810 /* Upper bound is 65536/1, map everything above to infinity */
811 if (s.denominator == 0 || s.numerator / s.denominator > 65536) {
812 timeperframe->numerator = 1;
813 timeperframe->denominator = 0;
814 return;
815 }
816
817 /* Reduce fraction to lowest terms */
818 div = gcd(s.numerator, s.denominator);
819 if (div > 1) {
820 s.numerator /= div;
821 s.denominator /= div;
822 }
823
824 if (s.numerator <= 65536 && s.denominator < 65536) {
825 *timeperframe = s;
826 return;
827 }
828
829 /* Find successive convergents from continued fraction expansion */
830 while (f2.numerator <= 65536 && f2.denominator < 65536) {
831 f0 = f1;
832 f1 = f2;
833
834 /* Stop when f2 exactly equals timeperframe */
835 if (s.numerator == 0)
836 break;
837
838 i = s.denominator / s.numerator;
839
840 f2.numerator = f0.numerator + i * f1.numerator;
841 f2.denominator = f0.denominator + i * f2.denominator;
842
843 s_denominator = s.numerator;
844 s.numerator = s.denominator % s.numerator;
845 s.denominator = s_denominator;
846 }
847
848 *timeperframe = f1;
849}
850
851static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe)
852{
853 return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) |
854 timeperframe->denominator;
855}
856
857static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
858{
859 struct coda_ctx *ctx = fh_to_ctx(fh);
860 struct v4l2_fract *tpf;
861
862 if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
863 return -EINVAL;
864
865 tpf = &a->parm.output.timeperframe;
866 coda_approximate_timeperframe(tpf);
867 ctx->params.framerate = coda_timeperframe_to_frate(tpf);
868
869 return 0;
870}
871
773static int coda_subscribe_event(struct v4l2_fh *fh, 872static int coda_subscribe_event(struct v4l2_fh *fh,
774 const struct v4l2_event_subscription *sub) 873 const struct v4l2_event_subscription *sub)
775{ 874{
@@ -810,6 +909,9 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
810 .vidioc_try_decoder_cmd = coda_try_decoder_cmd, 909 .vidioc_try_decoder_cmd = coda_try_decoder_cmd,
811 .vidioc_decoder_cmd = coda_decoder_cmd, 910 .vidioc_decoder_cmd = coda_decoder_cmd,
812 911
912 .vidioc_g_parm = coda_g_parm,
913 .vidioc_s_parm = coda_s_parm,
914
813 .vidioc_subscribe_event = coda_subscribe_event, 915 .vidioc_subscribe_event = coda_subscribe_event,
814 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 916 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
815}; 917};
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 7d026241171b..00e4f5160c1f 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -263,6 +263,10 @@
263#define CODADX6_PICHEIGHT_MASK 0x3ff 263#define CODADX6_PICHEIGHT_MASK 0x3ff
264#define CODA7_PICHEIGHT_MASK 0xffff 264#define CODA7_PICHEIGHT_MASK 0xffff
265#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 265#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194
266#define CODA_FRATE_RES_OFFSET 0
267#define CODA_FRATE_RES_MASK 0xffff
268#define CODA_FRATE_DIV_OFFSET 16
269#define CODA_FRATE_DIV_MASK 0xffff
266#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 270#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198
267#define CODA_MP4PARAM_VERID_OFFSET 6 271#define CODA_MP4PARAM_VERID_OFFSET 6
268#define CODA_MP4PARAM_VERID_MASK 0x01 272#define CODA_MP4PARAM_VERID_MASK 0x01