1*1802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27955f03dSHans Verkuil /*
37955f03dSHans Verkuil * Copyright (C) 2005-2006 Micronas USA Inc.
47955f03dSHans Verkuil */
57955f03dSHans Verkuil
67955f03dSHans Verkuil /*
77955f03dSHans Verkuil * This file contains code to generate a firmware image for the GO7007SB
87955f03dSHans Verkuil * encoder. Much of the firmware is read verbatim from a file, but some of
97955f03dSHans Verkuil * it concerning bitrate control and other things that can be configured at
107955f03dSHans Verkuil * run-time are generated dynamically. Note that the format headers
117955f03dSHans Verkuil * generated here do not affect the functioning of the encoder; they are
127955f03dSHans Verkuil * merely parroted back to the host at the start of each frame.
137955f03dSHans Verkuil */
147955f03dSHans Verkuil
157955f03dSHans Verkuil #include <linux/module.h>
167955f03dSHans Verkuil #include <linux/time.h>
177955f03dSHans Verkuil #include <linux/mm.h>
187955f03dSHans Verkuil #include <linux/device.h>
197955f03dSHans Verkuil #include <linux/i2c.h>
207955f03dSHans Verkuil #include <linux/firmware.h>
217955f03dSHans Verkuil #include <linux/slab.h>
227955f03dSHans Verkuil #include <asm/byteorder.h>
237955f03dSHans Verkuil
247955f03dSHans Verkuil #include "go7007-priv.h"
257955f03dSHans Verkuil
267955f03dSHans Verkuil #define GO7007_FW_NAME "go7007/go7007tv.bin"
277955f03dSHans Verkuil
287955f03dSHans Verkuil /* Constants used in the source firmware image to describe code segments */
297955f03dSHans Verkuil
307955f03dSHans Verkuil #define FLAG_MODE_MJPEG (1)
317955f03dSHans Verkuil #define FLAG_MODE_MPEG1 (1<<1)
327955f03dSHans Verkuil #define FLAG_MODE_MPEG2 (1<<2)
337955f03dSHans Verkuil #define FLAG_MODE_MPEG4 (1<<3)
347955f03dSHans Verkuil #define FLAG_MODE_H263 (1<<4)
357955f03dSHans Verkuil #define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \
367955f03dSHans Verkuil FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \
377955f03dSHans Verkuil FLAG_MODE_H263)
387955f03dSHans Verkuil #define FLAG_SPECIAL (1<<8)
397955f03dSHans Verkuil
407955f03dSHans Verkuil #define SPECIAL_FRM_HEAD 0
417955f03dSHans Verkuil #define SPECIAL_BRC_CTRL 1
427955f03dSHans Verkuil #define SPECIAL_CONFIG 2
437955f03dSHans Verkuil #define SPECIAL_SEQHEAD 3
447955f03dSHans Verkuil #define SPECIAL_AV_SYNC 4
457955f03dSHans Verkuil #define SPECIAL_FINAL 5
467955f03dSHans Verkuil #define SPECIAL_AUDIO 6
477955f03dSHans Verkuil #define SPECIAL_MODET 7
487955f03dSHans Verkuil
497955f03dSHans Verkuil /* Little data class for creating MPEG headers bit-by-bit */
507955f03dSHans Verkuil
517955f03dSHans Verkuil struct code_gen {
527955f03dSHans Verkuil unsigned char *p; /* destination */
537955f03dSHans Verkuil u32 a; /* collects bits at the top of the variable */
547955f03dSHans Verkuil int b; /* bit position of most recently-written bit */
557955f03dSHans Verkuil int len; /* written out so far */
567955f03dSHans Verkuil };
577955f03dSHans Verkuil
587955f03dSHans Verkuil #define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 }
597955f03dSHans Verkuil
607955f03dSHans Verkuil #define CODE_ADD(name, val, length) do { \
617955f03dSHans Verkuil name.b -= (length); \
627955f03dSHans Verkuil name.a |= (val) << name.b; \
637955f03dSHans Verkuil while (name.b <= 24) { \
647955f03dSHans Verkuil *name.p = name.a >> 24; \
657955f03dSHans Verkuil ++name.p; \
667955f03dSHans Verkuil name.a <<= 8; \
677955f03dSHans Verkuil name.b += 8; \
687955f03dSHans Verkuil name.len += 8; \
697955f03dSHans Verkuil } \
707955f03dSHans Verkuil } while (0)
717955f03dSHans Verkuil
727955f03dSHans Verkuil #define CODE_LENGTH(name) (name.len + (32 - name.b))
737955f03dSHans Verkuil
747955f03dSHans Verkuil /* Tables for creating the bitrate control data */
757955f03dSHans Verkuil
767955f03dSHans Verkuil static const s16 converge_speed_ip[101] = {
777955f03dSHans Verkuil 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
787955f03dSHans Verkuil 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
797955f03dSHans Verkuil 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
807955f03dSHans Verkuil 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
817955f03dSHans Verkuil 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
827955f03dSHans Verkuil 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
837955f03dSHans Verkuil 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
847955f03dSHans Verkuil 9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
857955f03dSHans Verkuil 19, 20, 22, 23, 25, 27, 30, 32, 35, 38,
867955f03dSHans Verkuil 41, 45, 49, 53, 58, 63, 69, 76, 83, 91,
877955f03dSHans Verkuil 100
887955f03dSHans Verkuil };
897955f03dSHans Verkuil
907955f03dSHans Verkuil static const s16 converge_speed_ipb[101] = {
917955f03dSHans Verkuil 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
927955f03dSHans Verkuil 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
937955f03dSHans Verkuil 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
947955f03dSHans Verkuil 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
957955f03dSHans Verkuil 6, 6, 6, 7, 7, 7, 7, 8, 8, 9,
967955f03dSHans Verkuil 9, 9, 10, 10, 11, 12, 12, 13, 14, 14,
977955f03dSHans Verkuil 15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
987955f03dSHans Verkuil 28, 30, 32, 34, 37, 40, 42, 46, 49, 53,
997955f03dSHans Verkuil 57, 61, 66, 71, 77, 83, 90, 97, 106, 115,
1007955f03dSHans Verkuil 125, 135, 147, 161, 175, 191, 209, 228, 249, 273,
1017955f03dSHans Verkuil 300
1027955f03dSHans Verkuil };
1037955f03dSHans Verkuil
1047955f03dSHans Verkuil static const s16 LAMBDA_table[4][101] = {
1057955f03dSHans Verkuil { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
1067955f03dSHans Verkuil 19, 19, 19, 20, 20, 20, 21, 21, 22, 22,
1077955f03dSHans Verkuil 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
1087955f03dSHans Verkuil 27, 27, 28, 28, 29, 29, 30, 31, 31, 32,
1097955f03dSHans Verkuil 32, 33, 33, 34, 35, 35, 36, 37, 37, 38,
1107955f03dSHans Verkuil 39, 39, 40, 41, 42, 42, 43, 44, 45, 46,
1117955f03dSHans Verkuil 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
1127955f03dSHans Verkuil 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
1137955f03dSHans Verkuil 67, 68, 69, 70, 72, 73, 74, 76, 77, 78,
1147955f03dSHans Verkuil 80, 81, 83, 84, 86, 87, 89, 90, 92, 94,
1157955f03dSHans Verkuil 96
1167955f03dSHans Verkuil },
1177955f03dSHans Verkuil {
1187955f03dSHans Verkuil 20, 20, 20, 21, 21, 21, 22, 22, 23, 23,
1197955f03dSHans Verkuil 23, 24, 24, 25, 25, 26, 26, 27, 27, 28,
1207955f03dSHans Verkuil 28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
1217955f03dSHans Verkuil 34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
1227955f03dSHans Verkuil 40, 41, 42, 43, 43, 44, 45, 46, 47, 48,
1237955f03dSHans Verkuil 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
1247955f03dSHans Verkuil 58, 59, 60, 61, 62, 64, 65, 66, 67, 68,
1257955f03dSHans Verkuil 70, 71, 72, 73, 75, 76, 78, 79, 80, 82,
1267955f03dSHans Verkuil 83, 85, 86, 88, 90, 91, 93, 95, 96, 98,
1277955f03dSHans Verkuil 100, 102, 103, 105, 107, 109, 111, 113, 115, 117,
1287955f03dSHans Verkuil 120
1297955f03dSHans Verkuil },
1307955f03dSHans Verkuil {
1317955f03dSHans Verkuil 24, 24, 24, 25, 25, 26, 26, 27, 27, 28,
1327955f03dSHans Verkuil 28, 29, 29, 30, 30, 31, 31, 32, 33, 33,
1337955f03dSHans Verkuil 34, 34, 35, 36, 36, 37, 38, 38, 39, 40,
1347955f03dSHans Verkuil 41, 41, 42, 43, 44, 44, 45, 46, 47, 48,
1357955f03dSHans Verkuil 49, 50, 50, 51, 52, 53, 54, 55, 56, 57,
1367955f03dSHans Verkuil 58, 59, 60, 62, 63, 64, 65, 66, 67, 69,
1377955f03dSHans Verkuil 70, 71, 72, 74, 75, 76, 78, 79, 81, 82,
1387955f03dSHans Verkuil 84, 85, 87, 88, 90, 92, 93, 95, 97, 98,
1397955f03dSHans Verkuil 100, 102, 104, 106, 108, 110, 112, 114, 116, 118,
1407955f03dSHans Verkuil 120, 122, 124, 127, 129, 131, 134, 136, 138, 141,
1417955f03dSHans Verkuil 144
1427955f03dSHans Verkuil },
1437955f03dSHans Verkuil {
1447955f03dSHans Verkuil 32, 32, 33, 33, 34, 34, 35, 36, 36, 37,
1457955f03dSHans Verkuil 38, 38, 39, 40, 41, 41, 42, 43, 44, 44,
1467955f03dSHans Verkuil 45, 46, 47, 48, 49, 50, 50, 51, 52, 53,
1477955f03dSHans Verkuil 54, 55, 56, 57, 58, 59, 60, 62, 63, 64,
1487955f03dSHans Verkuil 65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
1497955f03dSHans Verkuil 78, 79, 81, 82, 84, 85, 87, 88, 90, 92,
1507955f03dSHans Verkuil 93, 95, 97, 98, 100, 102, 104, 106, 108, 110,
1517955f03dSHans Verkuil 112, 114, 116, 118, 120, 122, 124, 127, 129, 131,
1527955f03dSHans Verkuil 134, 136, 139, 141, 144, 146, 149, 152, 154, 157,
1537955f03dSHans Verkuil 160, 163, 166, 169, 172, 175, 178, 181, 185, 188,
1547955f03dSHans Verkuil 192
1557955f03dSHans Verkuil }
1567955f03dSHans Verkuil };
1577955f03dSHans Verkuil
1587955f03dSHans Verkuil /* MPEG blank frame generation tables */
1597955f03dSHans Verkuil
1607955f03dSHans Verkuil enum mpeg_frame_type {
1617955f03dSHans Verkuil PFRAME,
1627955f03dSHans Verkuil BFRAME_PRE,
1637955f03dSHans Verkuil BFRAME_POST,
1647955f03dSHans Verkuil BFRAME_BIDIR,
1657955f03dSHans Verkuil BFRAME_EMPTY
1667955f03dSHans Verkuil };
1677955f03dSHans Verkuil
1687955f03dSHans Verkuil static const u32 addrinctab[33][2] = {
1697955f03dSHans Verkuil { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 },
1707955f03dSHans Verkuil { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 },
1717955f03dSHans Verkuil { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 },
1727955f03dSHans Verkuil { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 },
1737955f03dSHans Verkuil { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 },
1747955f03dSHans Verkuil { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 },
1757955f03dSHans Verkuil { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 },
1767955f03dSHans Verkuil { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 },
1777955f03dSHans Verkuil { 0x18, 11 }
1787955f03dSHans Verkuil };
1797955f03dSHans Verkuil
1807955f03dSHans Verkuil /* Standard JPEG tables */
1817955f03dSHans Verkuil
1827955f03dSHans Verkuil static const u8 default_intra_quant_table[] = {
1837955f03dSHans Verkuil 8, 16, 19, 22, 26, 27, 29, 34,
1847955f03dSHans Verkuil 16, 16, 22, 24, 27, 29, 34, 37,
1857955f03dSHans Verkuil 19, 22, 26, 27, 29, 34, 34, 38,
1867955f03dSHans Verkuil 22, 22, 26, 27, 29, 34, 37, 40,
1877955f03dSHans Verkuil 22, 26, 27, 29, 32, 35, 40, 48,
1887955f03dSHans Verkuil 26, 27, 29, 32, 35, 40, 48, 58,
1897955f03dSHans Verkuil 26, 27, 29, 34, 38, 46, 56, 69,
1907955f03dSHans Verkuil 27, 29, 35, 38, 46, 56, 69, 83
1917955f03dSHans Verkuil };
1927955f03dSHans Verkuil
1937955f03dSHans Verkuil static const u8 bits_dc_luminance[] = {
1947955f03dSHans Verkuil 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
1957955f03dSHans Verkuil };
1967955f03dSHans Verkuil
1977955f03dSHans Verkuil static const u8 val_dc_luminance[] = {
1987955f03dSHans Verkuil 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
1997955f03dSHans Verkuil };
2007955f03dSHans Verkuil
2017955f03dSHans Verkuil static const u8 bits_dc_chrominance[] = {
2027955f03dSHans Verkuil 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
2037955f03dSHans Verkuil };
2047955f03dSHans Verkuil
2057955f03dSHans Verkuil static const u8 val_dc_chrominance[] = {
2067955f03dSHans Verkuil 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
2077955f03dSHans Verkuil };
2087955f03dSHans Verkuil
2097955f03dSHans Verkuil static const u8 bits_ac_luminance[] = {
2107955f03dSHans Verkuil 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
2117955f03dSHans Verkuil };
2127955f03dSHans Verkuil
2137955f03dSHans Verkuil static const u8 val_ac_luminance[] = {
2147955f03dSHans Verkuil 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
2157955f03dSHans Verkuil 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
2167955f03dSHans Verkuil 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
2177955f03dSHans Verkuil 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
2187955f03dSHans Verkuil 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
2197955f03dSHans Verkuil 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
2207955f03dSHans Verkuil 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
2217955f03dSHans Verkuil 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
2227955f03dSHans Verkuil 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
2237955f03dSHans Verkuil 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
2247955f03dSHans Verkuil 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
2257955f03dSHans Verkuil 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
2267955f03dSHans Verkuil 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
2277955f03dSHans Verkuil 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
2287955f03dSHans Verkuil 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
2297955f03dSHans Verkuil 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
2307955f03dSHans Verkuil 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
2317955f03dSHans Verkuil 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
2327955f03dSHans Verkuil 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
2337955f03dSHans Verkuil 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
2347955f03dSHans Verkuil 0xf9, 0xfa
2357955f03dSHans Verkuil };
2367955f03dSHans Verkuil
2377955f03dSHans Verkuil static const u8 bits_ac_chrominance[] = {
2387955f03dSHans Verkuil 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
2397955f03dSHans Verkuil };
2407955f03dSHans Verkuil
2417955f03dSHans Verkuil static const u8 val_ac_chrominance[] = {
2427955f03dSHans Verkuil 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
2437955f03dSHans Verkuil 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
2447955f03dSHans Verkuil 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
2457955f03dSHans Verkuil 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
2467955f03dSHans Verkuil 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
2477955f03dSHans Verkuil 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
2487955f03dSHans Verkuil 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
2497955f03dSHans Verkuil 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
2507955f03dSHans Verkuil 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
2517955f03dSHans Verkuil 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
2527955f03dSHans Verkuil 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
2537955f03dSHans Verkuil 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
2547955f03dSHans Verkuil 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
2557955f03dSHans Verkuil 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
2567955f03dSHans Verkuil 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
2577955f03dSHans Verkuil 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
2587955f03dSHans Verkuil 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
2597955f03dSHans Verkuil 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
2607955f03dSHans Verkuil 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
2617955f03dSHans Verkuil 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
2627955f03dSHans Verkuil 0xf9, 0xfa
2637955f03dSHans Verkuil };
2647955f03dSHans Verkuil
2657955f03dSHans Verkuil /* Zig-zag mapping for quant table
2667955f03dSHans Verkuil *
2677955f03dSHans Verkuil * OK, let's do this mapping on the actual table above so it doesn't have
2687955f03dSHans Verkuil * to be done on the fly.
2697955f03dSHans Verkuil */
2707955f03dSHans Verkuil static const int zz[64] = {
2717955f03dSHans Verkuil 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
2727955f03dSHans Verkuil 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
2737955f03dSHans Verkuil 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
2747955f03dSHans Verkuil 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
2757955f03dSHans Verkuil };
2767955f03dSHans Verkuil
copy_packages(__le16 * dest,u16 * src,int pkg_cnt,int space)2777955f03dSHans Verkuil static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space)
2787955f03dSHans Verkuil {
2797955f03dSHans Verkuil int i, cnt = pkg_cnt * 32;
2807955f03dSHans Verkuil
2817955f03dSHans Verkuil if (space < cnt)
2827955f03dSHans Verkuil return -1;
2837955f03dSHans Verkuil
2847955f03dSHans Verkuil for (i = 0; i < cnt; ++i)
2857955f03dSHans Verkuil dest[i] = cpu_to_le16p(src + i);
2867955f03dSHans Verkuil
2877955f03dSHans Verkuil return cnt;
2887955f03dSHans Verkuil }
2897955f03dSHans Verkuil
mjpeg_frame_header(struct go7007 * go,unsigned char * buf,int q)2907955f03dSHans Verkuil static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q)
2917955f03dSHans Verkuil {
2927955f03dSHans Verkuil int i, p = 0;
2937955f03dSHans Verkuil
2947955f03dSHans Verkuil buf[p++] = 0xff;
2957955f03dSHans Verkuil buf[p++] = 0xd8;
2967955f03dSHans Verkuil buf[p++] = 0xff;
2977955f03dSHans Verkuil buf[p++] = 0xdb;
2987955f03dSHans Verkuil buf[p++] = 0;
2997955f03dSHans Verkuil buf[p++] = 2 + 65;
3007955f03dSHans Verkuil buf[p++] = 0;
3017955f03dSHans Verkuil buf[p++] = default_intra_quant_table[0];
3027955f03dSHans Verkuil for (i = 1; i < 64; ++i)
3037955f03dSHans Verkuil /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */
3047955f03dSHans Verkuil buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3;
3057955f03dSHans Verkuil buf[p++] = 0xff;
3067955f03dSHans Verkuil buf[p++] = 0xc0;
3077955f03dSHans Verkuil buf[p++] = 0;
3087955f03dSHans Verkuil buf[p++] = 17;
3097955f03dSHans Verkuil buf[p++] = 8;
3107955f03dSHans Verkuil buf[p++] = go->height >> 8;
3117955f03dSHans Verkuil buf[p++] = go->height & 0xff;
3127955f03dSHans Verkuil buf[p++] = go->width >> 8;
3137955f03dSHans Verkuil buf[p++] = go->width & 0xff;
3147955f03dSHans Verkuil buf[p++] = 3;
3157955f03dSHans Verkuil buf[p++] = 1;
3167955f03dSHans Verkuil buf[p++] = 0x22;
3177955f03dSHans Verkuil buf[p++] = 0;
3187955f03dSHans Verkuil buf[p++] = 2;
3197955f03dSHans Verkuil buf[p++] = 0x11;
3207955f03dSHans Verkuil buf[p++] = 0;
3217955f03dSHans Verkuil buf[p++] = 3;
3227955f03dSHans Verkuil buf[p++] = 0x11;
3237955f03dSHans Verkuil buf[p++] = 0;
3247955f03dSHans Verkuil buf[p++] = 0xff;
3257955f03dSHans Verkuil buf[p++] = 0xc4;
3267955f03dSHans Verkuil buf[p++] = 418 >> 8;
3277955f03dSHans Verkuil buf[p++] = 418 & 0xff;
3287955f03dSHans Verkuil buf[p++] = 0x00;
3297955f03dSHans Verkuil memcpy(buf + p, bits_dc_luminance + 1, 16);
3307955f03dSHans Verkuil p += 16;
3317955f03dSHans Verkuil memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance));
3327955f03dSHans Verkuil p += sizeof(val_dc_luminance);
3337955f03dSHans Verkuil buf[p++] = 0x01;
3347955f03dSHans Verkuil memcpy(buf + p, bits_dc_chrominance + 1, 16);
3357955f03dSHans Verkuil p += 16;
3367955f03dSHans Verkuil memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance));
3377955f03dSHans Verkuil p += sizeof(val_dc_chrominance);
3387955f03dSHans Verkuil buf[p++] = 0x10;
3397955f03dSHans Verkuil memcpy(buf + p, bits_ac_luminance + 1, 16);
3407955f03dSHans Verkuil p += 16;
3417955f03dSHans Verkuil memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance));
3427955f03dSHans Verkuil p += sizeof(val_ac_luminance);
3437955f03dSHans Verkuil buf[p++] = 0x11;
3447955f03dSHans Verkuil memcpy(buf + p, bits_ac_chrominance + 1, 16);
3457955f03dSHans Verkuil p += 16;
3467955f03dSHans Verkuil memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance));
3477955f03dSHans Verkuil p += sizeof(val_ac_chrominance);
3487955f03dSHans Verkuil buf[p++] = 0xff;
3497955f03dSHans Verkuil buf[p++] = 0xda;
3507955f03dSHans Verkuil buf[p++] = 0;
3517955f03dSHans Verkuil buf[p++] = 12;
3527955f03dSHans Verkuil buf[p++] = 3;
3537955f03dSHans Verkuil buf[p++] = 1;
3547955f03dSHans Verkuil buf[p++] = 0x00;
3557955f03dSHans Verkuil buf[p++] = 2;
3567955f03dSHans Verkuil buf[p++] = 0x11;
3577955f03dSHans Verkuil buf[p++] = 3;
3587955f03dSHans Verkuil buf[p++] = 0x11;
3597955f03dSHans Verkuil buf[p++] = 0;
3607955f03dSHans Verkuil buf[p++] = 63;
3617955f03dSHans Verkuil buf[p++] = 0;
3627955f03dSHans Verkuil return p;
3637955f03dSHans Verkuil }
3647955f03dSHans Verkuil
gen_mjpeghdr_to_package(struct go7007 * go,__le16 * code,int space)3657955f03dSHans Verkuil static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
3667955f03dSHans Verkuil {
3677955f03dSHans Verkuil u8 *buf;
3687955f03dSHans Verkuil u16 mem = 0x3e00;
3697955f03dSHans Verkuil unsigned int addr = 0x19;
3707955f03dSHans Verkuil int size = 0, i, off = 0, chunk;
3717955f03dSHans Verkuil
3727955f03dSHans Verkuil buf = kzalloc(4096, GFP_KERNEL);
3737955f03dSHans Verkuil if (buf == NULL)
3745bcc0dd7SJavier Martinez Canillas return -ENOMEM;
3757955f03dSHans Verkuil
3767955f03dSHans Verkuil for (i = 1; i < 32; ++i) {
3777955f03dSHans Verkuil mjpeg_frame_header(go, buf + size, i);
3787955f03dSHans Verkuil size += 80;
3797955f03dSHans Verkuil }
3807955f03dSHans Verkuil chunk = mjpeg_frame_header(go, buf + size, 1);
3817955f03dSHans Verkuil memmove(buf + size, buf + size + 80, chunk - 80);
3827955f03dSHans Verkuil size += chunk - 80;
3837955f03dSHans Verkuil
3847955f03dSHans Verkuil for (i = 0; i < size; i += chunk * 2) {
3857955f03dSHans Verkuil if (space - off < 32) {
3867955f03dSHans Verkuil off = -1;
3877955f03dSHans Verkuil goto done;
3887955f03dSHans Verkuil }
3897955f03dSHans Verkuil
3907955f03dSHans Verkuil code[off + 1] = __cpu_to_le16(0x8000 | mem);
3917955f03dSHans Verkuil
3927955f03dSHans Verkuil chunk = 28;
3937955f03dSHans Verkuil if (mem + chunk > 0x4000)
3947955f03dSHans Verkuil chunk = 0x4000 - mem;
3957955f03dSHans Verkuil if (i + 2 * chunk > size)
3967955f03dSHans Verkuil chunk = (size - i) / 2;
3977955f03dSHans Verkuil
3987955f03dSHans Verkuil if (chunk < 28) {
3997955f03dSHans Verkuil code[off] = __cpu_to_le16(0x4000 | chunk);
4007955f03dSHans Verkuil code[off + 31] = __cpu_to_le16(addr++);
4017955f03dSHans Verkuil mem = 0x3e00;
4027955f03dSHans Verkuil } else {
4037955f03dSHans Verkuil code[off] = __cpu_to_le16(0x1000 | 28);
4047955f03dSHans Verkuil code[off + 31] = 0;
4057955f03dSHans Verkuil mem += 28;
4067955f03dSHans Verkuil }
4077955f03dSHans Verkuil
4087955f03dSHans Verkuil memcpy(&code[off + 2], buf + i, chunk * 2);
4097955f03dSHans Verkuil off += 32;
4107955f03dSHans Verkuil }
4117955f03dSHans Verkuil done:
4127955f03dSHans Verkuil kfree(buf);
4137955f03dSHans Verkuil return off;
4147955f03dSHans Verkuil }
4157955f03dSHans Verkuil
mpeg1_frame_header(struct go7007 * go,unsigned char * buf,int modulo,int pict_struct,enum mpeg_frame_type frame)4167955f03dSHans Verkuil static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf,
4177955f03dSHans Verkuil int modulo, int pict_struct, enum mpeg_frame_type frame)
4187955f03dSHans Verkuil {
4197955f03dSHans Verkuil int i, j, mb_code, mb_len;
4207955f03dSHans Verkuil int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
4217955f03dSHans Verkuil CODE_GEN(c, buf + 6);
4227955f03dSHans Verkuil
4237955f03dSHans Verkuil switch (frame) {
4247955f03dSHans Verkuil case PFRAME:
4257955f03dSHans Verkuil mb_code = 0x1;
4267955f03dSHans Verkuil mb_len = 3;
4277955f03dSHans Verkuil break;
4287955f03dSHans Verkuil case BFRAME_PRE:
4297955f03dSHans Verkuil mb_code = 0x2;
4307955f03dSHans Verkuil mb_len = 4;
4317955f03dSHans Verkuil break;
4327955f03dSHans Verkuil case BFRAME_POST:
4337955f03dSHans Verkuil mb_code = 0x2;
4347955f03dSHans Verkuil mb_len = 3;
4357955f03dSHans Verkuil break;
4367955f03dSHans Verkuil case BFRAME_BIDIR:
4377955f03dSHans Verkuil mb_code = 0x2;
4387955f03dSHans Verkuil mb_len = 2;
4397955f03dSHans Verkuil break;
4407955f03dSHans Verkuil default: /* keep the compiler happy */
4417955f03dSHans Verkuil mb_code = mb_len = 0;
4427955f03dSHans Verkuil break;
4437955f03dSHans Verkuil }
4447955f03dSHans Verkuil
4457955f03dSHans Verkuil CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13);
4467955f03dSHans Verkuil CODE_ADD(c, 0xffff, 16);
4477955f03dSHans Verkuil CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
4487955f03dSHans Verkuil if (frame != PFRAME)
4497955f03dSHans Verkuil CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4);
4507955f03dSHans Verkuil else
4517955f03dSHans Verkuil CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */
4527955f03dSHans Verkuil CODE_ADD(c, 0, 3); /* What is this?? */
4537955f03dSHans Verkuil /* Byte-align with zeros */
4547955f03dSHans Verkuil j = 8 - (CODE_LENGTH(c) % 8);
4557955f03dSHans Verkuil if (j != 8)
4567955f03dSHans Verkuil CODE_ADD(c, 0, j);
4577955f03dSHans Verkuil
4587955f03dSHans Verkuil if (go->format == V4L2_PIX_FMT_MPEG2) {
4597955f03dSHans Verkuil CODE_ADD(c, 0x1, 24);
4607955f03dSHans Verkuil CODE_ADD(c, 0xb5, 8);
4617955f03dSHans Verkuil CODE_ADD(c, 0x844, 12);
4627955f03dSHans Verkuil CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8);
4637955f03dSHans Verkuil if (go->interlace_coding) {
4647955f03dSHans Verkuil CODE_ADD(c, pict_struct, 4);
4657955f03dSHans Verkuil if (go->dvd_mode)
4667955f03dSHans Verkuil CODE_ADD(c, 0x000, 11);
4677955f03dSHans Verkuil else
4687955f03dSHans Verkuil CODE_ADD(c, 0x200, 11);
4697955f03dSHans Verkuil } else {
4707955f03dSHans Verkuil CODE_ADD(c, 0x3, 4);
4717955f03dSHans Verkuil CODE_ADD(c, 0x20c, 11);
4727955f03dSHans Verkuil }
4737955f03dSHans Verkuil /* Byte-align with zeros */
4747955f03dSHans Verkuil j = 8 - (CODE_LENGTH(c) % 8);
4757955f03dSHans Verkuil if (j != 8)
4767955f03dSHans Verkuil CODE_ADD(c, 0, j);
4777955f03dSHans Verkuil }
4787955f03dSHans Verkuil
4797955f03dSHans Verkuil for (i = 0; i < rows; ++i) {
4807955f03dSHans Verkuil CODE_ADD(c, 1, 24);
4817955f03dSHans Verkuil CODE_ADD(c, i + 1, 8);
4827955f03dSHans Verkuil CODE_ADD(c, 0x2, 6);
4837955f03dSHans Verkuil CODE_ADD(c, 0x1, 1);
4847955f03dSHans Verkuil CODE_ADD(c, mb_code, mb_len);
4857955f03dSHans Verkuil if (go->interlace_coding) {
4867955f03dSHans Verkuil CODE_ADD(c, 0x1, 2);
4877955f03dSHans Verkuil CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
4887955f03dSHans Verkuil }
4897955f03dSHans Verkuil if (frame == BFRAME_BIDIR) {
4907955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
4917955f03dSHans Verkuil if (go->interlace_coding)
4927955f03dSHans Verkuil CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
4937955f03dSHans Verkuil }
4947955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
4957955f03dSHans Verkuil for (j = (go->width >> 4) - 2; j >= 33; j -= 33)
4967955f03dSHans Verkuil CODE_ADD(c, 0x8, 11);
4977955f03dSHans Verkuil CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]);
4987955f03dSHans Verkuil CODE_ADD(c, mb_code, mb_len);
4997955f03dSHans Verkuil if (go->interlace_coding) {
5007955f03dSHans Verkuil CODE_ADD(c, 0x1, 2);
5017955f03dSHans Verkuil CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
5027955f03dSHans Verkuil }
5037955f03dSHans Verkuil if (frame == BFRAME_BIDIR) {
5047955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
5057955f03dSHans Verkuil if (go->interlace_coding)
5067955f03dSHans Verkuil CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1);
5077955f03dSHans Verkuil }
5087955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
5097955f03dSHans Verkuil
5107955f03dSHans Verkuil /* Byte-align with zeros */
5117955f03dSHans Verkuil j = 8 - (CODE_LENGTH(c) % 8);
5127955f03dSHans Verkuil if (j != 8)
5137955f03dSHans Verkuil CODE_ADD(c, 0, j);
5147955f03dSHans Verkuil }
5157955f03dSHans Verkuil
5167955f03dSHans Verkuil i = CODE_LENGTH(c) + 4 * 8;
5177955f03dSHans Verkuil buf[2] = 0x00;
5187955f03dSHans Verkuil buf[3] = 0x00;
5197955f03dSHans Verkuil buf[4] = 0x01;
5207955f03dSHans Verkuil buf[5] = 0x00;
5217955f03dSHans Verkuil return i;
5227955f03dSHans Verkuil }
5237955f03dSHans Verkuil
mpeg1_sequence_header(struct go7007 * go,unsigned char * buf,int ext)5247955f03dSHans Verkuil static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
5257955f03dSHans Verkuil {
5267955f03dSHans Verkuil int i, aspect_ratio, picture_rate;
5277955f03dSHans Verkuil CODE_GEN(c, buf + 6);
5287955f03dSHans Verkuil
5297955f03dSHans Verkuil if (go->format == V4L2_PIX_FMT_MPEG1) {
5307955f03dSHans Verkuil switch (go->aspect_ratio) {
5317955f03dSHans Verkuil case GO7007_RATIO_4_3:
5327955f03dSHans Verkuil aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
5337955f03dSHans Verkuil break;
5347955f03dSHans Verkuil case GO7007_RATIO_16_9:
5357955f03dSHans Verkuil aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
5367955f03dSHans Verkuil break;
5377955f03dSHans Verkuil default:
5387955f03dSHans Verkuil aspect_ratio = 1;
5397955f03dSHans Verkuil break;
5407955f03dSHans Verkuil }
5417955f03dSHans Verkuil } else {
5427955f03dSHans Verkuil switch (go->aspect_ratio) {
5437955f03dSHans Verkuil case GO7007_RATIO_4_3:
5447955f03dSHans Verkuil aspect_ratio = 2;
5457955f03dSHans Verkuil break;
5467955f03dSHans Verkuil case GO7007_RATIO_16_9:
5477955f03dSHans Verkuil aspect_ratio = 3;
5487955f03dSHans Verkuil break;
5497955f03dSHans Verkuil default:
5507955f03dSHans Verkuil aspect_ratio = 1;
5517955f03dSHans Verkuil break;
5527955f03dSHans Verkuil }
5537955f03dSHans Verkuil }
5547955f03dSHans Verkuil switch (go->sensor_framerate) {
5557955f03dSHans Verkuil case 24000:
5567955f03dSHans Verkuil picture_rate = 1;
5577955f03dSHans Verkuil break;
5587955f03dSHans Verkuil case 24024:
5597955f03dSHans Verkuil picture_rate = 2;
5607955f03dSHans Verkuil break;
5617955f03dSHans Verkuil case 25025:
5627955f03dSHans Verkuil picture_rate = go->interlace_coding ? 6 : 3;
5637955f03dSHans Verkuil break;
5647955f03dSHans Verkuil case 30000:
5657955f03dSHans Verkuil picture_rate = go->interlace_coding ? 7 : 4;
5667955f03dSHans Verkuil break;
5677955f03dSHans Verkuil case 30030:
5687955f03dSHans Verkuil picture_rate = go->interlace_coding ? 8 : 5;
5697955f03dSHans Verkuil break;
5707955f03dSHans Verkuil default:
5717955f03dSHans Verkuil picture_rate = 5; /* 30 fps seems like a reasonable default */
5727955f03dSHans Verkuil break;
5737955f03dSHans Verkuil }
5747955f03dSHans Verkuil
5757955f03dSHans Verkuil CODE_ADD(c, go->width, 12);
5767955f03dSHans Verkuil CODE_ADD(c, go->height, 12);
5777955f03dSHans Verkuil CODE_ADD(c, aspect_ratio, 4);
5787955f03dSHans Verkuil CODE_ADD(c, picture_rate, 4);
5797955f03dSHans Verkuil CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18);
5807955f03dSHans Verkuil CODE_ADD(c, 1, 1);
5817955f03dSHans Verkuil CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10);
5827955f03dSHans Verkuil CODE_ADD(c, 0, 3);
5837955f03dSHans Verkuil
5847955f03dSHans Verkuil /* Byte-align with zeros */
5857955f03dSHans Verkuil i = 8 - (CODE_LENGTH(c) % 8);
5867955f03dSHans Verkuil if (i != 8)
5877955f03dSHans Verkuil CODE_ADD(c, 0, i);
5887955f03dSHans Verkuil
5897955f03dSHans Verkuil if (go->format == V4L2_PIX_FMT_MPEG2) {
5907955f03dSHans Verkuil CODE_ADD(c, 0x1, 24);
5917955f03dSHans Verkuil CODE_ADD(c, 0xb5, 8);
5927955f03dSHans Verkuil CODE_ADD(c, 0x148, 12);
5937955f03dSHans Verkuil if (go->interlace_coding)
5947955f03dSHans Verkuil CODE_ADD(c, 0x20001, 20);
5957955f03dSHans Verkuil else
5967955f03dSHans Verkuil CODE_ADD(c, 0xa0001, 20);
5977955f03dSHans Verkuil CODE_ADD(c, 0, 16);
5987955f03dSHans Verkuil
5997955f03dSHans Verkuil /* Byte-align with zeros */
6007955f03dSHans Verkuil i = 8 - (CODE_LENGTH(c) % 8);
6017955f03dSHans Verkuil if (i != 8)
6027955f03dSHans Verkuil CODE_ADD(c, 0, i);
6037955f03dSHans Verkuil
6047955f03dSHans Verkuil if (ext) {
6057955f03dSHans Verkuil CODE_ADD(c, 0x1, 24);
6067955f03dSHans Verkuil CODE_ADD(c, 0xb52, 12);
6077955f03dSHans Verkuil CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3);
6087955f03dSHans Verkuil CODE_ADD(c, 0x105, 9);
6097955f03dSHans Verkuil CODE_ADD(c, 0x505, 16);
6107955f03dSHans Verkuil CODE_ADD(c, go->width, 14);
6117955f03dSHans Verkuil CODE_ADD(c, 1, 1);
6127955f03dSHans Verkuil CODE_ADD(c, go->height, 14);
6137955f03dSHans Verkuil
6147955f03dSHans Verkuil /* Byte-align with zeros */
6157955f03dSHans Verkuil i = 8 - (CODE_LENGTH(c) % 8);
6167955f03dSHans Verkuil if (i != 8)
6177955f03dSHans Verkuil CODE_ADD(c, 0, i);
6187955f03dSHans Verkuil }
6197955f03dSHans Verkuil }
6207955f03dSHans Verkuil
6217955f03dSHans Verkuil i = CODE_LENGTH(c) + 4 * 8;
6227955f03dSHans Verkuil buf[0] = i & 0xff;
6237955f03dSHans Verkuil buf[1] = i >> 8;
6247955f03dSHans Verkuil buf[2] = 0x00;
6257955f03dSHans Verkuil buf[3] = 0x00;
6267955f03dSHans Verkuil buf[4] = 0x01;
6277955f03dSHans Verkuil buf[5] = 0xb3;
6287955f03dSHans Verkuil return i;
6297955f03dSHans Verkuil }
6307955f03dSHans Verkuil
gen_mpeg1hdr_to_package(struct go7007 * go,__le16 * code,int space,int * framelen)6317955f03dSHans Verkuil static int gen_mpeg1hdr_to_package(struct go7007 *go,
6327955f03dSHans Verkuil __le16 *code, int space, int *framelen)
6337955f03dSHans Verkuil {
6347955f03dSHans Verkuil u8 *buf;
6357955f03dSHans Verkuil u16 mem = 0x3e00;
6367955f03dSHans Verkuil unsigned int addr = 0x19;
6377955f03dSHans Verkuil int i, off = 0, chunk;
6387955f03dSHans Verkuil
6397955f03dSHans Verkuil buf = kzalloc(5120, GFP_KERNEL);
6407955f03dSHans Verkuil if (buf == NULL)
6415bcc0dd7SJavier Martinez Canillas return -ENOMEM;
6427955f03dSHans Verkuil
6437955f03dSHans Verkuil framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
6447955f03dSHans Verkuil if (go->interlace_coding)
6457955f03dSHans Verkuil framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8,
6467955f03dSHans Verkuil 0, 2, PFRAME);
6477955f03dSHans Verkuil buf[0] = framelen[0] & 0xff;
6487955f03dSHans Verkuil buf[1] = framelen[0] >> 8;
6497955f03dSHans Verkuil i = 368;
6507955f03dSHans Verkuil framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE);
6517955f03dSHans Verkuil if (go->interlace_coding)
6527955f03dSHans Verkuil framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8,
6537955f03dSHans Verkuil 0, 2, BFRAME_PRE);
6547955f03dSHans Verkuil buf[i] = framelen[1] & 0xff;
6557955f03dSHans Verkuil buf[i + 1] = framelen[1] >> 8;
6567955f03dSHans Verkuil i += 1632;
6577955f03dSHans Verkuil framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST);
6587955f03dSHans Verkuil if (go->interlace_coding)
6597955f03dSHans Verkuil framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8,
6607955f03dSHans Verkuil 0, 2, BFRAME_POST);
6617955f03dSHans Verkuil buf[i] = framelen[2] & 0xff;
6627955f03dSHans Verkuil buf[i + 1] = framelen[2] >> 8;
6637955f03dSHans Verkuil i += 1432;
6647955f03dSHans Verkuil framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR);
6657955f03dSHans Verkuil if (go->interlace_coding)
6667955f03dSHans Verkuil framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8,
6677955f03dSHans Verkuil 0, 2, BFRAME_BIDIR);
6687955f03dSHans Verkuil buf[i] = framelen[3] & 0xff;
6697955f03dSHans Verkuil buf[i + 1] = framelen[3] >> 8;
6707955f03dSHans Verkuil i += 1632 + 16;
6717955f03dSHans Verkuil mpeg1_sequence_header(go, buf + i, 0);
6727955f03dSHans Verkuil i += 40;
6737955f03dSHans Verkuil for (i = 0; i < 5120; i += chunk * 2) {
6747955f03dSHans Verkuil if (space - off < 32) {
6757955f03dSHans Verkuil off = -1;
6767955f03dSHans Verkuil goto done;
6777955f03dSHans Verkuil }
6787955f03dSHans Verkuil
6797955f03dSHans Verkuil code[off + 1] = __cpu_to_le16(0x8000 | mem);
6807955f03dSHans Verkuil
6817955f03dSHans Verkuil chunk = 28;
6827955f03dSHans Verkuil if (mem + chunk > 0x4000)
6837955f03dSHans Verkuil chunk = 0x4000 - mem;
6847955f03dSHans Verkuil if (i + 2 * chunk > 5120)
6857955f03dSHans Verkuil chunk = (5120 - i) / 2;
6867955f03dSHans Verkuil
6877955f03dSHans Verkuil if (chunk < 28) {
6887955f03dSHans Verkuil code[off] = __cpu_to_le16(0x4000 | chunk);
6897955f03dSHans Verkuil code[off + 31] = __cpu_to_le16(addr);
6907955f03dSHans Verkuil if (mem + chunk == 0x4000) {
6917955f03dSHans Verkuil mem = 0x3e00;
6927955f03dSHans Verkuil ++addr;
6937955f03dSHans Verkuil }
6947955f03dSHans Verkuil } else {
6957955f03dSHans Verkuil code[off] = __cpu_to_le16(0x1000 | 28);
6967955f03dSHans Verkuil code[off + 31] = 0;
6977955f03dSHans Verkuil mem += 28;
6987955f03dSHans Verkuil }
6997955f03dSHans Verkuil
7007955f03dSHans Verkuil memcpy(&code[off + 2], buf + i, chunk * 2);
7017955f03dSHans Verkuil off += 32;
7027955f03dSHans Verkuil }
7037955f03dSHans Verkuil done:
7047955f03dSHans Verkuil kfree(buf);
7057955f03dSHans Verkuil return off;
7067955f03dSHans Verkuil }
7077955f03dSHans Verkuil
vti_bitlen(struct go7007 * go)7087955f03dSHans Verkuil static int vti_bitlen(struct go7007 *go)
7097955f03dSHans Verkuil {
7107955f03dSHans Verkuil unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale;
7117955f03dSHans Verkuil
7127955f03dSHans Verkuil for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i)
7137955f03dSHans Verkuil ;
7147955f03dSHans Verkuil return i + 1;
7157955f03dSHans Verkuil }
7167955f03dSHans Verkuil
mpeg4_frame_header(struct go7007 * go,unsigned char * buf,int modulo,enum mpeg_frame_type frame)7177955f03dSHans Verkuil static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf,
7187955f03dSHans Verkuil int modulo, enum mpeg_frame_type frame)
7197955f03dSHans Verkuil {
7207955f03dSHans Verkuil int i;
7217955f03dSHans Verkuil CODE_GEN(c, buf + 6);
7227955f03dSHans Verkuil int mb_count = (go->width >> 4) * (go->height >> 4);
7237955f03dSHans Verkuil
7247955f03dSHans Verkuil CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2);
7257955f03dSHans Verkuil if (modulo)
7267955f03dSHans Verkuil CODE_ADD(c, 0x1, 1);
7277955f03dSHans Verkuil CODE_ADD(c, 0x1, 2);
7287955f03dSHans Verkuil CODE_ADD(c, 0, vti_bitlen(go));
7297955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
7307955f03dSHans Verkuil if (frame == PFRAME)
7317955f03dSHans Verkuil CODE_ADD(c, 0, 1);
7327955f03dSHans Verkuil CODE_ADD(c, 0xc, 11);
7337955f03dSHans Verkuil if (frame != PFRAME)
7347955f03dSHans Verkuil CODE_ADD(c, 0x4, 3);
7357955f03dSHans Verkuil if (frame != BFRAME_EMPTY) {
7367955f03dSHans Verkuil for (i = 0; i < mb_count; ++i) {
7377955f03dSHans Verkuil switch (frame) {
7387955f03dSHans Verkuil case PFRAME:
7397955f03dSHans Verkuil CODE_ADD(c, 0x1, 1);
7407955f03dSHans Verkuil break;
7417955f03dSHans Verkuil case BFRAME_PRE:
7427955f03dSHans Verkuil CODE_ADD(c, 0x47, 8);
7437955f03dSHans Verkuil break;
7447955f03dSHans Verkuil case BFRAME_POST:
7457955f03dSHans Verkuil CODE_ADD(c, 0x27, 7);
7467955f03dSHans Verkuil break;
7477955f03dSHans Verkuil case BFRAME_BIDIR:
7487955f03dSHans Verkuil CODE_ADD(c, 0x5f, 8);
7497955f03dSHans Verkuil break;
7507955f03dSHans Verkuil case BFRAME_EMPTY: /* keep compiler quiet */
7517955f03dSHans Verkuil break;
7527955f03dSHans Verkuil }
7537955f03dSHans Verkuil }
7547955f03dSHans Verkuil }
7557955f03dSHans Verkuil
7567955f03dSHans Verkuil /* Byte-align with a zero followed by ones */
7577955f03dSHans Verkuil i = 8 - (CODE_LENGTH(c) % 8);
7587955f03dSHans Verkuil CODE_ADD(c, 0, 1);
7597955f03dSHans Verkuil CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
7607955f03dSHans Verkuil
7617955f03dSHans Verkuil i = CODE_LENGTH(c) + 4 * 8;
7627955f03dSHans Verkuil buf[0] = i & 0xff;
7637955f03dSHans Verkuil buf[1] = i >> 8;
7647955f03dSHans Verkuil buf[2] = 0x00;
7657955f03dSHans Verkuil buf[3] = 0x00;
7667955f03dSHans Verkuil buf[4] = 0x01;
7677955f03dSHans Verkuil buf[5] = 0xb6;
7687955f03dSHans Verkuil return i;
7697955f03dSHans Verkuil }
7707955f03dSHans Verkuil
mpeg4_sequence_header(struct go7007 * go,unsigned char * buf,int ext)7717955f03dSHans Verkuil static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
7727955f03dSHans Verkuil {
7737955f03dSHans Verkuil const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali,
7747955f03dSHans Verkuil 0x00, 0x00, 0x01, 0xb5, 0x09,
7757955f03dSHans Verkuil 0x00, 0x00, 0x01, 0x00,
7767955f03dSHans Verkuil 0x00, 0x00, 0x01, 0x20, };
7777955f03dSHans Verkuil int i, aspect_ratio;
7787955f03dSHans Verkuil int fps = go->sensor_framerate / go->fps_scale;
7797955f03dSHans Verkuil CODE_GEN(c, buf + 2 + sizeof(head));
7807955f03dSHans Verkuil
7817955f03dSHans Verkuil switch (go->aspect_ratio) {
7827955f03dSHans Verkuil case GO7007_RATIO_4_3:
7837955f03dSHans Verkuil aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2;
7847955f03dSHans Verkuil break;
7857955f03dSHans Verkuil case GO7007_RATIO_16_9:
7867955f03dSHans Verkuil aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4;
7877955f03dSHans Verkuil break;
7887955f03dSHans Verkuil default:
7897955f03dSHans Verkuil aspect_ratio = 1;
7907955f03dSHans Verkuil break;
7917955f03dSHans Verkuil }
7927955f03dSHans Verkuil
7937955f03dSHans Verkuil memcpy(buf + 2, head, sizeof(head));
7947955f03dSHans Verkuil CODE_ADD(c, 0x191, 17);
7957955f03dSHans Verkuil CODE_ADD(c, aspect_ratio, 4);
7967955f03dSHans Verkuil CODE_ADD(c, 0x1, 4);
7977955f03dSHans Verkuil CODE_ADD(c, fps, 16);
7987955f03dSHans Verkuil CODE_ADD(c, 0x3, 2);
7997955f03dSHans Verkuil CODE_ADD(c, 1001, vti_bitlen(go));
8007955f03dSHans Verkuil CODE_ADD(c, 1, 1);
8017955f03dSHans Verkuil CODE_ADD(c, go->width, 13);
8027955f03dSHans Verkuil CODE_ADD(c, 1, 1);
8037955f03dSHans Verkuil CODE_ADD(c, go->height, 13);
8047955f03dSHans Verkuil CODE_ADD(c, 0x2830, 14);
8057955f03dSHans Verkuil
8067955f03dSHans Verkuil /* Byte-align */
8077955f03dSHans Verkuil i = 8 - (CODE_LENGTH(c) % 8);
8087955f03dSHans Verkuil CODE_ADD(c, 0, 1);
8097955f03dSHans Verkuil CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
8107955f03dSHans Verkuil
8117955f03dSHans Verkuil i = CODE_LENGTH(c) + sizeof(head) * 8;
8127955f03dSHans Verkuil buf[0] = i & 0xff;
8137955f03dSHans Verkuil buf[1] = i >> 8;
8147955f03dSHans Verkuil return i;
8157955f03dSHans Verkuil }
8167955f03dSHans Verkuil
gen_mpeg4hdr_to_package(struct go7007 * go,__le16 * code,int space,int * framelen)8177955f03dSHans Verkuil static int gen_mpeg4hdr_to_package(struct go7007 *go,
8187955f03dSHans Verkuil __le16 *code, int space, int *framelen)
8197955f03dSHans Verkuil {
8207955f03dSHans Verkuil u8 *buf;
8217955f03dSHans Verkuil u16 mem = 0x3e00;
8227955f03dSHans Verkuil unsigned int addr = 0x19;
8237955f03dSHans Verkuil int i, off = 0, chunk;
8247955f03dSHans Verkuil
8257955f03dSHans Verkuil buf = kzalloc(5120, GFP_KERNEL);
8267955f03dSHans Verkuil if (buf == NULL)
8275bcc0dd7SJavier Martinez Canillas return -ENOMEM;
8287955f03dSHans Verkuil
8297955f03dSHans Verkuil framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
8307955f03dSHans Verkuil i = 368;
8317955f03dSHans Verkuil framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE);
8327955f03dSHans Verkuil i += 1632;
8337955f03dSHans Verkuil framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST);
8347955f03dSHans Verkuil i += 1432;
8357955f03dSHans Verkuil framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR);
8367955f03dSHans Verkuil i += 1632;
8377955f03dSHans Verkuil mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY);
8387955f03dSHans Verkuil i += 16;
8397955f03dSHans Verkuil mpeg4_sequence_header(go, buf + i, 0);
8407955f03dSHans Verkuil i += 40;
8417955f03dSHans Verkuil for (i = 0; i < 5120; i += chunk * 2) {
8427955f03dSHans Verkuil if (space - off < 32) {
8437955f03dSHans Verkuil off = -1;
8447955f03dSHans Verkuil goto done;
8457955f03dSHans Verkuil }
8467955f03dSHans Verkuil
8477955f03dSHans Verkuil code[off + 1] = __cpu_to_le16(0x8000 | mem);
8487955f03dSHans Verkuil
8497955f03dSHans Verkuil chunk = 28;
8507955f03dSHans Verkuil if (mem + chunk > 0x4000)
8517955f03dSHans Verkuil chunk = 0x4000 - mem;
8527955f03dSHans Verkuil if (i + 2 * chunk > 5120)
8537955f03dSHans Verkuil chunk = (5120 - i) / 2;
8547955f03dSHans Verkuil
8557955f03dSHans Verkuil if (chunk < 28) {
8567955f03dSHans Verkuil code[off] = __cpu_to_le16(0x4000 | chunk);
8577955f03dSHans Verkuil code[off + 31] = __cpu_to_le16(addr);
8587955f03dSHans Verkuil if (mem + chunk == 0x4000) {
8597955f03dSHans Verkuil mem = 0x3e00;
8607955f03dSHans Verkuil ++addr;
8617955f03dSHans Verkuil }
8627955f03dSHans Verkuil } else {
8637955f03dSHans Verkuil code[off] = __cpu_to_le16(0x1000 | 28);
8647955f03dSHans Verkuil code[off + 31] = 0;
8657955f03dSHans Verkuil mem += 28;
8667955f03dSHans Verkuil }
8677955f03dSHans Verkuil
8687955f03dSHans Verkuil memcpy(&code[off + 2], buf + i, chunk * 2);
8697955f03dSHans Verkuil off += 32;
8707955f03dSHans Verkuil }
8717955f03dSHans Verkuil mem = 0x3e00;
8727955f03dSHans Verkuil addr = go->ipb ? 0x14f9 : 0x0af9;
8737955f03dSHans Verkuil memset(buf, 0, 5120);
8747955f03dSHans Verkuil framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME);
8757955f03dSHans Verkuil i = 368;
8767955f03dSHans Verkuil framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE);
8777955f03dSHans Verkuil i += 1632;
8787955f03dSHans Verkuil framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST);
8797955f03dSHans Verkuil i += 1432;
8807955f03dSHans Verkuil framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR);
8817955f03dSHans Verkuil i += 1632;
8827955f03dSHans Verkuil mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY);
8837955f03dSHans Verkuil i += 16;
8847955f03dSHans Verkuil for (i = 0; i < 5120; i += chunk * 2) {
8857955f03dSHans Verkuil if (space - off < 32) {
8867955f03dSHans Verkuil off = -1;
8877955f03dSHans Verkuil goto done;
8887955f03dSHans Verkuil }
8897955f03dSHans Verkuil
8907955f03dSHans Verkuil code[off + 1] = __cpu_to_le16(0x8000 | mem);
8917955f03dSHans Verkuil
8927955f03dSHans Verkuil chunk = 28;
8937955f03dSHans Verkuil if (mem + chunk > 0x4000)
8947955f03dSHans Verkuil chunk = 0x4000 - mem;
8957955f03dSHans Verkuil if (i + 2 * chunk > 5120)
8967955f03dSHans Verkuil chunk = (5120 - i) / 2;
8977955f03dSHans Verkuil
8987955f03dSHans Verkuil if (chunk < 28) {
8997955f03dSHans Verkuil code[off] = __cpu_to_le16(0x4000 | chunk);
9007955f03dSHans Verkuil code[off + 31] = __cpu_to_le16(addr);
9017955f03dSHans Verkuil if (mem + chunk == 0x4000) {
9027955f03dSHans Verkuil mem = 0x3e00;
9037955f03dSHans Verkuil ++addr;
9047955f03dSHans Verkuil }
9057955f03dSHans Verkuil } else {
9067955f03dSHans Verkuil code[off] = __cpu_to_le16(0x1000 | 28);
9077955f03dSHans Verkuil code[off + 31] = 0;
9087955f03dSHans Verkuil mem += 28;
9097955f03dSHans Verkuil }
9107955f03dSHans Verkuil
9117955f03dSHans Verkuil memcpy(&code[off + 2], buf + i, chunk * 2);
9127955f03dSHans Verkuil off += 32;
9137955f03dSHans Verkuil }
9147955f03dSHans Verkuil done:
9157955f03dSHans Verkuil kfree(buf);
9167955f03dSHans Verkuil return off;
9177955f03dSHans Verkuil }
9187955f03dSHans Verkuil
brctrl_to_package(struct go7007 * go,__le16 * code,int space,int * framelen)9197955f03dSHans Verkuil static int brctrl_to_package(struct go7007 *go,
9207955f03dSHans Verkuil __le16 *code, int space, int *framelen)
9217955f03dSHans Verkuil {
9227955f03dSHans Verkuil int converge_speed = 0;
9237955f03dSHans Verkuil int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ?
9247955f03dSHans Verkuil 100 : 0;
9257955f03dSHans Verkuil int peak_rate = 6 * go->bitrate / 5;
9267955f03dSHans Verkuil int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ?
9277955f03dSHans Verkuil go->bitrate :
9287955f03dSHans Verkuil (go->dvd_mode ? 900000 : peak_rate);
9297955f03dSHans Verkuil int fps = go->sensor_framerate / go->fps_scale;
9307955f03dSHans Verkuil int q = 0;
9317955f03dSHans Verkuil /* Bizarre math below depends on rounding errors in division */
9327955f03dSHans Verkuil u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps;
9337955f03dSHans Verkuil u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps;
9347955f03dSHans Verkuil u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000);
9357955f03dSHans Verkuil u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32);
9367955f03dSHans Verkuil u32 cplx[] = {
9377955f03dSHans Verkuil q > 0 ? sgop_expt_addr * q :
9387955f03dSHans Verkuil 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
9397955f03dSHans Verkuil q > 0 ? sgop_expt_addr * q :
9407955f03dSHans Verkuil 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
9417955f03dSHans Verkuil q > 0 ? sgop_expt_addr * q :
9427955f03dSHans Verkuil 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
9437955f03dSHans Verkuil q > 0 ? sgop_expt_addr * q :
9447955f03dSHans Verkuil 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32,
9457955f03dSHans Verkuil };
9467955f03dSHans Verkuil u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr;
9477955f03dSHans Verkuil u16 pack[] = {
9487955f03dSHans Verkuil 0x200e, 0x0000,
9497955f03dSHans Verkuil 0xBF20, go->ipb ? converge_speed_ipb[converge_speed]
9507955f03dSHans Verkuil : converge_speed_ip[converge_speed],
9517955f03dSHans Verkuil 0xBF21, go->ipb ? 2 : 0,
9527955f03dSHans Verkuil 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50]
9537955f03dSHans Verkuil : 32767,
9547955f03dSHans Verkuil 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767,
9557955f03dSHans Verkuil 0xBF24, 32767,
9567955f03dSHans Verkuil 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda],
9577955f03dSHans Verkuil 0xBF26, sgop_expt_addr & 0x0000FFFF,
9587955f03dSHans Verkuil 0xBF27, sgop_expt_addr >> 16,
9597955f03dSHans Verkuil 0xBF28, sgop_peak_addr & 0x0000FFFF,
9607955f03dSHans Verkuil 0xBF29, sgop_peak_addr >> 16,
9617955f03dSHans Verkuil 0xBF2A, vbv_alert_addr & 0x0000FFFF,
9627955f03dSHans Verkuil 0xBF2B, vbv_alert_addr >> 16,
9637955f03dSHans Verkuil 0xBF2C, 0,
9647955f03dSHans Verkuil 0xBF2D, 0,
9657955f03dSHans Verkuil 0, 0,
9667955f03dSHans Verkuil
9677955f03dSHans Verkuil 0x200e, 0x0000,
9687955f03dSHans Verkuil 0xBF2E, vbv_alert_addr & 0x0000FFFF,
9697955f03dSHans Verkuil 0xBF2F, vbv_alert_addr >> 16,
9707955f03dSHans Verkuil 0xBF30, cplx[0] & 0x0000FFFF,
9717955f03dSHans Verkuil 0xBF31, cplx[0] >> 16,
9727955f03dSHans Verkuil 0xBF32, cplx[1] & 0x0000FFFF,
9737955f03dSHans Verkuil 0xBF33, cplx[1] >> 16,
9747955f03dSHans Verkuil 0xBF34, cplx[2] & 0x0000FFFF,
9757955f03dSHans Verkuil 0xBF35, cplx[2] >> 16,
9767955f03dSHans Verkuil 0xBF36, cplx[3] & 0x0000FFFF,
9777955f03dSHans Verkuil 0xBF37, cplx[3] >> 16,
9787955f03dSHans Verkuil 0xBF38, 0,
9797955f03dSHans Verkuil 0xBF39, 0,
9807955f03dSHans Verkuil 0xBF3A, total_expt_addr & 0x0000FFFF,
9817955f03dSHans Verkuil 0xBF3B, total_expt_addr >> 16,
9827955f03dSHans Verkuil 0, 0,
9837955f03dSHans Verkuil
9847955f03dSHans Verkuil 0x200e, 0x0000,
9857955f03dSHans Verkuil 0xBF3C, total_expt_addr & 0x0000FFFF,
9867955f03dSHans Verkuil 0xBF3D, total_expt_addr >> 16,
9877955f03dSHans Verkuil 0xBF3E, 0,
9887955f03dSHans Verkuil 0xBF3F, 0,
9897955f03dSHans Verkuil 0xBF48, 0,
9907955f03dSHans Verkuil 0xBF49, 0,
9917955f03dSHans Verkuil 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q),
9927955f03dSHans Verkuil 0xBF4B, 4,
9937955f03dSHans Verkuil 0xBF4C, 0,
9947955f03dSHans Verkuil 0xBF4D, 0,
9957955f03dSHans Verkuil 0xBF4E, 0,
9967955f03dSHans Verkuil 0xBF4F, 0,
9977955f03dSHans Verkuil 0xBF50, 0,
9987955f03dSHans Verkuil 0xBF51, 0,
9997955f03dSHans Verkuil 0, 0,
10007955f03dSHans Verkuil
10017955f03dSHans Verkuil 0x200e, 0x0000,
10027955f03dSHans Verkuil 0xBF40, sgop_expt_addr & 0x0000FFFF,
10037955f03dSHans Verkuil 0xBF41, sgop_expt_addr >> 16,
10047955f03dSHans Verkuil 0xBF42, 0,
10057955f03dSHans Verkuil 0xBF43, 0,
10067955f03dSHans Verkuil 0xBF44, 0,
10077955f03dSHans Verkuil 0xBF45, 0,
10087955f03dSHans Verkuil 0xBF46, (go->width >> 4) * (go->height >> 4),
10097955f03dSHans Verkuil 0xBF47, 0,
10107955f03dSHans Verkuil 0xBF64, 0,
10117955f03dSHans Verkuil 0xBF65, 0,
10127955f03dSHans Verkuil 0xBF18, framelen[4],
10137955f03dSHans Verkuil 0xBF19, framelen[5],
10147955f03dSHans Verkuil 0xBF1A, framelen[6],
10157955f03dSHans Verkuil 0xBF1B, framelen[7],
10167955f03dSHans Verkuil 0, 0,
10177955f03dSHans Verkuil
10187955f03dSHans Verkuil #if 0
10197955f03dSHans Verkuil /* Remove once we don't care about matching */
10207955f03dSHans Verkuil 0x200e, 0x0000,
10217955f03dSHans Verkuil 0xBF56, 4,
10227955f03dSHans Verkuil 0xBF57, 0,
10237955f03dSHans Verkuil 0xBF58, 5,
10247955f03dSHans Verkuil 0xBF59, 0,
10257955f03dSHans Verkuil 0xBF5A, 6,
10267955f03dSHans Verkuil 0xBF5B, 0,
10277955f03dSHans Verkuil 0xBF5C, 8,
10287955f03dSHans Verkuil 0xBF5D, 0,
10297955f03dSHans Verkuil 0xBF5E, 1,
10307955f03dSHans Verkuil 0xBF5F, 0,
10317955f03dSHans Verkuil 0xBF60, 1,
10327955f03dSHans Verkuil 0xBF61, 0,
10337955f03dSHans Verkuil 0xBF62, 0,
10347955f03dSHans Verkuil 0xBF63, 0,
10357955f03dSHans Verkuil 0, 0,
10367955f03dSHans Verkuil #else
10377955f03dSHans Verkuil 0x2008, 0x0000,
10387955f03dSHans Verkuil 0xBF56, 4,
10397955f03dSHans Verkuil 0xBF57, 0,
10407955f03dSHans Verkuil 0xBF58, 5,
10417955f03dSHans Verkuil 0xBF59, 0,
10427955f03dSHans Verkuil 0xBF5A, 6,
10437955f03dSHans Verkuil 0xBF5B, 0,
10447955f03dSHans Verkuil 0xBF5C, 8,
10457955f03dSHans Verkuil 0xBF5D, 0,
10467955f03dSHans Verkuil 0, 0,
10477955f03dSHans Verkuil 0, 0,
10487955f03dSHans Verkuil 0, 0,
10497955f03dSHans Verkuil 0, 0,
10507955f03dSHans Verkuil 0, 0,
10517955f03dSHans Verkuil 0, 0,
10527955f03dSHans Verkuil 0, 0,
10537955f03dSHans Verkuil #endif
10547955f03dSHans Verkuil
10557955f03dSHans Verkuil 0x200e, 0x0000,
10567955f03dSHans Verkuil 0xBF10, 0,
10577955f03dSHans Verkuil 0xBF11, 0,
10587955f03dSHans Verkuil 0xBF12, 0,
10597955f03dSHans Verkuil 0xBF13, 0,
10607955f03dSHans Verkuil 0xBF14, 0,
10617955f03dSHans Verkuil 0xBF15, 0,
10627955f03dSHans Verkuil 0xBF16, 0,
10637955f03dSHans Verkuil 0xBF17, 0,
10647955f03dSHans Verkuil 0xBF7E, 0,
10657955f03dSHans Verkuil 0xBF7F, 1,
10667955f03dSHans Verkuil 0xBF52, framelen[0],
10677955f03dSHans Verkuil 0xBF53, framelen[1],
10687955f03dSHans Verkuil 0xBF54, framelen[2],
10697955f03dSHans Verkuil 0xBF55, framelen[3],
10707955f03dSHans Verkuil 0, 0,
10717955f03dSHans Verkuil };
10727955f03dSHans Verkuil
10737955f03dSHans Verkuil return copy_packages(code, pack, 6, space);
10747955f03dSHans Verkuil }
10757955f03dSHans Verkuil
config_package(struct go7007 * go,__le16 * code,int space)10767955f03dSHans Verkuil static int config_package(struct go7007 *go, __le16 *code, int space)
10777955f03dSHans Verkuil {
10787955f03dSHans Verkuil int fps = go->sensor_framerate / go->fps_scale / 1000;
10797955f03dSHans Verkuil int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
10807955f03dSHans Verkuil int brc_window_size = fps;
10817955f03dSHans Verkuil int q_min = 2, q_max = 31;
10827955f03dSHans Verkuil int THACCoeffSet0 = 0;
10837955f03dSHans Verkuil u16 pack[] = {
10847955f03dSHans Verkuil 0x200e, 0x0000,
10857955f03dSHans Verkuil 0xc002, 0x14b4,
10867955f03dSHans Verkuil 0xc003, 0x28b4,
10877955f03dSHans Verkuil 0xc004, 0x3c5a,
10887955f03dSHans Verkuil 0xdc05, 0x2a77,
10897955f03dSHans Verkuil 0xc6c3, go->format == V4L2_PIX_FMT_MPEG4 ? 0 :
10907955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_H263 ? 0 : 1),
10917955f03dSHans Verkuil 0xc680, go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 :
10927955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_H263 ? 0x61 :
10937955f03dSHans Verkuil 0xd3),
10947955f03dSHans Verkuil 0xc780, 0x0140,
10957955f03dSHans Verkuil 0xe009, 0x0001,
10967955f03dSHans Verkuil 0xc60f, 0x0008,
10977955f03dSHans Verkuil 0xd4ff, 0x0002,
10987955f03dSHans Verkuil 0xe403, 2340,
10997955f03dSHans Verkuil 0xe406, 75,
11007955f03dSHans Verkuil 0xd411, 0x0001,
11017955f03dSHans Verkuil 0xd410, 0xa1d6,
11027955f03dSHans Verkuil 0x0001, 0x2801,
11037955f03dSHans Verkuil
11047955f03dSHans Verkuil 0x200d, 0x0000,
11057955f03dSHans Verkuil 0xe402, 0x018b,
11067955f03dSHans Verkuil 0xe401, 0x8b01,
11077955f03dSHans Verkuil 0xd472, (go->board_info->sensor_flags &
11087955f03dSHans Verkuil GO7007_SENSOR_TV) &&
11097955f03dSHans Verkuil (!go->interlace_coding) ?
11107955f03dSHans Verkuil 0x01b0 : 0x0170,
11117955f03dSHans Verkuil 0xd475, (go->board_info->sensor_flags &
11127955f03dSHans Verkuil GO7007_SENSOR_TV) &&
11137955f03dSHans Verkuil (!go->interlace_coding) ?
11147955f03dSHans Verkuil 0x0008 : 0x0009,
11157955f03dSHans Verkuil 0xc404, go->interlace_coding ? 0x44 :
11167955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 :
11177955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 :
11187955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 :
11197955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_H263 ? 0x08 :
11207955f03dSHans Verkuil 0x20)))),
11217955f03dSHans Verkuil 0xbf0a, (go->format == V4L2_PIX_FMT_MPEG4 ? 8 :
11227955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG1 ? 1 :
11237955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG2 ? 2 :
11247955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) |
11257955f03dSHans Verkuil ((go->repeat_seqhead ? 1 : 0) << 6) |
11267955f03dSHans Verkuil ((go->dvd_mode ? 1 : 0) << 9) |
11277955f03dSHans Verkuil ((go->gop_header_enable ? 1 : 0) << 10),
11287955f03dSHans Verkuil 0xbf0b, 0,
11297955f03dSHans Verkuil 0xdd5a, go->ipb ? 0x14 : 0x0a,
11307955f03dSHans Verkuil 0xbf0c, 0,
11317955f03dSHans Verkuil 0xbf0d, 0,
11327955f03dSHans Verkuil 0xc683, THACCoeffSet0,
11337955f03dSHans Verkuil 0xc40a, (go->width << 4) | rows,
11347955f03dSHans Verkuil 0xe01a, go->board_info->hpi_buffer_cap,
11357955f03dSHans Verkuil 0, 0,
11367955f03dSHans Verkuil 0, 0,
11377955f03dSHans Verkuil
11387955f03dSHans Verkuil 0x2008, 0,
11397955f03dSHans Verkuil 0xe402, 0x88,
11407955f03dSHans Verkuil 0xe401, 0x8f01,
11417955f03dSHans Verkuil 0xbf6a, 0,
11427955f03dSHans Verkuil 0xbf6b, 0,
11437955f03dSHans Verkuil 0xbf6c, 0,
11447955f03dSHans Verkuil 0xbf6d, 0,
11457955f03dSHans Verkuil 0xbf6e, 0,
11467955f03dSHans Verkuil 0xbf6f, 0,
11477955f03dSHans Verkuil 0, 0,
11487955f03dSHans Verkuil 0, 0,
11497955f03dSHans Verkuil 0, 0,
11507955f03dSHans Verkuil 0, 0,
11517955f03dSHans Verkuil 0, 0,
11527955f03dSHans Verkuil 0, 0,
11537955f03dSHans Verkuil 0, 0,
11547955f03dSHans Verkuil
11557955f03dSHans Verkuil 0x200e, 0,
11567955f03dSHans Verkuil 0xbf66, brc_window_size,
11577955f03dSHans Verkuil 0xbf67, 0,
11587955f03dSHans Verkuil 0xbf68, q_min,
11597955f03dSHans Verkuil 0xbf69, q_max,
11607955f03dSHans Verkuil 0xbfe0, 0,
11617955f03dSHans Verkuil 0xbfe1, 0,
11627955f03dSHans Verkuil 0xbfe2, 0,
11637955f03dSHans Verkuil 0xbfe3, go->ipb ? 3 : 1,
11647955f03dSHans Verkuil 0xc031, go->board_info->sensor_flags &
11657955f03dSHans Verkuil GO7007_SENSOR_VBI ? 1 : 0,
11667955f03dSHans Verkuil 0xc01c, 0x1f,
11677955f03dSHans Verkuil 0xdd8c, 0x15,
11687955f03dSHans Verkuil 0xdd94, 0x15,
11697955f03dSHans Verkuil 0xdd88, go->ipb ? 0x1401 : 0x0a01,
11707955f03dSHans Verkuil 0xdd90, go->ipb ? 0x1401 : 0x0a01,
11717955f03dSHans Verkuil 0, 0,
11727955f03dSHans Verkuil
11737955f03dSHans Verkuil 0x200e, 0,
11747955f03dSHans Verkuil 0xbfe4, 0,
11757955f03dSHans Verkuil 0xbfe5, 0,
11767955f03dSHans Verkuil 0xbfe6, 0,
11777955f03dSHans Verkuil 0xbfe7, fps << 8,
11787955f03dSHans Verkuil 0xbfe8, 0x3a00,
11797955f03dSHans Verkuil 0xbfe9, 0,
11807955f03dSHans Verkuil 0xbfea, 0,
11817955f03dSHans Verkuil 0xbfeb, 0,
11827955f03dSHans Verkuil 0xbfec, (go->interlace_coding ? 1 << 15 : 0) |
11837955f03dSHans Verkuil (go->modet_enable ? 0xa : 0) |
11847955f03dSHans Verkuil (go->board_info->sensor_flags &
11857955f03dSHans Verkuil GO7007_SENSOR_VBI ? 1 : 0),
11867955f03dSHans Verkuil 0xbfed, 0,
11877955f03dSHans Verkuil 0xbfee, 0,
11887955f03dSHans Verkuil 0xbfef, 0,
11897955f03dSHans Verkuil 0xbff0, go->board_info->sensor_flags &
11907955f03dSHans Verkuil GO7007_SENSOR_TV ? 0xf060 : 0xb060,
11917955f03dSHans Verkuil 0xbff1, 0,
11927955f03dSHans Verkuil 0, 0,
11937955f03dSHans Verkuil };
11947955f03dSHans Verkuil
11957955f03dSHans Verkuil return copy_packages(code, pack, 5, space);
11967955f03dSHans Verkuil }
11977955f03dSHans Verkuil
seqhead_to_package(struct go7007 * go,__le16 * code,int space,int (* sequence_header_func)(struct go7007 * go,unsigned char * buf,int ext))11987955f03dSHans Verkuil static int seqhead_to_package(struct go7007 *go, __le16 *code, int space,
11997955f03dSHans Verkuil int (*sequence_header_func)(struct go7007 *go,
12007955f03dSHans Verkuil unsigned char *buf, int ext))
12017955f03dSHans Verkuil {
12027955f03dSHans Verkuil int vop_time_increment_bitlength = vti_bitlen(go);
12037955f03dSHans Verkuil int fps = go->sensor_framerate / go->fps_scale *
12047955f03dSHans Verkuil (go->interlace_coding ? 2 : 1);
12057955f03dSHans Verkuil unsigned char buf[40] = { };
12067955f03dSHans Verkuil int len = sequence_header_func(go, buf, 1);
12077955f03dSHans Verkuil u16 pack[] = {
12087955f03dSHans Verkuil 0x2006, 0,
12097955f03dSHans Verkuil 0xbf08, fps,
12107955f03dSHans Verkuil 0xbf09, 0,
12117955f03dSHans Verkuil 0xbff2, vop_time_increment_bitlength,
12127955f03dSHans Verkuil 0xbff3, (1 << vop_time_increment_bitlength) - 1,
12137955f03dSHans Verkuil 0xbfe6, 0,
12147955f03dSHans Verkuil 0xbfe7, (fps / 1000) << 8,
12157955f03dSHans Verkuil 0, 0,
12167955f03dSHans Verkuil 0, 0,
12177955f03dSHans Verkuil 0, 0,
12187955f03dSHans Verkuil 0, 0,
12197955f03dSHans Verkuil 0, 0,
12207955f03dSHans Verkuil 0, 0,
12217955f03dSHans Verkuil 0, 0,
12227955f03dSHans Verkuil 0, 0,
12237955f03dSHans Verkuil 0, 0,
12247955f03dSHans Verkuil
12257955f03dSHans Verkuil 0x2007, 0,
12267955f03dSHans Verkuil 0xc800, buf[2] << 8 | buf[3],
12277955f03dSHans Verkuil 0xc801, buf[4] << 8 | buf[5],
12287955f03dSHans Verkuil 0xc802, buf[6] << 8 | buf[7],
12297955f03dSHans Verkuil 0xc803, buf[8] << 8 | buf[9],
12307955f03dSHans Verkuil 0xc406, 64,
12317955f03dSHans Verkuil 0xc407, len - 64,
12327955f03dSHans Verkuil 0xc61b, 1,
12337955f03dSHans Verkuil 0, 0,
12347955f03dSHans Verkuil 0, 0,
12357955f03dSHans Verkuil 0, 0,
12367955f03dSHans Verkuil 0, 0,
12377955f03dSHans Verkuil 0, 0,
12387955f03dSHans Verkuil 0, 0,
12397955f03dSHans Verkuil 0, 0,
12407955f03dSHans Verkuil 0, 0,
12417955f03dSHans Verkuil
12427955f03dSHans Verkuil 0x200e, 0,
12437955f03dSHans Verkuil 0xc808, buf[10] << 8 | buf[11],
12447955f03dSHans Verkuil 0xc809, buf[12] << 8 | buf[13],
12457955f03dSHans Verkuil 0xc80a, buf[14] << 8 | buf[15],
12467955f03dSHans Verkuil 0xc80b, buf[16] << 8 | buf[17],
12477955f03dSHans Verkuil 0xc80c, buf[18] << 8 | buf[19],
12487955f03dSHans Verkuil 0xc80d, buf[20] << 8 | buf[21],
12497955f03dSHans Verkuil 0xc80e, buf[22] << 8 | buf[23],
12507955f03dSHans Verkuil 0xc80f, buf[24] << 8 | buf[25],
12517955f03dSHans Verkuil 0xc810, buf[26] << 8 | buf[27],
12527955f03dSHans Verkuil 0xc811, buf[28] << 8 | buf[29],
12537955f03dSHans Verkuil 0xc812, buf[30] << 8 | buf[31],
12547955f03dSHans Verkuil 0xc813, buf[32] << 8 | buf[33],
12557955f03dSHans Verkuil 0xc814, buf[34] << 8 | buf[35],
12567955f03dSHans Verkuil 0xc815, buf[36] << 8 | buf[37],
12577955f03dSHans Verkuil 0, 0,
12587955f03dSHans Verkuil 0, 0,
12597955f03dSHans Verkuil 0, 0,
12607955f03dSHans Verkuil };
12617955f03dSHans Verkuil
12627955f03dSHans Verkuil return copy_packages(code, pack, 3, space);
12637955f03dSHans Verkuil }
12647955f03dSHans Verkuil
relative_prime(int big,int little)12657955f03dSHans Verkuil static int relative_prime(int big, int little)
12667955f03dSHans Verkuil {
12677955f03dSHans Verkuil int remainder;
12687955f03dSHans Verkuil
12697955f03dSHans Verkuil while (little != 0) {
12707955f03dSHans Verkuil remainder = big % little;
12717955f03dSHans Verkuil big = little;
12727955f03dSHans Verkuil little = remainder;
12737955f03dSHans Verkuil }
12747955f03dSHans Verkuil return big;
12757955f03dSHans Verkuil }
12767955f03dSHans Verkuil
avsync_to_package(struct go7007 * go,__le16 * code,int space)12777955f03dSHans Verkuil static int avsync_to_package(struct go7007 *go, __le16 *code, int space)
12787955f03dSHans Verkuil {
12797955f03dSHans Verkuil int arate = go->board_info->audio_rate * 1001 * go->fps_scale;
12807955f03dSHans Verkuil int ratio = arate / go->sensor_framerate;
12817955f03dSHans Verkuil int adjratio = ratio * 215 / 100;
12827955f03dSHans Verkuil int rprime = relative_prime(go->sensor_framerate,
12837955f03dSHans Verkuil arate % go->sensor_framerate);
12847955f03dSHans Verkuil int f1 = (arate % go->sensor_framerate) / rprime;
12857955f03dSHans Verkuil int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime;
12867955f03dSHans Verkuil u16 pack[] = {
12877955f03dSHans Verkuil 0x200e, 0,
12887955f03dSHans Verkuil 0xbf98, (u16)((-adjratio) & 0xffff),
12897955f03dSHans Verkuil 0xbf99, (u16)((-adjratio) >> 16),
12907955f03dSHans Verkuil 0xbf92, 0,
12917955f03dSHans Verkuil 0xbf93, 0,
12927955f03dSHans Verkuil 0xbff4, f1 > f2 ? f1 : f2,
12937955f03dSHans Verkuil 0xbff5, f1 < f2 ? f1 : f2,
12947955f03dSHans Verkuil 0xbff6, f1 < f2 ? ratio : ratio + 1,
12957955f03dSHans Verkuil 0xbff7, f1 > f2 ? ratio : ratio + 1,
12967955f03dSHans Verkuil 0xbff8, 0,
12977955f03dSHans Verkuil 0xbff9, 0,
12987955f03dSHans Verkuil 0xbffa, adjratio & 0xffff,
12997955f03dSHans Verkuil 0xbffb, adjratio >> 16,
13007955f03dSHans Verkuil 0xbf94, 0,
13017955f03dSHans Verkuil 0xbf95, 0,
13027955f03dSHans Verkuil 0, 0,
13037955f03dSHans Verkuil };
13047955f03dSHans Verkuil
13057955f03dSHans Verkuil return copy_packages(code, pack, 1, space);
13067955f03dSHans Verkuil }
13077955f03dSHans Verkuil
final_package(struct go7007 * go,__le16 * code,int space)13087955f03dSHans Verkuil static int final_package(struct go7007 *go, __le16 *code, int space)
13097955f03dSHans Verkuil {
13107955f03dSHans Verkuil int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
13117955f03dSHans Verkuil u16 pack[] = {
13127955f03dSHans Verkuil 0x8000,
13137955f03dSHans Verkuil 0,
13147955f03dSHans Verkuil 0,
13157955f03dSHans Verkuil 0,
13167955f03dSHans Verkuil 0,
13177955f03dSHans Verkuil 0,
13187955f03dSHans Verkuil 0,
13197955f03dSHans Verkuil 2,
13207955f03dSHans Verkuil ((go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
13217955f03dSHans Verkuil (!go->interlace_coding) ?
13227955f03dSHans Verkuil (1 << 14) | (1 << 9) : 0) |
13237955f03dSHans Verkuil ((go->encoder_subsample ? 1 : 0) << 8) |
13247955f03dSHans Verkuil (go->board_info->sensor_flags &
13257955f03dSHans Verkuil GO7007_SENSOR_CONFIG_MASK),
13267955f03dSHans Verkuil ((go->encoder_v_halve ? 1 : 0) << 14) |
13277955f03dSHans Verkuil (go->encoder_v_halve ? rows << 9 : rows << 8) |
13287955f03dSHans Verkuil (go->encoder_h_halve ? 1 << 6 : 0) |
13297955f03dSHans Verkuil (go->encoder_h_halve ? go->width >> 3 : go->width >> 4),
13307955f03dSHans Verkuil (1 << 15) | (go->encoder_v_offset << 6) |
13317955f03dSHans Verkuil (1 << 7) | (go->encoder_h_offset >> 2),
13327955f03dSHans Verkuil (1 << 6),
13337955f03dSHans Verkuil 0,
13347955f03dSHans Verkuil 0,
13357955f03dSHans Verkuil ((go->fps_scale - 1) << 8) |
13367955f03dSHans Verkuil (go->board_info->sensor_flags & GO7007_SENSOR_TV ?
13377955f03dSHans Verkuil (1 << 7) : 0) |
13387955f03dSHans Verkuil 0x41,
13397955f03dSHans Verkuil go->ipb ? 0xd4c : 0x36b,
13407955f03dSHans Verkuil (rows << 8) | (go->width >> 4),
13417955f03dSHans Verkuil go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0,
13427955f03dSHans Verkuil (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) |
13437955f03dSHans Verkuil ((go->closed_gop ? 1 : 0) << 12) |
13447955f03dSHans Verkuil ((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) |
13457955f03dSHans Verkuil /* (1 << 9) | */
13467955f03dSHans Verkuil ((go->ipb ? 3 : 0) << 7) |
13477955f03dSHans Verkuil ((go->modet_enable ? 1 : 0) << 2) |
13487955f03dSHans Verkuil ((go->dvd_mode ? 1 : 0) << 1) | 1,
13497955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 :
13507955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 :
13517955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 :
13527955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 :
13537955f03dSHans Verkuil (go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))),
13547955f03dSHans Verkuil go->ipb ? 0x1f15 : 0x1f0b,
13557955f03dSHans Verkuil go->ipb ? 0x0015 : 0x000b,
13567955f03dSHans Verkuil go->ipb ? 0xa800 : 0x5800,
13577955f03dSHans Verkuil 0xffff,
13587955f03dSHans Verkuil 0x0020 + 0x034b * 0,
13597955f03dSHans Verkuil 0x0020 + 0x034b * 1,
13607955f03dSHans Verkuil 0x0020 + 0x034b * 2,
13617955f03dSHans Verkuil 0x0020 + 0x034b * 3,
13627955f03dSHans Verkuil 0x0020 + 0x034b * 4,
13637955f03dSHans Verkuil 0x0020 + 0x034b * 5,
13647955f03dSHans Verkuil go->ipb ? (go->gop_size / 3) : go->gop_size,
13657955f03dSHans Verkuil (go->height >> 4) * (go->width >> 4) * 110 / 100,
13667955f03dSHans Verkuil };
13677955f03dSHans Verkuil
13687955f03dSHans Verkuil return copy_packages(code, pack, 1, space);
13697955f03dSHans Verkuil }
13707955f03dSHans Verkuil
audio_to_package(struct go7007 * go,__le16 * code,int space)13717955f03dSHans Verkuil static int audio_to_package(struct go7007 *go, __le16 *code, int space)
13727955f03dSHans Verkuil {
13737955f03dSHans Verkuil int clock_config = ((go->board_info->audio_flags &
13747955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) |
13757955f03dSHans Verkuil ((go->board_info->audio_flags &
13767955f03dSHans Verkuil GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) |
13777955f03dSHans Verkuil (((go->board_info->audio_bclk_div / 4) - 1) << 4) |
13787955f03dSHans Verkuil (go->board_info->audio_main_div - 1);
13797955f03dSHans Verkuil u16 pack[] = {
13807955f03dSHans Verkuil 0x200d, 0,
13817955f03dSHans Verkuil 0x9002, 0,
13827955f03dSHans Verkuil 0x9002, 0,
13837955f03dSHans Verkuil 0x9031, 0,
13847955f03dSHans Verkuil 0x9032, 0,
13857955f03dSHans Verkuil 0x9033, 0,
13867955f03dSHans Verkuil 0x9034, 0,
13877955f03dSHans Verkuil 0x9035, 0,
13887955f03dSHans Verkuil 0x9036, 0,
13897955f03dSHans Verkuil 0x9037, 0,
13907955f03dSHans Verkuil 0x9040, 0,
13917955f03dSHans Verkuil 0x9000, clock_config,
13927955f03dSHans Verkuil 0x9001, (go->board_info->audio_flags & 0xffff) |
13937955f03dSHans Verkuil (1 << 9),
13947955f03dSHans Verkuil 0x9000, ((go->board_info->audio_flags &
13957955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER ?
13967955f03dSHans Verkuil 1 : 0) << 10) |
13977955f03dSHans Verkuil clock_config,
13987955f03dSHans Verkuil 0, 0,
13997955f03dSHans Verkuil 0, 0,
14007955f03dSHans Verkuil 0x2005, 0,
14017955f03dSHans Verkuil 0x9041, 0,
14027955f03dSHans Verkuil 0x9042, 256,
14037955f03dSHans Verkuil 0x9043, 0,
14047955f03dSHans Verkuil 0x9044, 16,
14057955f03dSHans Verkuil 0x9045, 16,
14067955f03dSHans Verkuil 0, 0,
14077955f03dSHans Verkuil 0, 0,
14087955f03dSHans Verkuil 0, 0,
14097955f03dSHans Verkuil 0, 0,
14107955f03dSHans Verkuil 0, 0,
14117955f03dSHans Verkuil 0, 0,
14127955f03dSHans Verkuil 0, 0,
14137955f03dSHans Verkuil 0, 0,
14147955f03dSHans Verkuil 0, 0,
14157955f03dSHans Verkuil 0, 0,
14167955f03dSHans Verkuil };
14177955f03dSHans Verkuil
14187955f03dSHans Verkuil return copy_packages(code, pack, 2, space);
14197955f03dSHans Verkuil }
14207955f03dSHans Verkuil
modet_to_package(struct go7007 * go,__le16 * code,int space)14217955f03dSHans Verkuil static int modet_to_package(struct go7007 *go, __le16 *code, int space)
14227955f03dSHans Verkuil {
14237955f03dSHans Verkuil bool has_modet0 = go->modet[0].enable;
14247955f03dSHans Verkuil bool has_modet1 = go->modet[1].enable;
14257955f03dSHans Verkuil bool has_modet2 = go->modet[2].enable;
14267955f03dSHans Verkuil bool has_modet3 = go->modet[3].enable;
14277955f03dSHans Verkuil int ret, mb, i, addr, cnt = 0;
14287955f03dSHans Verkuil u16 pack[32];
14297955f03dSHans Verkuil u16 thresholds[] = {
14307955f03dSHans Verkuil 0x200e, 0,
14317955f03dSHans Verkuil 0xbf82, has_modet0 ? go->modet[0].pixel_threshold : 32767,
14327955f03dSHans Verkuil 0xbf83, has_modet1 ? go->modet[1].pixel_threshold : 32767,
14337955f03dSHans Verkuil 0xbf84, has_modet2 ? go->modet[2].pixel_threshold : 32767,
14347955f03dSHans Verkuil 0xbf85, has_modet3 ? go->modet[3].pixel_threshold : 32767,
14357955f03dSHans Verkuil 0xbf86, has_modet0 ? go->modet[0].motion_threshold : 32767,
14367955f03dSHans Verkuil 0xbf87, has_modet1 ? go->modet[1].motion_threshold : 32767,
14377955f03dSHans Verkuil 0xbf88, has_modet2 ? go->modet[2].motion_threshold : 32767,
14387955f03dSHans Verkuil 0xbf89, has_modet3 ? go->modet[3].motion_threshold : 32767,
14397955f03dSHans Verkuil 0xbf8a, has_modet0 ? go->modet[0].mb_threshold : 32767,
14407955f03dSHans Verkuil 0xbf8b, has_modet1 ? go->modet[1].mb_threshold : 32767,
14417955f03dSHans Verkuil 0xbf8c, has_modet2 ? go->modet[2].mb_threshold : 32767,
14427955f03dSHans Verkuil 0xbf8d, has_modet3 ? go->modet[3].mb_threshold : 32767,
14437955f03dSHans Verkuil 0xbf8e, 0,
14447955f03dSHans Verkuil 0xbf8f, 0,
14457955f03dSHans Verkuil 0, 0,
14467955f03dSHans Verkuil };
14477955f03dSHans Verkuil
14487955f03dSHans Verkuil ret = copy_packages(code, thresholds, 1, space);
14497955f03dSHans Verkuil if (ret < 0)
14507955f03dSHans Verkuil return -1;
14517955f03dSHans Verkuil cnt += ret;
14527955f03dSHans Verkuil
14537955f03dSHans Verkuil addr = 0xbac0;
14547955f03dSHans Verkuil memset(pack, 0, 64);
14557955f03dSHans Verkuil i = 0;
14567955f03dSHans Verkuil for (mb = 0; mb < 1624; ++mb) {
14577955f03dSHans Verkuil pack[i * 2 + 3] <<= 2;
14587955f03dSHans Verkuil pack[i * 2 + 3] |= go->modet_map[mb];
14597955f03dSHans Verkuil if (mb % 8 != 7)
14607955f03dSHans Verkuil continue;
14617955f03dSHans Verkuil pack[i * 2 + 2] = addr++;
14627955f03dSHans Verkuil ++i;
14637955f03dSHans Verkuil if (i == 10 || mb == 1623) {
14647955f03dSHans Verkuil pack[0] = 0x2000 | i;
14657955f03dSHans Verkuil ret = copy_packages(code + cnt, pack, 1, space - cnt);
14667955f03dSHans Verkuil if (ret < 0)
14677955f03dSHans Verkuil return -1;
14687955f03dSHans Verkuil cnt += ret;
14697955f03dSHans Verkuil i = 0;
14707955f03dSHans Verkuil memset(pack, 0, 64);
14717955f03dSHans Verkuil }
14727955f03dSHans Verkuil pack[i * 2 + 3] = 0;
14737955f03dSHans Verkuil }
14747955f03dSHans Verkuil
14757955f03dSHans Verkuil memset(pack, 0, 64);
14767955f03dSHans Verkuil i = 0;
14777955f03dSHans Verkuil for (addr = 0xbb90; addr < 0xbbfa; ++addr) {
14787955f03dSHans Verkuil pack[i * 2 + 2] = addr;
14797955f03dSHans Verkuil pack[i * 2 + 3] = 0;
14807955f03dSHans Verkuil ++i;
14817955f03dSHans Verkuil if (i == 10 || addr == 0xbbf9) {
14827955f03dSHans Verkuil pack[0] = 0x2000 | i;
14837955f03dSHans Verkuil ret = copy_packages(code + cnt, pack, 1, space - cnt);
14847955f03dSHans Verkuil if (ret < 0)
14857955f03dSHans Verkuil return -1;
14867955f03dSHans Verkuil cnt += ret;
14877955f03dSHans Verkuil i = 0;
14887955f03dSHans Verkuil memset(pack, 0, 64);
14897955f03dSHans Verkuil }
14907955f03dSHans Verkuil }
14917955f03dSHans Verkuil return cnt;
14927955f03dSHans Verkuil }
14937955f03dSHans Verkuil
do_special(struct go7007 * go,u16 type,__le16 * code,int space,int * framelen)1494ed713a4aSArnd Bergmann static noinline_for_stack int do_special(struct go7007 *go, u16 type,
1495ed713a4aSArnd Bergmann __le16 *code, int space, int *framelen)
14967955f03dSHans Verkuil {
14977955f03dSHans Verkuil switch (type) {
14987955f03dSHans Verkuil case SPECIAL_FRM_HEAD:
14997955f03dSHans Verkuil switch (go->format) {
15007955f03dSHans Verkuil case V4L2_PIX_FMT_MJPEG:
15017955f03dSHans Verkuil return gen_mjpeghdr_to_package(go, code, space);
15027955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG1:
15037955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG2:
15047955f03dSHans Verkuil return gen_mpeg1hdr_to_package(go, code, space,
15057955f03dSHans Verkuil framelen);
15067955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG4:
15077955f03dSHans Verkuil return gen_mpeg4hdr_to_package(go, code, space,
15087955f03dSHans Verkuil framelen);
1509a7f3482dSHans Verkuil default:
1510a7f3482dSHans Verkuil break;
15117955f03dSHans Verkuil }
1512a7f3482dSHans Verkuil break;
15137955f03dSHans Verkuil case SPECIAL_BRC_CTRL:
15147955f03dSHans Verkuil return brctrl_to_package(go, code, space, framelen);
15157955f03dSHans Verkuil case SPECIAL_CONFIG:
15167955f03dSHans Verkuil return config_package(go, code, space);
15177955f03dSHans Verkuil case SPECIAL_SEQHEAD:
15187955f03dSHans Verkuil switch (go->format) {
15197955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG1:
15207955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG2:
15217955f03dSHans Verkuil return seqhead_to_package(go, code, space,
15227955f03dSHans Verkuil mpeg1_sequence_header);
15237955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG4:
15247955f03dSHans Verkuil return seqhead_to_package(go, code, space,
15257955f03dSHans Verkuil mpeg4_sequence_header);
15267955f03dSHans Verkuil default:
15277955f03dSHans Verkuil return 0;
15287955f03dSHans Verkuil }
15297955f03dSHans Verkuil case SPECIAL_AV_SYNC:
15307955f03dSHans Verkuil return avsync_to_package(go, code, space);
15317955f03dSHans Verkuil case SPECIAL_FINAL:
15327955f03dSHans Verkuil return final_package(go, code, space);
15337955f03dSHans Verkuil case SPECIAL_AUDIO:
15347955f03dSHans Verkuil return audio_to_package(go, code, space);
15357955f03dSHans Verkuil case SPECIAL_MODET:
15367955f03dSHans Verkuil return modet_to_package(go, code, space);
15377955f03dSHans Verkuil }
15387955f03dSHans Verkuil dev_err(go->dev,
15397955f03dSHans Verkuil "firmware file contains unsupported feature %04x\n", type);
15407955f03dSHans Verkuil return -1;
15417955f03dSHans Verkuil }
15427955f03dSHans Verkuil
go7007_construct_fw_image(struct go7007 * go,u8 ** fw,int * fwlen)15437955f03dSHans Verkuil int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
15447955f03dSHans Verkuil {
15457955f03dSHans Verkuil const struct firmware *fw_entry;
15467955f03dSHans Verkuil __le16 *code, *src;
15477955f03dSHans Verkuil int framelen[8] = { }; /* holds the lengths of empty frame templates */
15487955f03dSHans Verkuil int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags;
15497955f03dSHans Verkuil int mode_flag;
15507955f03dSHans Verkuil int ret;
15517955f03dSHans Verkuil
15527955f03dSHans Verkuil switch (go->format) {
15537955f03dSHans Verkuil case V4L2_PIX_FMT_MJPEG:
15547955f03dSHans Verkuil mode_flag = FLAG_MODE_MJPEG;
15557955f03dSHans Verkuil break;
15567955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG1:
15577955f03dSHans Verkuil mode_flag = FLAG_MODE_MPEG1;
15587955f03dSHans Verkuil break;
15597955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG2:
15607955f03dSHans Verkuil mode_flag = FLAG_MODE_MPEG2;
15617955f03dSHans Verkuil break;
15627955f03dSHans Verkuil case V4L2_PIX_FMT_MPEG4:
15637955f03dSHans Verkuil mode_flag = FLAG_MODE_MPEG4;
15647955f03dSHans Verkuil break;
15657955f03dSHans Verkuil default:
15667955f03dSHans Verkuil return -1;
15677955f03dSHans Verkuil }
15687955f03dSHans Verkuil if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) {
15697955f03dSHans Verkuil dev_err(go->dev,
15707955f03dSHans Verkuil "unable to load firmware from file \"%s\"\n",
15717955f03dSHans Verkuil GO7007_FW_NAME);
15727955f03dSHans Verkuil return -1;
15737955f03dSHans Verkuil }
15746396bb22SKees Cook code = kcalloc(codespace, 2, GFP_KERNEL);
15757955f03dSHans Verkuil if (code == NULL)
15767955f03dSHans Verkuil goto fw_failed;
15777955f03dSHans Verkuil
15787955f03dSHans Verkuil src = (__le16 *)fw_entry->data;
15797955f03dSHans Verkuil srclen = fw_entry->size / 2;
15807955f03dSHans Verkuil while (srclen >= 2) {
15817955f03dSHans Verkuil chunk_flags = __le16_to_cpu(src[0]);
15827955f03dSHans Verkuil chunk_len = __le16_to_cpu(src[1]);
15837955f03dSHans Verkuil if (chunk_len + 2 > srclen) {
15847955f03dSHans Verkuil dev_err(go->dev,
15857955f03dSHans Verkuil "firmware file \"%s\" appears to be corrupted\n",
15867955f03dSHans Verkuil GO7007_FW_NAME);
15877955f03dSHans Verkuil goto fw_failed;
15887955f03dSHans Verkuil }
15897955f03dSHans Verkuil if (chunk_flags & mode_flag) {
15907955f03dSHans Verkuil if (chunk_flags & FLAG_SPECIAL) {
15917955f03dSHans Verkuil ret = do_special(go, __le16_to_cpu(src[2]),
15927955f03dSHans Verkuil &code[i], codespace - i, framelen);
15937955f03dSHans Verkuil if (ret < 0) {
15947955f03dSHans Verkuil dev_err(go->dev,
15957955f03dSHans Verkuil "insufficient memory for firmware construction\n");
15967955f03dSHans Verkuil goto fw_failed;
15977955f03dSHans Verkuil }
15987955f03dSHans Verkuil i += ret;
15997955f03dSHans Verkuil } else {
16007955f03dSHans Verkuil if (codespace - i < chunk_len) {
16017955f03dSHans Verkuil dev_err(go->dev,
16027955f03dSHans Verkuil "insufficient memory for firmware construction\n");
16037955f03dSHans Verkuil goto fw_failed;
16047955f03dSHans Verkuil }
16057955f03dSHans Verkuil memcpy(&code[i], &src[2], chunk_len * 2);
16067955f03dSHans Verkuil i += chunk_len;
16077955f03dSHans Verkuil }
16087955f03dSHans Verkuil }
16097955f03dSHans Verkuil srclen -= chunk_len + 2;
16107955f03dSHans Verkuil src += chunk_len + 2;
16117955f03dSHans Verkuil }
16127955f03dSHans Verkuil release_firmware(fw_entry);
16137955f03dSHans Verkuil *fw = (u8 *)code;
16147955f03dSHans Verkuil *fwlen = i * 2;
16157955f03dSHans Verkuil return 0;
16167955f03dSHans Verkuil
16177955f03dSHans Verkuil fw_failed:
16187955f03dSHans Verkuil kfree(code);
16197955f03dSHans Verkuil release_firmware(fw_entry);
16207955f03dSHans Verkuil return -1;
16217955f03dSHans Verkuil }
16227955f03dSHans Verkuil
16237955f03dSHans Verkuil MODULE_FIRMWARE(GO7007_FW_NAME);
1624