From 04cedbc4a0824495569e367a66c5a0ebd97b4441 Mon Sep 17 00:00:00 2001 From: Mauro Ribeiro Date: Wed, 19 Nov 2014 16:57:38 -0200 Subject: [PATCH] apply dos2unix to some of the AMLogic files so patch's applies cleanly Change-Id: I13f9faff4b386773f305f447a882457fa22888a7 --- arch/arm/mach-meson8b/hdmi_tx_hw/hdmi_tx_hw.c | 6084 ++++++++--------- arch/arm/mach-meson8b/hdmi_tx_hw/tvenc_conf.h | 462 +- drivers/amlogic/display/vout/enc_clk_config.c | 1342 ++-- drivers/amlogic/display/vout/tvmode.h | 114 +- drivers/amlogic/hdmi/hdmi_tx/hdmi_tx_edid.c | 3139 +++++---- .../linux/amlogic/hdmi_tx/hdmi_info_global.h | 1360 ++-- include/linux/amlogic/vout/vinfo.h | 160 +- 7 files changed, 6330 insertions(+), 6331 deletions(-) diff --git a/arch/arm/mach-meson8b/hdmi_tx_hw/hdmi_tx_hw.c b/arch/arm/mach-meson8b/hdmi_tx_hw/hdmi_tx_hw.c index fdeae194395c..99bfe0aadee9 100755 --- a/arch/arm/mach-meson8b/hdmi_tx_hw/hdmi_tx_hw.c +++ b/arch/arm/mach-meson8b/hdmi_tx_hw/hdmi_tx_hw.c @@ -1,3042 +1,3042 @@ -/* - * Amlogic Meson HDMI Transmitter Driver - * Copyright (C) 2010 Amlogic, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the named License, - * or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PANEL_IT6681 -#include -#endif -#include -#include -#include - -#if 0 //todo -#include "../hdmi_tx_hdcp.h" -#include "../hdmi_tx_compliance.h" -#endif -#include -#include "tvenc_conf.h" -#ifdef Wr -#undef Wr -#endif -#ifdef Rd -#undef Rd -#endif -#define Wr(reg,val) WRITE_MPEG_REG(reg,val) -#define Rd(reg) READ_MPEG_REG(reg) -#define Wr_reg_bits(reg, val, start, len) \ - Wr(reg, (Rd(reg) & ~(((1L<<(len))-1)<<(start)))|((unsigned int)(val) << (start))) - -#define EDID_RAM_ADDR_SIZE (4*128) - -static void hdmi_audio_init(unsigned char spdif_flag); -static void hdmitx_dump_tvenc_reg(int cur_VIC, int printk_flag); - -static void hdmi_phy_suspend(void); -static void hdmi_phy_wakeup(hdmitx_dev_t* hdmitx_device); - -unsigned char hdmi_pll_mode = 0; /* 1, use external clk as hdmi pll source */ -static unsigned char aud_para = 0x49; - -#define HSYNC_POLARITY 1 // HSYNC polarity: active high -#define VSYNC_POLARITY 1 // VSYNC polarity: active high -#define TX_INPUT_COLOR_DEPTH 0 // Pixel bit width: 0=24-bit; 1=30-bit; 2=36-bit; 3=48-bit. -#define TX_INPUT_COLOR_FORMAT 1 // Pixel format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. -#define TX_INPUT_COLOR_RANGE 0 // Pixel range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. - - -#define TX_OUTPUT_COLOR_RANGE 0 // Pixel range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. - -#if 1 -//spdif -#define TX_I2S_SPDIF 0 // 0=SPDIF; 1=I2S. -#define TX_I2S_8_CHANNEL 0 // 0=I2S 2-channel; 1=I2S 4 x 2-channel. -#else -//i2s 8 channel -#define TX_I2S_SPDIF 1 // 0=SPDIF; 1=I2S. -#define TX_I2S_8_CHANNEL 1 // 0=I2S 2-channel; 1=I2S 4 x 2-channel. -#endif - -//static struct tasklet_struct EDID_tasklet; -static unsigned delay_flag = 0; -static unsigned serial_reg_val=0x1; //0x22; -static unsigned char i2s_to_spdif_flag=1; // if current channel number is larger than 2ch, using i2s -static unsigned color_depth_f=0; -static unsigned color_space_f=0; -static unsigned char new_reset_sequence_flag=1; -static unsigned char power_mode=1; -static unsigned char power_off_vdac_flag=0; - /* 0, do not use fixed tvenc val for all mode; 1, use fixed tvenc val mode for 480i; 2, use fixed tvenc val mode for all modes */ -static unsigned char use_tvenc_conf_flag=1; - -static unsigned char cur_vout_index = 1; //CONFIG_AM_TV_OUTPUT2 - -static void hdmi_tx_mode_ctrl(HDMI_Video_Codes_t vic) -{ - switch(vic) { - // Interlaced Mode - case HDMI_480i60: - case HDMI_480i60_16x9: - case HDMI_576i50: - case HDMI_576i50_16x9: - CLK_GATE_ON(CTS_ENCI); - CLK_GATE_ON(VCLK2_VENCI1); - CLK_GATE_OFF(CTS_ENCP); - CLK_GATE_ON(CTS_HDMI_TX_PIXEL); - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 15, 1); - break; - case HDMI_Unkown: - CLK_GATE_OFF(CTS_ENCP); - CLK_GATE_OFF(CTS_HDMI_TX_PIXEL); - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 15, 1); - break; - // Progressive Mode - default: - CLK_GATE_OFF(CTS_ENCI); - CLK_GATE_ON(CTS_ENCP); - CLK_GATE_ON(CTS_HDMI_TX_PIXEL); - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 15, 1); - break; - } -} - -static void hdmi_tx_gate_pwr_ctrl(enum hd_ctrl cmd, void * data) -{ - hdmi_print(IMP, SYS "gate/pwr cmd: %d\n", cmd); - switch(cmd) { - case VID_EN: - { - hdmitx_dev_t* hdmitx_device = (hdmitx_dev_t *)data; - hdmi_tx_mode_ctrl(hdmitx_device->cur_VIC); - } - break; - case VID_DIS: - hdmi_tx_mode_ctrl(HDMI_Unkown); - break; - case AUD_EN: - if(i2s_to_spdif_flag == 1) { - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 13, 1); - } - else { - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 13, 1); - } - aml_set_reg32_bits(P_AIU_HDMI_CLK_DATA_CTRL, 2, 0, 2); - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 10, 2); - break; - case AUD_DIS: - hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 13, 1); - aml_set_reg32_bits(P_AIU_HDMI_CLK_DATA_CTRL, 0, 0, 2); - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 10, 2); - break; - case EDID_EN: - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 8, 2); - break; - case EDID_DIS: - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 8, 2); - break; - case HDCP_EN: - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 12, 2); - break; - case HDCP_DIS: - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 12, 2); - break; - } -} - -static unsigned long modulo(unsigned long a, unsigned long b) -{ - if (a >= b) { - return(a-b); - } else { - return(a); - } -} - -static signed int to_signed(unsigned int a) -{ - if (a <= 7) { - return(a); - } else { - return(a-16); - } -} - -static void delay_us (int us) -{ - //udelay(us); - if(delay_flag&0x1) - mdelay((us+999)/1000); - else - udelay(us); -} /* delay_us */ - -static irqreturn_t intr_handler(int irq, void *dev_instance) -{ - unsigned int data32; - hdmitx_dev_t* hdmitx_device = (hdmitx_dev_t*)dev_instance; - data32 = hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT); - hdmi_print(IMP, SYS "irq %x\n", data32); - if(hdmitx_device->hpd_lock == 1) { - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0xf); - hdmi_print(IMP, HPD "HDMI hpd locked\n"); - return IRQ_HANDLED; - } - if(hdmitx_device->internal_mode_change == 1){ // if the irq from the internal mode change, just do nothing and return - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0x7); - hdmi_print(IMP, SYS "hdmitx: ignore irq\n"); - return IRQ_HANDLED; - } - - WRITE_MPEG_REG(HHI_GCLK_MPEG2, READ_MPEG_REG(HHI_GCLK_MPEG2) | (1<<4)); //Enable HDMI PCLK - - if (data32 & (1 << 1)) { //HPD falling - hdmitx_device->vic_count = 0; - hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 1); //clear HPD falling interrupt in hdmi module - hdmitx_device->hpd_event = 2; - } - if (data32 & (1 << 0)) { //HPD rising - hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 0); //clear HPD rising interrupt in hdmi module - // If HPD asserts, then start DDC transaction - if (hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) & (1<<1)) { - // Start DDC transaction - hdmitx_device->cur_edid_block=0; - hdmitx_device->cur_phy_block_ptr=0; - hdmitx_device->hpd_event = 1; - // Error if HPD deasserts - } else { - hdmi_print(ERR, HPD "HPD deasserts!\n"); - } - } - if (data32 & (1 << 2)) { //TX EDID interrupt - if((hdmitx_device->cur_edid_block+2)<=EDID_MAX_BLOCK){ - int ii, jj; - for(jj=0;jj<2;jj++){ - for(ii=0;ii<128;ii++){ - hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128+ii] - =hdmi_rd_reg(0x600+hdmitx_device->cur_phy_block_ptr*128+ii); - } - hdmitx_device->cur_edid_block++; - hdmitx_device->cur_phy_block_ptr++; - hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; - } - } -//#ifndef AML_A3 -// /*walkaround: manually clear EDID interrupt*/ -// hdmi_wr_reg(TX_HDCP_EDID_CONFIG, hdmi_rd_reg(TX_HDCP_EDID_CONFIG) | (1<<1)); -// hdmi_wr_reg(TX_HDCP_EDID_CONFIG, hdmi_rd_reg(TX_HDCP_EDID_CONFIG) & ~(1<<1)); -// /**/ -//#endif - //tasklet_schedule(&EDID_tasklet); - hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 2); //clear EDID rising interrupt in hdmi module - } - if (!((data32 == 1) || (data32 == 2) || (data32 == 4))) { - hdmi_print(ERR, SYS "Unkown HDMI Interrupt Source\n"); - hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, data32); //clear unkown interrupt in hdmi module - } -//#ifdef AML_A3 - hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR); // A read to allow the interrupt cleared in hdmi_module before next action - hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0xf); //clear HPD falling interrupt in hdmi module -//#endif - - //aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_STAT_CLR, 1 << 25); //clear hdmi_tx interrupt - return IRQ_HANDLED; -} - -static void hdmi_tvenc1080i_set(Hdmi_tx_video_para_t* param) -{ - unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; // Annie 01Sep2011: Change value from 3 to 2, due to video encoder path delay change. - unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; - unsigned FRONT_PORCH = 88, HSYNC_PIXELS, ACTIVE_LINES = 0, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; - unsigned LINES_F0, LINES_F1 = 563,BACK_PORCH, EOF_LINES = 2, TOTAL_FRAMES; - - unsigned long total_pixels_venc ; - unsigned long active_pixels_venc; - unsigned long front_porch_venc ; - unsigned long hsync_pixels_venc ; - - unsigned long de_h_begin, de_h_end; - unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; - unsigned long hs_begin, hs_end; - unsigned long vs_adjust; - unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; - unsigned long vso_begin_evn, vso_begin_odd; - - if(param->VIC==HDMI_1080i60){ - INTERLACE_MODE = 1; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 562; - LINES_F1 = 563; - FRONT_PORCH = 88; - HSYNC_PIXELS = 44; - BACK_PORCH = 148; - EOF_LINES = 2; - VSYNC_LINES = 5; - SOF_LINES = 15; - TOTAL_FRAMES = 4; - } - else if(param->VIC==HDMI_1080i50){ - INTERLACE_MODE = 1; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 562; - LINES_F1 = 563; - FRONT_PORCH = 528; - HSYNC_PIXELS = 44; - BACK_PORCH = 148; - EOF_LINES = 2; - VSYNC_LINES = 5; - SOF_LINES = 15; - TOTAL_FRAMES = 4; - } - TOTAL_PIXELS =(FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. - TOTAL_LINES =(LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. - - total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 2200 / 1 * 2 = 4400 - active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1920 / 1 * 2 = 3840 - front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 88 / 1 * 2 = 176 - hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 44 / 1 * 2 = 88 - - aml_write_reg32(P_ENCP_VIDEO_MODE, aml_read_reg32(P_ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 - - // Program DE timing - de_h_begin = modulo(aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (383 + 3) % 4400 = 386 - de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (386 + 3840) % 4400 = 4226 - aml_write_reg32(P_ENCP_DE_H_BEGIN, de_h_begin); // 386 - aml_write_reg32(P_ENCP_DE_H_END, de_h_end); // 4226 - // Program DE timing for even field - de_v_begin_even = aml_read_reg32(P_ENCP_VIDEO_VAVON_BLINE); // 20 - de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 20 + 540 = 560 - aml_write_reg32(P_ENCP_DE_V_BEGIN_EVEN,de_v_begin_even); // 20 - aml_write_reg32(P_ENCP_DE_V_END_EVEN, de_v_end_even); // 560 - // Program DE timing for odd field if needed - if (INTERLACE_MODE) { - // Calculate de_v_begin_odd according to enc480p_timing.v: - //wire[10:0] cfg_ofld_vavon_bline = {{7{ofld_vavon_ofst1 [3]}},ofld_vavon_ofst1 [3:0]} + cfg_video_vavon_bline + ofld_line; - de_v_begin_odd = to_signed((aml_read_reg32(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + de_v_begin_even + (TOTAL_LINES-1)/2; // 1 + 20 + (1125-1)/2 = 583 - de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; // 583 + 540 = 1123 - aml_write_reg32(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd);// 583 - aml_write_reg32(P_ENCP_DE_V_END_ODD, de_v_end_odd); // 1123 - } - - // Program Hsync timing - if (de_h_end + front_porch_venc >= total_pixels_venc) { - hs_begin = de_h_end + front_porch_venc - total_pixels_venc; // 4226 + 176 - 4400 = 2 - - - - - - vs_adjust = 1; - } else { - hs_begin = de_h_end + front_porch_venc; - vs_adjust = 0; - } - hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (2 + 88) % 4400 = 90 - aml_write_reg32(P_ENCP_DVI_HSO_BEGIN, hs_begin); // 2 - aml_write_reg32(P_ENCP_DVI_HSO_END, hs_end); // 90 - - // Program Vsync timing for even field - if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) { - vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); // 20 - 15 - 5 - 0 = 0 - } else { - vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); - } - vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); // (0 + 5) % 1125 = 5 - aml_write_reg32(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); // 0 - aml_write_reg32(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); // 5 - vso_begin_evn = hs_begin; // 2 - aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 2 - aml_write_reg32(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); // 2 - // Program Vsync timing for odd field if needed - if (INTERLACE_MODE) { - vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; // 583-1 - 15 - 5 = 562 - vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; // 583-1 - 15 = 567 - vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); // (2 + 4400/2) % 4400 = 2202 - aml_write_reg32(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); // 562 - aml_write_reg32(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); // 567 - aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); // 2202 - aml_write_reg32(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); // 2202 - } - - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci - (0 << 1) | // [ 1] src_sel_encp - (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. - (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. - (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). - (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: - // 0=output CrYCb(BRG); - // 1=output YCbCr(RGB); - // 2=output YCrCb(RBG); - // 3=output CbCrY(GBR); - // 4=output CbYCr(GRB); - // 5=output CrCbY(BGR); - // 6,7=Rsrv. -#ifdef DOUBLE_CLK_720P_1080I - (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. -#else - (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. -#endif - (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. - ); - aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 1, 1); // [ 1] src_sel_encp: Enable ENCP output to HDMI - -} - -static void hdmi_tvenc480i_set(Hdmi_tx_video_para_t* param) -{ - unsigned long VFIFO2VD_TO_HDMI_LATENCY = 1; // Annie 01Sep2011: Change value from 2 to 1, due to video encoder path delay change. - unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; - unsigned FRONT_PORCH = 38, HSYNC_PIXELS = 124, ACTIVE_LINES = 0, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; - unsigned LINES_F0 = 262, LINES_F1 = 263, BACK_PORCH = 114, EOF_LINES = 2, TOTAL_FRAMES; - - unsigned long total_pixels_venc ; - unsigned long active_pixels_venc; - unsigned long front_porch_venc ; - unsigned long hsync_pixels_venc ; - - unsigned long de_h_begin, de_h_end; - unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; - unsigned long hs_begin, hs_end; - unsigned long vs_adjust; - unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; - unsigned long vso_begin_evn, vso_begin_odd; - - if((param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9)){ - INTERLACE_MODE = 1; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 1; - ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (480/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 262; - LINES_F1 = 263; - FRONT_PORCH = 38; - HSYNC_PIXELS = 124; - BACK_PORCH = 114; - EOF_LINES = 4; - VSYNC_LINES = 3; - SOF_LINES = 15; - TOTAL_FRAMES = 4; - } - else if((param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ - INTERLACE_MODE = 1; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 1; - ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (576/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 312; - LINES_F1 = 313; - FRONT_PORCH = 24; - HSYNC_PIXELS = 126; - BACK_PORCH = 138; - EOF_LINES = 2; - VSYNC_LINES = 3; - SOF_LINES = 19; - TOTAL_FRAMES = 4; - } - TOTAL_PIXELS =(FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. - TOTAL_LINES =(LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. - - total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1716 / 2 * 2 = 1716 - active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1440 / 2 * 2 = 1440 - front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 38 / 2 * 2 = 38 - hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 124 / 2 * 2 = 124 - - // Annie 01Sep2011: Comment out the following 2 lines. Because ENCP is not used for 480i and 576i. - //Wr(ENCP_VIDEO_MODE,Rd(ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 - - // Program DE timing - // Annie 01Sep2011: for 480/576i, replace VFIFO2VD_PIXEL_START with ENCI_VFIFO2VD_PIXEL_START. - de_h_begin = modulo(aml_read_reg32(P_ENCI_VFIFO2VD_PIXEL_START) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (233 + 2) % 1716 = 235 - de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (235 + 1440) % 1716 = 1675 - aml_write_reg32(P_ENCI_DE_H_BEGIN, de_h_begin); // 235 - aml_write_reg32(P_ENCI_DE_H_END, de_h_end); // 1675 - - // Annie 01Sep2011: for 480/576i, replace VFIFO2VD_LINE_TOP/BOT_START with ENCI_VFIFO2VD_LINE_TOP/BOT_START. - de_v_begin_even = aml_read_reg32(P_ENCI_VFIFO2VD_LINE_TOP_START); // 17 - de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 17 + 240 = 257 - de_v_begin_odd = aml_read_reg32(P_ENCI_VFIFO2VD_LINE_BOT_START); // 18 - de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; // 18 + 480/2 = 258 - aml_write_reg32(P_ENCI_DE_V_BEGIN_EVEN,de_v_begin_even); // 17 - aml_write_reg32(P_ENCI_DE_V_END_EVEN, de_v_end_even); // 257 - aml_write_reg32(P_ENCI_DE_V_BEGIN_ODD, de_v_begin_odd); // 18 - aml_write_reg32(P_ENCI_DE_V_END_ODD, de_v_end_odd); // 258 - - // Program Hsync timing - if (de_h_end + front_porch_venc >= total_pixels_venc) { - hs_begin = de_h_end + front_porch_venc - total_pixels_venc; - vs_adjust = 1; - } else { - hs_begin = de_h_end + front_porch_venc; // 1675 + 38 = 1713 - vs_adjust = 0; - } - hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (1713 + 124) % 1716 = 121 - aml_write_reg32(P_ENCI_DVI_HSO_BEGIN, hs_begin); // 1713 - aml_write_reg32(P_ENCI_DVI_HSO_END, hs_end); // 121 - - // Program Vsync timing for even field - if (de_v_end_odd-1 + EOF_LINES + vs_adjust >= LINES_F1) { - vs_bline_evn = de_v_end_odd-1 + EOF_LINES + vs_adjust - LINES_F1; - vs_eline_evn = vs_bline_evn + VSYNC_LINES; - aml_write_reg32(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); - //vso_bline_evn_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); - //vso_eline_evn_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_EVN, hs_begin); - aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, hs_begin); - } else { - vs_bline_odd = de_v_end_odd-1 + EOF_LINES + vs_adjust; // 258-1 + 4 + 0 = 261 - aml_write_reg32(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); // 261 - //vso_bline_odd_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_ODD, hs_begin); // 1713 - if (vs_bline_odd + VSYNC_LINES >= LINES_F1) { - vs_eline_evn = vs_bline_odd + VSYNC_LINES - LINES_F1; // 261 + 3 - 263 = 1 - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); // 1 - //vso_eline_evn_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, hs_begin); // 1713 - } else { - vs_eline_odd = vs_bline_odd + VSYNC_LINES; - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); - //vso_eline_odd_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, hs_begin); - } - } - // Program Vsync timing for odd field - if (de_v_end_even-1 + EOF_LINES + 1 >= LINES_F0) { - vs_bline_odd = de_v_end_even-1 + EOF_LINES + 1 - LINES_F0; - vs_eline_odd = vs_bline_odd + VSYNC_LINES; - aml_write_reg32(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); - //vso_bline_odd_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); - //vso_eline_odd_reg_wr_cnt ++; - vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); - aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_ODD, vso_begin_odd); - aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, vso_begin_odd); - } else { - vs_bline_evn = de_v_end_even-1 + EOF_LINES + 1; // 257-1 + 4 + 1 = 261 - aml_write_reg32(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); // 261 - //vso_bline_evn_reg_wr_cnt ++; - vso_begin_evn = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); // (1713 + 1716/2) % 1716 = 855 - aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 855 - if (vs_bline_evn + VSYNC_LINES >= LINES_F0) { - vs_eline_odd = vs_bline_evn + VSYNC_LINES - LINES_F0; // 261 + 3 - 262 = 2 - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); // 2 - //vso_eline_odd_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, vso_begin_evn); // 855 - } else { - vs_eline_evn = vs_bline_evn + VSYNC_LINES; - aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); - //vso_eline_evn_reg_wr_cnt ++; - aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, vso_begin_evn); - } - } - aml_set_reg32_bits(P_HHI_GCLK_OTHER, 1, 8, 1); // Enable VENCI gate - // Check if there are duplicate or missing timing settings - //if ((vso_bline_evn_reg_wr_cnt != 1) || (vso_bline_odd_reg_wr_cnt != 1) || - // (vso_eline_evn_reg_wr_cnt != 1) || (vso_eline_odd_reg_wr_cnt != 1)) { - //stimulus_print("[TEST.C] Error: Multiple or missing timing settings on reg ENCI_DVI_VSO_B(E)LINE_EVN(ODD)!\n"); - //stimulus_finish_fail(1); - //} - - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci - (0 << 1) | // [ 1] src_sel_encp - (0 << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. - (0 << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. - (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). - (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: - // 0=output CrYCb(BRG); - // 1=output YCbCr(RGB); - // 2=output YCrCb(RBG); - // 3=output CbCrY(GBR); - // 4=output CbYCr(GRB); - // 5=output CrCbY(BGR); - // 6,7=Rsrv. - (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. - (1 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. - ); - aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 0, 1); // [ 0] src_sel_enci: Enable ENCI output to HDMI - -} - -static void hdmi_tvenc_set(Hdmi_tx_video_para_t *param) -{ - unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; // Annie 01Sep2011: Change value from 3 to 2, due to video encoder path delay change. - unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; - unsigned FRONT_PORCH, HSYNC_PIXELS, ACTIVE_LINES, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; - unsigned LINES_F0, LINES_F1,BACK_PORCH, EOF_LINES, TOTAL_FRAMES; - - unsigned long total_pixels_venc ; - unsigned long active_pixels_venc; - unsigned long front_porch_venc ; - unsigned long hsync_pixels_venc ; - - unsigned long de_h_begin, de_h_end; - unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; - unsigned long hs_begin, hs_end; - unsigned long vs_adjust; - unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; - unsigned long vso_begin_evn, vso_begin_odd; - - if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9)){ - INTERLACE_MODE = 0; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (480/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 525; - LINES_F1 = 525; - FRONT_PORCH = 16; - HSYNC_PIXELS = 62; - BACK_PORCH = 60; - EOF_LINES = 9; - VSYNC_LINES = 6; - SOF_LINES = 30; - TOTAL_FRAMES = 4; - } - else if((param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9)){ - INTERLACE_MODE = 0; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (576/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 625; - LINES_F1 = 625; - FRONT_PORCH = 12; - HSYNC_PIXELS = 64; - BACK_PORCH = 68; - EOF_LINES = 5; - VSYNC_LINES = 5; - SOF_LINES = 39; - TOTAL_FRAMES = 4; - } - else if(param->VIC==HDMI_720p60){ - INTERLACE_MODE = 0; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (720/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 750; - LINES_F1 = 750; - FRONT_PORCH = 110; - HSYNC_PIXELS = 40; - BACK_PORCH = 220; - EOF_LINES = 5; - VSYNC_LINES = 5; - SOF_LINES = 20; - TOTAL_FRAMES = 4; - } - else if(param->VIC==HDMI_720p50){ - INTERLACE_MODE = 0; - PIXEL_REPEAT_VENC = 1; - PIXEL_REPEAT_HDMI = 0; - ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES = (720/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 = 750; - LINES_F1 = 750; - FRONT_PORCH = 440; - HSYNC_PIXELS = 40; - BACK_PORCH = 220; - EOF_LINES = 5; - VSYNC_LINES = 5; - SOF_LINES = 20; - TOTAL_FRAMES = 4; - } - else if(param->VIC==HDMI_1080p50){ - INTERLACE_MODE =0; - PIXEL_REPEAT_VENC =0; - PIXEL_REPEAT_HDMI =0; - ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 =1125; - LINES_F1 =1125; - FRONT_PORCH =528; - HSYNC_PIXELS =44; - BACK_PORCH =148; - EOF_LINES =4; - VSYNC_LINES =5; - SOF_LINES =36; - TOTAL_FRAMES =4; - } - else if(param->VIC==HDMI_1080p24){//1080p24 support - INTERLACE_MODE =0; - PIXEL_REPEAT_VENC =0; - PIXEL_REPEAT_HDMI =0; - ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 =1125; - LINES_F1 =1125; - FRONT_PORCH =638; - HSYNC_PIXELS =44; - BACK_PORCH =148; - EOF_LINES =4; - VSYNC_LINES =5; - SOF_LINES =36; - TOTAL_FRAMES =4; - } - else{ //HDMI_1080p60, HDMI_1080p30 - INTERLACE_MODE =0; - PIXEL_REPEAT_VENC =0; - PIXEL_REPEAT_HDMI =0; - ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. - ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. - LINES_F0 =1125; - LINES_F1 =1125; - FRONT_PORCH =88; - HSYNC_PIXELS =44; - BACK_PORCH =148; - EOF_LINES =4; - VSYNC_LINES =5; - SOF_LINES =36; - TOTAL_FRAMES =4; - } - - TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. - TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. - - total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 858 / 1 * 2 = 1716 - active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 720 / 1 * 2 = 1440 - front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 16 / 1 * 2 = 32 - hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 62 / 1 * 2 = 124 - - aml_write_reg32(P_ENCP_VIDEO_MODE,aml_read_reg32(P_ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 - // Program DE timing - de_h_begin = modulo(aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (217 + 3) % 1716 = 220 - de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (220 + 1440) % 1716 = 1660 - aml_write_reg32(P_ENCP_DE_H_BEGIN, de_h_begin); // 220 - aml_write_reg32(P_ENCP_DE_H_END, de_h_end); // 1660 - // Program DE timing for even field - de_v_begin_even = aml_read_reg32(P_ENCP_VIDEO_VAVON_BLINE); // 42 - de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 42 + 480 = 522 - aml_write_reg32(P_ENCP_DE_V_BEGIN_EVEN,de_v_begin_even); // 42 - aml_write_reg32(P_ENCP_DE_V_END_EVEN, de_v_end_even); // 522 - // Program DE timing for odd field if needed - if (INTERLACE_MODE) { - // Calculate de_v_begin_odd according to enc480p_timing.v: - //wire[10:0] cfg_ofld_vavon_bline = {{7{ofld_vavon_ofst1 [3]}},ofld_vavon_ofst1 [3:0]} + cfg_video_vavon_bline + ofld_line; - de_v_begin_odd = to_signed((aml_read_reg32(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + de_v_begin_even + (TOTAL_LINES-1)/2; - de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; - aml_write_reg32(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd); - aml_write_reg32(P_ENCP_DE_V_END_ODD, de_v_end_odd); - } - - // Program Hsync timing - if (de_h_end + front_porch_venc >= total_pixels_venc) { - hs_begin = de_h_end + front_porch_venc - total_pixels_venc; - vs_adjust = 1; - } else { - hs_begin = de_h_end + front_porch_venc; // 1660 + 32 = 1692 - vs_adjust = 0; - } - hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (1692 + 124) % 1716 = 100 - aml_write_reg32(P_ENCP_DVI_HSO_BEGIN, hs_begin); // 1692 - aml_write_reg32(P_ENCP_DVI_HSO_END, hs_end); // 100 - - // Program Vsync timing for even field - if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) { - vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); // 42 - 30 - 6 - 1 = 5 - } else { - vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); - } - vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); // (5 + 6) % 525 = 11 - aml_write_reg32(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); // 5 - aml_write_reg32(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); // 11 - vso_begin_evn = hs_begin; // 1692 - aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 1692 - aml_write_reg32(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); // 1692 - // Program Vsync timing for odd field if needed - if (INTERLACE_MODE) { - vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; - vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; - vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); - aml_write_reg32(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); - aml_write_reg32(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); - aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); - aml_write_reg32(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); - } - // Annie 01Sep2011: Remove the following line as register VENC_DVI_SETTING_MORE is no long valid, use VPU_HDMI_SETTING instead. - //Wr(VENC_DVI_SETTING_MORE, (TX_INPUT_COLOR_FORMAT==0)? 1 : 0); // [0] 0=Map data pins from Venc to Hdmi Tx as CrYCb mode; - - switch(param->VIC) - { - case HDMI_480p60: - case HDMI_480p60_16x9: - case HDMI_576p50: - case HDMI_576p50_16x9: -//Note: Hsync & Vsync polarity should be negative. -//Refer to HDMI CTS 1.4A Page 169 - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci - (0 << 1) | // [ 1] src_sel_encp - (0 << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. - (0 << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. - (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). - (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: - // 0=output CrYCb(BRG); - // 1=output YCbCr(RGB); - // 2=output YCrCb(RBG); - // 3=output CbCrY(GBR); - // 4=output CbYCr(GRB); - // 5=output CrCbY(BGR); - // 6,7=Rsrv. - (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. - (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. - ); - break; - case HDMI_720p60: - case HDMI_720p50: - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci - (0 << 1) | // [ 1] src_sel_encp - (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. - (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. - (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). - (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: - // 0=output CrYCb(BRG); - // 1=output YCbCr(RGB); - // 2=output YCrCb(RBG); - // 3=output CbCrY(GBR); - // 4=output CbYCr(GRB); - // 5=output CrCbY(BGR); - // 6,7=Rsrv. -#ifdef DOUBLE_CLK_720P_1080I - (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. -#else - (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. -#endif - (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. - ); - break; - default: - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci - (0 << 1) | // [ 1] src_sel_encp - (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. - (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. - (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). - (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: - // 0=output CrYCb(BRG); - // 1=output YCbCr(RGB); - // 2=output YCrCb(RBG); - // 3=output CbCrY(GBR); - // 4=output CbYCr(GRB); - // 5=output CrCbY(BGR); - // 6,7=Rsrv. - (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. - (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. - ); - } - - // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. - aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 1, 1); // [ 1] src_sel_encp: Enable ENCP output to HDMI -} - -/* -hdmi on/off -*/ -static int is_hpd_muxed(void) -{ - int ret; - ret = !!(aml_read_reg32(P_PERIPHS_PIN_MUX_1)&(1<<26)); - return ret; -} - -static void mux_hpd(void) -{ - aml_write_reg32(P_PERIPHS_PIN_MUX_1, aml_read_reg32(P_PERIPHS_PIN_MUX_1)|(1 << 26)); -} - -static void unmux_hpd(void) -{ - aml_write_reg32(P_PERIPHS_PIN_MUX_1, aml_read_reg32(P_PERIPHS_PIN_MUX_1)&~(1 << 26)); - aml_write_reg32(P_PREG_PAD_GPIO3_EN_N, aml_read_reg32(P_PREG_PAD_GPIO3_EN_N) | (1 << 19)); //GPIOH_0 as input -} - -extern int read_hpd_gpio(void); -int read_hpd_gpio(void) -{ - int level; - - level = !!(aml_read_reg32(P_PREG_PAD_GPIO3_I)&(1<<19)); //read GPIOH_0 - return level; -} -EXPORT_SYMBOL(read_hpd_gpio); - -#if 0 -static unsigned long clk81_rate = 100000000; - -static void clk81_set(void) -{ - struct clk *clk_tmp; - - clk_tmp = clk_get_sys("clk81", NULL); - if (clk_tmp) - { - clk81_rate = clk_get_rate(clk_tmp); - clk_set_rate(clk_tmp, 168000000); - CLEAR_AOBUS_REG_MASK(AO_UART_CONTROL, (1 << 19) | 0xFFF); - WRITE_AOBUS_REG_BITS(AO_UART_CONTROL, ((168000000 / (115200 * 4)) - 1) & 0xfff, 0, 12); - } - msleep(2); //Waiting some time - //printk("%s clk81_rate: %d\n", __FUNCTION__, clk81_rate); -} - -static void clk81_resume(void) -{ - struct clk *clk_tmp; - - clk_tmp = clk_get_sys("clk81", NULL); - if (clk_tmp) - { - clk_set_rate(clk_tmp, clk81_rate); - CLEAR_AOBUS_REG_MASK(AO_UART_CONTROL, (1 << 19) | 0xFFF); - WRITE_AOBUS_REG_BITS(AO_UART_CONTROL, ((clk81_rate / (115200 * 4)) - 1) & 0xfff, 0, 12); - } - msleep(2); //Waiting some time - //printk("%s clk81_rate: %d\n", __FUNCTION__, clk81_rate); -} -#endif - -static void digital_clk_off(unsigned char flag) -{ -// clk81_resume(); - if(flag&1){ -//#ifdef AML_A3 - /* off hdmi audio clock */ -// hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1)&(~(1<<13))); // -// hdmi_wr_reg(TX_AUDIO_FORMAT, hdmi_rd_reg(TX_AUDIO_FORMAT)|(1<<7)); -// hdmi_wr_reg(TX_AUDIO_I2S, hdmi_rd_reg(TX_AUDIO_I2S)|(1<<1)); -//#endif - } - - if(flag&2){ - /* off hdmi pixel clock */ -// Wr(HHI_GCLK_MPEG2, Rd(HHI_GCLK_MPEG2)&(~(1<<4))); //disable pixel clock, set cbus reg HHI_GCLK_MPEG2 bit [4] = 0 - aml_write_reg32(P_HHI_GCLK_OTHER, aml_read_reg32(P_HHI_GCLK_OTHER)&(~(1<<17))); //disable VCLK1_HDMI GATE, set cbus reg HHI_GCLK_OTHER bit [17] = 0 - aml_write_reg32(P_VENC_DVI_SETTING, (aml_read_reg32(P_VENC_DVI_SETTING)&(~(7<<4)))|(5<<4)); //set cbus reg VENC_DVI_SETTING bit[6:4] = 0x5 - // Second turn off gate. - aml_write_reg32(P_HHI_GCLK_MPEG2, aml_read_reg32(P_HHI_GCLK_MPEG2) & (~(1<<4))); //Disable HDMI PCLK - } - if(flag&4){ - /* off hdmi sys clock */ - aml_write_reg32(P_HHI_HDMI_CLK_CNTL, aml_read_reg32(P_HHI_HDMI_CLK_CNTL)&(~(1<<8))); // off hdmi sys clock gate - } -} - -static void digital_clk_on(unsigned char flag) -{ -// clk81_set(); - if(flag&4){ - /* on hdmi sys clock */ - // ----------------------------------------- - // HDMI (90Mhz) - // ----------------------------------------- - // .clk_div ( hi_hdmi_clk_cntl[6:0] ), - // .clk_en ( hi_hdmi_clk_cntl[8] ), - // .clk_sel ( hi_hdmi_clk_cntl[11:9]), - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); // Divide the "other" PLL output by 1 - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 3); // select "XTAL" PLL - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); // Enable gated clock -// Wr( HHI_HDMI_CLK_CNTL, ((2 << 9) | // select "misc" PLL -// (1 << 8) | // Enable gated clock -// (5 << 0)) ); // Divide the "other" PLL output by 6 - } - if(flag&2){ - /* on hdmi pixel clock */ - aml_write_reg32(P_HHI_GCLK_MPEG2, aml_read_reg32(P_HHI_GCLK_MPEG2) | (1<<4)); //Enable HDMI PCLK -// Wr(HHI_GCLK_MPEG2, Rd(HHI_GCLK_MPEG2)|(1<<4)); //enable pixel clock, set cbus reg HHI_GCLK_MPEG2 bit [4] = 1 - aml_write_reg32(P_HHI_GCLK_OTHER, aml_read_reg32(P_HHI_GCLK_OTHER)|(1<<17)); //enable VCLK1_HDMI GATE, set cbus reg HHI_GCLK_OTHER bit [17] = 1 - } - if(flag&1){ - } -} - -static void phy_pll_off(void) -{ - hdmi_phy_suspend(); -} - -/**/ -void hdmi_hw_set_powermode(hdmitx_dev_t* hdmitx_device) -{ - int vic = hdmitx_device->cur_VIC; - - switch(vic) { - case HDMI_480i60: - case HDMI_480i60_16x9: - case HDMI_576p50: - case HDMI_576p50_16x9: - case HDMI_576i50: - case HDMI_576i50_16x9: - case HDMI_480p60: - case HDMI_480p60_16x9: - case HDMI_720p50: - case HDMI_720p60: - case HDMI_1080i50: - case HDMI_1080i60: - case HDMI_1080p24://1080p24 support - case HDMI_1080p50: - case HDMI_1080p60: - default: - //aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08c38d0b); - break; - } - //aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 2); -} - -void hdmi_hw_init(hdmitx_dev_t* hdmitx_device) -{ - unsigned int tmp_add_data; - HDMI_Video_Codes_t vic; - - digital_clk_on(7); - aml_set_reg32_bits(P_HHI_VPU_MEM_PD_REG1, 0x0, 20, 2); -// Powerup VPU_HDMI - aml_write_reg32(P_AO_RTI_GEN_PWR_SLEEP0, aml_read_reg32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<8))); // [8] power on - aml_write_reg32(P_HHI_MEM_PD_REG0, aml_read_reg32(P_HHI_MEM_PD_REG0) & (~(0xff << 8))); // HDMI MEM-PD - - // Remove VPU_HDMI ISO - aml_write_reg32(P_AO_RTI_GEN_PWR_SLEEP0, aml_read_reg32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<9))); // [9] VPU_HDMI - - aml_set_reg32_bits(P_HHI_GCLK_MPEG2, 1, 4, 1); //enable HDMI PCLK - aml_set_reg32_bits(P_HHI_GCLK_MPEG2, 1, 3, 1); //enable HDMI Int Sync - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 2); // select XTAL - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); // Divide by 1 - aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); // Enable gated clock - - aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0x00, 8, 8); //disable HDMI memory PD TODO: set in suspend/resume - - aml_write_reg32(P_HHI_HDMI_AFC_CNTL, aml_read_reg32(P_HHI_HDMI_AFC_CNTL) | 0x3); - - hdmi_wr_reg(TX_HDCP_MODE, 0x40); -#ifndef CONFIG_AML_HDMI_TX_HDCP - hdmi_tx_gate_pwr_ctrl(HDCP_DIS, NULL); -#endif - vic = hdmitx_device->HWOp.GetState(hdmitx_device, STAT_VIDEO_VIC, 0); - if(vic != HDMI_Unkown) { - hdmi_print(IMP, SYS "ALREADY init VIC = %d\n", vic); - hdmitx_device->cur_VIC = vic; - hdmi_tx_gate_pwr_ctrl(VID_EN, hdmitx_device); - return; - } - else { - hdmi_tx_gate_pwr_ctrl(VID_DIS, NULL); - } - hdmi_phy_suspend(); - //todo - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0xf, 23, 4); //Enable reg1[23:24]:HDMI SDA(5v)/SCL(5V) -#ifdef CONFIG_PANEL_IT6681 - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0, 23, 3); //disable reg1[23:25]:HDMI CEC/SCL(5v)/SDA(5V) -#endif - hdmi_print(IMP, SYS "hw init\n"); - - hdmi_wr_reg(0x017, 0x1d); //1d for power-up Band-gap and main-bias ,00 is power down - if(serial_reg_val<0x20){ - hdmi_wr_reg(0x018, 0x24); - } - else{ - hdmi_wr_reg(0x018, serial_reg_val); //Serializer Internal clock setting ,please fix to vaue 24 ,other setting is only for debug - } - hdmi_wr_reg(0x01a, 0xfb); //bit[2:0]=011 ,CK channel output TMDS CLOCK ,bit[2:0]=101 ,ck channel output PHYCLCK - - hdmi_hw_set_powermode(hdmitx_device); - - hdmi_wr_reg(0x0F7, 0x0F); // Termination resistor calib value - - // -------------------------------------------------------- - // Program core_pin_mux to enable HDMI pins - // -------------------------------------------------------- - //wire pm_hdmi_cec_en = pin_mux_reg0[2]; - //wire pm_hdmi_hpd_5v_en = pin_mux_reg0[1]; - //wire pm_hdmi_i2c_5v_en = pin_mux_reg0[0]; - - // Enable these interrupts: [2] tx_edit_int_rise [1] tx_hpd_int_fall [0] tx_hpd_int_rise - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0x0); - // HPD glitch filter - hdmi_wr_reg(TX_HDCP_HPD_FILTER_L, 0xa0); - hdmi_wr_reg(TX_HDCP_HPD_FILTER_H, 0xa0); - - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x90); //bit5,6 is converted - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); - delay_us(10); - - /**/ - - // Enable software controlled DDC transaction - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0 ; // forced_sys_trigger - //tmp_add_data[6] = 1'b0 ; // sys_trigger_config - //tmp_add_data[5] = 1'b0 ; // mem_acc_seq_mode - //tmp_add_data[4] = 1'b0 ; // mem_acc_seq_start - //tmp_add_data[3] = 1'b1 ; // forced_mem_copy_done - //tmp_add_data[2] = 1'b1 ; // mem_copy_done_config - //tmp_add_data[1] = 1'b1 ; // sys_trigger_config_semi_manu - //tmp_add_data[0] = 1'b0 ; // Rsrv - hdmi_wr_reg(TX_HDCP_EDID_CONFIG, 0x0c); //// for hdcp, can not use 0x0e - hdmi_wr_reg(TX_CORE_EDID_CONFIG_MORE, (1 << 0)); // [1]: keep_edid_error - // [0]: sys_trigger_config_semi_manu - - hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_1, 0); - hdmi_wr_reg(TX_PACKET_CONTROL_2, 2); - - hdmi_wr_reg(TX_HDCP_CONFIG0, 1<<3); //set TX rom_encrypt_off=1 - hdmi_wr_reg(TX_HDCP_MEM_CONFIG, 0<<3); //set TX read_decrypt=0 - hdmi_wr_reg(TX_HDCP_ENCRYPT_BYTE, 0); //set TX encrypt_byte=0x00 - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // Force packet timing - //tmp_add_data[6] = 1'b0; // PACKET ALLOC MODE - //tmp_add_data[5:0] = 6'd47 ; // PACKET_START_LATENCY - //tmp_add_data = 47; - tmp_add_data = 58; - hdmi_wr_reg(TX_PACKET_CONTROL_1, tmp_add_data); //this register should be set to ensure the first hdcp succeed - - //tmp_add_data[7] = 1'b0; // cp_desired - //tmp_add_data[6] = 1'b0; // ess_config - //tmp_add_data[5] = 1'b0; // set_avmute - //tmp_add_data[4] = 1'b1; // clear_avmute - //tmp_add_data[3] = 1'b0; // hdcp_1_1 - //tmp_add_data[2] = 1'b0; // Vsync/Hsync forced_polarity_select - //tmp_add_data[1] = 1'b0; // forced_vsync_polarity - //tmp_add_data[0] = 1'b0; // forced_hsync_polarity - //tmp_add_data = 0x10; - tmp_add_data = 0x0; //rain - hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); - //config_hdmi(1); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7:0] = 0xa ; // time_divider[7:0] for DDC I2C bus clock - //tmp_add_data = 0xa; //800k - //tmp_add_data = 0x3f; //190k - tmp_add_data = 0x18 - 1; //50k // hdmi system clock change to XTAL 24MHz - hdmi_wr_reg(TX_HDCP_CONFIG3, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 8'b1 ; //cp_desired - //tmp_add_data[6] = 8'b1 ; //ess_config - //tmp_add_data[5] = 8'b0 ; //set_avmute - //tmp_add_data[4] = 8'b0 ; //clear_avmute - //tmp_add_data[3] = 8'b1 ; //hdcp_1_1 - //tmp_add_data[2] = 8'b0 ; //forced_polarity - //tmp_add_data[1] = 8'b0 ; //forced_vsync_polarity - //tmp_add_data[0] = 8'b0 ; //forced_hsync_polarity - tmp_add_data = 0x40; - hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); - - hdmi_wr_reg(TX_AUDIO_CONTROL_MORE, 1); - - hdmi_hw_set_powermode(hdmitx_device); - - // -------------------------------------------------------- - // Release TX out of reset - // -------------------------------------------------------- - //new reset sequence, 2010Sep09, rain - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain - delay_us(10); - - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x68); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - delay_us(10); -} - -#ifdef CONFIG_ARCH_MESON6 -// TODO, need test in m8 -// When 1080p50hz output, we shall manually configure -// bolow register to get stable Video Timing. -static void hdmi_reconfig_packet_setting(void) -{ - hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_1, 0x01); - hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_2, 0x12); - hdmi_wr_reg(TX_PACKET_ALLOC_EOF_1, 0x10); - hdmi_wr_reg(TX_PACKET_ALLOC_EOF_2, 0x12); - hdmi_wr_reg(TX_PACKET_ALLOC_SOF_1, 0xb6); - hdmi_wr_reg(TX_PACKET_ALLOC_SOF_2, 0x11); - hdmi_wr_reg(TX_PACKET_CONTROL_1, (hdmi_rd_reg(TX_PACKET_CONTROL_1)) | (1 << 7)); // bit[7]: forced_packet_timing -} -#endif - -static void hdmi_hw_reset(hdmitx_dev_t* hdmitx_device, Hdmi_tx_video_para_t *param) -{ - unsigned int tmp_add_data; - unsigned long TX_OUTPUT_COLOR_FORMAT; - - hdmi_print(IMP, SYS "hw reset\n"); - - digital_clk_on(7); - - if(param->color==COLOR_SPACE_YUV444){ - TX_OUTPUT_COLOR_FORMAT=1; - } - else if(param->color==COLOR_SPACE_YUV422){ - TX_OUTPUT_COLOR_FORMAT=3; - } - else{ - TX_OUTPUT_COLOR_FORMAT=0; - } - - if(delay_flag&2) - delay_us(1000*100); - //printk("delay 100ms\n"); - - aml_write_reg32(P_HHI_HDMI_AFC_CNTL, aml_read_reg32(P_HHI_HDMI_AFC_CNTL) | 0x3); - - hdmi_wr_reg(0x017, 0x1d); //1d for power-up Band-gap and main-bias ,00 is power down - if(new_reset_sequence_flag==0){ - if(serial_reg_val==0){ - if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60) - ||(param->VIC==HDMI_1080p24)){ - hdmi_wr_reg(0x018, 0x22); - } - else{ - hdmi_wr_reg(0x018, 0x24); - } - } - else if(serial_reg_val==1){ - if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9) - ||(param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9) - ||(param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9) - ||(param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ - hdmi_wr_reg(0x018, 0x24); - } - else{ - hdmi_wr_reg(0x018, 0x22); - } - } - else{ - hdmi_wr_reg(0x018, serial_reg_val); - } - if((param->VIC==HDMI_1080p60)&&(param->color_depth==COLOR_30BIT)&&(hdmi_rd_reg(0x018)==0x22)){ - hdmi_wr_reg(0x018,0x12); - } - } - hdmi_wr_reg(0x01a, 0xfb); //bit[2:0]=011 ,CK channel output TMDS CLOCK ,bit[2:0]=101 ,ck channel output PHYCLCK - - hdmi_hw_set_powermode(hdmitx_device); - - hdmi_wr_reg(0x0F7, 0x0F); // Termination resistor calib value - - // delay 1000uS, then check HPLL_LOCK - delay_us(1000); - //while ( (Rd(HHI_VID_PLL_CNTL3) & (1<<31)) != (1<<31) ); - -//////////////////////////////reset - if(new_reset_sequence_flag){ - - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x90); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); - delay_us(10); - } - else{ - // Keep TX (except register I/F) in reset, while programming the registers: - tmp_add_data = 0; - tmp_add_data |= 1 << 7; // tx_pixel_rstn - tmp_add_data |= 1 << 6; // tx_tmds_rstn - tmp_add_data |= 1 << 5; // tx_audio_master_rstn - tmp_add_data |= 1 << 4; // tx_audio_sample_rstn - tmp_add_data |= 1 << 3; // tx_i2s_reset_rstn - tmp_add_data |= 1 << 2; // tx_dig_reset_n_ch2 - tmp_add_data |= 1 << 1; // tx_dig_reset_n_ch1 - tmp_add_data |= 1 << 0; // tx_dig_reset_n_ch0 - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, tmp_add_data); - - tmp_add_data = 0; - tmp_add_data |= 1 << 7; // HDMI_CH3_RST_IN - tmp_add_data |= 1 << 6; // HDMI_CH2_RST_IN - tmp_add_data |= 1 << 5; // HDMI_CH1_RST_IN - tmp_add_data |= 1 << 4; // HDMI_CH0_RST_IN - tmp_add_data |= 1 << 3; // HDMI_SR_RST - tmp_add_data |= 1 << 0; // tx_dig_reset_n_ch3 - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, tmp_add_data); - } - // Enable software controlled DDC transaction - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0 ; // forced_sys_trigger - //tmp_add_data[6] = 1'b0 ; // sys_trigger_config - //tmp_add_data[5] = 1'b0 ; // mem_acc_seq_mode - //tmp_add_data[4] = 1'b0 ; // mem_acc_seq_start - //tmp_add_data[3] = 1'b1 ; // forced_mem_copy_done - //tmp_add_data[2] = 1'b1 ; // mem_copy_done_config - //tmp_add_data[1] = 1'b1 ; // sys_trigger_config_semi_manu - //tmp_add_data[0] = 1'b0 ; // Rsrv - - tmp_add_data = 0x0c; // for hdcp, can not use 0x0e - hdmi_wr_reg(TX_HDCP_EDID_CONFIG, tmp_add_data); - - hdmi_wr_reg(TX_HDCP_CONFIG0, 0x3<<3); //set TX rom_encrypt_off=1 - hdmi_wr_reg(TX_HDCP_MEM_CONFIG, 0<<3); //set TX read_decrypt=0 - hdmi_wr_reg(TX_HDCP_ENCRYPT_BYTE, 0); //set TX encrypt_byte=0x00 - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // Force DTV timing (Auto) - //tmp_add_data[6] = 1'b0; // Force Video Scan, only if [7]is set - //tmp_add_data[5] = 1'b0 ; // Force Video field, only if [7]is set - //tmp_add_data[4:0] = 5'b00 ; // Rsrv - if(hdmitx_device->cur_VIC == 39) - tmp_add_data = 0; - else - tmp_add_data = (1<<4); - hdmi_wr_reg(TX_VIDEO_DTV_TIMING, tmp_add_data); - - tmp_add_data = 0; - tmp_add_data |= 0 << 7; // [7] forced_default_phase - tmp_add_data |= 0 << 2; // [6:2] Rsrv - tmp_add_data |= param->color_depth << 0; // [1:0] Color_depth:0=24-bit pixel; 1=30-bit pixel; 2=36-bit pixel; 3=48-bit pixel - hdmi_wr_reg(TX_VIDEO_DTV_MODE, tmp_add_data); // 0x00 - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // Force packet timing - //tmp_add_data[6] = 1'b0; // PACKET ALLOC MODE - //tmp_add_data[5:0] = 6'd47 ; // PACKET_START_LATENCY - //tmp_add_data = 47; - tmp_add_data = 58; - hdmi_wr_reg(TX_PACKET_CONTROL_1, tmp_add_data); - - // For debug: disable packets of audio_request, acr_request, deep_color_request, and avmute_request - //hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | 0x0f); - - //HDMI CT 7-19 GCP PB1 through PB6 not equal to 0 | 720 3 0 37 72 16367911819.90 31822 General Control Packet (GCP) - //PACKET_CONTROL[~deep_color_request_enable] - //0: horizontal GC packet transport enabled - //1: horizontal GC packet masked - hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | (0x1<<1)); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] - //tmp_add_data[5] = 1'b0; // external_packet_enable - //tmp_add_data[4] = 1'b1 ; // internal_packet_enable - //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] - //tmp_add_data[1:0] = 2'b0 ; // afe_fifo_source_select_lane_0[1:0] - tmp_add_data = 0x10; - hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // monitor_lane_1 - //tmp_add_data[6:4] = 3'd0; // monitor_select_lane_1[2:0] - //tmp_add_data[3] = 1'b1 ; // monitor_lane_0 - //tmp_add_data[2:0] = 3'd7; // monitor_select_lane_0[2:0] - tmp_add_data = 0xf; - hdmi_wr_reg(TX_CORE_DATA_MONITOR_1, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7:3] = 5'b0; // Rsrv - //tmp_add_data[2:0] = 3'd2; // monitor_select[2:0] - tmp_add_data = 0x2; - hdmi_wr_reg(TX_CORE_DATA_MONITOR_2, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b1; // forced_hdmi - //tmp_add_data[6] = 1'b1; // hdmi_config - //tmp_add_data[5:4] = 2'b0; // Rsrv - //tmp_add_data[3] = 1'b0; // bit_swap. - //tmp_add_data[2:0] = 3'd0; // channel_swap[2:0] - tmp_add_data = 0xc0; - hdmi_wr_reg(TX_TMDS_MODE, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // Rsrv - //tmp_add_data[6] = 1'b0; // TX_CONNECT_SEL: 0=use lower channel data[29:0]; 1=use upper channel data[59:30] - //tmp_add_data[5:0] = 'h0; // Rsrv - tmp_add_data = 0x0; - hdmi_wr_reg(TX_SYS4_CONNECT_SEL_1, tmp_add_data); - - // Normally it makes sense to synch 3 channel output with clock channel's rising edge, - // as HDMI's serializer is LSB out first, invert tmds_clk pattern from "1111100000" to - // "0000011111" actually enable data synch with clock rising edge. - //if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60)){ - // hdmi_wr_reg(TX_SYS4_CK_INV_VIDEO, 0xf0); - //} - //else{ - tmp_add_data = 1 << 4; // Set tmds_clk pattern to be "0000011111" before being sent to AFE clock channel - hdmi_wr_reg(TX_SYS4_CK_INV_VIDEO, tmp_add_data); - //} - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 1'b0; // Rsrv - //tmp_add_data[6] = 1'b0; // TX_AFE_FIFO channel 2 bypass=0 - //tmp_add_data[5] = 1'b0; // TX_AFE_FIFO channel 1 bypass=0 - //tmp_add_data[4] = 1'b0; // TX_AFE_FIFO channel 0 bypass=0 - //tmp_add_data[3] = 1'b1; // output enable of clk channel (channel 3) - //tmp_add_data[2] = 1'b1; // TX_AFE_FIFO channel 2 enable - //tmp_add_data[1] = 1'b1; // TX_AFE_FIFO channel 1 enable - //tmp_add_data[0] = 1'b1; // TX_AFE_FIFO channel 0 enable - tmp_add_data = 0x0f; - hdmi_wr_reg(TX_SYS5_FIFO_CONFIG, tmp_add_data); - - tmp_add_data = 0; - tmp_add_data |= TX_OUTPUT_COLOR_FORMAT << 6; // [7:6] output_color_format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. - tmp_add_data |= TX_INPUT_COLOR_FORMAT << 4; // [5:4] input_color_format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. - tmp_add_data |= param->color_depth << 2; // [3:2] output_color_depth: 0=24-b; 1=30-b; 2=36-b; 3=48-b. - tmp_add_data |= TX_INPUT_COLOR_DEPTH << 0; // [1:0] input_color_depth: 0=24-b; 1=30-b; 2=36-b; 3=48-b. - hdmi_wr_reg(TX_VIDEO_DTV_OPTION_L, tmp_add_data); // 0x50 - - if(hdmitx_device->cur_audio_param.channel_num > CC_2CH) { - i2s_to_spdif_flag = 0; - }else{ - i2s_to_spdif_flag = 1; - } - tmp_add_data = 0; - tmp_add_data |= 0 << 4; // [7:4] Rsrv - tmp_add_data |= TX_OUTPUT_COLOR_RANGE << 2; // [3:2] output_color_range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. - tmp_add_data |= TX_INPUT_COLOR_RANGE << 0; // [1:0] input_color_range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. - hdmi_wr_reg(TX_VIDEO_DTV_OPTION_H, tmp_add_data); // 0x00 - - if(!hdmi_audio_off_flag){ -#if 1 - hdmi_audio_init(i2s_to_spdif_flag); -#else - hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets -#endif - } - hdmi_wr_reg(TX_AUDIO_CONTROL_MORE, 1); - //tmp_add_data[7] = 1'b0; // cp_desired - //tmp_add_data[6] = 1'b0; // ess_config - //tmp_add_data[5] = 1'b0; // set_avmute - //tmp_add_data[4] = 1'b1; // clear_avmute - //tmp_add_data[3] = 1'b0; // hdcp_1_1 - //tmp_add_data[2] = 1'b0; // Vsync/Hsync forced_polarity_select - //tmp_add_data[1] = 1'b0; // forced_vsync_polarity - //tmp_add_data[0] = 1'b0; // forced_hsync_polarity - //tmp_add_data = 0x10; - tmp_add_data = 0x0; //rain -// hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); - //config_hdmi(1); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7:0] = 0xa ; // time_divider[7:0] for DDC I2C bus clock - - //tmp_add_data = 0xa; //800k - //tmp_add_data = 0x3f; //190k - tmp_add_data = 0x30 - 1; //50k // hdmi system clock change to XTAL 24MHz - hdmi_wr_reg(TX_HDCP_CONFIG3, tmp_add_data); - - //tmp_add_data[15:8] = 0; - //tmp_add_data[7] = 8'b1 ; //cp_desired - //tmp_add_data[6] = 8'b1 ; //ess_config - //tmp_add_data[5] = 8'b0 ; //set_avmute - //tmp_add_data[4] = 8'b0 ; //clear_avmute - //tmp_add_data[3] = 8'b1 ; //hdcp_1_1 - //tmp_add_data[2] = 8'b0 ; //forced_polarity - //tmp_add_data[1] = 8'b0 ; //forced_vsync_polarity - //tmp_add_data[0] = 8'b0 ; //forced_hsync_polarity - tmp_add_data = 0x40; - hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); - - if(param->cc == CC_ITU709){ - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B0, 0x7b); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B1, 0x12); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R0, 0x6c); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R1, 0x36); - - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB0, 0xf2); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB1, 0x2f); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR0, 0xd4); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR1, 0x77); - } - else{ - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B0, 0x2f); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B1, 0x1d); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R0, 0x8b); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R1, 0x4c); - - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB0, 0x18); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB1, 0x58); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR0, 0xd0); - hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR1, 0xb6); - } - - hdmi_hw_set_powermode(hdmitx_device); - - // -------------------------------------------------------- - // Release TX out of reset - // -------------------------------------------------------- - if(new_reset_sequence_flag){ - //new reset sequence, 2010Sep09, rain - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x68); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - delay_us(10); - /* select serial*/ - if(serial_reg_val==0){ - if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60) - ||(param->VIC==HDMI_1080p24)){ - hdmi_wr_reg(0x018, 0x22); - } - else{ - hdmi_wr_reg(0x018, 0x24); - } - } - else if(serial_reg_val==1){ - if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9) - ||(param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9) - ||(param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9) - ||(param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ - hdmi_wr_reg(0x018, 0x24); - } - else{ - hdmi_wr_reg(0x018, 0x22); - } - } - else{ - hdmi_wr_reg(0x018, serial_reg_val); - } - if((param->VIC==HDMI_1080p60)&&(param->color_depth==COLOR_30BIT)&&(hdmi_rd_reg(0x018)==0x22)){ - hdmi_wr_reg(0x018,0x12); - } - - } - else{ - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x01); // Release serializer resets - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x00); // Release reset on TX digital clock channel - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk - delay_us(10); - - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain - - tmp_add_data = hdmi_rd_reg(0x018); - if((tmp_add_data==0x22)||(tmp_add_data==0x12)){ - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x08); - delay_us(10); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x00); - } - } -#ifdef CONFIG_ARCH_MESON6 //todo - if(param->VIC == HDMI_1080p50) { - hdmi_reconfig_packet_setting(); // For 1080p50hz only - } -#endif -} - -static void hdmi_audio_init(unsigned char spdif_flag) -{ - unsigned tmp_add_data; - - /* If TX_AUDIO_FORMAT is set as 0, "Channel Status" will not be sent out correctly */ - /* TX_AUDIO_CONTROL[bit 0] should be 1, otherwise no sound??? */ - unsigned char tx_i2s_spdif; - unsigned char tx_i2s_8_channel; - - hdmi_print(IMP, AUD "%s\n", spdif_flag ? "SPDIF" : "I2S"); - - if(spdif_flag){ - tx_i2s_spdif=0; - } - else{ - tx_i2s_spdif=1; - } - tx_i2s_8_channel = ((i2s_to_spdif_flag == 1)? 0:1 ); - - tmp_add_data = 0; - tmp_add_data |= tx_i2s_spdif << 7; // [7] I2S or SPDIF - tmp_add_data |= tx_i2s_8_channel<< 6; // [6] 8 or 2ch - tmp_add_data |= 2 << 4; // [5:4] Serial Format: I2S format - tmp_add_data |= 3 << 2; // [3:2] Bit Width: 24-bit - tmp_add_data |= 0 << 1; // [1] WS Polarity: 0=WS high is right - tmp_add_data |= 1 << 0; // [0] For I2S: 0=one-bit audio; 1=I2S; - // For SPDIF: 0= channel status from input data; 1=from register - hdmi_wr_reg(TX_AUDIO_FORMAT, tmp_add_data); // 0x2f - - //tmp_add_data = 0; - //tmp_add_data |= 0x4 << 4; // [7:4] FIFO Depth=512 - //tmp_add_data |= 0x2 << 2; // [3:2] Critical threshold=Depth/16 - //tmp_add_data |= 0x1 << 0; // [1:0] Normal threshold=Depth/8 - //hdmi_wr_reg(TX_AUDIO_FIFO, tmp_add_data); // 0x49 - hdmi_wr_reg(TX_AUDIO_FIFO, aud_para); // 0x49 - - hdmi_wr_reg(TX_AUDIO_LIPSYNC, 0); // [7:0] Normalized lip-sync param: 0 means S(lipsync) = S(total)/2 - - tmp_add_data = 0; - tmp_add_data |= 0 << 7; // [7] forced_audio_fifo_clear - tmp_add_data |= 1 << 6; // [6] auto_audio_fifo_clear - tmp_add_data |= 0x0 << 4; // [5:4] audio_packet_type: 0=audio sample packet; 1=one bit audio; 2=HBR audio packet; 3=DST audio packet. - tmp_add_data |= 0 << 3; // [3] Rsrv - tmp_add_data |= 0 << 2; // [2] Audio sample packet's valid bit: 0=valid bit is 0 for I2S, is input data for SPDIF; 1=valid bit from register - tmp_add_data |= 0 << 1; // [1] Audio sample packet's user bit: 0=user bit is 0 for I2S, is input data for SPDIF; 1=user bit from register - tmp_add_data |= 0 << 0; // [0] 0=Audio sample packet's sample_flat bit is 1; 1=sample_flat is 0. - hdmi_wr_reg(TX_AUDIO_CONTROL, tmp_add_data); // 0x40 - - tmp_add_data = 0; - tmp_add_data |= tx_i2s_8_channel<< 7; // [7] Audio sample packet's header layout bit: 0=layout0; 1=layout1 - tmp_add_data |= 0 << 6; // [6] Set normal_double bit in DST packet header. - tmp_add_data |= 0 << 0; // [5:0] Rsrv - hdmi_wr_reg(TX_AUDIO_HEADER, tmp_add_data); // 0x00 - - tmp_add_data = tx_i2s_8_channel ? 0xff : 0x03; - hdmi_wr_reg(TX_AUDIO_SAMPLE, tmp_add_data); // Channel valid for up to 8 channels, 1 bit per channel. - - hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // Enable audio sample packets - - // Set N = 4096 (N is not measured, N must be configured so as to be a reference to clock_meter) - hdmi_wr_reg(TX_SYS1_ACR_N_0, 0x00); // N[7:0] - hdmi_wr_reg(TX_SYS1_ACR_N_1, 0x30); // N[15:8] - - tmp_add_data = 0; - tmp_add_data |= 0x3 << 4; // [7:4] Meas Tolerance - tmp_add_data |= 0x0 << 0; // [3:0] N[19:16] - hdmi_wr_reg(TX_SYS1_ACR_N_2, tmp_add_data); // 0xa0 - - hdmi_wr_reg(TX_AUDIO_CONTROL, hdmi_rd_reg(TX_AUDIO_CONTROL)|0x1); -} - -static void enable_audio_spdif(void) -{ - hdmi_print(INF, AUD "Enable audio spdif to HDMI\n"); - - /* enable audio*/ - hdmi_wr_reg(TX_AUDIO_I2S, 0x0 ); // Address 0x5A=0x0 TX_AUDIO_I2S - - hdmi_wr_reg(TX_AUDIO_SPDIF, 1); // TX AUDIO SPDIF Enable -} - -static void enable_audio_i2s(void) -{ - hdmi_print(INF, AUD "Enable audio i2s to HDMI\n"); - hdmi_wr_reg(TX_AUDIO_I2S, 0x1 ); // Address 0x5A=0x0 TX_AUDIO_I2S - hdmi_wr_reg(TX_AUDIO_SPDIF, 0); // TX AUDIO SPDIF Enable -} - -/************************************ -* hdmitx hardware level interface -*************************************/ - -static void hdmitx_dump_tvenc_reg(int cur_VIC, int printk_flag) -{ - int i,j; - for(i=0;hdmi_tvenc_configs[i].vic!=HDMI_Unkown;i++){ - if(cur_VIC==hdmi_tvenc_configs[i].vic){ - reg_t* reg_set=hdmi_tvenc_configs[i].reg_set; - hdmi_print(printk_flag, "------dump tevenc reg for mode %d----\n", cur_VIC); - for(j=0;reg_set[j].reg;j++){ - hdmi_print(printk_flag, "[%08x]=%08x\n",reg_set[j].reg,aml_read_reg32(CBUS_REG_ADDR(reg_set[j].reg))); - } - hdmi_print(printk_flag, "------------------\n"); - break; - } - } -} - -static void hdmitx_config_tvenc_reg(int vic, unsigned reg, unsigned val) -{ - int i,j; - for(i=0;hdmi_tvenc_configs[i].vic!=HDMI_Unkown;i++){ - if(vic==hdmi_tvenc_configs[i].vic){ - reg_t* reg_set=hdmi_tvenc_configs[i].reg_set; - for(j=0;reg_set[j].reg;j++){ - if(reg_set[j].reg==reg){ - reg_set[j].val = val; - hdmi_print(INF, SYS "set [%08x]=%08x\n",reg_set[j].reg, reg_set[j].val); - break; - } - } - if(reg_set[j].reg == 0){ - hdmi_print(INF, SYS "no [%08x] in config\n", reg); - } - break; - } - } -} - -static void hdmitx_set_pll(Hdmi_tx_video_para_t *param) -{ - hdmi_print(IMP, SYS "set pll\n"); - hdmi_print(IMP, SYS "param->VIC:%d\n", param->VIC); - - cur_vout_index = get_cur_vout_index(); - switch(param->VIC) - { - case HDMI_480p60: - case HDMI_480p60_16x9: - set_vmode_clk(VMODE_480P); - break; - case HDMI_576p50: - case HDMI_576p50_16x9: - set_vmode_clk(VMODE_576P); - break; - case HDMI_480i60: - case HDMI_480i60_16x9: - set_vmode_clk(VMODE_480I); - break; - case HDMI_576i50: - case HDMI_576i50_16x9: - set_vmode_clk(VMODE_576I); - break; - case HDMI_1080p24://1080p24 support - set_vmode_clk(VMODE_1080P_24HZ); - break; - case HDMI_1080p30: - - case HDMI_720p60: - case HDMI_720p50: - set_vmode_clk(VMODE_720P); - break; - case HDMI_1080i60: - case HDMI_1080i50: - set_vmode_clk(VMODE_1080I); - break; - case HDMI_1080p60: - case HDMI_1080p50: - set_vmode_clk(VMODE_1080P); - break; - default: - break; - } -} - -static void hdmitx_set_phy(hdmitx_dev_t* hdmitx_device) -{ - switch(hdmitx_device->cur_video_param->VIC) { - case HDMI_1080p60: - default: - aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08c31e8b); - break; - } -// P_HHI_HDMI_PHY_CNTL1 bit[1]: enable clock bit[0]: soft reset -#define RESET_HDMI_PHY() \ - aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 3); \ - msleep(1); \ - aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 2); \ - msleep(1) - - RESET_HDMI_PHY(); - RESET_HDMI_PHY(); - RESET_HDMI_PHY(); -#undef RESET_HDMI_PHY - hdmi_print(IMP, SYS "phy setting done\n"); -} - -static int hdmitx_set_dispmode(hdmitx_dev_t* hdmitx_device, Hdmi_tx_video_para_t *param) -{ - if(param == NULL){ //disable HDMI - hdmi_tx_gate_pwr_ctrl(VID_DIS, hdmitx_device); - return 0; - } - else if((param->VIC!=HDMI_480p60)&&(param->VIC!=HDMI_480p60_16x9) - &&(param->VIC!=HDMI_576p50)&&(param->VIC!=HDMI_576p50_16x9) - &&(param->VIC!=HDMI_480i60)&&(param->VIC!=HDMI_480i60_16x9) - &&(param->VIC!=HDMI_576i50)&&(param->VIC!=HDMI_576i50_16x9) - &&(param->VIC!=HDMI_1080p30) - &&(param->VIC!=HDMI_1080p24) - &&(param->VIC!=HDMI_1080p60)&&(param->VIC!=HDMI_1080p50) - &&(param->VIC!=HDMI_720p60)&&(param->VIC!=HDMI_720p50) - &&(param->VIC!=HDMI_4k2k_30)&&(param->VIC!=HDMI_4k2k_25)&&(param->VIC!=HDMI_4k2k_24)&&(param->VIC!=HDMI_4k2k_smpte_24) - &&(param->VIC!=HDMI_1080i60)&&(param->VIC!=HDMI_1080i50)){ - return -1; - } - else { - } - if((param->VIC==HDMI_4k2k_30)||(param->VIC==HDMI_4k2k_25)||(param->VIC==HDMI_4k2k_24)||(param->VIC==HDMI_4k2k_smpte_24)) { - hdmi_tx_gate_pwr_ctrl(VID_DIS, hdmitx_device); - printk("Not support HDMI format %d\n", param->VIC); - } - - if(color_depth_f==24) - param->color_depth = COLOR_24BIT; - else if(color_depth_f==30) - param->color_depth = COLOR_30BIT; - else if(color_depth_f==36) - param->color_depth = COLOR_36BIT; - else if(color_depth_f==48) - param->color_depth = COLOR_48BIT; - hdmi_print(INF, SYS " %d (cd%d,cs%d,pm%d,vd%d,%x) \n",param->VIC, color_depth_f, color_space_f,power_mode,power_off_vdac_flag,serial_reg_val); - if(color_space_f != 0){ - param->color = color_space_f; - } - hdmitx_device->cur_VIC = param->VIC; - hdmi_tx_gate_pwr_ctrl(VID_EN, hdmitx_device); - hdmi_hw_reset(hdmitx_device, param); - hdmitx_set_pll(param); - hdmitx_set_phy(hdmitx_device); - - if((param->VIC==HDMI_720p60)||(param->VIC==HDMI_720p50)|| - (param->VIC==HDMI_1080i60)||(param->VIC==HDMI_1080i50)){ - aml_write_reg32(P_ENCP_VIDEO_HAVON_BEGIN, aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN)-1); - aml_write_reg32(P_ENCP_VIDEO_HAVON_END, aml_read_reg32(P_ENCP_VIDEO_HAVON_END)-1); - } - - switch(param->VIC){ - case HDMI_480i60: - case HDMI_480i60_16x9: - case HDMI_576i50: - case HDMI_576i50_16x9: - hdmi_tvenc480i_set(param); - break; - case HDMI_1080i60: - case HDMI_1080i50: - hdmi_tvenc1080i_set(param); - break; - default: - hdmi_tvenc_set(param); - } - hdmitx_dump_tvenc_reg(param->VIC, 0); - -//todo hdmitx_special_handler_video(hdmitx_device); - - // reset TX_SYS5_TX_SOFT_RESET_1/2 twice - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x9f); - mdelay(5); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - mdelay(5); - - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x9f); - mdelay(5); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); - mdelay(5); - - return 0; -} - - -static void hdmitx_set_packet(int type, unsigned char* DB, unsigned char* HB) -{ - // AVI frame - int i ; - unsigned char ucData ; - unsigned int pkt_reg_base=TX_PKT_REG_AVI_INFO_BASE_ADDR; - int pkt_data_len=0; - - switch(type) - { - case HDMI_PACKET_AVI: - pkt_reg_base=TX_PKT_REG_AVI_INFO_BASE_ADDR; - pkt_data_len=13; - break; - case HDMI_PACKET_VEND: - pkt_reg_base=TX_PKT_REG_VEND_INFO_BASE_ADDR; - pkt_data_len=6; - break; - case HDMI_AUDIO_INFO: - pkt_reg_base=TX_PKT_REG_AUDIO_INFO_BASE_ADDR; - pkt_data_len=9; - break; - case HDMI_SOURCE_DESCRIPTION: - pkt_reg_base=TX_PKT_REG_SPD_INFO_BASE_ADDR; - pkt_data_len=25; - default: - break; - } - - if(DB){ - for(i=0;i>8)&0x3) != 0x2 ) { - // if (i > 255) { - // //stimulus_print("[TEST.C] Error: set_hdmi_audio_source timeout!\n"); - // //stimulus_finish_fail(10); - // } - i ++; - if(i>100000) - break; - } - if(i>100000) - hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL\n"); - break; - case 2: - hdmi_print(INF, AUD "I2S out to HDMI\n");//I2S - // Enable HDMI audio clock from the selected source - data32 = 0; - data32 |= 0 << 4; // [5:4] hdmi_data_sel: 00=disable hdmi i2s input; 01=Select pcm data; 10=Select AIU I2S data; 11=Not allowed. - data32 |= 2 << 0; // [1:0] hdmi_clk_sel: 00=Disable hdmi audio clock input; 01=Select pcm clock; 10=Select AIU aoclk; 11=Not allowed. - aml_write_reg32(P_AIU_HDMI_CLK_DATA_CTRL, data32); - - // Wait until clock change is settled - i = 0; - while ( (((aml_read_reg32(P_AIU_HDMI_CLK_DATA_CTRL))>>8)&0x3) != 0x2 ) { - // if (i > 255) { - // //stimulus_print("[TEST.C] Error: set_hdmi_audio_source timeout!\n"); - // //stimulus_finish_fail(10); - // } - i ++; - if(i>100000) - break; - } - if(i>100000) - hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL !\n"); - // Enable HDMI I2S input from the selected source - data32 = 0; - data32 |= 2 << 4; // [5:4] hdmi_data_sel: 00=disable hdmi i2s input; 01=Select pcm data; 10=Select AIU I2S data; 11=Not allowed. - data32 |= 2 << 0; // [1:0] hdmi_clk_sel: 00=Disable hdmi audio clock input; 01=Select pcm clock; 10=Select AIU aoclk; 11=Not allowed. - aml_write_reg32(P_AIU_HDMI_CLK_DATA_CTRL, data32); - - // Wait until data change is settled - i = 0; - while ((((aml_read_reg32(P_AIU_HDMI_CLK_DATA_CTRL))>>12)&0x3) != 0x2 ) { - i++; - if(i>100000) - break; - } - if(i>100000) - hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL...\n"); - break; - default: - hdmi_print(ERR, AUD "Audio Src clock to HDMI Error\n"); - break; - } -} /* set_hdmi_audio_source */ - -static int hdmitx_set_audmode(struct hdmi_tx_dev_s* hdmitx_device, Hdmi_tx_audio_para_t* audio_param) -{ - unsigned int audio_N_para = 6272; - unsigned int audio_N_tolerance = 3; -// unsigned int audio_CTS = 30000; - - hdmi_print(INF, AUD "audio channel num is %d\n", hdmitx_device->cur_audio_param.channel_num); - - hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) & (~(1<<3))); - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x30); // reset audio master & sample - hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); - - if(hdmitx_device->cur_audio_param.channel_num > CC_2CH) { - i2s_to_spdif_flag = 0; - }else{ - i2s_to_spdif_flag = 1; - } - if(!hdmi_audio_off_flag){ - hdmi_audio_init(i2s_to_spdif_flag); - } - else { - hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets - } - -//Refer to HDMI SPEC V1.4 Page 137 - hdmi_print(INF, AUD "current VIC: %d\n", hdmitx_device->cur_VIC); - hdmi_print(INF, AUD "audio sample rate: %d\n", audio_param->sample_rate); - switch(hdmitx_device->cur_VIC) - { - //TMDS Clock:27MHz - case HDMI_480p60: - case HDMI_480p60_16x9: - case HDMI_576p50: - case HDMI_576p50_16x9: - case HDMI_480i60: - case HDMI_480i60_16x9: - case HDMI_576i50: - case HDMI_576i50_16x9: - switch(audio_param->sample_rate) - { - case FS_32K: - audio_N_para = 4096; - break; - case FS_44K1: - audio_N_para = 6272; - break; - case FS_88K2: - audio_N_para = 12544; - break; - case FS_176K4: - audio_N_para = 25088; - break; - case FS_48K: - audio_N_para = 6144; - break; - case FS_96K: - audio_N_para = 12288; - break; - case FS_192K: - audio_N_para = 24576; - break; - default: - break; - } - break; - //TMDS Clock:74.176MHz - case HDMI_720p60: - case HDMI_720p50: - case HDMI_1080i60: - case HDMI_1080i50: - case HDMI_1080p30: - case HDMI_1080p24: - switch(audio_param->sample_rate) - { - case FS_32K: - audio_N_para = 4096; - break; - case FS_44K1: - audio_N_para = 6272; - break; - case FS_88K2: - audio_N_para = 12544; - break; - case FS_176K4: - audio_N_para = 25088; - break; - case FS_48K: - audio_N_para = 6144; - break; - case FS_96K: - audio_N_para = 12288; - break; - case FS_192K: - audio_N_para = 24576; - break; - default: - break; - } - break; - //TMDS Clock:148.5MHz - case HDMI_1080p50: - case HDMI_1080p60: - switch(audio_param->sample_rate) - { - case FS_32K: - audio_N_para = 4096; - break; - case FS_44K1: - audio_N_para = 6272; - break; - case FS_88K2: - audio_N_para = 12544; - break; - case FS_176K4: - audio_N_para = 25088; - break; - case FS_48K: - audio_N_para = 6144; - break; - case FS_96K: - audio_N_para = 12288; - break; - case FS_192K: - audio_N_para = 24576; - break; - default: - break; - } - break; - default: - break; - } - - hdmi_print(INF, AUD "reset audio N para\n"); - switch(audio_param->sample_rate){ - case FS_44K1: - audio_N_para = 6272 * 2; - break; - case FS_48K: - audio_N_para = 6144 * 2; - break; - default: - break; - } - - //TODO. Different audio type, maybe have different settings - switch(audio_param->type){ - case CT_PCM: - break; - case CT_AC_3: - break; - case CT_MPEG1: - break; - case CT_MP3: - break; - case CT_MPEG2: - break; - case CT_AAC: - break; - case CT_DTS: - break; - case CT_ATRAC: - break; - case CT_ONE_BIT_AUDIO: - break; - case CT_DOLBY_D: - audio_N_para *= 4; - break; - case CT_DTS_HD: - audio_N_para *= 4; - break; - case CT_MAT: - break; - case CT_DST: - break; - case CT_WMA: - break; - default: - break; - } - - hdmi_wr_reg(TX_SYS1_ACR_N_0, (audio_N_para&0xff)); // N[7:0] - hdmi_wr_reg(TX_SYS1_ACR_N_1, (audio_N_para>>8)&0xff); // N[15:8] - hdmi_wr_reg(TX_SYS1_ACR_N_2, (audio_N_tolerance<<4)|((audio_N_para>>16)&0xf)); // N[19:16] - hdmi_wr_reg(TX_AUDIO_CONTROL, hdmi_rd_reg(TX_AUDIO_CONTROL)|0x1); - - hdmi_wr_reg(TX_SYS0_ACR_CTS_0, 0); //audio_CTS & 0xff); - hdmi_wr_reg(TX_SYS0_ACR_CTS_1, 0); //(audio_CTS>>8) & 0xff); - hdmi_wr_reg(TX_SYS0_ACR_CTS_2, 1 << 5); // set bit[5] force_arc_stable to 1 - - set_hdmi_audio_source(i2s_to_spdif_flag ? 1 : 2); - - hdmi_print(INF, AUD "i2s_to_spdif_flag:%d \n", i2s_to_spdif_flag); - if(i2s_to_spdif_flag) - enable_audio_spdif(); - else - enable_audio_i2s(); - - if((i2s_to_spdif_flag == 1) && (hdmitx_device->cur_audio_param.type != CT_PCM)) { - hdmi_wr_reg(TX_AUDIO_FORMAT, (hdmi_rd_reg(TX_AUDIO_FORMAT) & 0xfe)); // clear bit0, use channel status bit from input data - } - -//todo hdmitx_special_handler_audio(hdmitx_device); - - return 0; -} - -static void hdmitx_setupirq(hdmitx_dev_t* hdmitx_device) -{ - int r; - r = request_irq(INT_HDMI_TX, &intr_handler, - IRQF_SHARED, "amhdmitx", - (void *)hdmitx_device); -} - - -#if 1 - -//Expect 8*10-Bit shift pattern data: -// -//0x2e3 = 1011100011 -//0x245 = 1001000101 -//0x1cb = 0111001011 -//0x225 = 1000100101 -//0x2da = 1011011010 -//0x3e0 = 1111100000 -//0x367 = 1101100111 -//0x000 = 0000000000 - -static void turn_on_shift_pattern (void) -{ - unsigned int tmp_add_data; - hdmi_wr_reg(TX_SYS0_BIST_DATA_0, 0x00); - hdmi_wr_reg(TX_SYS0_BIST_DATA_1, 0x6c); - hdmi_wr_reg(TX_SYS0_BIST_DATA_2, 0xfe); - hdmi_wr_reg(TX_SYS0_BIST_DATA_3, 0x41); - hdmi_wr_reg(TX_SYS0_BIST_DATA_4, 0x5b); - hdmi_wr_reg(TX_SYS0_BIST_DATA_5, 0x91); - hdmi_wr_reg(TX_SYS0_BIST_DATA_6, 0x3a); - hdmi_wr_reg(TX_SYS0_BIST_DATA_7, 0x9d); - hdmi_wr_reg(TX_SYS0_BIST_DATA_8, 0x68); - hdmi_wr_reg(TX_SYS0_BIST_DATA_9, 0xc7); - - //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] - //tmp_add_data[5] = 1'b0; // external_packet_enable - //tmp_add_data[4] = 1'b1 ; // internal_packet_enable - //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] - //tmp_add_data[1:0] = 2'd3 ; // afe_fifo_source_select_lane_0[1:0] : 0=data path; 1=injected on lane 0; 2=inject on lane 1; 3=BIST. - tmp_add_data = 0x13; - hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); - - hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0x00); // Reset BIST - hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0xc0); // Enable shift pattern BIST -} - -static void turn_off_shift_pattern (void) -{ - unsigned int tmp_add_data; - hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0x00); // Reset BIST - - //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] - //tmp_add_data[5] = 1'b0; // external_packet_enable - //tmp_add_data[4] = 1'b1 ; // internal_packet_enable - //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] - //tmp_add_data[1:0] = 2'd0 ; // afe_fifo_source_select_lane_0[1:0] : 0=data path; 1=injected on lane 0; 2=inject on lane 1; 3=BIST. - tmp_add_data = 0x10; - hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); -} - -static void turn_on_prbs_mode(int prbs_mode) -{ - unsigned int tmp_add_data; - tmp_add_data = 0; - tmp_add_data |= 0 << 6; // [7:6] audio_source_select[1:0] - tmp_add_data |= 0 << 5; // [5] external_packet_enable - tmp_add_data |= 0 << 4; // [4] internal_packet_enable - tmp_add_data |= 0 << 2; // [3:2] afe_fifo_source_select_lane_1[1:0]: 0=DATA_PATH; 1=TMDS_LANE_0; 2=TMDS_LANE_1; 3=BIST_PATTERN - tmp_add_data |= 3 << 0; // [1:0] afe_fifo_source_select_lane_0[1:0]: 0=DATA_PATH; 1=TMDS_LANE_0; 2=TMDS_LANE_1; 3=BIST_PATTERN - hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); // 0x03 - - tmp_add_data = 0; - tmp_add_data |= 0 << 7; // [7] monitor_lane_1 - tmp_add_data |= 0 << 4; // [6:4] monitor_select_lane_1[2:0] - tmp_add_data |= 1 << 3; // [3] monitor_lane_0 - tmp_add_data |= 7 << 0; // [2:0] monitor_select_lane_0[2:0]: 7=TMDS_ENCODE - hdmi_wr_reg(TX_CORE_DATA_MONITOR_1, tmp_add_data); // 0x0f - - // Program PRBS_MODE - hdmi_wr_reg(TX_SYS1_PRBS_DATA, prbs_mode); // 0=PRBS 11; 1=PRBS 15; 2=PRBS 7; 3=PRBS 31. - // Program PRBS BIST - - tmp_add_data = 0; - tmp_add_data |= 1 << 7; // [7] afe_bist_enable - tmp_add_data |= 0 << 6; // [6] tmds_shift_pattern_select - tmp_add_data |= 3 << 4; // [5:4] tmds_prbs_pattern_select[1:0]: - // 0=output all 0; 1=output 8-bit pattern; - // 2=output 1-bit differential pattern; 3=output 10-bit pattern - tmp_add_data |= 0 << 3; // [3] Rsrv - tmp_add_data |= 0 << 0; // [2:0] tmds_repeat_bist_pattern[2:0] - hdmi_wr_reg(TX_SYS0_BIST_CONTROL, tmp_add_data); // 0xb0 - - hdmi_print(INF, SYS "PRBS mode %d On\n", prbs_mode); -} - -#endif - -static void hdmitx_uninit(hdmitx_dev_t* hdmitx_device) -{ - //aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_STAT_CLR); - //aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK)&(~(1 << 25))); - free_irq(INT_HDMI_TX, (void *)hdmitx_device); - hdmi_print(1,"power off hdmi, unmux hpd\n"); - - phy_pll_off(); - digital_clk_off(7); //off sys clk - unmux_hpd(); -} - -static char hdcp_log_buf[HDMITX_HDCP_MONITOR_BUF_SIZE] = { 0 }; -const static hdcp_sub_t hdcp_monitor_array[] = { - {"Aksv_shw", TX_HDCP_SHW_AKSV_0, 5}, - {"Bksv ", TX_HDCP_SHW_BKSV_0, 5}, - {"Ainfo ", TX_HDCP_SHW_AINFO , 1}, - {"An ", TX_HDCP_SHW_AN_0 , 8}, - {"Bcaps ", TX_HDCP_SHW_BCAPS, 1}, - {"Bstatus ", TX_HDCP_SHW_BSTATUS_0, 2}, - {"Km ", 0x148, 7}, - {"Ri ", 0x150, 2}, - {"Ri' ", TX_HDCP_SHW_RI1_0 , 2}, - {"Pj ", 0x14f, 1}, - {"Pj' ", TX_HDCP_SHW_PJ1 , 1}, - {"AuthSt ", TX_HDCP_ST_AUTHENTICATION, 1}, - {"EncrySt0", TX_HDCP_ST_STATUS_0, 1}, - {"EncrySt1", TX_HDCP_ST_STATUS_1, 1}, - {"EncrySt2", TX_HDCP_ST_STATUS_2, 1}, - {"EncrySt3", TX_HDCP_ST_STATUS_3, 1}, - {"FramCnt ", TX_HDCP_ST_FRAME_COUNT, 1}, - {"EDIDStat", TX_HDCP_ST_EDID_STATUS, 1}, - {"MEMStat ", TX_HDCP_ST_MEM_STATUS, 1}, - {"EDID_Ext", 0x198, 1}, - {"EDDC_SEG", 0x199, 1}, - {"EDDC_ST ", 0x19a, 1}, - {"HDCP_RSV", 0x19b, 4}, - {"EDDC_SEG", 0x19c, 1}, - {"HDCPMODE", TX_HDCP_ST_ST_MODE, 1}, - {"TmdsMod ", TX_TMDS_MODE, 1}, -}; - -static int hdmitx_cntl(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) -{ - if(cmd == HDMITX_AVMUTE_CNTL) { - if(argv == AVMUTE_SET) { - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<4))); - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)|(1<<5)); - } - if(argv == AVMUTE_CLEAR) { - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<5))); - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)|(1<<4)); - } - if(argv == AVMUTE_OFF) { - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<4))); - hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<5))); - } - return 0; - } - else if(cmd == HDMITX_SW_INTERNAL_HPD_TRIG){ - if(argv == 1) // soft trig rising - hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT, 1); - else // soft trig falling - hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT, 2); - } - else if(cmd == HDMITX_EARLY_SUSPEND_RESUME_CNTL) { - if(argv == HDMITX_EARLY_SUSPEND) { - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 30, 1); - hdmi_phy_suspend(); - } - if(argv == HDMITX_LATE_RESUME) { - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 30, 1); - //hdmi_phy_wakeup(); // no need - } - return 0; - } - else if(cmd == HDMITX_HDCP_MONITOR) { - int i, len, st; - int array = sizeof(hdcp_monitor_array) / sizeof(hdcp_sub_t); - - int pos; - - if(!(hdmitx_device->log & HDMI_LOG_HDCP)) - return 0; - - memset(hdcp_log_buf, 0, HDMITX_HDCP_MONITOR_BUF_SIZE); - hdmi_print(INF, HDCP "\n\nMonitor HDCP start\n"); - pos = 0; - for(i = 0; i < array; i ++){ - len = hdcp_monitor_array[i].hdcp_sub_len; - st = hdcp_monitor_array[i].hdcp_sub_addr_start; - pos += sprintf(hdcp_log_buf + pos, " %s: ", hdcp_monitor_array[i].hdcp_sub_name); - do { - pos += sprintf(hdcp_log_buf + pos, "%02x", (unsigned)hdmi_rd_reg(st+len-1)); - }while(--len); - pos += sprintf(hdcp_log_buf + pos, "\n"); - } - pos += sprintf(hdcp_log_buf + pos, "HDCP %s", - ((hdmi_rd_reg(TX_HDCP_ST_STATUS_3)&0xa0)==0xa0) - ? "OK\n" : "BAD\n" - ); - printk("%s", hdcp_log_buf); - hdmi_print(INF, HDCP "Monitor HDCP end\n"); - return 0; - } - else if(cmd == HDMITX_IP_SW_RST){ - return 0; //TODO - aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16)); - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0) | (argv)); - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0) & (~(argv))); - aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16))); - hdmi_print(INF, SYS "reset IP: 0x%x\n", argv); - return 0; - } - else if(cmd == HDMITX_CBUS_RST) { - return 0;//todo - aml_set_reg32_bits(P_RESET2_REGISTER, 1, 15, 1); - msleep(50); - hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT_CLR, 0x7); - return 0; - } - else if(cmd == HDMITX_INTR_MASKN_CNTL) { - if(argv == INTR_MASKN_ENABLE) { - hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_MASKN, 0); - } - if(argv == INTR_MASKN_DISABLE) { - hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_MASKN, 0x7); - } - if(argv == INTR_CLEAR) { - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0x7); - } - return 0; - } - else if(cmd == HDMITX_IP_INTR_MASN_RST){ - hdmi_print(INF, SYS "reset intr mask\n"); - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0); - msleep(2); - hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0x7); - } - else if(cmd == HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH){ - /* turnon digital module if gpio is high */ - if(is_hpd_muxed() == 0){ - if(read_hpd_gpio()){ - hdmitx_device->internal_mode_change = 0; - msleep(500); - if(read_hpd_gpio()){ - hdmi_print(IMP, HPD "mux hpd\n"); - digital_clk_on(4); - delay_us(1000*100); - mux_hpd(); - } - } - } - } - else if(cmd == HDMITX_HWCMD_MUX_HPD){ - mux_hpd(); - } -// For test only. - else if(cmd == HDMITX_HWCMD_TURNOFF_HDMIHW){ - int unmux_hpd_flag = argv; -// WRITE_MPEG_REG(VENC_DVI_SETTING, READ_MPEG_REG(VENC_DVI_SETTING)&(~(1<<13))); //bit 13 is used by HDMI only -// digital_clk_on(4); //enable sys clk so that hdmi registers can be accessed when calling phy_pll_off/digit_clk_off - if(unmux_hpd_flag){ - hdmi_print(IMP, SYS "power off hdmi, unmux hpd\n"); - phy_pll_off(); - digital_clk_off(4); //off sys clk - unmux_hpd(); - } - else{ - hdmi_print(IMP, SYS "power off hdmi\n"); - digital_clk_on(6); - phy_pll_off(); //should call digital_clk_on(), otherwise hdmi_rd/wr_reg will hungup - digital_clk_off(3); //do not off sys clk - } -#ifdef CONFIG_HDMI_TX_PHY - digital_clk_off(7); -#endif - } - else if(cmd == HDMITX_HWCMD_TURN_ON_PRBS){ - turn_on_prbs_mode(argv); - } - return 0; -} - -static void hdmitx_print_info(hdmitx_dev_t* hdmitx_device, int printk_flag) -{ - hdmi_print(INF, "------------------\nHdmitx driver version: %s\nSerial %x\nColor Depth %d\n", HDMITX_VER, serial_reg_val, color_depth_f); - hdmi_print(INF, "current vout index %d\n", cur_vout_index); - hdmi_print(INF, "reset sequence %d\n", new_reset_sequence_flag); - hdmi_print(INF, "power mode %d\n", power_mode); - hdmi_print(INF, "%spowerdown when unplug\n",hdmitx_device->unplug_powerdown?"":"do not "); - hdmi_print(INF, "use_tvenc_conf_flag=%d\n",use_tvenc_conf_flag); - hdmi_print(INF, "vdac %s\n", power_off_vdac_flag?"off":"on"); - hdmi_print(INF, "hdmi audio %s\n", hdmi_audio_off_flag?"off":"on"); - if(!hdmi_audio_off_flag){ - hdmi_print(INF, "audio out type %s\n", i2s_to_spdif_flag?"spdif":"i2s"); - } - hdmi_print(INF, "delay flag %d\n", delay_flag); - hdmi_print(INF, "------------------\n"); -} - -static void hdmitx_debug(hdmitx_dev_t* hdmitx_device, const char* buf) -{ - char tmpbuf[128]; - int i=0; - unsigned int adr; - unsigned int value=0; - while((buf[i])&&(buf[i]!=',')&&(buf[i]!=' ')){ - tmpbuf[i]=buf[i]; - i++; - } - tmpbuf[i]=0; - if((strncmp(tmpbuf, "dumpreg", 7)==0) || (strncmp(tmpbuf, "dumptvencreg", 12)==0)){ - hdmitx_dump_tvenc_reg(hdmitx_device->cur_VIC, 1); - return; - } - else if(strncmp(tmpbuf, "ss", 2) == 0) { - printk("hdmitx_device->output_blank_flag: 0x%x\n", hdmitx_device->output_blank_flag); - printk("hdmitx_device->hpd_state: 0x%x\n", hdmitx_device->hpd_state); - printk("hdmitx_device->cur_VIC: 0x%x\n", hdmitx_device->cur_VIC); - } - else if(strncmp(tmpbuf, "hpd_lock", 8) == 0) { - if(tmpbuf[8] == '1') { - hdmitx_device->hpd_lock = 1; - hdmi_print(INF, HPD "hdmitx: lock hpd\n"); - } - else { - hdmitx_device->hpd_lock = 0; - hdmi_print(INF, HPD "hdmitx: unlock hpd\n"); - } - return ; - } - else if(strncmp(tmpbuf, "vic", 3)==0) { - printk("hdmi vic count = %d\n", hdmitx_device->vic_count); - if((tmpbuf[3] >= '0') && (tmpbuf[3] <= '9')){ - hdmitx_device->vic_count = tmpbuf[3] - '0'; - hdmi_print(INF, SYS "set hdmi vic count = %d\n", hdmitx_device->vic_count); - } - } - else if(strncmp(tmpbuf, "cec", 3)==0) { - extern void cec_test_(unsigned int cmd); - cec_test_(tmpbuf[3] - '0'); - } - else if(strncmp(tmpbuf, "dumphdmireg", 11)==0){ - unsigned char reg_val = 0; - unsigned int reg_adr = 0; - for (reg_adr = 0; reg_adr < 0x800; reg_adr ++){ //HDMI Regs address range: 0 ~ 0x7ff - reg_val = hdmi_rd_reg(reg_adr); - hdmi_print(INF, "HDMI[0x%x]: 0x%x\n", reg_adr, reg_val); - } - return ; - } - else if(strncmp(tmpbuf, "dumpcecreg",10) == 0){ - unsigned char cec_val = 0; - unsigned int cec_adr =0; - //HDMI CEC Regs address range:0xc000~0xc01c;0xc080~0xc094 - for(cec_adr = 0xc000; cec_adr < 0xc01d; cec_adr ++){ - cec_val = hdmi_rd_reg(cec_adr); - hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n",cec_adr,cec_val); - } - for(cec_adr = 0xc080; cec_adr < 0xc095; cec_adr ++){ - cec_val = hdmi_rd_reg(cec_adr); - hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n",cec_adr,cec_val); - } - return; - } - else if(strncmp(tmpbuf, "dumpcbusreg", 11)==0){ - unsigned j; - adr=simple_strtoul(tmpbuf+11, NULL, 16); //CBUS Start addr - value=simple_strtoul(buf+i+1, NULL, 16); //CBUS End addr - for(j = 0 ; j < value-adr+1 ; j++){ -// printk("CBUS[0x%x]: 0x%x\n", adr+j, READ_MPEG_REG(adr+j)); - hdmi_print(INF, "CBUS[0x%x]: 0x%x\n", adr+j, aml_read_reg32(CBUS_REG_ADDR(adr+j))); - - } - } - else if(strncmp(tmpbuf, "log", 3)==0){ - if(strncmp(tmpbuf+3, "hdcp", 4)==0){ - static unsigned int i = 1; - if(i & 1){ - hdmitx_device->log |= HDMI_LOG_HDCP; - } - else{ - hdmitx_device->log &= ~HDMI_LOG_HDCP; - } - i ++; - } - return ; - } - else if(strncmp(tmpbuf, "pllcalc", 7)==0){ - clk_measure(0xff); - return; - } - else if(strncmp(tmpbuf, "hdmiaudio", 9)==0){ - value=simple_strtoul(tmpbuf+9, NULL, 16); - if(value == 1){ - hdmi_audio_off_flag = 0; - hdmi_audio_init(i2s_to_spdif_flag); - } - else if(value == 0){ - hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets - } - return; - } - else if(strncmp(tmpbuf, "cfgreg", 6)==0){ - adr=simple_strtoul(tmpbuf+6, NULL, 16); - value=simple_strtoul(buf+i+1, NULL, 16); - hdmitx_config_tvenc_reg(hdmitx_device->cur_VIC, adr, value); - return; - } - else if(strncmp(tmpbuf, "tvenc_flag", 10)==0){ - use_tvenc_conf_flag = tmpbuf[10]-'0'; - hdmi_print(INF, "set use_tvenc_conf_flag = %d\n", use_tvenc_conf_flag); - } - else if(strncmp(tmpbuf, "reset", 5)==0){ - if(tmpbuf[5]=='0') - new_reset_sequence_flag=0; - else - new_reset_sequence_flag=1; - return; - } - else if(strncmp(tmpbuf, "delay_flag", 10)==0){ - delay_flag = tmpbuf[10]-'0'; - } - else if(tmpbuf[0]=='v'){ - hdmitx_print_info(hdmitx_device, 1); - return; - } - else if(tmpbuf[0]=='s'){ - serial_reg_val=simple_strtoul(tmpbuf+1,NULL,16); - return; - } - else if(tmpbuf[0]=='c'){ - if(tmpbuf[1]=='d'){ - color_depth_f=simple_strtoul(tmpbuf+2,NULL,10); - if((color_depth_f!=24)&&(color_depth_f!=30)&&(color_depth_f!=36)){ - printk("Color depth %d is not supported\n", color_depth_f); - color_depth_f=0; - } - return; - } - else if(tmpbuf[1]=='s'){ - color_space_f=simple_strtoul(tmpbuf+2,NULL,10); - if(color_space_f>2){ - printk("Color space %d is not supported\n", color_space_f); - color_space_f=0; - } - } - } - else if(strncmp(tmpbuf,"i2s",2)==0){ - if(strncmp(tmpbuf+3,"off",3)==0) - i2s_to_spdif_flag=1; - else - i2s_to_spdif_flag=0; - } - else if(strncmp(tmpbuf, "pattern_on", 10)==0){ - turn_on_shift_pattern(); - hdmi_print(INF, "Shift Pattern On\n"); - return; - } - else if(strncmp(tmpbuf, "pattern_off", 11)==0){ - turn_off_shift_pattern(); - hdmi_print(INF, "Shift Pattern Off\n"); - return; - } - else if(strncmp(tmpbuf, "prbs", 4)==0){ - int prbs_mode =simple_strtoul(tmpbuf+4, NULL, 10); - turn_on_prbs_mode(prbs_mode); - return; - } - else if(tmpbuf[0]=='w'){ - unsigned read_back = 0; - adr=simple_strtoul(tmpbuf+2, NULL, 16); - value=simple_strtoul(buf+i+1, NULL, 16); - if(buf[1]=='h'){ - hdmi_wr_reg(adr, value); - read_back = hdmi_rd_reg(adr); - } - else if(buf[1]=='c'){ - aml_write_reg32(CBUS_REG_ADDR(adr), value); - read_back = aml_read_reg32(CBUS_REG_ADDR(adr)); - - } - else if(buf[1]=='p'){ - aml_write_reg32(APB_REG_ADDR(adr), value); - read_back = aml_read_reg32(APB_REG_ADDR(adr)); - } - hdmi_print(INF, "write %x to %s reg[%x]\n",value,buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr); - //Add read back function in order to judge writting is OK or NG. - hdmi_print(INF, "Read Back %s reg[%x]=%x\n",buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr, read_back); - } - else if(tmpbuf[0]=='r'){ - adr=simple_strtoul(tmpbuf+2, NULL, 16); - if(buf[1]=='h'){ - value = hdmi_rd_reg(adr); - - } - else if(buf[1]=='c'){ - value = aml_read_reg32(CBUS_REG_ADDR(adr)); - } - else if(buf[1]=='p'){ - value = aml_read_reg32(APB_REG_ADDR(adr)); - } - hdmi_print(INF, "%s reg[%x]=%x\n",buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr, value); - } -} - -static void hdmitx_getediddata(hdmitx_dev_t* hdmitx_device, unsigned int blk_idx) -{ - int ii, jj; - -#ifdef CONFIG_PANEL_IT6681 - hdmitx_device->cur_edid_block = 0; - it6681_read_edid(0, &hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128], 256); - hdmitx_device->cur_edid_block += 2; - printk("%s: get edid from MHL buffer(cur_edid_block=%d)\n", __func__, hdmitx_device->cur_edid_block); -#else - if((hdmitx_device->cur_edid_block+2)<=EDID_MAX_BLOCK){ - if(blk_idx == 0) { - for(jj=0;jj<2;jj++){ - for(ii=0;ii<128;ii++){ - hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128+ii] - =hdmi_rd_reg(TX_RX_EDID_OFFSET+hdmitx_device->cur_phy_block_ptr*128+ii); - } - hdmitx_device->cur_edid_block++; - hdmitx_device->cur_phy_block_ptr++; - hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; - } - } - else { - for(jj=0;jj<2;jj++){ - for(ii=0;ii<128;ii++){ - hdmitx_device->EDID_buf1[hdmitx_device->cur_edid_block*128+ii] - =hdmi_rd_reg(TX_RX_EDID_OFFSET+hdmitx_device->cur_phy_block_ptr*128+ii); - } - hdmitx_device->cur_edid_block++; - hdmitx_device->cur_phy_block_ptr++; - hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; - } - } - } -#endif -} - -static int hdmitx_cntl_ddc(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) -{ - int i = 0; - unsigned char *tmp_char = NULL; - - if(!(cmd & CMD_DDC_OFFSET)) - hdmi_print(ERR, "ddc: " "w: invalid cmd 0x%x\n", cmd); - else - hdmi_print(LOW, "ddc: " "cmd 0x%x\n", cmd); - - switch(cmd) { - case DDC_RESET_EDID: - hdmi_tx_gate_pwr_ctrl(EDID_EN, NULL); - hdmi_set_reg_bits(TX_HDCP_EDID_CONFIG, 0, 6, 1); - hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 1, 1, 1); - hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 0, 1, 1); - break; - case DDC_IS_EDID_DATA_READY: - return !!(hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) & (1<<4)); - break; - case DDC_EDID_READ_DATA: - hdmi_set_reg_bits(TX_HDCP_EDID_CONFIG, 1, 6, 1); // Assert sys_trigger_config - break; - case DDC_EDID_GET_DATA: - hdmitx_getediddata(hdmitx_device, argv); - hdmi_tx_gate_pwr_ctrl(EDID_DIS, NULL); - break; - case DDC_PIN_MUX_OP: - if(argv == PIN_MUX) { - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x3, 24, 2); // Mux HDMI SDA(5v)/SCL(5V) - } - if(argv == PIN_UNMUX) { - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x0, 24, 2); // unMux HDMI SDA(5v)/SCL(5V) - } - break; - case DDC_EDID_CLEAR_RAM: - for(i = 0; i < EDID_RAM_ADDR_SIZE; i++) { - hdmi_wr_reg(TX_RX_EDID_OFFSET + i, 0); - } - break; - case DDC_RESET_HDCP: - hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 1, 2, 1); - hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 0, 2, 1); - break; - case DDC_HDCP_OP: - if(argv == HDCP_ON) { - hdmi_tx_gate_pwr_ctrl(HDCP_EN, NULL); - hdmi_set_reg_bits(TX_HDCP_MODE, 1, 7, 1); - } - if(argv == HDCP_OFF) { - hdmi_tx_gate_pwr_ctrl(HDCP_DIS, NULL); - hdmi_set_reg_bits(TX_HDCP_MODE, 0, 7, 1); - } - break; - case DDC_IS_HDCP_ON: - argv = !!((hdmi_rd_reg(TX_HDCP_MODE)) & (1 << 7)); - break; - case DDC_HDCP_GET_AKSV: - tmp_char = (unsigned char *) argv; - for(i = 0; i < 5; i++) { - tmp_char[i] = (unsigned char)hdmi_rd_reg(TX_HDCP_AKSV_SHADOW + 4 - i); - } - break; - case DDC_HDCP_GET_BKSV: - tmp_char = (unsigned char *) argv; - for(i = 0; i < 5; i++) { - tmp_char[i] = (unsigned char)hdmi_rd_reg(TX_HDCP_BKSV_SHADOW + 4 - i); - } - break; - case DDC_HDCP_GET_AUTH: - if((hdmi_rd_reg(TX_HDCP_ST_STATUS_3)&0xa0)==0xa0) { - return 1; - } - else { - return 0; - } - break; - default: - hdmi_print(INF, "ddc: " "unknown cmd: 0x%x\n", cmd); - } - return 1; -} - -// clear hdmi packet configure registers -static void hdmitx_clr_sub_packet(unsigned int reg_base) -{ - int i = 0; - for(i = 0; i < 0x20; i++) { - hdmi_wr_reg(reg_base + i, 0x00); - } -} - -static int hdmitx_cntl_config(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) -{ - if(!(cmd & CMD_CONF_OFFSET)) - hdmi_print(ERR, "config: " "hdmitx: w: invalid cmd 0x%x\n", cmd); - else - hdmi_print(LOW, "config: " "hdmitx: conf cmd 0x%x\n", cmd); - - switch(cmd) { - case CONF_HDMI_DVI_MODE: - if(argv == HDMI_MODE) { - hdmi_set_reg_bits(TX_TMDS_MODE, 0x3, 6, 2); - } - if(argv == DVI_MODE) { - hdmi_set_reg_bits(TX_VIDEO_DTV_OPTION_L, 0x0, 6, 2); - hdmi_set_reg_bits(TX_TMDS_MODE, 0x2, 6, 2); - } - break; - case CONF_SYSTEM_ST: - return (hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) >> 6); - break; - case CONF_AUDIO_MUTE_OP: - if(argv == AUDIO_MUTE) { - hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets - //hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | (1<<3)); - } - if((argv == AUDIO_UNMUTE) && (hdmitx_device->tx_aud_cfg != 0)) { - hdmi_wr_reg(TX_AUDIO_PACK, 0x01); - //hdmitx_device->audio_param_update_flag = 1; - } - break; - case CONF_VIDEO_BLANK_OP: - if(argv == VIDEO_BLANK) { - aml_write_reg32(P_VPU_HDMI_DATA_OVR, (0x200 << 20) | (0x0 << 10) | (0x200 << 0)); // set blank CrYCb as 0x200 0x0 0x200 - aml_set_reg32_bits(P_VPU_HDMI_SETTING, 0, 5, 3); // Output data map: CrYCb - aml_set_reg32_bits(P_VPU_HDMI_DATA_OVR, 1, 31, 1); // Enable HDMI data override - } - if(argv == VIDEO_UNBLANK) { - aml_write_reg32(P_VPU_HDMI_DATA_OVR, 0); // Disable HDMI data override - } - break; - case CONF_CLR_AVI_PACKET: - hdmitx_clr_sub_packet(TX_PKT_REG_AVI_INFO_BASE_ADDR); - break; - case CONF_CLR_VSDB_PACKET: - hdmitx_clr_sub_packet(TX_PKT_REG_VEND_INFO_BASE_ADDR); - break; - case CONF_CLR_AUDINFO_PACKET: - hdmitx_clr_sub_packet(TX_PKT_REG_AUDIO_INFO_BASE_ADDR); - break; - default: - hdmi_print(ERR, "config: ""hdmitx: unknown cmd: 0x%x\n", cmd); - } - return 1; -} - -static int hdmitx_cntl_misc(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) -{ - if(!(cmd & CMD_MISC_OFFSET)) - hdmi_print(ERR, "misc: " "hdmitx: w: invalid cmd 0x%x\n", cmd); - else - hdmi_print(LOW, "misc: " "hdmitx: misc cmd 0x%x\n", cmd); - - switch(cmd) { - case MISC_HPD_MUX_OP: - if(argv == PIN_MUX) { - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x1, 26, 1); // Mux HPD - } - if(argv == PIN_UNMUX) { - aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x0, 26, 1); // unMux HPD - } - break; - case MISC_HPD_GPI_ST: - return read_hpd_gpio(); - break; - case MISC_HPLL_OP: - if(argv == HPLL_ENABLE) { - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 30, 1); // disable hpll - } - if(argv == HPLL_DISABLE) { - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 30, 1); // disable hpll - } - break; - case MISC_TMDS_PHY_OP: - if(argv == TMDS_PHY_ENABLE) { - hdmi_phy_wakeup(hdmitx_device); // TODO - } - if(argv == TMDS_PHY_DISABLE) { - hdmi_phy_suspend(); - } - break; - case MISC_VIID_IS_USING: - return !!(aml_read_reg32(P_HHI_VID2_PLL_CNTL) & (1 << 30)); // bit30: enable - break; - default: - hdmi_print(ERR, "misc: " "hdmitx: unknown cmd: 0x%x\n", cmd); - } - return 1; -} - -static int hdmitx_get_state(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) -{ - int st = 0; - if(!(cmd & CMD_STAT_OFFSET)) - hdmi_print(ERR, "stat: " "hdmitx: w: invalid cmd 0x%x\n", cmd); - else - hdmi_print(LOW, "stat: " "hdmitx: misc cmd 0x%x\n", cmd); - - switch(cmd) { - case STAT_VIDEO_VIC: - { - /* - * get current video vic directly from VIC packet or VSDB packet - */ - HDMI_Video_Codes_t vic = HDMI_Unkown; - vic = (HDMI_Video_Codes_t)hdmi_rd_reg(TX_PKT_REG_AVI_INFO_BASE_ADDR + 4); - return (int)vic; - } - break; - case STAT_VIDEO_CLK: - break; - case STAT_AUDIO_PACK: - st = (hdmi_rd_reg(STAT_AUDIO_PACK) & 0x1); - return st; - break; - default: - break; - } - return st; -} - -void HDMITX_Meson_Init(hdmitx_dev_t* hdmitx_device) -{ - hdmitx_device->HWOp.SetPacket = hdmitx_set_packet; - hdmitx_device->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; - hdmitx_device->HWOp.SetDispMode = hdmitx_set_dispmode; - hdmitx_device->HWOp.SetAudMode = hdmitx_set_audmode; - hdmitx_device->HWOp.SetupIRQ = hdmitx_setupirq; - hdmitx_device->HWOp.DebugFun = hdmitx_debug; - hdmitx_device->HWOp.UnInit = hdmitx_uninit; - hdmitx_device->HWOp.Cntl = hdmitx_cntl; // todo - hdmitx_device->HWOp.CntlDDC = hdmitx_cntl_ddc; - hdmitx_device->HWOp.GetState = hdmitx_get_state; - hdmitx_device->HWOp.CntlPacket = hdmitx_cntl; - hdmitx_device->HWOp.CntlConfig = hdmitx_cntl_config; - hdmitx_device->HWOp.CntlMisc = hdmitx_cntl_misc; - // 1=Map data pins from Venc to Hdmi Tx as RGB mode. - // -------------------------------------------------------- - // Configure HDMI TX analog, and use HDMI PLL to generate TMDS clock - // -------------------------------------------------------- - // Enable APB3 fail on error -// WRITE_APB_REG(HDMI_CNTL_PORT, READ_APB_REG(HDMI_CNTL_PORT)|(1<<15)); //APB3 err_en -//\\ TODO - //aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 16, 1); // Disable GPIOH_0 internal pull-up register - //aml_write_reg32(P_HHI_HDMI_CLK_CNTL, aml_read_reg32(P_HHI_HDMI_CLK_CNTL)| (1 << 8)); - //aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<15)); //APB3 err_en -// hdmi_wr_reg(0x10, 0xff); - - /**/ - hdmi_hw_init(hdmitx_device); -} - -void hdmi_set_audio_para(int para) -{ - aud_para = para; - -} - -// The following two functions should move to -// static struct platform_driver amhdmitx_driver.suspend & .wakeup -// For tempelet use only. -// Later will change it. -typedef struct -{ - unsigned long reg; - unsigned long val_sleep; - unsigned long val_save; -}hdmi_phy_t; - -static unsigned int hdmi_phy_save = 0x08930e9b; // Default setting - -static void hdmi_phy_suspend(void) -{ - hdmi_phy_save = aml_read_reg32(P_HHI_HDMI_PHY_CNTL0); - aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08418d00); - //hdmi_print(INF, SYS "phy suspend\n"); -} - -static void hdmi_phy_wakeup(hdmitx_dev_t* hdmitx_device) -{ - hdmitx_set_phy(hdmitx_device); - //hdmi_print(INF, SYS "phy wakeup\n"); -} +/* + * Amlogic Meson HDMI Transmitter Driver + * Copyright (C) 2010 Amlogic, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PANEL_IT6681 +#include +#endif +#include +#include +#include + +#if 0 //todo +#include "../hdmi_tx_hdcp.h" +#include "../hdmi_tx_compliance.h" +#endif +#include +#include "tvenc_conf.h" +#ifdef Wr +#undef Wr +#endif +#ifdef Rd +#undef Rd +#endif +#define Wr(reg,val) WRITE_MPEG_REG(reg,val) +#define Rd(reg) READ_MPEG_REG(reg) +#define Wr_reg_bits(reg, val, start, len) \ + Wr(reg, (Rd(reg) & ~(((1L<<(len))-1)<<(start)))|((unsigned int)(val) << (start))) + +#define EDID_RAM_ADDR_SIZE (4*128) + +static void hdmi_audio_init(unsigned char spdif_flag); +static void hdmitx_dump_tvenc_reg(int cur_VIC, int printk_flag); + +static void hdmi_phy_suspend(void); +static void hdmi_phy_wakeup(hdmitx_dev_t* hdmitx_device); + +unsigned char hdmi_pll_mode = 0; /* 1, use external clk as hdmi pll source */ +static unsigned char aud_para = 0x49; + +#define HSYNC_POLARITY 1 // HSYNC polarity: active high +#define VSYNC_POLARITY 1 // VSYNC polarity: active high +#define TX_INPUT_COLOR_DEPTH 0 // Pixel bit width: 0=24-bit; 1=30-bit; 2=36-bit; 3=48-bit. +#define TX_INPUT_COLOR_FORMAT 1 // Pixel format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. +#define TX_INPUT_COLOR_RANGE 0 // Pixel range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. + + +#define TX_OUTPUT_COLOR_RANGE 0 // Pixel range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. + +#if 1 +//spdif +#define TX_I2S_SPDIF 0 // 0=SPDIF; 1=I2S. +#define TX_I2S_8_CHANNEL 0 // 0=I2S 2-channel; 1=I2S 4 x 2-channel. +#else +//i2s 8 channel +#define TX_I2S_SPDIF 1 // 0=SPDIF; 1=I2S. +#define TX_I2S_8_CHANNEL 1 // 0=I2S 2-channel; 1=I2S 4 x 2-channel. +#endif + +//static struct tasklet_struct EDID_tasklet; +static unsigned delay_flag = 0; +static unsigned serial_reg_val=0x1; //0x22; +static unsigned char i2s_to_spdif_flag=1; // if current channel number is larger than 2ch, using i2s +static unsigned color_depth_f=0; +static unsigned color_space_f=0; +static unsigned char new_reset_sequence_flag=1; +static unsigned char power_mode=1; +static unsigned char power_off_vdac_flag=0; + /* 0, do not use fixed tvenc val for all mode; 1, use fixed tvenc val mode for 480i; 2, use fixed tvenc val mode for all modes */ +static unsigned char use_tvenc_conf_flag=1; + +static unsigned char cur_vout_index = 1; //CONFIG_AM_TV_OUTPUT2 + +static void hdmi_tx_mode_ctrl(HDMI_Video_Codes_t vic) +{ + switch(vic) { + // Interlaced Mode + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + CLK_GATE_ON(CTS_ENCI); + CLK_GATE_ON(VCLK2_VENCI1); + CLK_GATE_OFF(CTS_ENCP); + CLK_GATE_ON(CTS_HDMI_TX_PIXEL); + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 15, 1); + break; + case HDMI_Unkown: + CLK_GATE_OFF(CTS_ENCP); + CLK_GATE_OFF(CTS_HDMI_TX_PIXEL); + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 15, 1); + break; + // Progressive Mode + default: + CLK_GATE_OFF(CTS_ENCI); + CLK_GATE_ON(CTS_ENCP); + CLK_GATE_ON(CTS_HDMI_TX_PIXEL); + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 15, 1); + break; + } +} + +static void hdmi_tx_gate_pwr_ctrl(enum hd_ctrl cmd, void * data) +{ + hdmi_print(IMP, SYS "gate/pwr cmd: %d\n", cmd); + switch(cmd) { + case VID_EN: + { + hdmitx_dev_t* hdmitx_device = (hdmitx_dev_t *)data; + hdmi_tx_mode_ctrl(hdmitx_device->cur_VIC); + } + break; + case VID_DIS: + hdmi_tx_mode_ctrl(HDMI_Unkown); + break; + case AUD_EN: + if(i2s_to_spdif_flag == 1) { + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 13, 1); + } + else { + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 1, 13, 1); + } + aml_set_reg32_bits(P_AIU_HDMI_CLK_DATA_CTRL, 2, 0, 2); + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 10, 2); + break; + case AUD_DIS: + hdmi_set_reg_bits(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, 0, 13, 1); + aml_set_reg32_bits(P_AIU_HDMI_CLK_DATA_CTRL, 0, 0, 2); + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 10, 2); + break; + case EDID_EN: + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 8, 2); + break; + case EDID_DIS: + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 8, 2); + break; + case HDCP_EN: + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0, 12, 2); + break; + case HDCP_DIS: + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 3, 12, 2); + break; + } +} + +static unsigned long modulo(unsigned long a, unsigned long b) +{ + if (a >= b) { + return(a-b); + } else { + return(a); + } +} + +static signed int to_signed(unsigned int a) +{ + if (a <= 7) { + return(a); + } else { + return(a-16); + } +} + +static void delay_us (int us) +{ + //udelay(us); + if(delay_flag&0x1) + mdelay((us+999)/1000); + else + udelay(us); +} /* delay_us */ + +static irqreturn_t intr_handler(int irq, void *dev_instance) +{ + unsigned int data32; + hdmitx_dev_t* hdmitx_device = (hdmitx_dev_t*)dev_instance; + data32 = hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT); + hdmi_print(IMP, SYS "irq %x\n", data32); + if(hdmitx_device->hpd_lock == 1) { + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0xf); + hdmi_print(IMP, HPD "HDMI hpd locked\n"); + return IRQ_HANDLED; + } + if(hdmitx_device->internal_mode_change == 1){ // if the irq from the internal mode change, just do nothing and return + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0x7); + hdmi_print(IMP, SYS "hdmitx: ignore irq\n"); + return IRQ_HANDLED; + } + + WRITE_MPEG_REG(HHI_GCLK_MPEG2, READ_MPEG_REG(HHI_GCLK_MPEG2) | (1<<4)); //Enable HDMI PCLK + + if (data32 & (1 << 1)) { //HPD falling + hdmitx_device->vic_count = 0; + hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 1); //clear HPD falling interrupt in hdmi module + hdmitx_device->hpd_event = 2; + } + if (data32 & (1 << 0)) { //HPD rising + hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 0); //clear HPD rising interrupt in hdmi module + // If HPD asserts, then start DDC transaction + if (hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) & (1<<1)) { + // Start DDC transaction + hdmitx_device->cur_edid_block=0; + hdmitx_device->cur_phy_block_ptr=0; + hdmitx_device->hpd_event = 1; + // Error if HPD deasserts + } else { + hdmi_print(ERR, HPD "HPD deasserts!\n"); + } + } + if (data32 & (1 << 2)) { //TX EDID interrupt + if((hdmitx_device->cur_edid_block+2)<=EDID_MAX_BLOCK){ + int ii, jj; + for(jj=0;jj<2;jj++){ + for(ii=0;ii<128;ii++){ + hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128+ii] + =hdmi_rd_reg(0x600+hdmitx_device->cur_phy_block_ptr*128+ii); + } + hdmitx_device->cur_edid_block++; + hdmitx_device->cur_phy_block_ptr++; + hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; + } + } +//#ifndef AML_A3 +// /*walkaround: manually clear EDID interrupt*/ +// hdmi_wr_reg(TX_HDCP_EDID_CONFIG, hdmi_rd_reg(TX_HDCP_EDID_CONFIG) | (1<<1)); +// hdmi_wr_reg(TX_HDCP_EDID_CONFIG, hdmi_rd_reg(TX_HDCP_EDID_CONFIG) & ~(1<<1)); +// /**/ +//#endif + //tasklet_schedule(&EDID_tasklet); + hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 1 << 2); //clear EDID rising interrupt in hdmi module + } + if (!((data32 == 1) || (data32 == 2) || (data32 == 4))) { + hdmi_print(ERR, SYS "Unkown HDMI Interrupt Source\n"); + hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, data32); //clear unkown interrupt in hdmi module + } +//#ifdef AML_A3 + hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR); // A read to allow the interrupt cleared in hdmi_module before next action + hdmi_wr_only_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0xf); //clear HPD falling interrupt in hdmi module +//#endif + + //aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_STAT_CLR, 1 << 25); //clear hdmi_tx interrupt + return IRQ_HANDLED; +} + +static void hdmi_tvenc1080i_set(Hdmi_tx_video_para_t* param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; // Annie 01Sep2011: Change value from 3 to 2, due to video encoder path delay change. + unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; + unsigned FRONT_PORCH = 88, HSYNC_PIXELS, ACTIVE_LINES = 0, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; + unsigned LINES_F0, LINES_F1 = 563,BACK_PORCH, EOF_LINES = 2, TOTAL_FRAMES; + + unsigned long total_pixels_venc ; + unsigned long active_pixels_venc; + unsigned long front_porch_venc ; + unsigned long hsync_pixels_venc ; + + unsigned long de_h_begin, de_h_end; + unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; + unsigned long hs_begin, hs_end; + unsigned long vs_adjust; + unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; + unsigned long vso_begin_evn, vso_begin_odd; + + if(param->VIC==HDMI_1080i60){ + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 562; + LINES_F1 = 563; + FRONT_PORCH = 88; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 2; + VSYNC_LINES = 5; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + } + else if(param->VIC==HDMI_1080i50){ + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (1080/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 562; + LINES_F1 = 563; + FRONT_PORCH = 528; + HSYNC_PIXELS = 44; + BACK_PORCH = 148; + EOF_LINES = 2; + VSYNC_LINES = 5; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + } + TOTAL_PIXELS =(FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. + TOTAL_LINES =(LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 2200 / 1 * 2 = 4400 + active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1920 / 1 * 2 = 3840 + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 88 / 1 * 2 = 176 + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 44 / 1 * 2 = 88 + + aml_write_reg32(P_ENCP_VIDEO_MODE, aml_read_reg32(P_ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 + + // Program DE timing + de_h_begin = modulo(aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (383 + 3) % 4400 = 386 + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (386 + 3840) % 4400 = 4226 + aml_write_reg32(P_ENCP_DE_H_BEGIN, de_h_begin); // 386 + aml_write_reg32(P_ENCP_DE_H_END, de_h_end); // 4226 + // Program DE timing for even field + de_v_begin_even = aml_read_reg32(P_ENCP_VIDEO_VAVON_BLINE); // 20 + de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 20 + 540 = 560 + aml_write_reg32(P_ENCP_DE_V_BEGIN_EVEN,de_v_begin_even); // 20 + aml_write_reg32(P_ENCP_DE_V_END_EVEN, de_v_end_even); // 560 + // Program DE timing for odd field if needed + if (INTERLACE_MODE) { + // Calculate de_v_begin_odd according to enc480p_timing.v: + //wire[10:0] cfg_ofld_vavon_bline = {{7{ofld_vavon_ofst1 [3]}},ofld_vavon_ofst1 [3:0]} + cfg_video_vavon_bline + ofld_line; + de_v_begin_odd = to_signed((aml_read_reg32(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + de_v_begin_even + (TOTAL_LINES-1)/2; // 1 + 20 + (1125-1)/2 = 583 + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; // 583 + 540 = 1123 + aml_write_reg32(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd);// 583 + aml_write_reg32(P_ENCP_DE_V_END_ODD, de_v_end_odd); // 1123 + } + + // Program Hsync timing + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; // 4226 + 176 - 4400 = 2 + + + + + + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (2 + 88) % 4400 = 90 + aml_write_reg32(P_ENCP_DVI_HSO_BEGIN, hs_begin); // 2 + aml_write_reg32(P_ENCP_DVI_HSO_END, hs_end); // 90 + + // Program Vsync timing for even field + if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) { + vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); // 20 - 15 - 5 - 0 = 0 + } else { + vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); + } + vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); // (0 + 5) % 1125 = 5 + aml_write_reg32(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); // 0 + aml_write_reg32(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); // 5 + vso_begin_evn = hs_begin; // 2 + aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 2 + aml_write_reg32(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); // 2 + // Program Vsync timing for odd field if needed + if (INTERLACE_MODE) { + vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; // 583-1 - 15 - 5 = 562 + vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; // 583-1 - 15 = 567 + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); // (2 + 4400/2) % 4400 = 2202 + aml_write_reg32(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); // 562 + aml_write_reg32(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); // 567 + aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); // 2202 + aml_write_reg32(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); // 2202 + } + + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci + (0 << 1) | // [ 1] src_sel_encp + (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. + (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. + (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). + (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: + // 0=output CrYCb(BRG); + // 1=output YCbCr(RGB); + // 2=output YCrCb(RBG); + // 3=output CbCrY(GBR); + // 4=output CbYCr(GRB); + // 5=output CrCbY(BGR); + // 6,7=Rsrv. +#ifdef DOUBLE_CLK_720P_1080I + (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. +#else + (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. +#endif + (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. + ); + aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 1, 1); // [ 1] src_sel_encp: Enable ENCP output to HDMI + +} + +static void hdmi_tvenc480i_set(Hdmi_tx_video_para_t* param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 1; // Annie 01Sep2011: Change value from 2 to 1, due to video encoder path delay change. + unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; + unsigned FRONT_PORCH = 38, HSYNC_PIXELS = 124, ACTIVE_LINES = 0, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; + unsigned LINES_F0 = 262, LINES_F1 = 263, BACK_PORCH = 114, EOF_LINES = 2, TOTAL_FRAMES; + + unsigned long total_pixels_venc ; + unsigned long active_pixels_venc; + unsigned long front_porch_venc ; + unsigned long hsync_pixels_venc ; + + unsigned long de_h_begin, de_h_end; + unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; + unsigned long hs_begin, hs_end; + unsigned long vs_adjust; + unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; + unsigned long vso_begin_evn, vso_begin_odd; + + if((param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9)){ + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 1; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (480/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 262; + LINES_F1 = 263; + FRONT_PORCH = 38; + HSYNC_PIXELS = 124; + BACK_PORCH = 114; + EOF_LINES = 4; + VSYNC_LINES = 3; + SOF_LINES = 15; + TOTAL_FRAMES = 4; + } + else if((param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ + INTERLACE_MODE = 1; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 1; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (576/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 312; + LINES_F1 = 313; + FRONT_PORCH = 24; + HSYNC_PIXELS = 126; + BACK_PORCH = 138; + EOF_LINES = 2; + VSYNC_LINES = 3; + SOF_LINES = 19; + TOTAL_FRAMES = 4; + } + TOTAL_PIXELS =(FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. + TOTAL_LINES =(LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1716 / 2 * 2 = 1716 + active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 1440 / 2 * 2 = 1440 + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 38 / 2 * 2 = 38 + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 124 / 2 * 2 = 124 + + // Annie 01Sep2011: Comment out the following 2 lines. Because ENCP is not used for 480i and 576i. + //Wr(ENCP_VIDEO_MODE,Rd(ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 + + // Program DE timing + // Annie 01Sep2011: for 480/576i, replace VFIFO2VD_PIXEL_START with ENCI_VFIFO2VD_PIXEL_START. + de_h_begin = modulo(aml_read_reg32(P_ENCI_VFIFO2VD_PIXEL_START) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (233 + 2) % 1716 = 235 + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (235 + 1440) % 1716 = 1675 + aml_write_reg32(P_ENCI_DE_H_BEGIN, de_h_begin); // 235 + aml_write_reg32(P_ENCI_DE_H_END, de_h_end); // 1675 + + // Annie 01Sep2011: for 480/576i, replace VFIFO2VD_LINE_TOP/BOT_START with ENCI_VFIFO2VD_LINE_TOP/BOT_START. + de_v_begin_even = aml_read_reg32(P_ENCI_VFIFO2VD_LINE_TOP_START); // 17 + de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 17 + 240 = 257 + de_v_begin_odd = aml_read_reg32(P_ENCI_VFIFO2VD_LINE_BOT_START); // 18 + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; // 18 + 480/2 = 258 + aml_write_reg32(P_ENCI_DE_V_BEGIN_EVEN,de_v_begin_even); // 17 + aml_write_reg32(P_ENCI_DE_V_END_EVEN, de_v_end_even); // 257 + aml_write_reg32(P_ENCI_DE_V_BEGIN_ODD, de_v_begin_odd); // 18 + aml_write_reg32(P_ENCI_DE_V_END_ODD, de_v_end_odd); // 258 + + // Program Hsync timing + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; // 1675 + 38 = 1713 + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (1713 + 124) % 1716 = 121 + aml_write_reg32(P_ENCI_DVI_HSO_BEGIN, hs_begin); // 1713 + aml_write_reg32(P_ENCI_DVI_HSO_END, hs_end); // 121 + + // Program Vsync timing for even field + if (de_v_end_odd-1 + EOF_LINES + vs_adjust >= LINES_F1) { + vs_bline_evn = de_v_end_odd-1 + EOF_LINES + vs_adjust - LINES_F1; + vs_eline_evn = vs_bline_evn + VSYNC_LINES; + aml_write_reg32(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); + //vso_bline_evn_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); + //vso_eline_evn_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_EVN, hs_begin); + aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, hs_begin); + } else { + vs_bline_odd = de_v_end_odd-1 + EOF_LINES + vs_adjust; // 258-1 + 4 + 0 = 261 + aml_write_reg32(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); // 261 + //vso_bline_odd_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_ODD, hs_begin); // 1713 + if (vs_bline_odd + VSYNC_LINES >= LINES_F1) { + vs_eline_evn = vs_bline_odd + VSYNC_LINES - LINES_F1; // 261 + 3 - 263 = 1 + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); // 1 + //vso_eline_evn_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, hs_begin); // 1713 + } else { + vs_eline_odd = vs_bline_odd + VSYNC_LINES; + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); + //vso_eline_odd_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, hs_begin); + } + } + // Program Vsync timing for odd field + if (de_v_end_even-1 + EOF_LINES + 1 >= LINES_F0) { + vs_bline_odd = de_v_end_even-1 + EOF_LINES + 1 - LINES_F0; + vs_eline_odd = vs_bline_odd + VSYNC_LINES; + aml_write_reg32(P_ENCI_DVI_VSO_BLINE_ODD, vs_bline_odd); + //vso_bline_odd_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); + //vso_eline_odd_reg_wr_cnt ++; + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); + aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_ODD, vso_begin_odd); + aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, vso_begin_odd); + } else { + vs_bline_evn = de_v_end_even-1 + EOF_LINES + 1; // 257-1 + 4 + 1 = 261 + aml_write_reg32(P_ENCI_DVI_VSO_BLINE_EVN, vs_bline_evn); // 261 + //vso_bline_evn_reg_wr_cnt ++; + vso_begin_evn = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); // (1713 + 1716/2) % 1716 = 855 + aml_write_reg32(P_ENCI_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 855 + if (vs_bline_evn + VSYNC_LINES >= LINES_F0) { + vs_eline_odd = vs_bline_evn + VSYNC_LINES - LINES_F0; // 261 + 3 - 262 = 2 + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_ODD, vs_eline_odd); // 2 + //vso_eline_odd_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_END_ODD, vso_begin_evn); // 855 + } else { + vs_eline_evn = vs_bline_evn + VSYNC_LINES; + aml_write_reg32(P_ENCI_DVI_VSO_ELINE_EVN, vs_eline_evn); + //vso_eline_evn_reg_wr_cnt ++; + aml_write_reg32(P_ENCI_DVI_VSO_END_EVN, vso_begin_evn); + } + } + aml_set_reg32_bits(P_HHI_GCLK_OTHER, 1, 8, 1); // Enable VENCI gate + // Check if there are duplicate or missing timing settings + //if ((vso_bline_evn_reg_wr_cnt != 1) || (vso_bline_odd_reg_wr_cnt != 1) || + // (vso_eline_evn_reg_wr_cnt != 1) || (vso_eline_odd_reg_wr_cnt != 1)) { + //stimulus_print("[TEST.C] Error: Multiple or missing timing settings on reg ENCI_DVI_VSO_B(E)LINE_EVN(ODD)!\n"); + //stimulus_finish_fail(1); + //} + + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci + (0 << 1) | // [ 1] src_sel_encp + (0 << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. + (0 << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. + (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). + (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: + // 0=output CrYCb(BRG); + // 1=output YCbCr(RGB); + // 2=output YCrCb(RBG); + // 3=output CbCrY(GBR); + // 4=output CbYCr(GRB); + // 5=output CrCbY(BGR); + // 6,7=Rsrv. + (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. + (1 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. + ); + aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 0, 1); // [ 0] src_sel_enci: Enable ENCI output to HDMI + +} + +static void hdmi_tvenc_set(Hdmi_tx_video_para_t *param) +{ + unsigned long VFIFO2VD_TO_HDMI_LATENCY = 2; // Annie 01Sep2011: Change value from 3 to 2, due to video encoder path delay change. + unsigned long TOTAL_PIXELS, PIXEL_REPEAT_HDMI, PIXEL_REPEAT_VENC, ACTIVE_PIXELS; + unsigned FRONT_PORCH, HSYNC_PIXELS, ACTIVE_LINES, INTERLACE_MODE, TOTAL_LINES, SOF_LINES, VSYNC_LINES; + unsigned LINES_F0, LINES_F1,BACK_PORCH, EOF_LINES, TOTAL_FRAMES; + + unsigned long total_pixels_venc ; + unsigned long active_pixels_venc; + unsigned long front_porch_venc ; + unsigned long hsync_pixels_venc ; + + unsigned long de_h_begin, de_h_end; + unsigned long de_v_begin_even, de_v_end_even, de_v_begin_odd, de_v_end_odd; + unsigned long hs_begin, hs_end; + unsigned long vs_adjust; + unsigned long vs_bline_evn, vs_eline_evn, vs_bline_odd, vs_eline_odd; + unsigned long vso_begin_evn, vso_begin_odd; + + if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9)){ + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (480/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 525; + LINES_F1 = 525; + FRONT_PORCH = 16; + HSYNC_PIXELS = 62; + BACK_PORCH = 60; + EOF_LINES = 9; + VSYNC_LINES = 6; + SOF_LINES = 30; + TOTAL_FRAMES = 4; + } + else if((param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9)){ + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (720*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (576/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 625; + LINES_F1 = 625; + FRONT_PORCH = 12; + HSYNC_PIXELS = 64; + BACK_PORCH = 68; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 39; + TOTAL_FRAMES = 4; + } + else if(param->VIC==HDMI_720p60){ + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (720/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 750; + LINES_F1 = 750; + FRONT_PORCH = 110; + HSYNC_PIXELS = 40; + BACK_PORCH = 220; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 20; + TOTAL_FRAMES = 4; + } + else if(param->VIC==HDMI_720p50){ + INTERLACE_MODE = 0; + PIXEL_REPEAT_VENC = 1; + PIXEL_REPEAT_HDMI = 0; + ACTIVE_PIXELS = (1280*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES = (720/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 = 750; + LINES_F1 = 750; + FRONT_PORCH = 440; + HSYNC_PIXELS = 40; + BACK_PORCH = 220; + EOF_LINES = 5; + VSYNC_LINES = 5; + SOF_LINES = 20; + TOTAL_FRAMES = 4; + } + else if(param->VIC==HDMI_1080p50){ + INTERLACE_MODE =0; + PIXEL_REPEAT_VENC =0; + PIXEL_REPEAT_HDMI =0; + ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 =1125; + LINES_F1 =1125; + FRONT_PORCH =528; + HSYNC_PIXELS =44; + BACK_PORCH =148; + EOF_LINES =4; + VSYNC_LINES =5; + SOF_LINES =36; + TOTAL_FRAMES =4; + } + else if(param->VIC==HDMI_1080p24){//1080p24 support + INTERLACE_MODE =0; + PIXEL_REPEAT_VENC =0; + PIXEL_REPEAT_HDMI =0; + ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 =1125; + LINES_F1 =1125; + FRONT_PORCH =638; + HSYNC_PIXELS =44; + BACK_PORCH =148; + EOF_LINES =4; + VSYNC_LINES =5; + SOF_LINES =36; + TOTAL_FRAMES =4; + } + else{ //HDMI_1080p60, HDMI_1080p30 + INTERLACE_MODE =0; + PIXEL_REPEAT_VENC =0; + PIXEL_REPEAT_HDMI =0; + ACTIVE_PIXELS =(1920*(1+PIXEL_REPEAT_HDMI)); // Number of active pixels per line. + ACTIVE_LINES =(1080/(1+INTERLACE_MODE)); // Number of active lines per field. + LINES_F0 =1125; + LINES_F1 =1125; + FRONT_PORCH =88; + HSYNC_PIXELS =44; + BACK_PORCH =148; + EOF_LINES =4; + VSYNC_LINES =5; + SOF_LINES =36; + TOTAL_FRAMES =4; + } + + TOTAL_PIXELS = (FRONT_PORCH+HSYNC_PIXELS+BACK_PORCH+ACTIVE_PIXELS); // Number of total pixels per line. + TOTAL_LINES = (LINES_F0+(LINES_F1*INTERLACE_MODE)); // Number of total lines per frame. + + total_pixels_venc = (TOTAL_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 858 / 1 * 2 = 1716 + active_pixels_venc= (ACTIVE_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 720 / 1 * 2 = 1440 + front_porch_venc = (FRONT_PORCH / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 16 / 1 * 2 = 32 + hsync_pixels_venc = (HSYNC_PIXELS / (1+PIXEL_REPEAT_HDMI)) * (1+PIXEL_REPEAT_VENC); // 62 / 1 * 2 = 124 + + aml_write_reg32(P_ENCP_VIDEO_MODE,aml_read_reg32(P_ENCP_VIDEO_MODE)|(1<<14)); // cfg_de_v = 1 + // Program DE timing + de_h_begin = modulo(aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN) + VFIFO2VD_TO_HDMI_LATENCY, total_pixels_venc); // (217 + 3) % 1716 = 220 + de_h_end = modulo(de_h_begin + active_pixels_venc, total_pixels_venc); // (220 + 1440) % 1716 = 1660 + aml_write_reg32(P_ENCP_DE_H_BEGIN, de_h_begin); // 220 + aml_write_reg32(P_ENCP_DE_H_END, de_h_end); // 1660 + // Program DE timing for even field + de_v_begin_even = aml_read_reg32(P_ENCP_VIDEO_VAVON_BLINE); // 42 + de_v_end_even = de_v_begin_even + ACTIVE_LINES; // 42 + 480 = 522 + aml_write_reg32(P_ENCP_DE_V_BEGIN_EVEN,de_v_begin_even); // 42 + aml_write_reg32(P_ENCP_DE_V_END_EVEN, de_v_end_even); // 522 + // Program DE timing for odd field if needed + if (INTERLACE_MODE) { + // Calculate de_v_begin_odd according to enc480p_timing.v: + //wire[10:0] cfg_ofld_vavon_bline = {{7{ofld_vavon_ofst1 [3]}},ofld_vavon_ofst1 [3:0]} + cfg_video_vavon_bline + ofld_line; + de_v_begin_odd = to_signed((aml_read_reg32(P_ENCP_VIDEO_OFLD_VOAV_OFST) & 0xf0)>>4) + de_v_begin_even + (TOTAL_LINES-1)/2; + de_v_end_odd = de_v_begin_odd + ACTIVE_LINES; + aml_write_reg32(P_ENCP_DE_V_BEGIN_ODD, de_v_begin_odd); + aml_write_reg32(P_ENCP_DE_V_END_ODD, de_v_end_odd); + } + + // Program Hsync timing + if (de_h_end + front_porch_venc >= total_pixels_venc) { + hs_begin = de_h_end + front_porch_venc - total_pixels_venc; + vs_adjust = 1; + } else { + hs_begin = de_h_end + front_porch_venc; // 1660 + 32 = 1692 + vs_adjust = 0; + } + hs_end = modulo(hs_begin + hsync_pixels_venc, total_pixels_venc); // (1692 + 124) % 1716 = 100 + aml_write_reg32(P_ENCP_DVI_HSO_BEGIN, hs_begin); // 1692 + aml_write_reg32(P_ENCP_DVI_HSO_END, hs_end); // 100 + + // Program Vsync timing for even field + if (de_v_begin_even >= SOF_LINES + VSYNC_LINES + (1-vs_adjust)) { + vs_bline_evn = de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); // 42 - 30 - 6 - 1 = 5 + } else { + vs_bline_evn = TOTAL_LINES + de_v_begin_even - SOF_LINES - VSYNC_LINES - (1-vs_adjust); + } + vs_eline_evn = modulo(vs_bline_evn + VSYNC_LINES, TOTAL_LINES); // (5 + 6) % 525 = 11 + aml_write_reg32(P_ENCP_DVI_VSO_BLINE_EVN, vs_bline_evn); // 5 + aml_write_reg32(P_ENCP_DVI_VSO_ELINE_EVN, vs_eline_evn); // 11 + vso_begin_evn = hs_begin; // 1692 + aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_EVN, vso_begin_evn); // 1692 + aml_write_reg32(P_ENCP_DVI_VSO_END_EVN, vso_begin_evn); // 1692 + // Program Vsync timing for odd field if needed + if (INTERLACE_MODE) { + vs_bline_odd = de_v_begin_odd-1 - SOF_LINES - VSYNC_LINES; + vs_eline_odd = de_v_begin_odd-1 - SOF_LINES; + vso_begin_odd = modulo(hs_begin + (total_pixels_venc>>1), total_pixels_venc); + aml_write_reg32(P_ENCP_DVI_VSO_BLINE_ODD, vs_bline_odd); + aml_write_reg32(P_ENCP_DVI_VSO_ELINE_ODD, vs_eline_odd); + aml_write_reg32(P_ENCP_DVI_VSO_BEGIN_ODD, vso_begin_odd); + aml_write_reg32(P_ENCP_DVI_VSO_END_ODD, vso_begin_odd); + } + // Annie 01Sep2011: Remove the following line as register VENC_DVI_SETTING_MORE is no long valid, use VPU_HDMI_SETTING instead. + //Wr(VENC_DVI_SETTING_MORE, (TX_INPUT_COLOR_FORMAT==0)? 1 : 0); // [0] 0=Map data pins from Venc to Hdmi Tx as CrYCb mode; + + switch(param->VIC) + { + case HDMI_480p60: + case HDMI_480p60_16x9: + case HDMI_576p50: + case HDMI_576p50_16x9: +//Note: Hsync & Vsync polarity should be negative. +//Refer to HDMI CTS 1.4A Page 169 + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci + (0 << 1) | // [ 1] src_sel_encp + (0 << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. + (0 << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. + (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). + (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: + // 0=output CrYCb(BRG); + // 1=output YCbCr(RGB); + // 2=output YCrCb(RBG); + // 3=output CbCrY(GBR); + // 4=output CbYCr(GRB); + // 5=output CrCbY(BGR); + // 6,7=Rsrv. + (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. + (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. + ); + break; + case HDMI_720p60: + case HDMI_720p50: + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci + (0 << 1) | // [ 1] src_sel_encp + (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. + (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. + (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). + (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: + // 0=output CrYCb(BRG); + // 1=output YCbCr(RGB); + // 2=output YCrCb(RBG); + // 3=output CbCrY(GBR); + // 4=output CbYCr(GRB); + // 5=output CrCbY(BGR); + // 6,7=Rsrv. +#ifdef DOUBLE_CLK_720P_1080I + (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. +#else + (1 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. +#endif + (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. + ); + break; + default: + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_write_reg32(P_VPU_HDMI_SETTING, (0 << 0) | // [ 0] src_sel_enci + (0 << 1) | // [ 1] src_sel_encp + (HSYNC_POLARITY << 2) | // [ 2] inv_hsync. 1=Invert Hsync polarity. + (VSYNC_POLARITY << 3) | // [ 3] inv_vsync. 1=Invert Vsync polarity. + (0 << 4) | // [ 4] inv_dvi_clk. 1=Invert clock to external DVI, (clock invertion exists at internal HDMI). + (((TX_INPUT_COLOR_FORMAT==0)?1:0) << 5) | // [ 7: 5] data_comp_map. Input data is CrYCb(BRG), map the output data to desired format: + // 0=output CrYCb(BRG); + // 1=output YCbCr(RGB); + // 2=output YCrCb(RBG); + // 3=output CbCrY(GBR); + // 4=output CbYCr(GRB); + // 5=output CrCbY(BGR); + // 6,7=Rsrv. + (0 << 8) | // [11: 8] wr_rate. 0=A write every clk1; 1=A write every 2 clk1; ...; 15=A write every 16 clk1. + (0 <<12) // [15:12] rd_rate. 0=A read every clk2; 1=A read every 2 clk2; ...; 15=A read every 16 clk2. + ); + } + + // Annie 01Sep2011: Register VENC_DVI_SETTING and VENC_DVI_SETTING_MORE are no long valid, use VPU_HDMI_SETTING instead. + aml_set_reg32_bits(P_VPU_HDMI_SETTING, 1, 1, 1); // [ 1] src_sel_encp: Enable ENCP output to HDMI +} + +/* +hdmi on/off +*/ +static int is_hpd_muxed(void) +{ + int ret; + ret = !!(aml_read_reg32(P_PERIPHS_PIN_MUX_1)&(1<<26)); + return ret; +} + +static void mux_hpd(void) +{ + aml_write_reg32(P_PERIPHS_PIN_MUX_1, aml_read_reg32(P_PERIPHS_PIN_MUX_1)|(1 << 26)); +} + +static void unmux_hpd(void) +{ + aml_write_reg32(P_PERIPHS_PIN_MUX_1, aml_read_reg32(P_PERIPHS_PIN_MUX_1)&~(1 << 26)); + aml_write_reg32(P_PREG_PAD_GPIO3_EN_N, aml_read_reg32(P_PREG_PAD_GPIO3_EN_N) | (1 << 19)); //GPIOH_0 as input +} + +extern int read_hpd_gpio(void); +int read_hpd_gpio(void) +{ + int level; + + level = !!(aml_read_reg32(P_PREG_PAD_GPIO3_I)&(1<<19)); //read GPIOH_0 + return level; +} +EXPORT_SYMBOL(read_hpd_gpio); + +#if 0 +static unsigned long clk81_rate = 100000000; + +static void clk81_set(void) +{ + struct clk *clk_tmp; + + clk_tmp = clk_get_sys("clk81", NULL); + if (clk_tmp) + { + clk81_rate = clk_get_rate(clk_tmp); + clk_set_rate(clk_tmp, 168000000); + CLEAR_AOBUS_REG_MASK(AO_UART_CONTROL, (1 << 19) | 0xFFF); + WRITE_AOBUS_REG_BITS(AO_UART_CONTROL, ((168000000 / (115200 * 4)) - 1) & 0xfff, 0, 12); + } + msleep(2); //Waiting some time + //printk("%s clk81_rate: %d\n", __FUNCTION__, clk81_rate); +} + +static void clk81_resume(void) +{ + struct clk *clk_tmp; + + clk_tmp = clk_get_sys("clk81", NULL); + if (clk_tmp) + { + clk_set_rate(clk_tmp, clk81_rate); + CLEAR_AOBUS_REG_MASK(AO_UART_CONTROL, (1 << 19) | 0xFFF); + WRITE_AOBUS_REG_BITS(AO_UART_CONTROL, ((clk81_rate / (115200 * 4)) - 1) & 0xfff, 0, 12); + } + msleep(2); //Waiting some time + //printk("%s clk81_rate: %d\n", __FUNCTION__, clk81_rate); +} +#endif + +static void digital_clk_off(unsigned char flag) +{ +// clk81_resume(); + if(flag&1){ +//#ifdef AML_A3 + /* off hdmi audio clock */ +// hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL1)&(~(1<<13))); // +// hdmi_wr_reg(TX_AUDIO_FORMAT, hdmi_rd_reg(TX_AUDIO_FORMAT)|(1<<7)); +// hdmi_wr_reg(TX_AUDIO_I2S, hdmi_rd_reg(TX_AUDIO_I2S)|(1<<1)); +//#endif + } + + if(flag&2){ + /* off hdmi pixel clock */ +// Wr(HHI_GCLK_MPEG2, Rd(HHI_GCLK_MPEG2)&(~(1<<4))); //disable pixel clock, set cbus reg HHI_GCLK_MPEG2 bit [4] = 0 + aml_write_reg32(P_HHI_GCLK_OTHER, aml_read_reg32(P_HHI_GCLK_OTHER)&(~(1<<17))); //disable VCLK1_HDMI GATE, set cbus reg HHI_GCLK_OTHER bit [17] = 0 + aml_write_reg32(P_VENC_DVI_SETTING, (aml_read_reg32(P_VENC_DVI_SETTING)&(~(7<<4)))|(5<<4)); //set cbus reg VENC_DVI_SETTING bit[6:4] = 0x5 + // Second turn off gate. + aml_write_reg32(P_HHI_GCLK_MPEG2, aml_read_reg32(P_HHI_GCLK_MPEG2) & (~(1<<4))); //Disable HDMI PCLK + } + if(flag&4){ + /* off hdmi sys clock */ + aml_write_reg32(P_HHI_HDMI_CLK_CNTL, aml_read_reg32(P_HHI_HDMI_CLK_CNTL)&(~(1<<8))); // off hdmi sys clock gate + } +} + +static void digital_clk_on(unsigned char flag) +{ +// clk81_set(); + if(flag&4){ + /* on hdmi sys clock */ + // ----------------------------------------- + // HDMI (90Mhz) + // ----------------------------------------- + // .clk_div ( hi_hdmi_clk_cntl[6:0] ), + // .clk_en ( hi_hdmi_clk_cntl[8] ), + // .clk_sel ( hi_hdmi_clk_cntl[11:9]), + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); // Divide the "other" PLL output by 1 + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 3); // select "XTAL" PLL + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); // Enable gated clock +// Wr( HHI_HDMI_CLK_CNTL, ((2 << 9) | // select "misc" PLL +// (1 << 8) | // Enable gated clock +// (5 << 0)) ); // Divide the "other" PLL output by 6 + } + if(flag&2){ + /* on hdmi pixel clock */ + aml_write_reg32(P_HHI_GCLK_MPEG2, aml_read_reg32(P_HHI_GCLK_MPEG2) | (1<<4)); //Enable HDMI PCLK +// Wr(HHI_GCLK_MPEG2, Rd(HHI_GCLK_MPEG2)|(1<<4)); //enable pixel clock, set cbus reg HHI_GCLK_MPEG2 bit [4] = 1 + aml_write_reg32(P_HHI_GCLK_OTHER, aml_read_reg32(P_HHI_GCLK_OTHER)|(1<<17)); //enable VCLK1_HDMI GATE, set cbus reg HHI_GCLK_OTHER bit [17] = 1 + } + if(flag&1){ + } +} + +static void phy_pll_off(void) +{ + hdmi_phy_suspend(); +} + +/**/ +void hdmi_hw_set_powermode(hdmitx_dev_t* hdmitx_device) +{ + int vic = hdmitx_device->cur_VIC; + + switch(vic) { + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576p50: + case HDMI_576p50_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + case HDMI_480p60: + case HDMI_480p60_16x9: + case HDMI_720p50: + case HDMI_720p60: + case HDMI_1080i50: + case HDMI_1080i60: + case HDMI_1080p24://1080p24 support + case HDMI_1080p50: + case HDMI_1080p60: + default: + //aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08c38d0b); + break; + } + //aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 2); +} + +void hdmi_hw_init(hdmitx_dev_t* hdmitx_device) +{ + unsigned int tmp_add_data; + HDMI_Video_Codes_t vic; + + digital_clk_on(7); + aml_set_reg32_bits(P_HHI_VPU_MEM_PD_REG1, 0x0, 20, 2); +// Powerup VPU_HDMI + aml_write_reg32(P_AO_RTI_GEN_PWR_SLEEP0, aml_read_reg32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<8))); // [8] power on + aml_write_reg32(P_HHI_MEM_PD_REG0, aml_read_reg32(P_HHI_MEM_PD_REG0) & (~(0xff << 8))); // HDMI MEM-PD + + // Remove VPU_HDMI ISO + aml_write_reg32(P_AO_RTI_GEN_PWR_SLEEP0, aml_read_reg32(P_AO_RTI_GEN_PWR_SLEEP0) & (~(0x1<<9))); // [9] VPU_HDMI + + aml_set_reg32_bits(P_HHI_GCLK_MPEG2, 1, 4, 1); //enable HDMI PCLK + aml_set_reg32_bits(P_HHI_GCLK_MPEG2, 1, 3, 1); //enable HDMI Int Sync + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 9, 2); // select XTAL + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 0, 0, 7); // Divide by 1 + aml_set_reg32_bits(P_HHI_HDMI_CLK_CNTL, 1, 8, 1); // Enable gated clock + + aml_set_reg32_bits(P_HHI_MEM_PD_REG0, 0x00, 8, 8); //disable HDMI memory PD TODO: set in suspend/resume + + aml_write_reg32(P_HHI_HDMI_AFC_CNTL, aml_read_reg32(P_HHI_HDMI_AFC_CNTL) | 0x3); + + hdmi_wr_reg(TX_HDCP_MODE, 0x40); +#ifndef CONFIG_AML_HDMI_TX_HDCP + hdmi_tx_gate_pwr_ctrl(HDCP_DIS, NULL); +#endif + vic = hdmitx_device->HWOp.GetState(hdmitx_device, STAT_VIDEO_VIC, 0); + if(vic != HDMI_Unkown) { + hdmi_print(IMP, SYS "ALREADY init VIC = %d\n", vic); + hdmitx_device->cur_VIC = vic; + hdmi_tx_gate_pwr_ctrl(VID_EN, hdmitx_device); + return; + } + else { + hdmi_tx_gate_pwr_ctrl(VID_DIS, NULL); + } + hdmi_phy_suspend(); + //todo + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0xf, 23, 4); //Enable reg1[23:24]:HDMI SDA(5v)/SCL(5V) +#ifdef CONFIG_PANEL_IT6681 + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0, 23, 3); //disable reg1[23:25]:HDMI CEC/SCL(5v)/SDA(5V) +#endif + hdmi_print(IMP, SYS "hw init\n"); + + hdmi_wr_reg(0x017, 0x1d); //1d for power-up Band-gap and main-bias ,00 is power down + if(serial_reg_val<0x20){ + hdmi_wr_reg(0x018, 0x24); + } + else{ + hdmi_wr_reg(0x018, serial_reg_val); //Serializer Internal clock setting ,please fix to vaue 24 ,other setting is only for debug + } + hdmi_wr_reg(0x01a, 0xfb); //bit[2:0]=011 ,CK channel output TMDS CLOCK ,bit[2:0]=101 ,ck channel output PHYCLCK + + hdmi_hw_set_powermode(hdmitx_device); + + hdmi_wr_reg(0x0F7, 0x0F); // Termination resistor calib value + + // -------------------------------------------------------- + // Program core_pin_mux to enable HDMI pins + // -------------------------------------------------------- + //wire pm_hdmi_cec_en = pin_mux_reg0[2]; + //wire pm_hdmi_hpd_5v_en = pin_mux_reg0[1]; + //wire pm_hdmi_i2c_5v_en = pin_mux_reg0[0]; + + // Enable these interrupts: [2] tx_edit_int_rise [1] tx_hpd_int_fall [0] tx_hpd_int_rise + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0x0); + // HPD glitch filter + hdmi_wr_reg(TX_HDCP_HPD_FILTER_L, 0xa0); + hdmi_wr_reg(TX_HDCP_HPD_FILTER_H, 0xa0); + + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x90); //bit5,6 is converted + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); + delay_us(10); + + /**/ + + // Enable software controlled DDC transaction + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0 ; // forced_sys_trigger + //tmp_add_data[6] = 1'b0 ; // sys_trigger_config + //tmp_add_data[5] = 1'b0 ; // mem_acc_seq_mode + //tmp_add_data[4] = 1'b0 ; // mem_acc_seq_start + //tmp_add_data[3] = 1'b1 ; // forced_mem_copy_done + //tmp_add_data[2] = 1'b1 ; // mem_copy_done_config + //tmp_add_data[1] = 1'b1 ; // sys_trigger_config_semi_manu + //tmp_add_data[0] = 1'b0 ; // Rsrv + hdmi_wr_reg(TX_HDCP_EDID_CONFIG, 0x0c); //// for hdcp, can not use 0x0e + hdmi_wr_reg(TX_CORE_EDID_CONFIG_MORE, (1 << 0)); // [1]: keep_edid_error + // [0]: sys_trigger_config_semi_manu + + hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_1, 0); + hdmi_wr_reg(TX_PACKET_CONTROL_2, 2); + + hdmi_wr_reg(TX_HDCP_CONFIG0, 1<<3); //set TX rom_encrypt_off=1 + hdmi_wr_reg(TX_HDCP_MEM_CONFIG, 0<<3); //set TX read_decrypt=0 + hdmi_wr_reg(TX_HDCP_ENCRYPT_BYTE, 0); //set TX encrypt_byte=0x00 + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // Force packet timing + //tmp_add_data[6] = 1'b0; // PACKET ALLOC MODE + //tmp_add_data[5:0] = 6'd47 ; // PACKET_START_LATENCY + //tmp_add_data = 47; + tmp_add_data = 58; + hdmi_wr_reg(TX_PACKET_CONTROL_1, tmp_add_data); //this register should be set to ensure the first hdcp succeed + + //tmp_add_data[7] = 1'b0; // cp_desired + //tmp_add_data[6] = 1'b0; // ess_config + //tmp_add_data[5] = 1'b0; // set_avmute + //tmp_add_data[4] = 1'b1; // clear_avmute + //tmp_add_data[3] = 1'b0; // hdcp_1_1 + //tmp_add_data[2] = 1'b0; // Vsync/Hsync forced_polarity_select + //tmp_add_data[1] = 1'b0; // forced_vsync_polarity + //tmp_add_data[0] = 1'b0; // forced_hsync_polarity + //tmp_add_data = 0x10; + tmp_add_data = 0x0; //rain + hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); + //config_hdmi(1); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7:0] = 0xa ; // time_divider[7:0] for DDC I2C bus clock + //tmp_add_data = 0xa; //800k + //tmp_add_data = 0x3f; //190k + tmp_add_data = 0x18 - 1; //50k // hdmi system clock change to XTAL 24MHz + hdmi_wr_reg(TX_HDCP_CONFIG3, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 8'b1 ; //cp_desired + //tmp_add_data[6] = 8'b1 ; //ess_config + //tmp_add_data[5] = 8'b0 ; //set_avmute + //tmp_add_data[4] = 8'b0 ; //clear_avmute + //tmp_add_data[3] = 8'b1 ; //hdcp_1_1 + //tmp_add_data[2] = 8'b0 ; //forced_polarity + //tmp_add_data[1] = 8'b0 ; //forced_vsync_polarity + //tmp_add_data[0] = 8'b0 ; //forced_hsync_polarity + tmp_add_data = 0x40; + hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); + + hdmi_wr_reg(TX_AUDIO_CONTROL_MORE, 1); + + hdmi_hw_set_powermode(hdmitx_device); + + // -------------------------------------------------------- + // Release TX out of reset + // -------------------------------------------------------- + //new reset sequence, 2010Sep09, rain + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain + delay_us(10); + + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x68); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + delay_us(10); +} + +#ifdef CONFIG_ARCH_MESON6 +// TODO, need test in m8 +// When 1080p50hz output, we shall manually configure +// bolow register to get stable Video Timing. +static void hdmi_reconfig_packet_setting(void) +{ + hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_1, 0x01); + hdmi_wr_reg(TX_PACKET_ALLOC_ACTIVE_2, 0x12); + hdmi_wr_reg(TX_PACKET_ALLOC_EOF_1, 0x10); + hdmi_wr_reg(TX_PACKET_ALLOC_EOF_2, 0x12); + hdmi_wr_reg(TX_PACKET_ALLOC_SOF_1, 0xb6); + hdmi_wr_reg(TX_PACKET_ALLOC_SOF_2, 0x11); + hdmi_wr_reg(TX_PACKET_CONTROL_1, (hdmi_rd_reg(TX_PACKET_CONTROL_1)) | (1 << 7)); // bit[7]: forced_packet_timing +} +#endif + +static void hdmi_hw_reset(hdmitx_dev_t* hdmitx_device, Hdmi_tx_video_para_t *param) +{ + unsigned int tmp_add_data; + unsigned long TX_OUTPUT_COLOR_FORMAT; + + hdmi_print(IMP, SYS "hw reset\n"); + + digital_clk_on(7); + + if(param->color==COLOR_SPACE_YUV444){ + TX_OUTPUT_COLOR_FORMAT=1; + } + else if(param->color==COLOR_SPACE_YUV422){ + TX_OUTPUT_COLOR_FORMAT=3; + } + else{ + TX_OUTPUT_COLOR_FORMAT=0; + } + + if(delay_flag&2) + delay_us(1000*100); + //printk("delay 100ms\n"); + + aml_write_reg32(P_HHI_HDMI_AFC_CNTL, aml_read_reg32(P_HHI_HDMI_AFC_CNTL) | 0x3); + + hdmi_wr_reg(0x017, 0x1d); //1d for power-up Band-gap and main-bias ,00 is power down + if(new_reset_sequence_flag==0){ + if(serial_reg_val==0){ + if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60) + ||(param->VIC==HDMI_1080p24)){ + hdmi_wr_reg(0x018, 0x22); + } + else{ + hdmi_wr_reg(0x018, 0x24); + } + } + else if(serial_reg_val==1){ + if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9) + ||(param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9) + ||(param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9) + ||(param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ + hdmi_wr_reg(0x018, 0x24); + } + else{ + hdmi_wr_reg(0x018, 0x22); + } + } + else{ + hdmi_wr_reg(0x018, serial_reg_val); + } + if((param->VIC==HDMI_1080p60)&&(param->color_depth==COLOR_30BIT)&&(hdmi_rd_reg(0x018)==0x22)){ + hdmi_wr_reg(0x018,0x12); + } + } + hdmi_wr_reg(0x01a, 0xfb); //bit[2:0]=011 ,CK channel output TMDS CLOCK ,bit[2:0]=101 ,ck channel output PHYCLCK + + hdmi_hw_set_powermode(hdmitx_device); + + hdmi_wr_reg(0x0F7, 0x0F); // Termination resistor calib value + + // delay 1000uS, then check HPLL_LOCK + delay_us(1000); + //while ( (Rd(HHI_VID_PLL_CNTL3) & (1<<31)) != (1<<31) ); + +//////////////////////////////reset + if(new_reset_sequence_flag){ + + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x90); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); + delay_us(10); + } + else{ + // Keep TX (except register I/F) in reset, while programming the registers: + tmp_add_data = 0; + tmp_add_data |= 1 << 7; // tx_pixel_rstn + tmp_add_data |= 1 << 6; // tx_tmds_rstn + tmp_add_data |= 1 << 5; // tx_audio_master_rstn + tmp_add_data |= 1 << 4; // tx_audio_sample_rstn + tmp_add_data |= 1 << 3; // tx_i2s_reset_rstn + tmp_add_data |= 1 << 2; // tx_dig_reset_n_ch2 + tmp_add_data |= 1 << 1; // tx_dig_reset_n_ch1 + tmp_add_data |= 1 << 0; // tx_dig_reset_n_ch0 + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, tmp_add_data); + + tmp_add_data = 0; + tmp_add_data |= 1 << 7; // HDMI_CH3_RST_IN + tmp_add_data |= 1 << 6; // HDMI_CH2_RST_IN + tmp_add_data |= 1 << 5; // HDMI_CH1_RST_IN + tmp_add_data |= 1 << 4; // HDMI_CH0_RST_IN + tmp_add_data |= 1 << 3; // HDMI_SR_RST + tmp_add_data |= 1 << 0; // tx_dig_reset_n_ch3 + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, tmp_add_data); + } + // Enable software controlled DDC transaction + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0 ; // forced_sys_trigger + //tmp_add_data[6] = 1'b0 ; // sys_trigger_config + //tmp_add_data[5] = 1'b0 ; // mem_acc_seq_mode + //tmp_add_data[4] = 1'b0 ; // mem_acc_seq_start + //tmp_add_data[3] = 1'b1 ; // forced_mem_copy_done + //tmp_add_data[2] = 1'b1 ; // mem_copy_done_config + //tmp_add_data[1] = 1'b1 ; // sys_trigger_config_semi_manu + //tmp_add_data[0] = 1'b0 ; // Rsrv + + tmp_add_data = 0x0c; // for hdcp, can not use 0x0e + hdmi_wr_reg(TX_HDCP_EDID_CONFIG, tmp_add_data); + + hdmi_wr_reg(TX_HDCP_CONFIG0, 0x3<<3); //set TX rom_encrypt_off=1 + hdmi_wr_reg(TX_HDCP_MEM_CONFIG, 0<<3); //set TX read_decrypt=0 + hdmi_wr_reg(TX_HDCP_ENCRYPT_BYTE, 0); //set TX encrypt_byte=0x00 + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // Force DTV timing (Auto) + //tmp_add_data[6] = 1'b0; // Force Video Scan, only if [7]is set + //tmp_add_data[5] = 1'b0 ; // Force Video field, only if [7]is set + //tmp_add_data[4:0] = 5'b00 ; // Rsrv + if(hdmitx_device->cur_VIC == 39) + tmp_add_data = 0; + else + tmp_add_data = (1<<4); + hdmi_wr_reg(TX_VIDEO_DTV_TIMING, tmp_add_data); + + tmp_add_data = 0; + tmp_add_data |= 0 << 7; // [7] forced_default_phase + tmp_add_data |= 0 << 2; // [6:2] Rsrv + tmp_add_data |= param->color_depth << 0; // [1:0] Color_depth:0=24-bit pixel; 1=30-bit pixel; 2=36-bit pixel; 3=48-bit pixel + hdmi_wr_reg(TX_VIDEO_DTV_MODE, tmp_add_data); // 0x00 + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // Force packet timing + //tmp_add_data[6] = 1'b0; // PACKET ALLOC MODE + //tmp_add_data[5:0] = 6'd47 ; // PACKET_START_LATENCY + //tmp_add_data = 47; + tmp_add_data = 58; + hdmi_wr_reg(TX_PACKET_CONTROL_1, tmp_add_data); + + // For debug: disable packets of audio_request, acr_request, deep_color_request, and avmute_request + //hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | 0x0f); + + //HDMI CT 7-19 GCP PB1 through PB6 not equal to 0 | 720 3 0 37 72 16367911819.90 31822 General Control Packet (GCP) + //PACKET_CONTROL[~deep_color_request_enable] + //0: horizontal GC packet transport enabled + //1: horizontal GC packet masked + hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | (0x1<<1)); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] + //tmp_add_data[5] = 1'b0; // external_packet_enable + //tmp_add_data[4] = 1'b1 ; // internal_packet_enable + //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] + //tmp_add_data[1:0] = 2'b0 ; // afe_fifo_source_select_lane_0[1:0] + tmp_add_data = 0x10; + hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // monitor_lane_1 + //tmp_add_data[6:4] = 3'd0; // monitor_select_lane_1[2:0] + //tmp_add_data[3] = 1'b1 ; // monitor_lane_0 + //tmp_add_data[2:0] = 3'd7; // monitor_select_lane_0[2:0] + tmp_add_data = 0xf; + hdmi_wr_reg(TX_CORE_DATA_MONITOR_1, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7:3] = 5'b0; // Rsrv + //tmp_add_data[2:0] = 3'd2; // monitor_select[2:0] + tmp_add_data = 0x2; + hdmi_wr_reg(TX_CORE_DATA_MONITOR_2, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b1; // forced_hdmi + //tmp_add_data[6] = 1'b1; // hdmi_config + //tmp_add_data[5:4] = 2'b0; // Rsrv + //tmp_add_data[3] = 1'b0; // bit_swap. + //tmp_add_data[2:0] = 3'd0; // channel_swap[2:0] + tmp_add_data = 0xc0; + hdmi_wr_reg(TX_TMDS_MODE, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // Rsrv + //tmp_add_data[6] = 1'b0; // TX_CONNECT_SEL: 0=use lower channel data[29:0]; 1=use upper channel data[59:30] + //tmp_add_data[5:0] = 'h0; // Rsrv + tmp_add_data = 0x0; + hdmi_wr_reg(TX_SYS4_CONNECT_SEL_1, tmp_add_data); + + // Normally it makes sense to synch 3 channel output with clock channel's rising edge, + // as HDMI's serializer is LSB out first, invert tmds_clk pattern from "1111100000" to + // "0000011111" actually enable data synch with clock rising edge. + //if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60)){ + // hdmi_wr_reg(TX_SYS4_CK_INV_VIDEO, 0xf0); + //} + //else{ + tmp_add_data = 1 << 4; // Set tmds_clk pattern to be "0000011111" before being sent to AFE clock channel + hdmi_wr_reg(TX_SYS4_CK_INV_VIDEO, tmp_add_data); + //} + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 1'b0; // Rsrv + //tmp_add_data[6] = 1'b0; // TX_AFE_FIFO channel 2 bypass=0 + //tmp_add_data[5] = 1'b0; // TX_AFE_FIFO channel 1 bypass=0 + //tmp_add_data[4] = 1'b0; // TX_AFE_FIFO channel 0 bypass=0 + //tmp_add_data[3] = 1'b1; // output enable of clk channel (channel 3) + //tmp_add_data[2] = 1'b1; // TX_AFE_FIFO channel 2 enable + //tmp_add_data[1] = 1'b1; // TX_AFE_FIFO channel 1 enable + //tmp_add_data[0] = 1'b1; // TX_AFE_FIFO channel 0 enable + tmp_add_data = 0x0f; + hdmi_wr_reg(TX_SYS5_FIFO_CONFIG, tmp_add_data); + + tmp_add_data = 0; + tmp_add_data |= TX_OUTPUT_COLOR_FORMAT << 6; // [7:6] output_color_format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. + tmp_add_data |= TX_INPUT_COLOR_FORMAT << 4; // [5:4] input_color_format: 0=RGB444; 1=YCbCr444; 2=Rsrv; 3=YCbCr422. + tmp_add_data |= param->color_depth << 2; // [3:2] output_color_depth: 0=24-b; 1=30-b; 2=36-b; 3=48-b. + tmp_add_data |= TX_INPUT_COLOR_DEPTH << 0; // [1:0] input_color_depth: 0=24-b; 1=30-b; 2=36-b; 3=48-b. + hdmi_wr_reg(TX_VIDEO_DTV_OPTION_L, tmp_add_data); // 0x50 + + if(hdmitx_device->cur_audio_param.channel_num > CC_2CH) { + i2s_to_spdif_flag = 0; + }else{ + i2s_to_spdif_flag = 1; + } + tmp_add_data = 0; + tmp_add_data |= 0 << 4; // [7:4] Rsrv + tmp_add_data |= TX_OUTPUT_COLOR_RANGE << 2; // [3:2] output_color_range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. + tmp_add_data |= TX_INPUT_COLOR_RANGE << 0; // [1:0] input_color_range: 0=16-235/240; 1=16-240; 2=1-254; 3=0-255. + hdmi_wr_reg(TX_VIDEO_DTV_OPTION_H, tmp_add_data); // 0x00 + + if(!hdmi_audio_off_flag){ +#if 1 + hdmi_audio_init(i2s_to_spdif_flag); +#else + hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets +#endif + } + hdmi_wr_reg(TX_AUDIO_CONTROL_MORE, 1); + //tmp_add_data[7] = 1'b0; // cp_desired + //tmp_add_data[6] = 1'b0; // ess_config + //tmp_add_data[5] = 1'b0; // set_avmute + //tmp_add_data[4] = 1'b1; // clear_avmute + //tmp_add_data[3] = 1'b0; // hdcp_1_1 + //tmp_add_data[2] = 1'b0; // Vsync/Hsync forced_polarity_select + //tmp_add_data[1] = 1'b0; // forced_vsync_polarity + //tmp_add_data[0] = 1'b0; // forced_hsync_polarity + //tmp_add_data = 0x10; + tmp_add_data = 0x0; //rain +// hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); + //config_hdmi(1); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7:0] = 0xa ; // time_divider[7:0] for DDC I2C bus clock + + //tmp_add_data = 0xa; //800k + //tmp_add_data = 0x3f; //190k + tmp_add_data = 0x30 - 1; //50k // hdmi system clock change to XTAL 24MHz + hdmi_wr_reg(TX_HDCP_CONFIG3, tmp_add_data); + + //tmp_add_data[15:8] = 0; + //tmp_add_data[7] = 8'b1 ; //cp_desired + //tmp_add_data[6] = 8'b1 ; //ess_config + //tmp_add_data[5] = 8'b0 ; //set_avmute + //tmp_add_data[4] = 8'b0 ; //clear_avmute + //tmp_add_data[3] = 8'b1 ; //hdcp_1_1 + //tmp_add_data[2] = 8'b0 ; //forced_polarity + //tmp_add_data[1] = 8'b0 ; //forced_vsync_polarity + //tmp_add_data[0] = 8'b0 ; //forced_hsync_polarity + tmp_add_data = 0x40; + hdmi_wr_reg(TX_HDCP_MODE, tmp_add_data); + + if(param->cc == CC_ITU709){ + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B0, 0x7b); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B1, 0x12); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R0, 0x6c); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R1, 0x36); + + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB0, 0xf2); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB1, 0x2f); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR0, 0xd4); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR1, 0x77); + } + else{ + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B0, 0x2f); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_B1, 0x1d); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R0, 0x8b); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_R1, 0x4c); + + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB0, 0x18); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CB1, 0x58); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR0, 0xd0); + hdmi_wr_reg(TX_VIDEO_CSC_COEFF_CR1, 0xb6); + } + + hdmi_hw_set_powermode(hdmitx_device); + + // -------------------------------------------------------- + // Release TX out of reset + // -------------------------------------------------------- + if(new_reset_sequence_flag){ + //new reset sequence, 2010Sep09, rain + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x68); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + delay_us(10); + /* select serial*/ + if(serial_reg_val==0){ + if((param->VIC==HDMI_1080p30)||(param->VIC==HDMI_720p60)||(param->VIC==HDMI_1080i60) + ||(param->VIC==HDMI_1080p24)){ + hdmi_wr_reg(0x018, 0x22); + } + else{ + hdmi_wr_reg(0x018, 0x24); + } + } + else if(serial_reg_val==1){ + if((param->VIC==HDMI_480p60)||(param->VIC==HDMI_480p60_16x9) + ||(param->VIC==HDMI_576p50)||(param->VIC==HDMI_576p50_16x9) + ||(param->VIC==HDMI_480i60)||(param->VIC==HDMI_480i60_16x9) + ||(param->VIC==HDMI_576i50)||(param->VIC==HDMI_576i50_16x9)){ + hdmi_wr_reg(0x018, 0x24); + } + else{ + hdmi_wr_reg(0x018, 0x22); + } + } + else{ + hdmi_wr_reg(0x018, serial_reg_val); + } + if((param->VIC==HDMI_1080p60)&&(param->color_depth==COLOR_30BIT)&&(hdmi_rd_reg(0x018)==0x22)){ + hdmi_wr_reg(0x018,0x12); + } + + } + else{ + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x01); // Release serializer resets + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x00); // Release reset on TX digital clock channel + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 1<<6); // Release resets all other TX digital clock domain, except tmds_clk + delay_us(10); + + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); // Final release reset on tmds_clk domain + + tmp_add_data = hdmi_rd_reg(0x018); + if((tmp_add_data==0x22)||(tmp_add_data==0x12)){ + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x08); + delay_us(10); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x00); + } + } +#ifdef CONFIG_ARCH_MESON6 //todo + if(param->VIC == HDMI_1080p50) { + hdmi_reconfig_packet_setting(); // For 1080p50hz only + } +#endif +} + +static void hdmi_audio_init(unsigned char spdif_flag) +{ + unsigned tmp_add_data; + + /* If TX_AUDIO_FORMAT is set as 0, "Channel Status" will not be sent out correctly */ + /* TX_AUDIO_CONTROL[bit 0] should be 1, otherwise no sound??? */ + unsigned char tx_i2s_spdif; + unsigned char tx_i2s_8_channel; + + hdmi_print(IMP, AUD "%s\n", spdif_flag ? "SPDIF" : "I2S"); + + if(spdif_flag){ + tx_i2s_spdif=0; + } + else{ + tx_i2s_spdif=1; + } + tx_i2s_8_channel = ((i2s_to_spdif_flag == 1)? 0:1 ); + + tmp_add_data = 0; + tmp_add_data |= tx_i2s_spdif << 7; // [7] I2S or SPDIF + tmp_add_data |= tx_i2s_8_channel<< 6; // [6] 8 or 2ch + tmp_add_data |= 2 << 4; // [5:4] Serial Format: I2S format + tmp_add_data |= 3 << 2; // [3:2] Bit Width: 24-bit + tmp_add_data |= 0 << 1; // [1] WS Polarity: 0=WS high is right + tmp_add_data |= 1 << 0; // [0] For I2S: 0=one-bit audio; 1=I2S; + // For SPDIF: 0= channel status from input data; 1=from register + hdmi_wr_reg(TX_AUDIO_FORMAT, tmp_add_data); // 0x2f + + //tmp_add_data = 0; + //tmp_add_data |= 0x4 << 4; // [7:4] FIFO Depth=512 + //tmp_add_data |= 0x2 << 2; // [3:2] Critical threshold=Depth/16 + //tmp_add_data |= 0x1 << 0; // [1:0] Normal threshold=Depth/8 + //hdmi_wr_reg(TX_AUDIO_FIFO, tmp_add_data); // 0x49 + hdmi_wr_reg(TX_AUDIO_FIFO, aud_para); // 0x49 + + hdmi_wr_reg(TX_AUDIO_LIPSYNC, 0); // [7:0] Normalized lip-sync param: 0 means S(lipsync) = S(total)/2 + + tmp_add_data = 0; + tmp_add_data |= 0 << 7; // [7] forced_audio_fifo_clear + tmp_add_data |= 1 << 6; // [6] auto_audio_fifo_clear + tmp_add_data |= 0x0 << 4; // [5:4] audio_packet_type: 0=audio sample packet; 1=one bit audio; 2=HBR audio packet; 3=DST audio packet. + tmp_add_data |= 0 << 3; // [3] Rsrv + tmp_add_data |= 0 << 2; // [2] Audio sample packet's valid bit: 0=valid bit is 0 for I2S, is input data for SPDIF; 1=valid bit from register + tmp_add_data |= 0 << 1; // [1] Audio sample packet's user bit: 0=user bit is 0 for I2S, is input data for SPDIF; 1=user bit from register + tmp_add_data |= 0 << 0; // [0] 0=Audio sample packet's sample_flat bit is 1; 1=sample_flat is 0. + hdmi_wr_reg(TX_AUDIO_CONTROL, tmp_add_data); // 0x40 + + tmp_add_data = 0; + tmp_add_data |= tx_i2s_8_channel<< 7; // [7] Audio sample packet's header layout bit: 0=layout0; 1=layout1 + tmp_add_data |= 0 << 6; // [6] Set normal_double bit in DST packet header. + tmp_add_data |= 0 << 0; // [5:0] Rsrv + hdmi_wr_reg(TX_AUDIO_HEADER, tmp_add_data); // 0x00 + + tmp_add_data = tx_i2s_8_channel ? 0xff : 0x03; + hdmi_wr_reg(TX_AUDIO_SAMPLE, tmp_add_data); // Channel valid for up to 8 channels, 1 bit per channel. + + hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // Enable audio sample packets + + // Set N = 4096 (N is not measured, N must be configured so as to be a reference to clock_meter) + hdmi_wr_reg(TX_SYS1_ACR_N_0, 0x00); // N[7:0] + hdmi_wr_reg(TX_SYS1_ACR_N_1, 0x30); // N[15:8] + + tmp_add_data = 0; + tmp_add_data |= 0x3 << 4; // [7:4] Meas Tolerance + tmp_add_data |= 0x0 << 0; // [3:0] N[19:16] + hdmi_wr_reg(TX_SYS1_ACR_N_2, tmp_add_data); // 0xa0 + + hdmi_wr_reg(TX_AUDIO_CONTROL, hdmi_rd_reg(TX_AUDIO_CONTROL)|0x1); +} + +static void enable_audio_spdif(void) +{ + hdmi_print(INF, AUD "Enable audio spdif to HDMI\n"); + + /* enable audio*/ + hdmi_wr_reg(TX_AUDIO_I2S, 0x0 ); // Address 0x5A=0x0 TX_AUDIO_I2S + + hdmi_wr_reg(TX_AUDIO_SPDIF, 1); // TX AUDIO SPDIF Enable +} + +static void enable_audio_i2s(void) +{ + hdmi_print(INF, AUD "Enable audio i2s to HDMI\n"); + hdmi_wr_reg(TX_AUDIO_I2S, 0x1 ); // Address 0x5A=0x0 TX_AUDIO_I2S + hdmi_wr_reg(TX_AUDIO_SPDIF, 0); // TX AUDIO SPDIF Enable +} + +/************************************ +* hdmitx hardware level interface +*************************************/ + +static void hdmitx_dump_tvenc_reg(int cur_VIC, int printk_flag) +{ + int i,j; + for(i=0;hdmi_tvenc_configs[i].vic!=HDMI_Unkown;i++){ + if(cur_VIC==hdmi_tvenc_configs[i].vic){ + reg_t* reg_set=hdmi_tvenc_configs[i].reg_set; + hdmi_print(printk_flag, "------dump tevenc reg for mode %d----\n", cur_VIC); + for(j=0;reg_set[j].reg;j++){ + hdmi_print(printk_flag, "[%08x]=%08x\n",reg_set[j].reg,aml_read_reg32(CBUS_REG_ADDR(reg_set[j].reg))); + } + hdmi_print(printk_flag, "------------------\n"); + break; + } + } +} + +static void hdmitx_config_tvenc_reg(int vic, unsigned reg, unsigned val) +{ + int i,j; + for(i=0;hdmi_tvenc_configs[i].vic!=HDMI_Unkown;i++){ + if(vic==hdmi_tvenc_configs[i].vic){ + reg_t* reg_set=hdmi_tvenc_configs[i].reg_set; + for(j=0;reg_set[j].reg;j++){ + if(reg_set[j].reg==reg){ + reg_set[j].val = val; + hdmi_print(INF, SYS "set [%08x]=%08x\n",reg_set[j].reg, reg_set[j].val); + break; + } + } + if(reg_set[j].reg == 0){ + hdmi_print(INF, SYS "no [%08x] in config\n", reg); + } + break; + } + } +} + +static void hdmitx_set_pll(Hdmi_tx_video_para_t *param) +{ + hdmi_print(IMP, SYS "set pll\n"); + hdmi_print(IMP, SYS "param->VIC:%d\n", param->VIC); + + cur_vout_index = get_cur_vout_index(); + switch(param->VIC) + { + case HDMI_480p60: + case HDMI_480p60_16x9: + set_vmode_clk(VMODE_480P); + break; + case HDMI_576p50: + case HDMI_576p50_16x9: + set_vmode_clk(VMODE_576P); + break; + case HDMI_480i60: + case HDMI_480i60_16x9: + set_vmode_clk(VMODE_480I); + break; + case HDMI_576i50: + case HDMI_576i50_16x9: + set_vmode_clk(VMODE_576I); + break; + case HDMI_1080p24://1080p24 support + set_vmode_clk(VMODE_1080P_24HZ); + break; + case HDMI_1080p30: + + case HDMI_720p60: + case HDMI_720p50: + set_vmode_clk(VMODE_720P); + break; + case HDMI_1080i60: + case HDMI_1080i50: + set_vmode_clk(VMODE_1080I); + break; + case HDMI_1080p60: + case HDMI_1080p50: + set_vmode_clk(VMODE_1080P); + break; + default: + break; + } +} + +static void hdmitx_set_phy(hdmitx_dev_t* hdmitx_device) +{ + switch(hdmitx_device->cur_video_param->VIC) { + case HDMI_1080p60: + default: + aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08c31e8b); + break; + } +// P_HHI_HDMI_PHY_CNTL1 bit[1]: enable clock bit[0]: soft reset +#define RESET_HDMI_PHY() \ + aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 3); \ + msleep(1); \ + aml_write_reg32(P_HHI_HDMI_PHY_CNTL1, 2); \ + msleep(1) + + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); +#undef RESET_HDMI_PHY + hdmi_print(IMP, SYS "phy setting done\n"); +} + +static int hdmitx_set_dispmode(hdmitx_dev_t* hdmitx_device, Hdmi_tx_video_para_t *param) +{ + if(param == NULL){ //disable HDMI + hdmi_tx_gate_pwr_ctrl(VID_DIS, hdmitx_device); + return 0; + } + else if((param->VIC!=HDMI_480p60)&&(param->VIC!=HDMI_480p60_16x9) + &&(param->VIC!=HDMI_576p50)&&(param->VIC!=HDMI_576p50_16x9) + &&(param->VIC!=HDMI_480i60)&&(param->VIC!=HDMI_480i60_16x9) + &&(param->VIC!=HDMI_576i50)&&(param->VIC!=HDMI_576i50_16x9) + &&(param->VIC!=HDMI_1080p30) + &&(param->VIC!=HDMI_1080p24) + &&(param->VIC!=HDMI_1080p60)&&(param->VIC!=HDMI_1080p50) + &&(param->VIC!=HDMI_720p60)&&(param->VIC!=HDMI_720p50) + &&(param->VIC!=HDMI_4k2k_30)&&(param->VIC!=HDMI_4k2k_25)&&(param->VIC!=HDMI_4k2k_24)&&(param->VIC!=HDMI_4k2k_smpte_24) + &&(param->VIC!=HDMI_1080i60)&&(param->VIC!=HDMI_1080i50)){ + return -1; + } + else { + } + if((param->VIC==HDMI_4k2k_30)||(param->VIC==HDMI_4k2k_25)||(param->VIC==HDMI_4k2k_24)||(param->VIC==HDMI_4k2k_smpte_24)) { + hdmi_tx_gate_pwr_ctrl(VID_DIS, hdmitx_device); + printk("Not support HDMI format %d\n", param->VIC); + } + + if(color_depth_f==24) + param->color_depth = COLOR_24BIT; + else if(color_depth_f==30) + param->color_depth = COLOR_30BIT; + else if(color_depth_f==36) + param->color_depth = COLOR_36BIT; + else if(color_depth_f==48) + param->color_depth = COLOR_48BIT; + hdmi_print(INF, SYS " %d (cd%d,cs%d,pm%d,vd%d,%x) \n",param->VIC, color_depth_f, color_space_f,power_mode,power_off_vdac_flag,serial_reg_val); + if(color_space_f != 0){ + param->color = color_space_f; + } + hdmitx_device->cur_VIC = param->VIC; + hdmi_tx_gate_pwr_ctrl(VID_EN, hdmitx_device); + hdmi_hw_reset(hdmitx_device, param); + hdmitx_set_pll(param); + hdmitx_set_phy(hdmitx_device); + + if((param->VIC==HDMI_720p60)||(param->VIC==HDMI_720p50)|| + (param->VIC==HDMI_1080i60)||(param->VIC==HDMI_1080i50)){ + aml_write_reg32(P_ENCP_VIDEO_HAVON_BEGIN, aml_read_reg32(P_ENCP_VIDEO_HAVON_BEGIN)-1); + aml_write_reg32(P_ENCP_VIDEO_HAVON_END, aml_read_reg32(P_ENCP_VIDEO_HAVON_END)-1); + } + + switch(param->VIC){ + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + hdmi_tvenc480i_set(param); + break; + case HDMI_1080i60: + case HDMI_1080i50: + hdmi_tvenc1080i_set(param); + break; + default: + hdmi_tvenc_set(param); + } + hdmitx_dump_tvenc_reg(param->VIC, 0); + +//todo hdmitx_special_handler_video(hdmitx_device); + + // reset TX_SYS5_TX_SOFT_RESET_1/2 twice + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x9f); + mdelay(5); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + mdelay(5); + + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0xff); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x9f); + mdelay(5); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_2, 0x60); + mdelay(5); + + return 0; +} + + +static void hdmitx_set_packet(int type, unsigned char* DB, unsigned char* HB) +{ + // AVI frame + int i ; + unsigned char ucData ; + unsigned int pkt_reg_base=TX_PKT_REG_AVI_INFO_BASE_ADDR; + int pkt_data_len=0; + + switch(type) + { + case HDMI_PACKET_AVI: + pkt_reg_base=TX_PKT_REG_AVI_INFO_BASE_ADDR; + pkt_data_len=13; + break; + case HDMI_PACKET_VEND: + pkt_reg_base=TX_PKT_REG_VEND_INFO_BASE_ADDR; + pkt_data_len=6; + break; + case HDMI_AUDIO_INFO: + pkt_reg_base=TX_PKT_REG_AUDIO_INFO_BASE_ADDR; + pkt_data_len=9; + break; + case HDMI_SOURCE_DESCRIPTION: + pkt_reg_base=TX_PKT_REG_SPD_INFO_BASE_ADDR; + pkt_data_len=25; + default: + break; + } + + if(DB){ + for(i=0;i>8)&0x3) != 0x2 ) { + // if (i > 255) { + // //stimulus_print("[TEST.C] Error: set_hdmi_audio_source timeout!\n"); + // //stimulus_finish_fail(10); + // } + i ++; + if(i>100000) + break; + } + if(i>100000) + hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL\n"); + break; + case 2: + hdmi_print(INF, AUD "I2S out to HDMI\n");//I2S + // Enable HDMI audio clock from the selected source + data32 = 0; + data32 |= 0 << 4; // [5:4] hdmi_data_sel: 00=disable hdmi i2s input; 01=Select pcm data; 10=Select AIU I2S data; 11=Not allowed. + data32 |= 2 << 0; // [1:0] hdmi_clk_sel: 00=Disable hdmi audio clock input; 01=Select pcm clock; 10=Select AIU aoclk; 11=Not allowed. + aml_write_reg32(P_AIU_HDMI_CLK_DATA_CTRL, data32); + + // Wait until clock change is settled + i = 0; + while ( (((aml_read_reg32(P_AIU_HDMI_CLK_DATA_CTRL))>>8)&0x3) != 0x2 ) { + // if (i > 255) { + // //stimulus_print("[TEST.C] Error: set_hdmi_audio_source timeout!\n"); + // //stimulus_finish_fail(10); + // } + i ++; + if(i>100000) + break; + } + if(i>100000) + hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL !\n"); + // Enable HDMI I2S input from the selected source + data32 = 0; + data32 |= 2 << 4; // [5:4] hdmi_data_sel: 00=disable hdmi i2s input; 01=Select pcm data; 10=Select AIU I2S data; 11=Not allowed. + data32 |= 2 << 0; // [1:0] hdmi_clk_sel: 00=Disable hdmi audio clock input; 01=Select pcm clock; 10=Select AIU aoclk; 11=Not allowed. + aml_write_reg32(P_AIU_HDMI_CLK_DATA_CTRL, data32); + + // Wait until data change is settled + i = 0; + while ((((aml_read_reg32(P_AIU_HDMI_CLK_DATA_CTRL))>>12)&0x3) != 0x2 ) { + i++; + if(i>100000) + break; + } + if(i>100000) + hdmi_print(ERR, AUD "Time out: AIU_HDMI_CLK_DATA_CTRL...\n"); + break; + default: + hdmi_print(ERR, AUD "Audio Src clock to HDMI Error\n"); + break; + } +} /* set_hdmi_audio_source */ + +static int hdmitx_set_audmode(struct hdmi_tx_dev_s* hdmitx_device, Hdmi_tx_audio_para_t* audio_param) +{ + unsigned int audio_N_para = 6272; + unsigned int audio_N_tolerance = 3; +// unsigned int audio_CTS = 30000; + + hdmi_print(INF, AUD "audio channel num is %d\n", hdmitx_device->cur_audio_param.channel_num); + + hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) & (~(1<<3))); + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x30); // reset audio master & sample + hdmi_wr_reg(TX_SYS5_TX_SOFT_RESET_1, 0x00); + + if(hdmitx_device->cur_audio_param.channel_num > CC_2CH) { + i2s_to_spdif_flag = 0; + }else{ + i2s_to_spdif_flag = 1; + } + if(!hdmi_audio_off_flag){ + hdmi_audio_init(i2s_to_spdif_flag); + } + else { + hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets + } + +//Refer to HDMI SPEC V1.4 Page 137 + hdmi_print(INF, AUD "current VIC: %d\n", hdmitx_device->cur_VIC); + hdmi_print(INF, AUD "audio sample rate: %d\n", audio_param->sample_rate); + switch(hdmitx_device->cur_VIC) + { + //TMDS Clock:27MHz + case HDMI_480p60: + case HDMI_480p60_16x9: + case HDMI_576p50: + case HDMI_576p50_16x9: + case HDMI_480i60: + case HDMI_480i60_16x9: + case HDMI_576i50: + case HDMI_576i50_16x9: + switch(audio_param->sample_rate) + { + case FS_32K: + audio_N_para = 4096; + break; + case FS_44K1: + audio_N_para = 6272; + break; + case FS_88K2: + audio_N_para = 12544; + break; + case FS_176K4: + audio_N_para = 25088; + break; + case FS_48K: + audio_N_para = 6144; + break; + case FS_96K: + audio_N_para = 12288; + break; + case FS_192K: + audio_N_para = 24576; + break; + default: + break; + } + break; + //TMDS Clock:74.176MHz + case HDMI_720p60: + case HDMI_720p50: + case HDMI_1080i60: + case HDMI_1080i50: + case HDMI_1080p30: + case HDMI_1080p24: + switch(audio_param->sample_rate) + { + case FS_32K: + audio_N_para = 4096; + break; + case FS_44K1: + audio_N_para = 6272; + break; + case FS_88K2: + audio_N_para = 12544; + break; + case FS_176K4: + audio_N_para = 25088; + break; + case FS_48K: + audio_N_para = 6144; + break; + case FS_96K: + audio_N_para = 12288; + break; + case FS_192K: + audio_N_para = 24576; + break; + default: + break; + } + break; + //TMDS Clock:148.5MHz + case HDMI_1080p50: + case HDMI_1080p60: + switch(audio_param->sample_rate) + { + case FS_32K: + audio_N_para = 4096; + break; + case FS_44K1: + audio_N_para = 6272; + break; + case FS_88K2: + audio_N_para = 12544; + break; + case FS_176K4: + audio_N_para = 25088; + break; + case FS_48K: + audio_N_para = 6144; + break; + case FS_96K: + audio_N_para = 12288; + break; + case FS_192K: + audio_N_para = 24576; + break; + default: + break; + } + break; + default: + break; + } + + hdmi_print(INF, AUD "reset audio N para\n"); + switch(audio_param->sample_rate){ + case FS_44K1: + audio_N_para = 6272 * 2; + break; + case FS_48K: + audio_N_para = 6144 * 2; + break; + default: + break; + } + + //TODO. Different audio type, maybe have different settings + switch(audio_param->type){ + case CT_PCM: + break; + case CT_AC_3: + break; + case CT_MPEG1: + break; + case CT_MP3: + break; + case CT_MPEG2: + break; + case CT_AAC: + break; + case CT_DTS: + break; + case CT_ATRAC: + break; + case CT_ONE_BIT_AUDIO: + break; + case CT_DOLBY_D: + audio_N_para *= 4; + break; + case CT_DTS_HD: + audio_N_para *= 4; + break; + case CT_MAT: + break; + case CT_DST: + break; + case CT_WMA: + break; + default: + break; + } + + hdmi_wr_reg(TX_SYS1_ACR_N_0, (audio_N_para&0xff)); // N[7:0] + hdmi_wr_reg(TX_SYS1_ACR_N_1, (audio_N_para>>8)&0xff); // N[15:8] + hdmi_wr_reg(TX_SYS1_ACR_N_2, (audio_N_tolerance<<4)|((audio_N_para>>16)&0xf)); // N[19:16] + hdmi_wr_reg(TX_AUDIO_CONTROL, hdmi_rd_reg(TX_AUDIO_CONTROL)|0x1); + + hdmi_wr_reg(TX_SYS0_ACR_CTS_0, 0); //audio_CTS & 0xff); + hdmi_wr_reg(TX_SYS0_ACR_CTS_1, 0); //(audio_CTS>>8) & 0xff); + hdmi_wr_reg(TX_SYS0_ACR_CTS_2, 1 << 5); // set bit[5] force_arc_stable to 1 + + set_hdmi_audio_source(i2s_to_spdif_flag ? 1 : 2); + + hdmi_print(INF, AUD "i2s_to_spdif_flag:%d \n", i2s_to_spdif_flag); + if(i2s_to_spdif_flag) + enable_audio_spdif(); + else + enable_audio_i2s(); + + if((i2s_to_spdif_flag == 1) && (hdmitx_device->cur_audio_param.type != CT_PCM)) { + hdmi_wr_reg(TX_AUDIO_FORMAT, (hdmi_rd_reg(TX_AUDIO_FORMAT) & 0xfe)); // clear bit0, use channel status bit from input data + } + +//todo hdmitx_special_handler_audio(hdmitx_device); + + return 0; +} + +static void hdmitx_setupirq(hdmitx_dev_t* hdmitx_device) +{ + int r; + r = request_irq(INT_HDMI_TX, &intr_handler, + IRQF_SHARED, "amhdmitx", + (void *)hdmitx_device); +} + + +#if 1 + +//Expect 8*10-Bit shift pattern data: +// +//0x2e3 = 1011100011 +//0x245 = 1001000101 +//0x1cb = 0111001011 +//0x225 = 1000100101 +//0x2da = 1011011010 +//0x3e0 = 1111100000 +//0x367 = 1101100111 +//0x000 = 0000000000 + +static void turn_on_shift_pattern (void) +{ + unsigned int tmp_add_data; + hdmi_wr_reg(TX_SYS0_BIST_DATA_0, 0x00); + hdmi_wr_reg(TX_SYS0_BIST_DATA_1, 0x6c); + hdmi_wr_reg(TX_SYS0_BIST_DATA_2, 0xfe); + hdmi_wr_reg(TX_SYS0_BIST_DATA_3, 0x41); + hdmi_wr_reg(TX_SYS0_BIST_DATA_4, 0x5b); + hdmi_wr_reg(TX_SYS0_BIST_DATA_5, 0x91); + hdmi_wr_reg(TX_SYS0_BIST_DATA_6, 0x3a); + hdmi_wr_reg(TX_SYS0_BIST_DATA_7, 0x9d); + hdmi_wr_reg(TX_SYS0_BIST_DATA_8, 0x68); + hdmi_wr_reg(TX_SYS0_BIST_DATA_9, 0xc7); + + //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] + //tmp_add_data[5] = 1'b0; // external_packet_enable + //tmp_add_data[4] = 1'b1 ; // internal_packet_enable + //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] + //tmp_add_data[1:0] = 2'd3 ; // afe_fifo_source_select_lane_0[1:0] : 0=data path; 1=injected on lane 0; 2=inject on lane 1; 3=BIST. + tmp_add_data = 0x13; + hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); + + hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0x00); // Reset BIST + hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0xc0); // Enable shift pattern BIST +} + +static void turn_off_shift_pattern (void) +{ + unsigned int tmp_add_data; + hdmi_wr_reg(TX_SYS0_BIST_CONTROL, 0x00); // Reset BIST + + //tmp_add_data[7:6] = 2'b0; // audio_source_select[1:0] + //tmp_add_data[5] = 1'b0; // external_packet_enable + //tmp_add_data[4] = 1'b1 ; // internal_packet_enable + //tmp_add_data[3:2] = 2'b0; // afe_fifo_source_select_lane_1[1:0] + //tmp_add_data[1:0] = 2'd0 ; // afe_fifo_source_select_lane_0[1:0] : 0=data path; 1=injected on lane 0; 2=inject on lane 1; 3=BIST. + tmp_add_data = 0x10; + hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); +} + +static void turn_on_prbs_mode(int prbs_mode) +{ + unsigned int tmp_add_data; + tmp_add_data = 0; + tmp_add_data |= 0 << 6; // [7:6] audio_source_select[1:0] + tmp_add_data |= 0 << 5; // [5] external_packet_enable + tmp_add_data |= 0 << 4; // [4] internal_packet_enable + tmp_add_data |= 0 << 2; // [3:2] afe_fifo_source_select_lane_1[1:0]: 0=DATA_PATH; 1=TMDS_LANE_0; 2=TMDS_LANE_1; 3=BIST_PATTERN + tmp_add_data |= 3 << 0; // [1:0] afe_fifo_source_select_lane_0[1:0]: 0=DATA_PATH; 1=TMDS_LANE_0; 2=TMDS_LANE_1; 3=BIST_PATTERN + hdmi_wr_reg(TX_CORE_DATA_CAPTURE_2, tmp_add_data); // 0x03 + + tmp_add_data = 0; + tmp_add_data |= 0 << 7; // [7] monitor_lane_1 + tmp_add_data |= 0 << 4; // [6:4] monitor_select_lane_1[2:0] + tmp_add_data |= 1 << 3; // [3] monitor_lane_0 + tmp_add_data |= 7 << 0; // [2:0] monitor_select_lane_0[2:0]: 7=TMDS_ENCODE + hdmi_wr_reg(TX_CORE_DATA_MONITOR_1, tmp_add_data); // 0x0f + + // Program PRBS_MODE + hdmi_wr_reg(TX_SYS1_PRBS_DATA, prbs_mode); // 0=PRBS 11; 1=PRBS 15; 2=PRBS 7; 3=PRBS 31. + // Program PRBS BIST + + tmp_add_data = 0; + tmp_add_data |= 1 << 7; // [7] afe_bist_enable + tmp_add_data |= 0 << 6; // [6] tmds_shift_pattern_select + tmp_add_data |= 3 << 4; // [5:4] tmds_prbs_pattern_select[1:0]: + // 0=output all 0; 1=output 8-bit pattern; + // 2=output 1-bit differential pattern; 3=output 10-bit pattern + tmp_add_data |= 0 << 3; // [3] Rsrv + tmp_add_data |= 0 << 0; // [2:0] tmds_repeat_bist_pattern[2:0] + hdmi_wr_reg(TX_SYS0_BIST_CONTROL, tmp_add_data); // 0xb0 + + hdmi_print(INF, SYS "PRBS mode %d On\n", prbs_mode); +} + +#endif + +static void hdmitx_uninit(hdmitx_dev_t* hdmitx_device) +{ + //aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_STAT_CLR); + //aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK)&(~(1 << 25))); + free_irq(INT_HDMI_TX, (void *)hdmitx_device); + hdmi_print(1,"power off hdmi, unmux hpd\n"); + + phy_pll_off(); + digital_clk_off(7); //off sys clk + unmux_hpd(); +} + +static char hdcp_log_buf[HDMITX_HDCP_MONITOR_BUF_SIZE] = { 0 }; +const static hdcp_sub_t hdcp_monitor_array[] = { + {"Aksv_shw", TX_HDCP_SHW_AKSV_0, 5}, + {"Bksv ", TX_HDCP_SHW_BKSV_0, 5}, + {"Ainfo ", TX_HDCP_SHW_AINFO , 1}, + {"An ", TX_HDCP_SHW_AN_0 , 8}, + {"Bcaps ", TX_HDCP_SHW_BCAPS, 1}, + {"Bstatus ", TX_HDCP_SHW_BSTATUS_0, 2}, + {"Km ", 0x148, 7}, + {"Ri ", 0x150, 2}, + {"Ri' ", TX_HDCP_SHW_RI1_0 , 2}, + {"Pj ", 0x14f, 1}, + {"Pj' ", TX_HDCP_SHW_PJ1 , 1}, + {"AuthSt ", TX_HDCP_ST_AUTHENTICATION, 1}, + {"EncrySt0", TX_HDCP_ST_STATUS_0, 1}, + {"EncrySt1", TX_HDCP_ST_STATUS_1, 1}, + {"EncrySt2", TX_HDCP_ST_STATUS_2, 1}, + {"EncrySt3", TX_HDCP_ST_STATUS_3, 1}, + {"FramCnt ", TX_HDCP_ST_FRAME_COUNT, 1}, + {"EDIDStat", TX_HDCP_ST_EDID_STATUS, 1}, + {"MEMStat ", TX_HDCP_ST_MEM_STATUS, 1}, + {"EDID_Ext", 0x198, 1}, + {"EDDC_SEG", 0x199, 1}, + {"EDDC_ST ", 0x19a, 1}, + {"HDCP_RSV", 0x19b, 4}, + {"EDDC_SEG", 0x19c, 1}, + {"HDCPMODE", TX_HDCP_ST_ST_MODE, 1}, + {"TmdsMod ", TX_TMDS_MODE, 1}, +}; + +static int hdmitx_cntl(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) +{ + if(cmd == HDMITX_AVMUTE_CNTL) { + if(argv == AVMUTE_SET) { + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<4))); + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)|(1<<5)); + } + if(argv == AVMUTE_CLEAR) { + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<5))); + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)|(1<<4)); + } + if(argv == AVMUTE_OFF) { + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<4))); + hdmi_wr_reg(TX_HDCP_MODE, hdmi_rd_reg(TX_HDCP_MODE)&(~(1<<5))); + } + return 0; + } + else if(cmd == HDMITX_SW_INTERNAL_HPD_TRIG){ + if(argv == 1) // soft trig rising + hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT, 1); + else // soft trig falling + hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT, 2); + } + else if(cmd == HDMITX_EARLY_SUSPEND_RESUME_CNTL) { + if(argv == HDMITX_EARLY_SUSPEND) { + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 30, 1); + hdmi_phy_suspend(); + } + if(argv == HDMITX_LATE_RESUME) { + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 30, 1); + //hdmi_phy_wakeup(); // no need + } + return 0; + } + else if(cmd == HDMITX_HDCP_MONITOR) { + int i, len, st; + int array = sizeof(hdcp_monitor_array) / sizeof(hdcp_sub_t); + + int pos; + + if(!(hdmitx_device->log & HDMI_LOG_HDCP)) + return 0; + + memset(hdcp_log_buf, 0, HDMITX_HDCP_MONITOR_BUF_SIZE); + hdmi_print(INF, HDCP "\n\nMonitor HDCP start\n"); + pos = 0; + for(i = 0; i < array; i ++){ + len = hdcp_monitor_array[i].hdcp_sub_len; + st = hdcp_monitor_array[i].hdcp_sub_addr_start; + pos += sprintf(hdcp_log_buf + pos, " %s: ", hdcp_monitor_array[i].hdcp_sub_name); + do { + pos += sprintf(hdcp_log_buf + pos, "%02x", (unsigned)hdmi_rd_reg(st+len-1)); + }while(--len); + pos += sprintf(hdcp_log_buf + pos, "\n"); + } + pos += sprintf(hdcp_log_buf + pos, "HDCP %s", + ((hdmi_rd_reg(TX_HDCP_ST_STATUS_3)&0xa0)==0xa0) + ? "OK\n" : "BAD\n" + ); + printk("%s", hdcp_log_buf); + hdmi_print(INF, HDCP "Monitor HDCP end\n"); + return 0; + } + else if(cmd == HDMITX_IP_SW_RST){ + return 0; //TODO + aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16)); + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0) | (argv)); + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0, hdmi_rd_reg(OTHER_BASE_ADDR + HDMI_OTHER_CTRL0) & (~(argv))); + aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16))); + hdmi_print(INF, SYS "reset IP: 0x%x\n", argv); + return 0; + } + else if(cmd == HDMITX_CBUS_RST) { + return 0;//todo + aml_set_reg32_bits(P_RESET2_REGISTER, 1, 15, 1); + msleep(50); + hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_STAT_CLR, 0x7); + return 0; + } + else if(cmd == HDMITX_INTR_MASKN_CNTL) { + if(argv == INTR_MASKN_ENABLE) { + hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_MASKN, 0); + } + if(argv == INTR_MASKN_DISABLE) { + hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_INTR_MASKN, 0x7); + } + if(argv == INTR_CLEAR) { + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_STAT_CLR, 0x7); + } + return 0; + } + else if(cmd == HDMITX_IP_INTR_MASN_RST){ + hdmi_print(INF, SYS "reset intr mask\n"); + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0); + msleep(2); + hdmi_wr_reg(OTHER_BASE_ADDR + HDMI_OTHER_INTR_MASKN, 0x7); + } + else if(cmd == HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH){ + /* turnon digital module if gpio is high */ + if(is_hpd_muxed() == 0){ + if(read_hpd_gpio()){ + hdmitx_device->internal_mode_change = 0; + msleep(500); + if(read_hpd_gpio()){ + hdmi_print(IMP, HPD "mux hpd\n"); + digital_clk_on(4); + delay_us(1000*100); + mux_hpd(); + } + } + } + } + else if(cmd == HDMITX_HWCMD_MUX_HPD){ + mux_hpd(); + } +// For test only. + else if(cmd == HDMITX_HWCMD_TURNOFF_HDMIHW){ + int unmux_hpd_flag = argv; +// WRITE_MPEG_REG(VENC_DVI_SETTING, READ_MPEG_REG(VENC_DVI_SETTING)&(~(1<<13))); //bit 13 is used by HDMI only +// digital_clk_on(4); //enable sys clk so that hdmi registers can be accessed when calling phy_pll_off/digit_clk_off + if(unmux_hpd_flag){ + hdmi_print(IMP, SYS "power off hdmi, unmux hpd\n"); + phy_pll_off(); + digital_clk_off(4); //off sys clk + unmux_hpd(); + } + else{ + hdmi_print(IMP, SYS "power off hdmi\n"); + digital_clk_on(6); + phy_pll_off(); //should call digital_clk_on(), otherwise hdmi_rd/wr_reg will hungup + digital_clk_off(3); //do not off sys clk + } +#ifdef CONFIG_HDMI_TX_PHY + digital_clk_off(7); +#endif + } + else if(cmd == HDMITX_HWCMD_TURN_ON_PRBS){ + turn_on_prbs_mode(argv); + } + return 0; +} + +static void hdmitx_print_info(hdmitx_dev_t* hdmitx_device, int printk_flag) +{ + hdmi_print(INF, "------------------\nHdmitx driver version: %s\nSerial %x\nColor Depth %d\n", HDMITX_VER, serial_reg_val, color_depth_f); + hdmi_print(INF, "current vout index %d\n", cur_vout_index); + hdmi_print(INF, "reset sequence %d\n", new_reset_sequence_flag); + hdmi_print(INF, "power mode %d\n", power_mode); + hdmi_print(INF, "%spowerdown when unplug\n",hdmitx_device->unplug_powerdown?"":"do not "); + hdmi_print(INF, "use_tvenc_conf_flag=%d\n",use_tvenc_conf_flag); + hdmi_print(INF, "vdac %s\n", power_off_vdac_flag?"off":"on"); + hdmi_print(INF, "hdmi audio %s\n", hdmi_audio_off_flag?"off":"on"); + if(!hdmi_audio_off_flag){ + hdmi_print(INF, "audio out type %s\n", i2s_to_spdif_flag?"spdif":"i2s"); + } + hdmi_print(INF, "delay flag %d\n", delay_flag); + hdmi_print(INF, "------------------\n"); +} + +static void hdmitx_debug(hdmitx_dev_t* hdmitx_device, const char* buf) +{ + char tmpbuf[128]; + int i=0; + unsigned int adr; + unsigned int value=0; + while((buf[i])&&(buf[i]!=',')&&(buf[i]!=' ')){ + tmpbuf[i]=buf[i]; + i++; + } + tmpbuf[i]=0; + if((strncmp(tmpbuf, "dumpreg", 7)==0) || (strncmp(tmpbuf, "dumptvencreg", 12)==0)){ + hdmitx_dump_tvenc_reg(hdmitx_device->cur_VIC, 1); + return; + } + else if(strncmp(tmpbuf, "ss", 2) == 0) { + printk("hdmitx_device->output_blank_flag: 0x%x\n", hdmitx_device->output_blank_flag); + printk("hdmitx_device->hpd_state: 0x%x\n", hdmitx_device->hpd_state); + printk("hdmitx_device->cur_VIC: 0x%x\n", hdmitx_device->cur_VIC); + } + else if(strncmp(tmpbuf, "hpd_lock", 8) == 0) { + if(tmpbuf[8] == '1') { + hdmitx_device->hpd_lock = 1; + hdmi_print(INF, HPD "hdmitx: lock hpd\n"); + } + else { + hdmitx_device->hpd_lock = 0; + hdmi_print(INF, HPD "hdmitx: unlock hpd\n"); + } + return ; + } + else if(strncmp(tmpbuf, "vic", 3)==0) { + printk("hdmi vic count = %d\n", hdmitx_device->vic_count); + if((tmpbuf[3] >= '0') && (tmpbuf[3] <= '9')){ + hdmitx_device->vic_count = tmpbuf[3] - '0'; + hdmi_print(INF, SYS "set hdmi vic count = %d\n", hdmitx_device->vic_count); + } + } + else if(strncmp(tmpbuf, "cec", 3)==0) { + extern void cec_test_(unsigned int cmd); + cec_test_(tmpbuf[3] - '0'); + } + else if(strncmp(tmpbuf, "dumphdmireg", 11)==0){ + unsigned char reg_val = 0; + unsigned int reg_adr = 0; + for (reg_adr = 0; reg_adr < 0x800; reg_adr ++){ //HDMI Regs address range: 0 ~ 0x7ff + reg_val = hdmi_rd_reg(reg_adr); + hdmi_print(INF, "HDMI[0x%x]: 0x%x\n", reg_adr, reg_val); + } + return ; + } + else if(strncmp(tmpbuf, "dumpcecreg",10) == 0){ + unsigned char cec_val = 0; + unsigned int cec_adr =0; + //HDMI CEC Regs address range:0xc000~0xc01c;0xc080~0xc094 + for(cec_adr = 0xc000; cec_adr < 0xc01d; cec_adr ++){ + cec_val = hdmi_rd_reg(cec_adr); + hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n",cec_adr,cec_val); + } + for(cec_adr = 0xc080; cec_adr < 0xc095; cec_adr ++){ + cec_val = hdmi_rd_reg(cec_adr); + hdmi_print(INF, "HDMI CEC Regs[0x%x]: 0x%x\n",cec_adr,cec_val); + } + return; + } + else if(strncmp(tmpbuf, "dumpcbusreg", 11)==0){ + unsigned j; + adr=simple_strtoul(tmpbuf+11, NULL, 16); //CBUS Start addr + value=simple_strtoul(buf+i+1, NULL, 16); //CBUS End addr + for(j = 0 ; j < value-adr+1 ; j++){ +// printk("CBUS[0x%x]: 0x%x\n", adr+j, READ_MPEG_REG(adr+j)); + hdmi_print(INF, "CBUS[0x%x]: 0x%x\n", adr+j, aml_read_reg32(CBUS_REG_ADDR(adr+j))); + + } + } + else if(strncmp(tmpbuf, "log", 3)==0){ + if(strncmp(tmpbuf+3, "hdcp", 4)==0){ + static unsigned int i = 1; + if(i & 1){ + hdmitx_device->log |= HDMI_LOG_HDCP; + } + else{ + hdmitx_device->log &= ~HDMI_LOG_HDCP; + } + i ++; + } + return ; + } + else if(strncmp(tmpbuf, "pllcalc", 7)==0){ + clk_measure(0xff); + return; + } + else if(strncmp(tmpbuf, "hdmiaudio", 9)==0){ + value=simple_strtoul(tmpbuf+9, NULL, 16); + if(value == 1){ + hdmi_audio_off_flag = 0; + hdmi_audio_init(i2s_to_spdif_flag); + } + else if(value == 0){ + hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets + } + return; + } + else if(strncmp(tmpbuf, "cfgreg", 6)==0){ + adr=simple_strtoul(tmpbuf+6, NULL, 16); + value=simple_strtoul(buf+i+1, NULL, 16); + hdmitx_config_tvenc_reg(hdmitx_device->cur_VIC, adr, value); + return; + } + else if(strncmp(tmpbuf, "tvenc_flag", 10)==0){ + use_tvenc_conf_flag = tmpbuf[10]-'0'; + hdmi_print(INF, "set use_tvenc_conf_flag = %d\n", use_tvenc_conf_flag); + } + else if(strncmp(tmpbuf, "reset", 5)==0){ + if(tmpbuf[5]=='0') + new_reset_sequence_flag=0; + else + new_reset_sequence_flag=1; + return; + } + else if(strncmp(tmpbuf, "delay_flag", 10)==0){ + delay_flag = tmpbuf[10]-'0'; + } + else if(tmpbuf[0]=='v'){ + hdmitx_print_info(hdmitx_device, 1); + return; + } + else if(tmpbuf[0]=='s'){ + serial_reg_val=simple_strtoul(tmpbuf+1,NULL,16); + return; + } + else if(tmpbuf[0]=='c'){ + if(tmpbuf[1]=='d'){ + color_depth_f=simple_strtoul(tmpbuf+2,NULL,10); + if((color_depth_f!=24)&&(color_depth_f!=30)&&(color_depth_f!=36)){ + printk("Color depth %d is not supported\n", color_depth_f); + color_depth_f=0; + } + return; + } + else if(tmpbuf[1]=='s'){ + color_space_f=simple_strtoul(tmpbuf+2,NULL,10); + if(color_space_f>2){ + printk("Color space %d is not supported\n", color_space_f); + color_space_f=0; + } + } + } + else if(strncmp(tmpbuf,"i2s",2)==0){ + if(strncmp(tmpbuf+3,"off",3)==0) + i2s_to_spdif_flag=1; + else + i2s_to_spdif_flag=0; + } + else if(strncmp(tmpbuf, "pattern_on", 10)==0){ + turn_on_shift_pattern(); + hdmi_print(INF, "Shift Pattern On\n"); + return; + } + else if(strncmp(tmpbuf, "pattern_off", 11)==0){ + turn_off_shift_pattern(); + hdmi_print(INF, "Shift Pattern Off\n"); + return; + } + else if(strncmp(tmpbuf, "prbs", 4)==0){ + int prbs_mode =simple_strtoul(tmpbuf+4, NULL, 10); + turn_on_prbs_mode(prbs_mode); + return; + } + else if(tmpbuf[0]=='w'){ + unsigned read_back = 0; + adr=simple_strtoul(tmpbuf+2, NULL, 16); + value=simple_strtoul(buf+i+1, NULL, 16); + if(buf[1]=='h'){ + hdmi_wr_reg(adr, value); + read_back = hdmi_rd_reg(adr); + } + else if(buf[1]=='c'){ + aml_write_reg32(CBUS_REG_ADDR(adr), value); + read_back = aml_read_reg32(CBUS_REG_ADDR(adr)); + + } + else if(buf[1]=='p'){ + aml_write_reg32(APB_REG_ADDR(adr), value); + read_back = aml_read_reg32(APB_REG_ADDR(adr)); + } + hdmi_print(INF, "write %x to %s reg[%x]\n",value,buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr); + //Add read back function in order to judge writting is OK or NG. + hdmi_print(INF, "Read Back %s reg[%x]=%x\n",buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr, read_back); + } + else if(tmpbuf[0]=='r'){ + adr=simple_strtoul(tmpbuf+2, NULL, 16); + if(buf[1]=='h'){ + value = hdmi_rd_reg(adr); + + } + else if(buf[1]=='c'){ + value = aml_read_reg32(CBUS_REG_ADDR(adr)); + } + else if(buf[1]=='p'){ + value = aml_read_reg32(APB_REG_ADDR(adr)); + } + hdmi_print(INF, "%s reg[%x]=%x\n",buf[1]=='p'?"APB":(buf[1]=='h'?"HDMI":"CBUS"), adr, value); + } +} + +static void hdmitx_getediddata(hdmitx_dev_t* hdmitx_device, unsigned int blk_idx) +{ + int ii, jj; + +#ifdef CONFIG_PANEL_IT6681 + hdmitx_device->cur_edid_block = 0; + it6681_read_edid(0, &hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128], 256); + hdmitx_device->cur_edid_block += 2; + printk("%s: get edid from MHL buffer(cur_edid_block=%d)\n", __func__, hdmitx_device->cur_edid_block); +#else + if((hdmitx_device->cur_edid_block+2)<=EDID_MAX_BLOCK){ + if(blk_idx == 0) { + for(jj=0;jj<2;jj++){ + for(ii=0;ii<128;ii++){ + hdmitx_device->EDID_buf[hdmitx_device->cur_edid_block*128+ii] + =hdmi_rd_reg(TX_RX_EDID_OFFSET+hdmitx_device->cur_phy_block_ptr*128+ii); + } + hdmitx_device->cur_edid_block++; + hdmitx_device->cur_phy_block_ptr++; + hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; + } + } + else { + for(jj=0;jj<2;jj++){ + for(ii=0;ii<128;ii++){ + hdmitx_device->EDID_buf1[hdmitx_device->cur_edid_block*128+ii] + =hdmi_rd_reg(TX_RX_EDID_OFFSET+hdmitx_device->cur_phy_block_ptr*128+ii); + } + hdmitx_device->cur_edid_block++; + hdmitx_device->cur_phy_block_ptr++; + hdmitx_device->cur_phy_block_ptr=hdmitx_device->cur_phy_block_ptr&0x3; + } + } + } +#endif +} + +static int hdmitx_cntl_ddc(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) +{ + int i = 0; + unsigned char *tmp_char = NULL; + + if(!(cmd & CMD_DDC_OFFSET)) + hdmi_print(ERR, "ddc: " "w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "ddc: " "cmd 0x%x\n", cmd); + + switch(cmd) { + case DDC_RESET_EDID: + hdmi_tx_gate_pwr_ctrl(EDID_EN, NULL); + hdmi_set_reg_bits(TX_HDCP_EDID_CONFIG, 0, 6, 1); + hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 1, 1, 1); + hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 0, 1, 1); + break; + case DDC_IS_EDID_DATA_READY: + return !!(hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) & (1<<4)); + break; + case DDC_EDID_READ_DATA: + hdmi_set_reg_bits(TX_HDCP_EDID_CONFIG, 1, 6, 1); // Assert sys_trigger_config + break; + case DDC_EDID_GET_DATA: + hdmitx_getediddata(hdmitx_device, argv); + hdmi_tx_gate_pwr_ctrl(EDID_DIS, NULL); + break; + case DDC_PIN_MUX_OP: + if(argv == PIN_MUX) { + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x3, 24, 2); // Mux HDMI SDA(5v)/SCL(5V) + } + if(argv == PIN_UNMUX) { + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x0, 24, 2); // unMux HDMI SDA(5v)/SCL(5V) + } + break; + case DDC_EDID_CLEAR_RAM: + for(i = 0; i < EDID_RAM_ADDR_SIZE; i++) { + hdmi_wr_reg(TX_RX_EDID_OFFSET + i, 0); + } + break; + case DDC_RESET_HDCP: + hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 1, 2, 1); + hdmi_set_reg_bits(TX_SYS5_TX_SOFT_RESET_2, 0, 2, 1); + break; + case DDC_HDCP_OP: + if(argv == HDCP_ON) { + hdmi_tx_gate_pwr_ctrl(HDCP_EN, NULL); + hdmi_set_reg_bits(TX_HDCP_MODE, 1, 7, 1); + } + if(argv == HDCP_OFF) { + hdmi_tx_gate_pwr_ctrl(HDCP_DIS, NULL); + hdmi_set_reg_bits(TX_HDCP_MODE, 0, 7, 1); + } + break; + case DDC_IS_HDCP_ON: + argv = !!((hdmi_rd_reg(TX_HDCP_MODE)) & (1 << 7)); + break; + case DDC_HDCP_GET_AKSV: + tmp_char = (unsigned char *) argv; + for(i = 0; i < 5; i++) { + tmp_char[i] = (unsigned char)hdmi_rd_reg(TX_HDCP_AKSV_SHADOW + 4 - i); + } + break; + case DDC_HDCP_GET_BKSV: + tmp_char = (unsigned char *) argv; + for(i = 0; i < 5; i++) { + tmp_char[i] = (unsigned char)hdmi_rd_reg(TX_HDCP_BKSV_SHADOW + 4 - i); + } + break; + case DDC_HDCP_GET_AUTH: + if((hdmi_rd_reg(TX_HDCP_ST_STATUS_3)&0xa0)==0xa0) { + return 1; + } + else { + return 0; + } + break; + default: + hdmi_print(INF, "ddc: " "unknown cmd: 0x%x\n", cmd); + } + return 1; +} + +// clear hdmi packet configure registers +static void hdmitx_clr_sub_packet(unsigned int reg_base) +{ + int i = 0; + for(i = 0; i < 0x20; i++) { + hdmi_wr_reg(reg_base + i, 0x00); + } +} + +static int hdmitx_cntl_config(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) +{ + if(!(cmd & CMD_CONF_OFFSET)) + hdmi_print(ERR, "config: " "hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "config: " "hdmitx: conf cmd 0x%x\n", cmd); + + switch(cmd) { + case CONF_HDMI_DVI_MODE: + if(argv == HDMI_MODE) { + hdmi_set_reg_bits(TX_TMDS_MODE, 0x3, 6, 2); + } + if(argv == DVI_MODE) { + hdmi_set_reg_bits(TX_VIDEO_DTV_OPTION_L, 0x0, 6, 2); + hdmi_set_reg_bits(TX_TMDS_MODE, 0x2, 6, 2); + } + break; + case CONF_SYSTEM_ST: + return (hdmi_rd_reg(TX_HDCP_ST_EDID_STATUS) >> 6); + break; + case CONF_AUDIO_MUTE_OP: + if(argv == AUDIO_MUTE) { + hdmi_wr_reg(TX_AUDIO_PACK, 0x00); // disable audio sample packets + //hdmi_wr_reg(TX_PACKET_CONTROL_2, hdmi_rd_reg(TX_PACKET_CONTROL_2) | (1<<3)); + } + if((argv == AUDIO_UNMUTE) && (hdmitx_device->tx_aud_cfg != 0)) { + hdmi_wr_reg(TX_AUDIO_PACK, 0x01); + //hdmitx_device->audio_param_update_flag = 1; + } + break; + case CONF_VIDEO_BLANK_OP: + if(argv == VIDEO_BLANK) { + aml_write_reg32(P_VPU_HDMI_DATA_OVR, (0x200 << 20) | (0x0 << 10) | (0x200 << 0)); // set blank CrYCb as 0x200 0x0 0x200 + aml_set_reg32_bits(P_VPU_HDMI_SETTING, 0, 5, 3); // Output data map: CrYCb + aml_set_reg32_bits(P_VPU_HDMI_DATA_OVR, 1, 31, 1); // Enable HDMI data override + } + if(argv == VIDEO_UNBLANK) { + aml_write_reg32(P_VPU_HDMI_DATA_OVR, 0); // Disable HDMI data override + } + break; + case CONF_CLR_AVI_PACKET: + hdmitx_clr_sub_packet(TX_PKT_REG_AVI_INFO_BASE_ADDR); + break; + case CONF_CLR_VSDB_PACKET: + hdmitx_clr_sub_packet(TX_PKT_REG_VEND_INFO_BASE_ADDR); + break; + case CONF_CLR_AUDINFO_PACKET: + hdmitx_clr_sub_packet(TX_PKT_REG_AUDIO_INFO_BASE_ADDR); + break; + default: + hdmi_print(ERR, "config: ""hdmitx: unknown cmd: 0x%x\n", cmd); + } + return 1; +} + +static int hdmitx_cntl_misc(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) +{ + if(!(cmd & CMD_MISC_OFFSET)) + hdmi_print(ERR, "misc: " "hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "misc: " "hdmitx: misc cmd 0x%x\n", cmd); + + switch(cmd) { + case MISC_HPD_MUX_OP: + if(argv == PIN_MUX) { + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x1, 26, 1); // Mux HPD + } + if(argv == PIN_UNMUX) { + aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 0x0, 26, 1); // unMux HPD + } + break; + case MISC_HPD_GPI_ST: + return read_hpd_gpio(); + break; + case MISC_HPLL_OP: + if(argv == HPLL_ENABLE) { + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 30, 1); // disable hpll + } + if(argv == HPLL_DISABLE) { + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 30, 1); // disable hpll + } + break; + case MISC_TMDS_PHY_OP: + if(argv == TMDS_PHY_ENABLE) { + hdmi_phy_wakeup(hdmitx_device); // TODO + } + if(argv == TMDS_PHY_DISABLE) { + hdmi_phy_suspend(); + } + break; + case MISC_VIID_IS_USING: + return !!(aml_read_reg32(P_HHI_VID2_PLL_CNTL) & (1 << 30)); // bit30: enable + break; + default: + hdmi_print(ERR, "misc: " "hdmitx: unknown cmd: 0x%x\n", cmd); + } + return 1; +} + +static int hdmitx_get_state(hdmitx_dev_t* hdmitx_device, unsigned cmd, unsigned argv) +{ + int st = 0; + if(!(cmd & CMD_STAT_OFFSET)) + hdmi_print(ERR, "stat: " "hdmitx: w: invalid cmd 0x%x\n", cmd); + else + hdmi_print(LOW, "stat: " "hdmitx: misc cmd 0x%x\n", cmd); + + switch(cmd) { + case STAT_VIDEO_VIC: + { + /* + * get current video vic directly from VIC packet or VSDB packet + */ + HDMI_Video_Codes_t vic = HDMI_Unkown; + vic = (HDMI_Video_Codes_t)hdmi_rd_reg(TX_PKT_REG_AVI_INFO_BASE_ADDR + 4); + return (int)vic; + } + break; + case STAT_VIDEO_CLK: + break; + case STAT_AUDIO_PACK: + st = (hdmi_rd_reg(STAT_AUDIO_PACK) & 0x1); + return st; + break; + default: + break; + } + return st; +} + +void HDMITX_Meson_Init(hdmitx_dev_t* hdmitx_device) +{ + hdmitx_device->HWOp.SetPacket = hdmitx_set_packet; + hdmitx_device->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; + hdmitx_device->HWOp.SetDispMode = hdmitx_set_dispmode; + hdmitx_device->HWOp.SetAudMode = hdmitx_set_audmode; + hdmitx_device->HWOp.SetupIRQ = hdmitx_setupirq; + hdmitx_device->HWOp.DebugFun = hdmitx_debug; + hdmitx_device->HWOp.UnInit = hdmitx_uninit; + hdmitx_device->HWOp.Cntl = hdmitx_cntl; // todo + hdmitx_device->HWOp.CntlDDC = hdmitx_cntl_ddc; + hdmitx_device->HWOp.GetState = hdmitx_get_state; + hdmitx_device->HWOp.CntlPacket = hdmitx_cntl; + hdmitx_device->HWOp.CntlConfig = hdmitx_cntl_config; + hdmitx_device->HWOp.CntlMisc = hdmitx_cntl_misc; + // 1=Map data pins from Venc to Hdmi Tx as RGB mode. + // -------------------------------------------------------- + // Configure HDMI TX analog, and use HDMI PLL to generate TMDS clock + // -------------------------------------------------------- + // Enable APB3 fail on error +// WRITE_APB_REG(HDMI_CNTL_PORT, READ_APB_REG(HDMI_CNTL_PORT)|(1<<15)); //APB3 err_en +//\\ TODO + //aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 16, 1); // Disable GPIOH_0 internal pull-up register + //aml_write_reg32(P_HHI_HDMI_CLK_CNTL, aml_read_reg32(P_HHI_HDMI_CLK_CNTL)| (1 << 8)); + //aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<15)); //APB3 err_en +// hdmi_wr_reg(0x10, 0xff); + + /**/ + hdmi_hw_init(hdmitx_device); +} + +void hdmi_set_audio_para(int para) +{ + aud_para = para; + +} + +// The following two functions should move to +// static struct platform_driver amhdmitx_driver.suspend & .wakeup +// For tempelet use only. +// Later will change it. +typedef struct +{ + unsigned long reg; + unsigned long val_sleep; + unsigned long val_save; +}hdmi_phy_t; + +static unsigned int hdmi_phy_save = 0x08930e9b; // Default setting + +static void hdmi_phy_suspend(void) +{ + hdmi_phy_save = aml_read_reg32(P_HHI_HDMI_PHY_CNTL0); + aml_write_reg32(P_HHI_HDMI_PHY_CNTL0, 0x08418d00); + //hdmi_print(INF, SYS "phy suspend\n"); +} + +static void hdmi_phy_wakeup(hdmitx_dev_t* hdmitx_device) +{ + hdmitx_set_phy(hdmitx_device); + //hdmi_print(INF, SYS "phy wakeup\n"); +} diff --git a/arch/arm/mach-meson8b/hdmi_tx_hw/tvenc_conf.h b/arch/arm/mach-meson8b/hdmi_tx_hw/tvenc_conf.h index 0be2cfe625b3..204eb88fe089 100644 --- a/arch/arm/mach-meson8b/hdmi_tx_hw/tvenc_conf.h +++ b/arch/arm/mach-meson8b/hdmi_tx_hw/tvenc_conf.h @@ -1,231 +1,231 @@ -typedef struct reg_s { - uint reg; - uint val; -} reg_t; - -static reg_t hdmi_tvenc_regs_480i[] = { - /*1st col: recommmended, but eof/sof/vs_lines +/- 1 from spec; 2nd col: from simu */ - {ENCP_VIDEO_MODE, 0 /*0 */ }, - {ENCI_DE_H_BEGIN, 229 /*0xeb */ }, - {ENCI_DE_H_END, 1669 /*0x68b */ }, - {ENCI_DE_V_BEGIN_EVEN, 18 /*0x11 */ }, - {ENCI_DE_V_END_EVEN, 258 /*0x101 */ }, - {ENCI_DE_V_BEGIN_ODD, 19 /*0x12 */ }, - {ENCI_DE_V_END_ODD, 259 /*0x102 */ }, - {ENCI_DVI_HSO_BEGIN, 1707 /*0x6b1 */ }, - {ENCI_DVI_HSO_END, 115 /*0x79 */ }, - {ENCI_DVI_VSO_BLINE_EVN, 0 /*0x105 */ }, - {ENCI_DVI_VSO_ELINE_EVN, 2 /*0x1 */ }, - {ENCI_DVI_VSO_BEGIN_EVN, 1707 /*0x357 */ }, - {ENCI_DVI_VSO_END_EVN, 1707 /*0x6b1 */ }, - {ENCI_DVI_VSO_BLINE_ODD, 0 /*0x105 */ }, - {ENCI_DVI_VSO_BEGIN_ODD, 849 /*0x6b1 */ }, - {ENCI_DVI_VSO_ELINE_ODD, 3 /*0x2 */ }, - {ENCI_DVI_VSO_END_ODD, 849 /*0x357 */ }, - {VENC_DVI_SETTING, 0x809c /*0x809c*/ }, - {VENC_DVI_SETTING_MORE, 0x0 /*0x0 */ }, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_576i[] = { - {ENCP_VIDEO_MODE, 0x00004000}, - {ENCI_DE_H_BEGIN, 0x000000f9}, - {ENCI_DE_H_END, 0x00000699}, - {ENCI_DE_V_BEGIN_EVEN, 0x00000015}, - {ENCI_DE_V_END_EVEN, 0x00000135}, - {ENCI_DE_V_BEGIN_ODD, 0x00000016}, - {ENCI_DE_V_END_ODD, 0x00000136}, - {ENCI_DVI_HSO_BEGIN, 0x000006b1}, - {ENCI_DVI_HSO_END, 0x0000006f}, - {ENCI_DVI_VSO_BLINE_EVN, 0x00000137}, - {ENCI_DVI_VSO_ELINE_EVN, 0x00000001}, - {ENCI_DVI_VSO_BEGIN_EVN, 0x00000351}, - {ENCI_DVI_VSO_END_EVN, 0x000006b1}, - {ENCI_DVI_VSO_BLINE_ODD, 0x00000137}, - {ENCI_DVI_VSO_BEGIN_ODD, 0x000006b1}, - {ENCI_DVI_VSO_ELINE_ODD, 0x00000002}, - {ENCI_DVI_VSO_END_ODD, 0x00000351}, - {VENC_DVI_SETTING, 0x0000809c}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_1080i[] = { - {ENCP_VIDEO_MODE, 0x00005ffc}, - {ENCP_DE_H_BEGIN, 0x00000210}, - {ENCP_DE_H_END, 0x00001110}, - {ENCP_DE_V_BEGIN_EVEN, 0x00000014}, - {ENCP_DE_V_END_EVEN, 0x00000230}, - {ENCP_DE_V_BEGIN_ODD, 0x00000247}, - {ENCP_DE_V_END_ODD, 0x00000463}, - {ENCP_DVI_HSO_BEGIN, 0x00000090}, - {ENCP_DVI_HSO_END, 0x000000e8}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000090}, - {ENCP_DVI_VSO_END_EVN, 0x00000090}, - {ENCP_DVI_VSO_BLINE_ODD, 0x00000232}, - {ENCP_DVI_VSO_ELINE_ODD, 0x00000237}, - {ENCP_DVI_VSO_BEGIN_ODD, 0x00000928}, - {ENCP_DVI_VSO_END_ODD, 0x00000928}, - {VENC_DVI_SETTING, 0x000080ad}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_1080i50[] = { - {ENCP_VIDEO_MODE, 0x00005ffc}, - {ENCP_DE_H_BEGIN, 0x00000210}, - {ENCP_DE_H_END, 0x00001110}, - {ENCP_DE_V_BEGIN_EVEN, 0x00000014}, - {ENCP_DE_V_END_EVEN, 0x00000230}, - {ENCP_DE_V_BEGIN_ODD, 0x00000247}, - {ENCP_DE_V_END_ODD, 0x00000463}, - {ENCP_DVI_HSO_BEGIN, 0x00000090}, - {ENCP_DVI_HSO_END, 0x000000e8}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000090}, - {ENCP_DVI_VSO_END_EVN, 0x00000090}, - {ENCP_DVI_VSO_BLINE_ODD, 0x00000232}, - {ENCP_DVI_VSO_ELINE_ODD, 0x00000237}, - {ENCP_DVI_VSO_BEGIN_ODD, 0x00000ae0}, - {ENCP_DVI_VSO_END_ODD, 0x00000ae0}, - {VENC_DVI_SETTING, 0x000080ad}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_480p[] = { - {ENCP_VIDEO_MODE, /*0x4000 */ 0x00004000}, - {ENCP_DE_H_BEGIN, /*0xdc */ 0x000000d7}, - {ENCP_DE_H_END, /*0x67c */ 0x00000677}, - {ENCP_DE_V_BEGIN_EVEN, /*0x2a */ 0x0000002b}, - {ENCP_DE_V_END_EVEN, /*0x2a */ 0x0000020b}, - {ENCP_DVI_HSO_BEGIN, /*0x69c */ 0x00000697}, - {ENCP_DVI_HSO_END, /*0x64 */ 0x0000005f}, - {ENCP_DVI_VSO_BLINE_EVN, /*0x5 */ 0x00000006}, - {ENCP_DVI_VSO_ELINE_EVN, /*0xb */ 0x0000000c}, - {ENCP_DVI_VSO_BEGIN_EVN, /*0x69c */ 0x00000697}, - {ENCP_DVI_VSO_END_EVN, /*0x69c */ 0x00000697}, - {VENC_DVI_SETTING_MORE, /*0x0 */ 0x00000000}, - {VENC_DVI_SETTING, /*0x80ad */ 0x000080ad}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_576p[] = { - {ENCP_VIDEO_MODE, 0x00004000}, - {ENCP_DE_H_BEGIN, 0x000000ef}, - {ENCP_DE_H_END, 0x0000068f}, - {ENCP_DE_V_BEGIN_EVEN, 0x0000002d}, - {ENCP_DE_V_END_EVEN, 0x0000026d}, - {ENCP_DVI_HSO_BEGIN, 0x000006a7}, - {ENCP_DVI_HSO_END, 0x00000067}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x000006a7}, - {ENCP_DVI_VSO_END_EVN, 0x000006a7}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {VENC_DVI_SETTING, 0x000080ad}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_720p[] = { - {ENCP_VIDEO_MODE, 0x00004040}, - {ENCP_DE_H_BEGIN, 0x0000028a}, - {ENCP_DE_H_END, 0x00000c8a}, - {ENCP_DE_V_BEGIN_EVEN, 0x0000001d}, - {ENCP_DE_V_END_EVEN, 0x000002ed}, - {ENCP_DVI_HSO_BEGIN, 0x00000082}, - {ENCP_DVI_HSO_END, 0x000000d2}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000004}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000009}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000082}, - {ENCP_DVI_VSO_END_EVN, 0x00000082}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {VENC_DVI_SETTING, 0x000080ad}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_1080p[] = { - {ENCP_VIDEO_MODE, 0x00004040}, - {ENCP_DE_H_BEGIN, 0x00000112}, - {ENCP_DE_H_END, 0x00000892}, - {ENCP_DE_V_BEGIN_EVEN, 0x00000029}, - {ENCP_DE_V_END_EVEN, 0x00000461}, - {ENCP_DVI_HSO_BEGIN, 0x00000052}, - {ENCP_DVI_HSO_END, 0x0000007e}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000052}, - {ENCP_DVI_VSO_END_EVN, 0x00000052}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {VENC_DVI_SETTING, 0x0000809d}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_720p50[] = { - {ENCP_VIDEO_MODE, 0x00004040}, - {ENCP_DE_H_BEGIN, 0x0000028a}, - {ENCP_DE_H_END, 0x00000c8a}, - {ENCP_DE_V_BEGIN_EVEN, 0x0000001d}, - {ENCP_DE_V_END_EVEN, 0x000002ed}, - {ENCP_DVI_HSO_BEGIN, 0x00000082}, - {ENCP_DVI_HSO_END, 0x000000d2}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000004}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000009}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000082}, - {ENCP_DVI_VSO_END_EVN, 0x00000082}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {VENC_DVI_SETTING, 0x000080ad}, - {0,0} -}; - -static reg_t hdmi_tvenc_regs_1080p50[] = { - {ENCP_VIDEO_MODE, 0x00004040}, - {ENCP_DE_H_BEGIN, 0x00000112}, - {ENCP_DE_H_END, 0x00000892}, - {ENCP_DE_V_BEGIN_EVEN, 0x00000029}, - {ENCP_DE_V_END_EVEN, 0x00000461}, - {ENCP_DVI_HSO_BEGIN, 0x00000052}, - {ENCP_DVI_HSO_END, 0x0000007e}, - {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, - {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, - {ENCP_DVI_VSO_BEGIN_EVN, 0x00000052}, - {ENCP_DVI_VSO_END_EVN, 0x00000052}, - {VENC_DVI_SETTING_MORE, 0x00000000}, - {VENC_DVI_SETTING, 0x0000809d}, - {0,0} -}; - -typedef struct hdmi_tvenc_config_ -{ - int vic; - reg_t* reg_set; -}hdmi_tvenc_config_t; - -static const hdmi_tvenc_config_t hdmi_tvenc_configs[] = { - {HDMI_640x480p60 , NULL }, - {HDMI_480p60, hdmi_tvenc_regs_480p}, - {HDMI_480p60_16x9, hdmi_tvenc_regs_480p}, - {HDMI_720p60, hdmi_tvenc_regs_720p}, - {HDMI_1080i60, hdmi_tvenc_regs_1080i}, - {HDMI_480i60, hdmi_tvenc_regs_480i}, - {HDMI_480i60_16x9, hdmi_tvenc_regs_480i}, - {HDMI_1440x480p60 , NULL }, - {HDMI_1440x480p60_16x9 , NULL }, - {HDMI_1080p60 , hdmi_tvenc_regs_1080p}, - {HDMI_576p50, hdmi_tvenc_regs_576p}, - {HDMI_576p50_16x9, hdmi_tvenc_regs_576p}, - {HDMI_720p50, hdmi_tvenc_regs_720p50}, - {HDMI_1080i50, hdmi_tvenc_regs_1080i50}, - {HDMI_576i50, hdmi_tvenc_regs_576i}, - {HDMI_576i50_16x9, hdmi_tvenc_regs_576i}, - {HDMI_1080p50 , hdmi_tvenc_regs_1080p50}, - {HDMI_1080p24, hdmi_tvenc_regs_1080p}, - {HDMI_1080p25, hdmi_tvenc_regs_1080p}, - {HDMI_1080p30, hdmi_tvenc_regs_1080p}, - {HDMI_Unkown, NULL}, -}; - - +typedef struct reg_s { + uint reg; + uint val; +} reg_t; + +static reg_t hdmi_tvenc_regs_480i[] = { + /*1st col: recommmended, but eof/sof/vs_lines +/- 1 from spec; 2nd col: from simu */ + {ENCP_VIDEO_MODE, 0 /*0 */ }, + {ENCI_DE_H_BEGIN, 229 /*0xeb */ }, + {ENCI_DE_H_END, 1669 /*0x68b */ }, + {ENCI_DE_V_BEGIN_EVEN, 18 /*0x11 */ }, + {ENCI_DE_V_END_EVEN, 258 /*0x101 */ }, + {ENCI_DE_V_BEGIN_ODD, 19 /*0x12 */ }, + {ENCI_DE_V_END_ODD, 259 /*0x102 */ }, + {ENCI_DVI_HSO_BEGIN, 1707 /*0x6b1 */ }, + {ENCI_DVI_HSO_END, 115 /*0x79 */ }, + {ENCI_DVI_VSO_BLINE_EVN, 0 /*0x105 */ }, + {ENCI_DVI_VSO_ELINE_EVN, 2 /*0x1 */ }, + {ENCI_DVI_VSO_BEGIN_EVN, 1707 /*0x357 */ }, + {ENCI_DVI_VSO_END_EVN, 1707 /*0x6b1 */ }, + {ENCI_DVI_VSO_BLINE_ODD, 0 /*0x105 */ }, + {ENCI_DVI_VSO_BEGIN_ODD, 849 /*0x6b1 */ }, + {ENCI_DVI_VSO_ELINE_ODD, 3 /*0x2 */ }, + {ENCI_DVI_VSO_END_ODD, 849 /*0x357 */ }, + {VENC_DVI_SETTING, 0x809c /*0x809c*/ }, + {VENC_DVI_SETTING_MORE, 0x0 /*0x0 */ }, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_576i[] = { + {ENCP_VIDEO_MODE, 0x00004000}, + {ENCI_DE_H_BEGIN, 0x000000f9}, + {ENCI_DE_H_END, 0x00000699}, + {ENCI_DE_V_BEGIN_EVEN, 0x00000015}, + {ENCI_DE_V_END_EVEN, 0x00000135}, + {ENCI_DE_V_BEGIN_ODD, 0x00000016}, + {ENCI_DE_V_END_ODD, 0x00000136}, + {ENCI_DVI_HSO_BEGIN, 0x000006b1}, + {ENCI_DVI_HSO_END, 0x0000006f}, + {ENCI_DVI_VSO_BLINE_EVN, 0x00000137}, + {ENCI_DVI_VSO_ELINE_EVN, 0x00000001}, + {ENCI_DVI_VSO_BEGIN_EVN, 0x00000351}, + {ENCI_DVI_VSO_END_EVN, 0x000006b1}, + {ENCI_DVI_VSO_BLINE_ODD, 0x00000137}, + {ENCI_DVI_VSO_BEGIN_ODD, 0x000006b1}, + {ENCI_DVI_VSO_ELINE_ODD, 0x00000002}, + {ENCI_DVI_VSO_END_ODD, 0x00000351}, + {VENC_DVI_SETTING, 0x0000809c}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_1080i[] = { + {ENCP_VIDEO_MODE, 0x00005ffc}, + {ENCP_DE_H_BEGIN, 0x00000210}, + {ENCP_DE_H_END, 0x00001110}, + {ENCP_DE_V_BEGIN_EVEN, 0x00000014}, + {ENCP_DE_V_END_EVEN, 0x00000230}, + {ENCP_DE_V_BEGIN_ODD, 0x00000247}, + {ENCP_DE_V_END_ODD, 0x00000463}, + {ENCP_DVI_HSO_BEGIN, 0x00000090}, + {ENCP_DVI_HSO_END, 0x000000e8}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000090}, + {ENCP_DVI_VSO_END_EVN, 0x00000090}, + {ENCP_DVI_VSO_BLINE_ODD, 0x00000232}, + {ENCP_DVI_VSO_ELINE_ODD, 0x00000237}, + {ENCP_DVI_VSO_BEGIN_ODD, 0x00000928}, + {ENCP_DVI_VSO_END_ODD, 0x00000928}, + {VENC_DVI_SETTING, 0x000080ad}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_1080i50[] = { + {ENCP_VIDEO_MODE, 0x00005ffc}, + {ENCP_DE_H_BEGIN, 0x00000210}, + {ENCP_DE_H_END, 0x00001110}, + {ENCP_DE_V_BEGIN_EVEN, 0x00000014}, + {ENCP_DE_V_END_EVEN, 0x00000230}, + {ENCP_DE_V_BEGIN_ODD, 0x00000247}, + {ENCP_DE_V_END_ODD, 0x00000463}, + {ENCP_DVI_HSO_BEGIN, 0x00000090}, + {ENCP_DVI_HSO_END, 0x000000e8}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000090}, + {ENCP_DVI_VSO_END_EVN, 0x00000090}, + {ENCP_DVI_VSO_BLINE_ODD, 0x00000232}, + {ENCP_DVI_VSO_ELINE_ODD, 0x00000237}, + {ENCP_DVI_VSO_BEGIN_ODD, 0x00000ae0}, + {ENCP_DVI_VSO_END_ODD, 0x00000ae0}, + {VENC_DVI_SETTING, 0x000080ad}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_480p[] = { + {ENCP_VIDEO_MODE, /*0x4000 */ 0x00004000}, + {ENCP_DE_H_BEGIN, /*0xdc */ 0x000000d7}, + {ENCP_DE_H_END, /*0x67c */ 0x00000677}, + {ENCP_DE_V_BEGIN_EVEN, /*0x2a */ 0x0000002b}, + {ENCP_DE_V_END_EVEN, /*0x2a */ 0x0000020b}, + {ENCP_DVI_HSO_BEGIN, /*0x69c */ 0x00000697}, + {ENCP_DVI_HSO_END, /*0x64 */ 0x0000005f}, + {ENCP_DVI_VSO_BLINE_EVN, /*0x5 */ 0x00000006}, + {ENCP_DVI_VSO_ELINE_EVN, /*0xb */ 0x0000000c}, + {ENCP_DVI_VSO_BEGIN_EVN, /*0x69c */ 0x00000697}, + {ENCP_DVI_VSO_END_EVN, /*0x69c */ 0x00000697}, + {VENC_DVI_SETTING_MORE, /*0x0 */ 0x00000000}, + {VENC_DVI_SETTING, /*0x80ad */ 0x000080ad}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_576p[] = { + {ENCP_VIDEO_MODE, 0x00004000}, + {ENCP_DE_H_BEGIN, 0x000000ef}, + {ENCP_DE_H_END, 0x0000068f}, + {ENCP_DE_V_BEGIN_EVEN, 0x0000002d}, + {ENCP_DE_V_END_EVEN, 0x0000026d}, + {ENCP_DVI_HSO_BEGIN, 0x000006a7}, + {ENCP_DVI_HSO_END, 0x00000067}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x000006a7}, + {ENCP_DVI_VSO_END_EVN, 0x000006a7}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {VENC_DVI_SETTING, 0x000080ad}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_720p[] = { + {ENCP_VIDEO_MODE, 0x00004040}, + {ENCP_DE_H_BEGIN, 0x0000028a}, + {ENCP_DE_H_END, 0x00000c8a}, + {ENCP_DE_V_BEGIN_EVEN, 0x0000001d}, + {ENCP_DE_V_END_EVEN, 0x000002ed}, + {ENCP_DVI_HSO_BEGIN, 0x00000082}, + {ENCP_DVI_HSO_END, 0x000000d2}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000004}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000009}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000082}, + {ENCP_DVI_VSO_END_EVN, 0x00000082}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {VENC_DVI_SETTING, 0x000080ad}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_1080p[] = { + {ENCP_VIDEO_MODE, 0x00004040}, + {ENCP_DE_H_BEGIN, 0x00000112}, + {ENCP_DE_H_END, 0x00000892}, + {ENCP_DE_V_BEGIN_EVEN, 0x00000029}, + {ENCP_DE_V_END_EVEN, 0x00000461}, + {ENCP_DVI_HSO_BEGIN, 0x00000052}, + {ENCP_DVI_HSO_END, 0x0000007e}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000052}, + {ENCP_DVI_VSO_END_EVN, 0x00000052}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {VENC_DVI_SETTING, 0x0000809d}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_720p50[] = { + {ENCP_VIDEO_MODE, 0x00004040}, + {ENCP_DE_H_BEGIN, 0x0000028a}, + {ENCP_DE_H_END, 0x00000c8a}, + {ENCP_DE_V_BEGIN_EVEN, 0x0000001d}, + {ENCP_DE_V_END_EVEN, 0x000002ed}, + {ENCP_DVI_HSO_BEGIN, 0x00000082}, + {ENCP_DVI_HSO_END, 0x000000d2}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000004}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000009}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000082}, + {ENCP_DVI_VSO_END_EVN, 0x00000082}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {VENC_DVI_SETTING, 0x000080ad}, + {0,0} +}; + +static reg_t hdmi_tvenc_regs_1080p50[] = { + {ENCP_VIDEO_MODE, 0x00004040}, + {ENCP_DE_H_BEGIN, 0x00000112}, + {ENCP_DE_H_END, 0x00000892}, + {ENCP_DE_V_BEGIN_EVEN, 0x00000029}, + {ENCP_DE_V_END_EVEN, 0x00000461}, + {ENCP_DVI_HSO_BEGIN, 0x00000052}, + {ENCP_DVI_HSO_END, 0x0000007e}, + {ENCP_DVI_VSO_BLINE_EVN, 0x00000000}, + {ENCP_DVI_VSO_ELINE_EVN, 0x00000005}, + {ENCP_DVI_VSO_BEGIN_EVN, 0x00000052}, + {ENCP_DVI_VSO_END_EVN, 0x00000052}, + {VENC_DVI_SETTING_MORE, 0x00000000}, + {VENC_DVI_SETTING, 0x0000809d}, + {0,0} +}; + +typedef struct hdmi_tvenc_config_ +{ + int vic; + reg_t* reg_set; +}hdmi_tvenc_config_t; + +static const hdmi_tvenc_config_t hdmi_tvenc_configs[] = { + {HDMI_640x480p60 , NULL }, + {HDMI_480p60, hdmi_tvenc_regs_480p}, + {HDMI_480p60_16x9, hdmi_tvenc_regs_480p}, + {HDMI_720p60, hdmi_tvenc_regs_720p}, + {HDMI_1080i60, hdmi_tvenc_regs_1080i}, + {HDMI_480i60, hdmi_tvenc_regs_480i}, + {HDMI_480i60_16x9, hdmi_tvenc_regs_480i}, + {HDMI_1440x480p60 , NULL }, + {HDMI_1440x480p60_16x9 , NULL }, + {HDMI_1080p60 , hdmi_tvenc_regs_1080p}, + {HDMI_576p50, hdmi_tvenc_regs_576p}, + {HDMI_576p50_16x9, hdmi_tvenc_regs_576p}, + {HDMI_720p50, hdmi_tvenc_regs_720p50}, + {HDMI_1080i50, hdmi_tvenc_regs_1080i50}, + {HDMI_576i50, hdmi_tvenc_regs_576i}, + {HDMI_576i50_16x9, hdmi_tvenc_regs_576i}, + {HDMI_1080p50 , hdmi_tvenc_regs_1080p50}, + {HDMI_1080p24, hdmi_tvenc_regs_1080p}, + {HDMI_1080p25, hdmi_tvenc_regs_1080p}, + {HDMI_1080p30, hdmi_tvenc_regs_1080p}, + {HDMI_Unkown, NULL}, +}; + + diff --git a/drivers/amlogic/display/vout/enc_clk_config.c b/drivers/amlogic/display/vout/enc_clk_config.c index 16f2d3dcda85..5f9ae886cdee 100755 --- a/drivers/amlogic/display/vout/enc_clk_config.c +++ b/drivers/amlogic/display/vout/enc_clk_config.c @@ -1,671 +1,671 @@ -#include -#include -#include -#include -#include -#include -#include - -#define check_div() \ - if(div == -1)\ - return ;\ - switch(div){\ - case 1:\ - div = 0; break;\ - case 2:\ - div = 1; break;\ - case 4:\ - div = 2; break;\ - case 6:\ - div = 3; break;\ - case 12:\ - div = 4; break;\ - default:\ - break;\ - } - -#define h_delay() \ - do { \ - int i = 1000; \ - while(i--); \ - }while(0) - -#define WAIT_FOR_PLL_LOCKED(reg) \ - do { \ - unsigned int st = 0, cnt = 10; \ - while(cnt --) { \ - msleep_interruptible(10); \ - st = !!(aml_read_reg32(reg) & (1 << 31)); \ - if(st) { \ - break; \ - } \ - else { /* reset pll */ \ - aml_set_reg32_bits(reg, 0x3, 29, 2); \ - aml_set_reg32_bits(reg, 0x2, 29, 2); \ - } \ - } \ - if(cnt < 9) \ - printk(KERN_CRIT "pll[0x%x] reset %d times\n", reg, 9 - cnt);\ - }while(0); - -static void set_hpll_clk_out(unsigned clk) -{ - printk("config HPLL\n"); - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 - if(IS_MESON_M8M2_CPU){ - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); - aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL - switch(clk){ - case 2970: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84e00); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xce49c822); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4123b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); - - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); - printk("waiting HPLL lock\n"); - while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { - ; - } - h_delay(); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); // optimise HPLL VCO 2.97GHz performance - break; - case 2160: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c80000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x0a563823); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0123b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12385); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6001042d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4001042d); - while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { - ; - } - break; - case 1488: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4023d100); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a7ad023); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12286); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); - while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { - ; - } - break; - case 1080: - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); - break; - case 1066: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); - break; - case 1058: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); - break; - case 1086: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); - break; - case 1296: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); - break; - default: - printk("error hpll clk: %d\n", clk); - break; - } - if(clk < 2970) - aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); - } -#endif - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); - aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL - switch(clk){ - case 2160: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c80000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x0a563823); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0123b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12385); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6001042d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4001042d); - WAIT_FOR_PLL_LOCKED(P_HHI_VID_PLL_CNTL); - break; - case 1488: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4023d100); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a7ad023); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12286); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); - WAIT_FOR_PLL_LOCKED(P_HHI_VID_PLL_CNTL); - break; - case 1080: - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); - break; - case 1066: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); - break; - case 1058: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); - break; - case 1086: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); - break; - case 1296: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); - break; - default: - printk("error hpll clk: %d\n", clk); - break; - } - if(clk < 2970) - aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); -#endif - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); - aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL - switch(clk){ - case 2970: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84e00); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xce49c822); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4123b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); - - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); - printk("waiting HPLL lock\n"); - while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { - ; - } - h_delay(); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); // optimise HPLL VCO 2.97GHz performance - break; - case 1488: - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); - printk("waiting HPLL lock[%d]\n", __LINE__); - while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { - ; - } - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); - break; - case 1080: - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); - break; - case 2160: - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000045a); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000045a); - break; - case 1066: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); - break; - case 1058: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); - break; - case 1086: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); - break; - case 1296: - aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); - aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); - aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); - break; - default: - printk("error hpll clk: %d\n", clk); - break; - } - if(clk < 2970) - aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); -#endif - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 - switch(clk){ - case 1488: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); - break; - case 1080: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42d); - break; - case 1066: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); - break; - case 1058: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); - break; - case 1086: - WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); - break; - case 1296: - break; - default: - printk("error hpll clk: %d\n", clk); - break; - } -#endif -#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - // Improve HDMI HPLL Long TIE - if( clk != 1296 ) // 1296MHz is only for 480cvbs/576cvbs on m8 serials, and is not suitable with 0x8a56d023 - aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a56d023); -#endif - printk("config HPLL done\n"); -} - -static void set_hpll_hdmi_od(unsigned div) -{ - switch(div){ - case 1: - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 0, 18, 2); - break; - case 2: - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 18, 2); - break; - case 3: - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 16, 2); - break; - case 4: - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 3, 18, 2); - break; - case 8: - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 16, 2); - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 3, 18, 2); - break; - default: - break; - } -} - -#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 -static void set_hpll_lvds_od(unsigned div) -{ - switch(div) { - case 1: - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 16, 2); - break; - case 2: - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 16, 2); - break; - case 4: - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 2, 16, 2); - break; - case 8: // note: need test - aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 3, 16, 2); - break; - default: - break; - } -} -#endif - -// viu_channel_sel: 1 or 2 -// viu_type_sel: 0: 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. -int set_viu_path(unsigned viu_channel_sel, viu_type_e viu_type_sel) -{ - if((viu_channel_sel > 2) || (viu_channel_sel == 0)) - return -1; -#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - printk("VPU_VIU_VENC_MUX_CTRL: 0x%x\n", aml_read_reg32(P_VPU_VIU_VENC_MUX_CTRL)); - if(viu_channel_sel == 1){ - aml_set_reg32_bits(P_VPU_VIU_VENC_MUX_CTRL, viu_type_sel, 0, 2); - printk("viu chan = 1\n"); - } - else{ - //viu_channel_sel ==2 - aml_set_reg32_bits(P_VPU_VIU_VENC_MUX_CTRL, viu_type_sel, 2, 2); - printk("viu chan = 2\n"); - } - printk("VPU_VIU_VENC_MUX_CTRL: 0x%x\n", aml_read_reg32(P_VPU_VIU_VENC_MUX_CTRL)); -#endif - return 0; -} - -static void set_vid_pll_div(unsigned div) -{ -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 - // Gate disable - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 16, 1); - switch(div){ - case 10: - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 4, 4, 3); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 8, 2); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 12, 3); - break; - case 5: - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 4, 4, 3); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 8, 2); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 12, 3); - break; - default: - break; - } - // Soft Reset div_post/div_pre - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 0, 2); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 3, 1); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 7, 1); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 3, 0, 2); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 3, 1); - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 7, 1); - // Gate enable - WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 16, 1); -#endif -#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - // Gate disable - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 16, 1); - switch(div){ - case 10: - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 4, 4, 3); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 8, 2); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 12, 3); - break; - case 5: - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 4, 4, 3); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 8, 2); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 12, 3); - break; - case 6: - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 5, 4, 3); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 8, 2); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 12, 3); - break; - default: - break; - } - // Soft Reset div_post/div_pre - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 0, 2); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 3, 1); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 7, 1); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 3, 0, 2); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 3, 1); - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 7, 1); - // Gate enable - aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 16, 1); -#endif -} - -static void set_clk_final_div(unsigned div) -{ - if(div == 0) - div = 1; - WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 1, 19, 1); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 0, 16, 3); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div-1, 0, 8); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 7, 0, 3); -} - -static void set_hdmi_tx_pixel_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_HDMI_CLK_CNTL, div, 16, 4); -} -static void set_encp_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 24, 4); -} - -static void set_enci_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 28, 4); -} - -static void set_enct_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 20, 4); -} - -static void set_encl_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 12, 4); -} - -static void set_vdac0_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 28, 4); -} - -static void set_vdac1_div(unsigned div) -{ - check_div(); - WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 24, 4); -} - -// mode hpll_clk_out hpll_hdmi_od viu_path viu_type vid_pll_div clk_final_div -// hdmi_tx_pixel_div unsigned encp_div unsigned enci_div unsigned enct_div unsigned ecnl_div; - -static enc_clk_val_t setting_enc_clk_val_m8m2[] = { - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 - {VMODE_480I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, - {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_480P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, - {VMODE_576I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, - {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_576P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, - {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_30HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_25HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_24HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_SMPTE, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, -#endif -}; -static enc_clk_val_t setting_enc_clk_val[] = { - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B - {VMODE_480I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_576I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, -#endif - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 - {VMODE_480I, 1080, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, - {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480P, 1080, 4, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_480P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, - {VMODE_576I, 1080, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, - {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576P, 1080, 4, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_576P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, - {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_30HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_25HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_24HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_4K2K_SMPTE, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, -#endif - -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 - {VMODE_480I, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480CVBS, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_480P, 1080, 4, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_576I, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576CVBS, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, - {VMODE_576P, 1080, 4, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_720P, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_720P_50HZ, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080I_50HZ, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_50HZ, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_1080P_24HZ, 1488, 2, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, - {VMODE_VGA, 1066, 3, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_SVGA, 1058, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, - {VMODE_XGA, 1085, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, -#endif -}; - -void set_vmode_clk(vmode_t mode) -{ - enc_clk_val_t *p_enc =NULL; - - int i = 0; - int j = 0; - if(IS_MESON_M8M2_CPU){ - p_enc=&setting_enc_clk_val_m8m2[0]; - i = sizeof(setting_enc_clk_val_m8m2) / sizeof(enc_clk_val_t); - }else{ - p_enc=&setting_enc_clk_val[0]; - i = sizeof(setting_enc_clk_val) / sizeof(enc_clk_val_t); - } - printk("mode is: %d\n", mode); - for (j = 0; j < i; j++){ - if(mode == p_enc[j].mode) - break; - } - set_viu_path(p_enc[j].viu_path, p_enc[j].viu_type); - set_hpll_clk_out(p_enc[j].hpll_clk_out); -#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 - set_hpll_lvds_od(p_enc[j].hpll_lvds_od); -#endif - set_hpll_hdmi_od(p_enc[j].hpll_hdmi_od); - set_vid_pll_div(p_enc[j].vid_pll_div); - set_clk_final_div(p_enc[j].clk_final_div); - set_hdmi_tx_pixel_div(p_enc[j].hdmi_tx_pixel_div); - set_encp_div(p_enc[j].encp_div); - set_enci_div(p_enc[j].enci_div); - set_enct_div(p_enc[j].enct_div); - set_encl_div(p_enc[j].encl_div); - set_vdac0_div(p_enc[j].vdac0_div); - set_vdac1_div(p_enc[j].vdac1_div); -#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 - // If VCO outputs 1488, then we will reset it to exact 1485 - // please note, don't forget to re-config CNTL3/4 - if(((READ_CBUS_REG(HHI_VID_PLL_CNTL) & 0x7fff) == 0x43e)||((READ_CBUS_REG(HHI_VID_PLL_CNTL) & 0x7fff) == 0x21ef)) { - WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 0x21ef, 0, 14); - WRITE_CBUS_REG(HHI_VID_PLL_CNTL3, 0x4b525012); - WRITE_CBUS_REG(HHI_VID_PLL_CNTL4, 0x42000101); - } -#endif - -// For debug only -#if 0 - printk("hdmi debug tag\n%s\n%s[%d]\n", __FILE__, __FUNCTION__, __LINE__); -#define P(a) printk("%s 0x%04x: 0x%08x\n", #a, a, READ_CBUS_REG(a)) - P(HHI_VID_PLL_CNTL); - P(HHI_VID_DIVIDER_CNTL); - P(HHI_VID_CLK_CNTL); - P(HHI_VID_CLK_DIV); - P(HHI_HDMI_CLK_CNTL); - P(HHI_VIID_CLK_DIV); -#define PP(a) printk("%s(%d): %d MHz\n", #a, a, clk_util_clk_msr(a)) - PP(CTS_PWM_A_CLK ); - PP(CTS_PWM_B_CLK ); - PP(CTS_PWM_C_CLK ); - PP(CTS_PWM_D_CLK ); - PP(CTS_ETH_RX_TX ); - PP(CTS_PCM_MCLK ); - PP(CTS_PCM_SCLK ); - PP(CTS_VDIN_MEAS_CLK ); - PP(CTS_VDAC_CLK1 ); - PP(CTS_HDMI_TX_PIXEL_CLK); - PP(CTS_MALI_CLK ); - PP(CTS_SDHC_CLK1 ); - PP(CTS_SDHC_CLK0 ); - PP(CTS_AUDAC_CLKPI ); - PP(CTS_A9_CLK ); - PP(CTS_DDR_CLK ); - PP(CTS_VDAC_CLK0 ); - PP(CTS_SAR_ADC_CLK ); - PP(CTS_ENCI_CLK ); - PP(SC_CLK_INT ); - PP(USB_CLK_12MHZ ); - PP(LVDS_FIFO_CLK ); - PP(HDMI_CH3_TMDSCLK ); - PP(MOD_ETH_CLK50_I ); - PP(MOD_AUDIN_AMCLK_I ); - PP(CTS_BTCLK27 ); - PP(CTS_HDMI_SYS_CLK ); - PP(CTS_LED_PLL_CLK ); - PP(CTS_VGHL_PLL_CLK ); - PP(CTS_FEC_CLK_2 ); - PP(CTS_FEC_CLK_1 ); - PP(CTS_FEC_CLK_0 ); - PP(CTS_AMCLK ); - PP(VID2_PLL_CLK ); - PP(CTS_ETH_RMII ); - PP(CTS_ENCT_CLK ); - PP(CTS_ENCL_CLK ); - PP(CTS_ENCP_CLK ); - PP(CLK81 ); - PP(VID_PLL_CLK ); - PP(AUD_PLL_CLK ); - PP(MISC_PLL_CLK ); - PP(DDR_PLL_CLK ); - PP(SYS_PLL_CLK ); - PP(AM_RING_OSC_CLK_OUT1 ); - PP(AM_RING_OSC_CLK_OUT0 ); -#endif -} - +#include +#include +#include +#include +#include +#include +#include + +#define check_div() \ + if(div == -1)\ + return ;\ + switch(div){\ + case 1:\ + div = 0; break;\ + case 2:\ + div = 1; break;\ + case 4:\ + div = 2; break;\ + case 6:\ + div = 3; break;\ + case 12:\ + div = 4; break;\ + default:\ + break;\ + } + +#define h_delay() \ + do { \ + int i = 1000; \ + while(i--); \ + }while(0) + +#define WAIT_FOR_PLL_LOCKED(reg) \ + do { \ + unsigned int st = 0, cnt = 10; \ + while(cnt --) { \ + msleep_interruptible(10); \ + st = !!(aml_read_reg32(reg) & (1 << 31)); \ + if(st) { \ + break; \ + } \ + else { /* reset pll */ \ + aml_set_reg32_bits(reg, 0x3, 29, 2); \ + aml_set_reg32_bits(reg, 0x2, 29, 2); \ + } \ + } \ + if(cnt < 9) \ + printk(KERN_CRIT "pll[0x%x] reset %d times\n", reg, 9 - cnt);\ + }while(0); + +static void set_hpll_clk_out(unsigned clk) +{ + printk("config HPLL\n"); + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 + if(IS_MESON_M8M2_CPU){ + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); + aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL + switch(clk){ + case 2970: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84e00); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xce49c822); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4123b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); + + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); + printk("waiting HPLL lock\n"); + while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { + ; + } + h_delay(); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); // optimise HPLL VCO 2.97GHz performance + break; + case 2160: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c80000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x0a563823); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0123b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12385); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6001042d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4001042d); + while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { + ; + } + break; + case 1488: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4023d100); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a7ad023); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12286); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); + while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { + ; + } + break; + case 1080: + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); + break; + case 1066: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); + break; + case 1058: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); + break; + case 1086: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); + break; + case 1296: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); + break; + default: + printk("error hpll clk: %d\n", clk); + break; + } + if(clk < 2970) + aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); + } +#endif + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); + aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL + switch(clk){ + case 2160: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c80000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x0a563823); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0123b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12385); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6001042d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4001042d); + WAIT_FOR_PLL_LOCKED(P_HHI_VID_PLL_CNTL); + break; + case 1488: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4023d100); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a7ad023); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x12286); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); + WAIT_FOR_PLL_LOCKED(P_HHI_VID_PLL_CNTL); + break; + case 1080: + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); + break; + case 1066: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); + break; + case 1058: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); + break; + case 1086: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); + break; + case 1296: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); + break; + default: + printk("error hpll clk: %d\n", clk); + break; + } + if(clk < 2970) + aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); +#endif + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca563823); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x40238100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012286); + aml_write_reg32(P_HHI_VID2_PLL_CNTL2, 0x430a800); // internal LDO share with HPLL & VIID PLL + switch(clk){ + case 2970: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84e00); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xce49c822); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x4123b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); + + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); + printk("waiting HPLL lock\n"); + while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { + ; + } + h_delay(); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); // optimise HPLL VCO 2.97GHz performance + break; + case 1488: + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000043d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000043d); + printk("waiting HPLL lock[%d]\n", __LINE__); + while(!(aml_read_reg32(P_HHI_VID_PLL_CNTL) & (1 << 31))) { + ; + } + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8ce00); + break; + case 1080: + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000042d); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000042d); + break; + case 2160: + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x6000045a); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4000045a); + break; + case 1066: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); + break; + case 1058: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); + break; + case 1086: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); + break; + case 1296: + aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c88000); + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0xca49b022); + aml_write_reg32(P_HHI_VID_PLL_CNTL4, 0x0023b100); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00012385); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x600c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400c0436); + aml_write_reg32(P_HHI_VID_PLL_CNTL5, 0x00016385); + break; + default: + printk("error hpll clk: %d\n", clk); + break; + } + if(clk < 2970) + aml_write_reg32(P_HHI_VID_PLL_CNTL5, (aml_read_reg32(P_HHI_VID_PLL_CNTL5) & (~(0xf << 12))) | (0x6 << 12)); +#endif + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + switch(clk){ + case 1488: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); + break; + case 1080: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42d); + break; + case 1066: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x42a); + break; + case 1058: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x422); + break; + case 1086: + WRITE_CBUS_REG(HHI_VID_PLL_CNTL, 0x43e); + break; + case 1296: + break; + default: + printk("error hpll clk: %d\n", clk); + break; + } +#endif +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + // Improve HDMI HPLL Long TIE + if( clk != 1296 ) // 1296MHz is only for 480cvbs/576cvbs on m8 serials, and is not suitable with 0x8a56d023 + aml_write_reg32(P_HHI_VID_PLL_CNTL3, 0x8a56d023); +#endif + printk("config HPLL done\n"); +} + +static void set_hpll_hdmi_od(unsigned div) +{ + switch(div){ + case 1: + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 0, 18, 2); + break; + case 2: + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 18, 2); + break; + case 3: + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 16, 2); + break; + case 4: + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 3, 18, 2); + break; + case 8: + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 1, 16, 2); + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 3, 18, 2); + break; + default: + break; + } +} + +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 +static void set_hpll_lvds_od(unsigned div) +{ + switch(div) { + case 1: + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 0, 16, 2); + break; + case 2: + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 1, 16, 2); + break; + case 4: + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 2, 16, 2); + break; + case 8: // note: need test + aml_set_reg32_bits(P_HHI_VID_PLL_CNTL, 3, 16, 2); + break; + default: + break; + } +} +#endif + +// viu_channel_sel: 1 or 2 +// viu_type_sel: 0: 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. +int set_viu_path(unsigned viu_channel_sel, viu_type_e viu_type_sel) +{ + if((viu_channel_sel > 2) || (viu_channel_sel == 0)) + return -1; +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + printk("VPU_VIU_VENC_MUX_CTRL: 0x%x\n", aml_read_reg32(P_VPU_VIU_VENC_MUX_CTRL)); + if(viu_channel_sel == 1){ + aml_set_reg32_bits(P_VPU_VIU_VENC_MUX_CTRL, viu_type_sel, 0, 2); + printk("viu chan = 1\n"); + } + else{ + //viu_channel_sel ==2 + aml_set_reg32_bits(P_VPU_VIU_VENC_MUX_CTRL, viu_type_sel, 2, 2); + printk("viu chan = 2\n"); + } + printk("VPU_VIU_VENC_MUX_CTRL: 0x%x\n", aml_read_reg32(P_VPU_VIU_VENC_MUX_CTRL)); +#endif + return 0; +} + +static void set_vid_pll_div(unsigned div) +{ +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + // Gate disable + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 16, 1); + switch(div){ + case 10: + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 4, 4, 3); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 8, 2); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 12, 3); + break; + case 5: + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 4, 4, 3); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 8, 2); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 12, 3); + break; + default: + break; + } + // Soft Reset div_post/div_pre + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 0, 2); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 3, 1); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 7, 1); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 3, 0, 2); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 3, 1); + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 0, 7, 1); + // Gate enable + WRITE_CBUS_REG_BITS(HHI_VID_DIVIDER_CNTL, 1, 16, 1); +#endif +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + // Gate disable + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 16, 1); + switch(div){ + case 10: + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 4, 4, 3); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 8, 2); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 12, 3); + break; + case 5: + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 4, 4, 3); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 8, 2); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 12, 3); + break; + case 6: + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 5, 4, 3); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 8, 2); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 12, 3); + break; + default: + break; + } + // Soft Reset div_post/div_pre + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 0, 2); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 3, 1); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 7, 1); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 3, 0, 2); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 3, 1); + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 0, 7, 1); + // Gate enable + aml_set_reg32_bits(P_HHI_VID_DIVIDER_CNTL, 1, 16, 1); +#endif +} + +static void set_clk_final_div(unsigned div) +{ + if(div == 0) + div = 1; + WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 1, 19, 1); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 0, 16, 3); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div-1, 0, 8); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_CNTL, 7, 0, 3); +} + +static void set_hdmi_tx_pixel_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_HDMI_CLK_CNTL, div, 16, 4); +} +static void set_encp_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 24, 4); +} + +static void set_enci_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 28, 4); +} + +static void set_enct_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VID_CLK_DIV, div, 20, 4); +} + +static void set_encl_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 12, 4); +} + +static void set_vdac0_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 28, 4); +} + +static void set_vdac1_div(unsigned div) +{ + check_div(); + WRITE_CBUS_REG_BITS(HHI_VIID_CLK_DIV, div, 24, 4); +} + +// mode hpll_clk_out hpll_hdmi_od viu_path viu_type vid_pll_div clk_final_div +// hdmi_tx_pixel_div unsigned encp_div unsigned enci_div unsigned enct_div unsigned ecnl_div; + +static enc_clk_val_t setting_enc_clk_val_m8m2[] = { + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 + {VMODE_480I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, + {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_480P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, + {VMODE_576I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, + {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_576P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, + {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_30HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_25HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_24HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_SMPTE, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, +#endif +}; +static enc_clk_val_t setting_enc_clk_val[] = { + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B + {VMODE_480I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_576I, 2160, 8, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576P, 2160, 8, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, +#endif + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 + {VMODE_480I, 1080, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, + {VMODE_480CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480P, 1080, 4, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_480P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, + {VMODE_576I, 1080, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576I_RPT, 2160, 4, 1, 1, VIU_ENCI, 5, 4, 2,-1, 4, -1, -1, 2, -1}, + {VMODE_576CVBS, 1296, 4, 1, 1, VIU_ENCI, 6, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576P, 1080, 4, 1, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_576P_RPT, 2160, 2, 1, 1, VIU_ENCP, 5, 4, 1, 2, -1, -1, -1, 1, -1}, + {VMODE_720P, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_720P_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I_50HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_50HZ, 1488, 1, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_24HZ, 1488, 2, 1, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_30HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_25HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_24HZ, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_4K2K_SMPTE, 2970, 1, 2, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_VGA, 1066, 3, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_SVGA, 1058, 2, 1, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_XGA, 1085, 1, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, +#endif + +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + {VMODE_480I, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480CVBS, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_480P, 1080, 4, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_576I, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576CVBS, 1080, 4, 1, VIU_ENCI, 5, 4, 2,-1, 2, -1, -1, 2, -1}, + {VMODE_576P, 1080, 4, 1, VIU_ENCP, 5, 4, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_720P, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_720P_50HZ, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080I_50HZ, 1488, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_50HZ, 1488, 1, 1, VIU_ENCP, 10, 1, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_1080P_24HZ, 1488, 2, 1, VIU_ENCP, 10, 2, 1, 1, -1, -1, -1, 1, -1}, + {VMODE_VGA, 1066, 3, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_SVGA, 1058, 2, 1, VIU_ENCP, 10, 1, 2, 1, -1, -1, -1, 1, 1}, + {VMODE_XGA, 1085, 1, 1, VIU_ENCP, 5, 1, 1, 1, -1, -1, -1, 1, 1}, +#endif +}; + +void set_vmode_clk(vmode_t mode) +{ + enc_clk_val_t *p_enc =NULL; + + int i = 0; + int j = 0; + if(IS_MESON_M8M2_CPU){ + p_enc=&setting_enc_clk_val_m8m2[0]; + i = sizeof(setting_enc_clk_val_m8m2) / sizeof(enc_clk_val_t); + }else{ + p_enc=&setting_enc_clk_val[0]; + i = sizeof(setting_enc_clk_val) / sizeof(enc_clk_val_t); + } + printk("mode is: %d\n", mode); + for (j = 0; j < i; j++){ + if(mode == p_enc[j].mode) + break; + } + set_viu_path(p_enc[j].viu_path, p_enc[j].viu_type); + set_hpll_clk_out(p_enc[j].hpll_clk_out); +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + set_hpll_lvds_od(p_enc[j].hpll_lvds_od); +#endif + set_hpll_hdmi_od(p_enc[j].hpll_hdmi_od); + set_vid_pll_div(p_enc[j].vid_pll_div); + set_clk_final_div(p_enc[j].clk_final_div); + set_hdmi_tx_pixel_div(p_enc[j].hdmi_tx_pixel_div); + set_encp_div(p_enc[j].encp_div); + set_enci_div(p_enc[j].enci_div); + set_enct_div(p_enc[j].enct_div); + set_encl_div(p_enc[j].encl_div); + set_vdac0_div(p_enc[j].vdac0_div); + set_vdac1_div(p_enc[j].vdac1_div); +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + // If VCO outputs 1488, then we will reset it to exact 1485 + // please note, don't forget to re-config CNTL3/4 + if(((READ_CBUS_REG(HHI_VID_PLL_CNTL) & 0x7fff) == 0x43e)||((READ_CBUS_REG(HHI_VID_PLL_CNTL) & 0x7fff) == 0x21ef)) { + WRITE_CBUS_REG_BITS(HHI_VID_PLL_CNTL, 0x21ef, 0, 14); + WRITE_CBUS_REG(HHI_VID_PLL_CNTL3, 0x4b525012); + WRITE_CBUS_REG(HHI_VID_PLL_CNTL4, 0x42000101); + } +#endif + +// For debug only +#if 0 + printk("hdmi debug tag\n%s\n%s[%d]\n", __FILE__, __FUNCTION__, __LINE__); +#define P(a) printk("%s 0x%04x: 0x%08x\n", #a, a, READ_CBUS_REG(a)) + P(HHI_VID_PLL_CNTL); + P(HHI_VID_DIVIDER_CNTL); + P(HHI_VID_CLK_CNTL); + P(HHI_VID_CLK_DIV); + P(HHI_HDMI_CLK_CNTL); + P(HHI_VIID_CLK_DIV); +#define PP(a) printk("%s(%d): %d MHz\n", #a, a, clk_util_clk_msr(a)) + PP(CTS_PWM_A_CLK ); + PP(CTS_PWM_B_CLK ); + PP(CTS_PWM_C_CLK ); + PP(CTS_PWM_D_CLK ); + PP(CTS_ETH_RX_TX ); + PP(CTS_PCM_MCLK ); + PP(CTS_PCM_SCLK ); + PP(CTS_VDIN_MEAS_CLK ); + PP(CTS_VDAC_CLK1 ); + PP(CTS_HDMI_TX_PIXEL_CLK); + PP(CTS_MALI_CLK ); + PP(CTS_SDHC_CLK1 ); + PP(CTS_SDHC_CLK0 ); + PP(CTS_AUDAC_CLKPI ); + PP(CTS_A9_CLK ); + PP(CTS_DDR_CLK ); + PP(CTS_VDAC_CLK0 ); + PP(CTS_SAR_ADC_CLK ); + PP(CTS_ENCI_CLK ); + PP(SC_CLK_INT ); + PP(USB_CLK_12MHZ ); + PP(LVDS_FIFO_CLK ); + PP(HDMI_CH3_TMDSCLK ); + PP(MOD_ETH_CLK50_I ); + PP(MOD_AUDIN_AMCLK_I ); + PP(CTS_BTCLK27 ); + PP(CTS_HDMI_SYS_CLK ); + PP(CTS_LED_PLL_CLK ); + PP(CTS_VGHL_PLL_CLK ); + PP(CTS_FEC_CLK_2 ); + PP(CTS_FEC_CLK_1 ); + PP(CTS_FEC_CLK_0 ); + PP(CTS_AMCLK ); + PP(VID2_PLL_CLK ); + PP(CTS_ETH_RMII ); + PP(CTS_ENCT_CLK ); + PP(CTS_ENCL_CLK ); + PP(CTS_ENCP_CLK ); + PP(CLK81 ); + PP(VID_PLL_CLK ); + PP(AUD_PLL_CLK ); + PP(MISC_PLL_CLK ); + PP(DDR_PLL_CLK ); + PP(SYS_PLL_CLK ); + PP(AM_RING_OSC_CLK_OUT1 ); + PP(AM_RING_OSC_CLK_OUT0 ); +#endif +} + diff --git a/drivers/amlogic/display/vout/tvmode.h b/drivers/amlogic/display/vout/tvmode.h index a357eec6f1d9..afaefe0ed2de 100755 --- a/drivers/amlogic/display/vout/tvmode.h +++ b/drivers/amlogic/display/vout/tvmode.h @@ -1,57 +1,57 @@ -/* - * Amlogic Apollo - * frame buffer driver - * - * Copyright (C) 2009 Amlogic, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the named License, - * or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA - * - * Author: Tim Yao - * - */ - -#ifndef TVMODE_H -#define TVMODE_H - -typedef enum { - TVMODE_480I = 0, - TVMODE_480I_RPT , - TVMODE_480CVBS, - TVMODE_480P , - TVMODE_480P_RPT , - TVMODE_576I , - TVMODE_576I_RPT , - TVMODE_576CVBS, - TVMODE_576P , - TVMODE_576P_RPT , - TVMODE_720P , - TVMODE_1080I , - TVMODE_1080P , - TVMODE_720P_50HZ , - TVMODE_1080I_50HZ , - TVMODE_1080P_50HZ , - TVMODE_1080P_24HZ , - TVMODE_4K2K_30HZ , - TVMODE_4K2K_25HZ , - TVMODE_4K2K_24HZ , - TVMODE_4K2K_SMPTE , - TVMODE_VGA , - TVMODE_SVGA, - TVMODE_XGA, - TVMODE_SXGA, - TVMODE_MAX -} tvmode_t; - -#endif /* TVMODE_H */ +/* + * Amlogic Apollo + * frame buffer driver + * + * Copyright (C) 2009 Amlogic, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Tim Yao + * + */ + +#ifndef TVMODE_H +#define TVMODE_H + +typedef enum { + TVMODE_480I = 0, + TVMODE_480I_RPT , + TVMODE_480CVBS, + TVMODE_480P , + TVMODE_480P_RPT , + TVMODE_576I , + TVMODE_576I_RPT , + TVMODE_576CVBS, + TVMODE_576P , + TVMODE_576P_RPT , + TVMODE_720P , + TVMODE_1080I , + TVMODE_1080P , + TVMODE_720P_50HZ , + TVMODE_1080I_50HZ , + TVMODE_1080P_50HZ , + TVMODE_1080P_24HZ , + TVMODE_4K2K_30HZ , + TVMODE_4K2K_25HZ , + TVMODE_4K2K_24HZ , + TVMODE_4K2K_SMPTE , + TVMODE_VGA , + TVMODE_SVGA, + TVMODE_XGA, + TVMODE_SXGA, + TVMODE_MAX +} tvmode_t; + +#endif /* TVMODE_H */ diff --git a/drivers/amlogic/hdmi/hdmi_tx/hdmi_tx_edid.c b/drivers/amlogic/hdmi/hdmi_tx/hdmi_tx_edid.c index 00a7219a861c..dd0aa17ddda2 100755 --- a/drivers/amlogic/hdmi/hdmi_tx/hdmi_tx_edid.c +++ b/drivers/amlogic/hdmi/hdmi_tx/hdmi_tx_edid.c @@ -1,1570 +1,1569 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -//#include "hw/hdmi_tx_reg.h" -#include -#include -#include -#include - -#include -#include - -#define CEA_DATA_BLOCK_COLLECTION_ADDR_1StP 0x04 -#define VIDEO_TAG 0x40 -#define AUDIO_TAG 0x20 -#define VENDOR_TAG 0x60 -#define SPEAKER_TAG 0x80 - - - -#define HDMI_EDID_BLOCK_TYPE_RESERVED 0 -#define HDMI_EDID_BLOCK_TYPE_AUDIO 1 -#define HDMI_EDID_BLOCK_TYPE_VIDEO 2 -#define HDMI_EDID_BLOCK_TYPE_VENDER 3 -#define HDMI_EDID_BLOCK_TYPE_SPEAKER 4 -#define HDMI_EDID_BLOCK_TYPE_VESA 5 -#define HDMI_EDID_BLOCK_TYPE_RESERVED2 6 -#define HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG 7 - -#define EDID_DETAILED_TIMING_DES_BLOCK0_POS 0x36 -#define EDID_DETAILED_TIMING_DES_BLOCK1_POS 0x48 -#define EDID_DETAILED_TIMING_DES_BLOCK2_POS 0x5A -#define EDID_DETAILED_TIMING_DES_BLOCK3_POS 0x6C - - -//----------------------------------------------------------- -static int Edid_DecodeHeader(HDMI_TX_INFO_t *info, unsigned char *buff) -{ - int i, ret = 0; -// UpdateCRC16WithBlock( pCRC16, 8, Data); - if(!(buff[0] | buff[7])) - { - for(i = 1; i < 7; i++){ - if(buff[i]!= 0xFF) - { - info->output_state = CABLE_PLUGIN_DVI_OUT; - ret = -1; - } - } - } - else - { - info->output_state = CABLE_PLUGIN_DVI_OUT; - ret = -1; - } - return ret; -} - -static void Edid_ReceiverBrandNameParse(rx_cap_t * pRxCap, unsigned char * data) -{ - int i; - unsigned char uppercase[26] = { 0 }; - unsigned char brand[3]; - - // Fill array uppercase with 'A' to 'Z' - for(i = 0; i < 26; i++) - uppercase[i] = 'A' + i; - - brand[0] = data[0] >> 2; - brand[1] = ((data[0] & 0x3) << 3) + (data[1] >> 5); - brand[2] = data[1] & 0x1f; - - for(i = 0; i < 3; i++) { - pRxCap->ReceiverBrandName[i] = uppercase[brand[i] - 1]; - } -} - -static int Edid_find_name_block(unsigned char * data) -{ - int ret = 0; - int i; - for(i = 0; i < 3; i++) { - if(data[i]) - return ret; - } - if(data[3] == 0xfc) - ret = 1; - return ret; -} - -static void Edid_ReceiverProductNameParse(rx_cap_t * pRxCap, unsigned char * data) -{ - int i = 0; - while((data[i] != 0x0a) && (data[i] != 0x20) && (i < 13)) { // some Display Product name end with 0x20, not 0x0a - pRxCap->ReceiverProductName[i] = data[i]; - i++; - } - pRxCap->ReceiverProductName[i] = '\0'; -} - -void Edid_DecodeStandardTiming(HDMI_TX_INFO_t * info, unsigned char * Data, unsigned char length) -{ - unsigned char i, TmpVal; - int hor_pixel, frame_rate; - - for(i = 0; i < length; i++ ) - { - if((Data[i*2] != 0x01)&&(Data[i*2 + 1] != 0x01)) //else - { - hor_pixel = (int)((Data[i*2]+31)*8); - TmpVal = Data[i*2 + 1] & 0xC0; - - frame_rate = (int)((Data[i*2 + 1])& 0x3F) + 60; - - if((hor_pixel == 720) && (frame_rate == 30)) - { - info->hdmi_sup_480i = 1; - } - - else if((hor_pixel == 720) && (frame_rate == 25)) - { - info->hdmi_sup_576i = 1; - } - - else if((hor_pixel == 720) && (frame_rate == 60)) - { - info->hdmi_sup_480p = 1; -// if(TmpVal==0x40) -// info->video_480p.support_4_3 = 1; -// else if(TmpVal==0xc0) -// info->video_480p.support_16_9 = 1; - } - - else if((hor_pixel == 720) && (frame_rate == 50)) - { - info->hdmi_sup_576p = 1; - } - - else if((hor_pixel == 1280) && (frame_rate == 60)) - { - info->hdmi_sup_720p_60hz = 1; - } - - else if((hor_pixel == 1280) && (frame_rate == 50)) - { - info->hdmi_sup_720p_50hz = 1; - } - - else if((hor_pixel == 1920) && (frame_rate == 30)) - { - info->hdmi_sup_1080i_60hz = 1; - } - - else if((hor_pixel == 1920) && (frame_rate == 25)) - { - info->hdmi_sup_1080i_50hz = 1; - } - - else if((hor_pixel == 1920) && (frame_rate == 60)) - { - info->hdmi_sup_1080p_60hz = 1; - } - - else if((hor_pixel == 1920) && (frame_rate == 50)) - { - info->hdmi_sup_1080p_50hz = 1; - } - else if((hor_pixel == 1920) && (frame_rate == 24)) - { - info->hdmi_sup_1080p_24hz = 1; - } - else if((hor_pixel == 1920) && (frame_rate == 25)) - { - info->hdmi_sup_1080p_25hz = 1; - } - else if((hor_pixel == 1920) && (frame_rate == 30)) - { - info->hdmi_sup_1080p_30hz = 1; - } - - } - } -} - -static unsigned char Edid_TimingDescriptors[204]= //12x17 - { - //pixel clk --hsync active & blank -- vsync active & blank-- hsync/vsync off & wid -- Image size - 0x8C,0x0A, 0xA0,0x14,0x51, 0xF0,0x16,0x00, 0x26,0x7c,0x43,0x00, //0x13,0x8e, //480i(4:3) - 0x8C,0x0A, 0xA0,0x14,0x51, 0xF0,0x16,0x00, 0x26,0x7c,0x43,0x00, // 0xc4,0x8e, //480i(16:9) - 0x8C,0x0A, 0xA0,0x20,0x51, 0x20,0x18,0x10, 0x18,0x7e,0x23,0x00, // 0x13,0x8e, //576i (4:3) - 0x8C,0x0A, 0xA0,0x20,0x51, 0x20,0x18,0x10, 0x18,0x7e,0x23,0x00, // 0xc4,0x8e, //576i (16:9) - 0x8C,0x0A, 0xD0,0x8A,0x20, 0xE0,0x2D,0x10, 0x10,0x3e,0x96,0x00, // 0x13,0x8e, //480p (4:3) - 0x8C,0x0A, 0xD0,0x8A,0x20, 0xE0,0x2D,0x10, 0x10,0x3e,0x96,0x00, // 0xc4,0x8e, //480p (16:9) - 0x8C,0x0A, 0xD0,0x90,0x20, 0x40,0x31,0x20, 0x0c,0x40,0x55,0x00, // 0x13,0x8e, //576p (4:3) - 0x8C,0x0A, 0xD0,0x90,0x20, 0x40,0x31,0x20, 0x0c,0x40,0x55,0x00, // 0xc4,0x8e, //576p (16:9) - 0x01,0x1D, 0x00,0x72,0x51, 0xD0,0x1E,0x20, 0x6e,0x28,0x55,0x00, // 0xc4,0x8e, //720p60(16:9) - 0x01,0x1D, 0x00,0xBC,0x52, 0xD0,0x1E,0x20, 0xb8,0x28,0x55,0x40, // 0xc4,0x8e, //720p50 (16:9) - 0x01,0x1D, 0x80,0x18,0x71, 0x1C,0x16,0x20, 0x58,0x2c,0x25,0x00, // 0xc4,0x8e, //1080i60 (16:9) - 0x01,0x1D, 0x80,0xD0,0x72, 0x1C,0x16,0x20, 0x10,0x2c,0x25,0x80, // 0xc4,0x8e, //1080i50 (16:9) - 0x02,0x3a, 0x80,0x18,0x71, 0x38,0x2d,0x40, 0x58,0x2c,0x45,0x00, // 0xc4,0x8e, //1080p60 (16:9) - 0x02,0x3a, 0x80,0xD0,0x72, 0x38,0x2d,0x40, 0x10,0x2c,0x45,0x80, // 0xc4,0x8e , //1080p50 (16:9) - 0xfa,0x1c, 0x80,0x3e,0x73, 0x38,0x2d,0x40, 0x7e,0x2c,0x45,0x80, // 0xc4,0x8e, //1080p24 (16:9) - 0x01,0x1D, 0x80,0xD0,0x72, 0x38,0x2d,0x40, 0x10,0x2c,0x45,0x80, // 0xc4,0x8e, //1080p25 (16:9) - 0x01,0x1D, 0x80,0x18,0x71, 0x38,0x2d,0x40, 0x58,0x2c,0x45,0x00, // 0xc4,0x8e, //1080p30 (16:9) - - }; - -//----------------------------------------------------------- -void Edid_CompareTimingDescriptors(HDMI_TX_INFO_t * info, unsigned char *Data) -{ - int index1,index2; - - for(index1=0;index1<17;index1++) - { - for(index2=0;index2<12;index2++) - { - if(Data[index2]!=Edid_TimingDescriptors[index1*14+index2]) - break; - } - if(index2==12) - { - switch(index1) - { - case 0: - case 1: - info->hdmi_sup_480i = 1; - break; - - case 2: - case 3: - info->hdmi_sup_576i = 1; - break; - - case 4: - case 5: - info->hdmi_sup_480p = 1; -// if((Data[12]==Edid_TimingDescriptors[4*14 + 12]) && (Data[13]==Edid_TimingDescriptors[4*14 + 13])) -// info->video_480p.support_4_3 = 1; -// else if((Data[12]==Edid_TimingDescriptors[5*14 + 12]) && (Data[13]==Edid_TimingDescriptors[5*14 + 13])) -// info->video_480p.support_16_9 = 1; - break; - - case 6: - case 7: - info->hdmi_sup_576p = 1; - break; - - case 8: - info->hdmi_sup_720p_60hz = 1; - break; - - case 9: - info->hdmi_sup_720p_50hz = 1; - break; - - case 10: - info->hdmi_sup_1080i_60hz = 1; - break; - - case 11: - info->hdmi_sup_1080i_50hz = 1; - break; - - case 12: - info->hdmi_sup_1080p_60hz = 1; - break; - - case 13: - info->hdmi_sup_1080p_50hz = 1; - break; - - case 14: - info->hdmi_sup_1080p_24hz = 1; - break; - - case 15: - info->hdmi_sup_1080p_25hz = 1; - break; - - case 16: - info->hdmi_sup_1080p_30hz = 1; - break; - default: - break; - } - break; - } - } -} - - -//----------------------------------------------------------- -void Edid_ParseCEADetailedTimingDescriptors(HDMI_TX_INFO_t * info, unsigned char blk_mun, unsigned char BaseAddr, unsigned char *buff) -{ - unsigned char index_edid; - - for( index_edid = 0; index_edid < blk_mun; index_edid++) - { - Edid_CompareTimingDescriptors(info, &buff[BaseAddr]); - BaseAddr += 18; - if((BaseAddr + 18) > 0x7d) //there is not the TimingDescriptors - break; - } - -} -static vsdb_phy_addr_t vsdb_local = {0}; -int get_vsdb_phy_addr(vsdb_phy_addr_t * vsdb) -{ - vsdb = &vsdb_local; - return vsdb->valid; -} - -void set_vsdb_phy_addr(vsdb_phy_addr_t * vsdb, unsigned char *edid_offset) -{ - vsdb->a = (edid_offset[4] >> 4 ) & 0xf; - vsdb->b = (edid_offset[4] >> 0 ) & 0xf; - vsdb->c = (edid_offset[5] >> 4 ) & 0xf; - vsdb->d = (edid_offset[5] >> 0 ) & 0xf; - vsdb_local = *vsdb; - vsdb->valid = 1; -} - -int Edid_Parse_check_HDMI_VSDB(HDMI_TX_INFO_t * info, unsigned char *buff) -{ - unsigned char VSpecificBoundary, BlockAddr, len; - int temp_addr=0; - VSpecificBoundary = buff[2] ; - if(VSpecificBoundary < 4) - { - info->output_state = CABLE_PLUGIN_DVI_OUT; - return -1; - } - BlockAddr = CEA_DATA_BLOCK_COLLECTION_ADDR_1StP; - while( BlockAddr < VSpecificBoundary) { - len = buff[BlockAddr] & 0x1F; - if((buff[BlockAddr] & 0xE0)== VENDOR_TAG){ //find the HDMI Vendor Specific Data Block - break; - } - temp_addr = BlockAddr + len + 1; - if(temp_addr >= VSpecificBoundary) - break; - BlockAddr = BlockAddr + len + 1; - } - - set_vsdb_phy_addr(&info->vsdb_phy_addr, &buff[BlockAddr]); - - if(temp_addr >= VSpecificBoundary) - { - info->output_state = CABLE_PLUGIN_DVI_OUT; - return -1; - } - else - { - if((buff[BlockAddr + 1]!= 0x03)||(buff[BlockAddr + 2]!= 0x0C)||(buff[BlockAddr + 3]!= 0x0)) - { - info->output_state = CABLE_PLUGIN_DVI_OUT; - return -1; - } - } - return 0; -} - -//----------------------------------------------------------- -void Edid_MonitorCapable861(HDMI_TX_INFO_t * info, unsigned char edid_flag) -{ - if(edid_flag & 0x80) - info->support_underscan_flag = 1; - if(edid_flag & 0x40) - info->support_basic_audio_flag =1; - if(edid_flag & 0x20) - { - info->support_ycbcr444_flag =1; -// info->videopath_outindex = 1; // Video Output Color Space Conversion : 0 - RGB out; 1 - YCbr (4:4:4) out; 2 - YCbr (4:2:2) out; - } - if(edid_flag & 0x10) - { - info->support_ycbcr422_flag =1 ; -// if(!(edid_flag & 0x20)) -// info->videopath_outindex = 2; // Video Output Color Space Conversion : 0 - RGB out; 1 - YCbr (4:4:4) out; 2 - YCbr (4:2:2) out; - } -} - - -//----------------------------------------------------------- -static void Edid_ParsingVideoDATABlock(HDMI_TX_INFO_t * info, unsigned char *buff, unsigned char BaseAddr, unsigned char NBytes) -{ - unsigned char i; - NBytes &= 0x1F; - for(i = 0; i < NBytes; i++) - { - switch(buff[i + BaseAddr]&0x7F) - { - case 6: - case 7: - info->hdmi_sup_480i = 1; - break; - - case 21: - case 22: - info->hdmi_sup_576i = 1; - break; - - case 2: - case 3: - info->hdmi_sup_480p = 1; - break; - - case 17: - case 18: - info->hdmi_sup_576p = 1; - break; - - case 4: - info->hdmi_sup_720p_60hz = 1; - break; - - case 19: - info->hdmi_sup_720p_50hz = 1; - break; - - case 5: - info->hdmi_sup_1080i_60hz = 1; - break; - - case 20: - info->hdmi_sup_1080i_50hz = 1; - break; - - case 16: - info->hdmi_sup_1080p_60hz = 1; - break; - - case 31: - info->hdmi_sup_1080p_50hz = 1; - break; - - case 32: - info->hdmi_sup_1080p_24hz = 1; - break; - - case 33: - info->hdmi_sup_1080p_25hz = 1; - break; - case 34: - info->hdmi_sup_1080p_30hz = 1; - break; - default: - break; - } - } -} - -//----------------------------------------------------------- -static void Edid_ParsingAudioDATABlock(HDMI_TX_INFO_t * info, unsigned char *Data, unsigned char BaseAddr, unsigned char NBytes) -{ - unsigned char AudioFormatCode; - int i = BaseAddr ; - NBytes&=0x1F; - do{ - AudioFormatCode = (Data[i]&0xF8)>>3; - switch(AudioFormatCode) - { - case 1: - info->tv_audio_info._60958_PCM.support_flag = 1; - info->tv_audio_info._60958_PCM.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._60958_PCM._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._60958_PCM._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._60958_PCM._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._60958_PCM._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._60958_PCM._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._60958_PCM._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._60958_PCM._32k = 1; - if((Data[i+2]&0x04)) - info->tv_audio_info._60958_PCM._24bit = 1; - if((Data[i+2]&0x02)) - info->tv_audio_info._60958_PCM._20bit = 1; - if((Data[i+2]&0x01)) - info->tv_audio_info._60958_PCM._16bit = 1; - break; - - case 2: - info->tv_audio_info._AC3.support_flag = 1; - info->tv_audio_info._AC3.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._AC3._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._AC3._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._AC3._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._AC3._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._AC3._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._AC3._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._AC3._32k = 1; - info->tv_audio_info._AC3._max_bit = Data[i+2]; - break; - - case 3: - info->tv_audio_info._MPEG1.support_flag = 1; - info->tv_audio_info._MPEG1.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._MPEG1._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._MPEG1._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._MPEG1._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._MPEG1._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._MPEG1._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._MPEG1._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._MPEG1._32k = 1; - info->tv_audio_info._MPEG1._max_bit = Data[i+2]; - break; - - case 4: - info->tv_audio_info._MP3.support_flag = 1; - info->tv_audio_info._MP3.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._MP3._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._MP3._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._MP3._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._MP3._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._MP3._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._MP3._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._MP3._32k = 1; - info->tv_audio_info._MP3._max_bit = Data[i+2]; - break; - - case 5: - info->tv_audio_info._MPEG2.support_flag = 1; - info->tv_audio_info._MPEG2.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._MPEG2._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._MPEG2._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._MPEG2._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._MPEG2._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._MPEG2._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._MPEG2._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._MPEG2._32k = 1; - info->tv_audio_info._MPEG2._max_bit = Data[i+2]; - break; - - case 6: - info->tv_audio_info._AAC.support_flag = 1; - info->tv_audio_info._AAC.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._AAC._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._AAC._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._AAC._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._AAC._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._AAC._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._AAC._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._AAC._32k = 1; - info->tv_audio_info._AAC._max_bit = Data[i+2]; - break; - - case 7: - info->tv_audio_info._DTS.support_flag = 1; - info->tv_audio_info._DTS.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._DTS._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._DTS._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._DTS._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._DTS._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._DTS._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._DTS._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._DTS._32k = 1; - info->tv_audio_info._DTS._max_bit = Data[i+2]; - break; - - case 8: - info->tv_audio_info._ATRAC.support_flag = 1; - info->tv_audio_info._ATRAC.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._ATRAC._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._ATRAC._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._ATRAC._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._ATRAC._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._ATRAC._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._ATRAC._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._ATRAC._32k = 1; - info->tv_audio_info._ATRAC._max_bit = Data[i+2]; - break; - - case 9: - info->tv_audio_info._One_Bit_Audio.support_flag = 1; - info->tv_audio_info._One_Bit_Audio.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._One_Bit_Audio._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._One_Bit_Audio._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._One_Bit_Audio._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._One_Bit_Audio._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._One_Bit_Audio._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._One_Bit_Audio._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._One_Bit_Audio._32k = 1; - info->tv_audio_info._One_Bit_Audio._max_bit = Data[i+2]; - break; - - case 10: - info->tv_audio_info._Dolby.support_flag = 1; - info->tv_audio_info._Dolby.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._Dolby._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._Dolby._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._Dolby._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._Dolby._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._Dolby._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._Dolby._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._Dolby._32k = 1; - info->tv_audio_info._Dolby._max_bit = Data[i+2]; - break; - - case 11: - info->tv_audio_info._DTS_HD.support_flag = 1; - info->tv_audio_info._DTS_HD.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._DTS_HD._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._DTS_HD._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._DTS_HD._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._DTS_HD._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._DTS_HD._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._DTS_HD._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._DTS_HD._32k = 1; - info->tv_audio_info._DTS_HD._max_bit = Data[i+2]; - break; - - - case 12: - info->tv_audio_info._MAT.support_flag = 1; - info->tv_audio_info._MAT.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._MAT._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._MAT._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._MAT._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._MAT._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._MAT._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._MAT._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._MAT._32k = 1; - info->tv_audio_info._MAT._max_bit = Data[i+2]; - break; - - case 13: - info->tv_audio_info._ATRAC.support_flag = 1; - info->tv_audio_info._ATRAC.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._DST._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._DST._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._DST._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._DST._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._DST._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._DST._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._DST._32k = 1; - info->tv_audio_info._DST._max_bit = Data[i+2]; - break; - - case 14: - info->tv_audio_info._WMA.support_flag = 1; - info->tv_audio_info._WMA.max_channel_num = (Data[i]&0x07); - if((Data[i+1]&0x40)) - info->tv_audio_info._WMA._192k = 1; - if((Data[i+1]&0x20)) - info->tv_audio_info._WMA._176k = 1; - if((Data[i+1]&0x10)) - info->tv_audio_info._WMA._96k = 1; - if((Data[i+1]&0x08)) - info->tv_audio_info._WMA._88k = 1; - if((Data[i+1]&0x04)) - info->tv_audio_info._WMA._48k = 1; - if((Data[i+1]&0x02)) - info->tv_audio_info._WMA._44k = 1; - if((Data[i+1]&0x01)) - info->tv_audio_info._WMA._32k = 1; - info->tv_audio_info._WMA._max_bit = Data[i+2]; - break; - - default: - break; - } - i+=3; - }while (i < (NBytes + BaseAddr)); -} - -//----------------------------------------------------------- -static void Edid_ParsingSpeakerDATABlock(HDMI_TX_INFO_t * info, unsigned char *buff, unsigned char BaseAddr) -{ - int ii; - for(ii = 1; ii < 0x80; ) - { - switch(buff[BaseAddr] & ii) - { - case 0x40: - info->tv_audio_info.speaker_allocation.rlc_rrc = 1; - break; - - case 0x20: - info->tv_audio_info.speaker_allocation.flc_frc = 1; - break; - - case 0x10: - info->tv_audio_info.speaker_allocation.rc = 1; - break; - - case 0x08: - info->tv_audio_info.speaker_allocation.rl_rr = 1; - break; - - case 0x04: - info->tv_audio_info.speaker_allocation.fc = 1; - break; - - case 0x02: - info->tv_audio_info.speaker_allocation.lfe = 1; - break; - - case 0x01: - info->tv_audio_info.speaker_allocation.fl_fr = 1; - break; - - default : - break; - } - ii = ii << 1; - } -} - - - -//----------------------------------------------------------- -int Edid_ParsingCEADataBlockCollection(HDMI_TX_INFO_t * info, unsigned char *buff) -{ - unsigned char AddrTag, D, Addr, Data; - int temp_addr; - - D = buff[2]; //Byte number offset d where Detailed Timing data begins - Addr = 4; - - AddrTag = Addr; - do{ - Data = buff[AddrTag]; - switch(Data&0xE0) - { - case VIDEO_TAG: - if((Addr + (Data&0x1f)) < D) - Edid_ParsingVideoDATABlock(info, buff, Addr + 1, (Data & 0x1F) ); - break; - - case AUDIO_TAG: - if((Addr + (Data&0x1f)) < D) - Edid_ParsingAudioDATABlock(info, buff, Addr + 1, (Data & 0x1F) ); - break; - - case SPEAKER_TAG: - if((Addr + (Data&0x1f)) < D) - Edid_ParsingSpeakerDATABlock(info, buff, Addr + 1 ); - break; - - case VENDOR_TAG: - if((Addr + (Data&0x1f)) < D) - { - if((buff[Addr + 1] != 0x03) || (buff[Addr + 2] != 0x0c) || (buff[Addr + 3] != 0x00)) - { - info->auth_state = HDCP_NO_AUTH ; - info->output_state = CABLE_PLUGIN_DVI_OUT; - } - if((Data&0x1f) > 5) - { - //A Source shall not transmit an ISRC1 or ISRC2 Packet to a Sink that does not have Supports_AI = 1 - //International Standard Recording Code (ISRC) - if(buff[Addr + 6] & 0x80) - info->support_ai_flag = 1; - } - } - break; - - default: - break; - } - Addr += ( Data & 0x1F ) ; // next Tag Address - AddrTag = ++Addr; - temp_addr = Addr + ( Data & 0x1F ) ; - if(temp_addr >= D) //force to break; - break; - }while (Addr < D); - - return 0; -} - -//----------------------------------------------------------- - -//parse Sink 3D information -static int hdmitx_edid_3d_parse(rx_cap_t* pRXCap, unsigned char *dat, unsigned size) -{ - int j = 0; - int bit = 16; - unsigned int base = 0; - unsigned int pos = base + 1; - - if(dat[base] & (1<<7)) - pos += 2; - if(dat[base] & (1<<6)) - pos += 2; - if(dat[base] & (1<<5)){ - pRXCap->threeD_present = dat[pos] >> 7; - pRXCap->threeD_Multi_present = (dat[pos] >> 5) & 0x3; - pos += 1; - pRXCap->HDMI_VIC_LEN = (dat[pos] ) >> 5; - pRXCap->HDMI_3D_LEN = (dat[pos] ) & 0x1f; - pos += pRXCap->HDMI_VIC_LEN + 1; - if((pRXCap->threeD_Multi_present == 0x01) || (pRXCap->threeD_Multi_present == 0x2)) { - pRXCap->threeD_Structure_ALL_15_0 = (dat[pos] << 8) + dat[pos+1]; - pos +=2; - } - if(pRXCap->threeD_Multi_present == 0x2) { - pRXCap->threeD_MASK_15_0 = (dat[pos] << 8) + dat[pos+1]; - pos +=2; - } - } - while(pos < size) { - if((dat[pos] & 0xf) == 0x0 ){ // frame packing - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].frame_packing = 1; - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].frame_packing = 1; - } - if((dat[pos] & 0xf) == 0x6 ){ // top and bottom - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].top_and_bottom = 1; - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].top_and_bottom = 1; - } - if((dat[pos] & 0xf) == 0x8 ){ // top and bottom - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].side_by_side = 1; - pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].side_by_side = 1; - } - pos += 2; - } - - while(bit--){ - if(((pRXCap->threeD_MASK_15_0) >> j) & 0x1) - if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 0)) { // frame packing - pRXCap->support_3d_format[pRXCap->VIC[j]].frame_packing = 1; - } - if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 6)) { // top and bottom - pRXCap->support_3d_format[pRXCap->VIC[j]].top_and_bottom = 1; - } - if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 8)) { // top and bottom - pRXCap->support_3d_format[pRXCap->VIC[j]].side_by_side = 1; - } - j++; - } - return 1; -} - -//parse Sink 4k2k information -static void hdmitx_edid_4k2k_parse(rx_cap_t* pRXCap, unsigned char *dat, unsigned size) -{ - if((size > 4) || (size == 0)) { - hdmi_print(ERR, EDID "HDMI: 4k2k in edid out of range, SIZE = %d\n", size); - return; - } - while(size--) { - if(*dat == 1) - pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_30; - else if(*dat == 2) - pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_25; - else if(*dat == 3) - pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_24; - else if(*dat == 4) - pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_smpte_24; - else { - } - dat ++; - pRXCap->VIC_count++ ; - } -} - -static int hdmitx_edid_block_parse(hdmitx_dev_t* hdmitx_device, unsigned char *BlockBuf) -{ - unsigned char offset,End ; - unsigned char count ; - unsigned char tag ; - int i, tmp, idx; - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - - if( BlockBuf[0] != 0x02 ) - return -1 ; // not a CEA BLOCK. - End = BlockBuf[2] ; // CEA description. - pRXCap->native_Mode = BlockBuf[3] ; - - pRXCap->VIC_count = 0 ; - pRXCap->native_VIC = 0xff ; - for( offset = 4 ; offset < End ; ){ - tag = BlockBuf[offset] >> 5 ; - count = BlockBuf[offset] & 0x1f ; - switch( tag ){ - case HDMI_EDID_BLOCK_TYPE_AUDIO: - pRXCap->AUD_count = count/3 ; - offset++ ; - for( i = 0 ; i < pRXCap->AUD_count ; i++) - { - pRXCap->RxAudioCap[i].audio_format_code = (BlockBuf[offset + i * 3]>>3)&0xf; - pRXCap->RxAudioCap[i].channel_num_max = BlockBuf[offset + i * 3]&0x7; - pRXCap->RxAudioCap[i].freq_cc = BlockBuf[offset + i * 3 +1]&0x7f; - pRXCap->RxAudioCap[i].cc3 = BlockBuf[offset + i * 3 + 2]&0x7; - } - offset += count; - break ; - - case HDMI_EDID_BLOCK_TYPE_VIDEO: - offset ++; - for( i = 0 ; i < count ; i++) - { - unsigned char VIC ; - VIC = BlockBuf[offset + i] & (~0x80) ; - pRXCap->VIC[pRXCap->VIC_count] = VIC ; - if( BlockBuf[offset + i] & 0x80 ){ - pRXCap->native_VIC = VIC; - } - pRXCap->VIC_count++ ; - } - offset += count; - break ; - - case HDMI_EDID_BLOCK_TYPE_VENDER: - offset ++ ; - pRXCap->IEEEOUI = (unsigned long)BlockBuf[offset+2] ; - pRXCap->IEEEOUI <<= 8 ; - pRXCap->IEEEOUI += (unsigned long)BlockBuf[offset+1] ; - pRXCap->IEEEOUI <<= 8 ; - pRXCap->IEEEOUI += (unsigned long)BlockBuf[offset] ; - /**/ - hdmi_print(0, "HDMI_EDID_BLOCK_TYPE_VENDER: IEEEOUI %x:", pRXCap->IEEEOUI); - for(i = 0; iColorDeepSupport = (unsigned long)BlockBuf[offset+5]; - pRXCap->Max_TMDS_Clock = (unsigned long)BlockBuf[offset+6]; - if(count > 7) { - tmp = BlockBuf[offset+7]; - idx = offset + 8; - if(tmp & (1<<6)) { - idx += 2; - } - if(tmp & (1<<7)) { - idx += 2; - } - if(tmp & (1<<5)) { - idx += 1; - if(BlockBuf[idx] & 0xe0) { //valid 4k - hdmitx_edid_4k2k_parse(pRXCap, &BlockBuf[idx + 1], BlockBuf[idx] >> 5); - } - if(BlockBuf[idx-1] & 0xe0) { //valid 3D - hdmitx_edid_3d_parse(pRXCap, &BlockBuf[offset+7], count - 7); - } - } - } - offset += count ; // ignore the remaind. - break ; - - case HDMI_EDID_BLOCK_TYPE_SPEAKER: - offset ++ ; - pRXCap->RxSpeakerAllocation = BlockBuf[offset] ; - offset += count; - break ; - - case HDMI_EDID_BLOCK_TYPE_VESA: - offset ++; - offset += count; - break ; - - case HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG: - offset ++; - offset += count; - break ; - - case HDMI_EDID_BLOCK_TYPE_RESERVED: - offset ++; - offset += count; - break; - - case HDMI_EDID_BLOCK_TYPE_RESERVED2: - offset ++; - offset += count; - break; - - default: - break; - } - } - hdmitx_device->vic_count=pRXCap->VIC_count; - return 0 ; -} - -// add default VICs for DVI case -static void hdmitx_edid_set_default_vic(hdmitx_dev_t* hdmitx_device) -{ - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - pRXCap->VIC_count = 0x3; - pRXCap->VIC[0] = 2; - pRXCap->VIC[1] = 4; - pRXCap->VIC[2] = 16; - pRXCap->native_VIC = 4; - hdmitx_device->vic_count = pRXCap->VIC_count; - hdmi_print(IMP, EDID "HDMI: set default vic\n"); -} - -#if 0 -#define PRINT_HASH(hash) {printk("%s:%d ",__func__,__LINE__);int __i;for(__i=0;__i<20;__i++)printk("%02x,",hash[__i]);printk("\n");} -#else -#define PRINT_HASH(hash) -#endif - -static int edid_hash_calc(unsigned char *hash, const char *data, unsigned int len) -{ - struct scatterlist sg; - - struct crypto_hash *tfm; - struct hash_desc desc; - - tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - PRINT_HASH(hash); - if (IS_ERR(tfm)) - return -EINVAL; - - PRINT_HASH(hash); - /* ... set up the scatterlists ... */ - sg_init_one(&sg, (u8 *) data, len); - desc.tfm = tfm; - desc.flags = 0; - - if (crypto_hash_digest(&desc, &sg,len, hash)) - return -EINVAL; - PRINT_HASH(hash); - crypto_free_hash(tfm); - return 1; -} - -static int hdmitx_edid_search_IEEEOUI(char *buf) -{ - int i; - - for(i = 0; i < 125; i++) { - if((buf[i] == 0x03) && (buf[i+1] == 0x0c) && (buf[i+2] == 0x00)) { - return 1; - } - } - return 0; -} - -int hdmitx_edid_parse(hdmitx_dev_t* hdmitx_device) -{ - unsigned char CheckSum ; - unsigned char zero_numbers; - unsigned char BlockCount ; - unsigned char* EDID_buf = hdmitx_device->EDID_buf; - int i, j, ret_val ; - int idx[4]; - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - hdmi_print(0, "EDID Parser:\n"); - - // Calculate the EDID hash for special use - memset(hdmitx_device->EDID_hash, 0, ARRAY_SIZE(hdmitx_device->EDID_hash)); - edid_hash_calc(hdmitx_device->EDID_hash, hdmitx_device->EDID_buf, 256); - - ret_val = Edid_DecodeHeader(&hdmitx_device->hdmi_info, &EDID_buf[0]); - -// if(ret_val == -1) -// return -1; - - for( i = 0, CheckSum = 0 ; i < 128 ; i++ ) - { - CheckSum += EDID_buf[i] ; - CheckSum &= 0xFF ; - } - - if( CheckSum != 0 ) - { - hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; - hdmi_print(0, "PLUGIN_DVI_OUT\n"); -// return -1 ; - } - - Edid_ReceiverBrandNameParse(&hdmitx_device->RXCap, &EDID_buf[8]); - - idx[0] = EDID_DETAILED_TIMING_DES_BLOCK0_POS; - idx[1] = EDID_DETAILED_TIMING_DES_BLOCK1_POS; - idx[2] = EDID_DETAILED_TIMING_DES_BLOCK2_POS; - idx[3] = EDID_DETAILED_TIMING_DES_BLOCK3_POS; - for(i = 0; i < 4; i++) { - if(Edid_find_name_block(&EDID_buf[idx[i]])) - Edid_ReceiverProductNameParse(&hdmitx_device->RXCap, &EDID_buf[idx[i]+5]); - } - Edid_DecodeStandardTiming(&hdmitx_device->hdmi_info, &EDID_buf[26], 8); - Edid_ParseCEADetailedTimingDescriptors(&hdmitx_device->hdmi_info, 4, 0x36, &EDID_buf[0]); - - BlockCount = EDID_buf[0x7E] ; - - if( BlockCount == 0 ){ - hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; - hdmi_print(0, "EDID BlockCount=0\n"); - hdmitx_edid_set_default_vic(hdmitx_device); - - // DVI case judgement: only contains one block and checksum valid - CheckSum = 0; - zero_numbers = 0; - for(i = 0; i < 128; i++) { - CheckSum += EDID_buf[i]; - if(EDID_buf[i] == 0) - zero_numbers ++; - } - hdmi_print(INF, EDID "edid blk0 checksum:%d ext_flag:%d\n",CheckSum, EDID_buf[0x7e]); - if((CheckSum & 0xff) == 0) { - hdmitx_device->RXCap.IEEEOUI = 0; - } else { - hdmitx_device->RXCap.IEEEOUI = 0x0c03; - } - if(zero_numbers > 120) - hdmitx_device->RXCap.IEEEOUI = 0x0c03; - - return 0 ; // do nothing. - } - - if((BlockCount == 1) && (EDID_buf[0x81] == 1)) { // Note: some DVI monitor have more than 1 block - hdmitx_device->RXCap.IEEEOUI = 0; - return 0; - } - - else if ( BlockCount > EDID_MAX_BLOCK ) - { - BlockCount = EDID_MAX_BLOCK ; - } - - for( i = 1 ; i <= BlockCount ; i++ ) - { - - if((BlockCount > 1) && (i == 1)) - { - CheckSum = 0; //ignore the block1 data - } - else - { - if(((BlockCount == 1) && (i == 1)) || ((BlockCount > 1) && (i == 2))) - Edid_Parse_check_HDMI_VSDB( &hdmitx_device->hdmi_info, &EDID_buf[i * 128]); - - for( j = 0, CheckSum = 0 ; j < 128 ; j++ ) - { - CheckSum += EDID_buf[i*128 + j] ; - CheckSum &= 0xFF ; - } - if( CheckSum != 0 ) - { - hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; - } - else - { - Edid_MonitorCapable861(&hdmitx_device->hdmi_info, EDID_buf[i * 128 + 3]); - ret_val = Edid_ParsingCEADataBlockCollection(&hdmitx_device->hdmi_info, &EDID_buf[i * 128]); - Edid_ParseCEADetailedTimingDescriptors(&hdmitx_device->hdmi_info, 5, EDID_buf[i * 128 + 2], &EDID_buf[i * 128]); - if(hdmitx_device->hdmi_info.output_state != CABLE_PLUGIN_DVI_OUT) - hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_HDMI_OUT; - } - - } - - if( EDID_buf[i*128+0] == 0x2 ) - { - if(hdmitx_edid_block_parse(hdmitx_device, &(EDID_buf[i*128]))>=0){ - if(hdmitx_device->RXCap.IEEEOUI==0x0c03){ - break; - } - } - } - } - - if(hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0c03; - printk("hdmitx: edid: find IEEEOUT\n"); - } - else { - pRXCap->IEEEOUI = 0x0; - printk("hdmitx: edid: not find IEEEOUT\n"); - } - - if((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0)|| (pRXCap->VIC_count == 0)){ - hdmitx_edid_set_default_vic(hdmitx_device); - } - -#if 1 - i=hdmitx_edid_dump(hdmitx_device, (char*)(hdmitx_device->tmp_buf), HDMI_TMP_BUF_SIZE); - hdmitx_device->tmp_buf[i]=0; - hdmi_print(0,"\n"); -#endif - return 0; - -} - -typedef struct{ - const char* disp_mode; - HDMI_Video_Codes_t VIC; -}dispmode_vic_t; - -static dispmode_vic_t dispmode_VIC_tab[]= -{ - {"480i_4_3", HDMI_480i60}, - {"480i_rpt", HDMI_480i60_16x9_rpt}, - {"480i", HDMI_480i60_16x9}, - {"480p_4_3", HDMI_480p60}, - {"480p_rpt", HDMI_480p60_16x9_rpt}, - {"480p", HDMI_480p60_16x9}, - {"576i_4_3", HDMI_576i50}, - {"576i_rpt", HDMI_576i50_16x9_rpt}, - {"576i", HDMI_576i50_16x9}, - {"576p_4_3", HDMI_576p50}, - {"576p_rpt", HDMI_576p50_16x9_rpt}, - {"576p", HDMI_576p50_16x9}, - {"720p50hz", HDMI_720p50}, - {"720p", HDMI_720p60}, - {"1080i50hz", HDMI_1080i50}, - {"1080i", HDMI_1080i60}, - {"1080p50hz", HDMI_1080p50}, - {"1080p30hz", HDMI_1080p30}, - {"1080p24hz", HDMI_1080p24}, - {"1080p", HDMI_1080p60}, - {"4k2k30hz", HDMI_4k2k_30}, - {"4k2k25hz", HDMI_4k2k_25}, - {"4k2k24hz", HDMI_4k2k_24}, - {"4k2ksmpte", HDMI_4k2k_smpte_24}, -}; - -int hdmitx_edid_VIC_support(HDMI_Video_Codes_t vic) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { - if(vic == dispmode_VIC_tab[i].VIC) - return 1; - } - - return 0; -} - -HDMI_Video_Codes_t hdmitx_edid_vic_tab_map_vic(const char* disp_mode) -{ - HDMI_Video_Codes_t vic = HDMI_Unkown; - int i; - - for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { - if(strncmp(disp_mode, dispmode_VIC_tab[i].disp_mode, strlen(dispmode_VIC_tab[i].disp_mode))==0) { - vic = dispmode_VIC_tab[i].VIC; - break; - } - } - - if(vic == HDMI_Unkown) - hdmi_print(INF, EDID "not find mapped vic\n"); - - return vic; -} - -const char * hdmitx_edid_vic_tab_map_string(HDMI_Video_Codes_t vic) -{ - int i; - const char * disp_str = NULL; - - for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { - if(vic == dispmode_VIC_tab[i].VIC) { - disp_str = dispmode_VIC_tab[i].disp_mode; - break; - } - } - - if(!disp_str) - hdmi_print(INF, EDID "not find mapped display mode\n"); - - return disp_str; -} - -// force_flag: 0 means check with RX's edid -// 1 means no check wich RX's edid -HDMI_Video_Codes_t hdmitx_edid_get_VIC(hdmitx_dev_t* hdmitx_device, const char* disp_mode, char force_flag) -{ - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - int j; - HDMI_Video_Codes_t vic = hdmitx_edid_vic_tab_map_vic(disp_mode); - - if(vic != HDMI_Unkown) { - if(force_flag == 0) { - for( j = 0 ; j < pRXCap->VIC_count ; j++ ){ - if(pRXCap->VIC[j]==vic) - break; - } - if(j>=pRXCap->VIC_count){ - vic = HDMI_Unkown; - } - } - } - return vic; -} - -const char* hdmitx_edid_get_native_VIC(hdmitx_dev_t* hdmitx_device) -{ - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - - return hdmitx_edid_vic_tab_map_string(pRXCap->native_VIC); -} - -//Clear HDMI Hardware Module EDID RAM and EDID Buffer -void hdmitx_edid_ram_buffer_clear(hdmitx_dev_t* hdmitx_device) -{ - unsigned int i = 0; - - //Clear HDMI Hardware Module EDID RAM - hdmitx_device->HWOp.CntlDDC(hdmitx_device, DDC_EDID_CLEAR_RAM, 0); - - //Clear EDID Buffer - for(i = 0; i < EDID_MAX_BLOCK*128; i++) { - hdmitx_device->EDID_buf[i] = 0; - } - for(i = 0; i < EDID_MAX_BLOCK*128; i++) { - hdmitx_device->EDID_buf1[i] = 0; - } -} - -//Clear the Parse result of HDMI Sink's EDID. -void hdmitx_edid_clear(hdmitx_dev_t* hdmitx_device) -{ - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - hdmitx_device->vic_count=0; - pRXCap->VIC_count = 0; - pRXCap->AUD_count = 0; - // Note: in most cases, we think that rx is tv and the default IEEEOUI is HDMI Identifier - pRXCap->IEEEOUI = 0x000c03; - pRXCap->native_Mode = 0; - pRXCap->native_VIC = 0xff; - pRXCap->RxSpeakerAllocation = 0; - hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; - hdmitx_device->hdmi_info.vsdb_phy_addr.b = 0; - hdmitx_device->hdmi_info.vsdb_phy_addr.c = 0; - hdmitx_device->hdmi_info.vsdb_phy_addr.d = 0; - hdmitx_device->hdmi_info.vsdb_phy_addr.valid = 0; - memset(&vsdb_local, 0, sizeof(vsdb_phy_addr_t)); - pRXCap->Video_Latency = 0; - pRXCap->Audio_Latency = 0; - pRXCap->Interlaced_Video_Latency=0; - pRXCap->Interlaced_Audio_Latency=0; - pRXCap->threeD_present=0; - pRXCap->threeD_Multi_present=0; - pRXCap->HDMI_VIC_LEN=0; - pRXCap->HDMI_3D_LEN=0; - pRXCap->threeD_Structure_ALL_15_0=0; - pRXCap->threeD_MASK_15_0=0; - memset(pRXCap->ReceiverBrandName, 0, sizeof(pRXCap->ReceiverBrandName)); - memset(pRXCap->ReceiverProductName, 0, sizeof(pRXCap->ReceiverProductName)); - memset(&hdmitx_device->RXCap.support_3d_format[0], 0, sizeof(hdmitx_device->RXCap.support_3d_format)); - memset(&hdmitx_device->EDID_hash[0], 0, sizeof(hdmitx_device->EDID_hash)); -} - -/* - * print one block data of edid - */ -static void hdmitx_edid_blk_print(unsigned char *blk, unsigned int blk_idx) -{ - unsigned int i; - hdmi_print(INF, EDID "blk%d raw data\n", blk_idx); - for(i = 0; i < 128; i++) { - printk("%02x", blk[i]); - if(((i+1) & 0x1f) == 0) // print 32bytes a line - printk("\n"); - } - printk("\n"); -} - -/* - * check EDID buf contains valid block numbers - */ -static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf) -{ - unsigned int valid_blk_no = 0; - unsigned int i = 0, j = 0; - unsigned int tmp_chksum = 0; - for(j = 0; j < EDID_MAX_BLOCK; j++) { - for(i = 0; i < 128; i++) { - tmp_chksum += buf[i + j*128]; - } - if(tmp_chksum !=0) { - valid_blk_no ++; - if((tmp_chksum & 0xff) == 0) { - hdmi_print(INF, EDID "check sum valid\n"); - } - else { - hdmi_print(INF, EDID "check sum invalid\n"); - } - } - tmp_chksum = 0; - } - return valid_blk_no; -} - -/* - * suppose DDC read EDID two times successfully, - * then compare EDID_buf and EDID_buf1. - * if same, just print out EDID_buf raw data, else print out 2 buffers - */ -void hdmitx_edid_buf_compare_print(hdmitx_dev_t* hdmitx_device) -{ - unsigned int i = 0; - unsigned int err_no = 0; - unsigned char *buf0 = hdmitx_device->EDID_buf; - unsigned char *buf1 = hdmitx_device->EDID_buf1; - unsigned int valid_blk_no = 0; - unsigned int blk_idx = 0; - - for(i = 0; i < EDID_MAX_BLOCK*128; i++) { - if(buf0[i] != buf1[i]) { - err_no ++; - } - } - - if(err_no == 0) { - // calculate valid edid block numbers - valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); - - if(valid_blk_no == 0) { - hdmi_print(ERR, EDID "raw data are all zeroes\n"); - } - else { - for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { - hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx); - } - } - } - else { - hdmi_print(ERR, EDID "%d errors between two reading\n", err_no); - valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); - for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { - hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx); - } - - valid_blk_no = hdmitx_edid_check_valid_blocks(buf1); - for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { - hdmitx_edid_blk_print(&buf1[blk_idx*128], blk_idx); - } - } -} - -int hdmitx_edid_dump(hdmitx_dev_t* hdmitx_device, char* buffer, int buffer_len) -{ - int i,pos=0; - rx_cap_t* pRXCap = &(hdmitx_device->RXCap); - - pos+=snprintf(buffer+pos, buffer_len-pos, "Receiver Brand Name: %s\r\n", pRXCap->ReceiverBrandName); - pos+=snprintf(buffer+pos, buffer_len-pos, "Receiver Product Name: %s\r\n", pRXCap->ReceiverProductName); - - pos+=snprintf(buffer+pos, buffer_len-pos, "EDID block number: 0x%x\r\n",hdmitx_device->EDID_buf[0x7e]); - - pos+=snprintf(buffer+pos, buffer_len-pos, "Source Physical Address[a.b.c.d]: %x.%x.%x.%x\r\n", - hdmitx_device->hdmi_info.vsdb_phy_addr.a, hdmitx_device->hdmi_info.vsdb_phy_addr.b, hdmitx_device->hdmi_info.vsdb_phy_addr.c, hdmitx_device->hdmi_info.vsdb_phy_addr.d); - - pos+=snprintf(buffer+pos, buffer_len-pos, "native Mode %x, VIC (native %d):\r\n", - pRXCap->native_Mode, pRXCap->native_VIC); - - pos+=snprintf(buffer+pos, buffer_len-pos, "ColorDeepSupport %x, MaxTMDSClock %d\r\n", - pRXCap->ColorDeepSupport, pRXCap->Max_TMDS_Clock); - - for( i = 0 ; i < pRXCap->VIC_count ; i++ ) - { - pos+=snprintf(buffer+pos, buffer_len-pos,"%d ", pRXCap->VIC[i]); - } - pos+=snprintf(buffer+pos, buffer_len-pos,"\r\n"); - pos+=snprintf(buffer+pos, buffer_len-pos, "Audio {format, channel, freq, cce}\r\n"); - for(i = 0; i< pRXCap->AUD_count; i++) { - pos+=snprintf(buffer+pos, buffer_len-pos, "{%d, %d, %x, %x}\r\n", pRXCap->RxAudioCap[i].audio_format_code, - pRXCap->RxAudioCap[i].channel_num_max, pRXCap->RxAudioCap[i].freq_cc, pRXCap->RxAudioCap[i].cc3); - } - pos+=snprintf(buffer+pos,buffer_len-pos,"Speaker Allocation: %x\r\n", pRXCap->RxSpeakerAllocation); - pos+=snprintf(buffer+pos,buffer_len-pos,"Vendor: %x\r\n", pRXCap->IEEEOUI); - - pos+=snprintf(buffer+pos,buffer_len-pos,"Rx 3D Format Support List:\r\n{VIC FramePacking TopBottom SidebySide}\r\n"); - for(i = 0 ; i < pRXCap->VIC_count; i++){ - pos+=snprintf(buffer+pos,buffer_len-pos,"{ %d\t%d\t%d\t%d }\n", pRXCap->VIC[i], - pRXCap->support_3d_format[pRXCap->VIC[i]].frame_packing, - pRXCap->support_3d_format[pRXCap->VIC[i]].top_and_bottom, - pRXCap->support_3d_format[pRXCap->VIC[i]].side_by_side); - } - return pos; -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +//#include "hw/hdmi_tx_reg.h" +#include +#include +#include +#include + +#include +#include + +#define CEA_DATA_BLOCK_COLLECTION_ADDR_1StP 0x04 +#define VIDEO_TAG 0x40 +#define AUDIO_TAG 0x20 +#define VENDOR_TAG 0x60 +#define SPEAKER_TAG 0x80 + + + +#define HDMI_EDID_BLOCK_TYPE_RESERVED 0 +#define HDMI_EDID_BLOCK_TYPE_AUDIO 1 +#define HDMI_EDID_BLOCK_TYPE_VIDEO 2 +#define HDMI_EDID_BLOCK_TYPE_VENDER 3 +#define HDMI_EDID_BLOCK_TYPE_SPEAKER 4 +#define HDMI_EDID_BLOCK_TYPE_VESA 5 +#define HDMI_EDID_BLOCK_TYPE_RESERVED2 6 +#define HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG 7 + +#define EDID_DETAILED_TIMING_DES_BLOCK0_POS 0x36 +#define EDID_DETAILED_TIMING_DES_BLOCK1_POS 0x48 +#define EDID_DETAILED_TIMING_DES_BLOCK2_POS 0x5A +#define EDID_DETAILED_TIMING_DES_BLOCK3_POS 0x6C + + +//----------------------------------------------------------- +static int Edid_DecodeHeader(HDMI_TX_INFO_t *info, unsigned char *buff) +{ + int i, ret = 0; +// UpdateCRC16WithBlock( pCRC16, 8, Data); + if(!(buff[0] | buff[7])) + { + for(i = 1; i < 7; i++){ + if(buff[i]!= 0xFF) + { + info->output_state = CABLE_PLUGIN_DVI_OUT; + ret = -1; + } + } + } + else + { + info->output_state = CABLE_PLUGIN_DVI_OUT; + ret = -1; + } + return ret; +} + +static void Edid_ReceiverBrandNameParse(rx_cap_t * pRxCap, unsigned char * data) +{ + int i; + unsigned char uppercase[26] = { 0 }; + unsigned char brand[3]; + + // Fill array uppercase with 'A' to 'Z' + for(i = 0; i < 26; i++) + uppercase[i] = 'A' + i; + + brand[0] = data[0] >> 2; + brand[1] = ((data[0] & 0x3) << 3) + (data[1] >> 5); + brand[2] = data[1] & 0x1f; + + for(i = 0; i < 3; i++) { + pRxCap->ReceiverBrandName[i] = uppercase[brand[i] - 1]; + } +} + +static int Edid_find_name_block(unsigned char * data) +{ + int ret = 0; + int i; + for(i = 0; i < 3; i++) { + if(data[i]) + return ret; + } + if(data[3] == 0xfc) + ret = 1; + return ret; +} + +static void Edid_ReceiverProductNameParse(rx_cap_t * pRxCap, unsigned char * data) +{ + int i = 0; + while((data[i] != 0x0a) && (data[i] != 0x20) && (i < 13)) { // some Display Product name end with 0x20, not 0x0a + pRxCap->ReceiverProductName[i] = data[i]; + i++; + } + pRxCap->ReceiverProductName[i] = '\0'; +} + +void Edid_DecodeStandardTiming(HDMI_TX_INFO_t * info, unsigned char * Data, unsigned char length) +{ + unsigned char i, TmpVal; + int hor_pixel, frame_rate; + + for(i = 0; i < length; i++ ) + { + if((Data[i*2] != 0x01)&&(Data[i*2 + 1] != 0x01)) //else + { + hor_pixel = (int)((Data[i*2]+31)*8); + TmpVal = Data[i*2 + 1] & 0xC0; + + frame_rate = (int)((Data[i*2 + 1])& 0x3F) + 60; + + if((hor_pixel == 720) && (frame_rate == 30)) + { + info->hdmi_sup_480i = 1; + } + + else if((hor_pixel == 720) && (frame_rate == 25)) + { + info->hdmi_sup_576i = 1; + } + + else if((hor_pixel == 720) && (frame_rate == 60)) + { + info->hdmi_sup_480p = 1; +// if(TmpVal==0x40) +// info->video_480p.support_4_3 = 1; +// else if(TmpVal==0xc0) +// info->video_480p.support_16_9 = 1; + } + + else if((hor_pixel == 720) && (frame_rate == 50)) + { + info->hdmi_sup_576p = 1; + } + + else if((hor_pixel == 1280) && (frame_rate == 60)) + { + info->hdmi_sup_720p_60hz = 1; + } + + else if((hor_pixel == 1280) && (frame_rate == 50)) + { + info->hdmi_sup_720p_50hz = 1; + } + + else if((hor_pixel == 1920) && (frame_rate == 30)) + { + info->hdmi_sup_1080i_60hz = 1; + } + + else if((hor_pixel == 1920) && (frame_rate == 25)) + { + info->hdmi_sup_1080i_50hz = 1; + } + + else if((hor_pixel == 1920) && (frame_rate == 60)) + { + info->hdmi_sup_1080p_60hz = 1; + } + + else if((hor_pixel == 1920) && (frame_rate == 50)) + { + info->hdmi_sup_1080p_50hz = 1; + } + else if((hor_pixel == 1920) && (frame_rate == 24)) + { + info->hdmi_sup_1080p_24hz = 1; + } + else if((hor_pixel == 1920) && (frame_rate == 25)) + { + info->hdmi_sup_1080p_25hz = 1; + } + else if((hor_pixel == 1920) && (frame_rate == 30)) + { + info->hdmi_sup_1080p_30hz = 1; + } + + } + } +} + +static unsigned char Edid_TimingDescriptors[204]= //12x17 + { + //pixel clk --hsync active & blank -- vsync active & blank-- hsync/vsync off & wid -- Image size + 0x8C,0x0A, 0xA0,0x14,0x51, 0xF0,0x16,0x00, 0x26,0x7c,0x43,0x00, //0x13,0x8e, //480i(4:3) + 0x8C,0x0A, 0xA0,0x14,0x51, 0xF0,0x16,0x00, 0x26,0x7c,0x43,0x00, // 0xc4,0x8e, //480i(16:9) + 0x8C,0x0A, 0xA0,0x20,0x51, 0x20,0x18,0x10, 0x18,0x7e,0x23,0x00, // 0x13,0x8e, //576i (4:3) + 0x8C,0x0A, 0xA0,0x20,0x51, 0x20,0x18,0x10, 0x18,0x7e,0x23,0x00, // 0xc4,0x8e, //576i (16:9) + 0x8C,0x0A, 0xD0,0x8A,0x20, 0xE0,0x2D,0x10, 0x10,0x3e,0x96,0x00, // 0x13,0x8e, //480p (4:3) + 0x8C,0x0A, 0xD0,0x8A,0x20, 0xE0,0x2D,0x10, 0x10,0x3e,0x96,0x00, // 0xc4,0x8e, //480p (16:9) + 0x8C,0x0A, 0xD0,0x90,0x20, 0x40,0x31,0x20, 0x0c,0x40,0x55,0x00, // 0x13,0x8e, //576p (4:3) + 0x8C,0x0A, 0xD0,0x90,0x20, 0x40,0x31,0x20, 0x0c,0x40,0x55,0x00, // 0xc4,0x8e, //576p (16:9) + 0x01,0x1D, 0x00,0x72,0x51, 0xD0,0x1E,0x20, 0x6e,0x28,0x55,0x00, // 0xc4,0x8e, //720p60(16:9) + 0x01,0x1D, 0x00,0xBC,0x52, 0xD0,0x1E,0x20, 0xb8,0x28,0x55,0x40, // 0xc4,0x8e, //720p50 (16:9) + 0x01,0x1D, 0x80,0x18,0x71, 0x1C,0x16,0x20, 0x58,0x2c,0x25,0x00, // 0xc4,0x8e, //1080i60 (16:9) + 0x01,0x1D, 0x80,0xD0,0x72, 0x1C,0x16,0x20, 0x10,0x2c,0x25,0x80, // 0xc4,0x8e, //1080i50 (16:9) + 0x02,0x3a, 0x80,0x18,0x71, 0x38,0x2d,0x40, 0x58,0x2c,0x45,0x00, // 0xc4,0x8e, //1080p60 (16:9) + 0x02,0x3a, 0x80,0xD0,0x72, 0x38,0x2d,0x40, 0x10,0x2c,0x45,0x80, // 0xc4,0x8e , //1080p50 (16:9) + 0xfa,0x1c, 0x80,0x3e,0x73, 0x38,0x2d,0x40, 0x7e,0x2c,0x45,0x80, // 0xc4,0x8e, //1080p24 (16:9) + 0x01,0x1D, 0x80,0xD0,0x72, 0x38,0x2d,0x40, 0x10,0x2c,0x45,0x80, // 0xc4,0x8e, //1080p25 (16:9) + 0x01,0x1D, 0x80,0x18,0x71, 0x38,0x2d,0x40, 0x58,0x2c,0x45,0x00, // 0xc4,0x8e, //1080p30 (16:9) + + }; + +//----------------------------------------------------------- +void Edid_CompareTimingDescriptors(HDMI_TX_INFO_t * info, unsigned char *Data) +{ + int index1,index2; + + for(index1=0;index1<17;index1++) + { + for(index2=0;index2<12;index2++) + { + if(Data[index2]!=Edid_TimingDescriptors[index1*12+index2]) + break; + } + if(index2==12) + { + switch(index1) + { + case 0: + case 1: + info->hdmi_sup_480i = 1; + break; + + case 2: + case 3: + info->hdmi_sup_576i = 1; + break; + + case 4: + case 5: + info->hdmi_sup_480p = 1; +// if((Data[12]==Edid_TimingDescriptors[4*14 + 12]) && (Data[13]==Edid_TimingDescriptors[4*14 + 13])) +// info->video_480p.support_4_3 = 1; +// else if((Data[12]==Edid_TimingDescriptors[5*14 + 12]) && (Data[13]==Edid_TimingDescriptors[5*14 + 13])) +// info->video_480p.support_16_9 = 1; + break; + + case 6: + case 7: + info->hdmi_sup_576p = 1; + break; + + case 8: + info->hdmi_sup_720p_60hz = 1; + break; + + case 9: + info->hdmi_sup_720p_50hz = 1; + break; + + case 10: + info->hdmi_sup_1080i_60hz = 1; + break; + + case 11: + info->hdmi_sup_1080i_50hz = 1; + break; + + case 12: + info->hdmi_sup_1080p_60hz = 1; + break; + + case 13: + info->hdmi_sup_1080p_50hz = 1; + break; + + case 14: + info->hdmi_sup_1080p_24hz = 1; + break; + + case 15: + info->hdmi_sup_1080p_25hz = 1; + break; + + case 16: + info->hdmi_sup_1080p_30hz = 1; + break; + default: + break; + } + break; + } + } +} + + +//----------------------------------------------------------- +void Edid_ParseCEADetailedTimingDescriptors(HDMI_TX_INFO_t * info, unsigned char blk_mun, unsigned char BaseAddr, unsigned char *buff) +{ + unsigned char index_edid; + + for( index_edid = 0; index_edid < blk_mun; index_edid++) + { + Edid_CompareTimingDescriptors(info, &buff[BaseAddr]); + BaseAddr += 18; + if((BaseAddr + 18) > 0x7d) //there is not the TimingDescriptors + break; + } + +} +static vsdb_phy_addr_t vsdb_local = {0}; +int get_vsdb_phy_addr(vsdb_phy_addr_t * vsdb) +{ + vsdb = &vsdb_local; + return vsdb->valid; +} + +void set_vsdb_phy_addr(vsdb_phy_addr_t * vsdb, unsigned char *edid_offset) +{ + vsdb->a = (edid_offset[4] >> 4 ) & 0xf; + vsdb->b = (edid_offset[4] >> 0 ) & 0xf; + vsdb->c = (edid_offset[5] >> 4 ) & 0xf; + vsdb->d = (edid_offset[5] >> 0 ) & 0xf; + vsdb_local = *vsdb; + vsdb->valid = 1; +} + +int Edid_Parse_check_HDMI_VSDB(HDMI_TX_INFO_t * info, unsigned char *buff) +{ + unsigned char VSpecificBoundary, BlockAddr, len; + int temp_addr=0; + VSpecificBoundary = buff[2] ; + if(VSpecificBoundary < 4) + { + info->output_state = CABLE_PLUGIN_DVI_OUT; + return -1; + } + BlockAddr = CEA_DATA_BLOCK_COLLECTION_ADDR_1StP; + while( BlockAddr < VSpecificBoundary) { + len = buff[BlockAddr] & 0x1F; + if((buff[BlockAddr] & 0xE0)== VENDOR_TAG){ //find the HDMI Vendor Specific Data Block + break; + } + temp_addr = BlockAddr + len + 1; + if(temp_addr >= VSpecificBoundary) + break; + BlockAddr = BlockAddr + len + 1; + } + + set_vsdb_phy_addr(&info->vsdb_phy_addr, &buff[BlockAddr]); + + if(temp_addr >= VSpecificBoundary) + { + info->output_state = CABLE_PLUGIN_DVI_OUT; + return -1; + } + else + { + if((buff[BlockAddr + 1]!= 0x03)||(buff[BlockAddr + 2]!= 0x0C)||(buff[BlockAddr + 3]!= 0x0)) + { + info->output_state = CABLE_PLUGIN_DVI_OUT; + return -1; + } + } + return 0; +} + +//----------------------------------------------------------- +void Edid_MonitorCapable861(HDMI_TX_INFO_t * info, unsigned char edid_flag) +{ + if(edid_flag & 0x80) + info->support_underscan_flag = 1; + if(edid_flag & 0x40) + info->support_basic_audio_flag =1; + if(edid_flag & 0x20) + { + info->support_ycbcr444_flag =1; +// info->videopath_outindex = 1; // Video Output Color Space Conversion : 0 - RGB out; 1 - YCbr (4:4:4) out; 2 - YCbr (4:2:2) out; + } + if(edid_flag & 0x10) + { + info->support_ycbcr422_flag =1 ; +// if(!(edid_flag & 0x20)) +// info->videopath_outindex = 2; // Video Output Color Space Conversion : 0 - RGB out; 1 - YCbr (4:4:4) out; 2 - YCbr (4:2:2) out; + } +} + + +//----------------------------------------------------------- +static void Edid_ParsingVideoDATABlock(HDMI_TX_INFO_t * info, unsigned char *buff, unsigned char BaseAddr, unsigned char NBytes) +{ + unsigned char i; + NBytes &= 0x1F; + for(i = 0; i < NBytes; i++) + { + switch(buff[i + BaseAddr]&0x7F) + { + case 6: + case 7: + info->hdmi_sup_480i = 1; + break; + + case 21: + case 22: + info->hdmi_sup_576i = 1; + break; + + case 2: + case 3: + info->hdmi_sup_480p = 1; + break; + + case 17: + case 18: + info->hdmi_sup_576p = 1; + break; + + case 4: + info->hdmi_sup_720p_60hz = 1; + break; + + case 19: + info->hdmi_sup_720p_50hz = 1; + break; + + case 5: + info->hdmi_sup_1080i_60hz = 1; + break; + + case 20: + info->hdmi_sup_1080i_50hz = 1; + break; + + case 16: + info->hdmi_sup_1080p_60hz = 1; + break; + + case 31: + info->hdmi_sup_1080p_50hz = 1; + break; + + case 32: + info->hdmi_sup_1080p_24hz = 1; + break; + + case 33: + info->hdmi_sup_1080p_25hz = 1; + break; + case 34: + info->hdmi_sup_1080p_30hz = 1; + break; + default: + break; + } + } +} + +//----------------------------------------------------------- +static void Edid_ParsingAudioDATABlock(HDMI_TX_INFO_t * info, unsigned char *Data, unsigned char BaseAddr, unsigned char NBytes) +{ + unsigned char AudioFormatCode; + int i = BaseAddr ; + NBytes&=0x1F; + do{ + AudioFormatCode = (Data[i]&0xF8)>>3; + switch(AudioFormatCode) + { + case 1: + info->tv_audio_info._60958_PCM.support_flag = 1; + info->tv_audio_info._60958_PCM.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._60958_PCM._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._60958_PCM._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._60958_PCM._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._60958_PCM._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._60958_PCM._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._60958_PCM._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._60958_PCM._32k = 1; + if((Data[i+2]&0x04)) + info->tv_audio_info._60958_PCM._24bit = 1; + if((Data[i+2]&0x02)) + info->tv_audio_info._60958_PCM._20bit = 1; + if((Data[i+2]&0x01)) + info->tv_audio_info._60958_PCM._16bit = 1; + break; + + case 2: + info->tv_audio_info._AC3.support_flag = 1; + info->tv_audio_info._AC3.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._AC3._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._AC3._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._AC3._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._AC3._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._AC3._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._AC3._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._AC3._32k = 1; + info->tv_audio_info._AC3._max_bit = Data[i+2]; + break; + + case 3: + info->tv_audio_info._MPEG1.support_flag = 1; + info->tv_audio_info._MPEG1.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._MPEG1._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._MPEG1._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._MPEG1._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._MPEG1._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._MPEG1._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._MPEG1._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._MPEG1._32k = 1; + info->tv_audio_info._MPEG1._max_bit = Data[i+2]; + break; + + case 4: + info->tv_audio_info._MP3.support_flag = 1; + info->tv_audio_info._MP3.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._MP3._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._MP3._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._MP3._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._MP3._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._MP3._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._MP3._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._MP3._32k = 1; + info->tv_audio_info._MP3._max_bit = Data[i+2]; + break; + + case 5: + info->tv_audio_info._MPEG2.support_flag = 1; + info->tv_audio_info._MPEG2.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._MPEG2._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._MPEG2._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._MPEG2._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._MPEG2._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._MPEG2._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._MPEG2._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._MPEG2._32k = 1; + info->tv_audio_info._MPEG2._max_bit = Data[i+2]; + break; + + case 6: + info->tv_audio_info._AAC.support_flag = 1; + info->tv_audio_info._AAC.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._AAC._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._AAC._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._AAC._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._AAC._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._AAC._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._AAC._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._AAC._32k = 1; + info->tv_audio_info._AAC._max_bit = Data[i+2]; + break; + + case 7: + info->tv_audio_info._DTS.support_flag = 1; + info->tv_audio_info._DTS.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._DTS._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._DTS._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._DTS._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._DTS._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._DTS._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._DTS._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._DTS._32k = 1; + info->tv_audio_info._DTS._max_bit = Data[i+2]; + break; + + case 8: + info->tv_audio_info._ATRAC.support_flag = 1; + info->tv_audio_info._ATRAC.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._ATRAC._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._ATRAC._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._ATRAC._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._ATRAC._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._ATRAC._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._ATRAC._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._ATRAC._32k = 1; + info->tv_audio_info._ATRAC._max_bit = Data[i+2]; + break; + + case 9: + info->tv_audio_info._One_Bit_Audio.support_flag = 1; + info->tv_audio_info._One_Bit_Audio.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._One_Bit_Audio._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._One_Bit_Audio._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._One_Bit_Audio._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._One_Bit_Audio._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._One_Bit_Audio._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._One_Bit_Audio._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._One_Bit_Audio._32k = 1; + info->tv_audio_info._One_Bit_Audio._max_bit = Data[i+2]; + break; + + case 10: + info->tv_audio_info._Dolby.support_flag = 1; + info->tv_audio_info._Dolby.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._Dolby._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._Dolby._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._Dolby._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._Dolby._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._Dolby._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._Dolby._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._Dolby._32k = 1; + info->tv_audio_info._Dolby._max_bit = Data[i+2]; + break; + + case 11: + info->tv_audio_info._DTS_HD.support_flag = 1; + info->tv_audio_info._DTS_HD.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._DTS_HD._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._DTS_HD._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._DTS_HD._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._DTS_HD._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._DTS_HD._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._DTS_HD._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._DTS_HD._32k = 1; + info->tv_audio_info._DTS_HD._max_bit = Data[i+2]; + break; + + + case 12: + info->tv_audio_info._MAT.support_flag = 1; + info->tv_audio_info._MAT.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._MAT._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._MAT._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._MAT._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._MAT._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._MAT._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._MAT._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._MAT._32k = 1; + info->tv_audio_info._MAT._max_bit = Data[i+2]; + break; + + case 13: + info->tv_audio_info._ATRAC.support_flag = 1; + info->tv_audio_info._ATRAC.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._DST._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._DST._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._DST._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._DST._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._DST._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._DST._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._DST._32k = 1; + info->tv_audio_info._DST._max_bit = Data[i+2]; + break; + + case 14: + info->tv_audio_info._WMA.support_flag = 1; + info->tv_audio_info._WMA.max_channel_num = (Data[i]&0x07); + if((Data[i+1]&0x40)) + info->tv_audio_info._WMA._192k = 1; + if((Data[i+1]&0x20)) + info->tv_audio_info._WMA._176k = 1; + if((Data[i+1]&0x10)) + info->tv_audio_info._WMA._96k = 1; + if((Data[i+1]&0x08)) + info->tv_audio_info._WMA._88k = 1; + if((Data[i+1]&0x04)) + info->tv_audio_info._WMA._48k = 1; + if((Data[i+1]&0x02)) + info->tv_audio_info._WMA._44k = 1; + if((Data[i+1]&0x01)) + info->tv_audio_info._WMA._32k = 1; + info->tv_audio_info._WMA._max_bit = Data[i+2]; + break; + + default: + break; + } + i+=3; + }while (i < (NBytes + BaseAddr)); +} + +//----------------------------------------------------------- +static void Edid_ParsingSpeakerDATABlock(HDMI_TX_INFO_t * info, unsigned char *buff, unsigned char BaseAddr) +{ + int ii; + for(ii = 1; ii < 0x80; ) + { + switch(buff[BaseAddr] & ii) + { + case 0x40: + info->tv_audio_info.speaker_allocation.rlc_rrc = 1; + break; + + case 0x20: + info->tv_audio_info.speaker_allocation.flc_frc = 1; + break; + + case 0x10: + info->tv_audio_info.speaker_allocation.rc = 1; + break; + + case 0x08: + info->tv_audio_info.speaker_allocation.rl_rr = 1; + break; + + case 0x04: + info->tv_audio_info.speaker_allocation.fc = 1; + break; + + case 0x02: + info->tv_audio_info.speaker_allocation.lfe = 1; + break; + + case 0x01: + info->tv_audio_info.speaker_allocation.fl_fr = 1; + break; + + default : + break; + } + ii = ii << 1; + } +} + + + +//----------------------------------------------------------- +int Edid_ParsingCEADataBlockCollection(HDMI_TX_INFO_t * info, unsigned char *buff) +{ + unsigned char AddrTag, D, Addr, Data; + int temp_addr; + + D = buff[2]; //Byte number offset d where Detailed Timing data begins + Addr = 4; + + AddrTag = Addr; + do{ + Data = buff[AddrTag]; + switch(Data&0xE0) + { + case VIDEO_TAG: + if((Addr + (Data&0x1f)) < D) + Edid_ParsingVideoDATABlock(info, buff, Addr + 1, (Data & 0x1F) ); + break; + + case AUDIO_TAG: + if((Addr + (Data&0x1f)) < D) + Edid_ParsingAudioDATABlock(info, buff, Addr + 1, (Data & 0x1F) ); + break; + + case SPEAKER_TAG: + if((Addr + (Data&0x1f)) < D) + Edid_ParsingSpeakerDATABlock(info, buff, Addr + 1 ); + break; + + case VENDOR_TAG: + if((Addr + (Data&0x1f)) < D) + { + if((buff[Addr + 1] != 0x03) || (buff[Addr + 2] != 0x0c) || (buff[Addr + 3] != 0x00)) + { + info->auth_state = HDCP_NO_AUTH ; + info->output_state = CABLE_PLUGIN_DVI_OUT; + } + if((Data&0x1f) > 5) + { + //A Source shall not transmit an ISRC1 or ISRC2 Packet to a Sink that does not have Supports_AI = 1 + //International Standard Recording Code (ISRC) + if(buff[Addr + 6] & 0x80) + info->support_ai_flag = 1; + } + } + break; + + default: + break; + } + Addr += ( Data & 0x1F ) ; // next Tag Address + AddrTag = ++Addr; + temp_addr = Addr + ( Data & 0x1F ) ; + if(temp_addr >= D) //force to break; + break; + }while (Addr < D); + + return 0; +} + +//----------------------------------------------------------- + +//parse Sink 3D information +static int hdmitx_edid_3d_parse(rx_cap_t* pRXCap, unsigned char *dat, unsigned size) +{ + int j = 0; + int bit = 16; + unsigned int base = 0; + unsigned int pos = base + 1; + + if(dat[base] & (1<<7)) + pos += 2; + if(dat[base] & (1<<6)) + pos += 2; + if(dat[base] & (1<<5)){ + pRXCap->threeD_present = dat[pos] >> 7; + pRXCap->threeD_Multi_present = (dat[pos] >> 5) & 0x3; + pos += 1; + pRXCap->HDMI_VIC_LEN = (dat[pos] ) >> 5; + pRXCap->HDMI_3D_LEN = (dat[pos] ) & 0x1f; + pos += pRXCap->HDMI_VIC_LEN + 1; + if((pRXCap->threeD_Multi_present == 0x01) || (pRXCap->threeD_Multi_present == 0x2)) { + pRXCap->threeD_Structure_ALL_15_0 = (dat[pos] << 8) + dat[pos+1]; + pos +=2; + } + if(pRXCap->threeD_Multi_present == 0x2) { + pRXCap->threeD_MASK_15_0 = (dat[pos] << 8) + dat[pos+1]; + pos +=2; + } + } + while(pos < size) { + if((dat[pos] & 0xf) == 0x0 ){ // frame packing + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].frame_packing = 1; + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].frame_packing = 1; + } + if((dat[pos] & 0xf) == 0x6 ){ // top and bottom + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].top_and_bottom = 1; + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].top_and_bottom = 1; + } + if((dat[pos] & 0xf) == 0x8 ){ // top and bottom + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos] & 0xf0) >> 4)]].side_by_side = 1; + pRXCap->support_3d_format[pRXCap->VIC[((dat[pos+1] & 0xf0) >> 4)]].side_by_side = 1; + } + pos += 2; + } + + while(bit--){ + if(((pRXCap->threeD_MASK_15_0) >> j) & 0x1) + if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 0)) { // frame packing + pRXCap->support_3d_format[pRXCap->VIC[j]].frame_packing = 1; + } + if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 6)) { // top and bottom + pRXCap->support_3d_format[pRXCap->VIC[j]].top_and_bottom = 1; + } + if(pRXCap->threeD_Structure_ALL_15_0 & (1 << 8)) { // top and bottom + pRXCap->support_3d_format[pRXCap->VIC[j]].side_by_side = 1; + } + j++; + } + return 1; +} + +//parse Sink 4k2k information +static void hdmitx_edid_4k2k_parse(rx_cap_t* pRXCap, unsigned char *dat, unsigned size) +{ + if((size > 4) || (size == 0)) { + hdmi_print(ERR, EDID "HDMI: 4k2k in edid out of range, SIZE = %d\n", size); + return; + } + while(size--) { + if(*dat == 1) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_30; + else if(*dat == 2) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_25; + else if(*dat == 3) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_24; + else if(*dat == 4) + pRXCap->VIC[pRXCap->VIC_count] = HDMI_4k2k_smpte_24; + else { + } + dat ++; + pRXCap->VIC_count++ ; + } +} + +static int hdmitx_edid_block_parse(hdmitx_dev_t* hdmitx_device, unsigned char *BlockBuf) +{ + unsigned char offset,End ; + unsigned char count ; + unsigned char tag ; + int i, tmp, idx; + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + + if( BlockBuf[0] != 0x02 ) + return -1 ; // not a CEA BLOCK. + End = BlockBuf[2] ; // CEA description. + pRXCap->native_Mode = BlockBuf[3] ; + + pRXCap->VIC_count = 0 ; + pRXCap->native_VIC = 0xff ; + for( offset = 4 ; offset < End ; ){ + tag = BlockBuf[offset] >> 5 ; + count = BlockBuf[offset] & 0x1f ; + switch( tag ){ + case HDMI_EDID_BLOCK_TYPE_AUDIO: + pRXCap->AUD_count = count/3 ; + offset++ ; + for( i = 0 ; i < pRXCap->AUD_count ; i++) + { + pRXCap->RxAudioCap[i].audio_format_code = (BlockBuf[offset + i * 3]>>3)&0xf; + pRXCap->RxAudioCap[i].channel_num_max = BlockBuf[offset + i * 3]&0x7; + pRXCap->RxAudioCap[i].freq_cc = BlockBuf[offset + i * 3 +1]&0x7f; + pRXCap->RxAudioCap[i].cc3 = BlockBuf[offset + i * 3 + 2]&0x7; + } + offset += count; + break ; + + case HDMI_EDID_BLOCK_TYPE_VIDEO: + offset ++; + for( i = 0 ; i < count ; i++) + { + unsigned char VIC ; + VIC = BlockBuf[offset + i] & (~0x80) ; + pRXCap->VIC[pRXCap->VIC_count] = VIC ; + if( BlockBuf[offset + i] & 0x80 ){ + pRXCap->native_VIC = VIC; + } + pRXCap->VIC_count++ ; + } + offset += count; + break ; + + case HDMI_EDID_BLOCK_TYPE_VENDER: + offset ++ ; + pRXCap->IEEEOUI = (unsigned long)BlockBuf[offset+2] ; + pRXCap->IEEEOUI <<= 8 ; + pRXCap->IEEEOUI += (unsigned long)BlockBuf[offset+1] ; + pRXCap->IEEEOUI <<= 8 ; + pRXCap->IEEEOUI += (unsigned long)BlockBuf[offset] ; + /**/ + hdmi_print(0, "HDMI_EDID_BLOCK_TYPE_VENDER: IEEEOUI %x:", pRXCap->IEEEOUI); + for(i = 0; iColorDeepSupport = (unsigned long)BlockBuf[offset+5]; + pRXCap->Max_TMDS_Clock = (unsigned long)BlockBuf[offset+6]; + if(count > 7) { + tmp = BlockBuf[offset+7]; + idx = offset + 8; + if(tmp & (1<<6)) { + idx += 2; + } + if(tmp & (1<<7)) { + idx += 2; + } + if(tmp & (1<<5)) { + idx += 1; + if(BlockBuf[idx] & 0xe0) { //valid 4k + hdmitx_edid_4k2k_parse(pRXCap, &BlockBuf[idx + 1], BlockBuf[idx] >> 5); + } + if(BlockBuf[idx-1] & 0xe0) { //valid 3D + hdmitx_edid_3d_parse(pRXCap, &BlockBuf[offset+7], count - 7); + } + } + } + offset += count ; // ignore the remaind. + break ; + + case HDMI_EDID_BLOCK_TYPE_SPEAKER: + offset ++ ; + pRXCap->RxSpeakerAllocation = BlockBuf[offset] ; + offset += count; + break ; + + case HDMI_EDID_BLOCK_TYPE_VESA: + offset ++; + offset += count; + break ; + + case HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG: + offset ++; + offset += count; + break ; + + case HDMI_EDID_BLOCK_TYPE_RESERVED: + offset ++; + offset += count; + break; + + case HDMI_EDID_BLOCK_TYPE_RESERVED2: + offset ++; + offset += count; + break; + + default: + break; + } + } + hdmitx_device->vic_count=pRXCap->VIC_count; + return 0 ; +} + +// add default VICs for DVI case +static void hdmitx_edid_set_default_vic(hdmitx_dev_t* hdmitx_device) +{ + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + pRXCap->VIC_count = 0x3; + pRXCap->VIC[0] = 2; + pRXCap->VIC[1] = 4; + pRXCap->VIC[2] = 16; + pRXCap->native_VIC = 4; + hdmitx_device->vic_count = pRXCap->VIC_count; + hdmi_print(IMP, EDID "HDMI: set default vic\n"); +} + +#if 0 +#define PRINT_HASH(hash) {printk("%s:%d ",__func__,__LINE__);int __i;for(__i=0;__i<20;__i++)printk("%02x,",hash[__i]);printk("\n");} +#else +#define PRINT_HASH(hash) +#endif + +static int edid_hash_calc(unsigned char *hash, const char *data, unsigned int len) +{ + struct scatterlist sg; + + struct crypto_hash *tfm; + struct hash_desc desc; + + tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); + PRINT_HASH(hash); + if (IS_ERR(tfm)) + return -EINVAL; + + PRINT_HASH(hash); + /* ... set up the scatterlists ... */ + sg_init_one(&sg, (u8 *) data, len); + desc.tfm = tfm; + desc.flags = 0; + + if (crypto_hash_digest(&desc, &sg,len, hash)) + return -EINVAL; + PRINT_HASH(hash); + crypto_free_hash(tfm); + return 1; +} + +static int hdmitx_edid_search_IEEEOUI(char *buf) +{ + int i; + + for(i = 0; i < 125; i++) { + if((buf[i] == 0x03) && (buf[i+1] == 0x0c) && (buf[i+2] == 0x00)) { + return 1; + } + } + return 0; +} + +int hdmitx_edid_parse(hdmitx_dev_t* hdmitx_device) +{ + unsigned char CheckSum ; + unsigned char zero_numbers; + unsigned char BlockCount ; + unsigned char* EDID_buf = hdmitx_device->EDID_buf; + int i, j, ret_val ; + int idx[4]; + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + hdmi_print(0, "EDID Parser:\n"); + + // Calculate the EDID hash for special use + memset(hdmitx_device->EDID_hash, 0, ARRAY_SIZE(hdmitx_device->EDID_hash)); + edid_hash_calc(hdmitx_device->EDID_hash, hdmitx_device->EDID_buf, 256); + + ret_val = Edid_DecodeHeader(&hdmitx_device->hdmi_info, &EDID_buf[0]); + +// if(ret_val == -1) +// return -1; + + for( i = 0, CheckSum = 0 ; i < 128 ; i++ ) + { + CheckSum += EDID_buf[i] ; + CheckSum &= 0xFF ; + } + + if( CheckSum != 0 ) + { + hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; + hdmi_print(0, "PLUGIN_DVI_OUT\n"); +// return -1 ; + } + + Edid_ReceiverBrandNameParse(&hdmitx_device->RXCap, &EDID_buf[8]); + + idx[0] = EDID_DETAILED_TIMING_DES_BLOCK0_POS; + idx[1] = EDID_DETAILED_TIMING_DES_BLOCK1_POS; + idx[2] = EDID_DETAILED_TIMING_DES_BLOCK2_POS; + idx[3] = EDID_DETAILED_TIMING_DES_BLOCK3_POS; + for(i = 0; i < 4; i++) { + if(Edid_find_name_block(&EDID_buf[idx[i]])) + Edid_ReceiverProductNameParse(&hdmitx_device->RXCap, &EDID_buf[idx[i]+5]); + } + Edid_DecodeStandardTiming(&hdmitx_device->hdmi_info, &EDID_buf[26], 8); + Edid_ParseCEADetailedTimingDescriptors(&hdmitx_device->hdmi_info, 4, 0x36, &EDID_buf[0]); + + BlockCount = EDID_buf[0x7E] ; + + if( BlockCount == 0 ){ + hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; + hdmi_print(0, "EDID BlockCount=0\n"); + hdmitx_edid_set_default_vic(hdmitx_device); + + // DVI case judgement: only contains one block and checksum valid + CheckSum = 0; + zero_numbers = 0; + for(i = 0; i < 128; i++) { + CheckSum += EDID_buf[i]; + if(EDID_buf[i] == 0) + zero_numbers ++; + } + hdmi_print(INF, EDID "edid blk0 checksum:%d ext_flag:%d\n",CheckSum, EDID_buf[0x7e]); + if((CheckSum & 0xff) == 0) { + hdmitx_device->RXCap.IEEEOUI = 0; + } else { + hdmitx_device->RXCap.IEEEOUI = 0x0c03; + } + if(zero_numbers > 120) + hdmitx_device->RXCap.IEEEOUI = 0x0c03; + + return 0 ; // do nothing. + } + + if((BlockCount == 1) && (EDID_buf[0x81] == 1)) { // Note: some DVI monitor have more than 1 block + hdmitx_device->RXCap.IEEEOUI = 0; + return 0; + } + + else if ( BlockCount > EDID_MAX_BLOCK ) + { + BlockCount = EDID_MAX_BLOCK ; + } + + for( i = 1 ; i <= BlockCount ; i++ ) + { + + if((BlockCount > 1) && (i == 1)) + { + CheckSum = 0; //ignore the block1 data + } + else + { + if(((BlockCount == 1) && (i == 1)) || ((BlockCount > 1) && (i == 2))) + Edid_Parse_check_HDMI_VSDB( &hdmitx_device->hdmi_info, &EDID_buf[i * 128]); + + for( j = 0, CheckSum = 0 ; j < 128 ; j++ ) + { + CheckSum += EDID_buf[i*128 + j] ; + CheckSum &= 0xFF ; + } + if( CheckSum != 0 ) + { + hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_DVI_OUT; + } + else + { + Edid_MonitorCapable861(&hdmitx_device->hdmi_info, EDID_buf[i * 128 + 3]); + ret_val = Edid_ParsingCEADataBlockCollection(&hdmitx_device->hdmi_info, &EDID_buf[i * 128]); + Edid_ParseCEADetailedTimingDescriptors(&hdmitx_device->hdmi_info, 5, EDID_buf[i * 128 + 2], &EDID_buf[i * 128]); + if(hdmitx_device->hdmi_info.output_state != CABLE_PLUGIN_DVI_OUT) + hdmitx_device->hdmi_info.output_state = CABLE_PLUGIN_HDMI_OUT; + } + + } + + if( EDID_buf[i*128+0] == 0x2 ) + { + if(hdmitx_edid_block_parse(hdmitx_device, &(EDID_buf[i*128]))>=0){ + if(hdmitx_device->RXCap.IEEEOUI==0x0c03){ + break; + } + } + } + } + + if(hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { + pRXCap->IEEEOUI = 0x0c03; + printk("hdmitx: edid: find IEEEOUT\n"); + } + else { + pRXCap->IEEEOUI = 0x0; + printk("hdmitx: edid: not find IEEEOUT\n"); + } + + if((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0)|| (pRXCap->VIC_count == 0)){ + hdmitx_edid_set_default_vic(hdmitx_device); + } + +#if 1 + i=hdmitx_edid_dump(hdmitx_device, (char*)(hdmitx_device->tmp_buf), HDMI_TMP_BUF_SIZE); + hdmitx_device->tmp_buf[i]=0; + hdmi_print(0,"\n"); +#endif + return 0; + +} + +typedef struct{ + const char* disp_mode; + HDMI_Video_Codes_t VIC; +}dispmode_vic_t; + +static dispmode_vic_t dispmode_VIC_tab[]= +{ + {"480i_4_3", HDMI_480i60}, + {"480i_rpt", HDMI_480i60_16x9_rpt}, + {"480i", HDMI_480i60_16x9}, + {"480p_4_3", HDMI_480p60}, + {"480p_rpt", HDMI_480p60_16x9_rpt}, + {"480p", HDMI_480p60_16x9}, + {"576i_4_3", HDMI_576i50}, + {"576i_rpt", HDMI_576i50_16x9_rpt}, + {"576i", HDMI_576i50_16x9}, + {"576p_4_3", HDMI_576p50}, + {"576p_rpt", HDMI_576p50_16x9_rpt}, + {"576p", HDMI_576p50_16x9}, + {"720p50hz", HDMI_720p50}, + {"720p", HDMI_720p60}, + {"1080i50hz", HDMI_1080i50}, + {"1080i", HDMI_1080i60}, + {"1080p50hz", HDMI_1080p50}, + {"1080p30hz", HDMI_1080p30}, + {"1080p24hz", HDMI_1080p24}, + {"1080p", HDMI_1080p60}, + {"4k2k30hz", HDMI_4k2k_30}, + {"4k2k25hz", HDMI_4k2k_25}, + {"4k2k24hz", HDMI_4k2k_24}, + {"4k2ksmpte", HDMI_4k2k_smpte_24}, +}; + +int hdmitx_edid_VIC_support(HDMI_Video_Codes_t vic) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { + if(vic == dispmode_VIC_tab[i].VIC) + return 1; + } + + return 0; +} + +HDMI_Video_Codes_t hdmitx_edid_vic_tab_map_vic(const char* disp_mode) +{ + HDMI_Video_Codes_t vic = HDMI_Unkown; + int i; + + for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { + if(strncmp(disp_mode, dispmode_VIC_tab[i].disp_mode, strlen(dispmode_VIC_tab[i].disp_mode))==0) { + vic = dispmode_VIC_tab[i].VIC; + break; + } + } + + if(vic == HDMI_Unkown) + hdmi_print(INF, EDID "not find mapped vic\n"); + + return vic; +} + +const char * hdmitx_edid_vic_tab_map_string(HDMI_Video_Codes_t vic) +{ + int i; + const char * disp_str = NULL; + + for(i = 0; i < ARRAY_SIZE(dispmode_VIC_tab); i++) { + if(vic == dispmode_VIC_tab[i].VIC) { + disp_str = dispmode_VIC_tab[i].disp_mode; + break; + } + } + + if(!disp_str) + hdmi_print(INF, EDID "not find mapped display mode\n"); + + return disp_str; +} + +// force_flag: 0 means check with RX's edid +// 1 means no check wich RX's edid +HDMI_Video_Codes_t hdmitx_edid_get_VIC(hdmitx_dev_t* hdmitx_device, const char* disp_mode, char force_flag) +{ + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + int j; + HDMI_Video_Codes_t vic = hdmitx_edid_vic_tab_map_vic(disp_mode); + + if(vic != HDMI_Unkown) { + if(force_flag == 0) { + for( j = 0 ; j < pRXCap->VIC_count ; j++ ){ + if(pRXCap->VIC[j]==vic) + break; + } + if(j>=pRXCap->VIC_count){ + vic = HDMI_Unkown; + } + } + } + return vic; +} + +const char* hdmitx_edid_get_native_VIC(hdmitx_dev_t* hdmitx_device) +{ + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + + return hdmitx_edid_vic_tab_map_string(pRXCap->native_VIC); +} + +//Clear HDMI Hardware Module EDID RAM and EDID Buffer +void hdmitx_edid_ram_buffer_clear(hdmitx_dev_t* hdmitx_device) +{ + unsigned int i = 0; + + //Clear HDMI Hardware Module EDID RAM + hdmitx_device->HWOp.CntlDDC(hdmitx_device, DDC_EDID_CLEAR_RAM, 0); + + //Clear EDID Buffer + for(i = 0; i < EDID_MAX_BLOCK*128; i++) { + hdmitx_device->EDID_buf[i] = 0; + } + for(i = 0; i < EDID_MAX_BLOCK*128; i++) { + hdmitx_device->EDID_buf1[i] = 0; + } +} + +//Clear the Parse result of HDMI Sink's EDID. +void hdmitx_edid_clear(hdmitx_dev_t* hdmitx_device) +{ + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + hdmitx_device->vic_count=0; + pRXCap->VIC_count = 0; + pRXCap->AUD_count = 0; + // Note: in most cases, we think that rx is tv and the default IEEEOUI is HDMI Identifier + pRXCap->IEEEOUI = 0x000c03; + pRXCap->native_Mode = 0; + pRXCap->native_VIC = 0xff; + pRXCap->RxSpeakerAllocation = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.b = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.c = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.d = 0; + hdmitx_device->hdmi_info.vsdb_phy_addr.valid = 0; + memset(&vsdb_local, 0, sizeof(vsdb_phy_addr_t)); + pRXCap->Video_Latency = 0; + pRXCap->Audio_Latency = 0; + pRXCap->Interlaced_Video_Latency=0; + pRXCap->Interlaced_Audio_Latency=0; + pRXCap->threeD_present=0; + pRXCap->threeD_Multi_present=0; + pRXCap->HDMI_VIC_LEN=0; + pRXCap->HDMI_3D_LEN=0; + pRXCap->threeD_Structure_ALL_15_0=0; + pRXCap->threeD_MASK_15_0=0; + memset(pRXCap->ReceiverBrandName, 0, sizeof(pRXCap->ReceiverBrandName)); + memset(pRXCap->ReceiverProductName, 0, sizeof(pRXCap->ReceiverProductName)); + memset(&hdmitx_device->RXCap.support_3d_format[0], 0, sizeof(hdmitx_device->RXCap.support_3d_format)); + memset(&hdmitx_device->EDID_hash[0], 0, sizeof(hdmitx_device->EDID_hash)); +} + +/* + * print one block data of edid + */ +static void hdmitx_edid_blk_print(unsigned char *blk, unsigned int blk_idx) +{ + unsigned int i; + hdmi_print(INF, EDID "blk%d raw data\n", blk_idx); + for(i = 0; i < 128; i++) { + printk("%02x", blk[i]); + if(((i+1) & 0x1f) == 0) // print 32bytes a line + printk("\n"); + } + printk("\n"); +} + +/* + * check EDID buf contains valid block numbers + */ +static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf) +{ + unsigned int valid_blk_no = 0; + unsigned int i = 0, j = 0; + unsigned int tmp_chksum = 0; + for(j = 0; j < EDID_MAX_BLOCK; j++) { + for(i = 0; i < 128; i++) { + tmp_chksum += buf[i + j*128]; + } + if(tmp_chksum !=0) { + valid_blk_no ++; + if((tmp_chksum & 0xff) == 0) { + hdmi_print(INF, EDID "check sum valid\n"); + } + else { + hdmi_print(INF, EDID "check sum invalid\n"); + } + } + tmp_chksum = 0; + } + return valid_blk_no; +} + +/* + * suppose DDC read EDID two times successfully, + * then compare EDID_buf and EDID_buf1. + * if same, just print out EDID_buf raw data, else print out 2 buffers + */ +void hdmitx_edid_buf_compare_print(hdmitx_dev_t* hdmitx_device) +{ + unsigned int i = 0; + unsigned int err_no = 0; + unsigned char *buf0 = hdmitx_device->EDID_buf; + unsigned char *buf1 = hdmitx_device->EDID_buf1; + unsigned int valid_blk_no = 0; + unsigned int blk_idx = 0; + + for(i = 0; i < EDID_MAX_BLOCK*128; i++) { + if(buf0[i] != buf1[i]) { + err_no ++; + } + } + + if(err_no == 0) { + // calculate valid edid block numbers + valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); + + if(valid_blk_no == 0) { + hdmi_print(ERR, EDID "raw data are all zeroes\n"); + } + else { + for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { + hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx); + } + } + } + else { + hdmi_print(ERR, EDID "%d errors between two reading\n", err_no); + valid_blk_no = hdmitx_edid_check_valid_blocks(buf0); + for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { + hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx); + } + + valid_blk_no = hdmitx_edid_check_valid_blocks(buf1); + for(blk_idx = 0; blk_idx < valid_blk_no; blk_idx++) { + hdmitx_edid_blk_print(&buf1[blk_idx*128], blk_idx); + } + } +} + +int hdmitx_edid_dump(hdmitx_dev_t* hdmitx_device, char* buffer, int buffer_len) +{ + int i,pos=0; + rx_cap_t* pRXCap = &(hdmitx_device->RXCap); + + pos+=snprintf(buffer+pos, buffer_len-pos, "Receiver Brand Name: %s\r\n", pRXCap->ReceiverBrandName); + pos+=snprintf(buffer+pos, buffer_len-pos, "Receiver Product Name: %s\r\n", pRXCap->ReceiverProductName); + + pos+=snprintf(buffer+pos, buffer_len-pos, "EDID block number: 0x%x\r\n",hdmitx_device->EDID_buf[0x7e]); + + pos+=snprintf(buffer+pos, buffer_len-pos, "Source Physical Address[a.b.c.d]: %x.%x.%x.%x\r\n", + hdmitx_device->hdmi_info.vsdb_phy_addr.a, hdmitx_device->hdmi_info.vsdb_phy_addr.b, hdmitx_device->hdmi_info.vsdb_phy_addr.c, hdmitx_device->hdmi_info.vsdb_phy_addr.d); + + pos+=snprintf(buffer+pos, buffer_len-pos, "native Mode %x, VIC (native %d):\r\n", + pRXCap->native_Mode, pRXCap->native_VIC); + + pos+=snprintf(buffer+pos, buffer_len-pos, "ColorDeepSupport %x, MaxTMDSClock %d\r\n", + pRXCap->ColorDeepSupport, pRXCap->Max_TMDS_Clock); + + for( i = 0 ; i < pRXCap->VIC_count ; i++ ) + { + pos+=snprintf(buffer+pos, buffer_len-pos,"%d ", pRXCap->VIC[i]); + } + pos+=snprintf(buffer+pos, buffer_len-pos,"\r\n"); + pos+=snprintf(buffer+pos, buffer_len-pos, "Audio {format, channel, freq, cce}\r\n"); + for(i = 0; i< pRXCap->AUD_count; i++) { + pos+=snprintf(buffer+pos, buffer_len-pos, "{%d, %d, %x, %x}\r\n", pRXCap->RxAudioCap[i].audio_format_code, + pRXCap->RxAudioCap[i].channel_num_max, pRXCap->RxAudioCap[i].freq_cc, pRXCap->RxAudioCap[i].cc3); + } + pos+=snprintf(buffer+pos,buffer_len-pos,"Speaker Allocation: %x\r\n", pRXCap->RxSpeakerAllocation); + pos+=snprintf(buffer+pos,buffer_len-pos,"Vendor: %x\r\n", pRXCap->IEEEOUI); + + pos+=snprintf(buffer+pos,buffer_len-pos,"Rx 3D Format Support List:\r\n{VIC FramePacking TopBottom SidebySide}\r\n"); + for(i = 0 ; i < pRXCap->VIC_count; i++){ + pos+=snprintf(buffer+pos,buffer_len-pos,"{ %d\t%d\t%d\t%d }\n", pRXCap->VIC[i], + pRXCap->support_3d_format[pRXCap->VIC[i]].frame_packing, + pRXCap->support_3d_format[pRXCap->VIC[i]].top_and_bottom, + pRXCap->support_3d_format[pRXCap->VIC[i]].side_by_side); + } + return pos; +} diff --git a/include/linux/amlogic/hdmi_tx/hdmi_info_global.h b/include/linux/amlogic/hdmi_tx/hdmi_info_global.h index d85796531ec5..415b8f1c50f8 100644 --- a/include/linux/amlogic/hdmi_tx/hdmi_info_global.h +++ b/include/linux/amlogic/hdmi_tx/hdmi_info_global.h @@ -1,680 +1,680 @@ -#ifndef _HDMI_INFO_GLOBAL_H -#define _HDMI_INFO_GLOBAL_H - -typedef enum HDMI_Video_Type_ { - HDMI_Unkown = 0 , - HDMI_640x480p60 = 1 , - HDMI_480p60, - HDMI_480p60_16x9, - HDMI_720p60, - HDMI_1080i60, - HDMI_480i60, - HDMI_480i60_16x9, - HDMI_480i60_16x9_rpt = 11, - HDMI_1440x480p60 = 14 , - HDMI_1440x480p60_16x9 = 15 , - HDMI_1080p60 = 16, - HDMI_576p50, - HDMI_576p50_16x9, - HDMI_720p50, - HDMI_1080i50, - HDMI_576i50, - HDMI_576i50_16x9, - HDMI_576i50_16x9_rpt = 26, - HDMI_1080p50 = 31, - HDMI_1080p24, - HDMI_1080p25, - HDMI_1080p30, - HDMI_480p60_16x9_rpt = 36, - HDMI_576p50_16x9_rpt = 38, - HDMI_4k2k_24 = 93, // CEA-861-F - HDMI_4k2k_25, - HDMI_4k2k_30, - HDMI_4k2k_50, - HDMI_4k2k_60, - HDMI_4k2k_smpte_24 = 98, //24 Hz - HDMI_4k2k_smpte_50 = 101, - HDMI_4k2k_smpte_60, -} HDMI_Video_Codes_t ; - - -//-------------------HDMI VIDEO-------------------------------- -#define TYPE_AVI_INFOFRAMES 0x82 -#define AVI_INFOFRAMES_VERSION 0x02 -#define AVI_INFOFRAMES_LENGTH 0x0D - -typedef enum -{ - COLOR_SPACE_RGB444 = 0, - COLOR_SPACE_YUV422 = 1, - COLOR_SPACE_YUV444 = 2, -}color_space_type_t; - -typedef enum -{ - STATE_VIDEO__POWERDOWN = 0, - STATE_VIDEO__MUTED = 1, - STATE_VIDEO__UNMUTE = 2, - STATE_VIDEO__ON = 3, -}hdmi_rx_video_state_t; - - -typedef struct -{ - short H; // Number of horizontal pixels - short V; // Number of vertical pixels -}pixs_type_t; - - -typedef enum -{ - ASPECT_RATIO_SAME_AS_SOURCE= 0, - TV_ASPECT_RATIO_4_3, - TV_ASPECT_RATIO_16_9, - TV_ASPECT_RATIO_14_9, - ASPECT_RATIO_MAX -} hdmi_aspect_ratio_t; - -typedef enum -{ - COLOR_24BIT = 0, - COLOR_30BIT, - COLOR_36BIT, - COLOR_48BIT -} hdmi_color_depth_t; - -typedef enum -{ - NO_REPEAT = 0, - HDMI_2_TIMES_REPEAT, - HDMI_3_TIMES_REPEAT, - HDMI_4_TIMES_REPEAT, - HDMI_5_TIMES_REPEAT, - HDMI_6_TIMES_REPEAT, - HDMI_7_TIMES_REPEAT, - HDMI_8_TIMES_REPEAT, - HDMI_9_TIMES_REPEAT, - HDMI_10_TIMES_REPEAT, - MAX_TIMES_REPEAT, -} hdmi_pixel_repeat_t; - -typedef enum -{ - SS_NO_DATA = 0, - SS_SCAN_OVER, // where some active pixelsand lines at the edges are not displayed. - SS_SCAN_UNDER, // where all active pixels&lines are displayed, with or withouta border. - SS_RSV -} hdmi_scan_t; - - -typedef enum -{ - B_UNVALID = 0, - B_BAR_VERT, // Vert. Bar Infovalid - B_BAR_HORIZ, // Horiz. Bar Infovalid - B_BAR_VERT_HORIZ, //Vert.and Horiz. Bar Info valid -} hdmi_bar_info_t; - - -typedef enum -{ - CC_NO_DATA = 0, - CC_ITU601, - CC_ITU709, - CC_XVYCC601, - CC_XVYCC709, -} hdmi_colorimetry_t; - - -typedef enum -{ - SC_NO_UINFORM = 0, - SC_SCALE_HORIZ, //Picture has been scaled horizontally - SC_SCALE_VERT, //Picture has been scaled verticallv - SC_SCALE_HORIZ_VERT, //Picture has been scaled horizontally & SC_SCALE_H_V -} hdmi_slacing_t; - - - -typedef struct { - HDMI_Video_Codes_t VIC; - color_space_type_t color; - hdmi_color_depth_t color_depth; - hdmi_bar_info_t bar_info; - hdmi_pixel_repeat_t repeat_time; - hdmi_aspect_ratio_t aspect_ratio; - hdmi_colorimetry_t cc; - hdmi_scan_t ss; - hdmi_slacing_t sc; -}Hdmi_rx_video_info_t; -//-----------------------HDMI VIDEO END---------------------------------------- - - - -//-------------------HDMI AUDIO-------------------------------- -#define TYPE_AUDIO_INFOFRAMES 0x84 -#define AUDIO_INFOFRAMES_VERSION 0x01 -#define AUDIO_INFOFRAMES_LENGTH 0x0A - - -typedef enum -{ - CT_REFER_TO_STREAM = 0, - CT_PCM, - CT_AC_3, - CT_MPEG1, - CT_MP3, - CT_MPEG2, - CT_AAC, - CT_DTS, - CT_ATRAC, - CT_ONE_BIT_AUDIO, - CT_DOLBY_D, - CT_DTS_HD, - CT_MAT, - CT_DST, - CT_WMA, - CT_MAX, -} audio_type_t; - - -typedef enum -{ - CC_REFER_TO_STREAM = 0, - CC_2CH, - CC_3CH, - CC_4CH, - CC_5CH, - CC_6CH, - CC_7CH, - CC_8CH, - CC_MAX_CH -} audio_channel_t; - -typedef enum -{ - AF_SPDIF = 0, - AF_I2S, - AF_DSD, - AF_HBR, - AT_MAX -} audio_format_t; - - -//Sampling Freq Fs:0 - Refer to Stream Header; 1 - 32KHz; 2 - 44.1KHz; 3 - 48KHz; 4 - 88.2KHz... -typedef enum { - FS_REFER_TO_STREAM = 0, - FS_32K = 1, - FS_44K1 = 2, - FS_48K = 3, - FS_88K2 = 4, - FS_96K = 5, - FS_176K4 = 6, - FS_192K = 7, - FS_MAX, -}audio_fs_t; - -struct rate_map_fs { - unsigned int rate; - audio_fs_t fs; -}; - -typedef enum { - SS_REFER_TO_STREAM = 0, - SS_16BITS, - SS_20BITS, - SS_24BITS, - SS_MAX -}audio_sample_size_t; - -struct size_map_ss { - unsigned int sample_bits; - audio_sample_size_t ss; -}; - -//FL-- Front Left -//FC --Front Center -//FR --Front Right -//FLC-- Front Left Center -//FRC-- Front RiQhtCenter -//RL-- Rear Left -//RC --Rear Center -//RR-- Rear Right -//RLC-- Rear Left Center -//RRC --Rear RiQhtCenter -//LFE-- Low Frequency Effect -typedef enum { - CA_FR_FL = 0, - CA_LFE_FR_FL, - CA_FC_FR_FL, - CA_FC_LFE_FR_FL, - - CA_RC_FR_FL, - CA_RC_LFE_FR_FL, - CA_RC_FC_FR_FL, - CA_RC_FC_LFE_FR_FL, - - CA_RR_RL_FR_FL, - CA_RR_RL_LFE_FR_FL, - CA_RR_RL_FC_FR_FL, - CA_RR_RL_FC_LFE_FR_FL, - - CA_RC_RR_RL_FR_FL, - CA_RC_RR_RL_LFE_FR_FL, - CA_RC_RR_RL_FC_FR_FL, - CA_RC_RR_RL_FC_LFE_FR_FL, - - CA_RRC_RC_RR_RL_FR_FL, - CA_RRC_RC_RR_RL_LFE_FR_FL, - CA_RRC_RC_RR_RL_FC_FR_FL, - CA_RRC_RC_RR_RL_FC_LFE_FR_FL, - - CA_FRC_RLC_FR_FL, - CA_FRC_RLC_LFE_FR_FL, - CA_FRC_RLC_FC_FR_FL, - CA_FRC_RLC_FC_LFE_FR_FL, - - CA_FRC_RLC_RC_FR_FL, - CA_FRC_RLC_RC_LFE_FR_FL, - CA_FRC_RLC_RC_FC_FR_FL, - CA_FRC_RLC_RC_FC_LFE_FR_FL, - - CA_FRC_RLC_RR_RL_FR_FL, - CA_FRC_RLC_RR_RL_LFE_FR_FL, - CA_FRC_RLC_RR_RL_FC_FR_FL, - CA_FRC_RLC_RR_RL_FC_LFE_FR_FL, - -}speak_location_t; - -typedef enum { - LSV_0DB = 0, - LSV_1DB, - LSV_2DB, - LSV_3DB, - LSV_4DB, - LSV_5DB, - LSV_6DB, - LSV_7DB, - LSV_8DB, - LSV_9DB, - LSV_10DB, - LSV_11DB, - LSV_12DB, - LSV_13DB, - LSV_14DB, - LSV_15DB, - -}audio_down_mix_t; - -typedef enum -{ - STATE_AUDIO__MUTED = 0, - STATE_AUDIO__REQUEST_AUDIO = 1, - STATE_AUDIO__AUDIO_READY = 2, - STATE_AUDIO__ON = 3, -}hdmi_rx_audio_state_t; - -typedef struct -{ - audio_type_t type ; //!< Signal decoding type -- TvAudioType - audio_format_t format; - audio_channel_t channels ; //!< active audio channels bit mask. - audio_fs_t fs; //!< Signal sample rate in Hz - audio_sample_size_t ss; - speak_location_t speak_loc; - audio_down_mix_t lsv; - unsigned N_value; - unsigned CTS; -} Hdmi_rx_audio_info_t; - -#define HDMI_E_NONE 0x0 -// HPD Event & Status -#define E_HPD_PULG_IN 0x1 -#define E_HPD_PLUG_OUT 0x2 -#define S_HPD_PLUG_IN 0x1 -#define S_HPD_PLUG_OUT 0x0 - -#define E_HDCP_CHK_BKSV 0x1 - -typedef struct { - unsigned int event; - unsigned int stat; -}hdmi_mo_s; - -//-----------------------HDMI AUDIO END---------------------------------------- - - -//-------------------HDCP-------------------------------- -// HDCP keys from Efuse are encrypted by default, in this test HDCP keys are written by CPU with encryption manually added -#define ENCRYPT_KEY 0xbe - -typedef enum { - HDCP_NO_AUTH = 0, - HDCP_NO_DEVICE_WITH_SLAVE_ADDR , - HDCP_BCAP_ERROR , - HDCP_BKSV_ERROR , - HDCP_R0S_ARE_MISSMATCH , - HDCP_RIS_ARE_MISSMATCH , - HDCP_REAUTHENTATION_REQ , - HDCP_REQ_AUTHENTICATION , - HDCP_NO_ACK_FROM_DEV , - HDCP_NO_RSEN , - HDCP_AUTHENTICATED , - HDCP_REPEATER_AUTH_REQ , - HDCP_REQ_SHA_CALC , - HDCP_REQ_SHA_HW_CALC , - HDCP_FAILED_ViERROR , - HDCP_MAX -} hdcp_auth_state_t; - - - -//-----------------------HDCP END---------------------------------------- - - - - -//-------------------CEC------------------------------------- -#define CEC_MAX_CMD_SIZE 16 // defnes number of operands - -typedef enum -{ - CEC_LogAddr_TV = 0x00, - CEC_LogAddr_RecDev1 = 0x01, - CEC_LogAddr_RecDev2 = 0x02, - CEC_LogAddr_STB1 = 0x03, - CEC_LogAddr_DVD1 = 0x04, - CEC_LogAddr_AudSys = 0x05, - CEC_LogAddr_STB2 = 0x06, - CEC_LogAddr_STB3 = 0x07, - CEC_LogAddr_DVD2 = 0x08, - CEC_LogAddr_RecDev3 = 0x09, - CEC_LogAddr_Res1 = 0x0A, - CEC_LogAddr_Res2 = 0x0B, - CEC_LogAddr_Res3 = 0x0C, - CEC_LogAddr_Res4 = 0x0D, - CEC_LogAddr_FreeUse = 0x0E, - LOGADDR_UNREGORBC_MSG = 0x0F - -} CEC_LogAddr_t; - -typedef enum { - CEC_TV = 0, - CEC_DVD, - CEC_STB, - CEC_SW -} CECDev_t; - -typedef enum { - CEC_EnumTV = 0, - CEC_EnumDVD -} CEC_EnumType; - -typedef enum { - CEC_Idle = 0, - CEC_ReqPing, - CEC_ReqCmd1, - CEC_ReqCmd2, - CEC_ReqCmd3, - CEC_Enumiration -} CECOp_t; - -typedef enum { - CEC_TXWaitCmd, - CEC_TXSending, - CEC_TXSendAcked, - CEC_TXFailedToSend -} CEC_TXState; - -typedef enum -{ - CEC_POWERSTATUS_ON = 0x00, - CEC_POWERSTATUS_STANDBY = 0x01, - CEC_POWERSTATUS_STANDBY_TO_ON = 0x02, - CEC_POWERSTATUS_ON_TO_STANDBY = 0x03 - } POWER_STATUS_ET; - - -typedef struct { - unsigned char bRXState; - CEC_TXState bTXState; - unsigned char bCECErrors; - -} CEC_Int_t; - - -typedef struct -{ - unsigned char bCount; - unsigned char bRXNextCount; - unsigned char bDestOrRXHeader; - unsigned char bOpcode; - unsigned char bOperand[ CEC_MAX_CMD_SIZE ]; - -} CEC_t; -//-----------------------CEC END---------------------------------------- - - - -//--------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------- -//----------------------------------------------HDMI TX---------------------------------- -//--------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------- -typedef enum { - CABLE_UNPLUG = 0, - CABLE_PLUGIN_CHECK_EDID_I2C_ERROR , - CABLE_PLUGIN_CHECK_EDID_HEAD_ERROR, - CABLE_PLUGIN_CHECK_EDID_CHECKSUM_ERROR, - CABLE_PLUGIN_DVI_OUT , - CABLE_PLUGIN_HDMI_OUT , - CABLE_MAX -}hdmi_tx_display_type_t; - - - - //0b000 = MCLK is 128*Fs - //0b001 = MCLK is 256*Fs (recommanded) - //0b010 = MCLK is 384*Fs - //0b011 = MCLK is 512*Fs - //0b100 = MCLK is 768*Fs - //0b101 = MCLK is 1024*Fs - //0b110 = MCLK is 1152*Fs - //0b111 = MCLK is 192*Fs -typedef enum { - MCLK_128_Fs = 0, - MCLK_256_Fs , - MCLK_384_Fs , - MCLK_512_Fs , - MCLK_768_Fs, - MCLK_1024_Fs, - MCLK_1152_Fs -} hdmi_tx_audio_mclk_t; - -typedef struct{ - int hpd_state : 1; - int support_480i : 1; - int support_576i : 1; - int support_480p : 1; - int support_576p : 1; - int support_720p_60hz : 1; - int support_720p_50hz : 1; - int support_1080i_60hz : 1; - int support_1080i_50hz : 1; - int support_1080p_60hz : 1; - int support_1080p_50hz : 1; - int support_1080p_24hz : 1; - int support_1080p_25hz : 1; - int support_1080p_30hz : 1; -}hdmi_tx_sup_status_t; - - - -typedef struct{ - int support_flag : 1; - int max_channel_num : 3; - int _192k : 1; - int _176k : 1; - int _96k : 1; - int _88k : 1; - int _48k : 1; - int _44k : 1; - int _32k : 1; - int _24bit : 1; - int _20bit : 1; - int _16bit : 1; -}hdmi_tx_sup_lpcm_info_t; - - -typedef struct{ - int support_flag : 1; - int max_channel_num : 3; - int _192k : 1; - int _176k : 1; - int _96k : 1; - int _88k : 1; - int _48k : 1; - int _44k : 1; - int _32k : 1; - int _max_bit : 10; -}hdmi_tx_sup_compressed_info_t; - -typedef struct{ - int rlc_rrc : 1; - int flc_frc : 1; - int rc : 1; - int rl_rr : 1; - int fc : 1; - int lfe : 1; - int fl_fr : 1; -}hdmi_tx_sup_speaker_format_t; - - -typedef struct{ - hdmi_tx_sup_lpcm_info_t _60958_PCM; - hdmi_tx_sup_compressed_info_t _AC3; - hdmi_tx_sup_compressed_info_t _MPEG1; - hdmi_tx_sup_compressed_info_t _MP3; - hdmi_tx_sup_compressed_info_t _MPEG2; - hdmi_tx_sup_compressed_info_t _AAC; - hdmi_tx_sup_compressed_info_t _DTS; - hdmi_tx_sup_compressed_info_t _ATRAC; - hdmi_tx_sup_compressed_info_t _One_Bit_Audio; - hdmi_tx_sup_compressed_info_t _Dolby; - hdmi_tx_sup_compressed_info_t _DTS_HD; - hdmi_tx_sup_compressed_info_t _MAT; - hdmi_tx_sup_compressed_info_t _DST; - hdmi_tx_sup_compressed_info_t _WMA; - hdmi_tx_sup_speaker_format_t speaker_allocation; -}hdmi_tx_sup_audio_info_t; - - -typedef struct { - unsigned char VIC; - color_space_type_t color_prefer; - color_space_type_t color; - hdmi_color_depth_t color_depth; - hdmi_bar_info_t bar_info; - hdmi_pixel_repeat_t repeat_time; - hdmi_aspect_ratio_t aspect_ratio; - hdmi_colorimetry_t cc; - hdmi_scan_t ss; - hdmi_slacing_t sc; -}Hdmi_tx_video_para_t; - -typedef struct { - audio_type_t type; - audio_channel_t channel_num; - audio_fs_t sample_rate; - audio_sample_size_t sample_size; -}Hdmi_tx_audio_para_t; - -// ACR packet CTS parameters have 3 types: -// 1. HW auto calculated -// 2. Fixed values defined by Spec -// 3. Calculated by clock meter -typedef enum { - AUD_CTS_AUTO = 0, - AUD_CTS_FIXED, - AUD_CTS_CALC, -}Hdmi_tx_audio_cts_t; - -typedef struct -{ - audio_type_t type ; //!< Signal decoding type -- TvAudioType - audio_format_t format; - audio_channel_t channels ; //!< active audio channels bit mask. - audio_fs_t fs; //!< Signal sample rate in Hz - audio_sample_size_t ss; - hdmi_tx_audio_mclk_t audio_mclk; - -} Hdmi_tx_audio_info_t; - -//-----------------Source Physical Address--------------- -typedef struct { - unsigned char a:4; - unsigned char b:4; - unsigned char c:4; - unsigned char d:4; - unsigned char valid; -}vsdb_phy_addr_t; - - -typedef struct { - //Hdmi_tx_video_info_t video_info; - Hdmi_tx_audio_info_t audio_info; - hdmi_tx_sup_audio_info_t tv_audio_info; - hdcp_auth_state_t auth_state; - hdmi_tx_display_type_t output_state; -//-----------------Source Physical Address--------------- - vsdb_phy_addr_t vsdb_phy_addr; -//------------------------------------------------------- - unsigned video_out_changing_flag : 1; - unsigned support_underscan_flag : 1; - unsigned support_ycbcr444_flag : 1; - unsigned support_ycbcr422_flag : 1; - unsigned tx_video_input_stable_flag : 1; - unsigned auto_hdcp_ri_flag : 1; // If == 1, turn on Auto Ri Checking, user control - unsigned hw_sha_calculator_flag : 1; // If == 1, use the HW SHA calculator, otherwise, use SW SHA calculator, user control - unsigned need_sup_cec : 1; //, user control - -//------------------------------------------------------- - unsigned audio_out_changing_flag : 1; - unsigned audio_flag : 1; // 1 - enable hdmi audio; 0 - display hdmi audio, user control - unsigned support_basic_audio_flag : 1; - unsigned audio_fifo_overflow : 1; - unsigned audio_fifo_underflow : 1; - unsigned audio_cts_status_err_flag : 1; - unsigned support_ai_flag : 1; - unsigned hdmi_sup_480i : 1; - - -//------------------------------------------------------- - unsigned hdmi_sup_576i : 1; - unsigned hdmi_sup_480p : 1; - unsigned hdmi_sup_576p : 1; - unsigned hdmi_sup_720p_60hz : 1; - unsigned hdmi_sup_720p_50hz : 1; - unsigned hdmi_sup_1080i_60hz : 1; - unsigned hdmi_sup_1080i_50hz : 1; - unsigned hdmi_sup_1080p_60hz : 1; - - - -//------------------------------------------------------- - unsigned hdmi_sup_1080p_50hz : 1; - unsigned hdmi_sup_1080p_24hz : 1; - unsigned hdmi_sup_1080p_25hz : 1; - unsigned hdmi_sup_1080p_30hz : 1; - -//------------------------------------------------------- - - - - -}HDMI_TX_INFO_t; - - -#endif // _HDMI_RX_GLOBAL_H +#ifndef _HDMI_INFO_GLOBAL_H +#define _HDMI_INFO_GLOBAL_H + +typedef enum HDMI_Video_Type_ { + HDMI_Unkown = 0 , + HDMI_640x480p60 = 1 , + HDMI_480p60, + HDMI_480p60_16x9, + HDMI_720p60, + HDMI_1080i60, + HDMI_480i60, + HDMI_480i60_16x9, + HDMI_480i60_16x9_rpt = 11, + HDMI_1440x480p60 = 14 , + HDMI_1440x480p60_16x9 = 15 , + HDMI_1080p60 = 16, + HDMI_576p50, + HDMI_576p50_16x9, + HDMI_720p50, + HDMI_1080i50, + HDMI_576i50, + HDMI_576i50_16x9, + HDMI_576i50_16x9_rpt = 26, + HDMI_1080p50 = 31, + HDMI_1080p24, + HDMI_1080p25, + HDMI_1080p30, + HDMI_480p60_16x9_rpt = 36, + HDMI_576p50_16x9_rpt = 38, + HDMI_4k2k_24 = 93, // CEA-861-F + HDMI_4k2k_25, + HDMI_4k2k_30, + HDMI_4k2k_50, + HDMI_4k2k_60, + HDMI_4k2k_smpte_24 = 98, //24 Hz + HDMI_4k2k_smpte_50 = 101, + HDMI_4k2k_smpte_60, +} HDMI_Video_Codes_t ; + + +//-------------------HDMI VIDEO-------------------------------- +#define TYPE_AVI_INFOFRAMES 0x82 +#define AVI_INFOFRAMES_VERSION 0x02 +#define AVI_INFOFRAMES_LENGTH 0x0D + +typedef enum +{ + COLOR_SPACE_RGB444 = 0, + COLOR_SPACE_YUV422 = 1, + COLOR_SPACE_YUV444 = 2, +}color_space_type_t; + +typedef enum +{ + STATE_VIDEO__POWERDOWN = 0, + STATE_VIDEO__MUTED = 1, + STATE_VIDEO__UNMUTE = 2, + STATE_VIDEO__ON = 3, +}hdmi_rx_video_state_t; + + +typedef struct +{ + short H; // Number of horizontal pixels + short V; // Number of vertical pixels +}pixs_type_t; + + +typedef enum +{ + ASPECT_RATIO_SAME_AS_SOURCE= 0, + TV_ASPECT_RATIO_4_3, + TV_ASPECT_RATIO_16_9, + TV_ASPECT_RATIO_14_9, + ASPECT_RATIO_MAX +} hdmi_aspect_ratio_t; + +typedef enum +{ + COLOR_24BIT = 0, + COLOR_30BIT, + COLOR_36BIT, + COLOR_48BIT +} hdmi_color_depth_t; + +typedef enum +{ + NO_REPEAT = 0, + HDMI_2_TIMES_REPEAT, + HDMI_3_TIMES_REPEAT, + HDMI_4_TIMES_REPEAT, + HDMI_5_TIMES_REPEAT, + HDMI_6_TIMES_REPEAT, + HDMI_7_TIMES_REPEAT, + HDMI_8_TIMES_REPEAT, + HDMI_9_TIMES_REPEAT, + HDMI_10_TIMES_REPEAT, + MAX_TIMES_REPEAT, +} hdmi_pixel_repeat_t; + +typedef enum +{ + SS_NO_DATA = 0, + SS_SCAN_OVER, // where some active pixelsand lines at the edges are not displayed. + SS_SCAN_UNDER, // where all active pixels&lines are displayed, with or withouta border. + SS_RSV +} hdmi_scan_t; + + +typedef enum +{ + B_UNVALID = 0, + B_BAR_VERT, // Vert. Bar Infovalid + B_BAR_HORIZ, // Horiz. Bar Infovalid + B_BAR_VERT_HORIZ, //Vert.and Horiz. Bar Info valid +} hdmi_bar_info_t; + + +typedef enum +{ + CC_NO_DATA = 0, + CC_ITU601, + CC_ITU709, + CC_XVYCC601, + CC_XVYCC709, +} hdmi_colorimetry_t; + + +typedef enum +{ + SC_NO_UINFORM = 0, + SC_SCALE_HORIZ, //Picture has been scaled horizontally + SC_SCALE_VERT, //Picture has been scaled verticallv + SC_SCALE_HORIZ_VERT, //Picture has been scaled horizontally & SC_SCALE_H_V +} hdmi_slacing_t; + + + +typedef struct { + HDMI_Video_Codes_t VIC; + color_space_type_t color; + hdmi_color_depth_t color_depth; + hdmi_bar_info_t bar_info; + hdmi_pixel_repeat_t repeat_time; + hdmi_aspect_ratio_t aspect_ratio; + hdmi_colorimetry_t cc; + hdmi_scan_t ss; + hdmi_slacing_t sc; +}Hdmi_rx_video_info_t; +//-----------------------HDMI VIDEO END---------------------------------------- + + + +//-------------------HDMI AUDIO-------------------------------- +#define TYPE_AUDIO_INFOFRAMES 0x84 +#define AUDIO_INFOFRAMES_VERSION 0x01 +#define AUDIO_INFOFRAMES_LENGTH 0x0A + + +typedef enum +{ + CT_REFER_TO_STREAM = 0, + CT_PCM, + CT_AC_3, + CT_MPEG1, + CT_MP3, + CT_MPEG2, + CT_AAC, + CT_DTS, + CT_ATRAC, + CT_ONE_BIT_AUDIO, + CT_DOLBY_D, + CT_DTS_HD, + CT_MAT, + CT_DST, + CT_WMA, + CT_MAX, +} audio_type_t; + + +typedef enum +{ + CC_REFER_TO_STREAM = 0, + CC_2CH, + CC_3CH, + CC_4CH, + CC_5CH, + CC_6CH, + CC_7CH, + CC_8CH, + CC_MAX_CH +} audio_channel_t; + +typedef enum +{ + AF_SPDIF = 0, + AF_I2S, + AF_DSD, + AF_HBR, + AT_MAX +} audio_format_t; + + +//Sampling Freq Fs:0 - Refer to Stream Header; 1 - 32KHz; 2 - 44.1KHz; 3 - 48KHz; 4 - 88.2KHz... +typedef enum { + FS_REFER_TO_STREAM = 0, + FS_32K = 1, + FS_44K1 = 2, + FS_48K = 3, + FS_88K2 = 4, + FS_96K = 5, + FS_176K4 = 6, + FS_192K = 7, + FS_MAX, +}audio_fs_t; + +struct rate_map_fs { + unsigned int rate; + audio_fs_t fs; +}; + +typedef enum { + SS_REFER_TO_STREAM = 0, + SS_16BITS, + SS_20BITS, + SS_24BITS, + SS_MAX +}audio_sample_size_t; + +struct size_map_ss { + unsigned int sample_bits; + audio_sample_size_t ss; +}; + +//FL-- Front Left +//FC --Front Center +//FR --Front Right +//FLC-- Front Left Center +//FRC-- Front RiQhtCenter +//RL-- Rear Left +//RC --Rear Center +//RR-- Rear Right +//RLC-- Rear Left Center +//RRC --Rear RiQhtCenter +//LFE-- Low Frequency Effect +typedef enum { + CA_FR_FL = 0, + CA_LFE_FR_FL, + CA_FC_FR_FL, + CA_FC_LFE_FR_FL, + + CA_RC_FR_FL, + CA_RC_LFE_FR_FL, + CA_RC_FC_FR_FL, + CA_RC_FC_LFE_FR_FL, + + CA_RR_RL_FR_FL, + CA_RR_RL_LFE_FR_FL, + CA_RR_RL_FC_FR_FL, + CA_RR_RL_FC_LFE_FR_FL, + + CA_RC_RR_RL_FR_FL, + CA_RC_RR_RL_LFE_FR_FL, + CA_RC_RR_RL_FC_FR_FL, + CA_RC_RR_RL_FC_LFE_FR_FL, + + CA_RRC_RC_RR_RL_FR_FL, + CA_RRC_RC_RR_RL_LFE_FR_FL, + CA_RRC_RC_RR_RL_FC_FR_FL, + CA_RRC_RC_RR_RL_FC_LFE_FR_FL, + + CA_FRC_RLC_FR_FL, + CA_FRC_RLC_LFE_FR_FL, + CA_FRC_RLC_FC_FR_FL, + CA_FRC_RLC_FC_LFE_FR_FL, + + CA_FRC_RLC_RC_FR_FL, + CA_FRC_RLC_RC_LFE_FR_FL, + CA_FRC_RLC_RC_FC_FR_FL, + CA_FRC_RLC_RC_FC_LFE_FR_FL, + + CA_FRC_RLC_RR_RL_FR_FL, + CA_FRC_RLC_RR_RL_LFE_FR_FL, + CA_FRC_RLC_RR_RL_FC_FR_FL, + CA_FRC_RLC_RR_RL_FC_LFE_FR_FL, + +}speak_location_t; + +typedef enum { + LSV_0DB = 0, + LSV_1DB, + LSV_2DB, + LSV_3DB, + LSV_4DB, + LSV_5DB, + LSV_6DB, + LSV_7DB, + LSV_8DB, + LSV_9DB, + LSV_10DB, + LSV_11DB, + LSV_12DB, + LSV_13DB, + LSV_14DB, + LSV_15DB, + +}audio_down_mix_t; + +typedef enum +{ + STATE_AUDIO__MUTED = 0, + STATE_AUDIO__REQUEST_AUDIO = 1, + STATE_AUDIO__AUDIO_READY = 2, + STATE_AUDIO__ON = 3, +}hdmi_rx_audio_state_t; + +typedef struct +{ + audio_type_t type ; //!< Signal decoding type -- TvAudioType + audio_format_t format; + audio_channel_t channels ; //!< active audio channels bit mask. + audio_fs_t fs; //!< Signal sample rate in Hz + audio_sample_size_t ss; + speak_location_t speak_loc; + audio_down_mix_t lsv; + unsigned N_value; + unsigned CTS; +} Hdmi_rx_audio_info_t; + +#define HDMI_E_NONE 0x0 +// HPD Event & Status +#define E_HPD_PULG_IN 0x1 +#define E_HPD_PLUG_OUT 0x2 +#define S_HPD_PLUG_IN 0x1 +#define S_HPD_PLUG_OUT 0x0 + +#define E_HDCP_CHK_BKSV 0x1 + +typedef struct { + unsigned int event; + unsigned int stat; +}hdmi_mo_s; + +//-----------------------HDMI AUDIO END---------------------------------------- + + +//-------------------HDCP-------------------------------- +// HDCP keys from Efuse are encrypted by default, in this test HDCP keys are written by CPU with encryption manually added +#define ENCRYPT_KEY 0xbe + +typedef enum { + HDCP_NO_AUTH = 0, + HDCP_NO_DEVICE_WITH_SLAVE_ADDR , + HDCP_BCAP_ERROR , + HDCP_BKSV_ERROR , + HDCP_R0S_ARE_MISSMATCH , + HDCP_RIS_ARE_MISSMATCH , + HDCP_REAUTHENTATION_REQ , + HDCP_REQ_AUTHENTICATION , + HDCP_NO_ACK_FROM_DEV , + HDCP_NO_RSEN , + HDCP_AUTHENTICATED , + HDCP_REPEATER_AUTH_REQ , + HDCP_REQ_SHA_CALC , + HDCP_REQ_SHA_HW_CALC , + HDCP_FAILED_ViERROR , + HDCP_MAX +} hdcp_auth_state_t; + + + +//-----------------------HDCP END---------------------------------------- + + + + +//-------------------CEC------------------------------------- +#define CEC_MAX_CMD_SIZE 16 // defnes number of operands + +typedef enum +{ + CEC_LogAddr_TV = 0x00, + CEC_LogAddr_RecDev1 = 0x01, + CEC_LogAddr_RecDev2 = 0x02, + CEC_LogAddr_STB1 = 0x03, + CEC_LogAddr_DVD1 = 0x04, + CEC_LogAddr_AudSys = 0x05, + CEC_LogAddr_STB2 = 0x06, + CEC_LogAddr_STB3 = 0x07, + CEC_LogAddr_DVD2 = 0x08, + CEC_LogAddr_RecDev3 = 0x09, + CEC_LogAddr_Res1 = 0x0A, + CEC_LogAddr_Res2 = 0x0B, + CEC_LogAddr_Res3 = 0x0C, + CEC_LogAddr_Res4 = 0x0D, + CEC_LogAddr_FreeUse = 0x0E, + LOGADDR_UNREGORBC_MSG = 0x0F + +} CEC_LogAddr_t; + +typedef enum { + CEC_TV = 0, + CEC_DVD, + CEC_STB, + CEC_SW +} CECDev_t; + +typedef enum { + CEC_EnumTV = 0, + CEC_EnumDVD +} CEC_EnumType; + +typedef enum { + CEC_Idle = 0, + CEC_ReqPing, + CEC_ReqCmd1, + CEC_ReqCmd2, + CEC_ReqCmd3, + CEC_Enumiration +} CECOp_t; + +typedef enum { + CEC_TXWaitCmd, + CEC_TXSending, + CEC_TXSendAcked, + CEC_TXFailedToSend +} CEC_TXState; + +typedef enum +{ + CEC_POWERSTATUS_ON = 0x00, + CEC_POWERSTATUS_STANDBY = 0x01, + CEC_POWERSTATUS_STANDBY_TO_ON = 0x02, + CEC_POWERSTATUS_ON_TO_STANDBY = 0x03 + } POWER_STATUS_ET; + + +typedef struct { + unsigned char bRXState; + CEC_TXState bTXState; + unsigned char bCECErrors; + +} CEC_Int_t; + + +typedef struct +{ + unsigned char bCount; + unsigned char bRXNextCount; + unsigned char bDestOrRXHeader; + unsigned char bOpcode; + unsigned char bOperand[ CEC_MAX_CMD_SIZE ]; + +} CEC_t; +//-----------------------CEC END---------------------------------------- + + + +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- +//----------------------------------------------HDMI TX---------------------------------- +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- +typedef enum { + CABLE_UNPLUG = 0, + CABLE_PLUGIN_CHECK_EDID_I2C_ERROR , + CABLE_PLUGIN_CHECK_EDID_HEAD_ERROR, + CABLE_PLUGIN_CHECK_EDID_CHECKSUM_ERROR, + CABLE_PLUGIN_DVI_OUT , + CABLE_PLUGIN_HDMI_OUT , + CABLE_MAX +}hdmi_tx_display_type_t; + + + + //0b000 = MCLK is 128*Fs + //0b001 = MCLK is 256*Fs (recommanded) + //0b010 = MCLK is 384*Fs + //0b011 = MCLK is 512*Fs + //0b100 = MCLK is 768*Fs + //0b101 = MCLK is 1024*Fs + //0b110 = MCLK is 1152*Fs + //0b111 = MCLK is 192*Fs +typedef enum { + MCLK_128_Fs = 0, + MCLK_256_Fs , + MCLK_384_Fs , + MCLK_512_Fs , + MCLK_768_Fs, + MCLK_1024_Fs, + MCLK_1152_Fs +} hdmi_tx_audio_mclk_t; + +typedef struct{ + int hpd_state : 1; + int support_480i : 1; + int support_576i : 1; + int support_480p : 1; + int support_576p : 1; + int support_720p_60hz : 1; + int support_720p_50hz : 1; + int support_1080i_60hz : 1; + int support_1080i_50hz : 1; + int support_1080p_60hz : 1; + int support_1080p_50hz : 1; + int support_1080p_24hz : 1; + int support_1080p_25hz : 1; + int support_1080p_30hz : 1; +}hdmi_tx_sup_status_t; + + + +typedef struct{ + int support_flag : 1; + int max_channel_num : 3; + int _192k : 1; + int _176k : 1; + int _96k : 1; + int _88k : 1; + int _48k : 1; + int _44k : 1; + int _32k : 1; + int _24bit : 1; + int _20bit : 1; + int _16bit : 1; +}hdmi_tx_sup_lpcm_info_t; + + +typedef struct{ + int support_flag : 1; + int max_channel_num : 3; + int _192k : 1; + int _176k : 1; + int _96k : 1; + int _88k : 1; + int _48k : 1; + int _44k : 1; + int _32k : 1; + int _max_bit : 10; +}hdmi_tx_sup_compressed_info_t; + +typedef struct{ + int rlc_rrc : 1; + int flc_frc : 1; + int rc : 1; + int rl_rr : 1; + int fc : 1; + int lfe : 1; + int fl_fr : 1; +}hdmi_tx_sup_speaker_format_t; + + +typedef struct{ + hdmi_tx_sup_lpcm_info_t _60958_PCM; + hdmi_tx_sup_compressed_info_t _AC3; + hdmi_tx_sup_compressed_info_t _MPEG1; + hdmi_tx_sup_compressed_info_t _MP3; + hdmi_tx_sup_compressed_info_t _MPEG2; + hdmi_tx_sup_compressed_info_t _AAC; + hdmi_tx_sup_compressed_info_t _DTS; + hdmi_tx_sup_compressed_info_t _ATRAC; + hdmi_tx_sup_compressed_info_t _One_Bit_Audio; + hdmi_tx_sup_compressed_info_t _Dolby; + hdmi_tx_sup_compressed_info_t _DTS_HD; + hdmi_tx_sup_compressed_info_t _MAT; + hdmi_tx_sup_compressed_info_t _DST; + hdmi_tx_sup_compressed_info_t _WMA; + hdmi_tx_sup_speaker_format_t speaker_allocation; +}hdmi_tx_sup_audio_info_t; + + +typedef struct { + unsigned char VIC; + color_space_type_t color_prefer; + color_space_type_t color; + hdmi_color_depth_t color_depth; + hdmi_bar_info_t bar_info; + hdmi_pixel_repeat_t repeat_time; + hdmi_aspect_ratio_t aspect_ratio; + hdmi_colorimetry_t cc; + hdmi_scan_t ss; + hdmi_slacing_t sc; +}Hdmi_tx_video_para_t; + +typedef struct { + audio_type_t type; + audio_channel_t channel_num; + audio_fs_t sample_rate; + audio_sample_size_t sample_size; +}Hdmi_tx_audio_para_t; + +// ACR packet CTS parameters have 3 types: +// 1. HW auto calculated +// 2. Fixed values defined by Spec +// 3. Calculated by clock meter +typedef enum { + AUD_CTS_AUTO = 0, + AUD_CTS_FIXED, + AUD_CTS_CALC, +}Hdmi_tx_audio_cts_t; + +typedef struct +{ + audio_type_t type ; //!< Signal decoding type -- TvAudioType + audio_format_t format; + audio_channel_t channels ; //!< active audio channels bit mask. + audio_fs_t fs; //!< Signal sample rate in Hz + audio_sample_size_t ss; + hdmi_tx_audio_mclk_t audio_mclk; + +} Hdmi_tx_audio_info_t; + +//-----------------Source Physical Address--------------- +typedef struct { + unsigned char a:4; + unsigned char b:4; + unsigned char c:4; + unsigned char d:4; + unsigned char valid; +}vsdb_phy_addr_t; + + +typedef struct { + //Hdmi_tx_video_info_t video_info; + Hdmi_tx_audio_info_t audio_info; + hdmi_tx_sup_audio_info_t tv_audio_info; + hdcp_auth_state_t auth_state; + hdmi_tx_display_type_t output_state; +//-----------------Source Physical Address--------------- + vsdb_phy_addr_t vsdb_phy_addr; +//------------------------------------------------------- + unsigned video_out_changing_flag : 1; + unsigned support_underscan_flag : 1; + unsigned support_ycbcr444_flag : 1; + unsigned support_ycbcr422_flag : 1; + unsigned tx_video_input_stable_flag : 1; + unsigned auto_hdcp_ri_flag : 1; // If == 1, turn on Auto Ri Checking, user control + unsigned hw_sha_calculator_flag : 1; // If == 1, use the HW SHA calculator, otherwise, use SW SHA calculator, user control + unsigned need_sup_cec : 1; //, user control + +//------------------------------------------------------- + unsigned audio_out_changing_flag : 1; + unsigned audio_flag : 1; // 1 - enable hdmi audio; 0 - display hdmi audio, user control + unsigned support_basic_audio_flag : 1; + unsigned audio_fifo_overflow : 1; + unsigned audio_fifo_underflow : 1; + unsigned audio_cts_status_err_flag : 1; + unsigned support_ai_flag : 1; + unsigned hdmi_sup_480i : 1; + + +//------------------------------------------------------- + unsigned hdmi_sup_576i : 1; + unsigned hdmi_sup_480p : 1; + unsigned hdmi_sup_576p : 1; + unsigned hdmi_sup_720p_60hz : 1; + unsigned hdmi_sup_720p_50hz : 1; + unsigned hdmi_sup_1080i_60hz : 1; + unsigned hdmi_sup_1080i_50hz : 1; + unsigned hdmi_sup_1080p_60hz : 1; + + + +//------------------------------------------------------- + unsigned hdmi_sup_1080p_50hz : 1; + unsigned hdmi_sup_1080p_24hz : 1; + unsigned hdmi_sup_1080p_25hz : 1; + unsigned hdmi_sup_1080p_30hz : 1; + +//------------------------------------------------------- + + + + +}HDMI_TX_INFO_t; + + +#endif // _HDMI_RX_GLOBAL_H diff --git a/include/linux/amlogic/vout/vinfo.h b/include/linux/amlogic/vout/vinfo.h index 7ab626cb1176..e7d070af1855 100755 --- a/include/linux/amlogic/vout/vinfo.h +++ b/include/linux/amlogic/vout/vinfo.h @@ -1,80 +1,80 @@ -/* - * Amlogic Apollo - * frame buffer driver - * - * Copyright (C) 2009 Amlogic, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the named License, - * or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA - * - * Author: Tim Yao - * - */ - -#ifndef VINFO_H -#define VINFO_H -//the MSB is represent vmode set by logo -#define VMODE_LOGO_BIT_MASK 0x8000 -#define VMODE_MODE_BIT_MASK 0xff -typedef enum { - VMODE_480I = 0, - VMODE_480I_RPT , - VMODE_480CVBS, - VMODE_480P , - VMODE_480P_RPT , - VMODE_576I , - VMODE_576I_RPT , - VMODE_576CVBS , - VMODE_576P , - VMODE_576P_RPT , - VMODE_720P , - VMODE_1080I , - VMODE_1080P , - VMODE_720P_50HZ , - VMODE_1080I_50HZ , - VMODE_1080P_50HZ , - VMODE_1080P_24HZ , - VMODE_4K2K_30HZ , - VMODE_4K2K_25HZ , - VMODE_4K2K_24HZ , - VMODE_4K2K_SMPTE, - VMODE_VGA, - VMODE_SVGA, - VMODE_XGA, - VMODE_SXGA, - VMODE_LCD , - VMODE_LVDS_1080P, - VMODE_LVDS_1080P_50HZ, - VMODE_LVDS_768P, - VMODE_MAX, - VMODE_INIT_NULL, - VMODE_MASK = 0xFF, -} vmode_t; - -typedef struct { - char *name; - vmode_t mode; - u32 width; - u32 height; - u32 field_height; - u32 aspect_ratio_num; - u32 aspect_ratio_den; - u32 sync_duration_num; - u32 sync_duration_den; - u32 screen_real_width; - u32 screen_real_height; - u32 video_clk; -} vinfo_t; - -#endif /* TVMODE_H */ +/* + * Amlogic Apollo + * frame buffer driver + * + * Copyright (C) 2009 Amlogic, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Tim Yao + * + */ + +#ifndef VINFO_H +#define VINFO_H +//the MSB is represent vmode set by logo +#define VMODE_LOGO_BIT_MASK 0x8000 +#define VMODE_MODE_BIT_MASK 0xff +typedef enum { + VMODE_480I = 0, + VMODE_480I_RPT , + VMODE_480CVBS, + VMODE_480P , + VMODE_480P_RPT , + VMODE_576I , + VMODE_576I_RPT , + VMODE_576CVBS , + VMODE_576P , + VMODE_576P_RPT , + VMODE_720P , + VMODE_1080I , + VMODE_1080P , + VMODE_720P_50HZ , + VMODE_1080I_50HZ , + VMODE_1080P_50HZ , + VMODE_1080P_24HZ , + VMODE_4K2K_30HZ , + VMODE_4K2K_25HZ , + VMODE_4K2K_24HZ , + VMODE_4K2K_SMPTE, + VMODE_VGA, + VMODE_SVGA, + VMODE_XGA, + VMODE_SXGA, + VMODE_LCD , + VMODE_LVDS_1080P, + VMODE_LVDS_1080P_50HZ, + VMODE_LVDS_768P, + VMODE_MAX, + VMODE_INIT_NULL, + VMODE_MASK = 0xFF, +} vmode_t; + +typedef struct { + char *name; + vmode_t mode; + u32 width; + u32 height; + u32 field_height; + u32 aspect_ratio_num; + u32 aspect_ratio_den; + u32 sync_duration_num; + u32 sync_duration_den; + u32 screen_real_width; + u32 screen_real_height; + u32 video_clk; +} vinfo_t; + +#endif /* TVMODE_H */