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