| // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <linux/i2c.h> |
| #include <linux/i2c-dev.h> |
| #include <sys/ioctl.h> |
| #include <sys/time.h> |
| #include <errno.h> |
| |
| #include "ch7036.h" |
| |
| /* Fast load of firmware does not work yet */ |
| /* #define FASTLOAD */ |
| int ch7036_debugi2c = 0; |
| int ch7036_cur_page = -1; |
| static int ch_page_map[5] = {-1, 0, 1, 3, 4}; |
| static int ch_page_revmap[8] = {1, 2, -1, 3, 4, -1, -1, -1}; |
| |
| /* Firmware data area moved in firmware 1.2 */ |
| #ifdef FIRMWARE_0_86 |
| #define MCU_DATA_PAGE 0x04 |
| static unsigned char es_map[16] = { |
| 0x08,0x09,0x0F,0x10,0x11,0x12,0x13,0x14, |
| 0x15,0x16,0x17,0x28,0x29,0x47,0x48,0x49 |
| }; //for A version 8/15/10 DT |
| #else |
| #define MCU_DATA_PAGE 0x01 |
| static unsigned char es_map[16] = { |
| 0x26,0x27,0x42,0x43,0x44,0x45,0x46,0x47, |
| 0x6A,0x51,0x52,0x53,0x57,0x58,0x59,0x5A |
| };//for D version 8/15/10 DT |
| #endif |
| |
| static unsigned char changed[5][256]; |
| |
| typedef struct { |
| unsigned char size; // total size should be less than 16 bytes |
| unsigned char ver_major; |
| unsigned char ver_minor; |
| unsigned char did; |
| // CH7036 device id |
| unsigned char rid; |
| // CH7036 revision id |
| unsigned char capbility; // FW capability; |
| // 0x01: EDID_Reading |
| unsigned char reserved; |
| } FW7036_CFG; |
| |
| |
| static uint8 g_DefRegMap[5][0x80] = { |
| //Page 0 : |
| { |
| 0x56, // Index = 0x00 ( page 0 ) |
| 0xF0, // Index = 0x01 ( page 0 ) |
| 0xF3, // Index = 0x02 ( page 0 ) |
| 0x00, // Index = 0x03 ( page 0 ) |
| 0x36, // Index = 0x04 ( page 0 ) |
| 0x58, // Index = 0x05 ( page 0 ) |
| 0xAC, // Index = 0x06 ( page 0 ) |
| 0xDD, // Index = 0x07 ( page 0 ) |
| 0x0F, // Index = 0x08 ( page 0 ) |
| 0x1F, // Index = 0x09 ( page 0 ) |
| 0xB4, // Index = 0x0A ( page 0 ) |
| 0x1A, // Index = 0x0B ( page 0 ) |
| 0x80, // Index = 0x0C ( page 0 ) |
| 0x20, // Index = 0x0D ( page 0 ) |
| 0x00, // Index = 0x0E ( page 0 ) |
| 0x10, // Index = 0x0F ( page 0 ) |
| 0x60, // Index = 0x10 ( page 0 ) |
| 0x11, // Index = 0x11 ( page 0 ) |
| 0xE0, // Index = 0x12 ( page 0 ) |
| 0x0D, // Index = 0x13 ( page 0 ) |
| 0x00, // Index = 0x14 ( page 0 ) |
| 0x0A, // Index = 0x15 ( page 0 ) |
| 0x02, // Index = 0x16 ( page 0 ) |
| 0x00, // Index = 0x17 ( page 0 ) |
| 0x00, // Index = 0x18 ( page 0 ) |
| 0xF8, // Index = 0x19 ( page 0 ) |
| 0x00, // Index = 0x1A ( page 0 ) |
| 0x00, // Index = 0x1B ( page 0 ) |
| 0x00, // Index = 0x1C ( page 0 ) |
| 0x00, // Index = 0x1D ( page 0 ) |
| 0x00, // Index = 0x1E ( page 0 ) |
| 0x1A, // Index = 0x1F ( page 0 ) |
| 0x80, // Index = 0x20 ( page 0 ) |
| 0x20, // Index = 0x21 ( page 0 ) |
| 0x00, // Index = 0x22 ( page 0 ) |
| 0x10, // Index = 0x23 ( page 0 ) |
| 0x60, // Index = 0x24 ( page 0 ) |
| 0x11, // Index = 0x25 ( page 0 ) |
| 0xE0, // Index = 0x26 ( page 0 ) |
| 0x0D, // Index = 0x27 ( page 0 ) |
| 0x00, // Index = 0x28 ( page 0 ) |
| 0x0A, // Index = 0x29 ( page 0 ) |
| 0x02, // Index = 0x2A ( page 0 ) |
| 0x08, // Index = 0x2B ( page 0 ) |
| 0x00, // Index = 0x2C ( page 0 ) |
| 0x00, // Index = 0x2D ( page 0 ) |
| 0x3C, // Index = 0x2E ( page 0 ) |
| 0x00, // Index = 0x2F ( page 0 ) |
| 0x01, // Index = 0x30 ( page 0 ) |
| 0x01, // Index = 0x31 ( page 0 ) |
| 0xC0, // Index = 0x32 ( page 0 ) |
| 0x01, // Index = 0x33 ( page 0 ) |
| 0x01, // Index = 0x34 ( page 0 ) |
| 0x80, // Index = 0x35 ( page 0 ) |
| 0x40, // Index = 0x36 ( page 0 ) |
| 0x40, // Index = 0x37 ( page 0 ) |
| 0x47, // Index = 0x38 ( page 0 ) |
| 0x88, // Index = 0x39 ( page 0 ) |
| 0x00, // Index = 0x3A ( page 0 ) |
| 0x00, // Index = 0x3B ( page 0 ) |
| 0x00, // Index = 0x3C ( page 0 ) |
| 0x86, // Index = 0x3D ( page 0 ) |
| 0x00, // Index = 0x3E ( page 0 ) |
| 0x11, // Index = 0x3F ( page 0 ) |
| 0x0E, // Index = 0x40 ( page 0 ) |
| 0x00, // Index = 0x41 ( page 0 ) |
| 0x00, // Index = 0x42 ( page 0 ) |
| 0x00, // Index = 0x43 ( page 0 ) |
| 0x00, // Index = 0x44 ( page 0 ) |
| 0x00, // Index = 0x45 ( page 0 ) |
| 0x00, // Index = 0x46 ( page 0 ) |
| 0x00, // Index = 0x47 ( page 0 ) |
| 0x00, // Index = 0x48 ( page 0 ) |
| 0x00, // Index = 0x49 ( page 0 ) |
| 0x00, // Index = 0x4A ( page 0 ) |
| 0x40, // Index = 0x4B ( page 0 ) |
| 0x40, // Index = 0x4C ( page 0 ) |
| 0x80, // Index = 0x4D ( page 0 ) |
| 0x00, // Index = 0x4E ( page 0 ) |
| 0x00, // Index = 0x4F ( page 0 ) |
| 0x00, // Index = 0x50 ( page 0 ) |
| 0x1F, // Index = 0x51 ( page 0 ) |
| 0xFF, // Index = 0x52 ( page 0 ) |
| 0x00, // Index = 0x53 ( page 0 ) |
| 0x80, // Index = 0x54 ( page 0 ) |
| 0x10, // Index = 0x55 ( page 0 ) |
| 0x60, // Index = 0x56 ( page 0 ) |
| 0x00, // Index = 0x57 ( page 0 ) |
| 0x0A, // Index = 0x58 ( page 0 ) |
| 0x02, // Index = 0x59 ( page 0 ) |
| 0x08, // Index = 0x5A ( page 0 ) |
| 0x00, // Index = 0x5B ( page 0 ) |
| 0x00, // Index = 0x5C ( page 0 ) |
| 0x00, // Index = 0x5D ( page 0 ) |
| 0x40, // Index = 0x5E ( page 0 ) |
| 0x00, // Index = 0x5F ( page 0 ) |
| 0x00, // Index = 0x60 ( page 0 ) |
| 0x00, // Index = 0x61 ( page 0 ) |
| 0x00, // Index = 0x62 ( page 0 ) |
| 0x01, // Index = 0x63 ( page 0 ) |
| 0x2D, // Index = 0x64 ( page 0 ) |
| 0x90, // Index = 0x65 ( page 0 ) |
| 0x20, // Index = 0x66 ( page 0 ) |
| 0x22, // Index = 0x67 ( page 0 ) |
| 0x44, // Index = 0x68 ( page 0 ) |
| 0x24, // Index = 0x69 ( page 0 ) |
| 0x40, // Index = 0x6A ( page 0 ) |
| 0x00, // Index = 0x6B ( page 0 ) |
| 0x10, // Index = 0x6C ( page 0 ) |
| 0x00, // Index = 0x6D ( page 0 ) |
| 0xA0, // Index = 0x6E ( page 0 ) |
| 0x4B, // Index = 0x6F ( page 0 ) |
| 0x18, // Index = 0x70 ( page 0 ) |
| 0x01, // Index = 0x71 ( page 0 ) |
| 0x00, // Index = 0x72 ( page 0 ) |
| 0x00, // Index = 0x73 ( page 0 ) |
| 0x20, // Index = 0x74 ( page 0 ) |
| 0x80, // Index = 0x75 ( page 0 ) |
| 0x18, // Index = 0x76 ( page 0 ) |
| 0x00, // Index = 0x77 ( page 0 ) |
| 0x00, // Index = 0x78 ( page 0 ) |
| 0x01, // Index = 0x79 ( page 0 ) |
| 0x00, // Index = 0x7A ( page 0 ) |
| 0x00, // Index = 0x7B ( page 0 ) |
| 0x00, // Index = 0x7C ( page 0 ) |
| 0xFF, // Index = 0x7D ( page 0 ) |
| 0x0F, // Index = 0x7E ( page 0 ) |
| 0x00, // Index = 0x7F ( page 0 ) |
| }, |
| |
| //Page 1: |
| { |
| 0x56, // Index = 0x00 ( page 1 ) |
| 0xF0, // Index = 0x01 ( page 1 ) |
| 0xF3, // Index = 0x02 ( page 1 ) |
| 0x01, // Index = 0x03 ( page 1 ) |
| 0x36, // Index = 0x04 ( page 1 ) |
| 0x58, // Index = 0x05 ( page 1 ) |
| 0xAC, // Index = 0x06 ( page 1 ) |
| 0x20, // Index = 0x07 ( page 1 ) |
| 0x00, // Index = 0x08 ( page 1 ) |
| 0x4B, // Index = 0x09 ( page 1 ) |
| 0x00, // Index = 0x0A ( page 1 ) |
| 0x6D, // Index = 0x0B ( page 1 ) |
| 0x6A, // Index = 0x0C ( page 1 ) |
| 0x51, // Index = 0x0D ( page 1 ) |
| 0x93, // Index = 0x0E ( page 1 ) |
| 0x1C, // Index = 0x0F ( page 1 ) |
| 0x00, // Index = 0x10 ( page 1 ) |
| 0x08, // Index = 0x11 ( page 1 ) |
| 0xC5, // Index = 0x12 ( page 1 ) |
| 0xA8, // Index = 0x13 ( page 1 ) |
| 0x91, // Index = 0x14 ( page 1 ) |
| 0x68, // Index = 0x15 ( page 1 ) |
| 0x29, // Index = 0x16 ( page 1 ) |
| 0x0E, // Index = 0x17 ( page 1 ) |
| 0xC8, // Index = 0x18 ( page 1 ) |
| 0x42, // Index = 0x19 ( page 1 ) |
| 0x6C, // Index = 0x1A ( page 1 ) |
| 0x00, // Index = 0x1B ( page 1 ) |
| 0x00, // Index = 0x1C ( page 1 ) |
| 0x00, // Index = 0x1D ( page 1 ) |
| 0x00, // Index = 0x1E ( page 1 ) |
| 0x00, // Index = 0x1F ( page 1 ) |
| 0x00, // Index = 0x20 ( page 1 ) |
| 0x10, // Index = 0x21 ( page 1 ) |
| 0x07, // Index = 0x22 ( page 1 ) |
| 0xFF, // Index = 0x23 ( page 1 ) |
| 0xB6, // Index = 0x24 ( page 1 ) |
| 0x10, // Index = 0x25 ( page 1 ) |
| 0x00, // Index = 0x26 ( page 1 ) |
| 0x00, // Index = 0x27 ( page 1 ) |
| 0x15, // Index = 0x28 ( page 1 ) |
| 0x18, // Index = 0x29 ( page 1 ) |
| 0x00, // Index = 0x2A ( page 1 ) |
| 0x00, // Index = 0x2B ( page 1 ) |
| 0x00, // Index = 0x2C ( page 1 ) |
| 0x00, // Index = 0x2D ( page 1 ) |
| 0x00, // Index = 0x2E ( page 1 ) |
| 0x00, // Index = 0x2F ( page 1 ) |
| 0x00, // Index = 0x30 ( page 1 ) |
| 0x00, // Index = 0x31 ( page 1 ) |
| 0x00, // Index = 0x32 ( page 1 ) |
| 0x00, // Index = 0x33 ( page 1 ) |
| 0x00, // Index = 0x34 ( page 1 ) |
| 0x00, // Index = 0x35 ( page 1 ) |
| 0x00, // Index = 0x36 ( page 1 ) |
| 0x00, // Index = 0x37 ( page 1 ) |
| 0x00, // Index = 0x38 ( page 1 ) |
| 0x00, // Index = 0x39 ( page 1 ) |
| 0x00, // Index = 0x3A ( page 1 ) |
| 0x0B, // Index = 0x3B ( page 1 ) |
| 0x00, // Index = 0x3C ( page 1 ) |
| 0x00, // Index = 0x3D ( page 1 ) |
| 0x00, // Index = 0x3E ( page 1 ) |
| 0x00, // Index = 0x3F ( page 1 ) |
| 0x08, // Index = 0x40 ( page 1 ) |
| 0x60, // Index = 0x41 ( page 1 ) |
| 0x14, // Index = 0x42 ( page 1 ) |
| 0x20, // Index = 0x43 ( page 1 ) |
| 0x00, // Index = 0x44 ( page 1 ) |
| 0x00, // Index = 0x45 ( page 1 ) |
| 0x20, // Index = 0x46 ( page 1 ) |
| 0x00, // Index = 0x47 ( page 1 ) |
| 0x49, // Index = 0x48 ( page 1 ) |
| 0x10, // Index = 0x49 ( page 1 ) |
| 0xFF, // Index = 0x4A ( page 1 ) |
| 0xFF, // Index = 0x4B ( page 1 ) |
| 0xFF, // Index = 0x4C ( page 1 ) |
| 0x00, // Index = 0x4D ( page 1 ) |
| 0x08, // Index = 0x4E ( page 1 ) |
| 0x00, // Index = 0x4F ( page 1 ) |
| 0x00, // Index = 0x50 ( page 1 ) |
| 0x00, // Index = 0x51 ( page 1 ) |
| 0x00, // Index = 0x52 ( page 1 ) |
| 0x00, // Index = 0x53 ( page 1 ) |
| 0x00, // Index = 0x54 ( page 1 ) |
| 0xA0, // Index = 0x55 ( page 1 ) |
| 0x00, // Index = 0x56 ( page 1 ) |
| 0x00, // Index = 0x57 ( page 1 ) |
| 0x00, // Index = 0x58 ( page 1 ) |
| 0x00, // Index = 0x59 ( page 1 ) |
| 0x00, // Index = 0x5A ( page 1 ) |
| 0x7A, // Index = 0x5B ( page 1 ) |
| 0x5E, // Index = 0x5C ( page 1 ) |
| 0x6E, // Index = 0x5D ( page 1 ) |
| 0x1F, // Index = 0x5E ( page 1 ) |
| 0x1F, // Index = 0x5F ( page 1 ) |
| 0x00, // Index = 0x60 ( page 1 ) |
| 0x00, // Index = 0x61 ( page 1 ) |
| 0x00, // Index = 0x62 ( page 1 ) |
| 0x20, // Index = 0x63 ( page 1 ) |
| 0x40, // Index = 0x64 ( page 1 ) |
| 0x40, // Index = 0x65 ( page 1 ) |
| 0x40, // Index = 0x66 ( page 1 ) |
| 0x00, // Index = 0x67 ( page 1 ) |
| 0x00, // Index = 0x68 ( page 1 ) |
| 0x00, // Index = 0x69 ( page 1 ) |
| 0x00, // Index = 0x6A ( page 1 ) |
| 0xFF, // Index = 0x6B ( page 1 ) |
| 0xFF, // Index = 0x6C ( page 1 ) |
| 0xFF, // Index = 0x6D ( page 1 ) |
| 0xFF, // Index = 0x6E ( page 1 ) |
| 0x50, // Index = 0x6F ( page 1 ) |
| 0x00, // Index = 0x70 ( page 1 ) |
| 0x00, // Index = 0x71 ( page 1 ) |
| 0x09, // Index = 0x72 ( page 1 ) |
| 0x00, // Index = 0x73 ( page 1 ) |
| 0x00, // Index = 0x74 ( page 1 ) |
| 0x70, // Index = 0x75 ( page 1 ) |
| 0x00, // Index = 0x76 ( page 1 ) |
| 0x50, // Index = 0x77 ( page 1 ) |
| 0x00, // Index = 0x78 ( page 1 ) |
| 0x98, // Index = 0x79 ( page 1 ) |
| 0x00, // Index = 0x7A ( page 1 ) |
| 0x98, // Index = 0x7B ( page 1 ) |
| 0xFF, // Index = 0x7C ( page 1 ) |
| 0x00, // Index = 0x7D ( page 1 ) |
| 0x00, // Index = 0x7E ( page 1 ) |
| 0x00, // Index = 0x7F ( page 1 ) |
| }, |
| |
| //Page 2: |
| { |
| 0x56, // Index = 0x00 ( page 2 ) |
| 0xF0, // Index = 0x01 ( page 2 ) |
| 0xF3, // Index = 0x02 ( page 2 ) |
| 0xFF, // Index = 0x03 ( page 2 ) |
| 0x36, // Index = 0x04 ( page 2 ) |
| 0x58, // Index = 0x05 ( page 2 ) |
| 0xAC, // Index = 0x06 ( page 2 ) |
| 0xFF, // Index = 0x07 ( page 2 ) |
| 0xFF, // Index = 0x08 ( page 2 ) |
| 0xFF, // Index = 0x09 ( page 2 ) |
| 0xFF, // Index = 0x0A ( page 2 ) |
| 0xFF, // Index = 0x0B ( page 2 ) |
| 0xFF, // Index = 0x0C ( page 2 ) |
| 0xFF, // Index = 0x0D ( page 2 ) |
| 0xFF, // Index = 0x0E ( page 2 ) |
| 0xFF, // Index = 0x0F ( page 2 ) |
| 0xFF, // Index = 0x10 ( page 2 ) |
| 0xFF, // Index = 0x11 ( page 2 ) |
| 0xFF, // Index = 0x12 ( page 2 ) |
| 0xFF, // Index = 0x13 ( page 2 ) |
| 0xFF, // Index = 0x14 ( page 2 ) |
| 0xFF, // Index = 0x15 ( page 2 ) |
| 0xFF, // Index = 0x16 ( page 2 ) |
| 0xFF, // Index = 0x17 ( page 2 ) |
| 0xFF, // Index = 0x18 ( page 2 ) |
| 0xFF, // Index = 0x19 ( page 2 ) |
| 0xFF, // Index = 0x1A ( page 2 ) |
| 0xFF, // Index = 0x1B ( page 2 ) |
| 0xFF, // Index = 0x1C ( page 2 ) |
| 0xFF, // Index = 0x1D ( page 2 ) |
| 0xFF, // Index = 0x1E ( page 2 ) |
| 0xFF, // Index = 0x1F ( page 2 ) |
| 0xFF, // Index = 0x20 ( page 2 ) |
| 0xFF, // Index = 0x21 ( page 2 ) |
| 0xFF, // Index = 0x22 ( page 2 ) |
| 0xFF, // Index = 0x23 ( page 2 ) |
| 0xFF, // Index = 0x24 ( page 2 ) |
| 0xFF, // Index = 0x25 ( page 2 ) |
| 0xFF, // Index = 0x26 ( page 2 ) |
| 0xFF, // Index = 0x27 ( page 2 ) |
| 0xFF, // Index = 0x28 ( page 2 ) |
| 0xFF, // Index = 0x29 ( page 2 ) |
| 0xFF, // Index = 0x2A ( page 2 ) |
| 0xFF, // Index = 0x2B ( page 2 ) |
| 0xFF, // Index = 0x2C ( page 2 ) |
| 0xFF, // Index = 0x2D ( page 2 ) |
| 0xFF, // Index = 0x2E ( page 2 ) |
| 0xFF, // Index = 0x2F ( page 2 ) |
| 0xFF, // Index = 0x30 ( page 2 ) |
| 0xFF, // Index = 0x31 ( page 2 ) |
| 0xFF, // Index = 0x32 ( page 2 ) |
| 0xFF, // Index = 0x33 ( page 2 ) |
| 0xFF, // Index = 0x34 ( page 2 ) |
| 0xFF, // Index = 0x35 ( page 2 ) |
| 0xFF, // Index = 0x36 ( page 2 ) |
| 0xFF, // Index = 0x37 ( page 2 ) |
| 0xFF, // Index = 0x38 ( page 2 ) |
| 0xFF, // Index = 0x39 ( page 2 ) |
| 0xFF, // Index = 0x3A ( page 2 ) |
| 0xFF, // Index = 0x3B ( page 2 ) |
| 0xFF, // Index = 0x3C ( page 2 ) |
| 0xFF, // Index = 0x3D ( page 2 ) |
| 0xFF, // Index = 0x3E ( page 2 ) |
| 0xFF, // Index = 0x3F ( page 2 ) |
| 0xFF, // Index = 0x40 ( page 2 ) |
| 0xFF, // Index = 0x41 ( page 2 ) |
| 0xFF, // Index = 0x42 ( page 2 ) |
| 0xFF, // Index = 0x43 ( page 2 ) |
| 0xFF, // Index = 0x44 ( page 2 ) |
| 0xFF, // Index = 0x45 ( page 2 ) |
| 0xFF, // Index = 0x46 ( page 2 ) |
| 0xFF, // Index = 0x47 ( page 2 ) |
| 0xFF, // Index = 0x48 ( page 2 ) |
| 0xFF, // Index = 0x49 ( page 2 ) |
| 0xFF, // Index = 0x4A ( page 2 ) |
| 0xFF, // Index = 0x4B ( page 2 ) |
| 0xFF, // Index = 0x4C ( page 2 ) |
| 0xFF, // Index = 0x4D ( page 2 ) |
| 0xFF, // Index = 0x4E ( page 2 ) |
| 0xFF, // Index = 0x4F ( page 2 ) |
| 0xFF, // Index = 0x50 ( page 2 ) |
| 0xFF, // Index = 0x51 ( page 2 ) |
| 0xFF, // Index = 0x52 ( page 2 ) |
| 0xFF, // Index = 0x53 ( page 2 ) |
| 0xFF, // Index = 0x54 ( page 2 ) |
| 0xFF, // Index = 0x55 ( page 2 ) |
| 0xFF, // Index = 0x56 ( page 2 ) |
| 0xFF, // Index = 0x57 ( page 2 ) |
| 0xFF, // Index = 0x58 ( page 2 ) |
| 0xFF, // Index = 0x59 ( page 2 ) |
| 0xFF, // Index = 0x5A ( page 2 ) |
| 0xFF, // Index = 0x5B ( page 2 ) |
| 0xFF, // Index = 0x5C ( page 2 ) |
| 0xFF, // Index = 0x5D ( page 2 ) |
| 0xFF, // Index = 0x5E ( page 2 ) |
| 0xFF, // Index = 0x5F ( page 2 ) |
| 0xFF, // Index = 0x60 ( page 2 ) |
| 0xFF, // Index = 0x61 ( page 2 ) |
| 0xFF, // Index = 0x62 ( page 2 ) |
| 0xFF, // Index = 0x63 ( page 2 ) |
| 0xFF, // Index = 0x64 ( page 2 ) |
| 0xFF, // Index = 0x65 ( page 2 ) |
| 0xFF, // Index = 0x66 ( page 2 ) |
| 0xFF, // Index = 0x67 ( page 2 ) |
| 0xFF, // Index = 0x68 ( page 2 ) |
| 0xFF, // Index = 0x69 ( page 2 ) |
| 0xFF, // Index = 0x6A ( page 2 ) |
| 0xFF, // Index = 0x6B ( page 2 ) |
| 0xFF, // Index = 0x6C ( page 2 ) |
| 0xFF, // Index = 0x6D ( page 2 ) |
| 0xFF, // Index = 0x6E ( page 2 ) |
| 0xFF, // Index = 0x6F ( page 2 ) |
| 0xFF, // Index = 0x70 ( page 2 ) |
| 0xFF, // Index = 0x71 ( page 2 ) |
| 0xFF, // Index = 0x72 ( page 2 ) |
| 0xFF, // Index = 0x73 ( page 2 ) |
| 0xFF, // Index = 0x74 ( page 2 ) |
| 0xFF, // Index = 0x75 ( page 2 ) |
| 0xFF, // Index = 0x76 ( page 2 ) |
| 0xFF, // Index = 0x77 ( page 2 ) |
| 0xFF, // Index = 0x78 ( page 2 ) |
| 0xFF, // Index = 0x79 ( page 2 ) |
| 0xFF, // Index = 0x7A ( page 2 ) |
| 0xFF, // Index = 0x7B ( page 2 ) |
| 0xFF, // Index = 0x7C ( page 2 ) |
| 0xFF, // Index = 0x7D ( page 2 ) |
| 0xFF, // Index = 0x7E ( page 2 ) |
| 0xFF, // Index = 0x7F ( page 2 ) |
| }, |
| |
| //Page 3: |
| { |
| 0x56, // Index = 0x00 ( page 3 ) |
| 0xF0, // Index = 0x01 ( page 3 ) |
| 0xF3, // Index = 0x02 ( page 3 ) |
| 0x03, // Index = 0x03 ( page 3 ) |
| 0x36, // Index = 0x04 ( page 3 ) |
| 0x58, // Index = 0x05 ( page 3 ) |
| 0xAC, // Index = 0x06 ( page 3 ) |
| 0x00, // Index = 0x07 ( page 3 ) |
| 0x00, // Index = 0x08 ( page 3 ) |
| 0x00, // Index = 0x09 ( page 3 ) |
| 0x00, // Index = 0x0A ( page 3 ) |
| 0x00, // Index = 0x0B ( page 3 ) |
| 0xFF, // Index = 0x0C ( page 3 ) |
| 0x00, // Index = 0x0D ( page 3 ) |
| 0x03, // Index = 0x0E ( page 3 ) |
| 0x19, // Index = 0x0F ( page 3 ) |
| 0x40, // Index = 0x10 ( page 3 ) |
| 0x00, // Index = 0x11 ( page 3 ) |
| 0x00, // Index = 0x12 ( page 3 ) |
| 0x00, // Index = 0x13 ( page 3 ) |
| 0x00, // Index = 0x14 ( page 3 ) |
| 0x00, // Index = 0x15 ( page 3 ) |
| 0x00, // Index = 0x16 ( page 3 ) |
| 0x00, // Index = 0x17 ( page 3 ) |
| 0x00, // Index = 0x18 ( page 3 ) |
| 0x00, // Index = 0x19 ( page 3 ) |
| 0x00, // Index = 0x1A ( page 3 ) |
| 0x00, // Index = 0x1B ( page 3 ) |
| 0x00, // Index = 0x1C ( page 3 ) |
| 0x00, // Index = 0x1D ( page 3 ) |
| 0x00, // Index = 0x1E ( page 3 ) |
| 0x00, // Index = 0x1F ( page 3 ) |
| 0x00, // Index = 0x20 ( page 3 ) |
| 0x00, // Index = 0x21 ( page 3 ) |
| 0x00, // Index = 0x22 ( page 3 ) |
| 0x00, // Index = 0x23 ( page 3 ) |
| 0x00, // Index = 0x24 ( page 3 ) |
| 0x11, // Index = 0x25 ( page 3 ) |
| 0xFF, // Index = 0x26 ( page 3 ) |
| 0xFF, // Index = 0x27 ( page 3 ) |
| 0xFF, // Index = 0x28 ( page 3 ) |
| 0xFF, // Index = 0x29 ( page 3 ) |
| 0xFF, // Index = 0x2A ( page 3 ) |
| 0xFF, // Index = 0x2B ( page 3 ) |
| 0xFF, // Index = 0x2C ( page 3 ) |
| 0xFF, // Index = 0x2D ( page 3 ) |
| 0xFF, // Index = 0x2E ( page 3 ) |
| 0xFF, // Index = 0x2F ( page 3 ) |
| 0xFF, // Index = 0x30 ( page 3 ) |
| 0xFF, // Index = 0x31 ( page 3 ) |
| 0xFF, // Index = 0x32 ( page 3 ) |
| 0xFF, // Index = 0x33 ( page 3 ) |
| 0xFF, // Index = 0x34 ( page 3 ) |
| 0xFF, // Index = 0x35 ( page 3 ) |
| 0xFF, // Index = 0x36 ( page 3 ) |
| 0xFF, // Index = 0x37 ( page 3 ) |
| 0xFF, // Index = 0x38 ( page 3 ) |
| 0xFF, // Index = 0x39 ( page 3 ) |
| 0xFF, // Index = 0x3A ( page 3 ) |
| 0xFF, // Index = 0x3B ( page 3 ) |
| 0xFF, // Index = 0x3C ( page 3 ) |
| 0xFF, // Index = 0x3D ( page 3 ) |
| 0xFF, // Index = 0x3E ( page 3 ) |
| 0xFF, // Index = 0x3F ( page 3 ) |
| 0xFF, // Index = 0x40 ( page 3 ) |
| 0x09, // Index = 0x41 ( page 3 ) |
| 0x1D, // Index = 0x42 ( page 3 ) |
| 0x0F, // Index = 0x43 ( page 3 ) |
| 0x00, // Index = 0x44 ( page 3 ) |
| 0xFF, // Index = 0x45 ( page 3 ) |
| 0xFF, // Index = 0x46 ( page 3 ) |
| 0xFF, // Index = 0x47 ( page 3 ) |
| 0xFF, // Index = 0x48 ( page 3 ) |
| 0xFF, // Index = 0x49 ( page 3 ) |
| 0xFF, // Index = 0x4A ( page 3 ) |
| 0xFF, // Index = 0x4B ( page 3 ) |
| 0xFF, // Index = 0x4C ( page 3 ) |
| 0xFF, // Index = 0x4D ( page 3 ) |
| 0xFF, // Index = 0x4E ( page 3 ) |
| 0xFF, // Index = 0x4F ( page 3 ) |
| 0xFF, // Index = 0x50 ( page 3 ) |
| 0xFF, // Index = 0x51 ( page 3 ) |
| 0xFF, // Index = 0x52 ( page 3 ) |
| 0xFF, // Index = 0x53 ( page 3 ) |
| 0xFF, // Index = 0x54 ( page 3 ) |
| 0xFF, // Index = 0x55 ( page 3 ) |
| 0xFF, // Index = 0x56 ( page 3 ) |
| 0xFF, // Index = 0x57 ( page 3 ) |
| 0xFF, // Index = 0x58 ( page 3 ) |
| 0xFF, // Index = 0x59 ( page 3 ) |
| 0xFF, // Index = 0x5A ( page 3 ) |
| 0xFF, // Index = 0x5B ( page 3 ) |
| 0xFF, // Index = 0x5C ( page 3 ) |
| 0xFF, // Index = 0x5D ( page 3 ) |
| 0xFF, // Index = 0x5E ( page 3 ) |
| 0xFF, // Index = 0x5F ( page 3 ) |
| 0xFF, // Index = 0x60 ( page 3 ) |
| 0xFF, // Index = 0x61 ( page 3 ) |
| 0xFF, // Index = 0x62 ( page 3 ) |
| 0xFF, // Index = 0x63 ( page 3 ) |
| 0xFF, // Index = 0x64 ( page 3 ) |
| 0xFF, // Index = 0x65 ( page 3 ) |
| 0xFF, // Index = 0x66 ( page 3 ) |
| 0xFF, // Index = 0x67 ( page 3 ) |
| 0xFF, // Index = 0x68 ( page 3 ) |
| 0xFF, // Index = 0x69 ( page 3 ) |
| 0xFF, // Index = 0x6A ( page 3 ) |
| 0xFF, // Index = 0x6B ( page 3 ) |
| 0xFF, // Index = 0x6C ( page 3 ) |
| 0xFF, // Index = 0x6D ( page 3 ) |
| 0x00, // Index = 0x6E ( page 3 ) |
| 0x00, // Index = 0x6F ( page 3 ) |
| 0xFF, // Index = 0x70 ( page 3 ) |
| 0xF8, // Index = 0x71 ( page 3 ) |
| 0xFF, // Index = 0x72 ( page 3 ) |
| 0x00, // Index = 0x73 ( page 3 ) |
| 0x02, // Index = 0x74 ( page 3 ) |
| 0xFF, // Index = 0x75 ( page 3 ) |
| 0x00, // Index = 0x76 ( page 3 ) |
| 0x00, // Index = 0x77 ( page 3 ) |
| 0x00, // Index = 0x78 ( page 3 ) |
| 0xFF, // Index = 0x79 ( page 3 ) |
| 0xFF, // Index = 0x7A ( page 3 ) |
| 0xFF, // Index = 0x7B ( page 3 ) |
| 0xFF, // Index = 0x7C ( page 3 ) |
| 0xFF, // Index = 0x7D ( page 3 ) |
| 0xFF, // Index = 0x7E ( page 3 ) |
| 0xFF, // Index = 0x7F ( page 3 ) |
| }, |
| |
| //Page 4: |
| { |
| 0x56, // Index = 0x00 ( page 4 ) |
| 0xF0, // Index = 0x01 ( page 4 ) |
| 0xF3, // Index = 0x02 ( page 4 ) |
| 0x04, // Index = 0x03 ( page 4 ) |
| 0x36, // Index = 0x04 ( page 4 ) |
| 0x58, // Index = 0x05 ( page 4 ) |
| 0xAC, // Index = 0x06 ( page 4 ) |
| 0xFF, // Index = 0x07 ( page 4 ) |
| 0x00, // Index = 0x08 ( page 4 ) |
| 0x00, // Index = 0x09 ( page 4 ) |
| 0x00, // Index = 0x0A ( page 4 ) |
| 0x00, // Index = 0x0B ( page 4 ) |
| 0x00, // Index = 0x0C ( page 4 ) |
| 0x00, // Index = 0x0D ( page 4 ) |
| 0xC0, // Index = 0x0E ( page 4 ) |
| 0x00, // Index = 0x0F ( page 4 ) |
| 0x00, // Index = 0x10 ( page 4 ) |
| 0x00, // Index = 0x11 ( page 4 ) |
| 0x00, // Index = 0x12 ( page 4 ) |
| 0x00, // Index = 0x13 ( page 4 ) |
| 0x00, // Index = 0x14 ( page 4 ) |
| 0x00, // Index = 0x15 ( page 4 ) |
| 0x00, // Index = 0x16 ( page 4 ) |
| 0x00, // Index = 0x17 ( page 4 ) |
| 0xFF, // Index = 0x18 ( page 4 ) |
| 0xFF, // Index = 0x19 ( page 4 ) |
| 0xFF, // Index = 0x1A ( page 4 ) |
| 0xFF, // Index = 0x1B ( page 4 ) |
| 0xFF, // Index = 0x1C ( page 4 ) |
| 0xFF, // Index = 0x1D ( page 4 ) |
| 0xFF, // Index = 0x1E ( page 4 ) |
| 0xFF, // Index = 0x1F ( page 4 ) |
| 0xFF, // Index = 0x20 ( page 4 ) |
| 0xFF, // Index = 0x21 ( page 4 ) |
| 0xFF, // Index = 0x22 ( page 4 ) |
| 0xFF, // Index = 0x23 ( page 4 ) |
| 0xFF, // Index = 0x24 ( page 4 ) |
| 0xFF, // Index = 0x25 ( page 4 ) |
| 0xFF, // Index = 0x26 ( page 4 ) |
| 0xFF, // Index = 0x27 ( page 4 ) |
| 0x00, // Index = 0x28 ( page 4 ) |
| 0x00, // Index = 0x29 ( page 4 ) |
| 0x4F, // Index = 0x2A ( page 4 ) |
| 0x07, // Index = 0x2B ( page 4 ) |
| 0x4F, // Index = 0x2C ( page 4 ) |
| 0x07, // Index = 0x2D ( page 4 ) |
| 0x3B, // Index = 0x2E ( page 4 ) |
| 0x07, // Index = 0x2F ( page 4 ) |
| 0x3B, // Index = 0x30 ( page 4 ) |
| 0x07, // Index = 0x31 ( page 4 ) |
| 0x50, // Index = 0x32 ( page 4 ) |
| 0x00, // Index = 0x33 ( page 4 ) |
| 0x50, // Index = 0x34 ( page 4 ) |
| 0x00, // Index = 0x35 ( page 4 ) |
| 0x10, // Index = 0x36 ( page 4 ) |
| 0x00, // Index = 0x37 ( page 4 ) |
| 0x00, // Index = 0x38 ( page 4 ) |
| 0x10, // Index = 0x39 ( page 4 ) |
| 0x00, // Index = 0x3A ( page 4 ) |
| 0x00, // Index = 0x3B ( page 4 ) |
| 0x00, // Index = 0x3C ( page 4 ) |
| 0x00, // Index = 0x3D ( page 4 ) |
| 0x00, // Index = 0x3E ( page 4 ) |
| 0x00, // Index = 0x3F ( page 4 ) |
| 0x00, // Index = 0x40 ( page 4 ) |
| 0xFF, // Index = 0x41 ( page 4 ) |
| 0xFF, // Index = 0x42 ( page 4 ) |
| 0xFF, // Index = 0x43 ( page 4 ) |
| 0xFF, // Index = 0x44 ( page 4 ) |
| 0x00, // Index = 0x45 ( page 4 ) |
| 0x03, // Index = 0x46 ( page 4 ) |
| 0x00, // Index = 0x47 ( page 4 ) |
| 0x00, // Index = 0x48 ( page 4 ) |
| 0x00, // Index = 0x49 ( page 4 ) |
| 0x24, // Index = 0x4A ( page 4 ) |
| 0x00, // Index = 0x4B ( page 4 ) |
| 0x40, // Index = 0x4C ( page 4 ) |
| 0xFF, // Index = 0x4D ( page 4 ) |
| 0xFF, // Index = 0x4E ( page 4 ) |
| 0x7F, // Index = 0x4F ( page 4 ) |
| 0x56, // Index = 0x50 ( page 4 ) |
| 0x80, // Index = 0x51 ( page 4 ) |
| 0x3F, // Index = 0x52 ( page 4 ) |
| 0x00, // Index = 0x53 ( page 4 ) |
| 0x84, // Index = 0x54 ( page 4 ) |
| 0x60, // Index = 0x55 ( page 4 ) |
| 0xAF, // Index = 0x56 ( page 4 ) |
| 0x00, // Index = 0x57 ( page 4 ) |
| 0x00, // Index = 0x58 ( page 4 ) |
| 0x80, // Index = 0x59 ( page 4 ) |
| 0x94, // Index = 0x5A ( page 4 ) |
| 0x00, // Index = 0x5B ( page 4 ) |
| 0x80, // Index = 0x5C ( page 4 ) |
| 0x00, // Index = 0x5D ( page 4 ) |
| 0x05, // Index = 0x5E ( page 4 ) |
| 0x38, // Index = 0x5F ( page 4 ) |
| 0x01, // Index = 0x60 ( page 4 ) |
| 0x83, // Index = 0x61 ( page 4 ) |
| 0x11, // Index = 0x62 ( page 4 ) |
| 0x01, // Index = 0x63 ( page 4 ) |
| 0x80, // Index = 0x64 ( page 4 ) |
| 0x90, // Index = 0x65 ( page 4 ) |
| 0x00, // Index = 0x66 ( page 4 ) |
| 0x40, // Index = 0x67 ( page 4 ) |
| 0x4A, // Index = 0x68 ( page 4 ) |
| 0xE4, // Index = 0x69 ( page 4 ) |
| 0x00, // Index = 0x6A ( page 4 ) |
| 0x00, // Index = 0x6B ( page 4 ) |
| 0x00, // Index = 0x6C ( page 4 ) |
| 0x00, // Index = 0x6D ( page 4 ) |
| 0x89, // Index = 0x6E ( page 4 ) |
| 0x10, // Index = 0x6F ( page 4 ) |
| 0xAC, // Index = 0x70 ( page 4 ) |
| 0x00, // Index = 0x71 ( page 4 ) |
| 0xE0, // Index = 0x72 ( page 4 ) |
| 0x80, // Index = 0x73 ( page 4 ) |
| 0x80, // Index = 0x74 ( page 4 ) |
| 0x19, // Index = 0x75 ( page 4 ) |
| 0x7D, // Index = 0x76 ( page 4 ) |
| 0x00, // Index = 0x77 ( page 4 ) |
| 0xFF, // Index = 0x78 ( page 4 ) |
| 0xFF, // Index = 0x79 ( page 4 ) |
| 0xFF, // Index = 0x7A ( page 4 ) |
| 0xFF, // Index = 0x7B ( page 4 ) |
| 0xFF, // Index = 0x7C ( page 4 ) |
| 0xFF, // Index = 0x7D ( page 4 ) |
| 0x00, // Index = 0x7E ( page 4 ) |
| 0x0C, // Index = 0x7F ( page 4 ) |
| }, |
| }; |
| |
| static unsigned char GenDefault(int p, int r) |
| { |
| if ((p < 5) && (r < 128)) |
| return g_DefRegMap[p][r]; |
| return 0; |
| } |
| |
| |
| static int smbus_write_byte_data(int dev, int reg, int data) |
| { |
| struct i2c_smbus_ioctl_data iodata; |
| union i2c_smbus_data value; |
| int res; |
| |
| if (dev < 0) { |
| printf("WR_%d {0x%02x, 0x%02x} -> %d\n", ch7036_cur_page, reg, data, 0); |
| return 0; |
| } |
| |
| value.byte = data; |
| iodata.read_write = I2C_SMBUS_WRITE; |
| iodata.command = reg; |
| iodata.size = I2C_SMBUS_BYTE_DATA; |
| iodata.data = &value; |
| res = ioctl(dev, I2C_SMBUS, &iodata); |
| if (res < 0) |
| fprintf(stderr, "Write byte fail (%d, %02x, %02x): %s", |
| dev, reg, data, strerror(errno)); |
| if (ch7036_debugi2c) |
| printf("WR_%d {0x%02x, 0x%02x} -> %d\n", ch7036_cur_page, reg, data, res); |
| return res; |
| } |
| |
| static int smbus_write_word_data(int dev, int reg, int data) |
| { |
| struct i2c_smbus_ioctl_data iodata; |
| union i2c_smbus_data value; |
| int res; |
| |
| if (dev < 0) { |
| printf("WR_%d {0x%02x, 0x%04x} -> %d\n", ch7036_cur_page, reg, data, 0); |
| return 0; |
| } |
| |
| value.word = data; |
| iodata.read_write = I2C_SMBUS_WRITE; |
| iodata.command = reg; |
| iodata.size = I2C_SMBUS_WORD_DATA; |
| iodata.data = &value; |
| res = ioctl(dev, I2C_SMBUS, &iodata); |
| if (res < 0) |
| fprintf(stderr, "Write word fail (%d, %04x, %02x): %s", |
| dev, reg, data, strerror(errno)); |
| if (ch7036_debugi2c) |
| printf("WR_%d {0x%02x, 0x%04x} -> %d\n", ch7036_cur_page, reg, data, res); |
| return res; |
| } |
| |
| #ifdef FASTLOAD |
| static int smbus_write_reg_bytes(int dev, int reg, int size, |
| unsigned char *data) |
| { |
| struct i2c_smbus_ioctl_data iodata; |
| union i2c_smbus_data value; |
| int res; |
| |
| if (size > I2C_SMBUS_BLOCK_MAX) { |
| fprintf(stderr, "Bad call to smbus_write_reg_bytes with size %d\n", size); |
| return -1; |
| } |
| |
| if (dev < 0) { |
| printf("WR_%d {0x%02x, 0x%02x,...[%d]} -> %d\n", |
| ch7036_cur_page, reg, data[0], size, 0); |
| return 0; |
| } |
| |
| memcpy(&value.block[1], data, size); |
| value.block[0] = size; |
| iodata.read_write = I2C_SMBUS_WRITE; |
| iodata.command = reg; |
| iodata.size = I2C_SMBUS_I2C_BLOCK_DATA; |
| iodata.data = &value; |
| res = ioctl(dev, I2C_SMBUS, &iodata); |
| if (res < 0) |
| fprintf(stderr, "Write bytes fail (%d, %02x, %02x,...[%d]): %s\n", |
| dev, reg, data[0], size, strerror(errno)); |
| if (ch7036_debugi2c) |
| printf("WR_%d {0x%02x, 0x%02x,...[%d]} -> %d\n", |
| ch7036_cur_page, reg, data[0], size, res); |
| return res; |
| } |
| #endif |
| |
| static int smbus_read_byte_data(int dev, int reg) |
| { |
| struct i2c_smbus_ioctl_data iodata; |
| union i2c_smbus_data value; |
| |
| if (dev < 0) { |
| printf("RD_%d {0x%02x} -> 0x%02x\n", ch7036_cur_page, reg, 0); |
| return 0; |
| } |
| |
| iodata.read_write = I2C_SMBUS_READ; |
| iodata.command = reg; |
| iodata.size = I2C_SMBUS_BYTE_DATA; |
| iodata.data = &value; |
| if (ioctl(dev, I2C_SMBUS, &iodata) < 0) { |
| fprintf(stderr, "Read byte fail (%d, %02x): %s", |
| dev, reg, strerror(errno)); |
| return -1; |
| } |
| if (ch7036_debugi2c) |
| printf("RD_%d {0x%02x} -> 0x%02x\n", ch7036_cur_page, reg, value.byte); |
| return value.byte; |
| } |
| |
| |
| int ch_write_reg(int dev, int page, int reg, int data) |
| { |
| int res; |
| |
| if (((page < 1) || (page > 4)) && (reg != CH7036_PAGE)) |
| return -1; |
| |
| if ((page != ch7036_cur_page) && (reg != CH7036_PAGE)) { |
| if (ch_write_reg(dev, ch7036_cur_page, CH7036_PAGE, ch_page_map[page]) < 0) |
| return -1; |
| } |
| |
| res = smbus_write_byte_data(dev, reg, data); |
| |
| if (res < 0) |
| return -1; |
| |
| if (reg == CH7036_PAGE) { |
| ch7036_cur_page = ch_page_revmap[data & 7]; |
| } |
| return 0; |
| } |
| |
| int ch_read_reg(int dev, int page, int reg) |
| { |
| int res; |
| |
| if ((page < 1) || (page > 4)) |
| return -1; |
| |
| if (page != ch7036_cur_page) { |
| if (ch_write_reg(dev, ch7036_cur_page, CH7036_PAGE, ch_page_map[page]) < 0) |
| return -1; |
| } |
| res = smbus_read_byte_data(dev, reg); |
| |
| return res; |
| } |
| |
| int ch_write_reg_sequence (int dev, struct reg_ch7036* seq) |
| { |
| int i, res; |
| int n_regs = N_REGS_IN_SEQ(seq); |
| |
| for (i=1; i <= n_regs; i++) { |
| res = smbus_write_byte_data(dev, seq[i].index, seq[i].value); |
| changed[ch_page_map[ch7036_cur_page]][seq[i].index] = 1; |
| |
| if (res < 0) |
| return -1; |
| if (seq[i].index == CH7036_PAGE) |
| ch7036_cur_page = ch_page_revmap[seq[i].value & 7]; |
| } |
| return 0; |
| } |
| |
| int ch_restore_notin_seq (int dev, struct reg_ch7036* seq, int verbose) |
| { |
| int i, j; |
| int n_regs = N_REGS_IN_SEQ(seq); |
| int loc_cp = ch7036_cur_page; |
| int err; |
| int nwritten = 0; |
| |
| /* Clear the changed vector for anything we are about to write */ |
| for (i=1; i <= n_regs; i++) { |
| changed[ch_page_map[loc_cp]][seq[i].index] = 0; |
| if (seq[i].index == CH7036_PAGE) |
| loc_cp = ch_page_revmap[seq[i].value & 7]; |
| } |
| |
| for(j=0; j < 5; j++) |
| for(i=0; i < 128; i++) if (changed[j][i]) { |
| if (i == CH7036_PAGE) continue; |
| err = ch_write_reg(dev, ch_page_revmap[j], i, GenDefault(j, i)); |
| if (err != 0) return err; |
| // Now at default, so it is no longer changed |
| changed[j][i] = 0; |
| nwritten++; |
| } |
| if (verbose) |
| printf("... Restored %d registers\n", nwritten); |
| return 0; |
| } |
| |
| int ch_remove_last_reg(struct reg_ch7036* seq, int page, int reg) |
| { |
| int i; |
| int n_regs = N_REGS_IN_SEQ(seq); |
| int cp = -1; |
| int last_found = -1; |
| |
| /* Some registers are in the list multiple times */ |
| /* Need to remove the last one */ |
| /* But must parse forward to follow page changes */ |
| for (i=1; i <= n_regs; i++) { |
| if ((cp == page) && (seq[i].index == reg)) |
| last_found = i; |
| if (seq[i].index == CH7036_PAGE) |
| cp = ch_page_revmap[seq[i].value & 7]; |
| } |
| if (last_found > 0) { |
| int ov = seq[last_found].value; |
| for (i=last_found; i < n_regs; i++) seq[i] = seq[i+1]; |
| n_regs--; |
| seq[0].index = (n_regs >> 8); |
| seq[0].value = (n_regs & 0xff); |
| return ov; |
| } |
| return -1; |
| } |
| int ch_change_reg(struct reg_ch7036* seq, int page, int reg, |
| int andv, int orv) |
| { |
| int i; |
| int n_regs = N_REGS_IN_SEQ(seq); |
| int cp = -1; |
| int last_found = -1; |
| |
| /* Some registers are in the list multiple times */ |
| /* Need to modify the last one to have an effect */ |
| /* But must parse forward to follow page changes */ |
| for (i=1; i <= n_regs; i++) { |
| if ((cp == page) && (seq[i].index == reg)) |
| last_found = i; |
| if (seq[i].index == CH7036_PAGE) |
| cp = ch_page_revmap[seq[i].value & 7]; |
| } |
| if (last_found > 0) { |
| int ov = seq[last_found].value; |
| seq[last_found].value = (ov & andv) | orv; |
| return ov; |
| } |
| return -1; |
| } |
| |
| |
| void ch_reset_datapath (int dev) |
| { |
| int res = ch_read_reg(dev, CH7036_RESET); |
| /* Reset the datapath then remove reset */ |
| ch_write_reg(dev, CH7036_RESET, res & ~0x1); |
| ch_write_reg(dev, CH7036_RESET, res | 0x1); |
| } |
| |
| /* Email from Chrontel 5/20 to reset to defaults */ |
| /* Note: will need to redo step1 after this! */ |
| void ch_reset_todefault (int dev) |
| { |
| int i; |
| int res = ch_read_reg(dev, CH7036_RESET); |
| /* Reset registers then remove reset */ |
| ch_write_reg(dev, CH7036_RESET, res & ~0x2); |
| ch_write_reg(dev, CH7036_RESET, res | 0x2); |
| |
| for(i=0; i < 256; i++) |
| changed[0][i] = changed[1][i] = changed[2][i] = |
| changed[3][i] = changed[4][i] = 0; |
| |
| } |
| |
| /* Turn the monitor on */ |
| void ch_monitor_on(int dev, int hdmi_out, int verbose) |
| { |
| int old; |
| int needed_bit_value; |
| |
| ch_write_reg(dev, CH7036_PWRST2, 0xD0); // HDMI driver, SDRAM. SPDIF on |
| ch_write_reg(dev, CH7036_PWRST3, 0x0F); // VGA dac powered down |
| ch_write_reg(dev, CH7036_PWRST4, 0x02); // SDRAM, HDMI power on, RGB off |
| |
| ch_write_reg(dev, CH7036_MAGIC2_0E, 0x13); // MAGIC |
| ch_write_reg(dev, CH7036_SDTIME1, 0x20); |
| |
| ch_write_reg(dev, CH7036_PWRSTATE1, 0x84); // Normal (pll on) |
| ch_reset_datapath(dev); |
| |
| /* reset datapath seems to mess with this bit with some fw revs */ |
| needed_bit_value = hdmi_out ? 0x04 : 0; |
| old = ch_read_reg(dev, CH7036_PWRST5); |
| if ((old & 0x04) != needed_bit_value) { |
| if (verbose) printf("Need %sI out: change PWRST5 from 0x%x to 0x%x\n", |
| hdmi_out ? "HDM" : "DV", |
| old, (old & ~0x04) | needed_bit_value); |
| ch_write_reg(dev, CH7036_PWRST5, (old & ~0x04) | needed_bit_value); |
| } |
| } |
| |
| /* Turn the monitor off */ |
| void ch_monitor_off(int dev) |
| { |
| ch_write_reg(dev, CH7036_PWRST2, 0xDF); // HDMI driver, SDRAM. SPDIF off |
| ch_write_reg(dev, CH7036_PWRST3, 0xFF); // VGA dac powered down |
| ch_write_reg(dev, CH7036_PWRST4, 0x7F); // Stop hdmi,scaler, pwr down |
| |
| ch_write_reg(dev, CH7036_MAGIC2_0E, 0x93); // MAGIC |
| ch_write_reg(dev, CH7036_SDTIME1, 0x29); // HDMI driver, PLL power off |
| |
| ch_write_reg(dev, CH7036_PWRSTATE1, 0x94); // pll power down |
| } |
| |
| /* Turn the monitor off but keep DDC running so EDID can still be read */ |
| void ch_monitor_off_keep_ddc(int dev) |
| { |
| ch_write_reg(dev, CH7036_PWRST2, 0xDF); // HDMI driver, SDRAM. SPDIF off |
| ch_write_reg(dev, CH7036_PWRST3, 0xFF); // VGA dac powered down |
| ch_write_reg(dev, CH7036_PWRST4, 0x7F); // Stop hdmi,scaler, pwr down |
| |
| /* Chrontel email response 2010-06-17 to Off preventing EDID reads */ |
| /* Please remove both 0xE and 0x16 registers */ |
| /* 0xE will power down DDC */ |
| |
| ch_write_reg(dev, CH7036_PWRSTATE1, 0x94); // pll power down |
| } |
| |
| int ch_hdmi_is_on(int dev) |
| { |
| int res; |
| res = ch_read_reg(dev, CH7036_PWRST2); |
| if (res < 0) { |
| fprintf(stderr, "Failed to read powerstate 2 to check hdmi on\n"); |
| return 0; |
| } |
| /* Check if HDMI driver is powered down (bit set) */ |
| return (res & 0x8) ? 0 : 1; |
| } |
| |
| /* Calculate INC registers from values the chip provides */ |
| |
| void ch_calculate_incs(int dev) |
| { |
| unsigned int hinca, hincb, hinc; |
| unsigned int vinca, vincb, vinc; |
| unsigned int hdinca, hdincb, hdinc; |
| |
| //first read out parameters: |
| |
| hinca = ((ch_read_reg(dev, CH7036_HINCA1) << 3) | |
| (ch_read_reg(dev, CH7036_HINCA2) & 0x7)); |
| hincb = ((ch_read_reg(dev, CH7036_HINCB1) << 3) | |
| (ch_read_reg(dev, CH7036_HINCB2) & 0x7)); |
| vinca = ((ch_read_reg(dev, CH7036_VINCA1) << 3) | |
| (ch_read_reg(dev, CH7036_VINCA2) & 0x7)); |
| vincb = ((ch_read_reg(dev, CH7036_VINCB1) << 3) | |
| (ch_read_reg(dev, CH7036_VINCB2) & 0x7)); |
| hdinca = ((ch_read_reg(dev, CH7036_HDINCA1) << 3) | |
| (ch_read_reg(dev, CH7036_HDINCA2) & 0x7)); |
| hdincb = ((ch_read_reg(dev, CH7036_HDINCB1) << 3) | |
| (ch_read_reg(dev, CH7036_HDINCB2) & 0x7)); |
| |
| /* calculate them */ |
| /* NOTE: this code works because the values are 11-bit */ |
| /* so the shift in a 32-bit uint will not drop any bits from the top */ |
| if (hinca == 0 || hincb == 0) { |
| hinc = 0; |
| } else { |
| hinc = (1 << 20) * hinca / hincb; |
| } |
| |
| if (vinca == 0 || vincb == 0) { |
| vinc = 0; |
| } else { |
| vinc = (1 << 20) * vinca / vincb; |
| } |
| |
| if (hdinca == 0 || hdincb == 0) { |
| hdinc = 0; |
| } else { |
| hdinc = (1 << 20) * hdinca / hdincb; |
| } |
| |
| ch_write_reg(dev, CH7036_HINCC1,(hinc>>16) & 0xFF); |
| ch_write_reg(dev, CH7036_HINCC2,(hinc>>8) & 0xFF); |
| ch_write_reg(dev, CH7036_HINCC3, hinc & 0xFF); |
| |
| ch_write_reg(dev, CH7036_VINCC1,(vinc>>16) & 0xFF); |
| ch_write_reg(dev, CH7036_VINCC2,(vinc>>8) & 0xFF); |
| ch_write_reg(dev, CH7036_VINCC3, vinc & 0xFF); |
| |
| ch_write_reg(dev, CH7036_HDINCC1,(hdinc>>16) & 0xFF); |
| ch_write_reg(dev, CH7036_HDINCC2,(hdinc>>8) & 0xFF); |
| ch_write_reg(dev, CH7036_HDINCC3, hdinc & 0xFF); |
| } |
| |
| int ch_suspend_firmware(int dev, int verbose) |
| { |
| int res = ch_read_reg(dev, CH7036_RESET); |
| res &= ~0x4; |
| if (verbose) printf("Suspend CH7036 firmware, set RESET to 0x%x\n", res); |
| ch_write_reg(dev, CH7036_RESET, res); |
| return res; |
| } |
| |
| int ch_release_firmware(int dev, int verbose) |
| { |
| int res = ch_read_reg(dev, CH7036_RESET); |
| res |= 0x4; |
| if (verbose) printf("Release CH7036 firmware, set RESET to 0x%x\n", res); |
| ch_write_reg(dev, CH7036_RESET, res); |
| return res; |
| } |
| |
| |
| /* Load Firmware */ |
| |
| int ch_load_firmware(int dev, char* fname) |
| { |
| unsigned char buf[10240]; |
| FILE* fp; |
| long fs, fs1; |
| int res = -1; |
| |
| do { |
| |
| fp = fopen(fname, "rb"); |
| if (fp==NULL) { |
| fprintf(stderr, "Could not open %s to read firmware\n", fname); |
| break; |
| } |
| fseek( fp, 0, SEEK_END); |
| fs = ftell(fp); |
| fseek( fp, 0, SEEK_SET); |
| |
| fs1 = fread( buf, 1, fs, fp); |
| if (fs1 != fs) { |
| printf("File %s reading error!\n", fname); |
| break; |
| } |
| |
| printf("Firmware size = %d bytes.\n", (int)fs); |
| /* Initialize the firmware download */ |
| ch_write_reg(dev, 4, 0x52, 0x2b); |
| ch_write_reg(dev, 4, 0x5b, 0x9e); |
| ch_write_reg(dev, 4, 0x5b, 0xb3); |
| smbus_write_byte_data(dev, 0x03, 0x07); |
| /* Download the firmware */ |
| /* "The downloading can be byte by byte, or using I2C block write" */ |
| /* FIXME mdhayter: Did not get the block write to work with count > 1 */ |
| /* The SMBus hangs completely using I2C_SMBUS_I2C_BLOCK which is the */ |
| /* version that does not send the length required by Chrontel (unless */ |
| /* the length is set to 1). The transfers complete ok using the */ |
| /* I2C_SMBUS_BLOCK version, but the firmware is no good (as expected) */ |
| /* Could it be the kernel driver? */ |
| /* Using word seems ok and halves the number of transactions */ |
| #ifdef SLOWLOAD |
| for (fs1=0; fs1<fs; fs1++) |
| smbus_write_byte_data(dev, 0x07, buf[fs1]); |
| #endif |
| |
| #ifndef FASTLOAD |
| for(fs1 = 0; (fs1+1) < fs; fs1+=2) |
| smbus_write_word_data(dev, 0x07, buf[fs1] | (buf[fs1+1]<<8)); |
| if (fs1 < fs) |
| smbus_write_byte_data(dev, 0x07, buf[fs1]); |
| #else |
| #define TXSIZE 32 |
| for(fs1 = 0; (fs1+TXSIZE) < fs; fs1+=TXSIZE) |
| smbus_write_reg_bytes(dev, 0x07, TXSIZE, buf+fs1); |
| if (fs1 < fs) |
| smbus_write_reg_bytes(dev, 0x07, fs-fs1, buf+fs1); |
| #endif |
| |
| /* Finishing the download and run the firmware */ |
| smbus_write_byte_data(dev, 0x03, 0x04); |
| smbus_write_byte_data(dev, 0x52, 0x2F); |
| smbus_write_byte_data(dev, 0x03, 0x00); |
| ch7036_cur_page = -1; |
| res = 0; |
| |
| } while(0); |
| |
| if (fp!=NULL) fclose(fp); |
| return res; |
| } |
| |
| |
| /* Note -- this only works if firmware is loaded */ |
| /* will time out if the firmware is not running */ |
| int ch_mcu_version(int dev, int newFirmware, int verbose) |
| { |
| unsigned char data[16]; |
| FW7036_CFG *config = (FW7036_CFG *) &data[0]; |
| struct timeval tv; |
| /* This timeout needs to be tuned. 500,000 works but is a bit */ |
| /* long when trying to detect the firmware going away */ |
| /* 100,000 seems to sometimes give false timeouts */ |
| /* 200,000 is good except when the firmware is restarting */ |
| struct timeval tout = {0, 200000}; |
| if (newFirmware) tout.tv_usec = 500000; |
| |
| ch7036_cur_page = -1; |
| |
| // Send Host Request |
| smbus_write_byte_data(dev, 0x03, 0x00); |
| smbus_write_byte_data(dev, 0x4F, 0x5F); |
| // Wait the MCU response |
| gettimeofday(&tv, NULL); |
| timeradd(&tv, &tout, &tout); |
| |
| while (1) { |
| smbus_write_byte_data(dev, 0x03, 0x00); |
| if (((0x7F & smbus_read_byte_data(dev, 0x4F))==0x1F) || (dev < 0)) { |
| int i; |
| smbus_write_byte_data(dev, 0x03, MCU_DATA_PAGE); |
| for (i=0; i<sizeof(FW7036_CFG); i++) { |
| // data[16] holds the return parameter block from MCU |
| data[i] = smbus_read_byte_data(dev, es_map[i]); |
| } |
| smbus_write_byte_data(dev, 0x03, 0x00); |
| break; |
| } |
| gettimeofday(&tv, NULL); |
| if (timercmp(&tv, &tout, >)) { |
| fprintf(stderr, "Timeout waiting for MCU version\n"); |
| return -1; |
| } |
| } |
| if (verbose) |
| printf("CH7036 MCU ver %d.%d, Device %02x rev %d, capability 0x%x\n", |
| config->ver_major, config->ver_minor, |
| config->did, config->rid, config->capbility); |
| return (config->ver_major<<8) | config->ver_minor; |
| } |
| |
| /* Note -- this only works if firmware is loaded */ |
| /* Always says hdmi detected if firmware is not loaded */ |
| int ch_hdmi_detected(int dev) |
| { |
| int res; |
| res = ch_read_reg(dev, CH7036_HDMI_ST); |
| if (res < 0) return res; |
| |
| res = (res & 0x10) ? 1 : 0; |
| return res; |
| } |
| |
| /* The hdmi detect can be read directly from a gpio */ |
| /* The Linux GPIO sysfs file reads as ascii '0' or '1' */ |
| /* This function returns 1 = connected, 0 = not connected or error */ |
| |
| int ch_hdmi_gpio_detected(int gpiodev, int verbose) |
| { |
| int err; |
| char buff[2]; |
| |
| err = lseek(gpiodev, 0, SEEK_SET); |
| if (err != 0) { |
| fprintf(stderr, "gpiodev(%d): lseek returned %d (%s)", |
| gpiodev, err, (err < 0) ? strerror(errno) : "Not at start"); |
| return 0; |
| } |
| err = read(gpiodev, buff, 1); |
| if (err != 1) { |
| fprintf(stderr, "gpiodev(%d): read returned %d (%s)", |
| gpiodev, err, (err < 0) ? strerror(errno) : "More than 1 byte"); |
| return 0; |
| } |
| if ((buff[0] != '0') && (buff[0] != '1')) { |
| fprintf(stderr, "gpiodev(%d): read gave unexpected character %c (0x%02x)\n", |
| gpiodev, buff[0], buff[0]); |
| return 0; |
| } |
| if (verbose) printf("HDMI GPIO read as %c\n", buff[0]); |
| return (buff[0] == '1'); |
| } |
| |
| |
| /* Note -- this only works if firmware is loaded */ |
| /* will time out if the firmware is not running */ |
| int ch_get_edid(int dev, int edid_block, unsigned char* edid) |
| { |
| int j; |
| int res; |
| struct timeval tv; |
| struct timeval tout = {0, 500000}; |
| ch7036_cur_page = -1; |
| |
| // edid_block |
| for (j=0; j<8; j++) { |
| // Send Host Request |
| res = smbus_write_byte_data(dev, 0x03, 0x00); |
| if (res < 0) return res; |
| // one edid block contains 128 bytes, so we need read 8 blocks |
| res = smbus_write_byte_data(dev, 0x50, ((edid_block*8)+j)); |
| if (res < 0) return res; |
| res = smbus_write_byte_data(dev, 0x4F, 0x41); |
| if (res < 0) return res; |
| // Wait the MCU response |
| gettimeofday(&tv, NULL); |
| timeradd(&tv, &tout, &tout); |
| while (1) { |
| res = smbus_write_byte_data(dev, 0x03, 0x00); |
| if (res < 0) return res; |
| // Order in dummy case should do one read... |
| if (((0x7F & smbus_read_byte_data(dev, 0x4F))==0x01) || (dev < 0)) { |
| int i; |
| smbus_write_byte_data(dev, 0x03, MCU_DATA_PAGE); |
| for (i=0; i<16; i++) { |
| edid[j*16 + i] = smbus_read_byte_data(dev, es_map[i] ); |
| } |
| smbus_write_byte_data(dev, 0x03, 0x00); |
| break; |
| } |
| gettimeofday(&tv, NULL); |
| if (timercmp(&tv, &tout, >)) { |
| fprintf(stderr, "Timeout waiting for MCU to return EDID\n"); |
| return -1; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| |