Skip to content

Instantly share code, notes, and snippets.

@xerpi
Created August 5, 2017 06:23
Show Gist options
  • Save xerpi/acf095250768b216471b8416e5bdc07c to your computer and use it in GitHub Desktop.
Save xerpi/acf095250768b216471b8416e5bdc07c to your computer and use it in GitHub Desktop.
#include "hdmi.h"
#include "libc.h"
#include "utils.h"
#include "adv7511.h"
#include "i2c.h"
#include "gpio.h"
#include "pervasive.h"
#include "syscon.h"
#include "log.h"
#define BIT(x) (1 << (x))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define HDMI_I2C_BUS 1
#define HDMI_I2C_ADDR 0x7A
/* Configurable addresses */
#define HDMI_I2C_CEC_ADDR 0x7C
static void hdmi_i2c_cmd_write(unsigned char addr, unsigned char reg, const unsigned char *data, int size)
{
unsigned char buffer[8];
int i = 0;
while (size > 7) {
buffer[0] = reg + i;
memcpy(&buffer[1], &data[i], sizeof(buffer) - 1);
i2c_transfer_write(HDMI_I2C_BUS, addr, buffer, sizeof(buffer));
i += 7;
size -= 7;
}
if (size > 0) {
buffer[0] = reg + i;
memcpy(&buffer[1], &data[i], size);
i2c_transfer_write(HDMI_I2C_BUS, addr, buffer, size + 1);
}
}
static void hdmi_i2c_cmd_write_read(unsigned char addr, unsigned char reg, unsigned char *buff, unsigned int size)
{
unsigned char buffer;
int i = 0;
while (size > 8) {
buffer = reg + i;
i2c_transfer_write_read(HDMI_I2C_BUS, addr, &buffer, sizeof(buffer), addr, &buff[i], size);
i += 8;
size -= 8;
}
if (size > 0) {
buffer = reg + i;
i2c_transfer_write_read(HDMI_I2C_BUS, addr, &buffer, sizeof(buffer), addr, &buff[i], size);
}
}
static inline void hdmi_i2c_cmd_write_1(unsigned char addr, unsigned char reg, unsigned char data)
{
unsigned char buff = data;
hdmi_i2c_cmd_write(addr, reg, &buff, sizeof(buff));
}
static inline void hdmi_i2c_cmd_write_read_1(unsigned char addr, unsigned char reg, unsigned char *data)
{
hdmi_i2c_cmd_write_read(addr, reg, data, 1);
}
struct reg_sequence {
unsigned char reg;
unsigned char cmd;
};
static const struct reg_sequence adv7511_fixed_registers[] = {
{ 0x98, 0x03 },
{ 0x9a, 0xe0 },
{ 0x9c, 0x30 },
{ 0x9d, 0x61 },
{ 0xa2, 0xa4 },
{ 0xa3, 0xa4 },
{ 0xe0, 0xd0 },
{ 0xf9, 0x00 },
{ 0x55, 0x02 },
};
static const struct reg_sequence adv7533_fixed_registers[] = {
{ 0x16, 0x20 },
{ 0x9a, 0xe0 },
{ 0xba, 0x70 },
{ 0xde, 0x82 },
{ 0xe4, 0x40 },
{ 0xe5, 0x80 },
};
static const struct reg_sequence adv7533_cec_fixed_registers[] = {
{ 0x15, 0xd0 },
{ 0x17, 0xd0 },
{ 0x24, 0x20 },
{ 0x57, 0x11 },
{ 0x05, 0xc8 },
};
void hdmi_i2c_update_bits(unsigned char addr, unsigned char reg,
unsigned char mask, unsigned char val)
{
unsigned char data;
hdmi_i2c_cmd_write_read_1(addr, reg, &data);
data &= ~mask;
data |= val & mask;
hdmi_i2c_cmd_write_1(addr, reg, data);
}
static void hdmi_config_dsi_timing_gen(void)
{
unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
static const unsigned char clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
/*
|VIC|Hactive|Vactive|I / P|Htotal|Hblank|Vtotal|Vblank|H Freq|V Freq |Pixel Freq|
|2,3| 720 | 480 |Prog | 858 | 138 | 525 | 45 |31.469|59.9403| 27.000 |
|flags|pixelclk24|subinfo_24bpp|pixelclk30|subinfo_30bpp|htotal|vtotal|mode|HFP|HSW|HBP|VFP|VSW|VBP|
| 1 |0x107AC0 |&stru_BD0E04 | 0x149970 |&stru_BD0AC4 | 858 | 525 | 0 |16 |62 |60 | 9 | 6 |30 |
HBP + HFP + HSS = 16 + 62 + 60 = 138
VFP + VBP + VSS = 9 + 6 + 30 = 45
VIC 4: 0x672, 0x2EE, 0, 0x6E, 0x28, 0xDC, 5, 5, 0x14};
*/
static const unsigned char lanes = 3;
unsigned int htotal = 1650;
unsigned int vtotal = 750;
hsw = 0x28;
hfp = 0x6E;
hbp = 0xDC;
vsw = 5;
vfp = 5;
vbp = 0x14;
/* set pixel clock divider mode */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x16,
clock_div_by_lanes[lanes - 2] << 3);
/* horizontal porch params */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x28, htotal >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x29, (htotal << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2a, hsw >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2b, (hsw << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2c, hfp >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2d, (hfp << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2e, hbp >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x2f, (hbp << 4) & 0xff);
/* vertical porch params */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x30, vtotal >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x31, (vtotal << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x32, vsw >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x33, (vsw << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x34, vfp >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x35, (vfp << 4) & 0xff);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x36, vbp >> 4);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x37, (vbp << 4) & 0xff);
}
static void hdmi_set_link_config(void)
{
/*
* The input style values documented in the datasheet don't match the
* hardware register field values :-(
*/
static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
static const unsigned int config_input_colorspace = HDMI_COLORSPACE_RGB;
static const unsigned int config_clock_delay = 0;
static const unsigned int config_input_style = 0;
static const unsigned int config_input_color_depth = 8;
static const unsigned int config_embedded_sync = 0;
static const unsigned int config_input_clock = ADV7511_INPUT_CLOCK_1X;
static const unsigned int config_input_justification = ADV7511_INPUT_JUSTIFICATION_LEFT;
static const unsigned int config_input_ddr_alignment = ADV7511_INPUT_DDR_ALIGNMENT_35_18;
static const unsigned int config_input_bus_order = ADV7511_INPUT_BUS_ORDER_REVERSE;
static const unsigned int config_sync_pulse = ADV7511_INPUT_SYNC_PULSE_DE;
unsigned int clock_delay;
unsigned int color_depth;
unsigned int input_id;
clock_delay = (config_clock_delay + 1200) / 400;
color_depth = config_input_color_depth == 8 ? 3
: (config_input_color_depth == 10 ? 1 : 2);
if (config_input_colorspace != HDMI_COLORSPACE_YUV422)
input_id = config_input_clock == ADV7511_INPUT_CLOCK_DDR
? 5 : 0;
else if (config_input_clock == ADV7511_INPUT_CLOCK_DDR)
input_id = config_embedded_sync ? 8 : 7;
else if (config_input_clock == ADV7511_INPUT_CLOCK_2X)
input_id = config_embedded_sync ? 4 : 3;
else
input_id = config_embedded_sync ? 2 : 1;
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_I2C_FREQ_ID_CFG, 0xf,
input_id);
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_VIDEO_INPUT_CFG1, 0x7e,
(color_depth << 4) |
(input_styles[config_input_style] << 2));
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, ADV7511_REG_VIDEO_INPUT_CFG2,
(config_input_justification << 3) |
(config_input_ddr_alignment << 5) |
(config_input_bus_order << 6));
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, ADV7511_REG_TIMING_GEN_SEQ,
config_sync_pulse << 2);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xba, clock_delay << 5);
}
typedef unsigned char u8;
#define hdmi_write(addr,reg, data) \
hdmi_i2c_cmd_write_1(addr, reg, data)
static inline u8 hdmi_read(u8 addr, u8 reg)
{
unsigned char data;
hdmi_i2c_cmd_write_read_1(addr, reg, &data);
return data;
}
void hdmi_set_bit(u8 addr, u8 reg, u8 bit)
{
u8 val;
val = hdmi_read(addr, reg);
val |= bit;
hdmi_write(addr, reg, val);
}
void hdmi_clr_bit(u8 addr, u8 reg, u8 bit)
{
u8 val;
val = hdmi_read(addr, reg);
val &= ~bit;
hdmi_write(addr, reg, val);
}
static int adv7533_set_video(int hdmi_format, int internal_timing)
{
//int fmt;
int temp_timing;
u8 temp_byte;
//fmt = hdmi_format - 1;
/* Set DSI LP Oscillator and HDMI Enable to Normal Operation (Enabled)*/
hdmi_write(HDMI_I2C_CEC_ADDR, 0x03, 0x89);
/* HDMI Startup*/
/* Set Vsync and Hsync Polarity according to hdmi_format*/
if ((hdmi_format == 0) || (hdmi_format == 4) || (hdmi_format == 5)
|| (hdmi_format == 16) || (hdmi_format == 19)) {
hdmi_clr_bit(HDMI_I2C_ADDR, ADV7533_MAIN_SYNC_REG,
(ADV7533_MAIN_SYNC_H|ADV7533_MAIN_SYNC_V));
} else {
hdmi_set_bit(HDMI_I2C_ADDR, ADV7533_MAIN_SYNC_REG,
(ADV7533_MAIN_SYNC_H | ADV7533_MAIN_SYNC_V));
}
/* Input aspect ratio 16:9 */
hdmi_set_bit(HDMI_I2C_ADDR, ADV7533_MAIN_SYNC_REG, 1 << 1);
/* Fixed Register Settings per PG*/
hdmi_write(HDMI_I2C_CEC_ADDR, 0x24, 0x20);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x26, 0x3C);
hdmi_write(HDMI_I2C_ADDR, 0x9A, 0xE0);
hdmi_write(HDMI_I2C_ADDR, 0x9B, 0x19);
hdmi_write(HDMI_I2C_ADDR, 0xBA, 0x70);
hdmi_write(HDMI_I2C_ADDR, 0xDE, 0x82);
hdmi_write(HDMI_I2C_ADDR, 0xE4, 0x40);
hdmi_write(HDMI_I2C_ADDR, 0xE5, 0x80);
/* Ungate Audio and CEC Clocks - clear bit 4 and 5*/
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0x05, 0x20);
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0x05, 0x10);
/* Start DSI Programming*/
/* Set Number of DSI Data Lanes to 3*/
hdmi_set_bit(HDMI_I2C_CEC_ADDR, 0x1C, 0x30);
/* Set CEC Power Mode = Always Active. Clear bits before*/
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0xBE, 0x03);
hdmi_set_bit(HDMI_I2C_CEC_ADDR, 0xBE, 0x01);
/* Set Timing Generator Settings*/
if (internal_timing) {
#if 0
struct lcd_frame_config frame_timings;
get_frame_config(&frame_timings, fmt);
/*Set Horizontal parameters*/
temp_timing = frame_timings.LCD_Horizontal
+ frame_timings.LCD_HSW + frame_timings.LCD_BLW
+ frame_timings.LCD_ELW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_TOTAL_WIDTH_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_TOTAL_WIDTH_L_REG, temp_byte);
temp_timing = frame_timings.LCD_HSW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HSYNC_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HSYNC_L_REG, temp_byte);
temp_timing = frame_timings.LCD_ELW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HFP_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HFP_L_REG, temp_byte);
temp_timing = frame_timings.LCD_BLW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HBP_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_HBP_L_REG, temp_byte);
/*Set Vertical parameters*/
temp_timing = frame_timings.LCD_Vertical + frame_timings.LCD_VSW
+ frame_timings.LCD_BFW + frame_timings.LCD_EFW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_TOTAL_HEIGHT_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_TOTAL_HEIGHT_L_REG, temp_byte);
temp_timing = frame_timings.LCD_VSW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VSYNC_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VSYNC_L_REG, temp_byte);
temp_timing = frame_timings.LCD_EFW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VFP_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VFP_L_REG, temp_byte);
temp_timing = frame_timings.LCD_BFW;
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_H_MASK)
>> ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VBP_H_REG, temp_byte);
temp_byte = (u8)((temp_timing & ADV7533_CEC_DSI_TIMING_L_MASK)
<< ADV7533_CEC_DSI_TIMING_OFFSET);
hdmi_write(HDMI_I2C_CEC_ADDR,
ADV7533_CEC_DSI_VBP_L_REG, temp_byte);
#endif
/*Enable timing generator*/
hdmi_set_bit(HDMI_I2C_CEC_ADDR, ADV7533_CEC_DSI_INTERNAL_TIMING,
ADV7533_CEC_DSI_INTERNAL_TIMING_EN);
} else {
/*Enable timing generator*/
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, ADV7533_CEC_DSI_INTERNAL_TIMING,
ADV7533_CEC_DSI_INTERNAL_TIMING_EN);
}
/* HDMI Output Settings*/
/* Set HDMI/DVI Mode Select = HDMI Mode Enabled - bit 1*/
hdmi_set_bit(HDMI_I2C_ADDR, 0xAF, 0x2);
/* Enable GC Packet */
hdmi_set_bit(HDMI_I2C_ADDR, 0x40, 0x80);
/* Set Color Depth to 24 Bits/Pixel. Clear field before*/
hdmi_clr_bit(HDMI_I2C_ADDR, 0x4C, 0x0F);
hdmi_set_bit(HDMI_I2C_ADDR, 0x4C, 0x04);
/* Set Active Format Aspect Ratio = 16:9 (Center) Clear field before*/
hdmi_clr_bit(HDMI_I2C_ADDR, 0x56, 0x0F);
hdmi_set_bit(HDMI_I2C_ADDR, 0x56, 0x0A);
/* ?? V*/
hdmi_write(HDMI_I2C_ADDR, 0xE4, 0xC0);
/* 24 bit RGB 4:4:4 or YCbCr 4:4:4 (separate syncs) */
hdmi_write(HDMI_I2C_ADDR, 0x15, 0x20);
return 0;
}
#if 0
int hdmi_init_old(void)
{
int i;
pervasive_hdmi_cec_set_enabled(1);
syscon_set_hdmi_cdc_hpd(1);
gpio_set_port_mode(0, GPIO_PORT_HDMI_BRIDGE,
GPIO_PORT_MODE_OUTPUT);
gpio_port_clear(0, GPIO_PORT_HDMI_BRIDGE);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, ADV7511_REG_CEC_I2C_ADDR,
HDMI_I2C_CEC_ADDR);
unsigned char status;
do {
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, ADV7511_REG_STATUS, &status);
} while (!(status & ADV7511_STATUS_HPD));
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_POWER,
ADV7511_POWER_POWER_DOWN, 0);
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_POWER2,
ADV7511_REG_POWER2_HPD_SRC_MASK,
ADV7511_REG_POWER2_HPD_SRC_HPD);
static unsigned char i2c_0x7A[] = {
0x14,
0x00,
0x2D,
0x80,
0x22,
0x25,
0x51,
0x00,
0x00,
0x00,
0x50,
0xCE,
0xB8,
0x18,
0x01,
0x13,
0x25,
0x37,
0x00,
0x00,
0x00,
0x20,
0x00,
0x02,
0xA8,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x08,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x08,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0xC0,
0x04,
0x04,
0x10,
0x00,
0xC0,
0x10,
0x70,
0x7E,
0x79,
0x70,
0x70,
0x70,
0x70,
0xFC,
0x80,
0x80,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x02,
0x0D,
0x43,
0x00,
0x28,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x01,
0x0A,
0x70,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0xC6,
0xBF,
0x31,
0x00,
0x03,
0x02,
0xE0,
0x18,
0x38,
0x61,
0x12,
0x00,
0x00,
0x00,
0xA0,
0xA0,
0x08,
0x04,
0x00,
0x00,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
0x40,
0x96,
0xA0,
0x87,
0x7B,
0x90,
0xF2,
0xE3,
0x0F,
0x39,
0x60,
0x00,
0x70,
0x00,
0x28,
0xCD,
0x80,
0x94,
0xA4,
0xDE,
0x2D,
0x72,
0x00,
0x70,
0x1E,
0x00,
0x04,
0x01,
0x00,
0x00,
0x02,
0x00,
0x01,
0x04,
0x30,
0xFF,
0x80,
0x80,
0x80,
0x00,
0x48,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x82,
0x01,
0x80,
0x7C,
0x00,
0x00,
0xC0,
0x80,
0xFD,
0x20,
0x00,
0x00,
0x52,
0x46,
0x00,
0x00,
0x00,
0x00,
0x95,
0x04,
0xFF,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x10,
0x7D,
0xAA,
0x1C,
0x00,
0xB0,
0x00
};
static unsigned char i2c_0x7C[] = {
0x75,
0x33,
0x01,
0x89,
0x78,
0xC8,
0x00,
0x80,
0x80,
0x80,
0x80,
0x80,
0x80,
0x80,
0x80,
0x80,
0xC0,
0x08,
0x00,
0x00,
0x90,
0xD0,
0x20,
0xD0,
0x60,
0x19,
0x04,
0x00,
0x30,
0xA4,
0x00,
0x30,
0x30,
0xFF,
0xFF,
0x80,
0x20,
0x12,
0x3C,
0xD0,
0x67,
0x20,
0x02,
0x80,
0x06,
0xE0,
0x0D,
0xC0,
0x2E,
0xE0,
0x00,
0x50,
0x00,
0x50,
0x01,
0x40,
0x80,
0x00,
0x7E,
0x00,
0x21,
0x00,
0x00,
0x12,
0x80,
0x10,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x73,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0A,
0x00,
0xEC,
0x11,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0x00,
0x09,
0xD8,
0xE4,
0x00,
0x40,
0x00,
0x89,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x04,
0x07,
0x13,
0x57,
0x00,
0x04,
0x89,
0x01,
0xE0,
0x91,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x03,
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x08,
0x10,
0xF4,
0x0F,
0x21,
0x07,
0x00,
0x0D,
0x2F,
0x0C,
0x4E,
0x0E,
0x10,
0x0A,
0xD7,
0x09,
0xF6,
0x0B,
0xB8,
0x07,
0x08,
0x05,
0xB7,
0x08,
0x5A,
0x01,
0xC2,
0x04,
0x65,
0x05,
0x46,
0x03,
0x14,
0x0A,
0x8C,
0x00,
0x00,
0xBC,
0x00,
0x00,
0xE1,
0x02,
0xA3,
0x03,
0x84,
0x6D,
0x8F,
0x82,
0x04,
0x0D,
0x70,
0x42,
0x41,
0x41,
0x00,
0x0F,
0xFF,
0x00,
0x0F,
0xFF,
0x00,
0x00,
0x20,
0x00,
0x60,
0x02,
0x00,
0x06,
0x06,
0x06,
};
/* HDCP disable */
i2c_0x7A[0xAF] = 0x06;
/* Disable SPDIF receiver */
i2c_0x7A[0x0B] = 0x0E;
/* Disable I2S */
i2c_0x7A[0x0C] = 0;
/* Disable all DSD Channel */
i2c_0x7A[0x46] = 0;
/* I2S Sampling Frequency: 0001 = Do not use; 0000 = 24 bit RGB 4:4:4 or YCbCr 4:4:4 (separate syncs) */
i2c_0x7A[0x15] = 0x10;
/* Audio Select: N/A */
i2c_0x7A[0x0A] = 0x50;
/* */
//i2c_0x7A[0x40] = 0x80;
/*for (int i = 0; i < ARRAY_SIZE(i2c_0x7A); i++) {
if (i != 0x41)
hdmi_i2c_cmd_write_1(0x7A, i, i2c_0x7A[i]);
}
for (int i = 0; i < ARRAY_SIZE(i2c_0x7C); i++)
hdmi_i2c_cmd_write_1(0x7C, i, i2c_0x7C[i]);
adv7533_set_video(4, 1);*/
#define ADV7533_MAIN HDMI_I2C_ADDR
#define ADV7533_CEC_DSI HDMI_I2C_CEC_ADDR
struct adv7533_reg_cfg {
u8 addr, reg, val;
};
static const struct adv7533_reg_cfg setup_cfg[] = {
//{ADV7533_MAIN, 0x41, 0x10}, /* HDMI normal */
//{ADV7533_MAIN, 0xd6, 0x48}, /* HPD overriden */
{ADV7533_CEC_DSI, 0x03, 0x89}, /* HDMI enabled */
{ADV7533_MAIN, 0x16, 0x20},
{ADV7533_MAIN, 0x9A, 0xE0},
{ADV7533_MAIN, 0xBA, 0x70},
{ADV7533_MAIN, 0xDE, 0x82},
{ADV7533_MAIN, 0xE4, 0xC0},
{ADV7533_MAIN, 0xE5, 0x80},
{ADV7533_CEC_DSI, 0x15, 0xD0},
{ADV7533_CEC_DSI, 0x17, 0xD0},
{ADV7533_CEC_DSI, 0x24, 0x20},
{ADV7533_CEC_DSI, 0x57, 0x11},
/* hdmi or dvi mode: hdmi */
{ADV7533_MAIN, 0xAF, 0x06},
{ADV7533_MAIN, 0x40, 0x80},
{ADV7533_MAIN, 0x4C, 0x04},
{ADV7533_MAIN, 0x49, 0x02},
{ADV7533_MAIN, 0x0D, 1 << 6},
};
static const struct adv7533_reg_cfg tg_cfg_1080p[] = {
/* 4 lanes */
{ADV7533_CEC_DSI, 0x1C, 0x40},
/* hsync and vsync active low */
{ADV7533_MAIN, 0x17, 0x02},
/* Control for Pixel Clock Divider */
{ADV7533_CEC_DSI, 0x16, 0x00},
/* Timing Generator Enable */
{ADV7533_CEC_DSI, 0x27, 0xCB},
/* h_width 0x898 2200*/
{ADV7533_CEC_DSI, 0x28, 0x89},
{ADV7533_CEC_DSI, 0x29, 0x80},
/* hsync_width 0x2C 44*/
{ADV7533_CEC_DSI, 0x2A, 0x02},
{ADV7533_CEC_DSI, 0x2B, 0xC0},
/* hfp 0x58 88 */
{ADV7533_CEC_DSI, 0x2C, 0x05},
{ADV7533_CEC_DSI, 0x2D, 0x80},
/* hbp 0x94 148 */
{ADV7533_CEC_DSI, 0x2E, 0x09},
{ADV7533_CEC_DSI, 0x2F, 0x40},
/* v_total 0x465 1125 */
{ADV7533_CEC_DSI, 0x30, 0x46},
{ADV7533_CEC_DSI, 0x31, 0x50},
/* vsync_width 0x05 5*/
{ADV7533_CEC_DSI, 0x32, 0x00},
{ADV7533_CEC_DSI, 0x33, 0x50},
/* vfp 0x04 4 */
{ADV7533_CEC_DSI, 0x34, 0x00},
{ADV7533_CEC_DSI, 0x35, 0x40},
/* vbp 0x24 36 */
{ADV7533_CEC_DSI, 0x36, 0x02},
{ADV7533_CEC_DSI, 0x37, 0x40},
/* Timing Generator Enable */
{ADV7533_CEC_DSI, 0x27, 0xCB},
{ADV7533_CEC_DSI, 0x27, 0x8B},
{ADV7533_CEC_DSI, 0x27, 0xCB},
/* Reset Internal Timing Generator */
{ADV7533_MAIN, 0xAF, 0x16},
/* HDMI Mode Select */
{ADV7533_CEC_DSI, 0x78, 0x03},
/* HDMI Output Enable */
{ADV7533_MAIN, 0x40, 0x80},
/* GC Packet Enable */
{ADV7533_MAIN, 0x4C, 0x04},
/* Colour Depth 24-bit per pixel */
{ADV7533_MAIN, 0x49, 0x00},
/* Down Dither Output 8-bit Colour Depth */
{ADV7533_CEC_DSI, 0x05, 0xC8},
/* ADI Required Write */
{ADV7533_CEC_DSI, 0xBE, 0x3D},
/* Test Pattern Disable (0x55[7] = 0) */
{ADV7533_CEC_DSI, 0x55, 0x00},
};
static const struct adv7533_reg_cfg tg_cfg_pattern_1080p[] = {
/* 4 lanes */
{ADV7533_CEC_DSI, 0x1C, 0x40},
/* hsync and vsync active low */
{ADV7533_MAIN, 0x17, 0x02},
/* Control for Pixel Clock Divider */
{ADV7533_CEC_DSI, 0x16, 0x00},
/* Timing Generator Enable */
{ADV7533_CEC_DSI, 0x27, 0xCB},
/* h_width 0x898 2200*/
{ADV7533_CEC_DSI, 0x28, 0x89},
{ADV7533_CEC_DSI, 0x29, 0x80},
/* hsync_width 0x2C 44*/
{ADV7533_CEC_DSI, 0x2A, 0x02},
{ADV7533_CEC_DSI, 0x2B, 0xC0},
/* hfp 0x58 88 */
{ADV7533_CEC_DSI, 0x2C, 0x05},
{ADV7533_CEC_DSI, 0x2D, 0x80},
/* hbp 0x94 148 */
{ADV7533_CEC_DSI, 0x2E, 0x09},
{ADV7533_CEC_DSI, 0x2F, 0x40},
/* v_total 0x465 1125 */
{ADV7533_CEC_DSI, 0x30, 0x46},
{ADV7533_CEC_DSI, 0x31, 0x50},
/* vsync_width 0x05 5*/
{ADV7533_CEC_DSI, 0x32, 0x00},
{ADV7533_CEC_DSI, 0x33, 0x50},
/* vfp 0x04 4 */
{ADV7533_CEC_DSI, 0x34, 0x00},
{ADV7533_CEC_DSI, 0x35, 0x40},
/* vbp 0x24 36 */
{ADV7533_CEC_DSI, 0x36, 0x02},
{ADV7533_CEC_DSI, 0x37, 0x40},
/* Timing Generator Enable */
{ADV7533_CEC_DSI, 0x27, 0xCB},
{ADV7533_CEC_DSI, 0x27, 0x8B},
{ADV7533_CEC_DSI, 0x27, 0xCB},
/* Reset Internal Timing Generator */
{ADV7533_MAIN, 0xAF, 0x16},
/* HDMI Mode Select */
{ADV7533_CEC_DSI, 0x78, 0x03},
/* HDMI Output Enable */
{ADV7533_MAIN, 0x40, 0x80},
/* GC Packet Enable */
{ADV7533_MAIN, 0x4C, 0x04},
/* Colour Depth 24-bit per pixel */
{ADV7533_MAIN, 0x49, 0x00},
/* Down Dither Output 8-bit Colour Depth */
{ADV7533_CEC_DSI, 0x05, 0xC8},
/* ADI Required Write */
{ADV7533_CEC_DSI, 0xBE, 0x3D},
/* Test Pattern Enable (0x55[7] = 1) */
{ADV7533_CEC_DSI, 0x55, 0x80},
};
static const struct adv7533_reg_cfg tg_cfg_720p[] = {
{ADV7533_CEC_DSI, 0x1C, 0x30},
/* hsync and vsync active low */
{ADV7533_MAIN, 0x17, 0x02},
/* Control for Pixel Clock Divider */
{ADV7533_CEC_DSI, 0x16, 0x24},
/* h_width 0x898 2200*/
{ADV7533_CEC_DSI, 0x28, 0x67},
{ADV7533_CEC_DSI, 0x29, 0x20},
/* hsync_width 0x2C 44*/
{ADV7533_CEC_DSI, 0x2A, 0x02},
{ADV7533_CEC_DSI, 0x2B, 0x80},
/* hfp 0x58 88 */
{ADV7533_CEC_DSI, 0x2C, 0x06},
{ADV7533_CEC_DSI, 0x2D, 0xE0},
/* hbp 0x94 148 */
{ADV7533_CEC_DSI, 0x2E, 0x0D},
{ADV7533_CEC_DSI, 0x2F, 0xC0},
/* v_total 0x465 1125 */
{ADV7533_CEC_DSI, 0x30, 0x2E},
{ADV7533_CEC_DSI, 0x31, 0xE0},
/* vsync_width 0x05 5*/
{ADV7533_CEC_DSI, 0x32, 0x00},
{ADV7533_CEC_DSI, 0x33, 0x50},
/* vfp 0x04 4 */
{ADV7533_CEC_DSI, 0x34, 0x00},
{ADV7533_CEC_DSI, 0x35, 0x50},
/* vbp 0x24 36 */
{ADV7533_CEC_DSI, 0x36, 0x01},
{ADV7533_CEC_DSI, 0x37, 0x40},
/* Test Pattern Disable (0x55[7] = 0) */
{ADV7533_CEC_DSI, 0x55, 0x00},
/* HDMI disabled */
{ADV7533_CEC_DSI, 0x03, 0x09},
/* HDMI enabled */
{ADV7533_CEC_DSI, 0x03, 0x89},
};
static const struct adv7533_reg_cfg tg_cfg_pattern_720p[] = {
{ADV7533_CEC_DSI, 0x1C, 0x30},
/* hsync and vsync active low */
{ADV7533_MAIN, 0x17, 0x02},
/* Control for Pixel Clock Divider */
{ADV7533_CEC_DSI, 0x16, 0x24},
/* h_width 0x898 2200*/
{ADV7533_CEC_DSI, 0x28, 0x67},
{ADV7533_CEC_DSI, 0x29, 0x20},
/* hsync_width 0x2C 44*/
{ADV7533_CEC_DSI, 0x2A, 0x02},
{ADV7533_CEC_DSI, 0x2B, 0x80},
/* hfp 0x58 88 */
{ADV7533_CEC_DSI, 0x2C, 0x06},
{ADV7533_CEC_DSI, 0x2D, 0xE0},
/* hbp 0x94 148 */
{ADV7533_CEC_DSI, 0x2E, 0x0D},
{ADV7533_CEC_DSI, 0x2F, 0xC0},
/* v_total 0x465 1125 */
{ADV7533_CEC_DSI, 0x30, 0x2E},
{ADV7533_CEC_DSI, 0x31, 0xE0},
/* vsync_width 0x05 5*/
{ADV7533_CEC_DSI, 0x32, 0x00},
{ADV7533_CEC_DSI, 0x33, 0x50},
/* vfp 0x04 4 */
{ADV7533_CEC_DSI, 0x34, 0x00},
{ADV7533_CEC_DSI, 0x35, 0x50},
/* vbp 0x24 36 */
{ADV7533_CEC_DSI, 0x36, 0x01},
{ADV7533_CEC_DSI, 0x37, 0x40},
/* DSI Internal Timing Generator Enable register bit (0x27[7] = 1) */
{ADV7533_CEC_DSI, 0x27, 0x8B},
/* Test Pattern Enable (0x55[7] = 1) */
{ADV7533_CEC_DSI, 0x55, 0x80},
/* DSI Internal Timing Generator Reset Enable
register bit (0x27[6] = 0) */
{ADV7533_CEC_DSI, 0x27, 0x8B},
/* DSI Internal Timing Generator Reset Enable
register bit (0x27[6] = 1) */
{ADV7533_CEC_DSI, 0x27, 0xCB},
{ADV7533_CEC_DSI, 0x03, 0x09},/* HDMI disabled */
{ADV7533_CEC_DSI, 0x03, 0x89},/* HDMI enabled */
};
static const struct adv7533_reg_cfg irq_config[] = {
{ADV7533_CEC_DSI, 0x38, 0xCE},
{ADV7533_CEC_DSI, 0x38, 0xC0},
};
for (i = 0; i < ARRAY_SIZE(adv7533_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR,
adv7533_fixed_registers[i].reg,
adv7533_fixed_registers[i].cmd);
for (i = 0; i < ARRAY_SIZE(adv7533_cec_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR,
adv7533_cec_fixed_registers[i].reg,
adv7533_cec_fixed_registers[i].cmd);
static const u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
static const unsigned char lanes = 3;
unsigned int htotal = 1650;
unsigned int vtotal = 750;
hsw = 0x28;
hfp = 0x6E;
hbp = 0xDC;
vsw = 5;
vfp = 5;
vbp = 0x14;
#define ADV7533_REG_CEC_PIXEL_CLOCK_DIV 0x16
/* set pixel clock auto mode */
hdmi_write(ADV7533_CEC_DSI, ADV7533_REG_CEC_PIXEL_CLOCK_DIV, 0x00);
/* horizontal porch params */
hdmi_write(ADV7533_CEC_DSI, 0x28, htotal >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x29,
(htotal << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x2a, hsw >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x2b, (hsw << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x2c, hfp >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x2d, (hfp << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x2e, hbp >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x2f, (hbp << 4) & 0xff);
/* vertical porch params */
hdmi_write(ADV7533_CEC_DSI, 0x30, vtotal >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x31,
(vtotal << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x32, vsw >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x33, (vsw << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x34, vfp >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x35, (vfp << 4) & 0xff);
hdmi_write(ADV7533_CEC_DSI, 0x36, vbp >> 4);
hdmi_write(ADV7533_CEC_DSI, 0x37, (vbp << 4) & 0xff);
/* 30Hz Low Refresh Rate (VIC Detection) */
/* set number of dsi lanes */
hdmi_write(ADV7533_CEC_DSI, 0x1c, 3 << 4);
/* reset internal timing generator */
hdmi_write(ADV7533_CEC_DSI, 0x27, 0xcb);
hdmi_write(ADV7533_CEC_DSI, 0x27, 0x8b);
hdmi_write(ADV7533_CEC_DSI, 0x27, 0xcb);
/* 09-03 AVI Infoframe - RGB - 16-9 Aspect Ratio */
hdmi_write(HDMI_I2C_ADDR, 0x55, 0x10);
hdmi_write(HDMI_I2C_ADDR, 0x56, 0x28);
/* 04-04 GC Packet Enable */
hdmi_write(HDMI_I2C_ADDR, 0x40, 0x80);
/* 04-06 GC Colour Depth - 24 Bit */
hdmi_write(HDMI_I2C_ADDR, 0x4c, 0x04);
/* 04-09 Down Dither Output Colour Depth - 8 Bit (default) */
hdmi_write(HDMI_I2C_ADDR, 0x49, 0x00);
/* 07-01 CEC Power Mode - Always Active */
hdmi_write(ADV7533_CEC_DSI, 0xbe, 0x3d);
/* enable hdmi */
hdmi_write(ADV7533_CEC_DSI, 0x03, 0x89);
/*enable test mode */
hdmi_write(ADV7533_CEC_DSI, 0x55, 0x80);
/*for (int k = 0; k < 32; k++) {
if (k == GPIO_PORT_HDMI_BRIDGE)
continue;
gpio_set_port_mode(0, k,
GPIO_PORT_MODE_OUTPUT);
gpio_port_clear(0, k);
delay(4000);
gpio_port_set(0, k);
delay(4000);
LOG_HEX(k);
}*/
/*for (int i = 0; i < ARRAY_SIZE(setup_cfg); i++)
hdmi_write(setup_cfg[i].addr, setup_cfg[i].reg,
setup_cfg[i].val);
for (int i = 0; i < ARRAY_SIZE(tg_cfg_pattern_720p); i++)
hdmi_write(tg_cfg_pattern_720p[i].addr, tg_cfg_pattern_720p[i].reg,
tg_cfg_pattern_720p[i].val);
for (int i = 0; i < ARRAY_SIZE(irq_config); i++)
hdmi_write(irq_config[i].addr, irq_config[i].reg,
irq_config[i].val);*/
#if 0
for (i = 0; i < ARRAY_SIZE(adv7533_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR,
adv7533_fixed_registers[i].reg,
adv7533_fixed_registers[i].cmd);
unsigned char irq;
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, ADV7511_REG_INT(0), &irq);
if (irq & ADV7511_INT0_HPD)
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, ADV7511_REG_INT(0), ADV7511_INT0_HPD);
/* Unknown */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x25, 18);
/* DSI */
hdmi_set_link_config();
hdmi_config_dsi_timing_gen();
/* set number of dsi lanes */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x1C, 3 << 4);
/* Reset internal timing generator */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x27, 0x90);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x27, 0xD0);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x26, 0x1C);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x26, 0x3C);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x0A, 0x41);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x15, 0x20);
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x07, 0x80);
/* enable hdmi */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x03, 0x89);
/* disable test mode */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x55, 0x00);
/* unk */
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x20, 0x30);
for (i = 0; i < ARRAY_SIZE(adv7533_cec_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR,
adv7533_cec_fixed_registers[i].reg,
adv7533_cec_fixed_registers[i].cmd);
/* CSC */
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x18, 0xA8);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x1A, 1 << 5);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x22, 0x08);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x26, 0x0F);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x27, 0xFF);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x2, 0x08);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x1A, 0 << 5);
#endif
/* CSC */
/*hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x18, 0xA8);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x1A, 1 << 5);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x22, 0x08);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x26, 0x0F);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x27, 0xFF);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x2, 0x08);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x1A, 0 << 5);*/
#if 0
/* Register Settings for DE Generation */
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x35, 0x40);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x36, 0xD9);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x37, 0x0A);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x38, 0x00);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x39, 0x2D);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x3A, 0x00);
/* Register Settings for Sync Adjustment */
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xD7, 0x1B);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xD8, 0x82);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xD9, 0x80);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xDA, 0x14);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xDB, 0x05);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x17, 0b11);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x41, 0x10 | (1 << 1));
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xD0, 0x30 | (1 << 1));
#endif
//while (1)
// hdmi_check();
}
#endif
int hdmi_init(void)
{
pervasive_hdmi_cec_set_enabled(1);
syscon_set_hdmi_cdc_hpd(1);
gpio_set_port_mode(0, GPIO_PORT_HDMI_BRIDGE,
GPIO_PORT_MODE_OUTPUT);
gpio_port_clear(0, GPIO_PORT_HDMI_BRIDGE);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, ADV7511_REG_CEC_I2C_ADDR,
HDMI_I2C_CEC_ADDR);
unsigned char status;
do {
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, ADV7511_REG_STATUS, &status);
} while (!(status & ADV7511_STATUS_HPD));
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_POWER,
ADV7511_POWER_POWER_DOWN, 0);
hdmi_i2c_update_bits(HDMI_I2C_ADDR, ADV7511_REG_POWER2,
ADV7511_REG_POWER2_HPD_SRC_MASK,
ADV7511_REG_POWER2_HPD_SRC_HPD);
for (int i = 0; i < ARRAY_SIZE(adv7533_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR,
adv7533_fixed_registers[i].reg,
adv7533_fixed_registers[i].cmd);
for (int i = 0; i < ARRAY_SIZE(adv7533_cec_fixed_registers); i++)
hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR,
adv7533_cec_fixed_registers[i].reg,
adv7533_cec_fixed_registers[i].cmd);
static const int test_mode = 0;
static const unsigned char lanes = 3;
if (test_mode) {
/* set pixel clock auto mode */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x16, 0x00);
} else {
static const u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
/* set pixel clock divider mode */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x16,
clock_div_by_lanes[lanes - 2] << 3);
}
if (test_mode) {
unsigned int htotal = 1650;
unsigned int vtotal = 750;
unsigned int hsw = 0x28;
unsigned int hfp = 0x6E;
unsigned int hbp = 0xDC;
unsigned int vsw = 5;
unsigned int vfp = 5;
unsigned int vbp = 0x14;
/* horizontal porch params */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x28, htotal >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x29,
(htotal << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2a, hsw >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2b, (hsw << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2c, hfp >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2d, (hfp << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2e, hbp >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x2f, (hbp << 4) & 0xff);
/* vertical porch params */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x30, vtotal >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x31,
(vtotal << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x32, vsw >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x33, (vsw << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x34, vfp >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x35, (vfp << 4) & 0xff);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x36, vbp >> 4);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x37, (vbp << 4) & 0xff);
/* set number of dsi lanes */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x1C, 3 << 4);
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0x05, 0x20);
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0x05, 0x10);
/* Set CEC Power Mode = Always Active. Clear bits before*/
hdmi_clr_bit(HDMI_I2C_CEC_ADDR, 0xBE, 0x03);
hdmi_set_bit(HDMI_I2C_CEC_ADDR, 0xBE, 0x01);
/* Fixed Register Settings per PG*/
hdmi_write(HDMI_I2C_CEC_ADDR, 0x24, 0x20);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x26, 0x3C);
hdmi_write(HDMI_I2C_ADDR, 0x9A, 0xE0);
hdmi_write(HDMI_I2C_ADDR, 0x9B, 0x19);
hdmi_write(HDMI_I2C_ADDR, 0xBA, 0x70);
hdmi_write(HDMI_I2C_ADDR, 0xDE, 0x82);
hdmi_write(HDMI_I2C_ADDR, 0xE4, 0x40);
hdmi_write(HDMI_I2C_ADDR, 0xE5, 0x80);
/* reset internal timing generator */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x27, 0xcb);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x27, 0x8b);
hdmi_write(HDMI_I2C_CEC_ADDR, 0x27, 0xcb);
} else {
/* disable internal timing generator */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x27, 0x0b);
}
/* 09-03 AVI Infoframe - RGB - 16-9 Aspect Ratio */
hdmi_write(HDMI_I2C_ADDR, 0x55, 0x10);
hdmi_write(HDMI_I2C_ADDR, 0x56, 0x28);
/* 04-04 GC Packet Enable */
hdmi_write(HDMI_I2C_ADDR, 0x40, 0x80);
/* 04-06 GC Colour Depth - 24 Bit */
hdmi_write(HDMI_I2C_ADDR, 0x4c, 0x04);
/* 04-09 Down Dither Output Colour Depth - 8 Bit (default) */
hdmi_write(HDMI_I2C_ADDR, 0x49, 0x00);
/* 07-01 CEC Power Mode - Always Active */
hdmi_write(HDMI_I2C_CEC_ADDR, 0xbe, 0x3d);
/* HDMI Output Settings*/
/* Set HDMI/DVI Mode Select = HDMI Mode Enabled - bit 1*/
hdmi_set_bit(HDMI_I2C_ADDR, 0xAF, 0x2);
/* Enable GC Packet */
hdmi_set_bit(HDMI_I2C_ADDR, 0x40, 0x80);
/* Set Color Depth to 24 Bits/Pixel. Clear field before*/
hdmi_clr_bit(HDMI_I2C_ADDR, 0x4C, 0x0F);
hdmi_set_bit(HDMI_I2C_ADDR, 0x4C, 0x04);
/* Set Active Format Aspect Ratio = 4:3 (Center) Clear field before*/
hdmi_clr_bit(HDMI_I2C_ADDR, 0x56, 0x0F);
hdmi_set_bit(HDMI_I2C_ADDR, 0x56, 0x09);
/* Set V1P2 Enable = +1.2V*/
hdmi_set_bit(HDMI_I2C_ADDR, 0xE4, 0xC0);
if (test_mode)
/*enable test mode */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x55, 0x80);
else
/* disable test mode */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x55, 0x00);
/* enable hdmi */
hdmi_write(HDMI_I2C_CEC_ADDR, 0x03, 0x89);
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0xAF, 0b10010110); // 0x96 = 0b10010110
//hdmi_i2c_cmd_write_1(HDMI_I2C_CEC_ADDR, 0x81, 0x07);
/* Wait for the BKSV flag */
unsigned char data;
do {
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, 0x97, &data);
} while (!(data & (1 << 6)));
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x97, (data & ~0xBF) | (1 << 6));
return 0;
}
void hdmi_check(void)
{
unsigned char data;
static int i = 0;
/*hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, 0x42, &data);
LOG_HEX(data);*/
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, 0x3E, &data);
LOG_HEX(data);
hdmi_i2c_cmd_write_read_1(HDMI_I2C_ADDR, 0x96, &data);
//if (data & (1 << 5))
hdmi_i2c_cmd_write_1(HDMI_I2C_ADDR, 0x96, data);
LOG_HEX(data);
hdmi_i2c_cmd_write_read_1(HDMI_I2C_CEC_ADDR, 0x83, &data);
LOG_HEX(data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment