diff options
author | Antti Palosaari <crope@iki.fi> | 2013-08-05 19:43:36 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-08-20 15:06:33 -0400 |
commit | 554cbfbe3b99d25caa3ab794a8619ccdea2b2935 (patch) | |
tree | b0debca878b71cbc91e8f1f87ed601003a06f1ee /drivers/staging | |
parent | 23df427e3333882beea2e65d27fd2a581e37fae4 (diff) |
[media] msi3101: add support for stream format "252" I+Q per frame
That one seems to have 14-bit ADC resolution, wow!
It is now used when sampling rate is below 6 Msps.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/media/msi3101/sdr-msi3101.c | 139 |
1 files changed, 125 insertions, 14 deletions
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c index 4ff6030bc950..a937d00ed153 100644 --- a/drivers/staging/media/msi3101/sdr-msi3101.c +++ b/drivers/staging/media/msi3101/sdr-msi3101.c | |||
@@ -397,6 +397,8 @@ struct msi3101_state { | |||
397 | unsigned int vb_full; /* vb is full and packets dropped */ | 397 | unsigned int vb_full; /* vb is full and packets dropped */ |
398 | 398 | ||
399 | struct urb *urbs[MAX_ISO_BUFS]; | 399 | struct urb *urbs[MAX_ISO_BUFS]; |
400 | int (*convert_stream) (struct msi3101_state *s, u32 *dst, u8 *src, | ||
401 | unsigned int src_len); | ||
400 | 402 | ||
401 | /* Controls */ | 403 | /* Controls */ |
402 | struct v4l2_ctrl_handler ctrl_handler; | 404 | struct v4l2_ctrl_handler ctrl_handler; |
@@ -484,7 +486,7 @@ leave: | |||
484 | */ | 486 | */ |
485 | #define I2F_FRAC_BITS 23 | 487 | #define I2F_FRAC_BITS 23 |
486 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) | 488 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) |
487 | static u32 msi3101_convert_sample(struct msi3101_state *s, u16 x, int shift) | 489 | static u32 msi3101_convert_sample_384(struct msi3101_state *s, u16 x, int shift) |
488 | { | 490 | { |
489 | u32 msb, exponent, fraction, sign; | 491 | u32 msb, exponent, fraction, sign; |
490 | s->sample_ctrl_bit[shift]++; | 492 | s->sample_ctrl_bit[shift]++; |
@@ -521,7 +523,7 @@ static u32 msi3101_convert_sample(struct msi3101_state *s, u16 x, int shift) | |||
521 | 523 | ||
522 | #define MSI3101_CONVERT_IN_URB_HANDLER | 524 | #define MSI3101_CONVERT_IN_URB_HANDLER |
523 | #define MSI3101_EXTENSIVE_DEBUG | 525 | #define MSI3101_EXTENSIVE_DEBUG |
524 | static int msi3101_convert_stream(struct msi3101_state *s, u32 *dst, | 526 | static int msi3101_convert_stream_384(struct msi3101_state *s, u32 *dst, |
525 | u8 *src, unsigned int src_len) | 527 | u8 *src, unsigned int src_len) |
526 | { | 528 | { |
527 | int i, j, k, l, i_max, dst_len = 0; | 529 | int i, j, k, l, i_max, dst_len = 0; |
@@ -561,10 +563,10 @@ static int msi3101_convert_stream(struct msi3101_state *s, u32 *dst, | |||
561 | sample[2] = (src[l + 2] & 0xf0) >> 4 | (src[l + 3] & 0x3f) << 4; | 563 | sample[2] = (src[l + 2] & 0xf0) >> 4 | (src[l + 3] & 0x3f) << 4; |
562 | sample[3] = (src[l + 3] & 0xc0) >> 6 | (src[l + 4] & 0xff) << 2; | 564 | sample[3] = (src[l + 3] & 0xc0) >> 6 | (src[l + 4] & 0xff) << 2; |
563 | 565 | ||
564 | *dst++ = msi3101_convert_sample(s, sample[0], (bits >> (2 * k)) & 0x3); | 566 | *dst++ = msi3101_convert_sample_384(s, sample[0], (bits >> (2 * k)) & 0x3); |
565 | *dst++ = msi3101_convert_sample(s, sample[1], (bits >> (2 * k)) & 0x3); | 567 | *dst++ = msi3101_convert_sample_384(s, sample[1], (bits >> (2 * k)) & 0x3); |
566 | *dst++ = msi3101_convert_sample(s, sample[2], (bits >> (2 * k)) & 0x3); | 568 | *dst++ = msi3101_convert_sample_384(s, sample[2], (bits >> (2 * k)) & 0x3); |
567 | *dst++ = msi3101_convert_sample(s, sample[3], (bits >> (2 * k)) & 0x3); | 569 | *dst++ = msi3101_convert_sample_384(s, sample[3], (bits >> (2 * k)) & 0x3); |
568 | 570 | ||
569 | /* 4 x 32bit float samples */ | 571 | /* 4 x 32bit float samples */ |
570 | dst_len += 4 * 4; | 572 | dst_len += 4 * 4; |
@@ -603,6 +605,103 @@ static int msi3101_convert_stream(struct msi3101_state *s, u32 *dst, | |||
603 | } | 605 | } |
604 | 606 | ||
605 | /* | 607 | /* |
608 | * Converts signed 14-bit integer into 32-bit IEEE floating point | ||
609 | * representation. | ||
610 | * Will be exact from 0 to 2^24. Above that, we round towards zero | ||
611 | * as the fractional bits will not fit in a float. (It would be better to | ||
612 | * round towards even as the fpu does, but that is slower.) | ||
613 | */ | ||
614 | #define I2F_FRAC_BITS 23 | ||
615 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) | ||
616 | static u32 msi3101_convert_sample_252(struct msi3101_state *s, u16 x) | ||
617 | { | ||
618 | u32 msb, exponent, fraction, sign; | ||
619 | |||
620 | /* Zero is special */ | ||
621 | if (!x) | ||
622 | return 0; | ||
623 | |||
624 | /* Negative / positive value */ | ||
625 | if (x & (1 << 13)) { | ||
626 | x = -x; | ||
627 | x &= 0x1fff; /* result is 13 bit ... + sign */ | ||
628 | sign = 1 << 31; | ||
629 | } else { | ||
630 | sign = 0 << 31; | ||
631 | } | ||
632 | |||
633 | /* Get location of the most significant bit */ | ||
634 | msb = __fls(x); | ||
635 | |||
636 | /* | ||
637 | * Use a rotate instead of a shift because that works both leftwards | ||
638 | * and rightwards due to the mod(32) behaviour. This means we don't | ||
639 | * need to check to see if we are above 2^24 or not. | ||
640 | */ | ||
641 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; | ||
642 | exponent = (127 + msb) << I2F_FRAC_BITS; | ||
643 | |||
644 | return (fraction + exponent) | sign; | ||
645 | } | ||
646 | |||
647 | static int msi3101_convert_stream_252(struct msi3101_state *s, u32 *dst, | ||
648 | u8 *src, unsigned int src_len) | ||
649 | { | ||
650 | int i, j, i_max, dst_len = 0; | ||
651 | u16 sample[2]; | ||
652 | u32 sample_num[3]; | ||
653 | |||
654 | /* There could be 1-3 1024 bytes URB frames */ | ||
655 | i_max = src_len / 1024; | ||
656 | |||
657 | for (i = 0; i < i_max; i++) { | ||
658 | sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; | ||
659 | if (i == 0 && s->next_sample != sample_num[0]) { | ||
660 | dev_dbg_ratelimited(&s->udev->dev, | ||
661 | "%d samples lost, %d %08x:%08x\n", | ||
662 | sample_num[0] - s->next_sample, | ||
663 | src_len, s->next_sample, sample_num[0]); | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * Dump all unknown 'garbage' data - maybe we will discover | ||
668 | * someday if there is something rational... | ||
669 | */ | ||
670 | dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); | ||
671 | |||
672 | src += 16; | ||
673 | for (j = 0; j < 1008; j += 4) { | ||
674 | sample[0] = src[j + 0] >> 0 | src[j + 1] << 8; | ||
675 | sample[1] = src[j + 2] >> 0 | src[j + 3] << 8; | ||
676 | |||
677 | *dst++ = msi3101_convert_sample_252(s, sample[0]); | ||
678 | *dst++ = msi3101_convert_sample_252(s, sample[1]); | ||
679 | } | ||
680 | /* 252 x I+Q 32bit float samples */ | ||
681 | dst_len += 252 * 2 * 4; | ||
682 | src += 1008; | ||
683 | } | ||
684 | |||
685 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
686 | if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) { | ||
687 | unsigned long jiffies_now = jiffies; | ||
688 | unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies); | ||
689 | unsigned int samples = sample_num[i_max - 1] - s->sample; | ||
690 | s->jiffies = jiffies_now; | ||
691 | s->sample = sample_num[i_max - 1]; | ||
692 | dev_dbg(&s->udev->dev, | ||
693 | "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", | ||
694 | src_len, samples, msecs, | ||
695 | samples * 1000UL / msecs); | ||
696 | } | ||
697 | |||
698 | /* next sample (sample = sample + i * 252) */ | ||
699 | s->next_sample = sample_num[i_max - 1] + 252; | ||
700 | |||
701 | return dst_len; | ||
702 | } | ||
703 | |||
704 | /* | ||
606 | * This gets called for the Isochronous pipe (stream). This is done in interrupt | 705 | * This gets called for the Isochronous pipe (stream). This is done in interrupt |
607 | * time, so it has to be fast, not crash, and not stall. Neat. | 706 | * time, so it has to be fast, not crash, and not stall. Neat. |
608 | */ | 707 | */ |
@@ -636,6 +735,8 @@ static void msi3101_isoc_handler(struct urb *urb) | |||
636 | 735 | ||
637 | /* Compact data */ | 736 | /* Compact data */ |
638 | for (i = 0; i < urb->number_of_packets; i++) { | 737 | for (i = 0; i < urb->number_of_packets; i++) { |
738 | void *ptr; | ||
739 | |||
639 | /* Check frame error */ | 740 | /* Check frame error */ |
640 | fstatus = urb->iso_frame_desc[i].status; | 741 | fstatus = urb->iso_frame_desc[i].status; |
641 | if (fstatus) { | 742 | if (fstatus) { |
@@ -664,9 +765,9 @@ static void msi3101_isoc_handler(struct urb *urb) | |||
664 | 765 | ||
665 | /* fill framebuffer */ | 766 | /* fill framebuffer */ |
666 | #ifdef MSI3101_CONVERT_IN_URB_HANDLER | 767 | #ifdef MSI3101_CONVERT_IN_URB_HANDLER |
667 | vb2_set_plane_payload(&fbuf->vb, 0, | 768 | ptr = vb2_plane_vaddr(&fbuf->vb, 0); |
668 | msi3101_convert_stream(s, | 769 | flen = s->convert_stream(s, ptr, iso_buf, flen); |
669 | vb2_plane_vaddr(&fbuf->vb, 0), iso_buf, flen)); | 770 | vb2_set_plane_payload(&fbuf->vb, 0, flen); |
670 | #else | 771 | #else |
671 | memcpy(fbuf->data, iso_buf, flen); | 772 | memcpy(fbuf->data, iso_buf, flen); |
672 | fbuf->filled = flen; | 773 | fbuf->filled = flen; |
@@ -908,7 +1009,7 @@ static int msi3101_buf_finish(struct vb2_buffer *vb) | |||
908 | container_of(vb, struct msi3101_frame_buf, vb); | 1009 | container_of(vb, struct msi3101_frame_buf, vb); |
909 | int ret; | 1010 | int ret; |
910 | u32 *dst = vb2_plane_vaddr(&fbuf->vb, 0); | 1011 | u32 *dst = vb2_plane_vaddr(&fbuf->vb, 0); |
911 | ret = msi3101_convert_stream(s, dst, fbuf->data, fbuf->filled); | 1012 | ret = msi3101_convert_stream_384(s, dst, fbuf->data, fbuf->filled); |
912 | vb2_set_plane_payload(&fbuf->vb, 0, ret); | 1013 | vb2_set_plane_payload(&fbuf->vb, 0, ret); |
913 | return 0; | 1014 | return 0; |
914 | } | 1015 | } |
@@ -988,7 +1089,19 @@ static int msi3101_tuner_write(struct msi3101_state *s, u32 data) | |||
988 | static int msi3101_set_usb_adc(struct msi3101_state *s) | 1089 | static int msi3101_set_usb_adc(struct msi3101_state *s) |
989 | { | 1090 | { |
990 | int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract; | 1091 | int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract; |
991 | u32 reg4, reg3; | 1092 | u32 reg3, reg4, reg7; |
1093 | |||
1094 | f_sr = s->ctrl_sampling_rate->val64; | ||
1095 | |||
1096 | /* select stream format */ | ||
1097 | if (f_sr < 6000000) { | ||
1098 | s->convert_stream = msi3101_convert_stream_252; | ||
1099 | reg7 = 0x00009407; | ||
1100 | } else { | ||
1101 | s->convert_stream = msi3101_convert_stream_384; | ||
1102 | reg7 = 0x0000a507; | ||
1103 | } | ||
1104 | |||
992 | /* | 1105 | /* |
993 | * Synthesizer config is just a educated guess... | 1106 | * Synthesizer config is just a educated guess... |
994 | * | 1107 | * |
@@ -1016,8 +1129,6 @@ static int msi3101_set_usb_adc(struct msi3101_state *s) | |||
1016 | * | 1129 | * |
1017 | * VCO 202000000 - 720000000++ | 1130 | * VCO 202000000 - 720000000++ |
1018 | */ | 1131 | */ |
1019 | |||
1020 | f_sr = s->ctrl_sampling_rate->val64; | ||
1021 | reg3 = 0x01c00303; | 1132 | reg3 = 0x01c00303; |
1022 | reg4 = 0x00000004; | 1133 | reg4 = 0x00000004; |
1023 | 1134 | ||
@@ -1062,7 +1173,7 @@ static int msi3101_set_usb_adc(struct msi3101_state *s) | |||
1062 | if (ret) | 1173 | if (ret) |
1063 | goto err; | 1174 | goto err; |
1064 | 1175 | ||
1065 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x0000a507); | 1176 | ret = msi3101_ctrl_msg(s, CMD_WREG, reg7); |
1066 | if (ret) | 1177 | if (ret) |
1067 | goto err; | 1178 | goto err; |
1068 | 1179 | ||