18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006 Micronas USA Inc. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * This file contains code to generate a firmware image for the GO7007SB 88c2ecf20Sopenharmony_ci * encoder. Much of the firmware is read verbatim from a file, but some of 98c2ecf20Sopenharmony_ci * it concerning bitrate control and other things that can be configured at 108c2ecf20Sopenharmony_ci * run-time are generated dynamically. Note that the format headers 118c2ecf20Sopenharmony_ci * generated here do not affect the functioning of the encoder; they are 128c2ecf20Sopenharmony_ci * merely parroted back to the host at the start of each frame. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/time.h> 178c2ecf20Sopenharmony_ci#include <linux/mm.h> 188c2ecf20Sopenharmony_ci#include <linux/device.h> 198c2ecf20Sopenharmony_ci#include <linux/i2c.h> 208c2ecf20Sopenharmony_ci#include <linux/firmware.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "go7007-priv.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define GO7007_FW_NAME "go7007/go7007tv.bin" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* Constants used in the source firmware image to describe code segments */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define FLAG_MODE_MJPEG (1) 318c2ecf20Sopenharmony_ci#define FLAG_MODE_MPEG1 (1<<1) 328c2ecf20Sopenharmony_ci#define FLAG_MODE_MPEG2 (1<<2) 338c2ecf20Sopenharmony_ci#define FLAG_MODE_MPEG4 (1<<3) 348c2ecf20Sopenharmony_ci#define FLAG_MODE_H263 (1<<4) 358c2ecf20Sopenharmony_ci#define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \ 368c2ecf20Sopenharmony_ci FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \ 378c2ecf20Sopenharmony_ci FLAG_MODE_H263) 388c2ecf20Sopenharmony_ci#define FLAG_SPECIAL (1<<8) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define SPECIAL_FRM_HEAD 0 418c2ecf20Sopenharmony_ci#define SPECIAL_BRC_CTRL 1 428c2ecf20Sopenharmony_ci#define SPECIAL_CONFIG 2 438c2ecf20Sopenharmony_ci#define SPECIAL_SEQHEAD 3 448c2ecf20Sopenharmony_ci#define SPECIAL_AV_SYNC 4 458c2ecf20Sopenharmony_ci#define SPECIAL_FINAL 5 468c2ecf20Sopenharmony_ci#define SPECIAL_AUDIO 6 478c2ecf20Sopenharmony_ci#define SPECIAL_MODET 7 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* Little data class for creating MPEG headers bit-by-bit */ 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistruct code_gen { 528c2ecf20Sopenharmony_ci unsigned char *p; /* destination */ 538c2ecf20Sopenharmony_ci u32 a; /* collects bits at the top of the variable */ 548c2ecf20Sopenharmony_ci int b; /* bit position of most recently-written bit */ 558c2ecf20Sopenharmony_ci int len; /* written out so far */ 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define CODE_ADD(name, val, length) do { \ 618c2ecf20Sopenharmony_ci name.b -= (length); \ 628c2ecf20Sopenharmony_ci name.a |= (val) << name.b; \ 638c2ecf20Sopenharmony_ci while (name.b <= 24) { \ 648c2ecf20Sopenharmony_ci *name.p = name.a >> 24; \ 658c2ecf20Sopenharmony_ci ++name.p; \ 668c2ecf20Sopenharmony_ci name.a <<= 8; \ 678c2ecf20Sopenharmony_ci name.b += 8; \ 688c2ecf20Sopenharmony_ci name.len += 8; \ 698c2ecf20Sopenharmony_ci } \ 708c2ecf20Sopenharmony_ci} while (0) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define CODE_LENGTH(name) (name.len + (32 - name.b)) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* Tables for creating the bitrate control data */ 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic const s16 converge_speed_ip[101] = { 778c2ecf20Sopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 788c2ecf20Sopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 798c2ecf20Sopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 808c2ecf20Sopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 818c2ecf20Sopenharmony_ci 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 828c2ecf20Sopenharmony_ci 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 838c2ecf20Sopenharmony_ci 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 848c2ecf20Sopenharmony_ci 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 858c2ecf20Sopenharmony_ci 19, 20, 22, 23, 25, 27, 30, 32, 35, 38, 868c2ecf20Sopenharmony_ci 41, 45, 49, 53, 58, 63, 69, 76, 83, 91, 878c2ecf20Sopenharmony_ci 100 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic const s16 converge_speed_ipb[101] = { 918c2ecf20Sopenharmony_ci 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 928c2ecf20Sopenharmony_ci 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 938c2ecf20Sopenharmony_ci 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 948c2ecf20Sopenharmony_ci 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 958c2ecf20Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, 968c2ecf20Sopenharmony_ci 9, 9, 10, 10, 11, 12, 12, 13, 14, 14, 978c2ecf20Sopenharmony_ci 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 988c2ecf20Sopenharmony_ci 28, 30, 32, 34, 37, 40, 42, 46, 49, 53, 998c2ecf20Sopenharmony_ci 57, 61, 66, 71, 77, 83, 90, 97, 106, 115, 1008c2ecf20Sopenharmony_ci 125, 135, 147, 161, 175, 191, 209, 228, 249, 273, 1018c2ecf20Sopenharmony_ci 300 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic const s16 LAMBDA_table[4][101] = { 1058c2ecf20Sopenharmony_ci { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 1068c2ecf20Sopenharmony_ci 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 1078c2ecf20Sopenharmony_ci 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, 1088c2ecf20Sopenharmony_ci 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, 1098c2ecf20Sopenharmony_ci 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, 1108c2ecf20Sopenharmony_ci 39, 39, 40, 41, 42, 42, 43, 44, 45, 46, 1118c2ecf20Sopenharmony_ci 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 1128c2ecf20Sopenharmony_ci 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 1138c2ecf20Sopenharmony_ci 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 1148c2ecf20Sopenharmony_ci 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 1158c2ecf20Sopenharmony_ci 96 1168c2ecf20Sopenharmony_ci }, 1178c2ecf20Sopenharmony_ci { 1188c2ecf20Sopenharmony_ci 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, 1198c2ecf20Sopenharmony_ci 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 1208c2ecf20Sopenharmony_ci 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, 1218c2ecf20Sopenharmony_ci 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 1228c2ecf20Sopenharmony_ci 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 1238c2ecf20Sopenharmony_ci 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 1248c2ecf20Sopenharmony_ci 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, 1258c2ecf20Sopenharmony_ci 70, 71, 72, 73, 75, 76, 78, 79, 80, 82, 1268c2ecf20Sopenharmony_ci 83, 85, 86, 88, 90, 91, 93, 95, 96, 98, 1278c2ecf20Sopenharmony_ci 100, 102, 103, 105, 107, 109, 111, 113, 115, 117, 1288c2ecf20Sopenharmony_ci 120 1298c2ecf20Sopenharmony_ci }, 1308c2ecf20Sopenharmony_ci { 1318c2ecf20Sopenharmony_ci 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, 1328c2ecf20Sopenharmony_ci 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, 1338c2ecf20Sopenharmony_ci 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 1348c2ecf20Sopenharmony_ci 41, 41, 42, 43, 44, 44, 45, 46, 47, 48, 1358c2ecf20Sopenharmony_ci 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, 1368c2ecf20Sopenharmony_ci 58, 59, 60, 62, 63, 64, 65, 66, 67, 69, 1378c2ecf20Sopenharmony_ci 70, 71, 72, 74, 75, 76, 78, 79, 81, 82, 1388c2ecf20Sopenharmony_ci 84, 85, 87, 88, 90, 92, 93, 95, 97, 98, 1398c2ecf20Sopenharmony_ci 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 1408c2ecf20Sopenharmony_ci 120, 122, 124, 127, 129, 131, 134, 136, 138, 141, 1418c2ecf20Sopenharmony_ci 144 1428c2ecf20Sopenharmony_ci }, 1438c2ecf20Sopenharmony_ci { 1448c2ecf20Sopenharmony_ci 32, 32, 33, 33, 34, 34, 35, 36, 36, 37, 1458c2ecf20Sopenharmony_ci 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, 1468c2ecf20Sopenharmony_ci 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 1478c2ecf20Sopenharmony_ci 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, 1488c2ecf20Sopenharmony_ci 65, 66, 67, 69, 70, 71, 72, 74, 75, 76, 1498c2ecf20Sopenharmony_ci 78, 79, 81, 82, 84, 85, 87, 88, 90, 92, 1508c2ecf20Sopenharmony_ci 93, 95, 97, 98, 100, 102, 104, 106, 108, 110, 1518c2ecf20Sopenharmony_ci 112, 114, 116, 118, 120, 122, 124, 127, 129, 131, 1528c2ecf20Sopenharmony_ci 134, 136, 139, 141, 144, 146, 149, 152, 154, 157, 1538c2ecf20Sopenharmony_ci 160, 163, 166, 169, 172, 175, 178, 181, 185, 188, 1548c2ecf20Sopenharmony_ci 192 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* MPEG blank frame generation tables */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cienum mpeg_frame_type { 1618c2ecf20Sopenharmony_ci PFRAME, 1628c2ecf20Sopenharmony_ci BFRAME_PRE, 1638c2ecf20Sopenharmony_ci BFRAME_POST, 1648c2ecf20Sopenharmony_ci BFRAME_BIDIR, 1658c2ecf20Sopenharmony_ci BFRAME_EMPTY 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic const u32 addrinctab[33][2] = { 1698c2ecf20Sopenharmony_ci { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 }, 1708c2ecf20Sopenharmony_ci { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 }, 1718c2ecf20Sopenharmony_ci { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 }, 1728c2ecf20Sopenharmony_ci { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 }, 1738c2ecf20Sopenharmony_ci { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 }, 1748c2ecf20Sopenharmony_ci { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 }, 1758c2ecf20Sopenharmony_ci { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 }, 1768c2ecf20Sopenharmony_ci { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 }, 1778c2ecf20Sopenharmony_ci { 0x18, 11 } 1788c2ecf20Sopenharmony_ci}; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* Standard JPEG tables */ 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic const u8 default_intra_quant_table[] = { 1838c2ecf20Sopenharmony_ci 8, 16, 19, 22, 26, 27, 29, 34, 1848c2ecf20Sopenharmony_ci 16, 16, 22, 24, 27, 29, 34, 37, 1858c2ecf20Sopenharmony_ci 19, 22, 26, 27, 29, 34, 34, 38, 1868c2ecf20Sopenharmony_ci 22, 22, 26, 27, 29, 34, 37, 40, 1878c2ecf20Sopenharmony_ci 22, 26, 27, 29, 32, 35, 40, 48, 1888c2ecf20Sopenharmony_ci 26, 27, 29, 32, 35, 40, 48, 58, 1898c2ecf20Sopenharmony_ci 26, 27, 29, 34, 38, 46, 56, 69, 1908c2ecf20Sopenharmony_ci 27, 29, 35, 38, 46, 56, 69, 83 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic const u8 bits_dc_luminance[] = { 1948c2ecf20Sopenharmony_ci 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic const u8 val_dc_luminance[] = { 1988c2ecf20Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic const u8 bits_dc_chrominance[] = { 2028c2ecf20Sopenharmony_ci 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic const u8 val_dc_chrominance[] = { 2068c2ecf20Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 2078c2ecf20Sopenharmony_ci}; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic const u8 bits_ac_luminance[] = { 2108c2ecf20Sopenharmony_ci 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d 2118c2ecf20Sopenharmony_ci}; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic const u8 val_ac_luminance[] = { 2148c2ecf20Sopenharmony_ci 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 2158c2ecf20Sopenharmony_ci 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 2168c2ecf20Sopenharmony_ci 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 2178c2ecf20Sopenharmony_ci 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 2188c2ecf20Sopenharmony_ci 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 2198c2ecf20Sopenharmony_ci 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 2208c2ecf20Sopenharmony_ci 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 2218c2ecf20Sopenharmony_ci 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 2228c2ecf20Sopenharmony_ci 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 2238c2ecf20Sopenharmony_ci 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 2248c2ecf20Sopenharmony_ci 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 2258c2ecf20Sopenharmony_ci 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 2268c2ecf20Sopenharmony_ci 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 2278c2ecf20Sopenharmony_ci 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 2288c2ecf20Sopenharmony_ci 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 2298c2ecf20Sopenharmony_ci 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 2308c2ecf20Sopenharmony_ci 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 2318c2ecf20Sopenharmony_ci 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 2328c2ecf20Sopenharmony_ci 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 2338c2ecf20Sopenharmony_ci 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 2348c2ecf20Sopenharmony_ci 0xf9, 0xfa 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic const u8 bits_ac_chrominance[] = { 2388c2ecf20Sopenharmony_ci 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const u8 val_ac_chrominance[] = { 2428c2ecf20Sopenharmony_ci 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 2438c2ecf20Sopenharmony_ci 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 2448c2ecf20Sopenharmony_ci 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 2458c2ecf20Sopenharmony_ci 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 2468c2ecf20Sopenharmony_ci 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 2478c2ecf20Sopenharmony_ci 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 2488c2ecf20Sopenharmony_ci 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 2498c2ecf20Sopenharmony_ci 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 2508c2ecf20Sopenharmony_ci 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 2518c2ecf20Sopenharmony_ci 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 2528c2ecf20Sopenharmony_ci 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 2538c2ecf20Sopenharmony_ci 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 2548c2ecf20Sopenharmony_ci 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 2558c2ecf20Sopenharmony_ci 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 2568c2ecf20Sopenharmony_ci 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 2578c2ecf20Sopenharmony_ci 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 2588c2ecf20Sopenharmony_ci 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 2598c2ecf20Sopenharmony_ci 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 2608c2ecf20Sopenharmony_ci 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 2618c2ecf20Sopenharmony_ci 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 2628c2ecf20Sopenharmony_ci 0xf9, 0xfa 2638c2ecf20Sopenharmony_ci}; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci/* Zig-zag mapping for quant table 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci * OK, let's do this mapping on the actual table above so it doesn't have 2688c2ecf20Sopenharmony_ci * to be done on the fly. 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_cistatic const int zz[64] = { 2718c2ecf20Sopenharmony_ci 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 2728c2ecf20Sopenharmony_ci 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 2738c2ecf20Sopenharmony_ci 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 2748c2ecf20Sopenharmony_ci 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 2758c2ecf20Sopenharmony_ci}; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci int i, cnt = pkg_cnt * 32; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (space < cnt) 2828c2ecf20Sopenharmony_ci return -1; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci for (i = 0; i < cnt; ++i) 2858c2ecf20Sopenharmony_ci dest[i] = cpu_to_le16p(src + i); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci return cnt; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci int i, p = 0; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci buf[p++] = 0xff; 2958c2ecf20Sopenharmony_ci buf[p++] = 0xd8; 2968c2ecf20Sopenharmony_ci buf[p++] = 0xff; 2978c2ecf20Sopenharmony_ci buf[p++] = 0xdb; 2988c2ecf20Sopenharmony_ci buf[p++] = 0; 2998c2ecf20Sopenharmony_ci buf[p++] = 2 + 65; 3008c2ecf20Sopenharmony_ci buf[p++] = 0; 3018c2ecf20Sopenharmony_ci buf[p++] = default_intra_quant_table[0]; 3028c2ecf20Sopenharmony_ci for (i = 1; i < 64; ++i) 3038c2ecf20Sopenharmony_ci /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */ 3048c2ecf20Sopenharmony_ci buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3; 3058c2ecf20Sopenharmony_ci buf[p++] = 0xff; 3068c2ecf20Sopenharmony_ci buf[p++] = 0xc0; 3078c2ecf20Sopenharmony_ci buf[p++] = 0; 3088c2ecf20Sopenharmony_ci buf[p++] = 17; 3098c2ecf20Sopenharmony_ci buf[p++] = 8; 3108c2ecf20Sopenharmony_ci buf[p++] = go->height >> 8; 3118c2ecf20Sopenharmony_ci buf[p++] = go->height & 0xff; 3128c2ecf20Sopenharmony_ci buf[p++] = go->width >> 8; 3138c2ecf20Sopenharmony_ci buf[p++] = go->width & 0xff; 3148c2ecf20Sopenharmony_ci buf[p++] = 3; 3158c2ecf20Sopenharmony_ci buf[p++] = 1; 3168c2ecf20Sopenharmony_ci buf[p++] = 0x22; 3178c2ecf20Sopenharmony_ci buf[p++] = 0; 3188c2ecf20Sopenharmony_ci buf[p++] = 2; 3198c2ecf20Sopenharmony_ci buf[p++] = 0x11; 3208c2ecf20Sopenharmony_ci buf[p++] = 0; 3218c2ecf20Sopenharmony_ci buf[p++] = 3; 3228c2ecf20Sopenharmony_ci buf[p++] = 0x11; 3238c2ecf20Sopenharmony_ci buf[p++] = 0; 3248c2ecf20Sopenharmony_ci buf[p++] = 0xff; 3258c2ecf20Sopenharmony_ci buf[p++] = 0xc4; 3268c2ecf20Sopenharmony_ci buf[p++] = 418 >> 8; 3278c2ecf20Sopenharmony_ci buf[p++] = 418 & 0xff; 3288c2ecf20Sopenharmony_ci buf[p++] = 0x00; 3298c2ecf20Sopenharmony_ci memcpy(buf + p, bits_dc_luminance + 1, 16); 3308c2ecf20Sopenharmony_ci p += 16; 3318c2ecf20Sopenharmony_ci memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance)); 3328c2ecf20Sopenharmony_ci p += sizeof(val_dc_luminance); 3338c2ecf20Sopenharmony_ci buf[p++] = 0x01; 3348c2ecf20Sopenharmony_ci memcpy(buf + p, bits_dc_chrominance + 1, 16); 3358c2ecf20Sopenharmony_ci p += 16; 3368c2ecf20Sopenharmony_ci memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance)); 3378c2ecf20Sopenharmony_ci p += sizeof(val_dc_chrominance); 3388c2ecf20Sopenharmony_ci buf[p++] = 0x10; 3398c2ecf20Sopenharmony_ci memcpy(buf + p, bits_ac_luminance + 1, 16); 3408c2ecf20Sopenharmony_ci p += 16; 3418c2ecf20Sopenharmony_ci memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance)); 3428c2ecf20Sopenharmony_ci p += sizeof(val_ac_luminance); 3438c2ecf20Sopenharmony_ci buf[p++] = 0x11; 3448c2ecf20Sopenharmony_ci memcpy(buf + p, bits_ac_chrominance + 1, 16); 3458c2ecf20Sopenharmony_ci p += 16; 3468c2ecf20Sopenharmony_ci memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance)); 3478c2ecf20Sopenharmony_ci p += sizeof(val_ac_chrominance); 3488c2ecf20Sopenharmony_ci buf[p++] = 0xff; 3498c2ecf20Sopenharmony_ci buf[p++] = 0xda; 3508c2ecf20Sopenharmony_ci buf[p++] = 0; 3518c2ecf20Sopenharmony_ci buf[p++] = 12; 3528c2ecf20Sopenharmony_ci buf[p++] = 3; 3538c2ecf20Sopenharmony_ci buf[p++] = 1; 3548c2ecf20Sopenharmony_ci buf[p++] = 0x00; 3558c2ecf20Sopenharmony_ci buf[p++] = 2; 3568c2ecf20Sopenharmony_ci buf[p++] = 0x11; 3578c2ecf20Sopenharmony_ci buf[p++] = 3; 3588c2ecf20Sopenharmony_ci buf[p++] = 0x11; 3598c2ecf20Sopenharmony_ci buf[p++] = 0; 3608c2ecf20Sopenharmony_ci buf[p++] = 63; 3618c2ecf20Sopenharmony_ci buf[p++] = 0; 3628c2ecf20Sopenharmony_ci return p; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci u8 *buf; 3688c2ecf20Sopenharmony_ci u16 mem = 0x3e00; 3698c2ecf20Sopenharmony_ci unsigned int addr = 0x19; 3708c2ecf20Sopenharmony_ci int size = 0, i, off = 0, chunk; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci buf = kzalloc(4096, GFP_KERNEL); 3738c2ecf20Sopenharmony_ci if (buf == NULL) 3748c2ecf20Sopenharmony_ci return -ENOMEM; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci for (i = 1; i < 32; ++i) { 3778c2ecf20Sopenharmony_ci mjpeg_frame_header(go, buf + size, i); 3788c2ecf20Sopenharmony_ci size += 80; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci chunk = mjpeg_frame_header(go, buf + size, 1); 3818c2ecf20Sopenharmony_ci memmove(buf + size, buf + size + 80, chunk - 80); 3828c2ecf20Sopenharmony_ci size += chunk - 80; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci for (i = 0; i < size; i += chunk * 2) { 3858c2ecf20Sopenharmony_ci if (space - off < 32) { 3868c2ecf20Sopenharmony_ci off = -1; 3878c2ecf20Sopenharmony_ci goto done; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci code[off + 1] = __cpu_to_le16(0x8000 | mem); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci chunk = 28; 3938c2ecf20Sopenharmony_ci if (mem + chunk > 0x4000) 3948c2ecf20Sopenharmony_ci chunk = 0x4000 - mem; 3958c2ecf20Sopenharmony_ci if (i + 2 * chunk > size) 3968c2ecf20Sopenharmony_ci chunk = (size - i) / 2; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (chunk < 28) { 3998c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x4000 | chunk); 4008c2ecf20Sopenharmony_ci code[off + 31] = __cpu_to_le16(addr++); 4018c2ecf20Sopenharmony_ci mem = 0x3e00; 4028c2ecf20Sopenharmony_ci } else { 4038c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x1000 | 28); 4048c2ecf20Sopenharmony_ci code[off + 31] = 0; 4058c2ecf20Sopenharmony_ci mem += 28; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci memcpy(&code[off + 2], buf + i, chunk * 2); 4098c2ecf20Sopenharmony_ci off += 32; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_cidone: 4128c2ecf20Sopenharmony_ci kfree(buf); 4138c2ecf20Sopenharmony_ci return off; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic int mpeg1_frame_header(struct go7007 *go, unsigned char *buf, 4178c2ecf20Sopenharmony_ci int modulo, int pict_struct, enum mpeg_frame_type frame) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci int i, j, mb_code, mb_len; 4208c2ecf20Sopenharmony_ci int rows = go->interlace_coding ? go->height / 32 : go->height / 16; 4218c2ecf20Sopenharmony_ci CODE_GEN(c, buf + 6); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci switch (frame) { 4248c2ecf20Sopenharmony_ci case PFRAME: 4258c2ecf20Sopenharmony_ci mb_code = 0x1; 4268c2ecf20Sopenharmony_ci mb_len = 3; 4278c2ecf20Sopenharmony_ci break; 4288c2ecf20Sopenharmony_ci case BFRAME_PRE: 4298c2ecf20Sopenharmony_ci mb_code = 0x2; 4308c2ecf20Sopenharmony_ci mb_len = 4; 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci case BFRAME_POST: 4338c2ecf20Sopenharmony_ci mb_code = 0x2; 4348c2ecf20Sopenharmony_ci mb_len = 3; 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci case BFRAME_BIDIR: 4378c2ecf20Sopenharmony_ci mb_code = 0x2; 4388c2ecf20Sopenharmony_ci mb_len = 2; 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci default: /* keep the compiler happy */ 4418c2ecf20Sopenharmony_ci mb_code = mb_len = 0; 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13); 4468c2ecf20Sopenharmony_ci CODE_ADD(c, 0xffff, 16); 4478c2ecf20Sopenharmony_ci CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); 4488c2ecf20Sopenharmony_ci if (frame != PFRAME) 4498c2ecf20Sopenharmony_ci CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); 4508c2ecf20Sopenharmony_ci else 4518c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */ 4528c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 3); /* What is this?? */ 4538c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 4548c2ecf20Sopenharmony_ci j = 8 - (CODE_LENGTH(c) % 8); 4558c2ecf20Sopenharmony_ci if (j != 8) 4568c2ecf20Sopenharmony_ci CODE_ADD(c, 0, j); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci if (go->format == V4L2_PIX_FMT_MPEG2) { 4598c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 24); 4608c2ecf20Sopenharmony_ci CODE_ADD(c, 0xb5, 8); 4618c2ecf20Sopenharmony_ci CODE_ADD(c, 0x844, 12); 4628c2ecf20Sopenharmony_ci CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8); 4638c2ecf20Sopenharmony_ci if (go->interlace_coding) { 4648c2ecf20Sopenharmony_ci CODE_ADD(c, pict_struct, 4); 4658c2ecf20Sopenharmony_ci if (go->dvd_mode) 4668c2ecf20Sopenharmony_ci CODE_ADD(c, 0x000, 11); 4678c2ecf20Sopenharmony_ci else 4688c2ecf20Sopenharmony_ci CODE_ADD(c, 0x200, 11); 4698c2ecf20Sopenharmony_ci } else { 4708c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 4); 4718c2ecf20Sopenharmony_ci CODE_ADD(c, 0x20c, 11); 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 4748c2ecf20Sopenharmony_ci j = 8 - (CODE_LENGTH(c) % 8); 4758c2ecf20Sopenharmony_ci if (j != 8) 4768c2ecf20Sopenharmony_ci CODE_ADD(c, 0, j); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci for (i = 0; i < rows; ++i) { 4808c2ecf20Sopenharmony_ci CODE_ADD(c, 1, 24); 4818c2ecf20Sopenharmony_ci CODE_ADD(c, i + 1, 8); 4828c2ecf20Sopenharmony_ci CODE_ADD(c, 0x2, 6); 4838c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 1); 4848c2ecf20Sopenharmony_ci CODE_ADD(c, mb_code, mb_len); 4858c2ecf20Sopenharmony_ci if (go->interlace_coding) { 4868c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 2); 4878c2ecf20Sopenharmony_ci CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci if (frame == BFRAME_BIDIR) { 4908c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 4918c2ecf20Sopenharmony_ci if (go->interlace_coding) 4928c2ecf20Sopenharmony_ci CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 4958c2ecf20Sopenharmony_ci for (j = (go->width >> 4) - 2; j >= 33; j -= 33) 4968c2ecf20Sopenharmony_ci CODE_ADD(c, 0x8, 11); 4978c2ecf20Sopenharmony_ci CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]); 4988c2ecf20Sopenharmony_ci CODE_ADD(c, mb_code, mb_len); 4998c2ecf20Sopenharmony_ci if (go->interlace_coding) { 5008c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 2); 5018c2ecf20Sopenharmony_ci CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci if (frame == BFRAME_BIDIR) { 5048c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 5058c2ecf20Sopenharmony_ci if (go->interlace_coding) 5068c2ecf20Sopenharmony_ci CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 5118c2ecf20Sopenharmony_ci j = 8 - (CODE_LENGTH(c) % 8); 5128c2ecf20Sopenharmony_ci if (j != 8) 5138c2ecf20Sopenharmony_ci CODE_ADD(c, 0, j); 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci i = CODE_LENGTH(c) + 4 * 8; 5178c2ecf20Sopenharmony_ci buf[2] = 0x00; 5188c2ecf20Sopenharmony_ci buf[3] = 0x00; 5198c2ecf20Sopenharmony_ci buf[4] = 0x01; 5208c2ecf20Sopenharmony_ci buf[5] = 0x00; 5218c2ecf20Sopenharmony_ci return i; 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci int i, aspect_ratio, picture_rate; 5278c2ecf20Sopenharmony_ci CODE_GEN(c, buf + 6); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci if (go->format == V4L2_PIX_FMT_MPEG1) { 5308c2ecf20Sopenharmony_ci switch (go->aspect_ratio) { 5318c2ecf20Sopenharmony_ci case GO7007_RATIO_4_3: 5328c2ecf20Sopenharmony_ci aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci case GO7007_RATIO_16_9: 5358c2ecf20Sopenharmony_ci aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; 5368c2ecf20Sopenharmony_ci break; 5378c2ecf20Sopenharmony_ci default: 5388c2ecf20Sopenharmony_ci aspect_ratio = 1; 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci } else { 5428c2ecf20Sopenharmony_ci switch (go->aspect_ratio) { 5438c2ecf20Sopenharmony_ci case GO7007_RATIO_4_3: 5448c2ecf20Sopenharmony_ci aspect_ratio = 2; 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci case GO7007_RATIO_16_9: 5478c2ecf20Sopenharmony_ci aspect_ratio = 3; 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci default: 5508c2ecf20Sopenharmony_ci aspect_ratio = 1; 5518c2ecf20Sopenharmony_ci break; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci switch (go->sensor_framerate) { 5558c2ecf20Sopenharmony_ci case 24000: 5568c2ecf20Sopenharmony_ci picture_rate = 1; 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case 24024: 5598c2ecf20Sopenharmony_ci picture_rate = 2; 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci case 25025: 5628c2ecf20Sopenharmony_ci picture_rate = go->interlace_coding ? 6 : 3; 5638c2ecf20Sopenharmony_ci break; 5648c2ecf20Sopenharmony_ci case 30000: 5658c2ecf20Sopenharmony_ci picture_rate = go->interlace_coding ? 7 : 4; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci case 30030: 5688c2ecf20Sopenharmony_ci picture_rate = go->interlace_coding ? 8 : 5; 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci default: 5718c2ecf20Sopenharmony_ci picture_rate = 5; /* 30 fps seems like a reasonable default */ 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci CODE_ADD(c, go->width, 12); 5768c2ecf20Sopenharmony_ci CODE_ADD(c, go->height, 12); 5778c2ecf20Sopenharmony_ci CODE_ADD(c, aspect_ratio, 4); 5788c2ecf20Sopenharmony_ci CODE_ADD(c, picture_rate, 4); 5798c2ecf20Sopenharmony_ci CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18); 5808c2ecf20Sopenharmony_ci CODE_ADD(c, 1, 1); 5818c2ecf20Sopenharmony_ci CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10); 5828c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 3); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 5858c2ecf20Sopenharmony_ci i = 8 - (CODE_LENGTH(c) % 8); 5868c2ecf20Sopenharmony_ci if (i != 8) 5878c2ecf20Sopenharmony_ci CODE_ADD(c, 0, i); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (go->format == V4L2_PIX_FMT_MPEG2) { 5908c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 24); 5918c2ecf20Sopenharmony_ci CODE_ADD(c, 0xb5, 8); 5928c2ecf20Sopenharmony_ci CODE_ADD(c, 0x148, 12); 5938c2ecf20Sopenharmony_ci if (go->interlace_coding) 5948c2ecf20Sopenharmony_ci CODE_ADD(c, 0x20001, 20); 5958c2ecf20Sopenharmony_ci else 5968c2ecf20Sopenharmony_ci CODE_ADD(c, 0xa0001, 20); 5978c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 16); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 6008c2ecf20Sopenharmony_ci i = 8 - (CODE_LENGTH(c) % 8); 6018c2ecf20Sopenharmony_ci if (i != 8) 6028c2ecf20Sopenharmony_ci CODE_ADD(c, 0, i); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci if (ext) { 6058c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 24); 6068c2ecf20Sopenharmony_ci CODE_ADD(c, 0xb52, 12); 6078c2ecf20Sopenharmony_ci CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3); 6088c2ecf20Sopenharmony_ci CODE_ADD(c, 0x105, 9); 6098c2ecf20Sopenharmony_ci CODE_ADD(c, 0x505, 16); 6108c2ecf20Sopenharmony_ci CODE_ADD(c, go->width, 14); 6118c2ecf20Sopenharmony_ci CODE_ADD(c, 1, 1); 6128c2ecf20Sopenharmony_ci CODE_ADD(c, go->height, 14); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* Byte-align with zeros */ 6158c2ecf20Sopenharmony_ci i = 8 - (CODE_LENGTH(c) % 8); 6168c2ecf20Sopenharmony_ci if (i != 8) 6178c2ecf20Sopenharmony_ci CODE_ADD(c, 0, i); 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci i = CODE_LENGTH(c) + 4 * 8; 6228c2ecf20Sopenharmony_ci buf[0] = i & 0xff; 6238c2ecf20Sopenharmony_ci buf[1] = i >> 8; 6248c2ecf20Sopenharmony_ci buf[2] = 0x00; 6258c2ecf20Sopenharmony_ci buf[3] = 0x00; 6268c2ecf20Sopenharmony_ci buf[4] = 0x01; 6278c2ecf20Sopenharmony_ci buf[5] = 0xb3; 6288c2ecf20Sopenharmony_ci return i; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int gen_mpeg1hdr_to_package(struct go7007 *go, 6328c2ecf20Sopenharmony_ci __le16 *code, int space, int *framelen) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci u8 *buf; 6358c2ecf20Sopenharmony_ci u16 mem = 0x3e00; 6368c2ecf20Sopenharmony_ci unsigned int addr = 0x19; 6378c2ecf20Sopenharmony_ci int i, off = 0, chunk; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci buf = kzalloc(5120, GFP_KERNEL); 6408c2ecf20Sopenharmony_ci if (buf == NULL) 6418c2ecf20Sopenharmony_ci return -ENOMEM; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME); 6448c2ecf20Sopenharmony_ci if (go->interlace_coding) 6458c2ecf20Sopenharmony_ci framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8, 6468c2ecf20Sopenharmony_ci 0, 2, PFRAME); 6478c2ecf20Sopenharmony_ci buf[0] = framelen[0] & 0xff; 6488c2ecf20Sopenharmony_ci buf[1] = framelen[0] >> 8; 6498c2ecf20Sopenharmony_ci i = 368; 6508c2ecf20Sopenharmony_ci framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE); 6518c2ecf20Sopenharmony_ci if (go->interlace_coding) 6528c2ecf20Sopenharmony_ci framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8, 6538c2ecf20Sopenharmony_ci 0, 2, BFRAME_PRE); 6548c2ecf20Sopenharmony_ci buf[i] = framelen[1] & 0xff; 6558c2ecf20Sopenharmony_ci buf[i + 1] = framelen[1] >> 8; 6568c2ecf20Sopenharmony_ci i += 1632; 6578c2ecf20Sopenharmony_ci framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST); 6588c2ecf20Sopenharmony_ci if (go->interlace_coding) 6598c2ecf20Sopenharmony_ci framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8, 6608c2ecf20Sopenharmony_ci 0, 2, BFRAME_POST); 6618c2ecf20Sopenharmony_ci buf[i] = framelen[2] & 0xff; 6628c2ecf20Sopenharmony_ci buf[i + 1] = framelen[2] >> 8; 6638c2ecf20Sopenharmony_ci i += 1432; 6648c2ecf20Sopenharmony_ci framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR); 6658c2ecf20Sopenharmony_ci if (go->interlace_coding) 6668c2ecf20Sopenharmony_ci framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8, 6678c2ecf20Sopenharmony_ci 0, 2, BFRAME_BIDIR); 6688c2ecf20Sopenharmony_ci buf[i] = framelen[3] & 0xff; 6698c2ecf20Sopenharmony_ci buf[i + 1] = framelen[3] >> 8; 6708c2ecf20Sopenharmony_ci i += 1632 + 16; 6718c2ecf20Sopenharmony_ci mpeg1_sequence_header(go, buf + i, 0); 6728c2ecf20Sopenharmony_ci i += 40; 6738c2ecf20Sopenharmony_ci for (i = 0; i < 5120; i += chunk * 2) { 6748c2ecf20Sopenharmony_ci if (space - off < 32) { 6758c2ecf20Sopenharmony_ci off = -1; 6768c2ecf20Sopenharmony_ci goto done; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci code[off + 1] = __cpu_to_le16(0x8000 | mem); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci chunk = 28; 6828c2ecf20Sopenharmony_ci if (mem + chunk > 0x4000) 6838c2ecf20Sopenharmony_ci chunk = 0x4000 - mem; 6848c2ecf20Sopenharmony_ci if (i + 2 * chunk > 5120) 6858c2ecf20Sopenharmony_ci chunk = (5120 - i) / 2; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (chunk < 28) { 6888c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x4000 | chunk); 6898c2ecf20Sopenharmony_ci code[off + 31] = __cpu_to_le16(addr); 6908c2ecf20Sopenharmony_ci if (mem + chunk == 0x4000) { 6918c2ecf20Sopenharmony_ci mem = 0x3e00; 6928c2ecf20Sopenharmony_ci ++addr; 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci } else { 6958c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x1000 | 28); 6968c2ecf20Sopenharmony_ci code[off + 31] = 0; 6978c2ecf20Sopenharmony_ci mem += 28; 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci memcpy(&code[off + 2], buf + i, chunk * 2); 7018c2ecf20Sopenharmony_ci off += 32; 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_cidone: 7048c2ecf20Sopenharmony_ci kfree(buf); 7058c2ecf20Sopenharmony_ci return off; 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic int vti_bitlen(struct go7007 *go) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i) 7138c2ecf20Sopenharmony_ci ; 7148c2ecf20Sopenharmony_ci return i + 1; 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistatic int mpeg4_frame_header(struct go7007 *go, unsigned char *buf, 7188c2ecf20Sopenharmony_ci int modulo, enum mpeg_frame_type frame) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci int i; 7218c2ecf20Sopenharmony_ci CODE_GEN(c, buf + 6); 7228c2ecf20Sopenharmony_ci int mb_count = (go->width >> 4) * (go->height >> 4); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2); 7258c2ecf20Sopenharmony_ci if (modulo) 7268c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 1); 7278c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 2); 7288c2ecf20Sopenharmony_ci CODE_ADD(c, 0, vti_bitlen(go)); 7298c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 7308c2ecf20Sopenharmony_ci if (frame == PFRAME) 7318c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 1); 7328c2ecf20Sopenharmony_ci CODE_ADD(c, 0xc, 11); 7338c2ecf20Sopenharmony_ci if (frame != PFRAME) 7348c2ecf20Sopenharmony_ci CODE_ADD(c, 0x4, 3); 7358c2ecf20Sopenharmony_ci if (frame != BFRAME_EMPTY) { 7368c2ecf20Sopenharmony_ci for (i = 0; i < mb_count; ++i) { 7378c2ecf20Sopenharmony_ci switch (frame) { 7388c2ecf20Sopenharmony_ci case PFRAME: 7398c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 1); 7408c2ecf20Sopenharmony_ci break; 7418c2ecf20Sopenharmony_ci case BFRAME_PRE: 7428c2ecf20Sopenharmony_ci CODE_ADD(c, 0x47, 8); 7438c2ecf20Sopenharmony_ci break; 7448c2ecf20Sopenharmony_ci case BFRAME_POST: 7458c2ecf20Sopenharmony_ci CODE_ADD(c, 0x27, 7); 7468c2ecf20Sopenharmony_ci break; 7478c2ecf20Sopenharmony_ci case BFRAME_BIDIR: 7488c2ecf20Sopenharmony_ci CODE_ADD(c, 0x5f, 8); 7498c2ecf20Sopenharmony_ci break; 7508c2ecf20Sopenharmony_ci case BFRAME_EMPTY: /* keep compiler quiet */ 7518c2ecf20Sopenharmony_ci break; 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* Byte-align with a zero followed by ones */ 7578c2ecf20Sopenharmony_ci i = 8 - (CODE_LENGTH(c) % 8); 7588c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 1); 7598c2ecf20Sopenharmony_ci CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci i = CODE_LENGTH(c) + 4 * 8; 7628c2ecf20Sopenharmony_ci buf[0] = i & 0xff; 7638c2ecf20Sopenharmony_ci buf[1] = i >> 8; 7648c2ecf20Sopenharmony_ci buf[2] = 0x00; 7658c2ecf20Sopenharmony_ci buf[3] = 0x00; 7668c2ecf20Sopenharmony_ci buf[4] = 0x01; 7678c2ecf20Sopenharmony_ci buf[5] = 0xb6; 7688c2ecf20Sopenharmony_ci return i; 7698c2ecf20Sopenharmony_ci} 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_cistatic int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali, 7748c2ecf20Sopenharmony_ci 0x00, 0x00, 0x01, 0xb5, 0x09, 7758c2ecf20Sopenharmony_ci 0x00, 0x00, 0x01, 0x00, 7768c2ecf20Sopenharmony_ci 0x00, 0x00, 0x01, 0x20, }; 7778c2ecf20Sopenharmony_ci int i, aspect_ratio; 7788c2ecf20Sopenharmony_ci int fps = go->sensor_framerate / go->fps_scale; 7798c2ecf20Sopenharmony_ci CODE_GEN(c, buf + 2 + sizeof(head)); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci switch (go->aspect_ratio) { 7828c2ecf20Sopenharmony_ci case GO7007_RATIO_4_3: 7838c2ecf20Sopenharmony_ci aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; 7848c2ecf20Sopenharmony_ci break; 7858c2ecf20Sopenharmony_ci case GO7007_RATIO_16_9: 7868c2ecf20Sopenharmony_ci aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; 7878c2ecf20Sopenharmony_ci break; 7888c2ecf20Sopenharmony_ci default: 7898c2ecf20Sopenharmony_ci aspect_ratio = 1; 7908c2ecf20Sopenharmony_ci break; 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci memcpy(buf + 2, head, sizeof(head)); 7948c2ecf20Sopenharmony_ci CODE_ADD(c, 0x191, 17); 7958c2ecf20Sopenharmony_ci CODE_ADD(c, aspect_ratio, 4); 7968c2ecf20Sopenharmony_ci CODE_ADD(c, 0x1, 4); 7978c2ecf20Sopenharmony_ci CODE_ADD(c, fps, 16); 7988c2ecf20Sopenharmony_ci CODE_ADD(c, 0x3, 2); 7998c2ecf20Sopenharmony_ci CODE_ADD(c, 1001, vti_bitlen(go)); 8008c2ecf20Sopenharmony_ci CODE_ADD(c, 1, 1); 8018c2ecf20Sopenharmony_ci CODE_ADD(c, go->width, 13); 8028c2ecf20Sopenharmony_ci CODE_ADD(c, 1, 1); 8038c2ecf20Sopenharmony_ci CODE_ADD(c, go->height, 13); 8048c2ecf20Sopenharmony_ci CODE_ADD(c, 0x2830, 14); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* Byte-align */ 8078c2ecf20Sopenharmony_ci i = 8 - (CODE_LENGTH(c) % 8); 8088c2ecf20Sopenharmony_ci CODE_ADD(c, 0, 1); 8098c2ecf20Sopenharmony_ci CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci i = CODE_LENGTH(c) + sizeof(head) * 8; 8128c2ecf20Sopenharmony_ci buf[0] = i & 0xff; 8138c2ecf20Sopenharmony_ci buf[1] = i >> 8; 8148c2ecf20Sopenharmony_ci return i; 8158c2ecf20Sopenharmony_ci} 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic int gen_mpeg4hdr_to_package(struct go7007 *go, 8188c2ecf20Sopenharmony_ci __le16 *code, int space, int *framelen) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci u8 *buf; 8218c2ecf20Sopenharmony_ci u16 mem = 0x3e00; 8228c2ecf20Sopenharmony_ci unsigned int addr = 0x19; 8238c2ecf20Sopenharmony_ci int i, off = 0, chunk; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci buf = kzalloc(5120, GFP_KERNEL); 8268c2ecf20Sopenharmony_ci if (buf == NULL) 8278c2ecf20Sopenharmony_ci return -ENOMEM; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME); 8308c2ecf20Sopenharmony_ci i = 368; 8318c2ecf20Sopenharmony_ci framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE); 8328c2ecf20Sopenharmony_ci i += 1632; 8338c2ecf20Sopenharmony_ci framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST); 8348c2ecf20Sopenharmony_ci i += 1432; 8358c2ecf20Sopenharmony_ci framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR); 8368c2ecf20Sopenharmony_ci i += 1632; 8378c2ecf20Sopenharmony_ci mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY); 8388c2ecf20Sopenharmony_ci i += 16; 8398c2ecf20Sopenharmony_ci mpeg4_sequence_header(go, buf + i, 0); 8408c2ecf20Sopenharmony_ci i += 40; 8418c2ecf20Sopenharmony_ci for (i = 0; i < 5120; i += chunk * 2) { 8428c2ecf20Sopenharmony_ci if (space - off < 32) { 8438c2ecf20Sopenharmony_ci off = -1; 8448c2ecf20Sopenharmony_ci goto done; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci code[off + 1] = __cpu_to_le16(0x8000 | mem); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci chunk = 28; 8508c2ecf20Sopenharmony_ci if (mem + chunk > 0x4000) 8518c2ecf20Sopenharmony_ci chunk = 0x4000 - mem; 8528c2ecf20Sopenharmony_ci if (i + 2 * chunk > 5120) 8538c2ecf20Sopenharmony_ci chunk = (5120 - i) / 2; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci if (chunk < 28) { 8568c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x4000 | chunk); 8578c2ecf20Sopenharmony_ci code[off + 31] = __cpu_to_le16(addr); 8588c2ecf20Sopenharmony_ci if (mem + chunk == 0x4000) { 8598c2ecf20Sopenharmony_ci mem = 0x3e00; 8608c2ecf20Sopenharmony_ci ++addr; 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci } else { 8638c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x1000 | 28); 8648c2ecf20Sopenharmony_ci code[off + 31] = 0; 8658c2ecf20Sopenharmony_ci mem += 28; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci memcpy(&code[off + 2], buf + i, chunk * 2); 8698c2ecf20Sopenharmony_ci off += 32; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci mem = 0x3e00; 8728c2ecf20Sopenharmony_ci addr = go->ipb ? 0x14f9 : 0x0af9; 8738c2ecf20Sopenharmony_ci memset(buf, 0, 5120); 8748c2ecf20Sopenharmony_ci framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME); 8758c2ecf20Sopenharmony_ci i = 368; 8768c2ecf20Sopenharmony_ci framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE); 8778c2ecf20Sopenharmony_ci i += 1632; 8788c2ecf20Sopenharmony_ci framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST); 8798c2ecf20Sopenharmony_ci i += 1432; 8808c2ecf20Sopenharmony_ci framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR); 8818c2ecf20Sopenharmony_ci i += 1632; 8828c2ecf20Sopenharmony_ci mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY); 8838c2ecf20Sopenharmony_ci i += 16; 8848c2ecf20Sopenharmony_ci for (i = 0; i < 5120; i += chunk * 2) { 8858c2ecf20Sopenharmony_ci if (space - off < 32) { 8868c2ecf20Sopenharmony_ci off = -1; 8878c2ecf20Sopenharmony_ci goto done; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci code[off + 1] = __cpu_to_le16(0x8000 | mem); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci chunk = 28; 8938c2ecf20Sopenharmony_ci if (mem + chunk > 0x4000) 8948c2ecf20Sopenharmony_ci chunk = 0x4000 - mem; 8958c2ecf20Sopenharmony_ci if (i + 2 * chunk > 5120) 8968c2ecf20Sopenharmony_ci chunk = (5120 - i) / 2; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (chunk < 28) { 8998c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x4000 | chunk); 9008c2ecf20Sopenharmony_ci code[off + 31] = __cpu_to_le16(addr); 9018c2ecf20Sopenharmony_ci if (mem + chunk == 0x4000) { 9028c2ecf20Sopenharmony_ci mem = 0x3e00; 9038c2ecf20Sopenharmony_ci ++addr; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci } else { 9068c2ecf20Sopenharmony_ci code[off] = __cpu_to_le16(0x1000 | 28); 9078c2ecf20Sopenharmony_ci code[off + 31] = 0; 9088c2ecf20Sopenharmony_ci mem += 28; 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci memcpy(&code[off + 2], buf + i, chunk * 2); 9128c2ecf20Sopenharmony_ci off += 32; 9138c2ecf20Sopenharmony_ci } 9148c2ecf20Sopenharmony_cidone: 9158c2ecf20Sopenharmony_ci kfree(buf); 9168c2ecf20Sopenharmony_ci return off; 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic int brctrl_to_package(struct go7007 *go, 9208c2ecf20Sopenharmony_ci __le16 *code, int space, int *framelen) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci int converge_speed = 0; 9238c2ecf20Sopenharmony_ci int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ? 9248c2ecf20Sopenharmony_ci 100 : 0; 9258c2ecf20Sopenharmony_ci int peak_rate = 6 * go->bitrate / 5; 9268c2ecf20Sopenharmony_ci int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ? 9278c2ecf20Sopenharmony_ci go->bitrate : 9288c2ecf20Sopenharmony_ci (go->dvd_mode ? 900000 : peak_rate); 9298c2ecf20Sopenharmony_ci int fps = go->sensor_framerate / go->fps_scale; 9308c2ecf20Sopenharmony_ci int q = 0; 9318c2ecf20Sopenharmony_ci /* Bizarre math below depends on rounding errors in division */ 9328c2ecf20Sopenharmony_ci u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps; 9338c2ecf20Sopenharmony_ci u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps; 9348c2ecf20Sopenharmony_ci u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000); 9358c2ecf20Sopenharmony_ci u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32); 9368c2ecf20Sopenharmony_ci u32 cplx[] = { 9378c2ecf20Sopenharmony_ci q > 0 ? sgop_expt_addr * q : 9388c2ecf20Sopenharmony_ci 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, 9398c2ecf20Sopenharmony_ci q > 0 ? sgop_expt_addr * q : 9408c2ecf20Sopenharmony_ci 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, 9418c2ecf20Sopenharmony_ci q > 0 ? sgop_expt_addr * q : 9428c2ecf20Sopenharmony_ci 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, 9438c2ecf20Sopenharmony_ci q > 0 ? sgop_expt_addr * q : 9448c2ecf20Sopenharmony_ci 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, 9458c2ecf20Sopenharmony_ci }; 9468c2ecf20Sopenharmony_ci u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr; 9478c2ecf20Sopenharmony_ci u16 pack[] = { 9488c2ecf20Sopenharmony_ci 0x200e, 0x0000, 9498c2ecf20Sopenharmony_ci 0xBF20, go->ipb ? converge_speed_ipb[converge_speed] 9508c2ecf20Sopenharmony_ci : converge_speed_ip[converge_speed], 9518c2ecf20Sopenharmony_ci 0xBF21, go->ipb ? 2 : 0, 9528c2ecf20Sopenharmony_ci 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50] 9538c2ecf20Sopenharmony_ci : 32767, 9548c2ecf20Sopenharmony_ci 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767, 9558c2ecf20Sopenharmony_ci 0xBF24, 32767, 9568c2ecf20Sopenharmony_ci 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda], 9578c2ecf20Sopenharmony_ci 0xBF26, sgop_expt_addr & 0x0000FFFF, 9588c2ecf20Sopenharmony_ci 0xBF27, sgop_expt_addr >> 16, 9598c2ecf20Sopenharmony_ci 0xBF28, sgop_peak_addr & 0x0000FFFF, 9608c2ecf20Sopenharmony_ci 0xBF29, sgop_peak_addr >> 16, 9618c2ecf20Sopenharmony_ci 0xBF2A, vbv_alert_addr & 0x0000FFFF, 9628c2ecf20Sopenharmony_ci 0xBF2B, vbv_alert_addr >> 16, 9638c2ecf20Sopenharmony_ci 0xBF2C, 0, 9648c2ecf20Sopenharmony_ci 0xBF2D, 0, 9658c2ecf20Sopenharmony_ci 0, 0, 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci 0x200e, 0x0000, 9688c2ecf20Sopenharmony_ci 0xBF2E, vbv_alert_addr & 0x0000FFFF, 9698c2ecf20Sopenharmony_ci 0xBF2F, vbv_alert_addr >> 16, 9708c2ecf20Sopenharmony_ci 0xBF30, cplx[0] & 0x0000FFFF, 9718c2ecf20Sopenharmony_ci 0xBF31, cplx[0] >> 16, 9728c2ecf20Sopenharmony_ci 0xBF32, cplx[1] & 0x0000FFFF, 9738c2ecf20Sopenharmony_ci 0xBF33, cplx[1] >> 16, 9748c2ecf20Sopenharmony_ci 0xBF34, cplx[2] & 0x0000FFFF, 9758c2ecf20Sopenharmony_ci 0xBF35, cplx[2] >> 16, 9768c2ecf20Sopenharmony_ci 0xBF36, cplx[3] & 0x0000FFFF, 9778c2ecf20Sopenharmony_ci 0xBF37, cplx[3] >> 16, 9788c2ecf20Sopenharmony_ci 0xBF38, 0, 9798c2ecf20Sopenharmony_ci 0xBF39, 0, 9808c2ecf20Sopenharmony_ci 0xBF3A, total_expt_addr & 0x0000FFFF, 9818c2ecf20Sopenharmony_ci 0xBF3B, total_expt_addr >> 16, 9828c2ecf20Sopenharmony_ci 0, 0, 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci 0x200e, 0x0000, 9858c2ecf20Sopenharmony_ci 0xBF3C, total_expt_addr & 0x0000FFFF, 9868c2ecf20Sopenharmony_ci 0xBF3D, total_expt_addr >> 16, 9878c2ecf20Sopenharmony_ci 0xBF3E, 0, 9888c2ecf20Sopenharmony_ci 0xBF3F, 0, 9898c2ecf20Sopenharmony_ci 0xBF48, 0, 9908c2ecf20Sopenharmony_ci 0xBF49, 0, 9918c2ecf20Sopenharmony_ci 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q), 9928c2ecf20Sopenharmony_ci 0xBF4B, 4, 9938c2ecf20Sopenharmony_ci 0xBF4C, 0, 9948c2ecf20Sopenharmony_ci 0xBF4D, 0, 9958c2ecf20Sopenharmony_ci 0xBF4E, 0, 9968c2ecf20Sopenharmony_ci 0xBF4F, 0, 9978c2ecf20Sopenharmony_ci 0xBF50, 0, 9988c2ecf20Sopenharmony_ci 0xBF51, 0, 9998c2ecf20Sopenharmony_ci 0, 0, 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci 0x200e, 0x0000, 10028c2ecf20Sopenharmony_ci 0xBF40, sgop_expt_addr & 0x0000FFFF, 10038c2ecf20Sopenharmony_ci 0xBF41, sgop_expt_addr >> 16, 10048c2ecf20Sopenharmony_ci 0xBF42, 0, 10058c2ecf20Sopenharmony_ci 0xBF43, 0, 10068c2ecf20Sopenharmony_ci 0xBF44, 0, 10078c2ecf20Sopenharmony_ci 0xBF45, 0, 10088c2ecf20Sopenharmony_ci 0xBF46, (go->width >> 4) * (go->height >> 4), 10098c2ecf20Sopenharmony_ci 0xBF47, 0, 10108c2ecf20Sopenharmony_ci 0xBF64, 0, 10118c2ecf20Sopenharmony_ci 0xBF65, 0, 10128c2ecf20Sopenharmony_ci 0xBF18, framelen[4], 10138c2ecf20Sopenharmony_ci 0xBF19, framelen[5], 10148c2ecf20Sopenharmony_ci 0xBF1A, framelen[6], 10158c2ecf20Sopenharmony_ci 0xBF1B, framelen[7], 10168c2ecf20Sopenharmony_ci 0, 0, 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci#if 0 10198c2ecf20Sopenharmony_ci /* Remove once we don't care about matching */ 10208c2ecf20Sopenharmony_ci 0x200e, 0x0000, 10218c2ecf20Sopenharmony_ci 0xBF56, 4, 10228c2ecf20Sopenharmony_ci 0xBF57, 0, 10238c2ecf20Sopenharmony_ci 0xBF58, 5, 10248c2ecf20Sopenharmony_ci 0xBF59, 0, 10258c2ecf20Sopenharmony_ci 0xBF5A, 6, 10268c2ecf20Sopenharmony_ci 0xBF5B, 0, 10278c2ecf20Sopenharmony_ci 0xBF5C, 8, 10288c2ecf20Sopenharmony_ci 0xBF5D, 0, 10298c2ecf20Sopenharmony_ci 0xBF5E, 1, 10308c2ecf20Sopenharmony_ci 0xBF5F, 0, 10318c2ecf20Sopenharmony_ci 0xBF60, 1, 10328c2ecf20Sopenharmony_ci 0xBF61, 0, 10338c2ecf20Sopenharmony_ci 0xBF62, 0, 10348c2ecf20Sopenharmony_ci 0xBF63, 0, 10358c2ecf20Sopenharmony_ci 0, 0, 10368c2ecf20Sopenharmony_ci#else 10378c2ecf20Sopenharmony_ci 0x2008, 0x0000, 10388c2ecf20Sopenharmony_ci 0xBF56, 4, 10398c2ecf20Sopenharmony_ci 0xBF57, 0, 10408c2ecf20Sopenharmony_ci 0xBF58, 5, 10418c2ecf20Sopenharmony_ci 0xBF59, 0, 10428c2ecf20Sopenharmony_ci 0xBF5A, 6, 10438c2ecf20Sopenharmony_ci 0xBF5B, 0, 10448c2ecf20Sopenharmony_ci 0xBF5C, 8, 10458c2ecf20Sopenharmony_ci 0xBF5D, 0, 10468c2ecf20Sopenharmony_ci 0, 0, 10478c2ecf20Sopenharmony_ci 0, 0, 10488c2ecf20Sopenharmony_ci 0, 0, 10498c2ecf20Sopenharmony_ci 0, 0, 10508c2ecf20Sopenharmony_ci 0, 0, 10518c2ecf20Sopenharmony_ci 0, 0, 10528c2ecf20Sopenharmony_ci 0, 0, 10538c2ecf20Sopenharmony_ci#endif 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci 0x200e, 0x0000, 10568c2ecf20Sopenharmony_ci 0xBF10, 0, 10578c2ecf20Sopenharmony_ci 0xBF11, 0, 10588c2ecf20Sopenharmony_ci 0xBF12, 0, 10598c2ecf20Sopenharmony_ci 0xBF13, 0, 10608c2ecf20Sopenharmony_ci 0xBF14, 0, 10618c2ecf20Sopenharmony_ci 0xBF15, 0, 10628c2ecf20Sopenharmony_ci 0xBF16, 0, 10638c2ecf20Sopenharmony_ci 0xBF17, 0, 10648c2ecf20Sopenharmony_ci 0xBF7E, 0, 10658c2ecf20Sopenharmony_ci 0xBF7F, 1, 10668c2ecf20Sopenharmony_ci 0xBF52, framelen[0], 10678c2ecf20Sopenharmony_ci 0xBF53, framelen[1], 10688c2ecf20Sopenharmony_ci 0xBF54, framelen[2], 10698c2ecf20Sopenharmony_ci 0xBF55, framelen[3], 10708c2ecf20Sopenharmony_ci 0, 0, 10718c2ecf20Sopenharmony_ci }; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci return copy_packages(code, pack, 6, space); 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_cistatic int config_package(struct go7007 *go, __le16 *code, int space) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci int fps = go->sensor_framerate / go->fps_scale / 1000; 10798c2ecf20Sopenharmony_ci int rows = go->interlace_coding ? go->height / 32 : go->height / 16; 10808c2ecf20Sopenharmony_ci int brc_window_size = fps; 10818c2ecf20Sopenharmony_ci int q_min = 2, q_max = 31; 10828c2ecf20Sopenharmony_ci int THACCoeffSet0 = 0; 10838c2ecf20Sopenharmony_ci u16 pack[] = { 10848c2ecf20Sopenharmony_ci 0x200e, 0x0000, 10858c2ecf20Sopenharmony_ci 0xc002, 0x14b4, 10868c2ecf20Sopenharmony_ci 0xc003, 0x28b4, 10878c2ecf20Sopenharmony_ci 0xc004, 0x3c5a, 10888c2ecf20Sopenharmony_ci 0xdc05, 0x2a77, 10898c2ecf20Sopenharmony_ci 0xc6c3, go->format == V4L2_PIX_FMT_MPEG4 ? 0 : 10908c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_H263 ? 0 : 1), 10918c2ecf20Sopenharmony_ci 0xc680, go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 : 10928c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_H263 ? 0x61 : 10938c2ecf20Sopenharmony_ci 0xd3), 10948c2ecf20Sopenharmony_ci 0xc780, 0x0140, 10958c2ecf20Sopenharmony_ci 0xe009, 0x0001, 10968c2ecf20Sopenharmony_ci 0xc60f, 0x0008, 10978c2ecf20Sopenharmony_ci 0xd4ff, 0x0002, 10988c2ecf20Sopenharmony_ci 0xe403, 2340, 10998c2ecf20Sopenharmony_ci 0xe406, 75, 11008c2ecf20Sopenharmony_ci 0xd411, 0x0001, 11018c2ecf20Sopenharmony_ci 0xd410, 0xa1d6, 11028c2ecf20Sopenharmony_ci 0x0001, 0x2801, 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci 0x200d, 0x0000, 11058c2ecf20Sopenharmony_ci 0xe402, 0x018b, 11068c2ecf20Sopenharmony_ci 0xe401, 0x8b01, 11078c2ecf20Sopenharmony_ci 0xd472, (go->board_info->sensor_flags & 11088c2ecf20Sopenharmony_ci GO7007_SENSOR_TV) && 11098c2ecf20Sopenharmony_ci (!go->interlace_coding) ? 11108c2ecf20Sopenharmony_ci 0x01b0 : 0x0170, 11118c2ecf20Sopenharmony_ci 0xd475, (go->board_info->sensor_flags & 11128c2ecf20Sopenharmony_ci GO7007_SENSOR_TV) && 11138c2ecf20Sopenharmony_ci (!go->interlace_coding) ? 11148c2ecf20Sopenharmony_ci 0x0008 : 0x0009, 11158c2ecf20Sopenharmony_ci 0xc404, go->interlace_coding ? 0x44 : 11168c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 : 11178c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 : 11188c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 : 11198c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_H263 ? 0x08 : 11208c2ecf20Sopenharmony_ci 0x20)))), 11218c2ecf20Sopenharmony_ci 0xbf0a, (go->format == V4L2_PIX_FMT_MPEG4 ? 8 : 11228c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG1 ? 1 : 11238c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG2 ? 2 : 11248c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) | 11258c2ecf20Sopenharmony_ci ((go->repeat_seqhead ? 1 : 0) << 6) | 11268c2ecf20Sopenharmony_ci ((go->dvd_mode ? 1 : 0) << 9) | 11278c2ecf20Sopenharmony_ci ((go->gop_header_enable ? 1 : 0) << 10), 11288c2ecf20Sopenharmony_ci 0xbf0b, 0, 11298c2ecf20Sopenharmony_ci 0xdd5a, go->ipb ? 0x14 : 0x0a, 11308c2ecf20Sopenharmony_ci 0xbf0c, 0, 11318c2ecf20Sopenharmony_ci 0xbf0d, 0, 11328c2ecf20Sopenharmony_ci 0xc683, THACCoeffSet0, 11338c2ecf20Sopenharmony_ci 0xc40a, (go->width << 4) | rows, 11348c2ecf20Sopenharmony_ci 0xe01a, go->board_info->hpi_buffer_cap, 11358c2ecf20Sopenharmony_ci 0, 0, 11368c2ecf20Sopenharmony_ci 0, 0, 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci 0x2008, 0, 11398c2ecf20Sopenharmony_ci 0xe402, 0x88, 11408c2ecf20Sopenharmony_ci 0xe401, 0x8f01, 11418c2ecf20Sopenharmony_ci 0xbf6a, 0, 11428c2ecf20Sopenharmony_ci 0xbf6b, 0, 11438c2ecf20Sopenharmony_ci 0xbf6c, 0, 11448c2ecf20Sopenharmony_ci 0xbf6d, 0, 11458c2ecf20Sopenharmony_ci 0xbf6e, 0, 11468c2ecf20Sopenharmony_ci 0xbf6f, 0, 11478c2ecf20Sopenharmony_ci 0, 0, 11488c2ecf20Sopenharmony_ci 0, 0, 11498c2ecf20Sopenharmony_ci 0, 0, 11508c2ecf20Sopenharmony_ci 0, 0, 11518c2ecf20Sopenharmony_ci 0, 0, 11528c2ecf20Sopenharmony_ci 0, 0, 11538c2ecf20Sopenharmony_ci 0, 0, 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci 0x200e, 0, 11568c2ecf20Sopenharmony_ci 0xbf66, brc_window_size, 11578c2ecf20Sopenharmony_ci 0xbf67, 0, 11588c2ecf20Sopenharmony_ci 0xbf68, q_min, 11598c2ecf20Sopenharmony_ci 0xbf69, q_max, 11608c2ecf20Sopenharmony_ci 0xbfe0, 0, 11618c2ecf20Sopenharmony_ci 0xbfe1, 0, 11628c2ecf20Sopenharmony_ci 0xbfe2, 0, 11638c2ecf20Sopenharmony_ci 0xbfe3, go->ipb ? 3 : 1, 11648c2ecf20Sopenharmony_ci 0xc031, go->board_info->sensor_flags & 11658c2ecf20Sopenharmony_ci GO7007_SENSOR_VBI ? 1 : 0, 11668c2ecf20Sopenharmony_ci 0xc01c, 0x1f, 11678c2ecf20Sopenharmony_ci 0xdd8c, 0x15, 11688c2ecf20Sopenharmony_ci 0xdd94, 0x15, 11698c2ecf20Sopenharmony_ci 0xdd88, go->ipb ? 0x1401 : 0x0a01, 11708c2ecf20Sopenharmony_ci 0xdd90, go->ipb ? 0x1401 : 0x0a01, 11718c2ecf20Sopenharmony_ci 0, 0, 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci 0x200e, 0, 11748c2ecf20Sopenharmony_ci 0xbfe4, 0, 11758c2ecf20Sopenharmony_ci 0xbfe5, 0, 11768c2ecf20Sopenharmony_ci 0xbfe6, 0, 11778c2ecf20Sopenharmony_ci 0xbfe7, fps << 8, 11788c2ecf20Sopenharmony_ci 0xbfe8, 0x3a00, 11798c2ecf20Sopenharmony_ci 0xbfe9, 0, 11808c2ecf20Sopenharmony_ci 0xbfea, 0, 11818c2ecf20Sopenharmony_ci 0xbfeb, 0, 11828c2ecf20Sopenharmony_ci 0xbfec, (go->interlace_coding ? 1 << 15 : 0) | 11838c2ecf20Sopenharmony_ci (go->modet_enable ? 0xa : 0) | 11848c2ecf20Sopenharmony_ci (go->board_info->sensor_flags & 11858c2ecf20Sopenharmony_ci GO7007_SENSOR_VBI ? 1 : 0), 11868c2ecf20Sopenharmony_ci 0xbfed, 0, 11878c2ecf20Sopenharmony_ci 0xbfee, 0, 11888c2ecf20Sopenharmony_ci 0xbfef, 0, 11898c2ecf20Sopenharmony_ci 0xbff0, go->board_info->sensor_flags & 11908c2ecf20Sopenharmony_ci GO7007_SENSOR_TV ? 0xf060 : 0xb060, 11918c2ecf20Sopenharmony_ci 0xbff1, 0, 11928c2ecf20Sopenharmony_ci 0, 0, 11938c2ecf20Sopenharmony_ci }; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci return copy_packages(code, pack, 5, space); 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_cistatic int seqhead_to_package(struct go7007 *go, __le16 *code, int space, 11998c2ecf20Sopenharmony_ci int (*sequence_header_func)(struct go7007 *go, 12008c2ecf20Sopenharmony_ci unsigned char *buf, int ext)) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci int vop_time_increment_bitlength = vti_bitlen(go); 12038c2ecf20Sopenharmony_ci int fps = go->sensor_framerate / go->fps_scale * 12048c2ecf20Sopenharmony_ci (go->interlace_coding ? 2 : 1); 12058c2ecf20Sopenharmony_ci unsigned char buf[40] = { }; 12068c2ecf20Sopenharmony_ci int len = sequence_header_func(go, buf, 1); 12078c2ecf20Sopenharmony_ci u16 pack[] = { 12088c2ecf20Sopenharmony_ci 0x2006, 0, 12098c2ecf20Sopenharmony_ci 0xbf08, fps, 12108c2ecf20Sopenharmony_ci 0xbf09, 0, 12118c2ecf20Sopenharmony_ci 0xbff2, vop_time_increment_bitlength, 12128c2ecf20Sopenharmony_ci 0xbff3, (1 << vop_time_increment_bitlength) - 1, 12138c2ecf20Sopenharmony_ci 0xbfe6, 0, 12148c2ecf20Sopenharmony_ci 0xbfe7, (fps / 1000) << 8, 12158c2ecf20Sopenharmony_ci 0, 0, 12168c2ecf20Sopenharmony_ci 0, 0, 12178c2ecf20Sopenharmony_ci 0, 0, 12188c2ecf20Sopenharmony_ci 0, 0, 12198c2ecf20Sopenharmony_ci 0, 0, 12208c2ecf20Sopenharmony_ci 0, 0, 12218c2ecf20Sopenharmony_ci 0, 0, 12228c2ecf20Sopenharmony_ci 0, 0, 12238c2ecf20Sopenharmony_ci 0, 0, 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci 0x2007, 0, 12268c2ecf20Sopenharmony_ci 0xc800, buf[2] << 8 | buf[3], 12278c2ecf20Sopenharmony_ci 0xc801, buf[4] << 8 | buf[5], 12288c2ecf20Sopenharmony_ci 0xc802, buf[6] << 8 | buf[7], 12298c2ecf20Sopenharmony_ci 0xc803, buf[8] << 8 | buf[9], 12308c2ecf20Sopenharmony_ci 0xc406, 64, 12318c2ecf20Sopenharmony_ci 0xc407, len - 64, 12328c2ecf20Sopenharmony_ci 0xc61b, 1, 12338c2ecf20Sopenharmony_ci 0, 0, 12348c2ecf20Sopenharmony_ci 0, 0, 12358c2ecf20Sopenharmony_ci 0, 0, 12368c2ecf20Sopenharmony_ci 0, 0, 12378c2ecf20Sopenharmony_ci 0, 0, 12388c2ecf20Sopenharmony_ci 0, 0, 12398c2ecf20Sopenharmony_ci 0, 0, 12408c2ecf20Sopenharmony_ci 0, 0, 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci 0x200e, 0, 12438c2ecf20Sopenharmony_ci 0xc808, buf[10] << 8 | buf[11], 12448c2ecf20Sopenharmony_ci 0xc809, buf[12] << 8 | buf[13], 12458c2ecf20Sopenharmony_ci 0xc80a, buf[14] << 8 | buf[15], 12468c2ecf20Sopenharmony_ci 0xc80b, buf[16] << 8 | buf[17], 12478c2ecf20Sopenharmony_ci 0xc80c, buf[18] << 8 | buf[19], 12488c2ecf20Sopenharmony_ci 0xc80d, buf[20] << 8 | buf[21], 12498c2ecf20Sopenharmony_ci 0xc80e, buf[22] << 8 | buf[23], 12508c2ecf20Sopenharmony_ci 0xc80f, buf[24] << 8 | buf[25], 12518c2ecf20Sopenharmony_ci 0xc810, buf[26] << 8 | buf[27], 12528c2ecf20Sopenharmony_ci 0xc811, buf[28] << 8 | buf[29], 12538c2ecf20Sopenharmony_ci 0xc812, buf[30] << 8 | buf[31], 12548c2ecf20Sopenharmony_ci 0xc813, buf[32] << 8 | buf[33], 12558c2ecf20Sopenharmony_ci 0xc814, buf[34] << 8 | buf[35], 12568c2ecf20Sopenharmony_ci 0xc815, buf[36] << 8 | buf[37], 12578c2ecf20Sopenharmony_ci 0, 0, 12588c2ecf20Sopenharmony_ci 0, 0, 12598c2ecf20Sopenharmony_ci 0, 0, 12608c2ecf20Sopenharmony_ci }; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci return copy_packages(code, pack, 3, space); 12638c2ecf20Sopenharmony_ci} 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cistatic int relative_prime(int big, int little) 12668c2ecf20Sopenharmony_ci{ 12678c2ecf20Sopenharmony_ci int remainder; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci while (little != 0) { 12708c2ecf20Sopenharmony_ci remainder = big % little; 12718c2ecf20Sopenharmony_ci big = little; 12728c2ecf20Sopenharmony_ci little = remainder; 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci return big; 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_cistatic int avsync_to_package(struct go7007 *go, __le16 *code, int space) 12788c2ecf20Sopenharmony_ci{ 12798c2ecf20Sopenharmony_ci int arate = go->board_info->audio_rate * 1001 * go->fps_scale; 12808c2ecf20Sopenharmony_ci int ratio = arate / go->sensor_framerate; 12818c2ecf20Sopenharmony_ci int adjratio = ratio * 215 / 100; 12828c2ecf20Sopenharmony_ci int rprime = relative_prime(go->sensor_framerate, 12838c2ecf20Sopenharmony_ci arate % go->sensor_framerate); 12848c2ecf20Sopenharmony_ci int f1 = (arate % go->sensor_framerate) / rprime; 12858c2ecf20Sopenharmony_ci int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime; 12868c2ecf20Sopenharmony_ci u16 pack[] = { 12878c2ecf20Sopenharmony_ci 0x200e, 0, 12888c2ecf20Sopenharmony_ci 0xbf98, (u16)((-adjratio) & 0xffff), 12898c2ecf20Sopenharmony_ci 0xbf99, (u16)((-adjratio) >> 16), 12908c2ecf20Sopenharmony_ci 0xbf92, 0, 12918c2ecf20Sopenharmony_ci 0xbf93, 0, 12928c2ecf20Sopenharmony_ci 0xbff4, f1 > f2 ? f1 : f2, 12938c2ecf20Sopenharmony_ci 0xbff5, f1 < f2 ? f1 : f2, 12948c2ecf20Sopenharmony_ci 0xbff6, f1 < f2 ? ratio : ratio + 1, 12958c2ecf20Sopenharmony_ci 0xbff7, f1 > f2 ? ratio : ratio + 1, 12968c2ecf20Sopenharmony_ci 0xbff8, 0, 12978c2ecf20Sopenharmony_ci 0xbff9, 0, 12988c2ecf20Sopenharmony_ci 0xbffa, adjratio & 0xffff, 12998c2ecf20Sopenharmony_ci 0xbffb, adjratio >> 16, 13008c2ecf20Sopenharmony_ci 0xbf94, 0, 13018c2ecf20Sopenharmony_ci 0xbf95, 0, 13028c2ecf20Sopenharmony_ci 0, 0, 13038c2ecf20Sopenharmony_ci }; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci return copy_packages(code, pack, 1, space); 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_cistatic int final_package(struct go7007 *go, __le16 *code, int space) 13098c2ecf20Sopenharmony_ci{ 13108c2ecf20Sopenharmony_ci int rows = go->interlace_coding ? go->height / 32 : go->height / 16; 13118c2ecf20Sopenharmony_ci u16 pack[] = { 13128c2ecf20Sopenharmony_ci 0x8000, 13138c2ecf20Sopenharmony_ci 0, 13148c2ecf20Sopenharmony_ci 0, 13158c2ecf20Sopenharmony_ci 0, 13168c2ecf20Sopenharmony_ci 0, 13178c2ecf20Sopenharmony_ci 0, 13188c2ecf20Sopenharmony_ci 0, 13198c2ecf20Sopenharmony_ci 2, 13208c2ecf20Sopenharmony_ci ((go->board_info->sensor_flags & GO7007_SENSOR_TV) && 13218c2ecf20Sopenharmony_ci (!go->interlace_coding) ? 13228c2ecf20Sopenharmony_ci (1 << 14) | (1 << 9) : 0) | 13238c2ecf20Sopenharmony_ci ((go->encoder_subsample ? 1 : 0) << 8) | 13248c2ecf20Sopenharmony_ci (go->board_info->sensor_flags & 13258c2ecf20Sopenharmony_ci GO7007_SENSOR_CONFIG_MASK), 13268c2ecf20Sopenharmony_ci ((go->encoder_v_halve ? 1 : 0) << 14) | 13278c2ecf20Sopenharmony_ci (go->encoder_v_halve ? rows << 9 : rows << 8) | 13288c2ecf20Sopenharmony_ci (go->encoder_h_halve ? 1 << 6 : 0) | 13298c2ecf20Sopenharmony_ci (go->encoder_h_halve ? go->width >> 3 : go->width >> 4), 13308c2ecf20Sopenharmony_ci (1 << 15) | (go->encoder_v_offset << 6) | 13318c2ecf20Sopenharmony_ci (1 << 7) | (go->encoder_h_offset >> 2), 13328c2ecf20Sopenharmony_ci (1 << 6), 13338c2ecf20Sopenharmony_ci 0, 13348c2ecf20Sopenharmony_ci 0, 13358c2ecf20Sopenharmony_ci ((go->fps_scale - 1) << 8) | 13368c2ecf20Sopenharmony_ci (go->board_info->sensor_flags & GO7007_SENSOR_TV ? 13378c2ecf20Sopenharmony_ci (1 << 7) : 0) | 13388c2ecf20Sopenharmony_ci 0x41, 13398c2ecf20Sopenharmony_ci go->ipb ? 0xd4c : 0x36b, 13408c2ecf20Sopenharmony_ci (rows << 8) | (go->width >> 4), 13418c2ecf20Sopenharmony_ci go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0, 13428c2ecf20Sopenharmony_ci (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) | 13438c2ecf20Sopenharmony_ci ((go->closed_gop ? 1 : 0) << 12) | 13448c2ecf20Sopenharmony_ci ((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) | 13458c2ecf20Sopenharmony_ci /* (1 << 9) | */ 13468c2ecf20Sopenharmony_ci ((go->ipb ? 3 : 0) << 7) | 13478c2ecf20Sopenharmony_ci ((go->modet_enable ? 1 : 0) << 2) | 13488c2ecf20Sopenharmony_ci ((go->dvd_mode ? 1 : 0) << 1) | 1, 13498c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 : 13508c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 : 13518c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 : 13528c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 : 13538c2ecf20Sopenharmony_ci (go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))), 13548c2ecf20Sopenharmony_ci go->ipb ? 0x1f15 : 0x1f0b, 13558c2ecf20Sopenharmony_ci go->ipb ? 0x0015 : 0x000b, 13568c2ecf20Sopenharmony_ci go->ipb ? 0xa800 : 0x5800, 13578c2ecf20Sopenharmony_ci 0xffff, 13588c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 0, 13598c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 1, 13608c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 2, 13618c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 3, 13628c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 4, 13638c2ecf20Sopenharmony_ci 0x0020 + 0x034b * 5, 13648c2ecf20Sopenharmony_ci go->ipb ? (go->gop_size / 3) : go->gop_size, 13658c2ecf20Sopenharmony_ci (go->height >> 4) * (go->width >> 4) * 110 / 100, 13668c2ecf20Sopenharmony_ci }; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci return copy_packages(code, pack, 1, space); 13698c2ecf20Sopenharmony_ci} 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_cistatic int audio_to_package(struct go7007 *go, __le16 *code, int space) 13728c2ecf20Sopenharmony_ci{ 13738c2ecf20Sopenharmony_ci int clock_config = ((go->board_info->audio_flags & 13748c2ecf20Sopenharmony_ci GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) | 13758c2ecf20Sopenharmony_ci ((go->board_info->audio_flags & 13768c2ecf20Sopenharmony_ci GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) | 13778c2ecf20Sopenharmony_ci (((go->board_info->audio_bclk_div / 4) - 1) << 4) | 13788c2ecf20Sopenharmony_ci (go->board_info->audio_main_div - 1); 13798c2ecf20Sopenharmony_ci u16 pack[] = { 13808c2ecf20Sopenharmony_ci 0x200d, 0, 13818c2ecf20Sopenharmony_ci 0x9002, 0, 13828c2ecf20Sopenharmony_ci 0x9002, 0, 13838c2ecf20Sopenharmony_ci 0x9031, 0, 13848c2ecf20Sopenharmony_ci 0x9032, 0, 13858c2ecf20Sopenharmony_ci 0x9033, 0, 13868c2ecf20Sopenharmony_ci 0x9034, 0, 13878c2ecf20Sopenharmony_ci 0x9035, 0, 13888c2ecf20Sopenharmony_ci 0x9036, 0, 13898c2ecf20Sopenharmony_ci 0x9037, 0, 13908c2ecf20Sopenharmony_ci 0x9040, 0, 13918c2ecf20Sopenharmony_ci 0x9000, clock_config, 13928c2ecf20Sopenharmony_ci 0x9001, (go->board_info->audio_flags & 0xffff) | 13938c2ecf20Sopenharmony_ci (1 << 9), 13948c2ecf20Sopenharmony_ci 0x9000, ((go->board_info->audio_flags & 13958c2ecf20Sopenharmony_ci GO7007_AUDIO_I2S_MASTER ? 13968c2ecf20Sopenharmony_ci 1 : 0) << 10) | 13978c2ecf20Sopenharmony_ci clock_config, 13988c2ecf20Sopenharmony_ci 0, 0, 13998c2ecf20Sopenharmony_ci 0, 0, 14008c2ecf20Sopenharmony_ci 0x2005, 0, 14018c2ecf20Sopenharmony_ci 0x9041, 0, 14028c2ecf20Sopenharmony_ci 0x9042, 256, 14038c2ecf20Sopenharmony_ci 0x9043, 0, 14048c2ecf20Sopenharmony_ci 0x9044, 16, 14058c2ecf20Sopenharmony_ci 0x9045, 16, 14068c2ecf20Sopenharmony_ci 0, 0, 14078c2ecf20Sopenharmony_ci 0, 0, 14088c2ecf20Sopenharmony_ci 0, 0, 14098c2ecf20Sopenharmony_ci 0, 0, 14108c2ecf20Sopenharmony_ci 0, 0, 14118c2ecf20Sopenharmony_ci 0, 0, 14128c2ecf20Sopenharmony_ci 0, 0, 14138c2ecf20Sopenharmony_ci 0, 0, 14148c2ecf20Sopenharmony_ci 0, 0, 14158c2ecf20Sopenharmony_ci 0, 0, 14168c2ecf20Sopenharmony_ci }; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci return copy_packages(code, pack, 2, space); 14198c2ecf20Sopenharmony_ci} 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_cistatic int modet_to_package(struct go7007 *go, __le16 *code, int space) 14228c2ecf20Sopenharmony_ci{ 14238c2ecf20Sopenharmony_ci bool has_modet0 = go->modet[0].enable; 14248c2ecf20Sopenharmony_ci bool has_modet1 = go->modet[1].enable; 14258c2ecf20Sopenharmony_ci bool has_modet2 = go->modet[2].enable; 14268c2ecf20Sopenharmony_ci bool has_modet3 = go->modet[3].enable; 14278c2ecf20Sopenharmony_ci int ret, mb, i, addr, cnt = 0; 14288c2ecf20Sopenharmony_ci u16 pack[32]; 14298c2ecf20Sopenharmony_ci u16 thresholds[] = { 14308c2ecf20Sopenharmony_ci 0x200e, 0, 14318c2ecf20Sopenharmony_ci 0xbf82, has_modet0 ? go->modet[0].pixel_threshold : 32767, 14328c2ecf20Sopenharmony_ci 0xbf83, has_modet1 ? go->modet[1].pixel_threshold : 32767, 14338c2ecf20Sopenharmony_ci 0xbf84, has_modet2 ? go->modet[2].pixel_threshold : 32767, 14348c2ecf20Sopenharmony_ci 0xbf85, has_modet3 ? go->modet[3].pixel_threshold : 32767, 14358c2ecf20Sopenharmony_ci 0xbf86, has_modet0 ? go->modet[0].motion_threshold : 32767, 14368c2ecf20Sopenharmony_ci 0xbf87, has_modet1 ? go->modet[1].motion_threshold : 32767, 14378c2ecf20Sopenharmony_ci 0xbf88, has_modet2 ? go->modet[2].motion_threshold : 32767, 14388c2ecf20Sopenharmony_ci 0xbf89, has_modet3 ? go->modet[3].motion_threshold : 32767, 14398c2ecf20Sopenharmony_ci 0xbf8a, has_modet0 ? go->modet[0].mb_threshold : 32767, 14408c2ecf20Sopenharmony_ci 0xbf8b, has_modet1 ? go->modet[1].mb_threshold : 32767, 14418c2ecf20Sopenharmony_ci 0xbf8c, has_modet2 ? go->modet[2].mb_threshold : 32767, 14428c2ecf20Sopenharmony_ci 0xbf8d, has_modet3 ? go->modet[3].mb_threshold : 32767, 14438c2ecf20Sopenharmony_ci 0xbf8e, 0, 14448c2ecf20Sopenharmony_ci 0xbf8f, 0, 14458c2ecf20Sopenharmony_ci 0, 0, 14468c2ecf20Sopenharmony_ci }; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci ret = copy_packages(code, thresholds, 1, space); 14498c2ecf20Sopenharmony_ci if (ret < 0) 14508c2ecf20Sopenharmony_ci return -1; 14518c2ecf20Sopenharmony_ci cnt += ret; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci addr = 0xbac0; 14548c2ecf20Sopenharmony_ci memset(pack, 0, 64); 14558c2ecf20Sopenharmony_ci i = 0; 14568c2ecf20Sopenharmony_ci for (mb = 0; mb < 1624; ++mb) { 14578c2ecf20Sopenharmony_ci pack[i * 2 + 3] <<= 2; 14588c2ecf20Sopenharmony_ci pack[i * 2 + 3] |= go->modet_map[mb]; 14598c2ecf20Sopenharmony_ci if (mb % 8 != 7) 14608c2ecf20Sopenharmony_ci continue; 14618c2ecf20Sopenharmony_ci pack[i * 2 + 2] = addr++; 14628c2ecf20Sopenharmony_ci ++i; 14638c2ecf20Sopenharmony_ci if (i == 10 || mb == 1623) { 14648c2ecf20Sopenharmony_ci pack[0] = 0x2000 | i; 14658c2ecf20Sopenharmony_ci ret = copy_packages(code + cnt, pack, 1, space - cnt); 14668c2ecf20Sopenharmony_ci if (ret < 0) 14678c2ecf20Sopenharmony_ci return -1; 14688c2ecf20Sopenharmony_ci cnt += ret; 14698c2ecf20Sopenharmony_ci i = 0; 14708c2ecf20Sopenharmony_ci memset(pack, 0, 64); 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci pack[i * 2 + 3] = 0; 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci memset(pack, 0, 64); 14768c2ecf20Sopenharmony_ci i = 0; 14778c2ecf20Sopenharmony_ci for (addr = 0xbb90; addr < 0xbbfa; ++addr) { 14788c2ecf20Sopenharmony_ci pack[i * 2 + 2] = addr; 14798c2ecf20Sopenharmony_ci pack[i * 2 + 3] = 0; 14808c2ecf20Sopenharmony_ci ++i; 14818c2ecf20Sopenharmony_ci if (i == 10 || addr == 0xbbf9) { 14828c2ecf20Sopenharmony_ci pack[0] = 0x2000 | i; 14838c2ecf20Sopenharmony_ci ret = copy_packages(code + cnt, pack, 1, space - cnt); 14848c2ecf20Sopenharmony_ci if (ret < 0) 14858c2ecf20Sopenharmony_ci return -1; 14868c2ecf20Sopenharmony_ci cnt += ret; 14878c2ecf20Sopenharmony_ci i = 0; 14888c2ecf20Sopenharmony_ci memset(pack, 0, 64); 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci return cnt; 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic noinline_for_stack int do_special(struct go7007 *go, u16 type, 14958c2ecf20Sopenharmony_ci __le16 *code, int space, int *framelen) 14968c2ecf20Sopenharmony_ci{ 14978c2ecf20Sopenharmony_ci switch (type) { 14988c2ecf20Sopenharmony_ci case SPECIAL_FRM_HEAD: 14998c2ecf20Sopenharmony_ci switch (go->format) { 15008c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MJPEG: 15018c2ecf20Sopenharmony_ci return gen_mjpeghdr_to_package(go, code, space); 15028c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG1: 15038c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG2: 15048c2ecf20Sopenharmony_ci return gen_mpeg1hdr_to_package(go, code, space, 15058c2ecf20Sopenharmony_ci framelen); 15068c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG4: 15078c2ecf20Sopenharmony_ci return gen_mpeg4hdr_to_package(go, code, space, 15088c2ecf20Sopenharmony_ci framelen); 15098c2ecf20Sopenharmony_ci default: 15108c2ecf20Sopenharmony_ci break; 15118c2ecf20Sopenharmony_ci } 15128c2ecf20Sopenharmony_ci break; 15138c2ecf20Sopenharmony_ci case SPECIAL_BRC_CTRL: 15148c2ecf20Sopenharmony_ci return brctrl_to_package(go, code, space, framelen); 15158c2ecf20Sopenharmony_ci case SPECIAL_CONFIG: 15168c2ecf20Sopenharmony_ci return config_package(go, code, space); 15178c2ecf20Sopenharmony_ci case SPECIAL_SEQHEAD: 15188c2ecf20Sopenharmony_ci switch (go->format) { 15198c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG1: 15208c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG2: 15218c2ecf20Sopenharmony_ci return seqhead_to_package(go, code, space, 15228c2ecf20Sopenharmony_ci mpeg1_sequence_header); 15238c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG4: 15248c2ecf20Sopenharmony_ci return seqhead_to_package(go, code, space, 15258c2ecf20Sopenharmony_ci mpeg4_sequence_header); 15268c2ecf20Sopenharmony_ci default: 15278c2ecf20Sopenharmony_ci return 0; 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci case SPECIAL_AV_SYNC: 15308c2ecf20Sopenharmony_ci return avsync_to_package(go, code, space); 15318c2ecf20Sopenharmony_ci case SPECIAL_FINAL: 15328c2ecf20Sopenharmony_ci return final_package(go, code, space); 15338c2ecf20Sopenharmony_ci case SPECIAL_AUDIO: 15348c2ecf20Sopenharmony_ci return audio_to_package(go, code, space); 15358c2ecf20Sopenharmony_ci case SPECIAL_MODET: 15368c2ecf20Sopenharmony_ci return modet_to_package(go, code, space); 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci dev_err(go->dev, 15398c2ecf20Sopenharmony_ci "firmware file contains unsupported feature %04x\n", type); 15408c2ecf20Sopenharmony_ci return -1; 15418c2ecf20Sopenharmony_ci} 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ciint go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) 15448c2ecf20Sopenharmony_ci{ 15458c2ecf20Sopenharmony_ci const struct firmware *fw_entry; 15468c2ecf20Sopenharmony_ci __le16 *code, *src; 15478c2ecf20Sopenharmony_ci int framelen[8] = { }; /* holds the lengths of empty frame templates */ 15488c2ecf20Sopenharmony_ci int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags; 15498c2ecf20Sopenharmony_ci int mode_flag; 15508c2ecf20Sopenharmony_ci int ret; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci switch (go->format) { 15538c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MJPEG: 15548c2ecf20Sopenharmony_ci mode_flag = FLAG_MODE_MJPEG; 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG1: 15578c2ecf20Sopenharmony_ci mode_flag = FLAG_MODE_MPEG1; 15588c2ecf20Sopenharmony_ci break; 15598c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG2: 15608c2ecf20Sopenharmony_ci mode_flag = FLAG_MODE_MPEG2; 15618c2ecf20Sopenharmony_ci break; 15628c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_MPEG4: 15638c2ecf20Sopenharmony_ci mode_flag = FLAG_MODE_MPEG4; 15648c2ecf20Sopenharmony_ci break; 15658c2ecf20Sopenharmony_ci default: 15668c2ecf20Sopenharmony_ci return -1; 15678c2ecf20Sopenharmony_ci } 15688c2ecf20Sopenharmony_ci if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) { 15698c2ecf20Sopenharmony_ci dev_err(go->dev, 15708c2ecf20Sopenharmony_ci "unable to load firmware from file \"%s\"\n", 15718c2ecf20Sopenharmony_ci GO7007_FW_NAME); 15728c2ecf20Sopenharmony_ci return -1; 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci code = kcalloc(codespace, 2, GFP_KERNEL); 15758c2ecf20Sopenharmony_ci if (code == NULL) 15768c2ecf20Sopenharmony_ci goto fw_failed; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci src = (__le16 *)fw_entry->data; 15798c2ecf20Sopenharmony_ci srclen = fw_entry->size / 2; 15808c2ecf20Sopenharmony_ci while (srclen >= 2) { 15818c2ecf20Sopenharmony_ci chunk_flags = __le16_to_cpu(src[0]); 15828c2ecf20Sopenharmony_ci chunk_len = __le16_to_cpu(src[1]); 15838c2ecf20Sopenharmony_ci if (chunk_len + 2 > srclen) { 15848c2ecf20Sopenharmony_ci dev_err(go->dev, 15858c2ecf20Sopenharmony_ci "firmware file \"%s\" appears to be corrupted\n", 15868c2ecf20Sopenharmony_ci GO7007_FW_NAME); 15878c2ecf20Sopenharmony_ci goto fw_failed; 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci if (chunk_flags & mode_flag) { 15908c2ecf20Sopenharmony_ci if (chunk_flags & FLAG_SPECIAL) { 15918c2ecf20Sopenharmony_ci ret = do_special(go, __le16_to_cpu(src[2]), 15928c2ecf20Sopenharmony_ci &code[i], codespace - i, framelen); 15938c2ecf20Sopenharmony_ci if (ret < 0) { 15948c2ecf20Sopenharmony_ci dev_err(go->dev, 15958c2ecf20Sopenharmony_ci "insufficient memory for firmware construction\n"); 15968c2ecf20Sopenharmony_ci goto fw_failed; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci i += ret; 15998c2ecf20Sopenharmony_ci } else { 16008c2ecf20Sopenharmony_ci if (codespace - i < chunk_len) { 16018c2ecf20Sopenharmony_ci dev_err(go->dev, 16028c2ecf20Sopenharmony_ci "insufficient memory for firmware construction\n"); 16038c2ecf20Sopenharmony_ci goto fw_failed; 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci memcpy(&code[i], &src[2], chunk_len * 2); 16068c2ecf20Sopenharmony_ci i += chunk_len; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci srclen -= chunk_len + 2; 16108c2ecf20Sopenharmony_ci src += chunk_len + 2; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci release_firmware(fw_entry); 16138c2ecf20Sopenharmony_ci *fw = (u8 *)code; 16148c2ecf20Sopenharmony_ci *fwlen = i * 2; 16158c2ecf20Sopenharmony_ci return 0; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_cifw_failed: 16188c2ecf20Sopenharmony_ci kfree(code); 16198c2ecf20Sopenharmony_ci release_firmware(fw_entry); 16208c2ecf20Sopenharmony_ci return -1; 16218c2ecf20Sopenharmony_ci} 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ciMODULE_FIRMWARE(GO7007_FW_NAME); 1624