From 04f88ca2add0f5425624da422508fdcd48563d4c Mon Sep 17 00:00:00 2001 From: kfx Date: Mon, 20 Dec 2010 14:58:15 +0800 Subject: [PATCH] add hdmi driver --- arch/arm/mach-rk29/board-rk29sdk.c | 9 + drivers/video/Kconfig | 1 + drivers/video/Makefile | 2 +- drivers/video/display/screen/screen.h | 2 + drivers/video/hdmi/Kconfig | 19 + drivers/video/hdmi/Makefile | 2 + drivers/video/hdmi/chips/Kconfig | 7 + drivers/video/hdmi/chips/Makefile | 2 + drivers/video/hdmi/chips/anx7150.c | 461 +++ drivers/video/hdmi/chips/anx7150.h | 102 + drivers/video/hdmi/chips/anx7150_hw.c | 4196 ++++++++++++++++++++++++ drivers/video/hdmi/chips/anx7150_hw.h | 1263 +++++++ drivers/video/hdmi/chips/anx7150_sys.c | 492 +++ drivers/video/hdmi/hdmi-codec.c | 6 + drivers/video/hdmi/hdmi-core.c | 129 + drivers/video/hdmi/hdmi-fb.c | 196 ++ drivers/video/hdmi/hdmi-sysfs.c | 162 + drivers/video/rk29_fb.c | 1304 ++++---- include/linux/hdmi.h | 70 + 19 files changed, 7813 insertions(+), 612 deletions(-) mode change 100644 => 100755 arch/arm/mach-rk29/board-rk29sdk.c create mode 100644 drivers/video/hdmi/Kconfig create mode 100644 drivers/video/hdmi/Makefile create mode 100644 drivers/video/hdmi/chips/Kconfig create mode 100644 drivers/video/hdmi/chips/Makefile create mode 100755 drivers/video/hdmi/chips/anx7150.c create mode 100755 drivers/video/hdmi/chips/anx7150.h create mode 100755 drivers/video/hdmi/chips/anx7150_hw.c create mode 100755 drivers/video/hdmi/chips/anx7150_hw.h create mode 100755 drivers/video/hdmi/chips/anx7150_sys.c create mode 100644 drivers/video/hdmi/hdmi-codec.c create mode 100755 drivers/video/hdmi/hdmi-core.c create mode 100755 drivers/video/hdmi/hdmi-fb.c create mode 100755 drivers/video/hdmi/hdmi-sysfs.c create mode 100755 include/linux/hdmi.h diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c old mode 100644 new mode 100755 index 89241e720f86..165de22e2922 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -521,6 +521,15 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = { .irq = RK29_PIN4_PA1, }, #endif +#if defined (CONFIG_ANX7150) + { + .type = "anx7150", + .addr = 0x39, //0x39, 0x3d + .flags = 0, + .irq = RK29_PIN1_PD7, + }, +#endif + }; #endif diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cab6a9a4e086..69339f4ab77f 100755 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2183,6 +2183,7 @@ source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" +source "drivers/video/hdmi/Kconfig" if VT source "drivers/video/console/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 6a0202b22b1e..2bf73ccd6c09 100755 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -13,7 +13,7 @@ fb-objs := $(fb-y) obj-$(CONFIG_VT) += console/ obj-$(CONFIG_LOGO) += logo/ -obj-y += backlight/ display/ +obj-y += backlight/ display/ hdmi/ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o diff --git a/drivers/video/display/screen/screen.h b/drivers/video/display/screen/screen.h index b661d07655d7..fb9c3f08e567 100755 --- a/drivers/video/display/screen/screen.h +++ b/drivers/video/display/screen/screen.h @@ -1,3 +1,5 @@ +#include + typedef enum _SCREEN_TYPE { SCREEN_NULL = 0, SCREEN_RGB, diff --git a/drivers/video/hdmi/Kconfig b/drivers/video/hdmi/Kconfig new file mode 100644 index 000000000000..8a8d284580fb --- /dev/null +++ b/drivers/video/hdmi/Kconfig @@ -0,0 +1,19 @@ +# +# Display drivers configuration +# + +menu "HDMI support" + +config HDMI + tristate "hdmi support" + help + nothing +if HDMI +source "drivers/video/hdmi/chips/Kconfig" +config HDMI_DEBUG + bool "hdmi debug" + help + nothing +endif + +endmenu diff --git a/drivers/video/hdmi/Makefile b/drivers/video/hdmi/Makefile new file mode 100644 index 000000000000..dcc0426e4189 --- /dev/null +++ b/drivers/video/hdmi/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_HDMI) += hdmi-core.o hdmi-sysfs.o hdmi-fb.o hdmi-codec.o +obj-$(CONFIG_HDMI) += chips/ diff --git a/drivers/video/hdmi/chips/Kconfig b/drivers/video/hdmi/chips/Kconfig new file mode 100644 index 000000000000..a1b838f76179 --- /dev/null +++ b/drivers/video/hdmi/chips/Kconfig @@ -0,0 +1,7 @@ +choice + prompt "HDMI chips select" +config ANX7150 + bool "anx7150" +config ANX9030 + bool "anx9030" +endchoice diff --git a/drivers/video/hdmi/chips/Makefile b/drivers/video/hdmi/chips/Makefile new file mode 100644 index 000000000000..92959ebe9772 --- /dev/null +++ b/drivers/video/hdmi/chips/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ANX7150) += anx7150_hw.o anx7150.o + diff --git a/drivers/video/hdmi/chips/anx7150.c b/drivers/video/hdmi/chips/anx7150.c new file mode 100755 index 000000000000..9bddc080b4df --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150.c @@ -0,0 +1,461 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "anx7150.h" +#include "anx7150_hw.h" + +int anx7150_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val) +{ + client->addr = ANX7150_I2C_ADDR0; + return i2c_master_reg8_recv(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL; +} +int anx7150_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val) +{ + client->addr = ANX7150_I2C_ADDR0; + return i2c_master_reg8_send(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL; +} +int anx7150_i2c_read_p1_reg(struct i2c_client *client, char reg, char *val) +{ + client->addr = ANX7150_I2C_ADDR1; + return i2c_master_reg8_recv(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL; +} +int anx7150_i2c_write_p1_reg(struct i2c_client *client, char reg, char *val) +{ + client->addr = ANX7150_I2C_ADDR1; + return i2c_master_reg8_send(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL; +} + +static int rk29_hdmi_enter(struct anx7150_dev_s *dev) +{ + if(dev->rk29_output_status == RK29_OUTPUT_STATUS_LCD) { + printk("%s, resolution = %d\n", __func__, dev->resolution_real); + if(hdmi_switch_fb(dev->resolution_real, 1) < 0) + return -1; + dev->hdmi->resolution = dev->resolution_real; + dev->rk29_output_status = RK29_OUTPUT_STATUS_HDMI; + } + return 0; +} +static int rk29_hdmi_exit(struct anx7150_dev_s *dev) +{ + if(dev->rk29_output_status == RK29_OUTPUT_STATUS_HDMI) { + printk("%s\n", __func__); + if(hdmi_switch_fb(dev->resolution_real, 0) < 0) + return -1; + dev->rk29_output_status = RK29_OUTPUT_STATUS_LCD; + } + return 0; +} + +static int anx7150_display_on(struct hdmi* hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + rk29_hdmi_enter(&anx->dev); + hdmi->display_on = HDMI_ENABLE; + anx->dev.hdmi_enable = HDMI_ENABLE; + anx->dev.parameter_config = 1; + hdmi_dbg(hdmi->dev, "hdmi display on\n"); + return 0; +} +static int anx7150_display_off(struct hdmi* hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + rk29_hdmi_exit(&anx->dev); + hdmi->display_on = HDMI_DISABLE; + anx->dev.hdmi_enable = HDMI_DISABLE; + anx->dev.parameter_config = 1; + hdmi_dbg(hdmi->dev, "hdmi display off\n"); + return 0; +} +static int anx7150_set_param(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->dev.resolution_set = hdmi->resolution; + anx->dev.i2s_Fs = hdmi->audio_fs; + anx->dev.hdcp_enable = hdmi->hdcp_on; + anx->dev.hdmi_auto_switch = hdmi->auto_switch; + anx->dev.parameter_config = 1; + + return 0; +} +static int anx7150_core_init(struct hdmi *hdmi) +{ + //struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + return 0; +} +static irqreturn_t anx7150_detect_irq(int irq, void *dev_id) +{ + //struct hdmi *hdmi = (struct hdmi *)dev_id; + + return IRQ_HANDLED; +} + +void anx7150_task(struct anx7150_pdata *anx) +{ + int state; + int ret; + + //anx->dev.anx7150_detect = anx7150_detect_device(anx); + if(anx->dev.anx7150_detect == 0) + goto out; + + state = ANX7150_Get_System_State(); + + if(anx->dev.parameter_config){ + if(state > WAIT_HDMI_ENABLE) + state = WAIT_HDMI_ENABLE; + anx->dev.parameter_config = 0; + anx->dev.fb_switch_state = 1; + } + if(anx->dev.hdmi_enable == HDMI_DISABLE && anx->dev.hdmi_auto_switch == HDMI_DISABLE){ + //if(state > WAIT_HDMI_ENABLE) + state = HDMI_INITIAL; + } + + state = ANX7150_Interrupt_Process(anx, state); + + switch(state){ + case HDMI_INITIAL: + if(anx->dev.hdmi_auto_switch) + rk29_hdmi_exit(&anx->dev); + ANX7150_API_Initial(anx->client); + state = WAIT_HOTPLUG; + if(anx->dev.hdmi_auto_switch) + anx->dev.rate = 1; + else + anx->dev.rate = 100; + break; + + case WAIT_HOTPLUG: + if(anx->dev.hdmi_auto_switch) + rk29_hdmi_exit(&anx->dev); + if(anx->dev.HPD_status){ + anx7150_plug(anx->client); + state = READ_PARSE_EDID; + } + if(anx->dev.hdmi_auto_switch) + anx->dev.rate = 50; + else + anx->dev.rate = 100; + break; + + case READ_PARSE_EDID: + ret = ANX7150_Parse_EDID(anx->client,&anx->dev); + if(ret != 0){ + dev_err(&anx->client->dev, "Parse_EDID err, ret=%d\n", ret); + } + + state = WAIT_RX_SENSE; + if(anx->dev.hdmi_auto_switch) + anx->dev.rate = 50; + else + anx->dev.rate = 100; + + break; + + case WAIT_RX_SENSE: + if(ANX7150_GET_SENSE_STATE(anx->client) == 1){ + hdmi_dbg(&anx->client->dev, "reciver active\n"); + state = WAIT_HDMI_ENABLE; + anx->dev.reciver_status = HDMI_RECIVER_ACTIVE; + hdmi_changed(anx->dev.hdmi, 1); + } + + if(anx->dev.hdmi_auto_switch) + anx->dev.rate = 50; + else + anx->dev.rate = 100; + + break; + + case WAIT_HDMI_ENABLE: + if(!anx->dev.hdmi_enable && anx->dev.hdmi_auto_switch) + rk29_hdmi_exit(&anx->dev); + if(anx->dev.hdmi_enable && + (anx->dev.hdmi_auto_switch || anx->init ||anx->dev.parameter_config)) { + rk29_hdmi_enter(&anx->dev); + anx->init = 0; + } + + /* + if(1 || anx->dev.rk29_output_status == RK29_OUTPUT_STATUS_HDMI){ + state = SYSTEM_CONFIG; + anx->dev.rate = 1; + } + */ + state = SYSTEM_CONFIG; + if(anx->dev.hdmi_auto_switch) + anx->dev.rate = 50; + else + anx->dev.rate = 100; + + break; + + case SYSTEM_CONFIG: + anx->dev.resolution_real = ANX7150_Get_Optimal_resolution(anx->dev.resolution_set); + HDMI_Set_Video_Format(anx->dev.resolution_real); + HDMI_Set_Audio_Fs(anx->dev.i2s_Fs); + ANX7150_API_HDCP_ONorOFF(anx->dev.hdcp_enable); + ANX7150_API_System_Config(); + state = CONFIG_VIDEO; + + anx->dev.rate = 1; + if(anx->dev.fb_switch_state && anx->dev.rk29_output_status == RK29_OUTPUT_STATUS_HDMI) { + anx->dev.rk29_output_status = RK29_OUTPUT_STATUS_LCD; + rk29_hdmi_enter(&anx->dev); + anx->dev.fb_switch_state = 0; + } + break; + + case CONFIG_VIDEO: + if(ANX7150_Config_Video(anx->client) == 0){ + if(ANX7150_GET_RECIVER_TYPE() == 1) + state = CONFIG_AUDIO; + else + state = HDCP_AUTHENTICATION; + + anx->dev.rate = 50; + } + + anx->dev.rate = 10; + break; + + case CONFIG_AUDIO: + ANX7150_Config_Audio(anx->client); + state = CONFIG_PACKETS; + anx->dev.rate = 1; + break; + + case CONFIG_PACKETS: + ANX7150_Config_Packet(anx->client); + state = HDCP_AUTHENTICATION; + anx->dev.rate = 1; + break; + + case HDCP_AUTHENTICATION: + ANX7150_HDCP_Process(anx->client); + state = PLAY_BACK; + anx->dev.rate = 100; + break; + + case PLAY_BACK: + ret = ANX7150_PLAYBACK_Process(); + if(ret == 1){ + state = CONFIG_PACKETS; + anx->dev.rate = 1; + } + + anx->dev.rate = 100; + break; + + default: + state = HDMI_INITIAL; + anx->dev.rate = 100; + break; + } + + if(state != ANX7150_Get_System_State()){ + ANX7150_Set_System_State(anx->client, state); + } + +out: + return; +} + +static void anx7150_work_func(struct work_struct * work) +{ + struct anx7150_dev_s *dev = container_of((void *)work, struct anx7150_dev_s, delay_work); + struct hdmi *hdmi = dev->hdmi; + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx7150_task(anx); +/* + if(dev->hdmi_auto_switch) + { + if(dev->HPD_status == HDMI_RECIVER_PLUG) + { + rk29_hdmi_enter(dev); + } + else + { + rk29_hdmi_exit(dev); + } + } + else + { + if(dev->hdmi_enable) + { + rk29_hdmi_enter(dev); + } + else + { + rk29_hdmi_exit(dev); + } + } +*/ + if(dev->anx7150_detect) + { + queue_delayed_work(dev->workqueue, &dev->delay_work, dev->rate); + } + else + { + hdmi_dbg(hdmi->dev, "ANX7150 not exist!\n"); + rk29_hdmi_exit(dev); + } + return; +} +static int anx7150_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + int rc = 0; + struct hdmi *hdmi = NULL; + struct anx7150_pdata *anx = NULL; + + hdmi = kzalloc(sizeof(struct hdmi), GFP_KERNEL); + if (!hdmi) + { + dev_err(&client->dev, "no memory for state\n"); + return -ENOMEM; + } + anx = kzalloc(sizeof(struct anx7150_pdata), GFP_KERNEL); + if(!anx) + { + dev_err(&client->dev, "no memory for state\n"); + goto err_kzalloc_anx; + } + anx->client = client; + anx->dev.anx7150_detect = 0; + anx->dev.resolution_set = HDMI_DEFAULT_RESOLUTION; + anx->dev.i2s_Fs = HDMI_I2S_DEFAULT_Fs; + anx->dev.hdmi_enable = HDMI_ENABLE; + anx->dev.hdmi_auto_switch = HDMI_AUTO_SWITCH; + anx->dev.reciver_status = HDMI_RECIVER_INACTIVE; + anx->dev.HPD_status = HDMI_RECIVER_UNPLUG; + anx->dev.HPD_change_cnt = 0; + anx->dev.rk29_output_status = RK29_OUTPUT_STATUS_LCD; + anx->dev.hdcp_enable = ANX7150_HDCP_EN; + + anx->init = 1; + + anx->dev.workqueue = create_singlethread_workqueue("ANX7150_WORKQUEUE"); + INIT_DELAYED_WORK(&anx->dev.delay_work, anx7150_work_func); + + hdmi->display_on = 0; + hdmi->auto_switch = anx->dev.hdmi_auto_switch; + hdmi->hdcp_on = anx->dev.hdcp_enable; + hdmi->audio_fs = anx->dev.i2s_Fs; + hdmi->resolution = anx->dev.resolution_set; + hdmi->dev = &client->dev; + hdmi->hdmi_display_on = anx7150_display_on; + hdmi->hdmi_display_off = anx7150_display_off; + hdmi->hdmi_set_param = anx7150_set_param; + hdmi->hdmi_core_init = anx7150_core_init; + + if((rc = hdmi_register(&client->dev, hdmi)) < 0) + { + dev_err(&client->dev, "fail to register hdmi\n"); + goto err_hdmi_register; + } + + if((rc = gpio_request(client->irq, "hdmi gpio")) < 0) + { + dev_err(&client->dev, "fail to request gpio %d\n", client->irq); + goto err_request_gpio; + } + + anx->irq = gpio_to_irq(client->irq); + anx->gpio = client->irq; + + anx->dev.hdmi = hdmi; + hdmi_set_privdata(hdmi, anx); + + i2c_set_clientdata(client, anx); + gpio_pull_updown(client->irq,GPIOPullUp); + + if((rc = request_irq(anx->irq, anx7150_detect_irq,IRQF_TRIGGER_FALLING,NULL,hdmi)) <0) + { + dev_err(&client->dev, "fail to request hdmi irq\n"); + goto err_request_irq; + } + anx->dev.anx7150_detect = anx7150_detect_device(anx); + if(anx->dev.anx7150_detect) { + ANX7150_API_Initial(client); + queue_delayed_work(anx->dev.workqueue, &anx->dev.delay_work, 200); + } + hdmi_dbg(&client->dev, "anx7150 i2c probe ok\n"); + return 0; + +err_request_irq: + gpio_free(client->irq); +err_request_gpio: + hdmi_unregister(hdmi); +err_hdmi_register: + destroy_workqueue(anx->dev.workqueue); + kfree(anx); + anx = NULL; +err_kzalloc_anx: + kfree(hdmi); + hdmi = NULL; + return rc; + +} + +static int __devexit anx7150_i2c_remove(struct i2c_client *client) +{ + struct anx7150_pdata *anx = (struct anx7150_pdata *)i2c_get_clientdata(client); + struct hdmi *hdmi = anx->dev.hdmi; + + free_irq(anx->irq, NULL); + gpio_free(client->irq); + hdmi_unregister(hdmi); + destroy_workqueue(anx->dev.workqueue); + kfree(anx); + anx = NULL; + kfree(hdmi); + hdmi = NULL; + + hdmi_dbg(hdmi->dev, "%s\n", __func__); + return 0; +} + +static const struct i2c_device_id anx7150_id[] = { + { "anx7150", 0 }, + { } +}; + +static struct i2c_driver anx7150_i2c_driver = { + .driver = { + .name = "anx7150", + .owner = THIS_MODULE, + }, + .probe = &anx7150_i2c_probe, + .remove = &anx7150_i2c_remove, + .id_table = anx7150_id, +}; + + +static int __init anx7150_init(void) +{ + return i2c_add_driver(&anx7150_i2c_driver); +} + +static void __exit anx7150_exit(void) +{ + i2c_del_driver(&anx7150_i2c_driver); +} + +//module_init(anx7150_init); +fs_initcall(anx7150_init); +module_exit(anx7150_exit); + + diff --git a/drivers/video/hdmi/chips/anx7150.h b/drivers/video/hdmi/chips/anx7150.h new file mode 100755 index 000000000000..b9289337dad6 --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150.h @@ -0,0 +1,102 @@ +#ifndef _ANX7150_H +#define _ANX7150_H + +#include + +#define ANX7150_I2C_ADDR0 0X39 +#define ANX7150_I2C_ADDR1 0X3d + +#define ANX7150_SCL_RATE 100 * 1000 + +/* HDMI STATUS */ +#define HDMI_DISABLE 0 +#define HDMI_ENABLE 1 + +/* HDMI auto switch */ +#define HDMI_AUTO_SWITCH HDMI_ENABLE + +/* HDMI reciver status */ +#define HDMI_RECIVER_INACTIVE 0 +#define HDMI_RECIVER_ACTIVE 1 + +/* ANX7150 reciver HPD Status */ +#define HDMI_RECIVER_UNPLUG 0 +#define HDMI_RECIVER_PLUG 1 + +#define LCD 0 +#define HDMI 1 + +#define RK29_OUTPUT_STATUS_LCD LCD +#define RK29_OUTPUT_STATUS_HDMI HDMI + +/* HDMI HDCP ENABLE */ +#define ANX7150_HDCP_EN HDMI_DISABLE + +/* HDMI default resolution */ +#define HDMI_DEFAULT_RESOLUTION HDMI_1280x720p_50Hz +/* I2S Fs */ +#define HDMI_I2S_Fs_44100 0 +#define HDMI_I2S_Fs_48000 2 + +/* I2S default sample rate */ +#define HDMI_I2S_DEFAULT_Fs HDMI_I2S_Fs_48000 + +/* ANX7150 state machine */ +enum{ + HDMI_INITIAL = 1, + WAIT_HOTPLUG, + READ_PARSE_EDID, + WAIT_RX_SENSE, + WAIT_HDMI_ENABLE, + SYSTEM_CONFIG, + CONFIG_VIDEO, + CONFIG_AUDIO, + CONFIG_PACKETS, + HDCP_AUTHENTICATION, + PLAY_BACK, + RESET_LINK, + UNKNOWN, +}; + + +struct anx7150_dev_s{ + struct i2c_driver *i2c_driver; + struct fasync_struct *async_queue; + struct workqueue_struct *workqueue; + struct delayed_work delay_work; + struct miscdevice *mdev; + void (*notifier_callback)(struct anx7150_dev_s *); + int anx7150_detect; + int resolution_set; + int resolution_real; + int i2s_Fs; + int hdmi_enable; + int hdmi_auto_switch; + int reciver_status; + int HPD_change_cnt; + int HPD_status; + int rk29_output_status; + int hdcp_enable; + int parameter_config; + int rate; + int fb_switch_state; + + struct hdmi *hdmi; +}; + +struct anx7150_pdata { + int irq; + int gpio; + int init; + struct i2c_client *client; + struct anx7150_dev_s dev; +}; + + + +int anx7150_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val); +int anx7150_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val); +int anx7150_i2c_read_p1_reg(struct i2c_client *client, char reg, char *val); +int anx7150_i2c_write_p1_reg(struct i2c_client *client, char reg, char *val); + +#endif diff --git a/drivers/video/hdmi/chips/anx7150_hw.c b/drivers/video/hdmi/chips/anx7150_hw.c new file mode 100755 index 000000000000..39cd987460ec --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150_hw.c @@ -0,0 +1,4196 @@ +#include +#include +#include + + +#include "anx7150.h" +#include "anx7150_hw.h" +//#ifdef ITU656 +struct ANX7150_video_timingtype ANX7150_video_timingtype_table = +{ + //640x480p-60hz + {0x20/*H_RES_LOW*/, 0x03/*H_RES_HIGH*/,0x80 /*ACT_PIX_LOW*/,0x02 /*ACT_PIX_HIGH*/, + 0x60/*HSYNC_WIDTH_LOW*/,0x00 /*HSYNC_WIDTH_HIGH*/,0x30 /*H_BP_LOW*/,0x00 /*H_BP_HIGH*/, + 0xe0/*ACT_LINE_LOW*/, 0x01/*ACT_LINE_HIGH*/,0x02 /*VSYNC_WIDTH*/, 0x21/*V_BP_LINE*/, + 0x0a/*V_FP_LINE*/,0x10 /*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Progressive, ANX7150_Neg_Hsync_pol, ANX7150_Neg_Vsync_pol}, + //720x480p-60hz + {0x5a/*H_RES_LOW*/,0x03 /*H_RES_HIGH*/,0xd0/*ACT_PIX_LOW*/, 0x02/*ACT_PIX_HIGH*/, + 0x3e/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x3c/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0xe0/*ACT_LINE_LOW*/, 0x01/*ACT_LINE_HIGH*/, 0x06/*VSYNC_WIDTH*/, 0x1e/*V_BP_LINE*/, + 0x09/*V_FP_LINE*/, 0x10/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Progressive, ANX7150_Neg_Hsync_pol, ANX7150_Neg_Vsync_pol}, + //720p-60hz + {0x72/*H_RES_LOW*/, 0x06/*H_RES_HIGH*/, 0x00/*ACT_PIX_LOW*/, 0x05/*ACT_PIX_HIGH*/, + 0x28/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0xdc/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0xd0/*ACT_LINE_LOW*/, 0x02/*ACT_LINE_HIGH*/, 0x05/*VSYNC_WIDTH*/, 0x14/*V_BP_LINE*/, + 0x05/*V_FP_LINE*/, 0x6e/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Progressive, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, + //1080i-60hz + {0x98/*H_RES_LOW*/, 0x08/*H_RES_HIGH*/, 0x80/*ACT_PIX_LOW*/, 0x07/*ACT_PIX_HIGH*/, + 0x2c/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x94/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0x38/*ACT_LINE_LOW*/, 0x04/*ACT_LINE_HIGH*/, 0x05/*VSYNC_WIDTH*/, 0x0f/*V_BP_LINE*/, + 0x02/*V_FP_LINE*/, 0x58/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, + //720x480i-60hz + {0x5a/*H_RES_LOW*/,0x03 /*H_RES_HIGH*/,0xd0/*ACT_PIX_LOW*/, 0x02/*ACT_PIX_HIGH*/, + 0x3e/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x39/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0xe0/*ACT_LINE_LOW*/, 0x01/*ACT_LINE_HIGH*/, 0x03/*VSYNC_WIDTH*/, 0x0f/*V_BP_LINE*/, + 0x04/*V_FP_LINE*/, 0x13/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Neg_Hsync_pol, ANX7150_Neg_Vsync_pol}, //update + //576p-50hz + {0x60/*H_RES_LOW*/,0x03 /*H_RES_HIGH*/,0xd0 /*ACT_PIX_LOW*/, 0x02/*ACT_PIX_HIGH*/, + 0x40/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x44/*H_BP_LOW*/,0x00 /*H_BP_HIGH*/, + 0x40/*ACT_LINE_LOW*/, 0x02/*ACT_LINE_HIGH*/, 0x05/*VSYNC_WIDTH*/, 0x27/*V_BP_LINE*/, + 0x05/*V_FP_LINE*/, 0x0c/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Progressive, ANX7150_Neg_Hsync_pol, ANX7150_Neg_Vsync_pol}, + //720p-50hz + {0xbc/*H_RES_LOW*/, 0x07/*H_RES_HIGH*/, 0x00/*ACT_PIX_LOW*/, 0x05/*ACT_PIX_HIGH*/, + 0x28/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0xdc/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0xd0/*ACT_LINE_LOW*/, 0x02/*ACT_LINE_HIGH*/, 0x05/*VSYNC_WIDTH*/, 0x14/*V_BP_LINE*/, + 0x05/*V_FP_LINE*/, 0xb8/*H_FP_LOW*/, 0x01/*H_FP_HIGH*/, + ANX7150_Progressive, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, + //1080i-50hz + {0x50/*H_RES_LOW*/, 0x0a/*H_RES_HIGH*/, 0x80/*ACT_PIX_LOW*/, 0x07/*ACT_PIX_HIGH*/, + 0x2c/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x94/*H_BP_LOW*/, 0x00/*H_BP_HIGH*/, + 0x38/*ACT_LINE_LOW*/, 0x04/*ACT_LINE_HIGH*/, 0x05/*VSYNC_WIDTH*/, 0x0f/*V_BP_LINE*/, + 0x02/*V_FP_LINE*/, 0x10/*H_FP_LOW*/, 0x02/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, + //576i-50hz + {0x60/*H_RES_LOW*/,0x03 /*H_RES_HIGH*/,0xd0 /*ACT_PIX_LOW*/, 0x02/*ACT_PIX_HIGH*/, + 0x3f/*HSYNC_WIDTH_LOW*/, 0x00/*HSYNC_WIDTH_HIGH*/, 0x45/*H_BP_LOW*/,0x00 /*H_BP_HIGH*/, + 0x40/*ACT_LINE_LOW*/,0x02 /*ACT_LINE_HIGH*/, 0x03/*VSYNC_WIDTH*/, 0x13/*V_BP_LINE*/, + 0x02/*V_FP_LINE*/, 0x0c/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Neg_Hsync_pol, ANX7150_Neg_Vsync_pol}, +}; +//#endif +int anx7150_mass_read_need_delay = 0; + +u8 g_video_format = 0x00; +u8 g_audio_format = 0x00; + + +u8 timer_slot = 0; +u8 ANX7150_EDID_Buf[256]; +u8 ANX7150_avi_data[19];//, ANX7150_avi_checksum; +u8 ANX7150_system_state = HDMI_INITIAL; +u8 spdif_error_cnt = 0x00; +u8 misc_reset_needed; +u8 ANX7150_stdaddr,ANX7150_stdreg,ANX7150_ext_block_num; +u8 ANX7150_svd_length,ANX7150_sau_length; +u8 ANX7150_edid_dtd[18]; +u32 ANX7150_edid_length; +ANX7150_edid_result_4_system ANX7150_edid_result; + +u8 ANX7150_ddc_fifo_full; +u8 ANX7150_ddc_progress; +u8 ANX7150_hdcp_auth_en; +//u8 ANX7150_bksv_ready; //replace by srm_checked xy 01.09 +u8 ANX7150_HDCP_enable; +u8 ANX7150_ksv_srm_pass; +u8 ANX7150_hdcp_bcaps; +u8 ANX7150_hdcp_bstatus[2]; +u8 ANX7150_srm_checked; +u8 ANX7150_hdcp_auth_pass; +u8 ANX7150_avmute_enable; +u8 ANX7150_send_blue_screen; +u8 ANX7150_hdcp_encryption; +u8 ANX7150_hdcp_init_done; +u8 ANX7150_hdcp_wait_100ms_needed; +u8 ANX7150_auth_fully_pass; +u8 ANX7150_parse_edid_done;//060714 XY +//u8 testen; +//u8 ANX7150_avi_data[19], ANX7150_avi_checksum; +u8 ANX7150_hdcp_auth_fail_counter ; + +u8 ANX7150_video_format_config; +u8 ANX7150_emb_sync_mode,ANX7150_de_gen_en,ANX7150_demux_yc_en,ANX7150_ddr_bus_mode; +u8 ANX7150_ddr_edge,ANX7150_ycmux_u8_sel; +u8 ANX7150_system_config_done; +u8 ANX7150_RGBorYCbCr; //modified by zy 060814 +u8 ANX7150_in_pix_rpt,ANX7150_tx_pix_rpt; +u8 ANX7150_in_pix_rpt_bkp,ANX7150_tx_pix_rpt_bkp; +u8 ANX7150_video_timing_id; +u8 ANX7150_pix_rpt_set_by_sys; +u8 ANX7150_video_timing_parameter[18]; +u8 switch_value_sw_backup,switch_value_pc_backup; +u8 switch_value,bist_switch_value_pc; +u8 ANX7150_new_csc,ANX7150_new_vid_id,ANX7150_new_HW_interface; +u8 ANX7150_INT_Done; + +audio_config_struct s_ANX7150_audio_config; +config_packets s_ANX7150_packet_config; + +u8 FREQ_MCLK; //0X72:0X50 u82:0 +//000b:Fm = 128*Fs +//001b:Fm = 256*Fs +//010b:Fm = 384*Fs +//011b:Fm = 512*Fs +u8 ANX7150_audio_clock_edge; + + +int anx7150_detect_device(struct anx7150_pdata *anx) +{ + int i, rc = 0; + char d1, d2; + + for (i=0; i<10; i++) + { + if((rc = anx7150_i2c_read_p0_reg(anx->client, ANX7150_DEV_IDL_REG, &d1)) < 0) + continue; + if((rc = anx7150_i2c_read_p0_reg(anx->client, ANX7150_DEV_IDH_REG, &d2)) < 0) + continue; + if (d1 == 0x50 && d2 == 0x71) + { + hdmi_dbg(&anx->client->dev, "anx7150 detected!\n"); + return 1; + } + } + + hdmi_dbg(&anx->client->dev, "anx7150 not detected"); + return 0; +} +u8 ANX7150_Get_System_State(void) +{ + return ANX7150_system_state; +} +void ANX7150_Set_System_State(struct i2c_client *client, u8 new_state) +{ + ANX7150_system_state = new_state; + switch (ANX7150_system_state) + { + case HDMI_INITIAL: + hdmi_dbg(&client->dev, "INITIAL\n"); + break; + case WAIT_HOTPLUG: + hdmi_dbg(&client->dev, "WAIT_HOTPLUG\n"); + break; + case READ_PARSE_EDID: + hdmi_dbg(&client->dev, "READ_PARSE_EDID\n"); + break; + case WAIT_RX_SENSE: + hdmi_dbg(&client->dev, "WAIT_RX_SENSE\n"); + break; + case WAIT_HDMI_ENABLE: + hdmi_dbg(&client->dev, "WAIT_HDMI_ENABLE\n"); + break; + case SYSTEM_CONFIG: + hdmi_dbg(&client->dev, "SYSTEM_CONFIG\n"); + break; + case CONFIG_VIDEO: + hdmi_dbg(&client->dev, "CONFIG_VIDEO\n"); + break; + case CONFIG_AUDIO: + hdmi_dbg(&client->dev, "CONFIG_AUDIO\n"); + break; + case CONFIG_PACKETS: + hdmi_dbg(&client->dev, "CONFIG_PACKETS\n"); + break; + case HDCP_AUTHENTICATION: + hdmi_dbg(&client->dev, "HDCP_AUTHENTICATION\n"); + break; + //////////////////////////////////////////////// + // System ANX7150_RESET_LINK is kept for RX clock recovery error case, not used in normal case. + case RESET_LINK: + hdmi_dbg(&client->dev, "RESET_LINK\n"); + break; + //////////////////////////////////////////////// + case PLAY_BACK: + hdmi_dbg(&client->dev, "PLAY_BACK\n"); + break; + default: + hdmi_dbg(&client->dev, "unknown state\n"); + break; + } +} + +static int anx7150_get_hpd(struct i2c_client *client) +{ + int rc = 0; + char sys_ctl3, intr_state, sys_state, hpd_state; + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL3_REG, &sys_ctl3)) < 0) + return rc; + if(sys_ctl3 & ANX7150_SYS_CTRL3_PWON_ALL) + { + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_STATE_REG, &sys_state)) < 0) + return rc; + hpd_state = (sys_state & ANX7150_SYS_STATE_HP)? 1:0; + } + else + { + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR_STATE_REG, &intr_state)) < 0) + return rc; + hpd_state = (intr_state)? 1:0; + } + return hpd_state; +} +static int anx7150_get_interrupt_status(struct i2c_client *client, struct anx7150_interrupt_s *interrupt_staus) +{ + int rc = 0; + u8 int_s1; + u8 int_s2; + u8 int_s3; + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR1_STATUS_REG, &int_s1);//jack wen, for spdif input from SD0. + rc |= anx7150_i2c_write_p0_reg(client, ANX7150_INTR1_STATUS_REG, &int_s1);//power down all, 090630 + rc |= anx7150_i2c_read_p0_reg(client, ANX7150_INTR2_STATUS_REG, &int_s2);//jack wen, for spdif input from SD0. + rc |= anx7150_i2c_write_p0_reg(client, ANX7150_INTR2_STATUS_REG, &int_s2);//power down all, 090630 + rc |= anx7150_i2c_read_p0_reg(client, ANX7150_INTR3_STATUS_REG, &int_s3);//jack wen, for spdif input from SD0. + rc |= anx7150_i2c_write_p0_reg(client, ANX7150_INTR3_STATUS_REG, &int_s3);//power down all, 090630 + + interrupt_staus->hotplug_change = (int_s1 & ANX7150_INTR1_STATUS_HP_CHG) ? 1 : 0; + interrupt_staus->video_format_change = (int_s3 & ANX7150_INTR3_STATUS_VIDF_CHG) ? 1 : 0; + interrupt_staus->auth_done = (int_s2 & ANX7150_INTR2_STATUS_AUTH_DONE) ? 1 : 0; + interrupt_staus->auth_state_change = (int_s2 & ANX7150_INTR2_STATUS_AUTH_CHG) ? 1 : 0; + interrupt_staus->pll_lock_change = (int_s2 & ANX7150_INTR2_STATUS_PLLLOCK_CHG) ? 1 : 0; + interrupt_staus->rx_sense_change = (int_s3 & ANX7150_INTR3_STATUS_RXSEN_CHG) ? 1 : 0; + interrupt_staus->HDCP_link_change = (int_s2 & ANX7150_INTR2_STATUS_HDCPLINK_CHK) ? 1 : 0; + interrupt_staus->audio_clk_change = (int_s3 & ANX7150_INTR3_STATUS_AUDCLK_CHG) ? 1 : 0; + interrupt_staus->audio_FIFO_overrun = (int_s1 & ANX7150_INTR1_STATUS_AFIFO_OVER) ? 1 : 0; + interrupt_staus->SPDIF_error = (int_s1 & ANX7150_INTR1_STATUS_SPDIF_ERR) ? 1 : 0; + interrupt_staus->SPDIF_bi_phase_error = ((int_s3 & ANX7150_INTR3_STATUS_SPDIFBI_ERR) ? 1 : 0) + || ((int_s3 & ANX7150_INTR3_STATUS_SPDIF_UNSTBL) ? 1 : 0); + return 0; +} +static void ANX7150_Variable_Initial(void) +{ + u8 i; + + ANX7150_hdcp_auth_en = 0; + ANX7150_ksv_srm_pass =0; + ANX7150_srm_checked = 0; + ANX7150_hdcp_auth_pass = 0; + ANX7150_avmute_enable = 1; + ANX7150_hdcp_auth_fail_counter =0; + ANX7150_hdcp_encryption = 0; + ANX7150_send_blue_screen = 0; + ANX7150_hdcp_init_done = 0; + ANX7150_hdcp_wait_100ms_needed = 1; + ANX7150_auth_fully_pass = 0; + timer_slot = 0; + //********************for video config************** + ANX7150_video_timing_id = 0; + ANX7150_in_pix_rpt = 0; + ANX7150_tx_pix_rpt = 0; + ANX7150_new_csc = 0; + ANX7150_new_vid_id = 0; + ANX7150_new_HW_interface = 0; + //********************end of video config********* + + //********************for edid parse*********** + ANX7150_edid_result.is_HDMI = 0; + ANX7150_edid_result.ycbcr422_supported = 0; + ANX7150_edid_result.ycbcr444_supported = 0; + ANX7150_edid_result.supported_720p_60Hz = 0; + ANX7150_edid_result.supported_720p_50Hz = 0; + ANX7150_edid_result.supported_576p_50Hz = 0; + ANX7150_edid_result.supported_576i_50Hz = 0; + ANX7150_edid_result.supported_1080i_60Hz = 0; + ANX7150_edid_result.supported_1080i_50Hz = 0; + ANX7150_edid_result.supported_640x480p_60Hz = 0; + ANX7150_edid_result.supported_720x480p_60Hz = 0; + ANX7150_edid_result.supported_720x480i_60Hz = 0; + ANX7150_edid_result.edid_errcode = 0; + ANX7150_edid_result.SpeakerFormat = 0; + for (i = 0; i < 8; i ++) + { + ANX7150_edid_result.AudioChannel[i] = 0; + ANX7150_edid_result.AudioFormat[i] = 0; + ANX7150_edid_result.AudioFs[i] = 0; + ANX7150_edid_result.AudioLength[i] = 0; + } + //********************end of edid************** + + s_ANX7150_packet_config.packets_need_config = 0x03; //new avi infoframe + s_ANX7150_packet_config.avi_info.type = 0x82; + s_ANX7150_packet_config.avi_info.version = 0x02; + s_ANX7150_packet_config.avi_info.length = 0x0d; + s_ANX7150_packet_config.avi_info.pb_u8[1] = 0x21;//YCbCr422 + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0x08; + s_ANX7150_packet_config.avi_info.pb_u8[3] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[4] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[5] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[6] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[7] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[8] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[9] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[10] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[11] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[12] = 0x00; + s_ANX7150_packet_config.avi_info.pb_u8[13] = 0x00; + + // audio infoframe + s_ANX7150_packet_config.audio_info.type = 0x84; + s_ANX7150_packet_config.audio_info.version = 0x01; + s_ANX7150_packet_config.audio_info.length = 0x0a; + s_ANX7150_packet_config.audio_info.pb_u8[1] = 0x00; //zy 061123 for ATC + s_ANX7150_packet_config.audio_info.pb_u8[2] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[3] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[4] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[5] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[6] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[7] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[8] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[9] = 0x00; + s_ANX7150_packet_config.audio_info.pb_u8[10] = 0x00; + + ANX7150_INT_Done = 0; +} +static void ANX7150_HW_Interface_Variable_Initial(void) +{ + u8 c; + + ANX7150_video_format_config = 0x00; + ANX7150_RGBorYCbCr = 0x00; + ANX7150_ddr_edge = ANX7150_IDCK_EDGE_DDR; + + c = 0; + c = (ANX7150_I2S_CH0_ENABLE << 2) | (ANX7150_I2S_CH1_ENABLE << 3) | + (ANX7150_I2S_CH2_ENABLE << 4) | (ANX7150_I2S_CH3_ENABLE << 5); + s_ANX7150_audio_config.audio_type = ANX7150_AUD_HW_INTERFACE; // input I2S + s_ANX7150_audio_config.down_sample = 0x00; + s_ANX7150_audio_config.i2s_config.audio_channel = c;//0x04; + s_ANX7150_audio_config.i2s_config.Channel_status1 =0x00; + s_ANX7150_audio_config.i2s_config.Channel_status1 = 0x00; + s_ANX7150_audio_config.i2s_config.Channel_status2 = 0x00; + s_ANX7150_audio_config.i2s_config.Channel_status3 = 0x00; + s_ANX7150_audio_config.i2s_config.Channel_status4 = 0x00;//0x02;//48k + s_ANX7150_audio_config.i2s_config.Channel_status5 = ANX7150_I2S_WORD_LENGTH;//0x0b; + s_ANX7150_audio_config.audio_layout = 0x00; + + c = (ANX7150_I2S_SHIFT_CTRL << 3) | (ANX7150_I2S_DIR_CTRL << 2) | + (ANX7150_I2S_WS_POL << 1) | ANX7150_I2S_JUST_CTRL; + s_ANX7150_audio_config.i2s_config.i2s_format = c;//0x00; + + FREQ_MCLK = ANX7150_MCLK_Fs_RELATION;//set the relation of MCLK and WS + ANX7150_audio_clock_edge = ANX7150_AUD_CLK_EDGE; + + +} +static int anx7150_hardware_initial(struct i2c_client *client) +{ + int rc = 0; + char c = 0; + + //clear HDCP_HPD_RST + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + c |= (0x01); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + + mdelay(10); + + c &= (~0x01); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + + //Power on I2C + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c); + c |= (ANX7150_SYS_CTRL3_I2C_PWON); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + c= 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SRST_REG, &c); + + //clear HDCP_HPD_RST + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c &= (0xbf); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + + //Power on Audio capture and Video capture module clock + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_PD_REG, &c); + c |= (0x06); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_PD_REG, &c); + + //Enable auto set clock range for video PLL + rc = anx7150_i2c_read_p0_reg(client, ANX7150_CHIP_CTRL_REG, &c); + c &= (0x00); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_CHIP_CTRL_REG, &c); + + //Set registers value of Blue Screen when HDCP authentication failed--RGB mode,green field + c = 0x10; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN0_REG, &c); + c = 0xeb; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN1_REG, &c); + c = 0x10; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN2_REG, &c); + + //ANX7150_i2c_read_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, (c | 0x80)); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_PLL_CTRL0_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_PLL_CTRL0_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c); + c |= (0x08); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_PLL_TX_AMP, &c);//jack wen + c |= (0x01); + + rc = anx7150_i2c_write_p0_reg(client, ANX7150_PLL_TX_AMP, &c); //TMDS swing + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_PLL_CTRL1_REG, &c); //Added for PLL unlock issue in high temperature - Feiw + //if (ANX7150_AUD_HW_INTERFACE == 0x02) //jack wen, spdif + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2S_CTRL_REG, &c);//jack wen, for spdif input from SD0. + c &= (0xef); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2S_CTRL_REG, &c); + + c = 0xc7; + rc = anx7150_i2c_write_p0_reg(client, 0xE1, &c); + + //ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c);//power down HDCP, 090630 + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c);//jack wen, for spdif input from SD0. + c &= (0xef); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c);//power down all, 090630 + + return rc; +} + +int anx7150_rst_ddcchannel(struct i2c_client *client) +{ + int rc = 0; + char c; + //Reset the DDC channel + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + + c |= (ANX7150_SYS_CTRL2_DDC_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + + c &= (~ANX7150_SYS_CTRL2_DDC_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACC_CMD_REG, &c);//abort current operation + + c = 0x06; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACC_CMD_REG, &c);//reset I2C command + + //Clear FIFO + c = 0x05; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACC_CMD_REG, &c);//reset I2C command + + return rc; +} + +int anx7150_unplug(struct i2c_client *client) +{ + int rc = 0; + char c; + hdmi_dbg(&client->dev, "anx7150 unplug\n"); + + //wen HDCP CTS + ANX7150_Variable_Initial(); //simon + ANX7150_HW_Interface_Variable_Initial(); //simon + + rc = anx7150_hardware_initial(client); //simon + if(rc < 0) + dev_err(&client->dev, "%s>> i2c transfer err\n", __func__); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); //simon + if(rc < 0) + dev_err(&client->dev, "%s>> i2c transfer err\n", __func__); + //wen HDCP CTS + ANX7150_hdcp_wait_100ms_needed = 1; + ANX7150_auth_fully_pass = 0; + + // clear ANX7150_parse_edid_done & ANX7150_system_config_done + ANX7150_parse_edid_done = 0; +// ANX7150_system_config_done = 0; + ANX7150_srm_checked = 0; + + return rc; +} +int anx7150_plug(struct i2c_client *client) +{ + int rc = 0; + char c; + + hdmi_dbg(&client->dev, "anx7150 plug\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c); + c |= (0x01); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL3_REG, &c);//power up all, 090630 + + //disable audio & video & hdcp & TMDS and init begin + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c &= (~ANX7150_VID_CTRL_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + c &= (~ANX7150_TMDS_CLKCH_MUTE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_HW_AUTHEN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + + ANX7150_Variable_Initial(); + //disable video & audio & hdcp & TMDS and init end + + + //Power on chip and select DVI mode + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c |= (0x05); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c);// cwz change 0x01 -> 0x05 + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c &= (0xfd); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + + //D("ANX7150 is set to DVI mode\n"); + rc = anx7150_rst_ddcchannel(client); + //Initial Interrupt + // disable video/audio CLK,Format change and before config video. 060713 xy + + c = 0x04; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR1_MASK_REG, &c); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR2_MASK_REG, &c); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR3_MASK_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR1_STATUS_REG, &c); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR1_STATUS_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR2_STATUS_REG, &c); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR2_STATUS_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR3_STATUS_REG, &c); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR3_STATUS_REG, &c); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR_CTRL_REG, &c); + + // clear ANX7150_parse_edid_done & ANX7150_system_config_done + ANX7150_parse_edid_done = 0; +// ANX7150_system_config_done = 0; + ANX7150_srm_checked = 0; + + return rc; +} + +static int anx7150_set_avmute(struct i2c_client *client) +{ + int rc = 0; + char c; + + c = 0x01; + if((rc = anx7150_i2c_write_p1_reg(client, ANX7150_GNRL_CTRL_PKT_REG, &c)) < 0) + return rc; + + if((rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c)) < 0) + return rc; + c |= (0x0c); + if((rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c)) < 0) + return rc; + ANX7150_avmute_enable = 1; + + return rc; +} +static int anx7150_clear_avmute(struct i2c_client *client) +{ + int rc = 0; + char c; + + c = 0x02; + if((rc = anx7150_i2c_write_p1_reg(client, ANX7150_GNRL_CTRL_PKT_REG, &c)) < 0) + return rc; + + if((rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c)) < 0) + return rc; + c |= (0x0c); + if((rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c)) < 0) + return rc; + ANX7150_avmute_enable = 0; +// D("@@@@@@@@@@@@@@@@@@@@ANX7150_Clear_AVMute\n"); + return rc; + +} + +static int anx7150_video_format_change(struct i2c_client *client) +{ + int rc; + char c; + + hdmi_dbg(&client->dev, "after video format change int \n"); + + rc = anx7150_set_avmute(client);//wen + //stop HDCP and reset DDC + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_HW_AUTHEN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + + rc = anx7150_rst_ddcchannel(client); + + //when format change, clear this reg to avoid error in package config + c = 0x00; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + //xy 11.06 when format change, need system config again + // ANX7150_system_config_done = 0; + return rc; +} +static int anx7150_blue_screen_disable(struct i2c_client *client) +{ + int rc = 0; + char c; + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c)) < 0) + return rc; + c &= (0xfb); + if((rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c)) < 0) + return rc; + + ANX7150_send_blue_screen = 0; + + return rc; +} +static int anx7150_blue_screen_enable(struct i2c_client *client) +{ + int rc = 0; + char c; + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c)) < 0) + return rc; + c |= (ANX7150_HDCP_CTRL1_BLUE_SCREEN_EN); + if((rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c)) < 0) + return rc; + ANX7150_send_blue_screen = 1; + + return rc; +} +static int anx7150_hdcp_encryption_enable(struct i2c_client *client) +{ + int rc = 0; + u8 c; + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c)) < 0) + return rc; + c |= (ANX7150_HDCP_CTRL0_ENC_EN); + if((rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c)) < 0) + return rc; + ANX7150_hdcp_encryption = 1; + + return rc; +} + +static int anx7150_hdcp_encryption_disable(struct i2c_client *client) +{ + int rc = 0; + u8 c; + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c)) < 0) + return rc; + c &= (0xfb); + if((rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c)) < 0) + return rc; + + ANX7150_hdcp_encryption = 0; + + return rc; +} + +static int anx7150_auth_done(struct i2c_client *client) +{ + int rc = 0; + char c; + + hdmi_dbg(&client->dev, "anx7150 auth done\n"); + + if((rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_STATUS_REG, &c)) < 0) + return rc; + + if (c & ANX7150_HDCP_STATUS_AUTH_PASS) + { + hdmi_dbg(&client->dev, "ANX7150_Authentication pass in Auth_Done\n"); + anx7150_blue_screen_disable(client); + ANX7150_hdcp_auth_pass = 1; + ANX7150_hdcp_auth_fail_counter = 0; + } + else + { + hdmi_dbg(&client->dev, "ANX7150_Authentication failed\n"); + ANX7150_hdcp_wait_100ms_needed = 1; + ANX7150_auth_fully_pass = 0; + ANX7150_hdcp_auth_pass = 0; + ANX7150_hdcp_auth_fail_counter ++; + if (ANX7150_hdcp_auth_fail_counter >= ANX7150_HDCP_FAIL_THRESHOLD) + { + ANX7150_hdcp_auth_fail_counter = 0; + //ANX7150_bksv_ready = 0; + // TODO: Reset link; + rc = anx7150_blue_screen_enable(client); + rc = anx7150_hdcp_encryption_disable(client); + //disable audio + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + } + return rc; +} + +static int anx7150_clean_hdcp(struct i2c_client *client) +{ + int rc = 0; + char c; + //mute TMDS link + //ANX7150_i2c_read_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, &c);//jack wen + //ANX7150_i2c_write_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, c & (~ANX7150_TMDS_CLKCH_MUTE)); + + //Disable hardware HDCP + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_HW_AUTHEN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + + //Reset HDCP logic + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SRST_REG, &c); + c |= (ANX7150_SRST_HDCP_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SRST_REG, &c); + c &= (~ANX7150_SRST_HDCP_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SRST_REG, &c); + + //Set ReAuth + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c |= (ANX7150_HDCP_CTRL0_RE_AUTH); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_RE_AUTH); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + ANX7150_hdcp_auth_en = 0; + //ANX7150_bksv_ready = 0; + ANX7150_hdcp_auth_pass = 0; + ANX7150_hdcp_auth_fail_counter =0 ; + ANX7150_hdcp_encryption = 0; + ANX7150_send_blue_screen = 0; + ANX7150_hdcp_init_done = 0; + ANX7150_hdcp_wait_100ms_needed = 1; + ANX7150_auth_fully_pass = 0; + ANX7150_srm_checked = 0; + rc = anx7150_rst_ddcchannel(client); + + return rc; +} +static int anx7150_auth_change(struct i2c_client *client) +{ + int rc = 0; + char c; + + int state = ANX7150_Get_System_State(); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_STATUS_REG, &c); + if (c & ANX7150_HDCP_STATUS_AUTH_PASS) + { + ANX7150_hdcp_auth_pass = 1; + hdmi_dbg(&client->dev, "ANX7150_Authentication pass in Auth_Change\n"); + } + else + { + rc = anx7150_set_avmute(client); //wen + hdmi_dbg(&client->dev, "ANX7150_Authentication failed_by_Auth_change\n"); + ANX7150_hdcp_auth_pass = 0; + ANX7150_hdcp_wait_100ms_needed = 1; + ANX7150_auth_fully_pass = 0; + ANX7150_hdcp_init_done=0; //wen HDCP CTS + ANX7150_hdcp_auth_en=0; //wen HDCP CTS + rc = anx7150_hdcp_encryption_disable(client); + if (state == PLAY_BACK) + { + ANX7150_auth_fully_pass = 0; + //disable audio + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + rc = anx7150_clean_hdcp(client); //wen updated for Changhong TV + } + } + return rc; +} +int ANX7150_GET_RECIVER_TYPE(void) +{ + return ANX7150_edid_result.is_HDMI; +} +static int anx7150_audio_clk_change(struct i2c_client *client) +{ + int rc = 0; + char c; + + hdmi_dbg(&client->dev, "ANX7150: audio clock changed interrupt,disable audio.\n"); + // disable audio + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + //xy 11.06 when format change, need system config again +// ANX7150_system_config_done = 0; + return rc; +} + +static int anx7150_afifo_overrun(struct i2c_client *client) +{ + int rc = 0; + char c; + hdmi_dbg(&client->dev, "ANX7150: AFIFO overrun interrupt,disable audio.\n"); + // disable audio + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + return rc; +} +static int anx7150_spdif_error(struct i2c_client *client, int cur_state, int SPDIF_bi_phase_err, int SPDIF_error) +{ + int rc = 0; + char c; + int state = cur_state; + + if(SPDIF_bi_phase_err || SPDIF_error) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + if( c & ANX7150_HDMI_AUDCTRL1_SPDIFIN_EN) + { + + if ((state == CONFIG_AUDIO + || state == CONFIG_PACKETS + || state == HDCP_AUTHENTICATION + || state == PLAY_BACK )) + { + if(SPDIF_bi_phase_err){ + hdmi_dbg(&client->dev, "SPDIF BI Phase or Unstable error.\n"); + spdif_error_cnt += 0x03; + } + + if(SPDIF_error){ + hdmi_dbg(&client->dev, "SPDIF Parity error.\n"); + spdif_error_cnt += 0x01; + } + + } + + // adjust spdif phase + if (spdif_error_cnt >= spdif_error_th) + { + char freq_mclk,c1,c2; + spdif_error_cnt = 0x00; + hdmi_dbg(&client->dev, "adjust mclk phase!\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c2); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2S_CTRL_REG, &c1); + + freq_mclk = c2 & 0x07; + switch (freq_mclk) + { + case ANX7150_mclk_128_Fs: //invert 0x50[3] + hdmi_dbg(&client->dev, "adjust mclk phase when 128*Fs!\n"); + if ( c2 & 0x08 ) c2 &= 0xf7; + else c2 |= 0x08; + + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c2); + break; + + case ANX7150_mclk_256_Fs: + case ANX7150_mclk_384_Fs: + hdmi_dbg(&client->dev, "adjust mclk phase when 256*Fs or 384*Fs!\n"); + if ( c1 & 0x60 ) c1 &= 0x9f; + else c1 |= 0x20; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2S_CTRL_REG, &c1); + break; + + case ANX7150_mclk_512_Fs: + hdmi_dbg(&client->dev, "adjust mclk phase when 512*Fs!\n"); + if ( c1 & 0x60 ) c1 &= 0x9f; + else c1 |= 0x40; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2S_CTRL_REG, &c1); + break; + default: + break; + + } + } + } + } + else{ + if(spdif_error_cnt > 0 && state == PLAY_BACK) spdif_error_cnt --; + if(spdif_error_cnt > 0 && state < CONFIG_AUDIO) spdif_error_cnt = 0x00; + + } + + return rc; +} +static int anx7150_plllock(struct i2c_client *client) +{ + int rc = 0; + char c; + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_CHIP_STATUS_REG, &c); + if((c&0x01) == 0) + { + rc = anx7150_set_avmute(client);//wen + hdmi_dbg(&client->dev, "ANX7150: PLL unlock interrupt,disable audio.\n"); + // disable audio & video + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c &= (~ANX7150_VID_CTRL_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + //when pll change, clear this reg to avoid error in package config + c = 0x00; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c);//wen + c = 0x00; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + +// ANX7150_system_config_done = 0;//jack wen + } + return rc; +} +static int anx7150_rx_sense_change(struct i2c_client *client, int cur_state) +{ + int rc = 0; + char c; + int state = cur_state; + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_STATE_REG, &c); + hdmi_dbg(&client->dev, "ANX7150_Rx_Sense_Interrupt, ANX7150_SYS_STATE_REG = %.2x\n", (unsigned int)c); //wen + + if ( c & ANX7150_SYS_STATE_RSV_DET) + { + //xy 11.06 Power on chip + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c |= (0x01); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + + s_ANX7150_packet_config.packets_need_config = 0x03; //new avi infoframe wen + } + else + { + // Rx is not active + if (state > WAIT_HOTPLUG) + { + //stop HDCP and reset DDC when lost Rx sense + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_REG); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + + rc = anx7150_rst_ddcchannel(client); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c &= (0xfd); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + + // mute TMDS link + rc = anx7150_i2c_read_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + c &= (~ANX7150_TMDS_CLKCH_MUTE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + } + //Power down chip + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c &= (0xfe); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + } + //xy 11.06 when format change, need system config again +// ANX7150_system_config_done = 0;//wen HDCP CTS + + return rc; +} +int ANX7150_Interrupt_Process(struct anx7150_pdata *anx, int cur_state) +{ + struct anx7150_interrupt_s interrupt_staus; + struct hdmi *hdmi = anx->dev.hdmi; + int state; + int hot_plug; + int rc; + + state = cur_state; + + hot_plug = anx7150_get_hpd(anx->client); + + rc = anx7150_get_interrupt_status(anx->client, &interrupt_staus); + if(rc < 0){ + goto out; + } + + if(anx->dev.HPD_status != hot_plug){ + anx->dev.HPD_change_cnt++; + } + else{ + anx->dev.HPD_change_cnt = 0; + } + + if(anx->dev.HPD_change_cnt > 2){ + hdmi_dbg(&anx->client->dev, "hotplug_change\n"); + + if(hot_plug == HDMI_RECIVER_UNPLUG){ + anx7150_unplug(anx->client); + state = HDMI_INITIAL; + anx->dev.reciver_status = HDMI_RECIVER_INACTIVE; + hdmi_changed(hdmi, 0); + } + + anx->dev.HPD_change_cnt = 0; + anx->dev.HPD_status = hot_plug; + } + if(state != HDMI_INITIAL && state != WAIT_HOTPLUG){ + if(interrupt_staus.video_format_change){ + if(state > SYSTEM_CONFIG){ + rc = anx7150_video_format_change(anx->client); + state = CONFIG_VIDEO; + } + } + + if(interrupt_staus.auth_done){ + rc = anx7150_auth_done(anx->client); + state = CONFIG_AUDIO; + } + + if(interrupt_staus.auth_state_change){ + rc = anx7150_auth_change(anx->client); + if(state == PLAY_BACK){ + state = HDCP_AUTHENTICATION; + } + } + + if(ANX7150_GET_RECIVER_TYPE() == 1){ + if(interrupt_staus.audio_clk_change){ + if(state > CONFIG_VIDEO){ + rc = anx7150_audio_clk_change(anx->client); + state = SYSTEM_CONFIG; + } + } + + if(interrupt_staus.audio_FIFO_overrun){ + if(state > CONFIG_VIDEO){ + rc = anx7150_afifo_overrun(anx->client); + state = CONFIG_AUDIO; + } + } + + rc = anx7150_spdif_error(anx->client, state, interrupt_staus.SPDIF_bi_phase_error, interrupt_staus.SPDIF_error); + } + + if(interrupt_staus.pll_lock_change){ + if(state > SYSTEM_CONFIG){ + rc = anx7150_plllock(anx->client); + state = SYSTEM_CONFIG; + } + } + + if(interrupt_staus.rx_sense_change){ + anx7150_rx_sense_change(anx->client, state); + if(state > WAIT_RX_SENSE) + state = WAIT_RX_SENSE; + } + } + +out: + return state; +} + +int ANX7150_API_Initial(struct i2c_client *client) +{ + int rc = 0; + hdmi_dbg(&client->dev, "%s\n", __func__); + + ANX7150_Variable_Initial(); + ANX7150_HW_Interface_Variable_Initial(); + rc = anx7150_hardware_initial(client); + + return rc; +} + +void ANX7150_Shutdown(struct i2c_client *client) +{ + hdmi_dbg(&client->dev, "%s\n", __func__); + ANX7150_API_Initial(client); + ANX7150_Set_System_State(client, HDMI_INITIAL); +} + +static int anx7150_initddc_read(struct i2c_client *client, + u8 devaddr, u8 segmentpointer, + u8 offset, u8 access_num_Low,u8 access_num_high) +{ + int rc = 0; + char c; + + //Write slave device address + c = devaddr; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_SLV_ADDR_REG, &c); + // Write segment address + c = segmentpointer; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_SLV_SEGADDR_REG, &c); + //Write offset + c = offset; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_SLV_OFFADDR_REG, &c); + //Write number for access + c = access_num_Low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACCNUM0_REG, &c); + c = access_num_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACCNUM1_REG, &c); + //Clear FIFO + c = 0x05; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACC_CMD_REG, &c); + //EDDC sequential Read + c = 0x04; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_DDC_ACC_CMD_REG, &c); + + return rc; +} +static int ANX7150_GetEDIDLength(struct i2c_client *client) +{ + u8 edid_data_length,i; + char c; + int rc = 0; + + anx7150_rst_ddcchannel(client); + + rc = anx7150_initddc_read(client, 0xa0, 0x00, 0x7e, 0x01, 0x00); + msleep(3);//FeiW - Analogix + for(i=0;i<10;i++) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFOCNT_REG, &c); + if(c!=0){ + return rc; + } + } + msleep(10); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &c); + edid_data_length = c; + + ANX7150_edid_length = edid_data_length * 128 + 128; + + return rc; + +} +static int ANX7150_DDC_Mass_Read(struct i2c_client *client, u32 length, u8 segment) +{ + int rc = 0; + u32 i, j; + char c, c1,ddc_empty_cnt; + + i = length; + while (i > 0) + { + //check DDC FIFO statue + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_CHSTATUS_REG, &c); + if (c & ANX7150_DDC_CHSTATUS_DDC_OCCUPY) + { + hdmi_dbg(&client->dev, "ANX7150 DDC channel is accessed by an external device, break!.\n"); + break; + } + if (c & ANX7150_DDC_CHSTATUS_FIFO_FULL) + ANX7150_ddc_fifo_full = 1; + else + ANX7150_ddc_fifo_full = 0; + if (c & ANX7150_DDC_CHSTATUS_INPRO) + ANX7150_ddc_progress = 1; + else + ANX7150_ddc_progress = 0; + if (ANX7150_ddc_fifo_full) + { + hdmi_dbg(&client->dev, "DDC FIFO is full during edid reading"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFOCNT_REG, &c); + hdmi_dbg(&client->dev, "FIFO counter is %.2x\n", (u32) c); + for (j=0; j= 0x0a) + i = 0; + } + } + return rc; +} +static int ANX7150_Read_EDID(struct i2c_client *client) +{ + int rc = 0; + + u8 edid_segment,segmentpointer,k; + + rc = anx7150_rst_ddcchannel(client); + msleep(5); + + edid_segment = ANX7150_edid_length / 256; + if (edid_segment==0) //update + segmentpointer =0; + else + segmentpointer = edid_segment - 1; + //segmentpointer = edid_segment - 1; + + for (k = 0; k <= segmentpointer; k ++) + { + rc =anx7150_initddc_read(client, 0xa0, k, 0x00, 0x80, 0x00); + msleep(10); + rc = ANX7150_DDC_Mass_Read(client, 128, k); + //msleep(10); + rc = anx7150_initddc_read(client, 0xa0, k, 0x80, 0x80, 0x00); + msleep(10); + rc = ANX7150_DDC_Mass_Read(client, 128, k + 1); + //msleep(10); + } + + if ((ANX7150_edid_length - 256 * edid_segment) == 0) + hdmi_dbg(&client->dev, "Finish reading EDID\n"); + else + { + hdmi_dbg(&client->dev, "Read one more block(128 u8s).........\n"); + rc = anx7150_initddc_read(client, 0xa0, segmentpointer + 1, 0x00, 0x80, 0x00); + msleep(5); + rc = ANX7150_DDC_Mass_Read(client, 128, segmentpointer + 1); + hdmi_dbg(&client->dev, "Finish reading EDID\n"); + msleep(5); + } + return rc; +} +static u8 ANX7150_Read_EDID_u8(u8 segmentpointer,u8 offset) +{ + /*u8 c; + anx7150_initddc_read(0xa0, segmentpointer, offset, 0x01, 0x00); + ANX7150_i2c_read_p0_reg(ANX7150_DDC_FIFOCNT_REG, &c); + while(c==0) + ANX7150_i2c_read_p0_reg(ANX7150_DDC_FIFO_ACC_REG, &c); + return c;*/ + + return ANX7150_EDID_Buf[offset]; +} +static u8 ANX7150_Parse_EDIDHeader(void) +{ + u8 i,temp; + temp = 0; + // the EDID header should begin with 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00 + if ((ANX7150_Read_EDID_u8(0, 0) == 0x00) && (ANX7150_Read_EDID_u8(0, 7) == 0x00)) + { + for (i = 1; i < 7; i++) + { + if (ANX7150_Read_EDID_u8(0, i) != 0xff) + { + temp = 0x01; + break; + } + } + } + else + { + temp = 0x01; + } + if (temp == 0x01) + { + return 0; + } + else + { + return 1; + } +} +static u8 ANX7150_Parse_EDIDVersion(void) +{ + + if (!((ANX7150_Read_EDID_u8(0, 0x12) == 1) && (ANX7150_Read_EDID_u8(0, 0x13) >= 3) )) + { + return 0; + } + else + { + return 1; + } +} +static void ANX7150_Parse_DTD(void) +{ + u32 temp; + unsigned long temp1,temp2; + u32 Hresolution,Vresolution,Hblanking,Vblanking; + u32 PixelCLK,Vtotal,H_image_size,V_image_size; + u8 Hz; + //float Ratio; + + temp = ANX7150_edid_dtd[1]; + temp = temp << 8; + PixelCLK = temp + ANX7150_edid_dtd[0]; + // D("Pixel clock is 10000 * %u\n", temp); + + temp = ANX7150_edid_dtd[4]; + temp = (temp << 4) & 0x0f00; + Hresolution = temp + ANX7150_edid_dtd[2]; + //D("Horizontal Active is %u\n", Hresolution); + + temp = ANX7150_edid_dtd[4]; + temp = (temp << 8) & 0x0f00; + Hblanking = temp + ANX7150_edid_dtd[3]; + //D("Horizontal Blanking is %u\n", temp); + + temp = ANX7150_edid_dtd[7]; + temp = (temp << 4) & 0x0f00; + Vresolution = temp + ANX7150_edid_dtd[5]; + //D("Vertical Active is %u\n", Vresolution); + + temp = ANX7150_edid_dtd[7]; + temp = (temp << 8) & 0x0f00; + Vblanking = temp + ANX7150_edid_dtd[6]; + //D("Vertical Blanking is %u\n", temp); + + temp = ANX7150_edid_dtd[11]; + temp = (temp << 2) & 0x0300; + temp = temp + ANX7150_edid_dtd[8]; + //D("Horizontal Sync Offset is %u\n", temp); + + temp = ANX7150_edid_dtd[11]; + temp = (temp << 4) & 0x0300; + temp = temp + ANX7150_edid_dtd[9]; + //D("Horizontal Sync Pulse is %u\n", temp); + + temp = ANX7150_edid_dtd[11]; + temp = (temp << 2) & 0x0030; + temp = temp + (ANX7150_edid_dtd[10] >> 4); + //D("Vertical Sync Offset is %u\n", temp); + + temp = ANX7150_edid_dtd[11]; + temp = (temp << 4) & 0x0030; + temp = temp + (ANX7150_edid_dtd[8] & 0x0f); + //D("Vertical Sync Pulse is %u\n", temp); + + temp = ANX7150_edid_dtd[14]; + temp = (temp << 4) & 0x0f00; + H_image_size = temp + ANX7150_edid_dtd[12]; + //D("Horizontal Image size is %u\n", temp); + + temp = ANX7150_edid_dtd[14]; + temp = (temp << 8) & 0x0f00; + V_image_size = temp + ANX7150_edid_dtd[13]; + //D("Vertical Image size is %u\n", temp); + + //D("Horizontal Border is %bu\n", ANX7150_edid_dtd[15]); + + //D("Vertical Border is %bu\n", ANX7150_edid_dtd[16]); + + temp1 = Hresolution + Hblanking; + Vtotal = Vresolution + Vblanking; + temp1 = temp1 * Vtotal; + temp2 = PixelCLK; + temp2 = temp2 * 10000; + if (temp1 == 0) //update + Hz=0; + else + Hz = temp2 / temp1; + //Hz = temp2 / temp1; + if ((Hz == 59) || (Hz == 60)) + { + Hz = 60; + //D("_______________Vertical Active is %u\n", Vresolution); + if (Vresolution == 540) + ANX7150_edid_result.supported_1080i_60Hz = 1; + if (Vresolution == 1080) + ANX7150_edid_result.supported_1080p_60Hz = 1; + if (Vresolution == 720) + ANX7150_edid_result.supported_720p_60Hz = 1; + if ((Hresolution == 640) && (Vresolution == 480)) + ANX7150_edid_result.supported_640x480p_60Hz = 1; + if ((Hresolution == 720) && (Vresolution == 480)) + ANX7150_edid_result.supported_720x480p_60Hz = 1; + if ((Hresolution == 720) && (Vresolution == 240)) + ANX7150_edid_result.supported_720x480i_60Hz = 1; + } + if (Hz == 50) + { + //D("+++++++++++++++Vertical Active is %u\n", Vresolution); + if (Vresolution == 540) + ANX7150_edid_result.supported_1080i_50Hz = 1; + if (Vresolution == 1080) + ANX7150_edid_result.supported_1080p_50Hz = 1; + if (Vresolution == 720) + ANX7150_edid_result.supported_720p_50Hz = 1; + if (Vresolution == 576) + ANX7150_edid_result.supported_576p_50Hz = 1; + if (Vresolution == 288) + ANX7150_edid_result.supported_576i_50Hz = 1; + } + //D("Fresh rate :% bu Hz\n", Hz); + //Ratio = H_image_size; + //Ratio = Ratio / V_image_size; + //D("Picture ratio : %f \n", Ratio); +} +static void ANX7150_Parse_DTDinBlockONE(void) +{ + u8 i; + for (i = 0; i < 18; i++) + { + ANX7150_edid_dtd[i] = ANX7150_Read_EDID_u8(0, (i + 0x36)); + } + //D("Parse the first DTD in Block one:\n"); + ANX7150_Parse_DTD(); + + if ((ANX7150_Read_EDID_u8(0, 0x48) == 0) + && (ANX7150_Read_EDID_u8(0, 0x49) == 0) + && (ANX7150_Read_EDID_u8(0, 0x4a) == 0)) + { + ;//D("the second DTD in Block one is not used to descript video timing.\n"); + } + else + { + for (i = 0; i < 18; i++) + { + ANX7150_edid_dtd[i] = ANX7150_Read_EDID_u8(0, (i + 0x48)); + } + ANX7150_Parse_DTD(); + } + + if ((ANX7150_Read_EDID_u8(0,0x5a) == 0) + && (ANX7150_Read_EDID_u8(0,0x5b) == 0) + && (ANX7150_Read_EDID_u8(0,0x5c) == 0)) + { + ;//D("the third DTD in Block one is not used to descript video timing.\n"); + } + else + { + for (i = 0; i < 18; i++) + { + ANX7150_edid_dtd[i] = ANX7150_Read_EDID_u8(0, (i + 0x5a)); + } + ANX7150_Parse_DTD(); + } + + if ((ANX7150_Read_EDID_u8(0,0x6c) == 0) + && (ANX7150_Read_EDID_u8(0,0x6d) == 0) + && (ANX7150_Read_EDID_u8(0,0x6e) == 0)) + { + ;//D("the fourth DTD in Block one is not used to descript video timing.\n"); + } + else + { + for (i = 0; i < 18; i++) + { + ANX7150_edid_dtd[i] = ANX7150_Read_EDID_u8(0,(i + 0x6c)); + } + ANX7150_Parse_DTD(); + } +} +static void ANX7150_Parse_NativeFormat(void) +{ + u8 temp; + temp = ANX7150_Read_EDID_u8(0,0x83) & 0xf0; + /*if(temp & 0x80) + ;//D("DTV supports underscan.\n"); + if(temp & 0x40) + ;//D("DTV supports BasicAudio.\n");*/ + if (temp & 0x20) + { + //D("DTV supports YCbCr 4:4:4.\n"); + ANX7150_edid_result.ycbcr444_supported= 1; + } + if (temp & 0x10) + { + //D("DTV supports YCbCr 4:2:2.\n"); + ANX7150_edid_result.ycbcr422_supported= 1; + } +} +static void ANX7150_Parse_DTDinExtBlock(void) +{ + u8 i,DTDbeginAddr; + DTDbeginAddr = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2, 0x82) + + 0x80; + while (DTDbeginAddr < (0x6c + 0x80)) + { + if ((ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,DTDbeginAddr) == 0) + && (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(DTDbeginAddr + 1)) == 0) + && (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(DTDbeginAddr + 2)) == 0)) + { + ;//D("this DTD in Extension Block is not used to descript video timing.\n"); + } + else + { + for (i = 0; i < 18; i++) + { + ANX7150_edid_dtd[i] = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(i + DTDbeginAddr)); + } + //D("Parse the DTD in Extension Block :\n"); + ANX7150_Parse_DTD(); + } + DTDbeginAddr = DTDbeginAddr + 18; + } +} +static void ANX7150_Parse_AudioSTD(void) +{ + u8 i,AudioFormat,STDReg_tmp,STDAddr_tmp; + STDReg_tmp = ANX7150_stdreg & 0x1f; + STDAddr_tmp = ANX7150_stdaddr + 1; + i = 0; + while (i < STDReg_tmp) + { + AudioFormat = (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,STDAddr_tmp ) & 0xF8) >> 3; + ANX7150_edid_result.AudioChannel[i/3] = (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,STDAddr_tmp) & 0x07) + 1; + ANX7150_edid_result.AudioFormat[i/3] = AudioFormat; + ANX7150_edid_result.AudioFs[i/3] = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(STDAddr_tmp + 1)) & 0x7f; + + if (AudioFormat == 1) + ANX7150_edid_result.AudioLength[i/3] = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(STDAddr_tmp + 2)) & 0x07; + else + ANX7150_edid_result.AudioLength[i/3] = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(STDAddr_tmp + 2)) << 3; + + i = i + 3; + STDAddr_tmp = STDAddr_tmp + 3; + } +} +static void ANX7150_Parse_VideoSTD(void) +{ + u8 i,STDReg_tmp,STDAddr_tmp; + u8 SVD_ID[34]; + STDReg_tmp = ANX7150_stdreg & 0x1f; + STDAddr_tmp = ANX7150_stdaddr + 1; + i = 0; + while (i < STDReg_tmp) + { + SVD_ID[i] = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,STDAddr_tmp) & 0x7F; + //D("ANX7150_edid_result.SVD_ID[%.2x]=0x%.2x\n",(u32)i,(u32)ANX7150_edid_result.SVD_ID[i]); + //if(ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,STDAddr_tmp) & 0x80) + // D(" Native mode"); + if (SVD_ID[i] == 1) + ANX7150_edid_result.supported_640x480p_60Hz = 1; + else if (SVD_ID[i] == 4) + ANX7150_edid_result.supported_720p_60Hz = 1; + else if (SVD_ID[i] == 19) + ANX7150_edid_result.supported_720p_50Hz = 1; + else if (SVD_ID[i] == 16) + ANX7150_edid_result.supported_1080p_60Hz = 1; + else if (SVD_ID[i] == 31) + ANX7150_edid_result.supported_1080p_50Hz = 1; + else if (SVD_ID[i] == 5) + ANX7150_edid_result.supported_1080i_60Hz = 1; + else if (SVD_ID[i] == 20) + ANX7150_edid_result.supported_1080i_50Hz = 1; + else if ((SVD_ID[i] == 2) ||(SVD_ID[i] == 3)) + ANX7150_edid_result.supported_720x480p_60Hz = 1; + else if ((SVD_ID[i] == 6) ||(SVD_ID[i] == 7)) + ANX7150_edid_result.supported_720x480i_60Hz = 1; + else if ((SVD_ID[i] == 17) ||(SVD_ID[i] == 18)) + ANX7150_edid_result.supported_576p_50Hz = 1; + else if ((SVD_ID[i] == 21) ||(SVD_ID[i] == 22)) + ANX7150_edid_result.supported_576i_50Hz = 1; + + i = i + 1; + STDAddr_tmp = STDAddr_tmp + 1; + } +} +static void ANX7150_Parse_SpeakerSTD(void) +{ + ANX7150_edid_result.SpeakerFormat = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(ANX7150_stdaddr + 1)) ; +} +static void ANX7150_Parse_VendorSTD(void) +{ + //u8 c; + if ((ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(ANX7150_stdaddr + 1)) == 0x03) + && (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(ANX7150_stdaddr + 2)) == 0x0c) + && (ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,(ANX7150_stdaddr + 3)) == 0x00)) + { + ANX7150_edid_result.is_HDMI = 1; + //ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_SYS_CTRL1_REG, c |ANX7150_SYS_CTRL1_HDMI); + } + else + { + ANX7150_edid_result.is_HDMI = 0; + //ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_SYS_CTRL1_REG, c & (~ANX7150_SYS_CTRL1_HDMI)); + } +} + +static void ANX7150_Parse_STD(void) +{ + u8 DTDbeginAddr; + ANX7150_stdaddr = 0x84; + DTDbeginAddr = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,0x82) + 0x80; + // D("Video DTDbeginAddr Register :%.2x\n", (u32) DTDbeginAddr); + while (ANX7150_stdaddr < DTDbeginAddr) + { + ANX7150_stdreg = ANX7150_Read_EDID_u8(ANX7150_ext_block_num/2,ANX7150_stdaddr); + switch (ANX7150_stdreg & 0xe0) + { + case 0x20: + ANX7150_Parse_AudioSTD(); + ANX7150_sau_length = ANX7150_stdreg & 0x1f; + break; + case 0x40: + ANX7150_Parse_VideoSTD(); + ANX7150_svd_length = ANX7150_stdreg & 0x1f; + break; + case 0x80: + ANX7150_Parse_SpeakerSTD(); + break; + case 0x60: + ANX7150_Parse_VendorSTD(); + break; + default: + break; + } + ANX7150_stdaddr = ANX7150_stdaddr + (ANX7150_stdreg & 0x1f) + 0x01; + } +} +static u8 ANX7150_EDID_Checksum(u8 block_number) +{ + u8 i, real_checksum; + u8 edid_block_checksum; + + edid_block_checksum = 0; + for (i = 0; i < 127; i ++) + { + if ((block_number / 2) * 2 == block_number) + edid_block_checksum = edid_block_checksum + ANX7150_Read_EDID_u8(block_number/2, i); + else + edid_block_checksum = edid_block_checksum + ANX7150_Read_EDID_u8(block_number/2, i + 0x80); + } + edid_block_checksum = (~edid_block_checksum) + 1; + // D("edid_block_checksum = 0x%.2x\n",(u32)edid_block_checksum); + if ((block_number / 2) * 2 == block_number) + real_checksum = ANX7150_Read_EDID_u8(block_number/2, 0x7f); + else + real_checksum = ANX7150_Read_EDID_u8(block_number/2, 0xff); + if (real_checksum == edid_block_checksum) + return 1; + else + return 0; +} +static u8 ANX7150_Parse_ExtBlock(void) +{ + u8 i,c; + + for (i = 0; i < ANX7150_Read_EDID_u8(0, 0x7e); i++) //read in blocks + { + c = ANX7150_Read_EDID_u8(i/2, 0x80); + if ( c == 0x02) + { + ANX7150_ext_block_num = i + 1; + ANX7150_Parse_DTDinExtBlock(); + ANX7150_Parse_STD(); + if (!(ANX7150_EDID_Checksum(ANX7150_ext_block_num))) + { + ANX7150_edid_result.edid_errcode = ANX7150_EDID_CheckSum_ERR; + return ANX7150_edid_result.edid_errcode; + } + } + else + { + ANX7150_edid_result.edid_errcode = ANX7150_EDID_ExtBlock_NotFor_861B; + return ANX7150_edid_result.edid_errcode; + } + } + + return 0; +} +int ANX7150_Parse_EDID(struct i2c_client *client, struct anx7150_dev_s *dev) +{ + int rc = 0, i; + char c; + + if(dev->rk29_output_status == RK29_OUTPUT_STATUS_LCD) + anx7150_mass_read_need_delay = 1; + else + anx7150_mass_read_need_delay = 0; + + /* Clear HDCP Authentication indicator */ + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= (~ANX7150_HDCP_CTRL0_HW_AUTHEN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + ANX7150_hdcp_auth_en = 0; + + rc = ANX7150_GetEDIDLength(client); + + hdmi_dbg(&client->dev, "EDIDLength is %.u\n", ANX7150_edid_length); + + rc = ANX7150_Read_EDID(client); + + if(!(ANX7150_Parse_EDIDHeader())) + { + dev_err(&client->dev, "BAD EDID Header, Stop parsing \n"); + ANX7150_edid_result.edid_errcode = ANX7150_EDID_BadHeader; + goto err; + } + + if(!(ANX7150_Parse_EDIDVersion())) + { + dev_err(&client->dev, "EDID does not support 861B, Stop parsing\n"); + ANX7150_edid_result.edid_errcode = ANX7150_EDID_861B_not_supported; + goto err; + } + +/* + if(ANX7150_EDID_Checksum(0) == 0) + { + D("EDID Block one check sum error, Stop parsing\n"); + ANX7150_edid_result.edid_errcode = ANX7150_EDID_CheckSum_ERR; + return ANX7150_edid_result.edid_errcode; + } +*/ + + //ANX7150_Parse_BasicDis(); + ANX7150_Parse_DTDinBlockONE(); + /* + if(ANX7150_EDID_Buf[0x7e] == 0) + { + D("No EDID extension blocks.\n"); + ANX7150_edid_result.edid_errcode = ANX7150_EDID_No_ExtBlock; + return ANX7150_edid_result.edid_errcode; + }*/ + ANX7150_Parse_NativeFormat(); + ANX7150_Parse_ExtBlock(); + + if (ANX7150_edid_result.edid_errcode == ANX7150_EDID_ExtBlock_NotFor_861B){ + dev_err(&client->dev,"EDID ExtBlock not support for 861B, Stop parsing\n"); + goto err; + } + + if (ANX7150_edid_result.edid_errcode == ANX7150_EDID_CheckSum_ERR){ + dev_err(&client->dev,"EDID Block check sum error, Stop parsing\n"); + goto err; + } + + hdmi_dbg(&client->dev,"EDID parsing finished!\n"); + + { + hdmi_dbg(&client->dev,"ANX7150_edid_result.edid_errcode = 0x%.2x\n",(u32)ANX7150_edid_result.edid_errcode); + hdmi_dbg(&client->dev,"ANX7150_edid_result.is_HDMI = 0x%.2x\n",(u32)ANX7150_edid_result.is_HDMI); + hdmi_dbg(&client->dev,"ANX7150_edid_result.ycbcr422_supported = 0x%.2x\n",(u32)ANX7150_edid_result.ycbcr422_supported); + hdmi_dbg(&client->dev,"ANX7150_edid_result.ycbcr444_supported = 0x%.2x\n",(u32)ANX7150_edid_result.ycbcr444_supported); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_1080i_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080i_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_1080i_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080i_50Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_720p_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_720p_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_720p_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_720p_50Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_640x480p_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_640x480p_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_720x480p_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_720x480p_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_720x480i_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_720x480i_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_576p_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_576p_50Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_576i_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_576i_50Hz); + if (!ANX7150_edid_result.edid_errcode) + { + for (i = 0; i < ANX7150_sau_length/3; i++) + { + hdmi_dbg(&client->dev,"ANX7150_edid_result.AudioChannel = 0x%.2x\n",(u32)ANX7150_edid_result.AudioChannel[i]); + hdmi_dbg(&client->dev,"ANX7150_edid_result.AudioFormat = 0x%.2x\n",(u32)ANX7150_edid_result.AudioFormat[i]); + hdmi_dbg(&client->dev,"ANX7150_edid_result.AudioFs = 0x%.2x\n",(u32)ANX7150_edid_result.AudioFs[i]); + hdmi_dbg(&client->dev,"ANX7150_edid_result.AudioLength = 0x%.2x\n",(u32)ANX7150_edid_result.AudioLength[i]); + } + hdmi_dbg(&client->dev,"ANX7150_edid_result.SpeakerFormat = 0x%.2x\n",(u32)ANX7150_edid_result.SpeakerFormat); + } + } + + ANX7150_parse_edid_done = 1; + + return 0; + +err: + return ANX7150_edid_result.edid_errcode; +} +int ANX7150_GET_SENSE_STATE(struct i2c_client *client) +{ + int rc = 0; + char c; + + hdmi_dbg(&client->dev, "enter\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_STATE_REG, &c); + + return (c & ANX7150_SYS_STATE_RSV_DET) ? 1 : 0; +} +int ANX7150_Get_Optimal_resolution(int resolution_set) +{ + int resolution_real; + int find_resolution = 0; + + switch(resolution_set){ + case HDMI_1280x720p_50Hz: + if(ANX7150_edid_result.supported_720p_50Hz){ + resolution_real = HDMI_1280x720p_50Hz; + find_resolution = 1; + } + break; + case HDMI_1280x720p_60Hz: + if(ANX7150_edid_result.supported_720p_60Hz){ + resolution_real = HDMI_1280x720p_60Hz; + find_resolution = 1; + } + break; + case HDMI_720x576p_50Hz: + if(ANX7150_edid_result.supported_576p_50Hz){ + resolution_real = HDMI_720x576p_50Hz; + find_resolution = 1; + } + break; + default: + break; + } + + if(find_resolution == 0){ + + if(ANX7150_edid_result.supported_720p_50Hz) + resolution_real = HDMI_1280x720p_50Hz; + else if(ANX7150_edid_result.supported_720p_60Hz) + resolution_real = HDMI_1280x720p_60Hz; + else if(ANX7150_edid_result.supported_576p_50Hz) + resolution_real = HDMI_720x576p_50Hz; + else + resolution_real = HDMI_1280x720p_50Hz; + } + + return resolution_real; +} +void ANX7150_API_HDCP_ONorOFF(u8 HDCP_ONorOFF) +{ + ANX7150_HDCP_enable = HDCP_ONorOFF;// 1: on; 0:off +} +static void ANX7150_API_Video_Config(u8 video_id,u8 input_pixel_rpt_time) +{ + ANX7150_video_timing_id = video_id; + ANX7150_in_pix_rpt = input_pixel_rpt_time; +} +static void ANX7150_API_Packets_Config(u8 pkt_sel) +{ + s_ANX7150_packet_config.packets_need_config = pkt_sel; +} +static void ANX7150_API_AVI_Config(u8 pb1,u8 pb2,u8 pb3,u8 pb4,u8 pb5, + u8 pb6,u8 pb7,u8 pb8,u8 pb9,u8 pb10,u8 pb11,u8 pb12,u8 pb13) +{ + s_ANX7150_packet_config.avi_info.pb_u8[1] = pb1; + s_ANX7150_packet_config.avi_info.pb_u8[2] = pb2; + s_ANX7150_packet_config.avi_info.pb_u8[3] = pb3; + s_ANX7150_packet_config.avi_info.pb_u8[4] = pb4; + s_ANX7150_packet_config.avi_info.pb_u8[5] = pb5; + s_ANX7150_packet_config.avi_info.pb_u8[6] = pb6; + s_ANX7150_packet_config.avi_info.pb_u8[7] = pb7; + s_ANX7150_packet_config.avi_info.pb_u8[8] = pb8; + s_ANX7150_packet_config.avi_info.pb_u8[9] = pb9; + s_ANX7150_packet_config.avi_info.pb_u8[10] = pb10; + s_ANX7150_packet_config.avi_info.pb_u8[11] = pb11; + s_ANX7150_packet_config.avi_info.pb_u8[12] = pb12; + s_ANX7150_packet_config.avi_info.pb_u8[13] = pb13; +} +static void ANX7150_API_AUD_INFO_Config(u8 pb1,u8 pb2,u8 pb3,u8 pb4,u8 pb5, + u8 pb6,u8 pb7,u8 pb8,u8 pb9,u8 pb10) +{ + s_ANX7150_packet_config.audio_info.pb_u8[1] = pb1; + s_ANX7150_packet_config.audio_info.pb_u8[2] = pb2; + s_ANX7150_packet_config.audio_info.pb_u8[3] = pb3; + s_ANX7150_packet_config.audio_info.pb_u8[4] = pb4; + s_ANX7150_packet_config.audio_info.pb_u8[5] = pb5; + s_ANX7150_packet_config.audio_info.pb_u8[6] = pb6; + s_ANX7150_packet_config.audio_info.pb_u8[7] = pb7; + s_ANX7150_packet_config.audio_info.pb_u8[8] = pb8; + s_ANX7150_packet_config.audio_info.pb_u8[9] = pb9; + s_ANX7150_packet_config.audio_info.pb_u8[10] = pb10; +} +static void ANX7150_API_AUD_CHStatus_Config(u8 MODE,u8 PCM_MODE,u8 SW_CPRGT,u8 NON_PCM, + u8 PROF_APP,u8 CAT_CODE,u8 CH_NUM,u8 SOURCE_NUM,u8 CLK_ACCUR,u8 Fs) +{ + //MODE: 0x00 = PCM Audio + //PCM_MODE: 0x00 = 2 audio channels without pre-emphasis; + //0x01 = 2 audio channels with 50/15 usec pre-emphasis; + //SW_CPRGT: 0x00 = copyright is asserted; + // 0x01 = copyright is not asserted; + //NON_PCM: 0x00 = Represents linear PCM + //0x01 = For other purposes + //PROF_APP: 0x00 = consumer applications; + // 0x01 = professional applications; + + //CAT_CODE: Category code + //CH_NUM: 0x00 = Do not take into account + // 0x01 = left channel for stereo channel format + // 0x02 = right channel for stereo channel format + //SOURCE_NUM: source number + // 0x00 = Do not take into account + // 0x01 = 1; 0x02 = 2; 0x03 = 3 + //CLK_ACCUR: 0x00 = level II + // 0x01 = level I + // 0x02 = level III + // else reserved; + + s_ANX7150_audio_config.i2s_config.Channel_status1 = (MODE << 7) | (PCM_MODE << 5) | + (SW_CPRGT << 2) | (NON_PCM << 1) | PROF_APP; + s_ANX7150_audio_config.i2s_config.Channel_status2 = CAT_CODE; + s_ANX7150_audio_config.i2s_config.Channel_status3 = (CH_NUM << 7) | SOURCE_NUM; + s_ANX7150_audio_config.i2s_config.Channel_status4 = (CLK_ACCUR << 5) | Fs; +} +void ANX7150_API_System_Config(void) +{ + ANX7150_API_Video_Config(g_video_format,input_pixel_clk_1x_repeatition); + ANX7150_API_Packets_Config(ANX7150_avi_sel | ANX7150_audio_sel); + if (s_ANX7150_packet_config.packets_need_config & ANX7150_avi_sel) + ANX7150_API_AVI_Config( 0x00,source_ratio,null,null,null,null,null,null,null,null,null,null,null); + if (s_ANX7150_packet_config.packets_need_config & ANX7150_audio_sel) + ANX7150_API_AUD_INFO_Config(null,null,null,null,null,null,null,null,null,null); + ANX7150_API_AUD_CHStatus_Config(null,null,null,null,null,null,null,null,null,g_audio_format); + +// ANX7150_system_config_done = 1; +} + +static int anx7150_blue_screen_format_config(struct i2c_client *client) +{ + int rc = 0 ; + char c; + + // TODO:Add ITU 601 format.(Now only ITU 709 format added) + switch (ANX7150_RGBorYCbCr) + { + case ANX7150_RGB: //select RGB mode + c = 0x10; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN0_REG, &c); + c = 0xeb; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN1_REG, &c); + c = 0x10; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN2_REG, &c); + break; + case ANX7150_YCbCr422: //select YCbCr4:2:2 mode + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN0_REG, &c); + c = 0xad; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN1_REG, &c); + c = 0x2a; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN2_REG, &c); + break; + case ANX7150_YCbCr444: //select YCbCr4:4:4 mode + c = 0x1a; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN0_REG, &c); + c = 0xad; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN1_REG, &c); + c = 0x2a; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_BLUESCREEN2_REG, &c); + break; + default: + break; + } + return rc; +} +static void ANX7150_Get_Video_Timing(void) +{ + u8 i; +//#ifdef ITU656 + for (i = 0; i < 18; i++) + { + switch (ANX7150_video_timing_id) + { + case ANX7150_V640x480p_60Hz: + //D("640x480p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_640x480p_60Hz[i]; + break; + case ANX7150_V720x480p_60Hz_4x3: + case ANX7150_V720x480p_60Hz_16x9: + //D("720x480p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_720x480p_60Hz[i]; + break; + case ANX7150_V1280x720p_60Hz: + //D("1280x720p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_1280x720p_60Hz[i]; + break; + case ANX7150_V1920x1080i_60Hz: + //D("1920x1080i_60Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_1920x1080i_60Hz[i]; + break; + case ANX7150_V720x480i_60Hz_4x3: + case ANX7150_V720x480i_60Hz_16x9: + //D("720x480i_60Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_720x480i_60Hz[i]; + break; + case ANX7150_V720x576p_50Hz_4x3: + case ANX7150_V720x576p_50Hz_16x9: + //D("720x576p_50Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_720x576p_50Hz[i]; + break; + case ANX7150_V1280x720p_50Hz: + //D("1280x720p_50Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_1280x720p_50Hz[i]; + break; + case ANX7150_V1920x1080i_50Hz: + //D("1920x1080i_50Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_1920x1080i_50Hz[i]; + break; + case ANX7150_V720x576i_50Hz_4x3: + case ANX7150_V720x576i_50Hz_16x9: + //D("720x576i_50Hz!\n"); + ANX7150_video_timing_parameter[i] = ANX7150_video_timingtype_table.ANX7150_720x576i_50Hz[i]; + break; + + default: + break; + } + //D("Video_Timing_Parameter[%.2x]=%.2x\n", (u32)i, (u32) ANX7150_video_timing_parameter[i]); + } + /*#else + for(i = 0; i < 18; i++) + { + switch(ANX7150_video_timing_id) + { + case ANX7150_V640x480p_60Hz: + //D("640x480p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, i); + DRVDelayMs(3); + break; + case ANX7150_V720x480p_60Hz_4x3: + case ANX7150_V720x480p_60Hz_16x9: + //D("720x480p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 18 + i); + DRVDelayMs(3); + break; + case ANX7150_V1280x720p_60Hz: + //D("1280x720p_60Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 36 + i); + DRVDelayMs(3); + break; + case ANX7150_V1920x1080i_60Hz: + //D("1920x1080i_60Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 54 + i); + DRVDelayMs(3); + break; + case ANX7150_V720x480i_60Hz_4x3: + case ANX7150_V720x480i_60Hz_16x9: + //D("720x480i_60Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 72 + i); + DRVDelayMs(3); + break; + case ANX7150_V720x576p_50Hz_4x3: + case ANX7150_V720x576p_50Hz_16x9: + //D("720x576p_50Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 90 + i); + DRVDelayMs(3); + break; + case ANX7150_V1280x720p_50Hz: + //D("1280x720p_50Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 108 + i); + DRVDelayMs(3); + break; + case ANX7150_V1920x1080i_50Hz: + //D("1920x1080i_50Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 126 + i); + DRVDelayMs(3); + break; + case ANX7150_V720x576i_50Hz_4x3: + case ANX7150_V720x576i_50Hz_16x9: + //D("720x576i_50Hz!\n"); + ANX7150_video_timing_parameter[i] = Load_from_EEPROM(0, 144 + i); + DRVDelayMs(3); + break; + + default: + break; + } + //D("Video_Timing_Parameter[%.2x]=%.2x\n", (u32)i, (u32) ANX7150_video_timing_parameter[i]); + } + #endif*/ +} +static void ANX7150_Parse_Video_Format(void) +{ + switch (ANX7150_video_format_config) + { + case ANX7150_RGB_YCrCb444_SepSync: + ANX7150_emb_sync_mode = 0; + ANX7150_demux_yc_en = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + //D("RGB_YCrCb444_SepSync mode!\n"); + break; + case ANX7150_YCrCb422_SepSync: + ANX7150_emb_sync_mode = 0; + ANX7150_demux_yc_en = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + //D("YCrCb422_SepSync mode!\n"); + break; + case ANX7150_YCrCb422_EmbSync: + //D("YCrCb422_EmbSync mode!\n"); + ANX7150_demux_yc_en = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + ANX7150_emb_sync_mode = 1; + ANX7150_Get_Video_Timing(); + break; + case ANX7150_YCMux422_SepSync_Mode1: + //D("YCMux422_SepSync_Mode1 mode!\n"); + ANX7150_emb_sync_mode = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + ANX7150_ycmux_u8_sel = 0; + ANX7150_demux_yc_en = 1; + break; + case ANX7150_YCMux422_SepSync_Mode2: + //D("YCMux422_SepSync_Mode2 mode!\n"); + ANX7150_emb_sync_mode = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + ANX7150_ycmux_u8_sel = 1; + ANX7150_demux_yc_en = 1; + break; + case ANX7150_YCMux422_EmbSync_Mode1: + //D("YCMux422_EmbSync_Mode1 mode!\n"); + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + ANX7150_emb_sync_mode = 1; + ANX7150_ycmux_u8_sel = 0; + ANX7150_demux_yc_en = 1; + ANX7150_Get_Video_Timing(); + break; + case ANX7150_YCMux422_EmbSync_Mode2: + //D("YCMux422_EmbSync_Mode2 mode!\n"); + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 0; + ANX7150_emb_sync_mode = 1; + ANX7150_ycmux_u8_sel = 1; + ANX7150_demux_yc_en = 1; + ANX7150_Get_Video_Timing(); + break; + case ANX7150_RGB_YCrCb444_DDR_SepSync: + //D("RGB_YCrCb444_DDR_SepSync mode!\n"); + ANX7150_emb_sync_mode = 0; + ANX7150_demux_yc_en = 0; + ANX7150_de_gen_en = 0; + ANX7150_ddr_bus_mode = 1; + break; + case ANX7150_RGB_YCrCb444_DDR_EmbSync: + //D("RGB_YCrCb444_DDR_EmbSync mode!\n"); + ANX7150_demux_yc_en = 0; + ANX7150_de_gen_en = 0; + ANX7150_emb_sync_mode = 1; + ANX7150_ddr_bus_mode = 1; + ANX7150_Get_Video_Timing(); + break; + case ANX7150_RGB_YCrCb444_SepSync_No_DE: + //D("RGB_YCrCb444_SepSync_No_DE mode!\n"); + ANX7150_emb_sync_mode = 0; + ANX7150_demux_yc_en = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 1; + ANX7150_Get_Video_Timing(); + break; + case ANX7150_YCrCb422_SepSync_No_DE: + //D("YCrCb422_SepSync_No_DE mode!\n"); + ANX7150_emb_sync_mode = 0; + ANX7150_demux_yc_en = 0; + ANX7150_ddr_bus_mode = 0; + ANX7150_de_gen_en = 1; + ANX7150_Get_Video_Timing(); + break; + default: + break; + } +} +static int anx7150_de_generator(struct i2c_client *client) +{ + int rc = 0; + char c; + u8 video_type,hsync_pol,vsync_pol,v_fp,v_bp,vsync_width; + u8 hsync_width_low,hsync_width_high,v_active_low,v_active_high; + u8 h_active_low,h_active_high,h_res_low,h_res_high,h_bp_low,h_bp_high; + u32 hsync_width,h_active,h_res,h_bp; + + video_type = ANX7150_video_timing_parameter[15]; + hsync_pol = ANX7150_video_timing_parameter[16]; + vsync_pol = ANX7150_video_timing_parameter[17]; + v_fp = ANX7150_video_timing_parameter[12]; + v_bp = ANX7150_video_timing_parameter[11]; + vsync_width = ANX7150_video_timing_parameter[10]; + hsync_width = ANX7150_video_timing_parameter[5]; + hsync_width = (hsync_width << 8) + ANX7150_video_timing_parameter[4]; + v_active_high = ANX7150_video_timing_parameter[9]; + v_active_low = ANX7150_video_timing_parameter[8]; + h_active = ANX7150_video_timing_parameter[3]; + h_active = (h_active << 8) + ANX7150_video_timing_parameter[2]; + h_res = ANX7150_video_timing_parameter[1]; + h_res = (h_res << 8) + ANX7150_video_timing_parameter[0]; + h_bp = ANX7150_video_timing_parameter[7]; + h_bp = (h_bp << 8) + ANX7150_video_timing_parameter[6]; + if (ANX7150_demux_yc_en) + { + hsync_width = 2* hsync_width; + h_active = 2 * h_active; + h_res = 2 * h_res; + h_bp = 2 * h_bp; + } + hsync_width_low = hsync_width & 0xff; + hsync_width_high = (hsync_width >> 8) & 0xff; + h_active_low = h_active & 0xff; + h_active_high = (h_active >> 8) & 0xff; + h_res_low = h_res & 0xff; + h_res_high = (h_res >> 8) & 0xff; + h_bp_low = h_bp & 0xff; + h_bp_high = (h_bp >> 8) & 0xff; + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xf7) | video_type; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xdf) | hsync_pol; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xbf) | vsync_pol; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = v_active_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_ACT_LINEL_REG, &c); + c = v_active_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_ACT_LINEH_REG, &c); + c = vsync_width; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VSYNC_WID_REG, &c); + c = v_bp; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VSYNC_TAIL2VIDLINE_REG, &c); + c = h_active_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_PIXL_REG, &c); + c = h_active_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_PIXH_REG, &c); + c = h_res_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_RESL_REG, &c); + c = h_res_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_RESH_REG, &c); + c = hsync_width_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HSYNC_ACT_WIDTHL_REG, &c); + c = hsync_width_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HSYNC_ACT_WIDTHH_REG, &c); + c = h_bp_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_BACKPORCHL_REG, &c); + c = h_bp_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_BACKPORCHH_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c |= ANX7150_VID_CAPCTRL0_DEGEN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + + return rc; +} +static int anx7150_embed_sync_decode(struct i2c_client *client) +{ + int rc = 0; + char c; + u8 video_type,hsync_pol,vsync_pol,v_fp,vsync_width; + u8 h_fp_low,h_fp_high,hsync_width_low,hsync_width_high; + u32 h_fp,hsync_width; + + video_type = ANX7150_video_timing_parameter[15]; + hsync_pol = ANX7150_video_timing_parameter[16]; + vsync_pol = ANX7150_video_timing_parameter[17]; + v_fp = ANX7150_video_timing_parameter[12]; + vsync_width = ANX7150_video_timing_parameter[10]; + h_fp = ANX7150_video_timing_parameter[14]; + h_fp = (h_fp << 8) + ANX7150_video_timing_parameter[13]; + hsync_width = ANX7150_video_timing_parameter[5]; + hsync_width = (hsync_width << 8) + ANX7150_video_timing_parameter[4]; + if (ANX7150_demux_yc_en) + { + h_fp = 2 * h_fp; + hsync_width = 2* hsync_width; + } + h_fp_low = h_fp & 0xff; + h_fp_high = (h_fp >> 8) & 0xff; + hsync_width_low = hsync_width & 0xff; + hsync_width_high = (hsync_width >> 8) & 0xff; + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xf7) | video_type; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xdf) | hsync_pol; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + c = (c & 0xbf) | vsync_pol; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL1_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c = c | ANX7150_VID_CAPCTRL0_EMSYNC_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + + c = v_fp; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_ACT_LINE2VSYNC_REG, &c); + c = vsync_width; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VSYNC_WID_REG, &c); + c = h_fp_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_FRONTPORCHL_REG, &c); + c = h_fp_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_H_FRONTPORCHH_REG, &c); + c = hsync_width_low; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HSYNC_ACT_WIDTHL_REG, &c); + c = hsync_width_high; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HSYNC_ACT_WIDTHH_REG, &c); + return rc; +} +//******************************Video Config*************************************** +int ANX7150_Config_Video(struct i2c_client *client) +{ + int rc = 0; + char c,TX_is_HDMI; + char cspace_y2r, y2r_sel, up_sample,range_y2r; + + cspace_y2r = 0; + y2r_sel = 0; + up_sample = 0; + range_y2r = 0; + + //ANX7150_RGBorYCbCr = 0x00; //RGB + //ANX7150_RGBorYCbCr = ANX7150_INPUT_COLORSPACE; //update + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c &= (~ANX7150_VID_CTRL_u8CTRL_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); +/* + if (!ANX7150_system_config_done) + { + D("System has not finished config!\n"); + return; + } +*/ + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_STATE_REG, &c); + if (!(c & 0x02)) + { + hdmi_dbg(&client->dev, "No clock detected !\n"); + //ANX7150_i2c_write_p0_reg(ANX7150_SYS_CTRL2_REG, 0x02); + return -1; + } + + rc = anx7150_clean_hdcp(client); + + //color space issue + switch (ANX7150_video_timing_id) + { + case ANX7150_V1280x720p_50Hz: + case ANX7150_V1280x720p_60Hz: + case ANX7150_V1920x1080i_60Hz: + case ANX7150_V1920x1080i_50Hz: + case ANX7150_V1920x1080p_60Hz: + case ANX7150_V1920x1080p_50Hz: + y2r_sel = ANX7150_CSC_BT709; + break; + default: + y2r_sel = ANX7150_CSC_BT601; + break; + } + //rang[0~255]/[16~235] select + if (ANX7150_video_timing_id == ANX7150_V640x480p_60Hz) + range_y2r = 1;//rang[0~255] + else + range_y2r = 0;//rang[16~235] + if ((ANX7150_RGBorYCbCr == ANX7150_YCbCr422) && (!ANX7150_edid_result.ycbcr422_supported)) + { + up_sample = 1; + if (ANX7150_edid_result.ycbcr444_supported) + cspace_y2r = 0; + else + cspace_y2r = 1; + } + if ((ANX7150_RGBorYCbCr == ANX7150_YCbCr444) && (!ANX7150_edid_result.ycbcr444_supported)) + { + cspace_y2r = 1; + } + //Config the embeded blue screen format according to output video format. + rc = anx7150_blue_screen_format_config(client); + + ANX7150_Parse_Video_Format(); + + if (ANX7150_de_gen_en) + { + hdmi_dbg(&client->dev, "ANX7150_de_gen_en!\n"); + rc = anx7150_de_generator(client); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_DEGEN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + } + if (ANX7150_emb_sync_mode) + { + hdmi_dbg(&client->dev, "ANX7150_Embed_Sync_Decode!\n"); + rc = anx7150_embed_sync_decode(client); + + if (ANX7150_ddr_bus_mode) //jack wen; for DDR embeded sync + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + c |= (0x04); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + c &= (0xfb); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + } + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_EMSYNC_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + } + if (ANX7150_demux_yc_en) + { + hdmi_dbg(&client->dev, "ANX7150_demux_yc_en!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c |= (ANX7150_VID_CAPCTRL0_DEMUX_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + + if (ANX7150_ycmux_u8_sel) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_YCu8_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + //jack wen, u8 mapping for yc mux, D3-8,1-0 -->D1-4 + hdmi_dbg(&client->dev, "ANX7150_demux_yc_en!####D1-4\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_u8CTRL_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + c = 0x0d; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL11, &c); + c = 0x0c; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL10, &c); + c = 0x0b; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL9, &c); + c = 0x0a; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL8, &c); + c = 0x09; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL7, &c); + c = 0x08; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL6, &c); + c = 0x01; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL5, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL4, &c); + // + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c &= (~ANX7150_VID_CTRL_YCu8_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + //jack wen, u8 mapping for yc mux, D3-8,1-0 -->D5-8, + hdmi_dbg(&client->dev, "ANX7150_demux_yc_en!####D5-8\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_u8CTRL_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + c = 0x0d; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL15, &c); + c = 0x0c; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL14, &c); + c = 0x0b; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL3, &c); + c = 0x0a; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL12, &c); + c = 0x09; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL11, &c); + c = 0x08; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL10, &c); + c = 0x01; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL9, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL8, &c); + // + } + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_DEMUX_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + //jack wen + + // + + } + if (ANX7150_ddr_bus_mode) + { + //D("ANX7150_ddr_bus_mode!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c |= (ANX7150_VID_CAPCTRL0_DV_BUSMODE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + //jack wen + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + c = (c & 0xfc) | 0x02; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_YCu8_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + //jack wen + + if (ANX7150_ddr_edge) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c |= (ANX7150_VID_CAPCTRL0_DDR_EDGE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_DDR_EDGE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + } + + //jack wen for DDR+seperate maping + if (ANX7150_video_format_config == 0x07)//jack wen, DDR yc422, 601, + { + hdmi_dbg(&client->dev, "ANX7150_DDR_601_Maping!\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_u8CTRL_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + c = 0x0b; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL23, &c); + c = 0x0a; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL22, &c); + c = 0x09; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL21, &c); + c = 0x08; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL20, &c); + c = 0x07; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL19, &c); + c = 0x06; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL18, &c); + c = 0x05; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL17, &c); + c = 0x04; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL16, &c); + + c = 0x17; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL15, &c); + c = 0x16; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL14, &c); + c = 0x15; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL13, &c); + c = 0x14; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL12, &c); + c = 0x13; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL11, &c); + c = 0x12; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL10, &c); + c = 0x11; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL9, &c); + c = 0x10; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL8, &c); + + c = 0x03; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL7, &c); + c = 0x02; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL6, &c); + c = 0x01; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL5, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL4, &c); + c = 0x0f; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL3, &c); + c = 0x0e; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL2, &c); + c = 0x0d; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL1, &c); + c = 0x0c; + rc = anx7150_i2c_write_p0_reg(client, VID_u8_CTRL0, &c); + + } + else if (ANX7150_video_format_config == 0x08)//jack wen, DDR yc422, 656, + { + hdmi_dbg(&client->dev, "ANX7150_DDR_656_Maping!\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c &= (~ANX7150_VID_CTRL_u8CTRL_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + } + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_DV_BUSMODE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + c &= (~ANX7150_VID_CAPCTRL0_DDR_EDGE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CAPCTRL0_REG, &c); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + c &= (0xfc); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL4_REG, &c); + } + + if (cspace_y2r) + { + hdmi_dbg(&client->dev, "Color space Y2R enabled********\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c |= (ANX7150_VID_MODE_CSPACE_Y2R); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + if (y2r_sel) + { + hdmi_dbg(&client->dev, "Y2R_SEL!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c |= (ANX7150_VID_MODE_Y2R_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c &= (~ANX7150_VID_MODE_Y2R_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c &= (~ANX7150_VID_MODE_CSPACE_Y2R); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + + if (up_sample) + { + hdmi_dbg(&client->dev, "UP_SAMPLE!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c |= (ANX7150_VID_MODE_UPSAMPLE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c &= (~ANX7150_VID_MODE_UPSAMPLE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + + if (range_y2r) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c |= (ANX7150_VID_MODE_RANGE_Y2R); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + else + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c &= (~ANX7150_VID_MODE_RANGE_Y2R); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + } + + if (!ANX7150_pix_rpt_set_by_sys) + { + if ((ANX7150_video_timing_id == ANX7150_V720x480i_60Hz_16x9) + || (ANX7150_video_timing_id == ANX7150_V720x576i_50Hz_16x9) + || (ANX7150_video_timing_id == ANX7150_V720x480i_60Hz_4x3) + || (ANX7150_video_timing_id == ANX7150_V720x576i_50Hz_4x3)) + ANX7150_tx_pix_rpt = 1; + else + ANX7150_tx_pix_rpt = 0; + } + //set input pixel repeat times + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_MODE_REG, &c); + c = ((c & 0xfc) |ANX7150_in_pix_rpt); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_MODE_REG, &c); + //set link pixel repeat times + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c = ((c & 0xfc) |ANX7150_tx_pix_rpt); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + if ((ANX7150_in_pix_rpt != ANX7150_in_pix_rpt_bkp) + ||(ANX7150_tx_pix_rpt != ANX7150_tx_pix_rpt_bkp) ) + { + c = 0x02; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL2_REG, &c); + hdmi_dbg(&client->dev, "MISC_Reset!\n"); + ANX7150_in_pix_rpt_bkp = ANX7150_in_pix_rpt; + ANX7150_tx_pix_rpt_bkp = ANX7150_tx_pix_rpt; + } + //enable video input + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + c |= (ANX7150_VID_CTRL_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_VID_CTRL_REG, &c); + + //D("Video configure OK!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_STATUS_REG, &c); + if (!(c & ANX7150_VID_STATUS_VID_STABLE)) + { + hdmi_dbg(&client->dev,"Video not stable!\n"); + return -1; + } + if (cspace_y2r) + ANX7150_RGBorYCbCr = ANX7150_RGB; + //Enable video CLK,Format change after config video. + // ANX7150_i2c_read_p0_reg(ANX7150_INTR1_MASK_REG, &c); + // ANX7150_i2c_write_p0_reg(ANX7150_INTR1_MASK_REG, c |0x01);//3 + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR2_MASK_REG, &c); + c |= (0x48); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR2_MASK_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR3_MASK_REG, &c); + c |= (0x40); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR3_MASK_REG, &c); + + if (ANX7150_edid_result.is_HDMI) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c |= (0x02); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + hdmi_dbg(&client->dev,"ANX7150 is set to HDMI mode\n"); + } + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + TX_is_HDMI = c & 0x02; + + if (TX_is_HDMI == 0x02) + { + anx7150_set_avmute(client);//wen + } + + //reset TMDS link to align 4 channels xy 061120 + hdmi_dbg(&client->dev,"reset TMDS link to align 4 channels\n"); + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SRST_REG, &c); + c |= (ANX7150_TX_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SRST_REG, &c); + c &= (~ANX7150_TX_RST); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SRST_REG, &c); + + //Enable TMDS clock output // just enable u87, and let the other u8s along to avoid overwriting. + hdmi_dbg(&client->dev,"Enable TMDS clock output\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + c |= (ANX7150_TMDS_CLKCH_MUTE); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + + msleep(400); //400ms only for HDCP CTS + + //ANX7150_i2c_read_p0_reg(ANX7150_VID_MODE_REG, &c); //zy 061110 + return 0; +} +static u8 anx7150_config_i2s(struct i2c_client *client) +{ + int rc; + char c = 0x00; + u8 exe_result = 0x00; + char c1 = 0x00; + + hdmi_dbg(&client->dev,"ANX7150: config i2s audio.\n"); + + //select SCK as source + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= ~ANX7150_HDMI_AUDCTRL1_CLK_SEL; + hdmi_dbg(&client->dev,"select SCK as source, c = 0x%.2x\n",(u32)c); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + + //config i2s channel + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c1 = s_ANX7150_audio_config.i2s_config.audio_channel; // need u8[5:2] + c1 &= 0x3c; + c &= ~0x3c; + c |= c1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + hdmi_dbg(&client->dev,"config i2s channel, c = 0x%.2x\n",(u32)c); + + //config i2s format + //ANX7150_i2c_read_p0_reg(ANX7150_I2S_CTRL_REG, &c); + c = s_ANX7150_audio_config.i2s_config.i2s_format; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2S_CTRL_REG, &c); + hdmi_dbg(&client->dev,"config i2s format, c = 0x%.2x\n",(u32)c); + + //map i2s fifo + + //TODO: config I2S channel map register according to system + + + //ANX7150_i2c_write_p0_reg(ANX7150_I2SCH_CTRL_REG, c); + + //swap right/left channel + /*ANX7150_i2c_read_p0_reg(ANX7150_I2SCH_SWCTRL_REG, &c); + c1 = 0x00; + c1 &= 0xf0; + c &= ~0xf0; + c |= c1; + ANX7150_i2c_write_p0_reg(ANX7150_I2SCH_SWCTRL_REG, c); + D("map i2s ffio, c = 0x%.2x\n",(u32)c);*/ + + //down sample + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c1 = s_ANX7150_audio_config.down_sample; + c1 &= 0x60; + c &= ~0x60; + c |= c1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + hdmi_dbg(&client->dev,"down sample, c = 0x%.2x\n",(u32)c); + + //config i2s channel status(5 regs) + c = s_ANX7150_audio_config.i2s_config.Channel_status1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS1_REG, &c); + c = s_ANX7150_audio_config.i2s_config.Channel_status2; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS2_REG, &c); + c = s_ANX7150_audio_config.i2s_config.Channel_status3; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS3_REG, &c); + c = s_ANX7150_audio_config.i2s_config.Channel_status4; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + hdmi_dbg(&client->dev,"@@@@@@@@config i2s channel status4, c = 0x%.2x\n",(unsigned int)c);//jack wen + + c = s_ANX7150_audio_config.i2s_config.Channel_status5; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS5_REG, &c); + hdmi_dbg(&client->dev,"config i2s channel status, c = 0x%.2x\n",(u32)c); + + exe_result = ANX7150_i2s_input; + //D("return = 0x%.2x\n",(u32)exe_result); + + // open corresponding interrupt + //ANX7150_i2c_read_p0_reg(ANX7150_INTR1_MASK_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_INTR1_MASK_REG, (c | 0x22) ); + //ANX7150_i2c_read_p0_reg(ANX7150_INTR3_MASK_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_INTR3_MASK_REG, (c | 0x20) ); + + + return exe_result; +} + +static u8 anx7150_config_spdif(struct i2c_client *client) +{ + int rc = 0; + u8 exe_result = 0x00; + char c = 0x00; + char c1 = 0x00; + // u8 c2 = 0x00; + // u8 freq_mclk = 0x00; + + hdmi_dbg(&client->dev, "ANX7150: config SPDIF audio.\n"); + + + //Select MCLK + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= (ANX7150_HDMI_AUDCTRL1_CLK_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + //D("ANX7150: enable SPDIF audio.\n"); + //Enable SPDIF + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= (ANX7150_HDMI_AUDCTRL1_SPDIFIN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + //adjust MCLK phase in interrupt routine + + // adjust FS_FREQ //FS_FREQ + c1 = s_ANX7150_audio_config.i2s_config.Channel_status4 & 0x0f; + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SPDIFCH_STATUS_REG, &c); + c &= ANX7150_SPDIFCH_STATUS_FS_FREG; + c = c >> 4; + + if ( c != c1) + { + //D("adjust FS_FREQ by system!\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + c &= 0xf0; + c |= c1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + + //enable using FS_FREQ from 0x59 + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= (0x02); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + + // down sample + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c1 = s_ANX7150_audio_config.down_sample; + c1 &= 0x60; + c &= ~0x60; + c |= c1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + + if (s_ANX7150_audio_config.down_sample) //zy 060816 + { + // adjust FS_FREQ by system because down sample + //D("adjust FS_FREQ by system because down sample!\n"); + + c1 = s_ANX7150_audio_config.i2s_config.Channel_status4 & 0x0f; + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + + c &= 0xf0; + c |= c1; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + } + + + // spdif is stable + hdmi_dbg(&client->dev, "config SPDIF audio done"); + exe_result = ANX7150_spdif_input; + + // open corresponding interrupt + rc = anx7150_i2c_read_p0_reg(client, ANX7150_INTR1_MASK_REG, &c); + c |= (0x32); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_INTR1_MASK_REG, &c); + //ANX7150_i2c_read_p0_reg(ANX7150_INTR3_MASK_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_INTR3_MASK_REG, (c | 0xa1) ); + return exe_result; +} + +static u8 anx7150_config_super_audio(struct i2c_client *client) +{ + int rc = 0; + u8 exe_result = 0x00; + u8 c = 0x00; + + + //D("ANX7150: config one u8 audio.\n"); + + // select sck as source + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= (~ANX7150_HDMI_AUDCTRL1_CLK_SEL); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + // Enable stream 0x60 + c = s_ANX7150_audio_config.super_audio_config.one_u8_ctrl; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_ONEu8_AUD_CTRL_REG, &c); + + + // Map stream 0x61 + // TODO: config super audio map register according to system + + exe_result = ANX7150_super_audio_input; + return exe_result; + +} + +u8 ANX7150_Config_Audio(struct i2c_client *client) +{ + int rc; + char c = 0x00; + u8 exe_result = 0x00; + u8 audio_layout = 0x00; + u8 fs = 0x00; + u32 ACR_N = 0x0000; + + //set audio clock edge + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c = ((c & 0xf7) | ANX7150_audio_clock_edge); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + + //cts get select from SCK + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c = (c & 0xef); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + hdmi_dbg(&client->dev, "audio_type = 0x%.2x\n",(u32)s_ANX7150_audio_config.audio_type); + if (s_ANX7150_audio_config.audio_type & ANX7150_i2s_input) + { + hdmi_dbg(&client->dev, "Config I2s.\n"); + exe_result |= anx7150_config_i2s(client); + } + else + { + //disable I2S audio input + hdmi_dbg(&client->dev, "Disable I2S audio input.\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= 0xc3; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + + if (s_ANX7150_audio_config.audio_type & ANX7150_spdif_input) + { + exe_result |= anx7150_config_spdif(client); + } + else + { + //disable SPDIF audio input + hdmi_dbg(&client->dev, "Disable SPDIF audio input.\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= ~ANX7150_HDMI_AUDCTRL1_SPDIFIN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + + if (s_ANX7150_audio_config.audio_type & ANX7150_super_audio_input) + { + exe_result |= anx7150_config_super_audio(client); + } + else + { + //disable super audio output + hdmi_dbg(&client->dev, "ANX7150: disable super audio output.\n"); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_ONEu8_AUD_CTRL_REG, &c); + } + + if ((s_ANX7150_audio_config.audio_type & 0x07) == 0x00) + { + hdmi_dbg(&client->dev, "ANX7150 input no audio type.\n"); + } + + //audio layout + if (s_ANX7150_audio_config.audio_type & ANX7150_i2s_input) + { + //ANX7150_i2c_read_p0_reg(ANX7150_HDMI_AUDCTRL1_REG, &c); + audio_layout = s_ANX7150_audio_config.audio_layout; + + //HDMI_RX_ReadI2C_RX0(0x15, &c); +#if 0 + if ((c & 0x08) ==0x08 ) //u8[5:3] + { + audio_layout = 0x80; + } + else + { + audio_layout = 0x00; + } +#endif + } + if (s_ANX7150_audio_config.audio_type & ANX7150_super_audio_input) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_ONEu8_AUD_CTRL_REG, &c); + if ( c & 0xfc) //u8[5:3] + { + audio_layout = 0x80; + } + } + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c &= ~0x80; + c |= audio_layout; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + + if ( (s_ANX7150_audio_config.audio_type & 0x07) == exe_result ) + { + //Initial N value + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + fs = c & 0x0f; + // set default value to N + ACR_N = ANX7150_N_48k; + switch (fs) + { + case(0x00)://44.1k + ACR_N = ANX7150_N_44k; + break; + case(0x02)://48k + ACR_N = ANX7150_N_48k; + break; + case(0x03)://32k + ACR_N = ANX7150_N_32k; + break; + case(0x08)://88k + ACR_N = ANX7150_N_88k; + break; + case(0x0a)://96k + ACR_N = ANX7150_N_96k; + break; + case(0x0c)://176k + ACR_N = ANX7150_N_176k; + break; + case(0x0e)://192k + ACR_N = ANX7150_N_192k; + break; + default: + dev_err(&client->dev, "note wrong fs.\n"); + break; + } + // write N(ACR) to corresponding regs + c = ACR_N; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_ACR_N1_SW_REG, &c); + c = ACR_N>>8; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_ACR_N2_SW_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_ACR_N3_SW_REG, &c); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c = (c & 0xf8) | FREQ_MCLK; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + + // set the relation of MCLK and Fs xy 070117 + hdmi_dbg(&client->dev, "Audio MCLK input mode is: %.2x\n",(u32)FREQ_MCLK); + + //Enable control of ACR + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + c |= (ANX7150_INFO_PKTCTRL1_ACR_EN); + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + //audio enable: + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= (ANX7150_HDMI_AUDCTRL1_IN_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + + return exe_result; + +} +static u8 ANX7150_Checksum(infoframe_struct *p) +{ + u8 checksum = 0x00; + u8 i; + + checksum = p->type + p->length + p->version; + for (i=1; i <= p->length; i++) + { + checksum += p->pb_u8[i]; + } + checksum = ~checksum; + checksum += 0x01; + + return checksum; +} +static u8 anx7150_load_infoframe(struct i2c_client *client, packet_type member, + infoframe_struct *p) +{ + int rc = 0; + u8 exe_result = 0x00; + u8 address[8] = {0x00,0x20,0x40,0x60,0x80,0x80,0xa0,0xa0}; + u8 i; + char c; + + p->pb_u8[0] = ANX7150_Checksum(p); + + // write infoframe to according regs + c = p->type; + rc = anx7150_i2c_write_p1_reg(client, address[member], &c); + c = p->version; + rc = anx7150_i2c_write_p1_reg(client, address[member]+1, &c); + c = p->length; + rc = anx7150_i2c_write_p1_reg(client, address[member]+2, &c); + + for (i=0; i <= p->length; i++) + { + c = p->pb_u8[i]; + rc = anx7150_i2c_write_p1_reg(client, address[member]+3+i, &c); + rc = anx7150_i2c_read_p1_reg(client, address[member]+3+i, &c); + } + return exe_result; +} + +//*************** Config Packet **************************** +u8 ANX7150_Config_Packet(struct i2c_client *client) +{ + int rc = 0; + u8 exe_result = 0x00; // There is no use in current solution + u8 info_packet_sel; + char c; + + info_packet_sel = s_ANX7150_packet_config.packets_need_config; + hdmi_dbg(&client->dev, "info_packet_sel = 0x%.2x\n",(u32) info_packet_sel); + // New packet? + if ( info_packet_sel != 0x00) + { + // avi infoframe + if ( info_packet_sel & ANX7150_avi_sel ) + { + c = s_ANX7150_packet_config.avi_info.pb_u8[1]; //color space + c &= 0x9f; + c |= (ANX7150_RGBorYCbCr << 5); + s_ANX7150_packet_config.avi_info.pb_u8[1] = c | 0x10; + + switch(ANX7150_video_timing_id) { + case ANX7150_V720x576p_50Hz_4x3: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0x59; + break; + case ANX7150_V1280x720p_50Hz: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xaa; + break; + case ANX7150_V1280x720p_60Hz: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xaa; + break; + default: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xaa; + break; + } + + c = s_ANX7150_packet_config.avi_info.pb_u8[4];// vid ID + c = c & 0x80; + s_ANX7150_packet_config.avi_info.pb_u8[4] = c | ANX7150_video_timing_id; + c = s_ANX7150_packet_config.avi_info.pb_u8[5]; //repeat times + c = c & 0xf0; + c |= (ANX7150_tx_pix_rpt & 0x0f); + s_ANX7150_packet_config.avi_info.pb_u8[5] = c; + hdmi_dbg(&client->dev, "config avi infoframe packet.\n"); + // Disable repeater + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL1_AVI_RPT; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + + // Enable?wait:go + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + if (c & ANX7150_INFO_PKTCTRL1_AVI_EN) + { + //D("wait disable, config avi infoframe packet.\n"); + return exe_result; //jack wen + } + + // load packet data to regs + rc = anx7150_load_infoframe(client, ANX7150_avi_infoframe, + &(s_ANX7150_packet_config.avi_info)); + // Enable and repeater + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + c |= 0x30; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL1_REG, &c); + + // complete avi packet + hdmi_dbg(&client->dev, "config avi infoframe packet done.\n"); + s_ANX7150_packet_config.packets_need_config &= ~ANX7150_avi_sel; + + } + + // audio infoframe + if ( info_packet_sel & ANX7150_audio_sel ) + { + hdmi_dbg(&client->dev, "config audio infoframe packet.\n"); + + // Disable repeater + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_AIF_RPT; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + + // Enable?wait:go + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + if (c & ANX7150_INFO_PKTCTRL2_AIF_EN) + { + //D("wait disable, config audio infoframe packet.\n"); + //return exe_result;//jack wen + } + // config packet + + // load packet data to regs + + anx7150_load_infoframe( client, ANX7150_audio_infoframe, + &(s_ANX7150_packet_config.audio_info)); + // Enable and repeater + rc = anx7150_i2c_read_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0x03; + rc = anx7150_i2c_write_p1_reg(client, ANX7150_INFO_PKTCTRL2_REG, &c); + + // complete avi packet + + hdmi_dbg(&client->dev, "config audio infoframe packet done.\n"); + s_ANX7150_packet_config.packets_need_config &= ~ANX7150_audio_sel; + + } + + // config other 4 packets + /* + + if( info_packet_sel & 0xfc ) + { + D("other packets.\n"); + + //find the current type need config + if(info_packet_sel & ANX7150_spd_sel) type_sel = ANX7150_spd_sel; + else if(info_packet_sel & ANX7150_mpeg_sel) type_sel = ANX7150_mpeg_sel; + else if(info_packet_sel & ANX7150_acp_sel) type_sel = ANX7150_acp_sel; + else if(info_packet_sel & ANX7150_isrc1_sel) type_sel = ANX7150_isrc1_sel; + else if(info_packet_sel & ANX7150_isrc2_sel) type_sel = ANX7150_isrc2_sel; + else type_sel = ANX7150_vendor_sel; + + + // Disable repeater + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_AIF_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + + switch(type_sel) + { + case ANX7150_spd_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL1_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL1_SPD_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL1_REG, c); + + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL1_REG, &c); + if(c & ANX7150_INFO_PKTCTRL1_SPD_EN) + { + D("wait disable, config spd infoframe packet.\n"); + return exe_result; + } + break; + + case ANX7150_mpeg_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_MPEG_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + if(c & ANX7150_INFO_PKTCTRL2_MPEG_EN) + { + D("wait disable, config mpeg infoframe packet.\n"); + return exe_result; + } + break; + + case ANX7150_acp_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_UD0_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + if(c & ANX7150_INFO_PKTCTRL2_UD0_EN) + { + D("wait disable, config mpeg infoframe packet.\n"); + return exe_result; + } + break; + + case ANX7150_isrc1_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_UD0_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + if(c & ANX7150_INFO_PKTCTRL2_UD0_EN) + { + D("wait disable, config isrc1 packet.\n"); + return exe_result; + } + break; + + case ANX7150_isrc2_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_UD_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + if(c & ANX7150_INFO_PKTCTRL2_UD_EN) + { + D("wait disable, config isrc2 packet.\n"); + return exe_result; + } + break; + + case ANX7150_vendor_sel: + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c &= ~ANX7150_INFO_PKTCTRL2_UD_RPT; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + if(c & ANX7150_INFO_PKTCTRL2_UD_EN) + { + D("wait disable, config vendor packet.\n"); + return exe_result; + } + break; + + default : break; + } + + + // config packet + // TODO: config packet in top level + + // load packet data to regs + switch(type_sel) + { + case ANX7150_spd_sel: + ANX7150_Load_Infoframe( ANX7150_spd_infoframe, + &(s_ANX7150_packet_config.spd_info)); + D("config spd done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL1_REG, &c); + c |= 0xc0; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL1_REG, c); + break; + + case ANX7150_mpeg_sel: + ANX7150_Load_Infoframe( ANX7150_mpeg_infoframe, + &(s_ANX7150_packet_config.mpeg_info)); + D("config mpeg done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0x0c; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + break; + + case ANX7150_acp_sel: + ANX7150_Load_Packet( ANX7150_acp_packet, + &(s_ANX7150_packet_config.acp_pkt)); + D("config acp done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0x30; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + break; + + case ANX7150_isrc1_sel: + ANX7150_Load_Packet( ANX7150_isrc1_packet, + &(s_ANX7150_packet_config.acp_pkt)); + D("config isrc1 done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0x30; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + break; + + case ANX7150_isrc2_sel: + ANX7150_Load_Packet( ANX7150_isrc2_packet, + &(s_ANX7150_packet_config.acp_pkt)); + D("config isrc2 done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0xc0; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + break; + + case ANX7150_vendor_sel: + ANX7150_Load_Infoframe( ANX7150_vendor_infoframe, + &(s_ANX7150_packet_config.vendor_info)); + D("config vendor done.\n"); + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0xc0; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + break; + + default : break; + } + + // Enable and repeater + ANX7150_i2c_read_p1_reg(ANX7150_INFO_PKTCTRL2_REG, &c); + c |= 0x03; + ANX7150_i2c_write_p1_reg(ANX7150_INFO_PKTCTRL2_REG, c); + + // complete config packet + D("config other packets done.\n"); + s_ANX7150_packet_config.packets_need_config &= ~type_sel; + + } + */ + } + + + if ( s_ANX7150_packet_config.packets_need_config == 0x00) + { + hdmi_dbg(&client->dev, "config packets done\n"); + //ANX7150_Set_System_State(ANX7150_HDCP_AUTHENTICATION); + } + + + return exe_result; +} +//******************** HDCP process ******************************** +static int anx7150_hardware_hdcp_auth_init(struct i2c_client *client) +{ + int rc = 0; + u8 c; + +// ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); //72:07.2 hdcp on +// ANX7150_i2c_write_p0_reg(ANX7150_SYS_CTRL1_REG, (c | ANX7150_SYS_CTRL1_HDCPMODE)); + // disable hw hdcp +// ANX7150_i2c_read_p0_reg(ANX7150_HDCP_CTRL0_REG, &c); +// ANX7150_i2c_write_p0_reg(ANX7150_HDCP_CTRL0_REG, (c & (~ANX7150_HDCP_CTRL0_HW_AUTHEN))); + + //ANX7150_i2c_write_p0_reg(ANX7150_HDCP_CTRL0_REG, 0x03); //h/w auth off, jh simplay/hdcp + c = 0x00; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); //bit 0/1 off, as from start, we don't know if Bksv/srm/KSVList valid or not. SY. + + // DDC reset + rc = anx7150_rst_ddcchannel(client); + + anx7150_initddc_read(client, 0x74, 0x00, 0x40, 0x01, 0x00); + msleep(5); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &ANX7150_hdcp_bcaps); + hdmi_dbg(&client->dev, "ANX7150_Hardware_HDCP_Auth_Init(): ANX7150_hdcp_bcaps = 0x%.2x\n", (u32)ANX7150_hdcp_bcaps); + + if (ANX7150_hdcp_bcaps & 0x02) + { //enable 1.1 feature + hdmi_dbg(&client->dev, "ANX7150_Hardware_HDCP_Auth_Init(): bcaps supports 1.1\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + c |= ANX7150_HDCP_CTRL1_HDCP11_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + } + else + { //disable 1.1 feature and enable HDCP two special point check + hdmi_dbg(&client->dev, "bcaps don't support 1.1\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + c = ((c & (~ANX7150_HDCP_CTRL1_HDCP11_EN)) | ANX7150_LINK_CHK_12_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + } + //handle repeater bit. SY. + if (ANX7150_hdcp_bcaps & 0x40) + { + //repeater + hdmi_dbg(&client->dev, "ANX7150_Hardware_HDCP_Auth_Init(): bcaps shows Sink is a repeater\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c |= ANX7150_HDCP_CTRL0_RX_REP; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + } + else + { + //receiver + hdmi_dbg(&client->dev, "ANX7150_Hardware_HDCP_Auth_Init(): bcaps shows Sink is a receiver\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= ~ANX7150_HDCP_CTRL0_RX_REP; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + } + anx7150_rst_ddcchannel(client); + ANX7150_hdcp_auth_en = 0; + + return rc; +} +static u8 anx7150_bksv_srm(struct i2c_client *client) +{ + int rc = 0; +#if 1 + u8 bksv[5],i,bksv_one,c1; + anx7150_initddc_read(client, 0x74, 0x00, 0x00, 0x05, 0x00); + msleep(15); + for (i = 0; i < 5; i ++) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &bksv[i]); + } + + bksv_one = 0; + for (i = 0; i < 8; i++) + { + c1 = 0x01 << i; + if (bksv[0] & c1) + bksv_one ++; + if (bksv[1] & c1) + bksv_one ++; + if (bksv[2] & c1) + bksv_one ++; + if (bksv[3] & c1) + bksv_one ++; + if (bksv[4] & c1) + bksv_one ++; + } + //wen HDCP CTS + if (bksv_one != 20) + { + hdmi_dbg(&client->dev, "BKSV check fail\n"); + return 0; + } + else + { + hdmi_dbg(&client->dev, "BKSV check OK\n"); + return 1; + } +#endif + +#if 0 //wen HDCP CTS + /*address by gerard.zhu*/ + u8 i,j,bksv_ones_count,bksv_data[Bksv_Data_Nums] = {0}; + ANX7150_DDC_Addr bksv_ddc_addr; + u32 bksv_length; + ANX7150_DDC_Type ddc_type; + + i = 0; + j = 0; + bksv_ones_count = 0; + bksv_ddc_addr.dev_addr = HDCP_Dev_Addr; + bksv_ddc_addr.sgmt_addr = 0; + bksv_ddc_addr.offset_addr = HDCP_Bksv_Offset; + bksv_length = Bksv_Data_Nums; + ddc_type = DDC_Hdcp; + + if (!ANX7150_DDC_Read(bksv_ddc_addr, bksv_data, bksv_length, ddc_type)) + { + /*Judge validity for Bksv*/ + while (i < Bksv_Data_Nums) + { + while (j < 8) + { + if (((bksv_data[i] >> j) & 0x01) == 1) + { + bksv_ones_count++; + } + j++; + } + i++; + j = 0; + } + if (bksv_ones_count != 20) + { + rk29printk ("!!!!BKSV 1s ¡Ù20\n"); //update rk29printk ("!!!!BKSV 1s ¡Ù20\n"); + return 0; + } + } + /*end*/ + + D("bksv is ready.\n"); + // TODO: Compare the bskv[] value to the revocation list to decide if this value is a illegal BKSV. This is system depended. + //If illegal, return 0; legal, return 1. Now just return 1 + return 1; +#endif +} + +static u8 anx7150_is_ksvlist_vld(struct i2c_client *client) +{ + int rc = 0; +//wen HDCP CTS +#if 1 + hdmi_dbg(&client->dev, "ANX7150_IS_KSVList_VLD() is called.\n"); + anx7150_initddc_read(client, 0x74, 0x00, 0x41, 0x02, 0x00); //Bstatus, two u8s + msleep(5); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &ANX7150_hdcp_bstatus[0]); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &ANX7150_hdcp_bstatus[1]); + + if ((ANX7150_hdcp_bstatus[0] & 0x80) | (ANX7150_hdcp_bstatus[1] & 0x08)) + { + hdmi_dbg(&client->dev, "Max dev/cascade exceeded: ANX7150_hdcp_bstatus[0]: 0x%x,ANX7150_hdcp_bstatus[1]:0x%x\n", (u32)ANX7150_hdcp_bstatus[0],(u32)ANX7150_hdcp_bstatus[1]); + return 0;//HDCP topology error. More than 127 RX are attached or more than seven levels of repeater are cascaded. + } + return 1; +#endif +//wen HDCP CTS + +} + +static void anx7150_show_video_parameter(struct i2c_client *client) +{ + int rc = 0; + // int h_res,h_act,v_res,v_act,h_fp,hsync_width,h_bp; + char c, c1; + + hdmi_dbg(&client->dev, "\n\n**********************************ANX7150 Info**********************************\n"); + + hdmi_dbg(&client->dev, " ANX7150 mode = Normal mode\n"); + if ((ANX7150_demux_yc_en == 1) && (ANX7150_emb_sync_mode == 0)) + hdmi_dbg(&client->dev, " Input video format = YC_MUX\n"); + if ((ANX7150_demux_yc_en == 0) && (ANX7150_emb_sync_mode == 1)) + hdmi_dbg(&client->dev, " Input video format = 656\n"); + if ((ANX7150_demux_yc_en == 1) && (ANX7150_emb_sync_mode == 1)) + hdmi_dbg(&client->dev, " Input video format = YC_MUX + 656\n"); + if ((ANX7150_demux_yc_en == 0) && (ANX7150_emb_sync_mode == 0)) + hdmi_dbg(&client->dev, " Input video format = Seperate Sync\n"); + if (ANX7150_de_gen_en) + hdmi_dbg(&client->dev, " DE generator = Enable\n"); + else + hdmi_dbg(&client->dev, " DE generator = Disable\n"); + if ((ANX7150_ddr_bus_mode == 1)&& (ANX7150_emb_sync_mode == 0)) + hdmi_dbg(&client->dev, " Input video format = DDR mode\n"); + else if ((ANX7150_ddr_bus_mode == 1)&& (ANX7150_emb_sync_mode == 1)) + hdmi_dbg(&client->dev, " Input video format = DDR mode + 656\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c1); + c1 = (c1 & 0x02); + if (c1) + { + hdmi_dbg(&client->dev, " Output video mode = HDMI\n"); + rc = anx7150_i2c_read_p0_reg(client, 0x04, &c); + c = (c & 0x60) >> 5; + switch (c) + { + case ANX7150_RGB: + hdmi_dbg(&client->dev, " Output video color format = RGB\n"); + break; + case ANX7150_YCbCr422: + hdmi_dbg(&client->dev, " Output video color format = YCbCr422\n"); + break; + case ANX7150_YCbCr444: + hdmi_dbg(&client->dev, " Output video color format = YCbCr444\n"); + break; + default: + break; + } + } + else + { + hdmi_dbg(&client->dev, " Output video mode = DVI\n"); + hdmi_dbg(&client->dev, " Output video color format = RGB\n"); + } + + /*for(i = 0x10; i < 0x25; i ++) + { + ANX7150_i2c_read_p0_reg(i, &c ); + D("0x%.2x = 0x%.2x\n",(unsigned int)i,(unsigned int)c); + }*/ + /* ANX7150_i2c_read_p0_reg(ANX7150_VID_STATUS_REG, &c); + if((c & ANX7150_VID_STATUS_TYPE) == 0x04) + D("Video Type = Interlace"); + else + D("Video Type = Progressive"); + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HRESH_REG, &c); + h_res = c; + h_res = h_res << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HRESL_REG, &c); + h_res = h_res + c; + D("H_resolution = %u\n",h_res); + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_PIXH_REG, &c); + h_act = c; + h_act = h_act << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_PIXL_REG, &c); + h_act = h_act + c; + D("H_active = %u\n",h_act); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_VRESH_REG, &c); + v_res = c; + v_res = v_res << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_VRESL_REG, &c); + v_res = v_res + c; + D("V_resolution = %u\n",v_res); + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_ACTVIDLINEH_REG, &c); + v_act = c; + v_act = v_act << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_ACTVIDLINEL_REG, &c); + v_act = v_act + c; + D("V_active = %u\n",v_act); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HFORNTPORCHH_REG, &c); + h_fp = c; + h_fp = h_fp << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HFORNTPORCHL_REG, &c); + h_fp = h_fp + c; + D("H_FP = %u\n",h_fp); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HBACKPORCHH_REG, &c); + h_bp = c; + h_bp = h_bp << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HBACKPORCHL_REG, &c); + h_bp = h_bp + c; + D("H_BP = %u\n",h_bp); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HSYNCWIDH_REG, &c); + hsync_width = c; + hsync_width = hsync_width << 8; + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_HSYNCWIDL_REG, &c); + hsync_width = hsync_width + c; + D("Hsync_width = %u\n",hsync_width); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_ACTLINE2VSYNC_REG, &c); + D("Vsync_FP = %bu\n",c); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_VSYNCTAIL2VIDLINE_REG, &c); + D("Vsync_BP = %bu\n",c); + + ANX7150_i2c_read_p0_reg(ANX7150_VIDF_VSYNCWIDLINE_REG, &c); + D("Vsync_width = %bu\n",c);*/ + { + hdmi_dbg(&client->dev, " Normal mode output video format: \n"); + switch (ANX7150_video_timing_id) + { + case ANX7150_V720x480p_60Hz_4x3: + case ANX7150_V720x480p_60Hz_16x9: + hdmi_dbg(&client->dev, "720x480p@60\n"); + if (ANX7150_edid_result.supported_720x480p_60Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1280x720p_60Hz: + hdmi_dbg(&client->dev, "1280x720p@60\n"); + if (ANX7150_edid_result.supported_720p_60Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1920x1080i_60Hz: + hdmi_dbg(&client->dev, "1920x1080i@60\n"); + if (ANX7150_edid_result.supported_1080i_60Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1920x1080p_60Hz: + hdmi_dbg(&client->dev, "1920x1080p@60\n"); + if (ANX7150_edid_result.supported_1080p_60Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1920x1080p_50Hz: + hdmi_dbg(&client->dev, "1920x1080p@50\n"); + if (ANX7150_edid_result.supported_1080p_50Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1280x720p_50Hz: + hdmi_dbg(&client->dev, "1280x720p@50\n"); + if (ANX7150_edid_result.supported_720p_50Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V1920x1080i_50Hz: + hdmi_dbg(&client->dev, "1920x1080i@50\n"); + if (ANX7150_edid_result.supported_1080i_50Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V720x576p_50Hz_4x3: + case ANX7150_V720x576p_50Hz_16x9: + hdmi_dbg(&client->dev, "720x576p@50\n"); + if (ANX7150_edid_result.supported_576p_50Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V720x576i_50Hz_4x3: + case ANX7150_V720x576i_50Hz_16x9: + hdmi_dbg(&client->dev, "720x576i@50\n"); + if (ANX7150_edid_result.supported_576i_50Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + case ANX7150_V720x480i_60Hz_4x3: + case ANX7150_V720x480i_60Hz_16x9: + hdmi_dbg(&client->dev, "720x480i@60\n"); + if (ANX7150_edid_result.supported_720x480i_60Hz) + hdmi_dbg(&client->dev, "and sink supports this format.\n"); + else + hdmi_dbg(&client->dev, "but sink does not support this format.\n"); + break; + default: + hdmi_dbg(&client->dev, "unknown(video ID is: %.2x).\n",(u32)ANX7150_video_timing_id); + break; + } + } + if (c1)//HDMI output + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL0_REG, &c); + c = c & 0x03; + hdmi_dbg(&client->dev, " MCLK Frequence = "); + + switch (c) + { + case 0x00: + hdmi_dbg(&client->dev, "128 * Fs.\n"); + break; + case 0x01: + hdmi_dbg(&client->dev, "256 * Fs.\n"); + break; + case 0x02: + hdmi_dbg(&client->dev, "384 * Fs.\n"); + break; + case 0x03: + hdmi_dbg(&client->dev, "512 * Fs.\n"); + break; + default : + hdmi_dbg(&client->dev, "Wrong MCLK output.\n"); + break; + } + + if ( ANX7150_AUD_HW_INTERFACE == 0x01) + { + hdmi_dbg(&client->dev, " Input Audio Interface = I2S.\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + } + else if (ANX7150_AUD_HW_INTERFACE == 0x02) + { + hdmi_dbg(&client->dev, " Input Audio Interface = SPDIF.\n"); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SPDIFCH_STATUS_REG, &c); + c=c>>4; + } + rc = anx7150_i2c_read_p0_reg(client, ANX7150_I2SCH_STATUS4_REG, &c); + hdmi_dbg(&client->dev, " Audio Fs = "); + c &= 0x0f; + switch (c) + { + case 0x00: + hdmi_dbg(&client->dev, " Audio Fs = 44.1 KHz.\n"); + break; + case 0x02: + hdmi_dbg(&client->dev, " Audio Fs = 48 KHz.\n"); + break; + case 0x03: + hdmi_dbg(&client->dev, " Audio Fs = 32 KHz.\n"); + break; + case 0x08: + hdmi_dbg(&client->dev, " Audio Fs = 88.2 KHz.\n"); + break; + case 0x0a: + hdmi_dbg(&client->dev, " Audio Fs = 96 KHz.\n\n"); + break; + case 0x0c: + hdmi_dbg(&client->dev, " Audio Fs = 176.4 KHz.\n"); + break; + case 0x0e: + hdmi_dbg(&client->dev, " Audio Fs = 192 KHz.\n"); + hdmi_dbg(&client->dev, "192 KHz.\n"); + break; + default : + hdmi_dbg(&client->dev, " Audio Fs = Wrong Fs output.\n"); + hdmi_dbg(&client->dev, "Wrong Fs output.\n"); + break; + } + + if (ANX7150_HDCP_enable == 1) + hdmi_dbg(&client->dev, " ANX7150_HDCP_Enable.\n"); + else + hdmi_dbg(&client->dev, " ANX7150_HDCP_Disable.\n"); + + } + hdmi_dbg(&client->dev, "\n********************************************************************************\n\n"); +} +void ANX7150_HDCP_Process(struct i2c_client *client) +{ + int rc = 0; + char c,i; + //u8 c1; + u8 Bksv_valid=0;//wen HDCP CTS + + if (ANX7150_HDCP_enable) + { //HDCP_EN =1 means to do HDCP authentication,SWITCH4 = 0 means not to do HDCP authentication. + + //ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_SYS_CTRL1_REG, c | 0x04);//power on HDCP, 090630 + + //ANX7150_i2c_read_p0_reg(ANX7150_INTR2_MASK_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_INTR2_MASK_REG, c |0x03); + msleep(10);//let unencrypted video play a while, required by HDCP CTS. SY//wen HDCP CTS + anx7150_set_avmute(client);//before auth, set_avmute//wen + msleep(10);//wen HDCP CTS + + if ( !ANX7150_hdcp_init_done ) + { + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + c |= ANX7150_SYS_CTRL1_HDCPMODE; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); + if (ANX7150_edid_result.is_HDMI) + rc = anx7150_hardware_hdcp_auth_init(client); + else + { //DVI, disable 1.1 feature and enable HDCP two special point check + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + c = ((c & (~ANX7150_HDCP_CTRL1_HDCP11_EN)) | ANX7150_LINK_CHK_12_EN); + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL1_REG, &c); + } + + //wen HDCP CTS + if (!anx7150_bksv_srm(client)) + { + anx7150_blue_screen_enable(client); + anx7150_clear_avmute(client); + Bksv_valid=0; + return; + } + else //SY. + { + Bksv_valid=1; + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c |= 0x03; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + } + + ANX7150_hdcp_init_done = 1; +//wen HDCP CTS + } + + +//wen HDCP CTS + if ((Bksv_valid) && (!ANX7150_hdcp_auth_en)) + { + hdmi_dbg(&client->dev, "enable hw hdcp\n"); + anx7150_rst_ddcchannel(client); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c |= ANX7150_HDCP_CTRL0_HW_AUTHEN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + ANX7150_hdcp_auth_en = 1; + } + + if ((Bksv_valid) && (ANX7150_hdcp_wait_100ms_needed)) + { + ANX7150_hdcp_wait_100ms_needed = 0; + //disable audio + + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= ~ANX7150_HDMI_AUDCTRL1_IN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + hdmi_dbg(&client->dev, "++++++++ANX7150_hdcp_wait_100ms_needed+++++++++\n"); + msleep(150); // 100 -> 150 + return; + } +//wen HDCP CTS + + if (ANX7150_hdcp_auth_pass) //wen HDCP CTS + { + //Clear the SRM_Check_Pass u8, then when reauthentication occurs, firmware can catch it. + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= 0xfc; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + + //Enable HDCP Hardware encryption + if (!ANX7150_hdcp_encryption) + { + anx7150_hdcp_encryption_enable(client); + } + if (ANX7150_send_blue_screen) + { + anx7150_blue_screen_disable(client); + } + if (ANX7150_avmute_enable) + { + anx7150_clear_avmute(client); + } + + i = 0; + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_STATUS_REG, &c); + while((c&0x04)==0x00)//wait for encryption. + { + msleep(2); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_STATUS_REG, &c); + i++; + if (i > 10) + break; + } + + //enable audio SY. + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= ANX7150_HDMI_AUDCTRL1_IN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + hdmi_dbg(&client->dev, "@@@@@ HDCP Auth PASSED! @@@@@\n"); + + if (ANX7150_hdcp_bcaps & 0x40) //repeater + { + hdmi_dbg(&client->dev, "Find a repeater!\n"); + //actually it is KSVList check. we can't do SRM check due to the lack of SRM file. SY. + if (!ANX7150_srm_checked) + { + if (!anx7150_is_ksvlist_vld(client)) + { + hdmi_dbg(&client->dev, "ksvlist not good. disable encryption"); + anx7150_hdcp_encryption_disable(client); + anx7150_blue_screen_enable(client); + anx7150_clear_avmute(client); + ANX7150_ksv_srm_pass = 0; + anx7150_clean_hdcp(client);//SY. + //remove below will pass 1b-05/1b-06 + //ANX7150_Set_System_State(ANX7150_WAIT_HOTPLUG);//SY. + return; + } + ANX7150_srm_checked=1; + ANX7150_ksv_srm_pass = 1; + } + } + else + { + hdmi_dbg(&client->dev, "Find a receiver.\n"); + } + } + else //wen HDCP CTS + { + hdmi_dbg(&client->dev, "##### HDCP Auth FAILED! #####\n"); + //also need to disable HW AUTHEN + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + c &= ~ANX7150_HDCP_CTRL0_HW_AUTHEN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDCP_CTRL0_REG, &c); + ANX7150_hdcp_auth_en = 0; + //ANX7150_hdcp_init_done = 0; + //ANX7150_hdcp_wait_100ms_needed = 1; //wen, update 080703 + + if (ANX7150_hdcp_encryption) + { + anx7150_hdcp_encryption_disable(client); + } + if (!ANX7150_send_blue_screen) + { + anx7150_blue_screen_enable(client); + } + if (ANX7150_avmute_enable) + { + anx7150_clear_avmute(client); + } + //disable audio + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c &= ~ANX7150_HDMI_AUDCTRL1_IN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + + return; + } + + } + else //wen HDCP CTS + { + hdmi_dbg(&client->dev, "hdcp pin is off.\n"); + if (ANX7150_send_blue_screen) + { + anx7150_blue_screen_disable(client); + } + if (ANX7150_avmute_enable) + { + anx7150_clear_avmute(client); + } + //enable audio SY. + rc = anx7150_i2c_read_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + c |= ANX7150_HDMI_AUDCTRL1_IN_EN; + rc = anx7150_i2c_write_p0_reg(client, ANX7150_HDMI_AUDCTRL1_REG, &c); + } + +//wen HDCP CTS + rc = anx7150_i2c_read_p0_reg(client, ANX7150_SYS_CTRL1_REG, &c); //72:07.1 hdmi or dvi mode + c = c & 0x02; + if (c == 0x02) + { + hdmi_dbg(&client->dev, "end of ANX7150_HDCP_Process(): in HDMI mode.\n"); + } + else + { + hdmi_dbg(&client->dev, "!end of ANX7150_HDCP_Process(): in DVI mode.\n"); + //To-Do: Config to DVI mode. + } + + anx7150_show_video_parameter(client); +} + +void HDMI_Set_Video_Format(u8 video_format) //CPU set the lowpower mode +{ + switch (video_format) + { + case HDMI_1280x720p_50Hz: + g_video_format = ANX7150_V1280x720p_50Hz; + break; + case HDMI_1280x720p_60Hz: + g_video_format = ANX7150_V1280x720p_60Hz; + break; + case HDMI_720x576p_50Hz: + g_video_format = ANX7150_V720x576p_50Hz_4x3; + break; + default: + g_video_format = ANX7150_V1280x720p_50Hz; + break; + } +// ANX7150_system_config_done = 0; +} +void HDMI_Set_Audio_Fs( u8 audio_fs) //ANX7150 call this to check lowpower +{ + g_audio_format = audio_fs; +// ANX7150_system_config_done = 0; +} +int ANX7150_PLAYBACK_Process(void) +{ +// D("enter\n"); + + if ((s_ANX7150_packet_config.packets_need_config != 0x00) && (ANX7150_edid_result.is_HDMI == 1)) + { + return 1; + } + + return 0; +} + + diff --git a/drivers/video/hdmi/chips/anx7150_hw.h b/drivers/video/hdmi/chips/anx7150_hw.h new file mode 100755 index 000000000000..0654998a78b3 --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150_hw.h @@ -0,0 +1,1263 @@ +#ifndef _ANX7150_HW_H +#define _ANX7150_HW_H + +#include +extern u8 timer_slot,misc_reset_needed; +extern u8 bist_switch_value_pc,switch_value; +extern u8 switch_value_sw_backup,switch_value_pc_backup; +extern u8 ANX7150_system_state; +extern u8 ANX7150_srm_checked; +extern u8 ANX7150_HDCP_enable; +extern u8 ANX7150_INT_Done; +extern u8 FREQ_MCLK; +//extern u8 int_s1, int_s2, int_s3; +extern u8 HDMI_Mode_Auto_Manual,HDMI_Lowpower_Mode; + +struct anx7150_interrupt_s{ + int hotplug_change; + int video_format_change; + int auth_done; + int auth_state_change; + int pll_lock_change; + int rx_sense_change; + int HDCP_link_change; + int audio_clk_change; + int audio_FIFO_overrun; + int SPDIF_bi_phase_error; + int SPDIF_error; +}; +typedef struct +{ + u8 is_HDMI; + u8 ycbcr444_supported; + u8 ycbcr422_supported; + u8 supported_1080p_60Hz; + u8 supported_1080p_50Hz; + u8 supported_1080i_60Hz; + u8 supported_1080i_50Hz; + u8 supported_720p_60Hz; + u8 supported_720p_50Hz; + u8 supported_576p_50Hz; + u8 supported_576i_50Hz; + u8 supported_640x480p_60Hz; + u8 supported_720x480p_60Hz; + u8 supported_720x480i_60Hz; + u8 AudioFormat[10];//MAX audio STD block is 10(0x1f / 3) + u8 AudioChannel[10]; + u8 AudioFs[10]; + u8 AudioLength[10]; + u8 SpeakerFormat;u8 edid_errcode;}ANX7150_edid_result_4_system; + extern ANX7150_edid_result_4_system ANX7150_edid_result; +//#define ITU656 +//#ifdef ITU656 +struct ANX7150_video_timingtype{ //CEA-861C format + u8 ANX7150_640x480p_60Hz[18];//format 1 + u8 ANX7150_720x480p_60Hz[18];//format 2 & 3 + u8 ANX7150_1280x720p_60Hz[18];//format 4 + u8 ANX7150_1920x1080i_60Hz[18];//format 5 + u8 ANX7150_720x480i_60Hz[18];//format 6 & 7 + //u8 ANX7150_720x240p_60Hz[18];//format 8 & 9 + //u8 ANX7150_2880x480i_60Hz[18];//format 10 & 11 + //u8 ANX7150_2880x240p_60Hz[18];//format 12 & 13 + //u8 ANX7150_1440x480p_60Hz[18];//format 14 & 15 + //u8 ANX7150_1920x1080p_60Hz[18];//format 16 + u8 ANX7150_720x576p_50Hz[18];//format 17 & 18 + u8 ANX7150_1280x720p_50Hz[18];//format 19 + u8 ANX7150_1920x1080i_50Hz[18];//format 20*/ + u8 ANX7150_720x576i_50Hz[18];//format 21 & 22 + /* u8 ANX7150_720x288p_50Hz[18];//formats 23 & 24 + u8 ANX7150_2880x576i_50Hz[18];//formats 25 & 26 + u8 ANX7150_2880x288p_50Hz[18];//formats 27 & 28 + u8 ANX7150_1440x576p_50Hz[18];//formats 29 & 30 + u8 ANX7150_1920x1080p_50Hz[18];//format 31 + u8 ANX7150_1920x1080p_24Hz[18];//format 32 + u8 ANX7150_1920x1080p_25Hz[18];//format 33 + u8 ANX7150_1920x1080p_30Hz[18];//format 34*/ +}; +//#endif +// 8 type of packets are legal, It is possible to sent 6 types in the same time; +// So select 6 types below at most; +// avi_infoframe and audio_infoframe have fixxed address; +// config other selected types of packet to the rest 4 address with no limits. +typedef enum +{ + ANX7150_avi_infoframe, + ANX7150_audio_infoframe, + /*ANX7150_spd_infoframe, + ANX7150_mpeg_infoframe, + ANX7150_acp_packet, + ANX7150_isrc1_packet, + ANX7150_isrc2_packet, + ANX7150_vendor_infoframe,*/ +}packet_type; + +typedef struct +{ + u8 type; + u8 version; + u8 length; + u8 pb_u8[28]; +}infoframe_struct; + +typedef struct +{ + u8 packets_need_config; //which infoframe packet is need updated + infoframe_struct avi_info; + infoframe_struct audio_info; + /* for the funture use + infoframe_struct spd_info; + infoframe_struct mpeg_info; + infoframe_struct acp_pkt; + infoframe_struct isrc1_pkt; + infoframe_struct isrc2_pkt; + infoframe_struct vendor_info; */ + +} config_packets; +/* + u8 i2s_format; + + u8(s) Name Type Default Description + 7 EXT_VUCP R/W 0x0 + Enable indicator of VUCP u8s extraction from input + I2S audio stream. 0 = disable; 1 = enable. + 6:5 MCLK_PHS_CTRL R/W 0x0 + MCLK phase control for audio SPDIF input, which value + is depended on the value of MCLK frequency set and not great than it. + 4 Reserved + 3 SHIFT_CTRL R/W 0x0 + WS to SD shift first u8. 0 = fist u8 shift (Philips Spec); 1 = no shift. + 2 DIR_CTRL R/W 0x0 + SD data Indian (MSB or LSB first) control. 0 = MSB first; 1 = LSB first. + 1 WS_POL R/W 0x0 + Word select left/right polarity select. 0 = left polarity + when works select is low; 1 = left polarity when word select is high. + 0 JUST_CTRL R/W 0x0 + SD Justification control. 1 = data is right justified; + 0 = data is left justified. + +*/ +/* + u8 audio_channel +u8(s) Name Type Default Description +5 AUD_SD3_IN R/W 0x0 Set I2S input channel #3 enable. 0 = disable; 1 = enable. +4 AUD_SD2_IN R/W 0x0 Set I2S input channel #2 enable. 0 = disable; 1 = enable. +3 AUD_SD1_IN R/W 0x0 Set I2S input channel #1 enable. 0 = disable; 1 = enable. +2 AUD_SD0_IN R/W 0x0 Set I2S input channel #0 enable. 0 = disable; 1 = enable. + + +*/ +/* + u8 i2s_map0 +u8(s) Name Type Default Description +7:6 FIFO3_SEL R/W 0x3 I2S Channel data stream select for audio FIFO 3. 0 = SD 0; 1 = SD 1; 2 = SD 2; 3 = SD 3; +5:4 FIFO2_SEL R/W 0x2 I2S Channel data stream select for audio FIFO 2. 0 = SD 0; 1 = SD 1; 2 = SD 2; 3 = SD 3; +3:2 FIFO1_SEL R/W 0x1 I2S Channel data stream select for audio FIFO 1. 0 = SD 0; 1 = SD 1; 2 = SD 2; 3 = SD 3; +1:0 FIFO0_SEL R/W 0x0 I2S Channel data stream select for audio FIFO 0. 0 = SD 0; 1 = SD 1; 2 = SD 2; 3 = SD 3; + + u8 i2s_map1 +u8(s) Name Type Default Description +7 SW3 R/W 0x0 Swap left/right channel on I2S channel 3. 1 = swap; 0 = no swap. +6 SW2 R/W 0x0 Swap left/right channel on I2S channel 2. 1 = swap; 0 = no swap. +5 SW1 R/W 0x0 Swap left/right channel on I2S channel 1. 1 = swap; 0 = no swap. +4 SW0 R/W 0x0 Swap left/right channel on I2S channel 0. 1 = swap; 0 = no swap. +3:1 IN_WORD_LEN R/W 0x5 Input I2S audio word length (corresponding to channel status u8s [35:33]). When IN_WORD_MAX = 0, 001 = 16 u8s; 010 = 18 u8s; 100 = 19 u8s; 101 = 20 u8s; 110 = 17 u8s; when IN_WORD_MAX = 1, 001 = 20 u8s; 010 = 22 u8s; 100 = 23 u8s; 101 = 24 u8s; 110 = 21 u8s. +0 IN_WORD_MAX R/W 0x1 Input I2S audio word length Max (corresponding to channel status u8s 32). 0 = maximal word length is 20 u8s; 1 = maximal word length is 24 u8s. +*/ +/* + u8 Channel_status1 +u8(s) Name Type Default Description +7:6 MODE R/W 0x0 00 = PCM Audio +5:3 PCM_MODE R/W 0x0 000 = 2 audio channels without pre-emphasis; + 001 = 2 audio channels with 50/15 usec pre-emphasis +2 SW_CPRGT R/W 0x0 0 = software for which copyright is asserted; + 1 = software for which no copyright is asserted +1 NON_PCM R/W 0x0 0 = audio sample word represents linear PCM samples; + 1 = audio sample word used for other purposes. +0 PROF_APP R/W 0x0 0 = consumer applications; 1 = professional applications. + + u8 Channel_status2 +u8(s) Name Type Default Description +7:0 CAT_CODE R/W 0x0 Category code (corresponding to channel status u8s [15:8]) + + u8 Channel_status3 +u8(s) Name Type Default Description +7:4 CH_NUM R/W 0x0 Channel number (corresponding to channel status u8s [23:20]) +3:0 SOURCE_NUM R/W 0x0 Source number (corresponding to channel status u8s [19:16]) + + u8 Channel_status4 +u8(s) Name Type Default Description +7:6 CHNL_u81 R/W 0x0 corresponding to channels status u8s [31:30] +5:4 CLK_ACCUR R/W 0x0 Clock accuracy (corresponding to channels status u8s [29:28]). These two u8s define the sampling frequency tolerance. The u8s are set in the transmitter. +3:0 FS_FREQ R/W 0x0 Sampling clock frequency (corresponding to channel status u8s [27:24]). 0000 = 44.1 KHz; 0010 = 48 KHz; 0011 = 32 KHz; 1000 = 88.2 KHz; 1010 = 96 KHz; 176.4 KHz; 1110 = 192 KHz; others = reserved. + + u8 Channel_status5 +u8(s) Name Type Default Description +7:4 CHNL_u82 R/W 0x0 corresponding to channels status u8s [39:36] +3:1 WORD_LENGTH R/W 0x5 Audio word length (corresponding to channel status u8s [35:33]). When WORD_MAX = 0, 001 = 16 u8s; 010 = 18 u8s; 100 = 19 u8s; 101 = 20 u8s; 110 = 17 u8s; when WORD_MAX = 1, 001 = 20 u8s; 010 = 22 u8s; 100 = 23 u8s; 101 = 24 u8s; 110 = 21 u8s. +0 WORD_MAX R/W 0x1 Audio word length Max (corresponding to channel status u8s 32). 0 = maximal word length is 20 u8s; 1 = maximal word length is 24 u8s. + +*/ +typedef struct +{ + u8 audio_channel; + u8 i2s_format; + u8 i2s_swap; + u8 Channel_status1; + u8 Channel_status2; + u8 Channel_status3; + u8 Channel_status4; + u8 Channel_status5; +} i2s_config_struct; +/* + u8 FS_FREQ; + + 7:4 FS_FREQ R 0x0 + Sampling clock frequency (corresponding to channel status u8s [27:24]). + 0000 = 44.1 KHz; 0010 = 48 KHz; 0011 = 32 KHz; 1000 = 88.2 KHz; 1010 = 96 KHz; + 176.4 KHz; 1110 = 192 KHz; others = reserved. +*/ + +typedef struct +{ + u8 one_u8_ctrl; + +} super_audio_config_struct; + +typedef struct +{ + u8 audio_type; // audio type + // #define ANX7150_i2s_input 0x01 + // #define ANX7150_spdif_input 0x02 + // #define ANX7150_super_audio_input 0x04 + + u8 down_sample; // 0x72:0x50 + // 0x00: 00 no down sample + // 0x20: 01 2 to 1 down sample + // 0x60: 11 4 to 1 down sample + // 0x40: 10 reserved + u8 audio_layout;//audio layout; + //0x00, 2-channel + //0x80, 8-channel + + i2s_config_struct i2s_config; + super_audio_config_struct super_audio_config; + +} audio_config_struct; + +/*added by gerard.zhu*/ +/*DDC type*/ +typedef enum { + DDC_Hdcp, + DDC_Edid, +}ANX7150_DDC_Type; + +/*Read DDC status type*/ +typedef enum { + report, + Judge, +}ANX7150_DDC_Status_Check_Type; + +/*Define DDC address struction*/ +typedef struct { + u8 dev_addr; + u8 sgmt_addr; + u8 offset_addr; +}ANX7150_DDC_Addr; + +/*DDC status u8*/ +#define DDC_Error_u8 0x07 +#define DDC_Occup_u8 0x06 +#define DDC_Fifo_Full_u8 0x05 +#define DDC_Fifo_Empt_u8 0x04 +#define DDC_No_Ack_u8 0x03 +#define DDC_Fifo_Rd_u8 0x02 +#define DDC_Fifo_Wr_u8 0x01 +#define DDC_Progress_u8 0x00 + +#define YCbCr422 0x20 +#define null 0 +#define source_ratio 0x08 + +/*DDC Command*/ +#define Abort_Current_Operation 0x00 +#define Sequential_u8_Read 0x01 +#define Sequential_u8_Write 0x02 +#define Implicit_Offset_Address_Read 0x3 +#define Enhanced_DDC_Sequenital_Read 0x04 +#define Clear_DDC_Fifo 0x05 +#define I2c_reset 0x06 + +/*DDC result*/ +#define DDC_NO_Err 0x00 +#define DDC_Status_Err 0x01 +#define DDC_Data_Addr_Err 0x02 +#define DDC_Length_Err 0x03 + +/*checksum result*/ +#define Edid_Checksum_No_Err 0x00 +#define Edid_Checksum_Err 0x01 + +/*HDCP device base address*/ +#define HDCP_Dev_Addr 0x74 + +/*HDCP Bksv offset*/ +#define HDCP_Bksv_Offset 0x00 + +/*HDCP Bcaps offset*/ +#define HDCP_Bcaps_Offset 0x40 + +/*HDCP Bstatus offset*/ +#define HDCP_Bstatus_offset 0x41 + +/*HDCP KSV Fifo offset */ +#define HDCP_Ksv_Fifo_Offset 0x43 + +/*HDCP bksv data nums*/ +#define Bksv_Data_Nums 5 + +/*HDCP ksvs data number by defult*/ +#define ksvs_data_nums 50 + +/*DDC Max u8s*/ +#define DDC_Max_Length 1024 + +/*DDC fifo depth*/ +#define DDC_Fifo_Depth 16 + +/*DDC read delay ms*/ +#define DDC_Read_Delay 3 + +/*DDC Write delay ms*/ +#define DDC_Write_Delay 3 +/*end*/ + +extern u8 ANX7150_parse_edid_done; +extern u8 ANX7150_system_config_done; +extern u8 ANX7150_video_format_config,ANX7150_video_timing_id; +extern u8 ANX7150_new_csc,ANX7150_new_vid_id,ANX7150_new_HW_interface; +extern u8 ANX7150_ddr_edge; +extern u8 ANX7150_in_pix_rpt_bkp,ANX7150_tx_pix_rpt_bkp; +extern u8 ANX7150_in_pix_rpt,ANX7150_tx_pix_rpt; +extern u8 ANX7150_pix_rpt_set_by_sys; +extern u8 ANX7150_RGBorYCbCr; +extern audio_config_struct s_ANX7150_audio_config; +extern config_packets s_ANX7150_packet_config; + +//********************** BIST Enable*********************************** + + +#define ddr_falling_edge 1 +#define ddr_rising_edge 0 + +#define input_pixel_clk_1x_repeatition 0x00 +#define input_pixel_clk_2x_repeatition 0x01 +#define input_pixel_clk_4x_repeatition 0x03 + +//***********************Video Config*********************************** +#define ANX7150_RGB_YCrCb444_SepSync 0 +#define ANX7150_YCrCb422_SepSync 1 +#define ANX7150_YCrCb422_EmbSync 2 +#define ANX7150_YCMux422_SepSync_Mode1 3 +#define ANX7150_YCMux422_SepSync_Mode2 4 +#define ANX7150_YCMux422_EmbSync_Mode1 5 +#define ANX7150_YCMux422_EmbSync_Mode2 6 +#define ANX7150_RGB_YCrCb444_DDR_SepSync 7 +#define ANX7150_RGB_YCrCb444_DDR_EmbSync 8 + +#define ANX7150_RGB_YCrCb444_SepSync_No_DE 9 +#define ANX7150_YCrCb422_SepSync_No_DE 10 + +#define ANX7150_Progressive 0 +#define ANX7150_Interlace 0x08 +#define ANX7150_Neg_Hsync_pol 0x20 +#define ANX7150_Pos_Hsync_pol 0 +#define ANX7150_Neg_Vsync_pol 0x40 +#define ANX7150_Pos_Vsync_pol 0 + +#define ANX7150_V640x480p_60Hz 1 +#define ANX7150_V720x480p_60Hz_4x3 2 +#define ANX7150_V720x480p_60Hz_16x9 3 +#define ANX7150_V1280x720p_60Hz 4 +#define ANX7150_V1280x720p_50Hz 19 +#define ANX7150_V1920x1080i_60Hz 5 +#define ANX7150_V1920x1080p_60Hz 16 +#define ANX7150_V1920x1080p_50Hz 31 +#define ANX7150_V1920x1080i_50Hz 20 +#define ANX7150_V720x480i_60Hz_4x3 6 +#define ANX7150_V720x480i_60Hz_16x9 7 +#define ANX7150_V720x576i_50Hz_4x3 21 +#define ANX7150_V720x576i_50Hz_16x9 22 +#define ANX7150_V720x576p_50Hz_4x3 17 +#define ANX7150_V720x576p_50Hz_16x9 18 + +#define ANX7150_RGB 0x00 +#define ANX7150_YCbCr422 0x01 +#define ANX7150_YCbCr444 0x02 +#define ANX7150_CSC_BT709 1 +#define ANX7150_CSC_BT601 0 + +#define ANX7150_EMBEDED_BLUE_SCREEN_ENABLE 1 +#define ANX7150_HDCP_FAIL_THRESHOLD 10 + +#define ANX7150_avi_sel 0x01 +#define ANX7150_audio_sel 0x02 +#define ANX7150_spd_sel 0x04 +#define ANX7150_mpeg_sel 0x08 +#define ANX7150_acp_sel 0x10 +#define ANX7150_isrc1_sel 0x20 +#define ANX7150_isrc2_sel 0x40 +#define ANX7150_vendor_sel 0x80 + +// audio type +#define ANX7150_i2s_input 0x01 +#define ANX7150_spdif_input 0x02 +#define ANX7150_super_audio_input 0x04 +// freq_mclk +#define ANX7150_mclk_128_Fs 0x00 +#define ANX7150_mclk_256_Fs 0x01 +#define ANX7150_mclk_384_Fs 0x02 +#define ANX7150_mclk_512_Fs 0x03 +// thresholds +#define ANX7150_spdif_stable_th 0x03 +// fs -> N(ACR) +#define ANX7150_N_32k 0x1000 +#define ANX7150_N_44k 0x1880 +#define ANX7150_N_88k 0x3100 +#define ANX7150_N_176k 0x6200 +#define ANX7150_N_48k 0x1800 +#define ANX7150_N_96k 0x3000 +#define ANX7150_N_192k 0x6000 + +#define spdif_error_th 0x0a + +#define Hresolution_1920 1920 +#define Vresolution_540 540 +#define Vresolution_1080 1080 +#define Hresolution_1280 1280 +#define Vresolution_720 720 +#define Hresolution_640 640 +#define Vresolution_480 480 +#define Hresolution_720 720 +#define Vresolution_240 240 +#define Vresolution_576 576 +#define Vresolution_288 288 +#define Hz_50 50 +#define Hz_60 60 +#define Interlace_EDID 0 +#define Progressive_EDID 1 +#define ratio_16_9 1.777778 +#define ratio_4_3 1.333333 + +#define ANX7150_EDID_BadHeader 0x01 +#define ANX7150_EDID_861B_not_supported 0x02 +#define ANX7150_EDID_CheckSum_ERR 0x03 +#define ANX7150_EDID_No_ExtBlock 0x04 +#define ANX7150_EDID_ExtBlock_NotFor_861B 0x05 + +#define ANX7150_VND_IDL_REG 0x00 +#define ANX7150_VND_IDH_REG 0x01 +#define ANX7150_DEV_IDL_REG 0x02 +#define ANX7150_DEV_IDH_REG 0x03 +#define ANX7150_DEV_REV_REG 0x04 + +#define ANX7150_SRST_REG 0x05 +#define ANX7150_TX_RST 0x40 +#define ANX7150_SRST_VIDCAP_RST 0x20 // u8 position +#define ANX7150_SRST_AFIFO_RST 0x10 // u8 position +#define ANX7150_SRST_HDCP_RST 0x08 // u8 position +#define ANX7150_SRST_VID_FIFO_RST 0x04 // u8 position +#define ANX7150_SRST_AUD_RST 0x02 // u8 position +#define ANX7150_SRST_SW_RST 0x01 // u8 position + +#define ANX7150_SYS_STATE_REG 0x06 +#define ANX7150_SYS_STATE_AUD_CLK_DET 0x20 // u8 position +#define ANX7150_SYS_STATE_AVMUTE 0x10 // u8 position +#define ANX7150_SYS_STATE_HP 0x08 // u8 position +#define ANX7150_SYS_STATE_VSYNC 0x04 // u8 position +#define ANX7150_SYS_STATE_CLK_DET 0x02 // u8 position +#define ANX7150_SYS_STATE_RSV_DET 0x01 // u8 position + +#define ANX7150_SYS_CTRL1_REG 0x07 +#define ANX7150_SYS_CTRL1_LINKMUTE_EN 0x80 // u8 position +#define ANX7150_SYS_CTRL1_HDCPHPD_RST 0x40 // u8 position +#define ANX7150_SYS_CTRL1_PDINT_SEL 0x20 // u8 position +#define ANX7150_SYS_CTRL1_DDC_FAST 0x10 // u8 position +#define ANX7150_SYS_CTRL1_DDC_SWCTRL 0x08 // u8 position +#define ANX7150_SYS_CTRL1_HDCPMODE 0x04 // u8 position +#define ANX7150_SYS_CTRL1_HDMI 0x02 // u8 position +#define ANX7150_SYS_CTRL1_PWDN_CTRL 0x01 // u8 position + +#define ANX7150_SYS_CTRL2_REG 0x08 +#define ANX7150_SYS_CTRL2_DDC_RST 0x08 // u8 position +#define ANX7150_SYS_CTRL2_TMDSBIST_RST 0x04 // u8 position +#define ANX7150_SYS_CTRL2_MISC_RST 0x02 // u8 position +#define ANX7150_SYS_CTRL2_HW_RST 0x01 // u8 position + +#define ANX7150_SYS_CTRL3_REG 0x09 +#define ANX7150_SYS_CTRL3_I2C_PWON 0x02 +#define ANX7150_SYS_CTRL3_PWON_ALL 0x01 + +#define ANX7150_SYS_CTRL4_REG 0x0b + +#define ANX7150_VID_STATUS_REG 0x10 +#define ANX7150_VID_STATUS_VID_STABLE 0x20 // u8 position +#define ANX7150_VID_STATUS_EMSYNC_ERR 0x10 // u8 position +#define ANX7150_VID_STATUS_FLD_POL 0x08 // u8 position +#define ANX7150_VID_STATUS_TYPE 0x04 // u8 position +#define ANX7150_VID_STATUS_VSYNC_POL 0x02 // u8 position +#define ANX7150_VID_STATUS_HSYNC_POL 0x01 // u8 position + +#define ANX7150_VID_MODE_REG 0x11 +#define ANX7150_VID_MODE_CHKSHARED_EN 0x80 // u8 position +#define ANX7150_VID_MODE_LINKVID_EN 0x40 // u8 position +#define ANX7150_VID_MODE_RANGE_Y2R 0x20 // u8 position +#define ANX7150_VID_MODE_CSPACE_Y2R 0x10 // u8 position +#define ANX7150_VID_MODE_Y2R_SEL 0x08 // u8 position +#define ANX7150_VID_MODE_UPSAMPLE 0x04 // u8 position + +#define ANX7150_VID_CTRL_REG 0x12 +#define ANX7150_VID_CTRL_IN_EN 0x10 // u8 position +#define ANX7150_VID_CTRL_YCu8_SEL 0x08 // u8 position +#define ANX7150_VID_CTRL_u8CTRL_EN 0x04 // u8 position + +#define ANX7150_VID_CAPCTRL0_REG 0x13 +#define ANX7150_VID_CAPCTRL0_DEGEN_EN 0x80 // u8 position +#define ANX7150_VID_CAPCTRL0_EMSYNC_EN 0x40 // u8 position +#define ANX7150_VID_CAPCTRL0_DEMUX_EN 0x20 // u8 position +#define ANX7150_VID_CAPCTRL0_INV_IDCK 0x10 // u8 position +#define ANX7150_VID_CAPCTRL0_DV_BUSMODE 0x08 // u8 position +#define ANX7150_VID_CAPCTRL0_DDR_EDGE 0x04 // u8 position +#define ANX7150_VID_CAPCTRL0_VIDu8_SWAP 0x02 // u8 position +#define ANX7150_VID_CAPCTRL0_VIDBIST_EN 0x01 // u8 position + +#define ANX7150_VID_CAPCTRL1_REG 0x14 +#define ANX7150_VID_CAPCTRL1_FORMAT_SEL 0x80 // u8 position +#define ANX7150_VID_CAPCTRL1_VSYNC_POL 0x40 // u8 position +#define ANX7150_VID_CAPCTRL1_HSYNC_POL 0x20 // u8 position +#define ANX7150_VID_CAPCTRL1_INV_FLDPOL 0x10 // u8 position +#define ANX7150_VID_CAPCTRL1_VID_TYPE 0x08 // u8 position + +#define ANX7150_H_RESL_REG 0x15 +#define ANX7150_H_RESH_REG 0x16 +#define ANX7150_VID_PIXL_REG 0x17 +#define ANX7150_VID_PIXH_REG 0x18 +#define ANX7150_H_FRONTPORCHL_REG 0x19 +#define ANX7150_H_FRONTPORCHH_REG 0x1A +#define ANX7150_HSYNC_ACT_WIDTHL_REG 0x1B +#define ANX7150_HSYNC_ACT_WIDTHH_REG 0x1C +#define ANX7150_H_BACKPORCHL_REG 0x1D +#define ANX7150_H_BACKPORCHH_REG 0x1E +#define ANX7150_V_RESL_REG 0x1F +#define ANX7150_V_RESH_REG 0x20 +#define ANX7150_ACT_LINEL_REG 0x21 +#define ANX7150_ACT_LINEH_REG 0x22 +#define ANX7150_ACT_LINE2VSYNC_REG 0x23 +#define ANX7150_VSYNC_WID_REG 0x24 +#define ANX7150_VSYNC_TAIL2VIDLINE_REG 0x25 +#define ANX7150_VIDF_HRESL_REG 0x26 +#define ANX7150_VIDF_HRESH_REG 0x27 +#define ANX7150_VIDF_PIXL_REG 0x28 +#define ANX7150_VIDF_PIXH_REG 0x29 +#define ANX7150_VIDF_HFORNTPORCHL_REG 0x2A +#define ANX7150_VIDF_HFORNTPORCHH_REG 0x2B +#define ANX7150_VIDF_HSYNCWIDL_REG 0x2C +#define ANX7150_VIDF_HSYNCWIDH_REG 0x2D +#define ANX7150_VIDF_HBACKPORCHL_REG 0x2E +#define ANX7150_VIDF_HBACKPORCHH_REG 0x2F +#define ANX7150_VIDF_VRESL_REG 0x30 +#define ANX7150_VIDF_VRESH_REG 0x31 +#define ANX7150_VIDF_ACTVIDLINEL_REG 0x32 +#define ANX7150_VIDF_ACTVIDLINEH_REG 0x33 +#define ANX7150_VIDF_ACTLINE2VSYNC_REG 0x34 +#define ANX7150_VIDF_VSYNCWIDLINE_REG 0x35 +#define ANX7150_VIDF_VSYNCTAIL2VIDLINE_REG 0x36 + +//Video input data u8 control registers + +#define VID_u8_CTRL0 0x37 //added +#define VID_u8_CTRL1 0x38 +#define VID_u8_CTRL2 0x39 +#define VID_u8_CTRL3 0x3A +#define VID_u8_CTRL4 0x3B +#define VID_u8_CTRL5 0x3C +#define VID_u8_CTRL6 0x3D +#define VID_u8_CTRL7 0x3E +#define VID_u8_CTRL8 0x3F +#define VID_u8_CTRL9 0x48 +#define VID_u8_CTRL10 0x49 +#define VID_u8_CTRL11 0x4A +#define VID_u8_CTRL12 0x4B +#define VID_u8_CTRL13 0x4C +#define VID_u8_CTRL14 0x4D +#define VID_u8_CTRL15 0x4E +#define VID_u8_CTRL16 0x4F +#define VID_u8_CTRL17 0x89 +#define VID_u8_CTRL18 0x8A +#define VID_u8_CTRL19 0x8B +#define VID_u8_CTRL20 0x8C +#define VID_u8_CTRL21 0x8D +#define VID_u8_CTRL22 0x8E +#define VID_u8_CTRL23 0x8F + + +#define ANX7150_INTR_STATE_REG 0x40 + +#define ANX7150_INTR_CTRL_REG 0x41 + +#define ANX7150_INTR_CTRL_SOFT_INTR 0x04 // u8 position +#define ANX7150_INTR_CTRL_TYPE 0x02 // u8 position +#define ANX7150_INTR_CTRL_POL 0x01 // u8 position + +#define ANX7150_INTR1_STATUS_REG 0x42 +#define ANX7150_INTR1_STATUS_CTS_CHG 0x80 // u8 position +#define ANX7150_INTR1_STATUS_AFIFO_UNDER 0x40 // u8 position +#define ANX7150_INTR1_STATUS_AFIFO_OVER 0x20 // u8 position +#define ANX7150_INTR1_STATUS_SPDIF_ERR 0x10 // u8 position +#define ANX7150_INTR1_STATUS_SW_INT 0x08 // u8 position +#define ANX7150_INTR1_STATUS_HP_CHG 0x04 // u8 position +#define ANX7150_INTR1_STATUS_CTS_OVRWR 0x02 // u8 position +#define ANX7150_INTR1_STATUS_CLK_CHG 0x01 // u8 position + +#define ANX7150_INTR2_STATUS_REG 0x43 +#define ANX7150_INTR2_STATUS_ENCEN_CHG 0x80 // u8 position +#define ANX7150_INTR2_STATUS_HDCPLINK_CHK 0x40 // u8 position +#define ANX7150_INTR2_STATUS_HDCPENHC_CHK 0x20 // u8 position +#define ANX7150_INTR2_STATUS_BKSV_RDY 0x10 // u8 position +#define ANX7150_INTR2_STATUS_PLLLOCK_CHG 0x08 // u8 position +#define ANX7150_INTR2_STATUS_SHA_DONE 0x04 // u8 position +#define ANX7150_INTR2_STATUS_AUTH_CHG 0x02 // u8 position +#define ANX7150_INTR2_STATUS_AUTH_DONE 0x01 // u8 position + +#define ANX7150_INTR3_STATUS_REG 0x44 +#define ANX7150_INTR3_STATUS_SPDIFBI_ERR 0x80 // u8 position +#define ANX7150_INTR3_STATUS_VIDF_CHG 0x40 // u8 position +#define ANX7150_INTR3_STATUS_AUDCLK_CHG 0x20 // u8 position +#define ANX7150_INTR3_STATUS_DDCACC_ERR 0x10 // u8 position +#define ANX7150_INTR3_STATUS_DDC_NOACK 0x08 // u8 position +#define ANX7150_INTR3_STATUS_VSYNC_DET 0x04 // u8 position +#define ANX7150_INTR3_STATUS_RXSEN_CHG 0x02 // u8 position +#define ANX7150_INTR3_STATUS_SPDIF_UNSTBL 0x01 // u8 position + +#define ANX7150_INTR1_MASK_REG 0x45 +#define ANX7150_INTR2_MASK_REG 0x46 +#define ANX7150_INTR3_MASK_REG 0x47 + +#define ANX7150_HDMI_AUDCTRL0_REG 0x50 +#define ANX7150_HDMI_AUDCTRL0_LAYOUT 0x80 // u8 position +#define ANX7150_HDMI_AUDCTRL0_DOWN_SMPL 0x60 // u8 position +#define ANX7150_HDMI_AUDCTRL0_CTSGEN_SC 0x10 // u8 position +#define ANX7150_HDMI_AUDCTRL0_INV_AUDCLK 0x08 // u8 position + +#define ANX7150_HDMI_AUDCTRL1_REG 0x51 +#define ANX7150_HDMI_AUDCTRL1_IN_EN 0x80 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SPDIFIN_EN 0x40 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SD3IN_EN 0x20 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SD2IN_EN 0x10 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SD1IN_EN 0x08 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SD0IN_EN 0x04 // u8 position +#define ANX7150_HDMI_AUDCTRL1_SPDIFFS_OVRWR 0x02 // u8 position +#define ANX7150_HDMI_AUDCTRL1_CLK_SEL 0x01 // u8 position + +#define ANX7150_I2S_CTRL_REG 0x52 +#define ANX7150_I2S_CTRL_VUCP 0x80 // u8 position +#define SPDIF_IN_SEL 0x10 //0-spdif, 1-multi with sd0 +#define ANX7150_I2S_CTRL_SHIFT_CTRL 0x08 // u8 position +#define ANX7150_I2S_CTRL_DIR_CTRL 0x04 // u8 position +#define ANX7150_I2S_CTRL_WS_POL 0x02 // u8 position +#define ANX7150_I2S_CTRL_JUST_CTRL 0x01 // u8 position + +#define ANX7150_I2SCH_CTRL_REG 0x53 +#define ANX7150_I2SCH_FIFO3_SEL 0xC0 // u8 position +#define ANX7150_I2SCH_FIFO2_SEL 0x30 // u8 position +#define ANX7150_I2SCH_FIFO1_SEL 0x0C // u8 position +#define ANX7150_I2SCH_FIFO0_SEL 0x03 // u8 position + +#define ANX7150_I2SCH_SWCTRL_REG 0x54 + +#define ANX7150_I2SCH_SWCTRL_SW3 0x80 // u8 position +#define ANX7150_I2SCH_SWCTRL_SW2 0x40 // u8 position +#define ANX7150_I2SCH_SWCTRL_SW1 0x20 // u8 position +#define ANX7150_I2SCH_SWCTRL_SW0 0x10 // u8 position +#define ANX7150_I2SCH_SWCTRL_INWD_LEN 0xE0 // u8 position +#define ANX7150_I2SCH_SWCTRL_INWD_MAX 0x01 // u8 position + +#define ANX7150_SPDIFCH_STATUS_REG 0x55 +#define ANX7150_SPDIFCH_STATUS_FS_FREG 0xF0 // u8 position +#define ANX7150_SPDIFCH_STATUS_WD_LEN 0x0E // u8 position +#define ANX7150_SPDIFCH_STATUS_WD_MX 0x01 // u8 position + +#define ANX7150_I2SCH_STATUS1_REG 0x56 +#define ANX7150_I2SCH_STATUS1_MODE 0xC0 // u8 position +#define ANX7150_I2SCH_STATUS1_PCM_MODE 0x38 // u8 position +#define ANX7150_I2SCH_STATUS1_SW_CPRGT 0x04 // u8 position +#define ANX7150_I2SCH_STATUS1_NON_PCM 0x02 // u8 position +#define ANX7150_I2SCH_STATUS1_PROF_APP 0x01 // u8 position + +#define ANX7150_I2SCH_STATUS2_REG 0x57 + +#define ANX7150_I2SCH_STATUS3_REG 0x58 +#define ANX7150_I2SCH_STATUS3_CH_NUM 0xF0 // u8 position +#define ANX7150_I2SCH_STATUS3_SRC_NUM 0x0F // u8 position + + + +#define ANX7150_I2SCH_STATUS4_REG 0x59 + +#define ANX7150_I2SCH_STATUS5_REG 0x5A + +#define ANX7150_I2SCH_STATUS5_WORD_MAX 0x01 // u8 position + +#define ANX7150_HDMI_AUDSTATUS_REG 0x5B + +#define ANX7150_HDMI_AUDSTATUS_SPDIF_DET 0x01 // u8 position + +#define ANX7150_HDMI_AUDBIST_CTRL_REG 0x5C + +#define ANX7150_HDMI_AUDBIST_EN3 0x08 // u8 position +#define ANX7150_HDMI_AUDBIST_EN2 0x04 // u8 position +#define ANX7150_HDMI_AUDBIST_EN1 0x02 // u8 position +#define ANX7150_HDMI_AUDBIST_EN0 0x01 // u8 position + +#define ANX7150_AUD_INCLK_CNT_REG 0x5D +#define ANX7150_AUD_DEBUG_STATUS_REG 0x5E + +#define ANX7150_ONEu8_AUD_CTRL_REG 0x60 + +#define ANX7150_ONEu8_AUD_CTRL_SEN7 0x80 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN6 0x40 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN5 0x20 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN4 0x10 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN3 0x08 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN2 0x04 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN1 0x02 // u8 position +#define ANX7150_ONEu8_AUD_CTRL_SEN0 0x01 // u8 position + +#define ANX7150_ONEu8_AUD0_CTRL_REG 0x61 +#define ANX7150_ONEu8_AUD1_CTRL_REG 0x62 +#define ANX7150_ONEu8_AUD2_CTRL_REG 0x63 +#define ANX7150_ONEu8_AUD3_CTRL_REG 0x64 + +#define ANX7150_ONEu8_AUDCLK_CTRL_REG 0x65 + +#define ANX7150_ONEu8_AUDCLK_DET 0x08 // u8 position + +#define ANX7150_SPDIF_ERR_THRSHLD_REG 0x66 +#define ANX7150_SPDIF_ERR_CNT_REG 0x67 + +#define ANX7150_HDMI_LINK_CTRL_REG 0x70 + +#define ANX7150_HDMI_LINK_DATA_MUTEEN1 0x80 // u8 position +#define ANX7150_HDMI_LINK_DATA_MUTEEN0 0x40 // u8 position +#define ANX7150_HDMI_LINK_CLK_MUTEEN2 0x20 // u8 position +#define ANX7150_HDMI_LINK_CLK_MUTEEN1 0x10 // u8 position +#define ANX7150_HDMI_LINK_CLK_MUTEEN0 0x08 // u8 position +#define ANX7150_HDMI_LINK_DEC_DE 0x04 // u8 position +#define ANX7150_HDMI_LINK_PRMB_INC 0x02 // u8 position +#define ANX7150_HDMI_LINK_AUTO_PROG 0x01 // u8 position + +#define ANX7150_VID_CAPCTRL2_REG 0x71 + +#define ANX7150_VID_CAPCTRL2_CHK_UPDATEEN 0x10 // u8 position + +#define ANX7150_LINK_MUTEEE_REG 0x72 + +#define ANX7150_LINK_MUTEEE_AVMUTE_EN2 0x20 // u8 position +#define ANX7150_LINK_MUTEEE_AVMUTE_EN1 0x10 // u8 position +#define ANX7150_LINK_MUTEEE_AVMUTE_EN0 0x08 // u8 position +#define ANX7150_LINK_MUTEEE_AUDMUTE_EN2 0x04 // u8 position +#define ANX7150_LINK_MUTEEE_AUDMUTE_EN1 0x02 // u8 position +#define ANX7150_LINK_MUTEEE_AUDMUTE_EN0 0x01 // u8 position + +#define ANX7150_SERDES_TEST0_REG 0x73 +#define ANX7150_SERDES_TEST1_REG 0x74 +#define ANX7150_SERDES_TEST2_REG 0x75 + +#define ANX7150_PLL_TX_AMP 0x76 + + +#define ANX7150_DDC_SLV_ADDR_REG 0x80 +#define ANX7150_DDC_SLV_SEGADDR_REG 0x81 +#define ANX7150_DDC_SLV_OFFADDR_REG 0x82 +#define ANX7150_DDC_ACC_CMD_REG 0x83 +#define ANX7150_DDC_ACCNUM0_REG 0x84 +#define ANX7150_DDC_ACCNUM1_REG 0x85 + +#define ANX7150_DDC_CHSTATUS_REG 0x86 + +#define ANX7150_DDC_CHSTATUS_DDCERR 0x80 // u8 position +#define ANX7150_DDC_CHSTATUS_DDC_OCCUPY 0x40 // u8 position +#define ANX7150_DDC_CHSTATUS_FIFO_FULL 0x20 // u8 position +#define ANX7150_DDC_CHSTATUS_FIFO_EMPT 0x10 // u8 position +#define ANX7150_DDC_CHSTATUS_NOACK 0x08 // u8 position +#define ANX7150_DDC_CHSTATUS_FIFO_RD 0x04 // u8 position +#define ANX7150_DDC_CHSTATUS_FIFO_WR 0x02 // u8 position +#define ANX7150_DDC_CHSTATUS_INPRO 0x01 // u8 position + +#define ANX7150_DDC_FIFO_ACC_REG 0x87 +#define ANX7150_DDC_FIFOCNT_REG 0x88 + +#define ANX7150_SYS_PD_REG 0x90 +#define ANX7150_SYS_PD_PLL 0x80 // u8 position +#define ANX7150_SYS_PD_TMDS 0x40 // u8 position +#define ANX7150_SYS_PD_TMDS_CLK 0x20 // u8 position +#define ANX7150_SYS_PD_MISC 0x10 // u8 position +#define ANX7150_SYS_PD_LINK 0x08 // u8 position +#define ANX7150_SYS_PD_IDCK 0x04 // u8 position +#define ANX7150_SYS_PD_AUD 0x02 // u8 position +#define ANX7150_SYS_PD_MACRO_ALL 0x01 // u8 position + +#define ANX7150_LINKFSM_DEBUG0_REG 0x91 +#define ANX7150_LINKFSM_DEBUG1_REG 0x92 + +#define ANX7150_PLL_CTRL0_REG 0x93 +#define ANX7150_PLL_CTRL0_CPREG_BLEED 0x02 // u8 position +#define ANX7150_PLL_CTRL0_TEST_EN 0x01 // u8 position + +#define ANX7150_PLL_CTRL1_REG 0x94 +#define ANX7150_PLL_CTRL1_TESTEN 0x80 // u8 position + +#define ANX7150_OSC_CTRL_REG 0x95 +#define ANX7150_OSC_CTRL_TESTEN 0x80 // u8 position +#define ANX7150_OSC_CTRL_SEL_BG 0x40 // u8 position + +#define ANX7150_TMDS_CH0_CONFIG_REG 0x96 +#define ANX7150_TMDS_CH0_TESTEN 0x20 // u8 position +#define ANX7150_TMDS_CH0_AMP 0x1C // u8 position +#define ANX7150_TMDS_CHO_EMP 0x03 // u8 position + +#define ANX7150_TMDS_CH1_CONFIG_REG 0x97 +#define ANX7150_TMDS_CH1_TESTEN 0x20 // u8 position +#define ANX7150_TMDS_CH1_AMP 0x1C // u8 position +#define ANX7150_TMDS_CH1_EMP 0x03 // u8 position + +#define ANX7150_TMDS_CH2_CONFIG_REG 0x98 +#define ANX7150_TMDS_CH2_TESTEN 0x20 // u8 position +#define ANX7150_TMDS_CH2_AMP 0x1C // u8 position +#define ANX7150_TMDS_CH2_EMP 0x03 // u8 position + +#define ANX7150_TMDS_CLKCH_CONFIG_REG 0x99 +#define ANX7150_TMDS_CLKCH_MUTE 0x80 // u8 position +#define ANX7150_TMDS_CLKCH_TESTEN 0x08 // u8 position +#define ANX7150_TMDS_CLKCH_AMP 0x07 // u8 position + +#define ANX7150_CHIP_CTRL_REG 0x9A +#define ANX7150_CHIP_CTRL_PRBS_GENEN 0x80 // u8 position +#define ANX7150_CHIP_CTRL_LINK_DBGSEL 0x70 // u8 position +#define ANX7150_CHIP_CTRL_VIDCHK_EN 0x08 // u8 position +#define ANX7150_CHIP_CTRL_MISC_TIMER 0x04 // u8 position +#define ANX7150_CHIP_CTRL_PLL_RNG 0x02 // u8 position +#define ANX7150_CHIP_CTRL_PLL_MAN 0x01 // u8 position + +#define ANX7150_CHIP_STATUS_REG 0x9B +#define ANX7150_CHIP_STATUS_GPIO 0x80 // u8 position +#define ANX7150_CHIP_STATUS_SDA 0x40 // u8 position +#define ANX7150_CHIP_STATUS_SCL 0x20 // u8 position +#define ANX7150_CHIP_STATUS_PLL_HSPO 0x04 // u8 position +#define ANX7150_CHIP_STATUS_PLL_LOCK 0x02 // u8 position +#define ANX7150_CHIP_STATUS_MISC_LOCK 0x01 // u8 position + +#define ANX7150_DBG_PINGPIO_CTRL_REG 0x9C +#define ANX7150_DBG_PINGPIO_VDLOW_SHAREDEN 0x04 // u8 position +#define ANX7150_DBG_PINGPIO_GPIO_ADDREN 0x02 // u8 position +#define ANX7150_DBG_PINGPIO_GPIO_OUT 0x01 // u8 position + +#define ANX7150_CHIP_DEBUG0_CTRL_REG 0x9D +#define ANX7150_CHIP_DEBUG0_PRBS_ERR 0xE0 // u8 position +#define ANX7150_CHIP_DEBUG0_CAPST 0x1F // u8 position + +#define ANX7150_CHIP_DEBUG1_CTRL_REG 0x9E +#define ANX7150_CHIP_DEBUG1_SDA_SW 0x80 // u8 position +#define ANX7150_CHIP_DEBUG1_SCL_SW 0x40 // u8 position +#define ANX7150_CHIP_DEBUG1_SERDES_TESTEN 0x20 // u8 position +#define ANX7150_CHIP_DEBUG1_CLK_BYPASS 0x10 // u8 position +#define ANX7150_CHIP_DEBUG1_FORCE_PLLLOCK 0x08 // u8 position +#define ANX7150_CHIP_DEBUG1_PLLLOCK_BYPASS 0x04 // u8 position +#define ANX7150_CHIP_DEBUG1_FORCE_HP 0x02 // u8 position +#define ANX7150_CHIP_DEBUG1_HP_DEGLITCH 0x01 // u8 position + +#define ANX7150_CHIP_DEBUG2_CTRL_REG 0x9F +#define ANX7150_CHIP_DEBUG2_EXEMB_SYNCEN 0x04 // u8 position +#define ANX7150_CHIP_DEBUG2_VIDBIST 0x02 // u8 position + +#define ANX7150_VID_INCLK_REG 0x5F + +#define ANX7150_HDCP_STATUS_REG 0xA0 +#define ANX7150_HDCP_STATUS_ADV_CIPHER 0x80 // u8 position +#define ANX7150_HDCP_STATUS_R0_READY 0x10 // u8 position +#define ANX7150_HDCP_STATUS_AKSV_ACT 0x08 // u8 position +#define ANX7150_HDCP_STATUS_ENCRYPT 0x04 // u8 position +#define ANX7150_HDCP_STATUS_AUTH_PASS 0x02 // u8 position +#define ANX7150_HDCP_STATUS_KEY_DONE 0x01 // u8 position + +#define ANX7150_HDCP_CTRL0_REG 0xA1 +#define ANX7150_HDCP_CTRL0_STORE_AN 0x80 // u8 position +#define ANX7150_HDCP_CTRL0_RX_REP 0x40 // u8 position +#define ANX7150_HDCP_CTRL0_RE_AUTH 0x20 // u8 position +#define ANX7150_HDCP_CTRL0_SW_AUTHOK 0x10 // u8 position +#define ANX7150_HDCP_CTRL0_HW_AUTHEN 0x08 // u8 position +#define ANX7150_HDCP_CTRL0_ENC_EN 0x04 // u8 position +#define ANX7150_HDCP_CTRL0_BKSV_SRM 0x02 // u8 position +#define ANX7150_HDCP_CTRL0_KSV_VLD 0x01 // u8 position + +#define ANX7150_HDCP_CTRL1_REG 0xA2 +#define ANX7150_LINK_CHK_12_EN 0x40 +#define ANX7150_HDCP_CTRL1_DDC_NOSTOP 0x20 // u8 position +#define ANX7150_HDCP_CTRL1_DDC_NOACK 0x10 // u8 position +#define ANX7150_HDCP_CTRL1_EDDC_NOACK 0x08 // u8 position +#define ANX7150_HDCP_CTRL1_BLUE_SCREEN_EN 0x04 // u8 position +#define ANX7150_HDCP_CTRL1_RCV11_EN 0x02 // u8 position +#define ANX7150_HDCP_CTRL1_HDCP11_EN 0x01 // u8 position + +#define ANX7150_HDCP_Link_Check_FRAME_NUM_REG 0xA3 +#define ANX7150_HDCP_AKSV1_REG 0xA5 +#define ANX7150_HDCP_AKSV2_REG 0xA6 +#define ANX7150_HDCP_AKSV3_REG 0xA7 +#define ANX7150_HDCP_AKSV4_REG 0xA8 +#define ANX7150_HDCP_AKSV5_REG 0xA9 + +#define ANX7150_HDCP_AN1_REG 0xAA +#define ANX7150_HDCP_AN2_REG 0xAB +#define ANX7150_HDCP_AN3_REG 0xAC +#define ANX7150_HDCP_AN4_REG 0xAD +#define ANX7150_HDCP_AN5_REG 0xAE +#define ANX7150_HDCP_AN6_REG 0xAF +#define ANX7150_HDCP_AN7_REG 0xB0 +#define ANX7150_HDCP_AN8_REG 0xB1 + +#define ANX7150_HDCP_BKSV1_REG 0xB2 +#define ANX7150_HDCP_BKSV2_REG 0xB3 +#define ANX7150_HDCP_BKSV3_REG 0xB4 +#define ANX7150_HDCP_BKSV4_REG 0xB5 +#define ANX7150_HDCP_BKSV5_REG 0xB6 + +#define ANX7150_HDCP_RI1_REG 0xB7 +#define ANX7150_HDCP_RI2_REG 0xB8 + +#define ANX7150_HDCP_PJ_REG 0xB9 +#define ANX7150_HDCP_RX_CAPS_REG 0xBA +#define ANX7150_HDCP_BSTATUS0_REG 0xBB +#define ANX7150_HDCP_BSTATUS1_REG 0xBC + +#define ANX7150_HDCP_AMO0_REG 0xD0 +#define ANX7150_HDCP_AMO1_REG 0xD1 +#define ANX7150_HDCP_AMO2_REG 0xD2 +#define ANX7150_HDCP_AMO3_REG 0xD3 +#define ANX7150_HDCP_AMO4_REG 0xD4 +#define ANX7150_HDCP_AMO5_REG 0xD5 +#define ANX7150_HDCP_AMO6_REG 0xD6 +#define ANX7150_HDCP_AMO7_REG 0xD7 + +#define ANX7150_HDCP_DBG_CTRL_REG 0xBD + +#define ANX7150_HDCP_DBG_ENC_INC 0x08 // u8 position +#define ANX7150_HDCP_DBG_DDC_SPEED 0x06 // u8 position +#define ANX7150_HDCP_DBG_SKIP_RPT 0x01 // u8 position + +#define ANX7150_HDCP_KEY_STATUS_REG 0xBE +#define ANX7150_HDCP_KEY_BIST_EN 0x04 // u8 position +#define ANX7150_HDCP_KEY_BIST_ERR 0x02 // u8 position +#define ANX7150_HDCP_KEY_CMD_DONE 0x01 // u8 position + +#define ANX7150_KEY_CMD_REGISTER 0xBF //added + +#define ANX7150_HDCP_AUTHDBG_STATUS_REG 0xC7 +#define ANX7150_HDCP_ENCRYPTDBG_STATUS_REG 0xC8 +#define ANX7150_HDCP_FRAME_NUM_REG 0xC9 + +#define ANX7150_DDC_MSTR_INTER_REG 0xCA +#define ANX7150_DDC_MSTR_LINK_REG 0xCB + +#define ANX7150_HDCP_BLUESCREEN0_REG 0xCC +#define ANX7150_HDCP_BLUESCREEN1_REG 0xCD +#define ANX7150_HDCP_BLUESCREEN2_REG 0xCE +// DEV_ADDR = 0x7A or 0x7E +#define ANX7150_INFO_PKTCTRL1_REG 0xC0 +#define ANX7150_INFO_PKTCTRL1_SPD_RPT 0x80 // u8 position +#define ANX7150_INFO_PKTCTRL1_SPD_EN 0x40 // u8 position +#define ANX7150_INFO_PKTCTRL1_AVI_RPT 0x20 // u8 position +#define ANX7150_INFO_PKTCTRL1_AVI_EN 0x10 // u8 position +#define ANX7150_INFO_PKTCTRL1_GCP_RPT 0x08 // u8 position +#define ANX7150_INFO_PKTCTRL1_GCP_EN 0x04 // u8 position +#define ANX7150_INFO_PKTCTRL1_ACR_NEW 0x02 // u8 position +#define ANX7150_INFO_PKTCTRL1_ACR_EN 0x01 // u8 position + +#define ANX7150_INFO_PKTCTRL2_REG 0xC1 +#define ANX7150_INFO_PKTCTRL2_UD1_RPT 0x80 // u8 position +#define ANX7150_INFO_PKTCTRL2_UD1_EN 0x40 // u8 position +#define ANX7150_INFO_PKTCTRL2_UD0_RPT 0x20 // u8 position +#define ANX7150_INFO_PKTCTRL2_UD0_EN 0x10 // u8 position +#define ANX7150_INFO_PKTCTRL2_MPEG_RPT 0x08 // u8 position +#define ANX7150_INFO_PKTCTRL2_MPEG_EN 0x04 // u8 position +#define ANX7150_INFO_PKTCTRL2_AIF_RPT 0x02 // u8 position +#define ANX7150_INFO_PKTCTRL2_AIF_EN 0x01 // u8 position + +#define ANX7150_ACR_N1_SW_REG 0xC2 +#define ANX7150_ACR_N2_SW_REG 0xC3 +#define ANX7150_ACR_N3_SW_REG 0xC4 + +#define ANX7150_ACR_CTS1_SW_REG 0xC5 +#define ANX7150_ACR_CTS2_SW_REG 0xC6 +#define ANX7150_ACR_CTS3_SW_REG 0xC7 + +#define ANX7150_ACR_CTS1_HW_REG 0xC8 +#define ANX7150_ACR_CTS2_HW_REG 0xC9 +#define ANX7150_ACR_CTS3_HW_REG 0xCA + +#define ANX7150_ACR_CTS_CTRL_REG 0xCB + +#define ANX7150_GNRL_CTRL_PKT_REG 0xCC +#define ANX7150_GNRL_CTRL_CLR_AVMUTE 0x02 // u8 position +#define ANX7150_GNRL_CTRL_SET_AVMUTE 0x01 // u8 position + +#define ANX7150_AUD_PKT_FLATCTRL_REG 0xCD +#define ANX7150_AUD_PKT_AUTOFLAT_EN 0x80 // u8 position +#define ANX7150_AUD_PKT_FLAT 0x07 // u8 position + + +//select video hardware interface +#define ANX7150_VID_HW_INTERFACE 0x03//0x00:RGB and YcbCr 4:4:4 Formats with Separate Syncs (24-bpp mode) + //0x01:YCbCr 4:2:2 Formats with Separate Syncs(16-bbp) + //0x02:YCbCr 4:2:2 Formats with Embedded Syncs(No HS/VS/DE) + //0x03:YC Mux 4:2:2 Formats with Separate Sync Mode1(u815:8 and u8 3:0 are used) + //0x04:YC Mux 4:2:2 Formats with Separate Sync Mode2(u811:0 are used) + //0x05:YC Mux 4:2:2 Formats with Embedded Sync Mode1(u815:8 and u8 3:0 are used) + //0x06:YC Mux 4:2:2 Formats with Embedded Sync Mode2(u811:0 are used) + //0x07:RGB and YcbCr 4:4:4 DDR Formats with Separate Syncs + //0x08:RGB and YcbCr 4:4:4 DDR Formats with Embedded Syncs + //0x09:RGB and YcbCr 4:4:4 Formats with Separate Syncs but no DE + //0x0a:YCbCr 4:2:2 Formats with Separate Syncs but no DE +//select input color space +#define ANX7150_INPUT_COLORSPACE 0x01//0x00: input color space is RGB + //0x01: input color space is YCbCr422 + //0x02: input color space is YCbCr444 +//select input pixel clock edge for DDR mode +#define ANX7150_IDCK_EDGE_DDR 0x00 //0x00:use rising edge to latch even numbered pixel data//jack wen + //0x01:use falling edge to latch even numbered pixel data + +//select audio hardware interface +#define ANX7150_AUD_HW_INTERFACE 0x01//0x01:audio input comes from I2S + //0x02:audio input comes from SPDIF + //0x04:audio input comes from one u8 audio +//select MCLK and Fs relationship if audio HW interface is I2S +#define ANX7150_MCLK_Fs_RELATION 0x01//0x00:MCLK = 128 * Fs + //0x01:MCLK = 256 * Fs + //0x02:MCLK = 384 * Fs + //0x03:MCLK = 512 * Fs //wen updated error + +#define ANX7150_AUD_CLK_EDGE 0x00 //0x00:use MCLK and SCK rising edge to latch audio data + //0x08, revised by wen. //0x80:use MCLK and SCK falling edge to latch audio data +//select I2S channel numbers if audio HW interface is I2S +#define ANX7150_I2S_CH0_ENABLE 0x01 //0x01:enable channel 0 input; 0x00: disable +#define ANX7150_I2S_CH1_ENABLE 0x00 //0x01:enable channel 0 input; 0x00: disable +#define ANX7150_I2S_CH2_ENABLE 0x00 //0x01:enable channel 0 input; 0x00: disable +#define ANX7150_I2S_CH3_ENABLE 0x00 //0x01:enable channel 0 input; 0x00: disable +//select I2S word length if audio HW interface is I2S +#define ANX7150_I2S_WORD_LENGTH 0x0b + //0x02 = 16u8s; 0x04 = 18 u8s; 0x08 = 19 u8s; 0x0a = 20 u8s(maximal word length is 20u8s); 0x0c = 17 u8s; + // 0x03 = 20u8s(maximal word length is 24u8s); 0x05 = 22 u8s; 0x09 = 23 u8s; 0x0b = 24 u8s; 0x0d = 21 u8s; + +//select I2S format if audio HW interface is I2S +#define ANX7150_I2S_SHIFT_CTRL 0x00//0x00: fist u8 shift(philips spec) + //0x01:no shift +#define ANX7150_I2S_DIR_CTRL 0x00//0x00:SD data MSB first + //0x01:LSB first +#define ANX7150_I2S_WS_POL 0x00//0x00:left polarity when word select is low + //0x01:left polarity when word select is high +#define ANX7150_I2S_JUST_CTRL 0x00//0x00:data is left justified + //0x01:data is right justified + +#define EDID_Parse_Enable 1 // cwz 0 for test, 1 normal +//InfoFrame and Control Packet Registers +// 0x7A or 0X7E +/* +#define AVI_HB0 0x00 +#define AVI_HB1 0x01 +#define AVI_HB2 0x02 +#define AVI_PB0 0x03 +#define AVI_PB1 0x04 +#define AVI_PB2 0x05 +#define AVI_PB3 0x06 +#define AVI_PB4 0x07 +#define AVI_PB5 0x08 +#define AVI_PB6 0x09 +#define AVI_PB7 0x0A +#define AVI_PB8 0x0B +#define AVI_PB9 0x0C +#define AVI_PB10 0x0D +#define AVI_PB11 0x0E +#define AVI_PB12 0x0F +#define AVI_PB13 0x10 +#define AVI_PB14 0x11 +#define AVI_PB15 0x12 + +#define AUD_HBO 0x20 +#define AUD_HB1 0x21 +#define AUD_HB2 0x22 +#define AUD_PB0 0x23 +#define AUD_PB1 0x24 +#define AUD_PB2 0x25 +#define AUD_PB3 0x26 +#define AUD_PB4 0x27 +#define AUD_PB5 0x28 +#define AUD_PB6 0x29 +#define AUD_PB7 0x2A +#define AUD_PB8 0x2B +#define AUD_PB9 0x2C +#define AUD_PB10 0x2D + +#define SPD_HBO 0x40 +#define SPD_HB1 0x41 +#define SPD_HB2 0x42 +#define SPD_PB0 0x43 +#define SPD_PB1 0x44 +#define SPD_PB2 0x45 +#define SPD_PB3 0x46 +#define SPD_PB4 0x47 +#define SPD_PB5 0x48 +#define SPD_PB6 0x49 +#define SPD_PB7 0x4A +#define SPD_PB8 0x4B +#define SPD_PB9 0x4C +#define SPD_PB10 0x4D +#define SPD_PB11 0x4E +#define SPD_PB12 0x4F +#define SPD_PB13 0x50 +#define SPD_PB14 0x51 +#define SPD_PB15 0x52 +#define SPD_PB16 0x53 +#define SPD_PB17 0x54 +#define SPD_PB18 0x55 +#define SPD_PB19 0x56 +#define SPD_PB20 0x57 +#define SPD_PB21 0x58 +#define SPD_PB22 0x59 +#define SPD_PB23 0x5A +#define SPD_PB24 0x5B +#define SPD_PB25 0x5C +#define SPD_PB26 0x5D +#define SPD_PB27 0x5E + +#define MPEG_HBO 0x60 +#define MPEG_HB1 0x61 +#define MPEG_HB2 0x62 +#define MPEG_PB0 0x63 +#define MPEG_PB1 0x64 +#define MPEG_PB2 0x65 +#define MPEG_PB3 0x66 +#define MPEG_PB4 0x67 +#define MPEG_PB5 0x68 +#define MPEG_PB6 0x69 +#define MPEG_PB7 0x6A +#define MPEG_PB8 0x6B +#define MPEG_PB9 0x6C +#define MPEG_PB10 0x6D +#define MPEG_PB11 0x6E +#define MPEG_PB12 0x6F +#define MPEG_PB13 0x70 +#define MPEG_PB14 0x71 +#define MPEG_PB15 0x72 +#define MPEG_PB16 0x73 +#define MPEG_PB17 0x74 +#define MPEG_PB18 0x75 +#define MPEG_PB19 0x76 +#define MPEG_PB20 0x77 +#define MPEG_PB21 0x78 +#define MPEG_PB22 0x79 +#define MPEG_PB23 0x7A +#define MPEG_PB24 0x7B +#define MPEG_PB25 0x7C +#define MPEG_PB26 0x7D +#define MPEG_PB27 0x7E + +#define USRDF0_HBO 0x80 +#define USRDF0_HB1 0x81 +#define USRDF0_HB2 0x82 +#define USRDF0_PB0 0x83 +#define USRDF0_PB1 0x84 +#define USRDF0_PB2 0x85 +#define USRDF0_PB3 0x86 +#define USRDF0_PB4 0x87 +#define USRDF0_PB5 0x88 +#define USRDF0_PB6 0x89 +#define USRDF0_PB7 0x8A +#define USRDF0_PB8 0x8B +#define USRDF0_PB9 0x8C +#define USRDF0_PB10 0x8D +#define USRDF0_PB11 0x8E +#define USRDF0_PB12 0x8F +#define USRDF0_PB13 0x90 +#define USRDF0_PB14 0x91 +#define USRDF0_PB15 0x92 +#define USRDF0_PB16 0x93 +#define USRDF0_PB17 0x94 +#define USRDF0_PB18 0x95 +#define USRDF0_PB19 0x96 +#define USRDF0_PB20 0x97 +#define USRDF0_PB21 0x98 +#define USRDF0_PB22 0x99 +#define USRDF0_PB23 0x9A +#define USRDF0_PB24 0x9B +#define USRDF0_PB25 0x9C +#define USRDF0_PB26 0x9D +#define USRDF0_PB27 0x9E + +#define USRDF1_HBO 0xA0 +#define USRDF1_HB1 0xA1 +#define USRDF1_HB2 0xA2 +#define USRDF1_PB0 0xA3 +#define USRDF1_PB1 0xA4 +#define USRDF1_PB2 0xA5 +#define USRDF1_PB3 0xA6 +#define USRDF1_PB4 0xA7 +#define USRDF1_PB5 0xA8 +#define USRDF1_PB6 0xA9 +#define USRDF1_PB7 0xAA +#define USRDF1_PB8 0xAB +#define USRDF1_PB9 0xAC +#define USRDF1_PB10 0xAD +#define USRDF1_PB11 0xAE +#define USRDF1_PB12 0xAF +#define USRDF1_PB13 0xB0 +#define USRDF1_PB14 0xB1 +#define USRDF1_PB15 0xB2 +#define USRDF1_PB16 0xB3 +#define USRDF1_PB17 0xB4 +#define USRDF1_PB18 0xB5 +#define USRDF1_PB19 0xB6 +#define USRDF1_PB20 0xB7 +#define USRDF1_PB21 0xB8 +#define USRDF1_PB22 0xB9 +#define USRDF1_PB23 0xBA +#define USRDF1_PB24 0xBB +#define USRDF1_PB25 0xBC +#define USRDF1_PB26 0xBD +#define USRDF1_PB27 0xBE +*/ + +void ANX7150_API_HDCP_ONorOFF(u8 HDCP_ONorOFF); +int anx7150_detect_device(struct anx7150_pdata *anx); +u8 ANX7150_Get_System_State(void); +int ANX7150_Interrupt_Process(struct anx7150_pdata *anx, int cur_state); +int anx7150_unplug(struct i2c_client *client); +int anx7150_plug(struct i2c_client *client); +int ANX7150_API_Initial(struct i2c_client *client); +void ANX7150_Shutdown(struct i2c_client *client); +int ANX7150_Parse_EDID(struct i2c_client *client, struct anx7150_dev_s *dev); +int ANX7150_GET_SENSE_STATE(struct i2c_client *client); +int ANX7150_Get_Optimal_resolution(int resolution_set); +void HDMI_Set_Video_Format(u8 video_format); +void HDMI_Set_Audio_Fs( u8 audio_fs); +void ANX7150_API_System_Config(void); +u8 ANX7150_Config_Audio(struct i2c_client *client); +u8 ANX7150_Config_Packet(struct i2c_client *client); +void ANX7150_HDCP_Process(struct i2c_client *client); +int ANX7150_PLAYBACK_Process(void); +void ANX7150_Set_System_State(struct i2c_client *client, u8 new_state); +int ANX7150_Config_Video(struct i2c_client *client); +int ANX7150_GET_RECIVER_TYPE(void); +void HDMI_Set_Video_Format(u8 video_format); +void HDMI_Set_Audio_Fs( u8 audio_fs); +int ANX7150_PLAYBACK_Process(void); + + +#endif diff --git a/drivers/video/hdmi/chips/anx7150_sys.c b/drivers/video/hdmi/chips/anx7150_sys.c new file mode 100755 index 000000000000..baf99b9724be --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150_sys.c @@ -0,0 +1,492 @@ +// ANALOGIX Company +// ANX7150 Demo Firmware +#include +#include +#include + + +#include "anx7150_sys.h" + + +/******** define uint8 and WORD, by kfx *******/ +int anx7150_tmds_enable(struct hdmi *hdmi) +{ + int rc = 0; + char c; + + /* andio stream enable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0) + return rc; + c |= (ANX7150_HDMI_AUDCTRL1_IN_EN); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0) + return rc; + + /* video stream enable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0) + return rc; + c |= (ANX7150_VID_CTRL_IN_EN); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0) + return rc; + + /* TMDS enable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0) + return rc; + c |= (ANX7150_TMDS_CLKCH_MUTE); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0) + return rc; + + return rc; +} + +int anx7150_tmds_disable(struct hdmi *hdmi) +{ + int rc = 0; + char c; + + /* andio stream disable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0) + return rc; + c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0) + return rc; + + /* video stream disable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0) + return rc; + c &= (~ANX7150_VID_CTRL_IN_EN); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0) + return rc; + + /* TMDS disable */ + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0) + return rc; + c &= (~ANX7150_TMDS_CLKCH_MUTE); + + if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0) + return rc; + + return rc; +} +static void anx7150_set_video_format(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + switch(hdmi->resolution) + { + case HDMI_720x576p_50Hz: + anx->video_format = ANX7150_V720x576p_50Hz_4x3; + break; + case ANX7150_V1280x720p_50Hz: + anx->video_format = ANX7150_V1280x720p_50Hz; + break; + case HDMI_1280x720p_60Hz: + anx->video_format = ANX7150_V1280x720p_60Hz; + break; + default: + anx->video_format = ANX7150_V1280x720p_50Hz; + break; + } + anx->system_config_done = 0; + return; +} +static void anx7150_set_audio_fs(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->audio_format = hdmi->audio_fs; + anx->system_config_done = 0; + return; +} + +static void anx7150_set_system_state(struct hdmi *hdmi, unsigned char ss) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->system_state = ss; + switch (ss) + { + case ANX7150_INITIAL: + dev_info(hdmi->dev, "system state: ANX7150_INITIAL\n"); + break; + case ANX7150_WAIT_HOTPLUG: + dev_info(hdmi->dev, "system state: ANX7150_WAIT_HOTPLUG\n"); + break; + case ANX7150_READ_PARSE_EDID: + dev_info(hdmi->dev, "system state: ANX7150_READ_PARSE_EDID\n"); + break; + case ANX7150_WAIT_RX_SENSE: + dev_info(hdmi->dev, "system state: ANX7150_WAIT_RX_SENSE\n"); + break; + case ANX7150_CONFIG_VIDEO: + dev_info(hdmi->dev, "system state: ANX7150_CONFIG_VIDEO\n"); + break; + case ANX7150_CONFIG_AUDIO: + dev_info(hdmi->dev, "system state: ANX7150_CONFIG_AUDIO\n"); + break; + case ANX7150_CONFIG_PACKETS: + dev_info(hdmi->dev, "system state: ANX7150_CONFIG_PACKETS\n"); + break; + case ANX7150_HDCP_AUTHENTICATION: + dev_info(hdmi->dev, "system state: ANX7150_HDCP_AUTHENTICATION\n"); + break; + case ANX7150_RESET_LINK: + dev_info(hdmi->dev, "system state: ANX7150_RESET_LINK\n"); + break; + case ANX7150_PLAY_BACK: + dev_info(hdmi->dev, "system state: ANX7150_PLAY_BACK\n"); + break; + default: + dev_info(hdmi->dev, "system state: ANX7150 unknown state\n"); + break; + } + return; +} + +static void anx7150_variable_initial(struct hdmi *hdmi) +{ + int i; + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx7150_set_system_state(hdmi, ANX7150_INITIAL); + + anx->anx7150_hdcp_auth_en = 0; + anx->anx7150_ksv_srm_pass =0; + anx->anx7150_srm_checked = 0; + anx->anx7150_hdcp_auth_pass = 0; + anx->anx7150_avmute_enable = 1; + anx->anx7150_hdcp_auth_fail_counter =0; + anx->anx7150_hdcp_encryption = 0; + anx->anx7150_send_blue_screen = 0; + anx->anx7150_hdcp_init_done = 0; + anx->anx7150_hdcp_wait_100ms_needed = 1; + anx->anx7150_auth_fully_pass = 0; + anx->timer_slot = 0; + /***************for video config***************/ + anx->anx7150_video_timing_id = 0; + anx->anx7150_in_pix_rpt = 0; + anx->anx7150_tx_pix_rpt = 0; + anx->anx7150_new_csc = 0; + anx->anx7150_new_vid_id = 0; + anx->anx7150_new_hw_interface = 0; + /*****************end of video config**********/ + + /********************for edid parse************/ + anx->edid.is_HDMI = 0; + anx->edid.ycbcr422_supported = 0; + anx->edid.ycbcr444_supported = 0; + anx->edid.supported_720p_60Hz = 0; + anx->edid.supported_720p_50Hz = 0; + anx->edid.supported_576p_50Hz = 0; + anx->edid.supported_576i_50Hz = 0; + anx->edid.supported_1080i_60Hz = 0; + anx->edid.supported_1080i_50Hz = 0; + anx->edid.supported_640x480p_60Hz = 0; + anx->edid.supported_720x480p_60Hz = 0; + anx->edid.supported_720x480i_60Hz = 0; + anx->edid.edid_errcode = 0; + anx->edid.SpeakerFormat = 0; + for (i = 0; i < 8; i ++) + { + anx->edid.AudioChannel[i] = 0; + anx->edid.AudioFormat[i] = 0; + anx->edid.AudioFs[i] = 0; + anx->edid.AudioLength[i] = 0; + } + /********************end of edid****************/ + + anx->packets_config.packets_need_config = 0x03; //new avi infoframe + anx->packets_config.avi_info.type = 0x82; + anx->packets_config.avi_info.version = 0x02; + anx->packets_config.avi_info.length = 0x0d; + anx->packets_config.avi_info.pb_uint8[1] = 0x21;//YCbCr422 + anx->packets_config.avi_info.pb_uint8[2] = 0x08; + anx->packets_config.avi_info.pb_uint8[3] = 0x00; + anx->packets_config.avi_info.pb_uint8[4] = 0x00; + anx->packets_config.avi_info.pb_uint8[5] = 0x00; + anx->packets_config.avi_info.pb_uint8[6] = 0x00; + anx->packets_config.avi_info.pb_uint8[7] = 0x00; + anx->packets_config.avi_info.pb_uint8[8] = 0x00; + anx->packets_config.avi_info.pb_uint8[9] = 0x00; + anx->packets_config.avi_info.pb_uint8[10] = 0x00; + anx->packets_config.avi_info.pb_uint8[11] = 0x00; + anx->packets_config.avi_info.pb_uint8[12] = 0x00; + anx->packets_config.avi_info.pb_uint8[13] = 0x00; + + // audio infoframe + anx->packets_config.audio_info.type = 0x84; + anx->packets_config.audio_info.version = 0x01; + anx->packets_config.audio_info.length = 0x0a; + anx->packets_config.audio_info.pb_uint8[1] = 0x00; //zy 061123 for ATC + anx->packets_config.audio_info.pb_uint8[2] = 0x00; + anx->packets_config.audio_info.pb_uint8[3] = 0x00; + anx->packets_config.audio_info.pb_uint8[4] = 0x00; + anx->packets_config.audio_info.pb_uint8[5] = 0x00; + anx->packets_config.audio_info.pb_uint8[6] = 0x00; + anx->packets_config.audio_info.pb_uint8[7] = 0x00; + anx->packets_config.audio_info.pb_uint8[8] = 0x00; + anx->packets_config.audio_info.pb_uint8[9] = 0x00; + anx->packets_config.audio_info.pb_uint8[10] = 0x00; + + anx->anx7150_int_done = 0; +} + + +static void anx7150_hw_interface_variable_initial(struct hdmi *hdmi) +{ + unsigned char c; + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->anx7150_video_format_config = 0x00; + anx->anx7150_rgborycbcr = 0x00; + anx->anx7150_ddr_edge = ANX7150_IDCK_EDGE_DDR; + + c = 0; + c = (ANX7150_I2S_CH0_ENABLE << 2) | (ANX7150_I2S_CH1_ENABLE << 3) | + (ANX7150_I2S_CH2_ENABLE << 4) | (ANX7150_I2S_CH3_ENABLE << 5); + + anx->audio_config.audio_type = ANX7150_AUD_HW_INTERFACE; // input I2S + anx->audio_config.down_sample = 0x00; + anx->audio_config.i2s_config.audio_channel = c;//0x04; + anx->audio_config.i2s_config.Channel_status1 =0x00; + anx->audio_config.i2s_config.Channel_status1 = 0x00; + anx->audio_config.i2s_config.Channel_status2 = 0x00; + anx->audio_config.i2s_config.Channel_status3 = 0x00; + anx->audio_config.i2s_config.Channel_status4 = 0x00;//0x02;//48k + anx->audio_config.i2s_config.Channel_status5 = ANX7150_I2S_WORD_LENGTH;//0x0b; + anx->audio_config.audio_layout = 0x00; + + c = (ANX7150_I2S_SHIFT_CTRL << 3) | (ANX7150_I2S_DIR_CTRL << 2) | + (ANX7150_I2S_WS_POL << 1) | ANX7150_I2S_JUST_CTRL; + anx->audio_config.i2s_config.i2s_format = c;//0x00; + + anx->freq_mclk= ANX7150_MCLK_Fs_RELATION;//set the relation of MCLK and WS + anx->anx7150_audio_clock_edge = ANX7150_AUD_CLK_EDGE; + return; +} +static int anx7150_hardware_initial(struct hdmi *hdmi) +{ + int rc = 0; + char c = 0; + + //clear HDCP_HPD_RST + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c); + c |= (0x01); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c); + + mdelay(10); + + c &= (~0x01); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c); + + //Power on I2C + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c); + c |= (ANX7150_SYS_CTRL3_I2C_PWON); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c); + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c); + c= 0x00; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SRST_REG, &c); + + //clear HDCP_HPD_RST + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c); + c &= (0xbf); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c); + + //Power on Audio capture and Video capture module clock + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_PD_REG, &c); + c |= (0x06); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_PD_REG, &c); + + //Enable auto set clock range for video PLL + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_CHIP_CTRL_REG, &c); + c &= (0x00); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_CHIP_CTRL_REG, &c); + + //Set registers value of Blue Screen when HDCP authentication failed--RGB mode,green field + c = 0x10; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN0_REG, &c); + c = 0xeb; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN1_REG, &c); + c = 0x10; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN2_REG, &c); + + //ANX7150_i2c_read_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, &c); + //ANX7150_i2c_write_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, (c | 0x80)); + + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_PLL_CTRL0_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_CTRL0_REG, &c); + + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c); + c |= (0x08); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c); + + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_PLL_TX_AMP, &c);//jack wen + c |= (0x01); + + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_TX_AMP, &c); //TMDS swing + + c = 0x00; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_CTRL1_REG, &c); //Added for PLL unlock issue in high temperature - Feiw + //if (ANX7150_AUD_HW_INTERFACE == 0x02) //jack wen, spdif + + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_I2S_CTRL_REG, &c);//jack wen, for spdif input from SD0. + c &= (0xef); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_I2S_CTRL_REG, &c); + + c = 0xc7; + rc = anx7150_i2c_write_p0_reg(hdmi->client, 0xE1, &c); + + //ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c); + c = 0x00; + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c);//power down HDCP, 090630 + + rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);//jack wen, for spdif input from SD0. + c &= (0xef); + rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);//power down all, 090630 + + //anx7150_set_system_state(hdmi, ANX7150_WAIT_HOTPLUG); + return rc; +} + +static int anx7150_initial(struct hdmi *hdmi) +{ + int rc = 0; + anx7150_variable_initial(hdmi); + anx7150_hw_interface_variable_initial(hdmi); + + rc = anx7150_hardware_initial(hdmi); + return rc; +} +static void anx7150_set_hdcp_state(struct hdmi* hdmi) +{ + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->hdcp_on = hdmi->hdcp_on; + return; +} +int anx7150_system_init(struct hdmi *hdmi) +{ + int rc = 0; + + if((rc = anx7150_detect_device(hdmi)) < 0) + { + dev_err(hdmi->dev, "anx7150 api detectdevice err!\n"); + return rc; + } + anx7150_set_audio_fs(hdmi); + + if((rc = anx7150_initial(hdmi)) < 0) + { + dev_err(hdmi->dev, "anx7150 initial err!\n"); + return rc; + } + anx7150_set_hdcp_state(hdmi); + + return 0; +} + + + + + + + + + + + + + + + + + + +static u8 anx7150_detect_device(struct hdmi *hdmi) +{ + int i, rc = 0; + char d1, d2; + + for (i=0; i<10; i++) + { + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_DEV_IDL_REG, &d1)) < 0) + continue; + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_DEV_IDH_REG, &d2)) < 0) + continue; + if (d1 == 0x50 && d2 == 0x71) + { + dev_info(hdmi->dev, "anx7150 detected!\n"); + return 1; + } + } + + dev_info(hdmi->dev, "anx7150 not detected"); + return 0; +} +static u8 anx7150_get_system_state(struct anx7150_pdata *anx) +{ + return anx->anx7150_system_state; +} +static u8 anx7150_get_hpd(struct i2c_client *client) +{ + char c; + + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c)) < 0) + return rc; + if(c & ANX7150_SYS_CTRL3_PWON_ALL) + { + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_STATE_REG, &c)) < 0) + return rc; + return (c & ANX7150_SYS_STATE_HP)? 1:0; + } + else + { + if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_INTR_STATE_REG, &c)) < 0) + return rc; + return (c)? 1:0; + } +} +static u8 anx7150_interrupt_process(struct hdmi *hdmi, int state) +{ + int hot_plug; + int rc; + + hot_plug = anx7150_get_hpd(hdmi->client); +} + +int anx7150_display_on_hw(struct hdmi *hdmi) +{ + u8 state; + struct anx7150_pdata *anx = hdmi_get_privdata(hdmi); + + anx->anx7150_detect = anx7150_detect_device(hdmi); + if(anx->anx7150_detect < 0) + { + return -EIO; + } + + state = anx7150_get_system_state(anx); + if(hdmi->display_on == 0 && hdmi->auto_switch == 0) + { + if(state > WAIT_HDMI_ENABLE) + state = INITIAL; + } + if(hdmi->param_conf == 1) + { + if(state > WAIT_HDMI_ENABLE) + state = WAIT_HDMI_ENABLE; + hdmi->param_conf = 0; + } + + state = anx7150_interrupt_process(); + +} + + diff --git a/drivers/video/hdmi/hdmi-codec.c b/drivers/video/hdmi/hdmi-codec.c new file mode 100644 index 000000000000..5f27786c1bcc --- /dev/null +++ b/drivers/video/hdmi/hdmi-codec.c @@ -0,0 +1,6 @@ +#include + +int hdmi_codec_set_audio_fs(unsigned char audio_fs) +{ + return 0; +} diff --git a/drivers/video/hdmi/hdmi-core.c b/drivers/video/hdmi/hdmi-core.c new file mode 100755 index 000000000000..047a22eb7792 --- /dev/null +++ b/drivers/video/hdmi/hdmi-core.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include + +struct class *hdmi_class; +struct hdmi_id_ref_info { + int id; + int ref; +}ref_info[HDMI_MAX_ID]; +#ifdef CONFIG_SYSFS + +extern int hdmi_create_attrs(struct hdmi *hdmi); +extern void hdmi_remove_attrs(struct hdmi *hdmi); + +#else + +static inline int hdmi_create_attrs(struct hdmi *hdmi) +{ return 0; } +static inline void hdmi_remove_attrs(struct hdmi *hdmi) {} + +#endif /* CONFIG_SYSFS */ + +void *hdmi_get_privdata(struct hdmi *hdmi) +{ + return hdmi->priv; +} +void hdmi_set_privdata(struct hdmi *hdmi, void *data) +{ + hdmi->priv = data; + return; +} + +void hdmi_changed(struct hdmi *hdmi, int plug) +{ + hdmi_dbg(hdmi->dev, "%s\n", __FUNCTION__); + hdmi->plug = plug; + schedule_work(&hdmi->changed_work); +} + +static void hdmi_changed_work(struct work_struct *work) +{ + struct hdmi *hdmi = container_of(work, struct hdmi, + changed_work); + + hdmi_dbg(hdmi->dev, "%s\n", __FUNCTION__); + + kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE); +} + +int hdmi_register(struct device *parent, struct hdmi *hdmi) +{ + int rc = 0, i; + char name[8]; + + for(i = 0; i < HDMI_MAX_ID; i++) + { + if(ref_info[i].ref == 0) + { + ref_info[i].ref = 1; + hdmi->id = i; + break; + } + } + if(i == HDMI_MAX_ID) + return -EINVAL; + sprintf(name, "hdmi-%d", hdmi->id); + + hdmi->dev = device_create(hdmi_class, parent, 0, + "%s", name); + if (IS_ERR(hdmi->dev)) { + rc = PTR_ERR(hdmi->dev); + goto dev_create_failed; + } + + dev_set_drvdata(hdmi->dev, hdmi); + + INIT_WORK(&hdmi->changed_work, hdmi_changed_work); + + rc = hdmi_create_attrs(hdmi); + if (rc) + goto create_attrs_failed; + + //hdmi_changed(hdmi, 0); + + goto success; + +create_attrs_failed: + device_unregister(hdmi->dev); +dev_create_failed: +success: + return rc; +} +void hdmi_unregister(struct hdmi *hdmi) +{ + flush_scheduled_work(); + hdmi_remove_attrs(hdmi); + device_unregister(hdmi->dev); + ref_info[hdmi->id].ref = 0; +} + +static int __init hdmi_class_init(void) +{ + int i; + + hdmi_class = class_create(THIS_MODULE, "hdmi"); + + if (IS_ERR(hdmi_class)) + return PTR_ERR(hdmi_class); + for(i = 0; i < HDMI_MAX_ID; i++) { + ref_info[i].id = i; + ref_info[i].ref = 0; + } + return 0; +} + +static void __exit hdmi_class_exit(void) +{ + class_destroy(hdmi_class); +} +EXPORT_SYMBOL(hdmi_changed); +EXPORT_SYMBOL(hdmi_register); +EXPORT_SYMBOL(hdmi_unregister); + +subsys_initcall(hdmi_class_init); +module_exit(hdmi_class_exit); + diff --git a/drivers/video/hdmi/hdmi-fb.c b/drivers/video/hdmi/hdmi-fb.c new file mode 100755 index 000000000000..2e854e12eafb --- /dev/null +++ b/drivers/video/hdmi/hdmi-fb.c @@ -0,0 +1,196 @@ +#include +#include +#include + +#include "../display/screen/screen.h" +#include "../rk29_fb.h" + + +/* Base */ +#define OUT_TYPE SCREEN_RGB +#define OUT_FACE OUT_P888 +#define DCLK_POL 0 +#define SWAP_RB 0 + +/* 720p@60Hz Timing */ +#define OUT_CLK 74250000 +#define H_PW 40 +#define H_BP 220 +#define H_VD 1280 +#define H_FP 110 +#define V_PW 5 +#define V_BP 20 +#define V_VD 720 +#define V_FP 5 + +/* 720p@50Hz Timing */ +#define OUT_CLK2 74250000 +#define H_PW2 40 +#define H_BP2 220 +#define H_VD2 1280 +#define H_FP2 440 +#define V_PW2 5 +#define V_BP2 20 +#define V_VD2 720 +#define V_FP2 5 + +/* 576p@50Hz Timing */ +#define OUT_CLK3 27000000 +#define H_PW3 64 +#define H_BP3 68 +#define H_VD3 720 +#define H_FP3 12 +#define V_PW3 5 +#define V_BP3 39 +#define V_VD3 576 +#define V_FP3 5 + +extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ); + +static int anx7150_init(void) +{ + return 0; +} + +static int anx7150_standby(u8 enable) +{ + return 0; +} + +static void hdmi_set_info(struct rk29fb_screen *screen) +{ + struct rk29fb_screen *screen2 = screen + 1; + struct rk29fb_screen *screen3 = screen + 2; + + /* ****************** 720p@60Hz ******************* */ + /* screen type & face */ + screen->type = OUT_TYPE; + screen->face = OUT_FACE; + + /* Screen size */ + screen->x_res = H_VD; + screen->y_res = V_VD; + + /* Timing */ + screen->pixclock = OUT_CLK; + screen->left_margin = H_BP; + screen->right_margin = H_FP; + screen->hsync_len = H_PW; + screen->upper_margin = V_BP; + screen->lower_margin = V_FP; + screen->vsync_len = V_PW; + + /* Pin polarity */ + screen->pin_hsync = 0; + screen->pin_vsync = 0; + screen->pin_den = 0; + screen->pin_dclk = DCLK_POL; + + /* Swap rule */ + screen->swap_rb = SWAP_RB; + screen->swap_rg = 0; + screen->swap_gb = 0; + screen->swap_delta = 0; + screen->swap_dumy = 0; + + /* Operation function*/ + screen->init = anx7150_init; + screen->standby = anx7150_standby; + + + /* ****************** 720p@50Hz ******************* */ + /* screen type & face */ + screen2->type = OUT_TYPE; + screen2->face = OUT_FACE; + + /* Screen size */ + screen2->x_res = H_VD2; + screen2->y_res = V_VD2; + + /* Timing */ + screen2->pixclock = OUT_CLK2; + screen2->left_margin = H_BP2; + screen2->right_margin = H_FP2; + screen2->hsync_len = H_PW2; + screen2->upper_margin = V_BP2; + screen2->lower_margin = V_FP2; + screen2->vsync_len = V_PW2; + + /* Pin polarity */ + screen2->pin_hsync = 0; + screen2->pin_vsync = 0; + screen2->pin_den = 0; + screen2->pin_dclk = DCLK_POL; + + /* Swap rule */ + screen2->swap_rb = SWAP_RB; + screen2->swap_rg = 0; + screen2->swap_gb = 0; + screen2->swap_delta = 0; + screen2->swap_dumy = 0; + + /* Operation function*/ + screen2->init = anx7150_init; + screen2->standby = anx7150_standby; + + /* ****************** 576p@50Hz ******************* */ + /* screen type & face */ + screen3->type = OUT_TYPE; + screen3->face = OUT_FACE; + + /* Screen size */ + screen3->x_res = H_VD3; + screen3->y_res = V_VD3; + + /* Timing */ + screen3->pixclock = OUT_CLK3; + screen3->left_margin = H_BP3; + screen3->right_margin = H_FP3; + screen3->hsync_len = H_PW3; + screen3->upper_margin = V_BP3; + screen3->lower_margin = V_FP3; + screen3->vsync_len = V_PW3; + + /* Pin polarity */ + screen3->pin_hsync = 0; + screen3->pin_vsync = 0; + screen3->pin_den = 0; + screen3->pin_dclk = DCLK_POL; + + /* Swap rule */ + screen3->swap_rb = SWAP_RB; + screen3->swap_rg = 0; + screen3->swap_gb = 0; + screen3->swap_delta = 0; + screen3->swap_dumy = 0; + + /* Operation function*/ + screen3->init = anx7150_init; + screen3->standby = anx7150_standby; +} + +int hdmi_switch_fb(int resolution, int type) +{ + int rc = 0; + struct rk29fb_screen hdmi_info[3]; + + hdmi_set_info(&hdmi_info[0]); + + switch(resolution) + { + case HDMI_1280x720p_50Hz: + rc = FB_Switch_Screen(&hdmi_info[1], type); + break; + case HDMI_1280x720p_60Hz: + rc = FB_Switch_Screen(&hdmi_info[0], type); + break; + case HDMI_720x576p_50Hz: + rc = FB_Switch_Screen(&hdmi_info[2], type); + break; + default: + rc = FB_Switch_Screen(&hdmi_info[1], type); + break; + } + return rc; +} + diff --git a/drivers/video/hdmi/hdmi-sysfs.c b/drivers/video/hdmi/hdmi-sysfs.c new file mode 100755 index 000000000000..7b83c4b4ecbe --- /dev/null +++ b/drivers/video/hdmi/hdmi-sysfs.c @@ -0,0 +1,162 @@ +#include +#include +#include + + +static ssize_t hdmi_show_state_attrs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + + return sprintf(buf, "display_on=%d\n" + "plug=%d\n" + "--------------------------\n" + "resolution support:\n" + "0 -- 1280x720p_50Hz\n" + "1 -- 1280x720p_60Hz\n" + "2 -- 720x576p_50Hz\n" + "--------------------------\n" + "auto_switch=%d\n" + "hdcp_on=%d\n" + "audio_fs=%d\n" + "resolution=%d\n", + hdmi->display_on,hdmi->plug, + hdmi->auto_switch, hdmi->hdcp_on, + hdmi->audio_fs, hdmi->resolution); +} +static ssize_t hdmi_restore_state_attrs(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + char *p; + const char *q; + int auto_switch = -1, hdcp_on = -1, audio_fs = -1, resolution = -1; + + q = buf; + do + { + if((p = strstr(q, "auto_switch=")) != NULL) + { + q = p + 12; + if((sscanf(q, "%d", &auto_switch) == 1) && + (auto_switch == 0 || auto_switch == 1)) + hdmi->auto_switch = auto_switch; + else + { + dev_err(dev, "failed to set hdmi configuration\n"); + return -EINVAL; + } + } + else if((p = strstr(q, "hdcp_on=")) != NULL) + { + q = p + 8; + if((sscanf(q, "%d", &hdcp_on) == 1) && + (hdcp_on == 0 || hdcp_on == 1)) + hdmi->hdcp_on = hdcp_on; + else + { + dev_err(dev, "failed to set hdmi configuration\n"); + return -EINVAL; + } + } + else if((p = strstr(q, "audio_fs=")) != NULL) + { + q = p + 9; + if((sscanf(q, "%d", &audio_fs) == 1) && + (audio_fs >= 0)) + hdmi->audio_fs = audio_fs; + else + { + dev_err(dev, "failed to set hdmi configuration\n"); + return -EINVAL; + } + } + else if((p = strstr(q, "resolution=")) != NULL) + { + q = p + 11; + if((sscanf(q, "%d", &resolution) == 1) && + (resolution >= 0)) + hdmi->resolution = resolution; + else + { + dev_err(dev, "failed to set hdmi configuration\n"); + return -EINVAL; + } + } + else + break; + + }while(*q != 0); + if(auto_switch == -1 && + hdcp_on == -1 && + audio_fs == -1 && + resolution == -1) + { + dev_err(dev, "failed to set hdmi configuration\n"); + return -EINVAL; + } + if(hdmi->hdmi_set_param) + hdmi->hdmi_set_param(hdmi); + return size; +} + +static ssize_t hdmi_show_switch_attrs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hdmi *hdmi = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", hdmi->display_on); +} +static ssize_t hdmi_restore_switch_attrs(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int display_on = 0; + struct hdmi *hdmi = dev_get_drvdata(dev); + + sscanf(buf, "%d", &display_on); + + if(hdmi->hdmi_display_on && display_on == 1) + hdmi->hdmi_display_on(hdmi); + else if(hdmi->hdmi_display_off && display_on == 0) + hdmi->hdmi_display_off(hdmi); + + return size; +} +static struct device_attribute hdmi_attrs[] = { + __ATTR(state, 0664, hdmi_show_state_attrs, hdmi_restore_state_attrs), + __ATTR(enable, 0664, hdmi_show_switch_attrs, hdmi_restore_switch_attrs), +}; + +int hdmi_create_attrs(struct hdmi *hdmi) +{ + int rc = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_attrs); i++) { + rc = device_create_file(hdmi->dev, &hdmi_attrs[i]); + if (rc) + goto create_failed; + } + + goto succeed; + +create_failed: + while (i--) + device_remove_file(hdmi->dev, &hdmi_attrs[i]); +succeed: + return rc; +} + +void hdmi_remove_attrs(struct hdmi *hdmi) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_attrs); i++) + device_remove_file(hdmi->dev, &hdmi_attrs[i]); +} + + diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index 1e7418efb2e4..e233f1ce4c01 100755 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -53,7 +53,6 @@ #include "./display/screen/screen.h" -#define ANDROID_USE_THREE_BUFS 0 //android use three buffers to accelerate UI display in rgb plane #if 0 #define fbprintk(msg...) printk(msg); @@ -101,6 +100,11 @@ struct win0_par { u32 pseudo_pal[16]; u32 y_offset; u32 uv_offset; + u32 xpos; //size in panel + u32 ypos; + u32 xsize; //start point in panel + u32 ysize; + u32 format; u8 par_seted; u8 addr_seted; @@ -110,15 +114,22 @@ struct win1_par { u32 refcount; u32 pseudo_pal[16]; int lstblank; + u32 xpos; + u32 ypos; + u32 xsize; + u32 ysize; + u32 format; + u32 addr_offset; }; struct rk29fb_inf { - struct fb_info *win0fb; - struct fb_info *win1fb; + struct fb_info *fb1; + struct fb_info *fb0; void __iomem *reg_vir_base; // virtual basic address of lcdc register u32 reg_phy_base; // physical basic address of lcdc register u32 len; // physical map length of lcdc register + u32 video_mode; struct clk *clk; struct clk *dclk; //lcdc dclk @@ -153,9 +164,8 @@ struct rk29fb_inf { __u32 cursor_size; /* Amount of ioremapped VRAM or 0 */ unsigned long cursor_start; - struct rk29fb_screen lcd_info; - struct rk29fb_screen tv_info[5]; - struct rk29fb_screen hdmi_info[2]; + struct rk29fb_screen panel1_info; // 1st panel, it's lcd normally + struct rk29fb_screen panel2_info; // 2nd panel struct rk29fb_screen *cur_screen; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; @@ -191,10 +201,6 @@ static int win1fb_set_par(struct fb_info *info); static DECLARE_WAIT_QUEUE_HEAD(wq); static int wq_condition = 0; -#if ANDROID_USE_THREE_BUFS -static int new_frame_seted = 1; -#endif - void set_lcd_pin(struct platform_device *pdev, int enable) { struct rk29fb_info *mach_info = pdev->dev.platform_data; @@ -541,10 +547,11 @@ void load_screen(struct fb_info *info, bool initscreen) return ; } - if(inf->cur_screen == &inf->lcd_info) { + if(inf->cur_screen == &inf->panel1_info) { inf->dclk_parent = clk_get(&g_pdev->dev, "periph_pll"); } else { inf->dclk_parent = clk_get(&g_pdev->dev, "codec_pll"); + clk_set_rate(inf->dclk_parent, 297000000); } if (!inf->dclk_parent || IS_ERR(inf->dclk_parent)) @@ -785,7 +792,7 @@ int rk29_set_cursor(struct fb_info *info, struct fb_cursor *cursor) } #endif -static int win0fb_blank(int blank_mode, struct fb_info *info) +static int win0_blank(int blank_mode, struct fb_info *info) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); @@ -808,121 +815,7 @@ static int win0fb_blank(int blank_mode, struct fb_info *info) return 0; } -static int win0fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct rk29fb_inf *inf = dev_get_drvdata(info->device); - struct rk29fb_screen *screen = inf->cur_screen; - - u32 ScaleYRGBY=0x1000; - u16 xpos = (var->nonstd>>8) & 0xfff; //offset in panel - u16 ypos = (var->nonstd>>20) & 0xfff; - u16 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel - u16 ysize = (var->grayscale>>20) & 0xfff; - u16 xlcd = screen->x_res; //size of panel - u16 ylcd = screen->y_res; - u16 yres = 0; - - if(inf->win0fb->var.rotate == 270) { - xlcd = screen->y_res; - ylcd = screen->x_res; - } - - fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); - - CHK_SUSPEND(inf); - - if( 0==var->xres_virtual || 0==var->yres_virtual || - 0==var->xres || 0==var->yres || var->xres<16 || - 0==xsize || 0==ysize || xsize<16 || - ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) ) - { - printk(">>>>>> win0fb_check_var fail 1!!! \n"); - printk("0==%d || 0==%d || 0==%d || 0==%d || %d<16 \n ||0==%d || 0==%d || %d<16 ||((16!=%d)&&(32!=%d)) \n", - var->xres_virtual, var->yres_virtual, var->xres, var->yres, var->xres, xsize, ysize, xsize, - var->bits_per_pixel, var->bits_per_pixel); - return -EINVAL; - } - - if( (var->xoffset+var->xres)>var->xres_virtual || - (var->yoffset+var->yres)>var->yres_virtual || - (xpos+xsize)>xlcd || (ypos+ysize)>ylcd ) - { - printk(">>>>>> win0fb_check_var fail 2!!! \n"); - printk("(%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d \n ", - var->xoffset, var->xres, var->xres_virtual, var->yoffset, var->yres, - var->yres_virtual, xpos, xsize, xlcd, ypos, ysize, ylcd); - return -EINVAL; - } - - switch(var->nonstd&0x0f) - { - case 0: // rgb - switch(var->bits_per_pixel) - { - case 16: // rgb565 - var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1); - var->xres = (var->xres + 0x1) & (~0x1); - var->xoffset = (var->xoffset) & (~0x1); - break; - default: // rgb888 - var->bits_per_pixel = 32; - break; - } - var->nonstd &= ~0xc0; //not support I2P in this format - break; - case 1: // yuv422 - var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); - var->xres = (var->xres + 0x3) & (~0x3); - var->xoffset = (var->xoffset) & (~0x3); - break; - case 2: // yuv4200 - var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); - var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1); - var->xres = (var->xres + 0x3) & (~0x3); - var->yres = (var->yres + 0x1) & (~0x1); - var->xoffset = (var->xoffset) & (~0x3); - var->yoffset = (var->yoffset) & (~0x1); - break; - case 3: // yuv4201 - var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); - var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1); - var->xres = (var->xres + 0x3) & (~0x3); - var->yres = (var->yres + 0x1) & (~0x1); - var->xoffset = (var->xoffset) & (~0x3); - var->yoffset = (var->yoffset) & (~0x1); - var->nonstd &= ~0xc0; //not support I2P in this format - break; - case 4: // none - case 5: // yuv444 - var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); - var->xres = (var->xres + 0x3) & (~0x3); - var->xoffset = (var->xoffset) & (~0x3); - var->nonstd &= ~0xc0; //not support I2P in this format - break; - default: - printk(">>>>>> win0fb var->nonstd=%d is invalid! \n", var->nonstd); - return -EINVAL; - } - - if(var->rotate == 270) - { - yres = var->xres; - } - else - { - yres = var->yres; - } - ScaleYRGBY = CalScaleW0(yres, ysize); - - if((ScaleYRGBY>0x8000) || (ScaleYRGBY<0x200)) - { - return -EINVAL; // multiple of scale down or scale up can't exceed 8 - } - - return 0; -} - -static int win0fb_set_par(struct fb_info *info) +static int win0_set_par(struct fb_info *info) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); struct rk29fb_screen *screen = inf->cur_screen; @@ -930,128 +823,50 @@ static int win0fb_set_par(struct fb_info *info) struct fb_fix_screeninfo *fix = &info->fix; struct win0_par *par = info->par; - u8 format = 0; - u32 cblen=0, crlen=0, map_size=0, smem_len=0; - u32 xact = var->xres; /* visible resolution */ u32 yact = var->yres; u32 xvir = var->xres_virtual; /* virtual resolution */ u32 yvir = var->yres_virtual; u32 xact_st = var->xoffset; /* offset from virtual to visible */ u32 yact_st = var->yoffset; /* resolution */ - - u16 xpos = (var->nonstd>>8) & 0xfff; //visiable pos in panel - u16 ypos = (var->nonstd>>20) & 0xfff; - u16 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel - u16 ysize = (var->grayscale>>20) & 0xfff; + u32 xpos = par->xpos; + u32 ypos = par->ypos; u32 ScaleYrgbX=0x1000,ScaleYrgbY=0x1000; u32 ScaleCbrX=0x1000, ScaleCbrY=0x1000; u8 data_format = var->nonstd&0x0f; - u32 win0_en = var->reserved[2]; - u32 y_addr = var->reserved[3]; //user alloc buf addr y - u32 uv_addr = var->reserved[4]; + u32 y_addr = 0; //user alloc buf addr y + u32 uv_addr = 0; fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); CHK_SUSPEND(inf); - /* calculate y_offset,uv_offset,line_length,cblen and crlen */ - switch (data_format) - { - case 0: // rgb - switch(var->bits_per_pixel) - { - case 16: // rgb565 - format = 1; - fix->line_length = 2 * xvir; - par->y_offset = (yact_st*xvir + xact_st)*2; - break; - case 32: // rgb888 - format = 0; - fix->line_length = 4 * xvir; - par->y_offset = (yact_st*xvir + xact_st)*4; - break; - default: - return -EINVAL; - } - break; - case 1: // yuv422 - format = 2; - fix->line_length = xvir; - cblen = crlen = (xvir*yvir)/2; - par->y_offset = yact_st*xvir + xact_st; - par->uv_offset = yact_st*xvir + xact_st; - break; - case 2: // yuv4200 - format = 3; - fix->line_length = xvir; - cblen = crlen = (xvir*yvir)/4; - - par->y_offset = yact_st*xvir + xact_st; - par->uv_offset = (yact_st/2)*xvir + xact_st; - - break; - case 3: // yuv4201 - format = 4; - fix->line_length = xvir; - par->y_offset = (yact_st/2)*2*xvir + (xact_st)*2; - par->uv_offset = (yact_st/2)*xvir + xact_st; - cblen = crlen = (xvir*yvir)/4; - break; - case 4: // none - case 5: // yuv444 - format = 5; - fix->line_length = xvir; - par->y_offset = yact_st*xvir + xact_st; - par->uv_offset = yact_st*2*xvir + xact_st*2; - cblen = crlen = (xvir*yvir); - break; - default: - return -EINVAL; - } - - smem_len = fix->line_length * yvir + cblen + crlen; - map_size = PAGE_ALIGN(smem_len); - - if (info->screen_base) { - printk(">>>>>> win0fb unmap memory(%d)! \n", info->fix.smem_len); - dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start); - info->screen_base = 0; - } - fix->smem_start = y_addr; - fix->smem_len = smem_len; - fix->mmio_start = uv_addr; - - par->addr_seted = (((-1==(int)y_addr)&&(-1==(int)uv_addr))||((0==(int)y_addr)&&(0==(int)uv_addr))) ? 0 : 1; - fbprintk("buffer alloced by user fix->smem_start = %8x, fix->smem_len = %8x, fix->mmio_start = %8x \n", (u32)fix->smem_start, (u32)fix->smem_len, (u32)fix->mmio_start); - // calculate the display phy address y_addr = fix->smem_start + par->y_offset; uv_addr = fix->mmio_start + par->uv_offset; - fbprintk("y_addr 0x%08x = 0x%08x + %d\n", y_addr, (u32)fix->smem_start, par->y_offset); - fbprintk("uv_addr 0x%08x = 0x%08x + %d\n", uv_addr, (u32)fix->mmio_start , par->uv_offset); - - ScaleYrgbX = CalScaleW0(xact, xsize); - ScaleYrgbY = CalScaleW0(yact, ysize); + ScaleYrgbX = CalScaleW0(xact, par->xsize); + ScaleYrgbY = CalScaleW0(yact, par->ysize); switch (data_format) { case 1:// yuv422 - ScaleCbrX= CalScaleW0((xact/2), xsize); - ScaleCbrY = CalScaleW0(yact, ysize); + ScaleCbrX= CalScaleW0((xact/2), par->xsize); + ScaleCbrY = CalScaleW0(yact, par->ysize); break; case 2: // yuv4200 case 3: // yuv4201 - ScaleCbrX= CalScaleW0(xact/2, xsize); - ScaleCbrY = CalScaleW0(yact/2, ysize); + ScaleCbrX= CalScaleW0(xact/2, par->xsize); + ScaleCbrY = CalScaleW0(yact/2, par->ysize); break; case 4: // none case 5:// yuv444 - ScaleCbrX= CalScaleW0(xact, xsize); - ScaleCbrY = CalScaleW0(yact, ysize); + ScaleCbrX= CalScaleW0(xact, par->xsize); + ScaleCbrY = CalScaleW0(yact, par->ysize); + break; + default: break; } @@ -1061,20 +876,23 @@ static int win0fb_set_par(struct fb_info *info) LcdWrReg(inf, WIN0_YRGB_MST, y_addr); LcdWrReg(inf, WIN0_CBR_MST, uv_addr); - LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE | m_W0_FORMAT, v_W0_ENABLE(win0_en && par->addr_seted) | v_W0_FORMAT(format)); + LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE | m_W0_FORMAT, v_W0_ENABLE(par->addr_seted) | v_W0_FORMAT(par->format)); LcdMskReg(inf, WIN0_VIR, m_WORDLO | m_WORDHI, v_VIRWIDTH(xvir) | v_VIRHEIGHT((yvir)) ); LcdMskReg(inf, WIN0_ACT_INFO, m_WORDLO | m_WORDHI, v_WORDLO(xact) | v_WORDHI(yact)); LcdMskReg(inf, WIN0_DSP_ST, m_BIT11LO | m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos)); - LcdMskReg(inf, WIN0_DSP_INFO, m_BIT11LO | m_BIT11HI, v_BIT11LO(xsize) | v_BIT11HI(ysize)); + LcdMskReg(inf, WIN0_DSP_INFO, m_BIT11LO | m_BIT11HI, v_BIT11LO(par->xsize) | v_BIT11HI(par->ysize)); LcdMskReg(inf, WIN0_SCL_FACTOR_YRGB, m_WORDLO | m_WORDHI, v_WORDLO(ScaleYrgbX) | v_WORDHI(ScaleYrgbY)); LcdMskReg(inf, WIN0_SCL_FACTOR_CBR, m_WORDLO | m_WORDHI, v_WORDLO(ScaleCbrX) | v_WORDHI(ScaleCbrY)); - switch(format) + switch(par->format) { + case 0: //rgb888 + LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP, + v_W0_YRGB_8_SWAP(1) | v_W0_YRGB_16_SWAP(1) | v_W0_YRGB_R_SHIFT_SWAP(1) | v_W0_565_RB_SWAP(1) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0)); case 1: //rgb565 LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP, - v_W0_YRGB_8_SWAP(0) | v_W0_YRGB_16_SWAP(0) | v_W0_YRGB_R_SHIFT_SWAP(0) | v_W0_565_RB_SWAP(1) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0)); + v_W0_YRGB_8_SWAP(0) | v_W0_YRGB_16_SWAP(0) | v_W0_YRGB_R_SHIFT_SWAP(0) | v_W0_565_RB_SWAP(0) | v_W0_YRGB_M8_SWAP(0) | v_W0_CBR_8_SWAP(0)); break; case 4: //yuv4201 LcdMskReg(inf, SWAP_CTRL, m_W0_YRGB_8_SWAP | m_W0_YRGB_16_SWAP | m_W0_YRGB_R_SHIFT_SWAP | m_W0_565_RB_SWAP | m_W0_YRGB_M8_SWAP | m_W0_CBR_8_SWAP, @@ -1089,9 +907,10 @@ static int win0fb_set_par(struct fb_info *info) LcdWrReg(inf, REG_CFG_DONE, 0x01); return 0; + } -static int win0fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +static int win0_pan( struct fb_info *info ) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); // struct fb_var_screeninfo *var0 = &info->var; @@ -1111,159 +930,136 @@ static int win0fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf LcdWrReg(inf, REG_CFG_DONE, 0x01); // enable win0 after the win0 addr is seted - par->par_seted = 1; - LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE((1==par->addr_seted)?(1):(0))); + LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE((1==par->addr_seted)?(1):(0))); mcu_refresh(inf); return 0; } -int win0fb_open(struct fb_info *info, int user) +static int win1_blank(int blank_mode, struct fb_info *info) { - struct win0_par *par = info->par; + struct rk29fb_inf *inf = dev_get_drvdata(info->device); fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); - par->par_seted = 0; - par->addr_seted = 0; + CHK_SUSPEND(inf); - if(par->refcount) { - printk(">>>>>> win0fb has opened! \n"); - return -EACCES; - } else { - par->refcount++; - return 0; + switch(blank_mode) + { + case FB_BLANK_UNBLANK: + LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(1)); + break; + default: + LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0)); + break; } + LcdWrReg(inf, REG_CFG_DONE, 0x01); + + mcu_refresh(inf); + return 0; } -int win0fb_release(struct fb_info *info, int user) +static int win1_set_par(struct fb_info *info) { + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct fb_var_screeninfo *var = &info->var; + struct fb_fix_screeninfo *fix = &info->fix; + struct rk29fb_screen *screen = inf->cur_screen; struct win0_par *par = info->par; - struct fb_var_screeninfo *var0 = &info->var; - fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); + u32 offset=0, addr=0, map_size=0, smem_len=0; - if(par->refcount) { - par->refcount--; + u16 xres_virtual = var->xres_virtual; //virtual screen size - win0fb_blank(FB_BLANK_POWERDOWN, info); - // wait for lcdc stop access memory - msleep(50); + u16 xpos_virtual = var->xoffset; //visiable offset in virtual screen + u16 ypos_virtual = var->yoffset; - // unmap memory - if (info->screen_base) { - printk(">>>>>> win0fb unmap memory(%d)! \n", info->fix.smem_len); - dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start); - info->screen_base = 0; - info->fix.smem_start = 0; - info->fix.smem_len = 0; - } + u16 xpos = par->xpos; //visiable offset in panel + u16 ypos = par->ypos; - // clean the var param - memset(var0, 0, sizeof(struct fb_var_screeninfo)); - } + u8 trspmode = TRSP_CLOSE; + u8 trspval = 0; - return 0; -} + //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); -static int win0fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) -{ - struct rk29fb_inf *inf = dev_get_drvdata(info->device); - struct win0_par *par = info->par; - void __user *argp = (void __user *)arg; + addr = fix->smem_start + par->y_offset; - fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); - fbprintk("win0fb_ioctl cmd = %8x, arg = %8x \n", (u32)cmd, (u32)arg); + LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE|m_W1_FORMAT, v_W1_ENABLE(1)|v_W1_FORMAT(par->format)); - CHK_SUSPEND(inf); + xpos += (screen->left_margin + screen->hsync_len); + ypos += (screen->upper_margin + screen->vsync_len); - switch(cmd) - { - case FB1_IOCTL_GET_PANEL_SIZE: //get panel size - { - u32 panel_size[2]; - if(inf->win0fb->var.rotate == 270) { - panel_size[0] = inf->cur_screen->y_res; - panel_size[1] = inf->cur_screen->x_res; - } else { - panel_size[0] = inf->cur_screen->x_res; - panel_size[1] = inf->cur_screen->y_res; - } + LcdWrReg(inf, WIN1_YRGB_MST, addr); - if(copy_to_user(argp, panel_size, 8)) return -EFAULT; - } - break; + LcdMskReg(inf, WIN1_DSP_ST, m_BIT11LO|m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos)); + LcdMskReg(inf, WIN1_DSP_INFO, m_BIT11LO|m_BIT11HI, v_BIT11LO(par->xsize) | v_BIT11HI(par->ysize)); - case FB1_IOCTL_SET_YUV_ADDR: //set y&uv address to register direct - { - u32 yuv_phy[2]; - if (copy_from_user(yuv_phy, argp, 8)) - return -EFAULT; + LcdMskReg(inf, WIN1_VIR, m_WORDLO , v_WORDLO(xres_virtual)); - yuv_phy[0] += par->y_offset; - yuv_phy[1] += par->uv_offset; + LcdMskReg(inf, BLEND_CTRL, m_W1_BLEND_EN | m_W1_BLEND_FACTOR, + v_W1_BLEND_EN((TRSP_FMREG==trspmode) || (TRSP_MASK==trspmode)) | v_W1_BLEND_FACTOR(trspval)); - LcdWrReg(inf, WIN0_YRGB_MST, yuv_phy[0]); - LcdWrReg(inf, WIN0_CBR_MST, yuv_phy[1]); - LcdWrReg(inf, REG_CFG_DONE, 0x01); - // enable win0 after the win0 par is seted - par->addr_seted = 1; - if(par->par_seted) { - LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(1)); - mcu_refresh(inf); - } - } - break; + // enable win1 color key and set the color to black(rgb=0) + LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, v_COLORKEY_EN(1) | v_KEYCOLOR(0)); - case FB1_IOCTL_SET_ROTATE: //change MCU panel scan direction - fbprintk(">>>>>> change lcdc direction(%d) \n", (int)arg); - return -1; - break; - default: - break; + if(1==par->format) //rgb565 + { + LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP, + v_W1_8_SWAP(0) | v_W1_16_SWAP(0) | v_W1_R_SHIFT_SWAP(0) | v_W1_565_RB_SWAP(0) ); } + else + { + LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP, + v_W1_8_SWAP(1) | v_W1_16_SWAP(1) | v_W1_R_SHIFT_SWAP(1) | v_W1_565_RB_SWAP(0) ); + + LcdMskReg(inf, DSP_CTRL0, m_W1_TRANSP_FROM, v_W1_TRANSP_FROM(TRSP_FMRAM==trspmode) ); + } + + LcdWrReg(inf, REG_CFG_DONE, 0x01); + return 0; } -static struct fb_ops win0fb_ops = { - .owner = THIS_MODULE, - .fb_open = win0fb_open, - .fb_release = win0fb_release, - .fb_check_var = win0fb_check_var, - .fb_set_par = win0fb_set_par, - .fb_blank = win0fb_blank, - .fb_pan_display = win0fb_pan_display, - .fb_ioctl = win0fb_ioctl, - .fb_setcolreg = fb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - -static int win1fb_blank(int blank_mode, struct fb_info *info) +static int win1_pan( struct fb_info *info ) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct fb_var_screeninfo *var1 = &info->var; + struct fb_fix_screeninfo *fix1 = &info->fix; + struct win0_par *par = info->par; - fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); + u32 addr = 0; + + //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); CHK_SUSPEND(inf); - switch(blank_mode) - { - case FB_BLANK_UNBLANK: - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(1)); - break; - default: - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0)); - break; - } - LcdWrReg(inf, REG_CFG_DONE, 0x01); + addr = fix1->smem_start + par->y_offset; + //fbprintk("info->screen_base = %8x ; fix1->smem_len = %d , addr = %8x\n",(u32)info->screen_base, fix1->smem_len, addr); + + LcdWrReg(inf, WIN1_YRGB_MST, addr); + LcdWrReg(inf, REG_CFG_DONE, 0x01); mcu_refresh(inf); + return 0; } -static int win1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +static int fb0_blank(int blank_mode, struct fb_info *info) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + + if(inf->video_mode == 1) + { + win1_blank(blank_mode, info); + } + else + { + win0_blank(blank_mode, info); + } + return 0; +} + +static int fb0_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); struct rk29fb_screen *screen = inf->cur_screen; @@ -1271,8 +1067,6 @@ static int win1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) u16 ypos = (var->nonstd>>20) & 0xfff; u16 xlcd = screen->x_res; u16 ylcd = screen->y_res; - u8 trspmode = (var->grayscale>>8) & 0xff; - u8 trspval = (var->grayscale) & 0xff; //fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); @@ -1285,7 +1079,6 @@ static int win1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) printk(">>>>>> win1fb_check_var fail 1!!! \n"); printk(">>>>>> 0==%d || 0==%d ", var->xres_virtual,var->yres_virtual); printk("0==%d || 0==%d || %d<16 || ", var->xres,var->yres,var->xres<16); - printk("%d>5 || %d>16 \n", trspmode,trspval); printk("bits_per_pixel=%d \n", var->bits_per_pixel); return -EINVAL; } @@ -1315,24 +1108,25 @@ static int win1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static int win1fb_set_par(struct fb_info *info) + +static int fb0_set_par(struct fb_info *info) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); struct fb_var_screeninfo *var = &info->var; struct fb_fix_screeninfo *fix = &info->fix; struct rk29fb_screen *screen = inf->cur_screen; + struct win0_par *par = info->par; u8 format = 0; u32 offset=0, addr=0, map_size=0, smem_len=0; u16 xres_virtual = var->xres_virtual; //virtual screen size - //u16 yres_virtual = var->yres_virtual; u16 xpos_virtual = var->xoffset; //visiable offset in virtual screen u16 ypos_virtual = var->yoffset; - u16 xpos = 0; //visiable offset in panel - u16 ypos = 0; + u16 xpos = (screen->x_res - var->xres)/2; //visiable offset in panel + u16 ypos = (screen->y_res - var->yres)/2; u16 xsize = screen->x_res; //visiable size in panel u16 ysize = screen->y_res; u8 trspmode = TRSP_CLOSE; @@ -1345,106 +1139,57 @@ static int win1fb_set_par(struct fb_info *info) switch(var->bits_per_pixel) { case 16: // rgb565 - format = 1; + par->format = 1; fix->line_length = 2 * xres_virtual; offset = (ypos_virtual*xres_virtual + xpos_virtual)*2; break; case 32: // rgb888 default: - format = 0; + par->format = 0; fix->line_length = 4 * xres_virtual; offset = (ypos_virtual*xres_virtual + xpos_virtual)*4; break; } - smem_len = fix->line_length * var->yres_virtual; //cursor buf also alloc here + smem_len = fix->line_length * var->yres_virtual; map_size = PAGE_ALIGN(smem_len); if (smem_len > fix->smem_len) // buffer need realloc { - printk("%s win1 buf \n",__FUNCTION__); - #if 0 - fbprintk(">>>>>> win1 buffer size is change(%d->%d)! remap memory!\n",fix->smem_len, smem_len); - fbprintk(">>>>>> smem_len %d = %d * %d \n", smem_len, fix->line_length, var->yres_virtual); - fbprintk(">>>>>> map_size = %d\n", map_size); - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0)); - LcdWrReg(inf, REG_CFG_DONE, 0x01); - msleep(50); - if (info->screen_base) { - printk(">>>>>> win1fb unmap memory(%d)! \n", info->fix.smem_len); - dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len), info->screen_base, info->fix.smem_start); - info->screen_base = 0; - fix->smem_start = 0; - fix->smem_len = 0; - } - - info->screen_base = dma_alloc_writecombine(NULL, map_size, &map_dma, GFP_KERNEL); - if(!info->screen_base) { - printk(">>>>>> win1fb dma_alloc_writecombine fail!\n"); - return -ENOMEM; - } - memset(info->screen_base, 0, map_size); - fix->smem_start = map_dma; - fix->smem_len = smem_len; - - fbprintk(">>>>>> alloc succ, mem=%08x, len=%d!\n", (u32)fix->smem_start, fix->smem_len); - #endif + printk("%s sorry!!! win1 buf is not enough\n",__FUNCTION__); } + par->y_offset = offset; + par->addr_seted = 1; - addr = fix->smem_start + offset; - -#if ANDROID_USE_THREE_BUFS - if(0==new_frame_seted) { - wq_condition = 0; - wait_event_interruptible_timeout(wq, wq_condition, HZ/20); - } - new_frame_seted = 0; -#endif - - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE|m_W1_FORMAT, v_W1_ENABLE(1)|v_W1_FORMAT(format)); - - xpos += (screen->left_margin + screen->hsync_len); - ypos += (screen->upper_margin + screen->vsync_len); - - LcdWrReg(inf, WIN1_YRGB_MST, addr); - - LcdMskReg(inf, WIN1_DSP_ST, m_BIT11LO|m_BIT11HI, v_BIT11LO(xpos) | v_BIT11HI(ypos)); - LcdMskReg(inf, WIN1_DSP_INFO, m_BIT11LO|m_BIT11HI, v_BIT11LO(xsize) | v_BIT11HI(ysize)); - - LcdMskReg(inf, WIN1_VIR, m_WORDLO | m_WORDHI , v_WORDLO(xres_virtual) | v_WORDHI(var->yres_virtual)); - - LcdMskReg(inf, BLEND_CTRL, m_W1_BLEND_EN | m_W1_BLEND_FACTOR, - v_W1_BLEND_EN((TRSP_FMREG==trspmode) || (TRSP_MASK==trspmode)) | v_W1_BLEND_FACTOR(trspval)); - - // enable win1 color key and set the color to black(rgb=0) - LcdMskReg(inf, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, v_COLORKEY_EN(1) | v_KEYCOLOR(0)); - - if(1==format) //rgb565 + if(inf->video_mode == 1) { - LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP, - v_W1_8_SWAP(0) | v_W1_16_SWAP(0) | v_W1_R_SHIFT_SWAP(0) | v_W1_565_RB_SWAP(0) ); + par->xpos = (screen->x_res - var->xres)/2; //visiable offset in panel + par->ypos = (screen->y_res - var->yres)/2; + par->xsize = screen->x_res; //visiable size in panel + par->ysize = screen->y_res; + win1_set_par(info); } else { - LcdMskReg(inf, SWAP_CTRL, m_W1_8_SWAP | m_W1_16_SWAP | m_W1_R_SHIFT_SWAP | m_W1_565_RB_SWAP, - v_W1_8_SWAP(1) | v_W1_16_SWAP(1) | v_W1_R_SHIFT_SWAP(1) | v_W1_565_RB_SWAP(0) ); - - LcdMskReg(inf, DSP_CTRL0, m_W1_TRANSP_FROM, v_W1_TRANSP_FROM(TRSP_FMRAM==trspmode) ); + par->xpos = 0; + par->ypos = 0; + par->xsize = screen->x_res; + par->ysize = screen->y_res; + win0_set_par(info); } - LcdWrReg(inf, REG_CFG_DONE, 0x01); - return 0; } -static int win1fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +static int fb0_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); struct fb_var_screeninfo *var1 = &info->var; struct fb_fix_screeninfo *fix1 = &info->fix; + struct win0_par *par = info->par; - u32 offset = 0, addr = 0; + u32 offset = 0; //fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); @@ -1463,17 +1208,17 @@ static int win1fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf return -EINVAL; } - addr = fix1->smem_start + offset; - - //fbprintk("info->screen_base = %8x ; fix1->smem_len = %d , addr = %8x\n",(u32)info->screen_base, fix1->smem_len, addr); - - LcdWrReg(inf, WIN1_YRGB_MST, addr); - LcdWrReg(inf, REG_CFG_DONE, 0x01); + par->y_offset = offset; - mcu_refresh(inf); - -#if !ANDROID_USE_THREE_BUFS - // flush end when wq_condition=1 in mcu panel, but not in rgb panel + if(inf->video_mode == 1) + { + win1_pan(info); + } + else + { + win0_pan(info); + } + // flush end when wq_condition=1 in mcu panel, but not in rgb panel if(SCREEN_MCU == inf->cur_screen->type) { wait_event_interruptible_timeout(wq, wq_condition, HZ/20); wq_condition = 0; @@ -1481,19 +1226,12 @@ static int win1fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf wq_condition = 0; wait_event_interruptible_timeout(wq, wq_condition, HZ/20); } -#endif - return 0; } - -static int win1fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct rk29fb_inf *inf = dev_get_drvdata(info->device); - struct rk29fb_info *mach_info = info->device->platform_data; - unsigned display_on; - int display_on_pol; - fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); CHK_SUSPEND(inf); @@ -1506,47 +1244,350 @@ static int win1fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar inf->mcu_usetimer = 0; } break; + default: + break; + } + return 0; +} - case FB0_IOCTL_SET_PANEL: - if(arg>7) return -1; +static int fb1_blank(int blank_mode, struct fb_info *info) +{ + win0_blank(blank_mode, info); + return 0; +} - /* Black out, because some display device need clock to standby */ - //LcdMskReg(inf, DSP_CTRL_REG1, m_BLACK_OUT, v_BLACK_OUT(1)); - LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0)); - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0)); - LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(1)); - LcdWrReg(inf, REG_CFG_DONE, 0x01); - if(inf->cur_screen) +static int fb1_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct rk29fb_screen *screen = inf->cur_screen; + + u32 ScaleYRGBY=0x1000; + u16 xpos = (var->nonstd>>8) & 0xfff; //offset in panel + u16 ypos = (var->nonstd>>20) & 0xfff; + u16 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel + u16 ysize = (var->grayscale>>20) & 0xfff; + u16 xlcd = screen->x_res; //size of panel + u16 ylcd = screen->y_res; + u16 yres = 0; + + xpos = (xpos * screen->x_res) / inf->panel1_info.x_res; + ypos = (ypos * screen->y_res) / inf->panel1_info.y_res; + xsize = (xsize * screen->x_res) / inf->panel1_info.x_res; + ysize = (ysize * screen->y_res) / inf->panel1_info.y_res; + + fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); + + CHK_SUSPEND(inf); + + if( 0==var->xres_virtual || 0==var->yres_virtual || + 0==var->xres || 0==var->yres || var->xres<16 || + 0==xsize || 0==ysize || xsize<16 || + ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) ) + { + printk(">>>>>> win0fb_check_var fail 1!!! \n"); + printk("0==%d || 0==%d || 0==%d || 0==%d || %d<16 \n ||0==%d || 0==%d || %d<16 ||((16!=%d)&&(32!=%d)) \n", + var->xres_virtual, var->yres_virtual, var->xres, var->yres, var->xres, xsize, ysize, xsize, + var->bits_per_pixel, var->bits_per_pixel); + return -EINVAL; + } + + if( (var->xoffset+var->xres)>var->xres_virtual || + (var->yoffset+var->yres)>var->yres_virtual || + (xpos+xsize)>xlcd || (ypos+ysize)>ylcd ) + { + printk(">>>>>> win0fb_check_var fail 2!!! \n"); + printk("(%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d || (%d+%d)>%d \n ", + var->xoffset, var->xres, var->xres_virtual, var->yoffset, var->yres, + var->yres_virtual, xpos, xsize, xlcd, ypos, ysize, ylcd); + return -EINVAL; + } + + switch(var->nonstd&0x0f) + { + case 0: // rgb + switch(var->bits_per_pixel) { - if(inf->cur_screen->standby) inf->cur_screen->standby(1); - // operate the display_on pin to power down the lcd - if(SCREEN_RGB==inf->cur_screen->type || SCREEN_MCU==inf->cur_screen->type) - { - if(mach_info && mach_info->disp_on_pin) - { - display_on = mach_info->disp_on_pin; - display_on_pol = mach_info->disp_on_value; - gpio_direction_output(display_on, 0); - gpio_set_value(display_on, !display_on_pol); - } + case 16: // rgb565 + var->xres_virtual = (var->xres_virtual + 0x1) & (~0x1); + var->xres = (var->xres + 0x1) & (~0x1); + var->xoffset = (var->xoffset) & (~0x1); + break; + default: // rgb888 + var->bits_per_pixel = 32; + break; + } + var->nonstd &= ~0xc0; //not support I2P in this format + break; + case 1: // yuv422 + var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); + var->xres = (var->xres + 0x3) & (~0x3); + var->xoffset = (var->xoffset) & (~0x3); + break; + case 2: // yuv4200 + var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); + var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1); + var->xres = (var->xres + 0x3) & (~0x3); + var->yres = (var->yres + 0x1) & (~0x1); + var->xoffset = (var->xoffset) & (~0x3); + var->yoffset = (var->yoffset) & (~0x1); + break; + case 3: // yuv4201 + var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); + var->yres_virtual = (var->yres_virtual + 0x1) & (~0x1); + var->xres = (var->xres + 0x3) & (~0x3); + var->yres = (var->yres + 0x1) & (~0x1); + var->xoffset = (var->xoffset) & (~0x3); + var->yoffset = (var->yoffset) & (~0x1); + var->nonstd &= ~0xc0; //not support I2P in this format + break; + case 4: // none + case 5: // yuv444 + var->xres_virtual = (var->xres_virtual + 0x3) & (~0x3); + var->xres = (var->xres + 0x3) & (~0x3); + var->xoffset = (var->xoffset) & (~0x3); + var->nonstd &= ~0xc0; //not support I2P in this format + break; + default: + printk(">>>>>> fb1 var->nonstd=%d is invalid! \n", var->nonstd); + return -EINVAL; + } + + yres = var->yres; + + ScaleYRGBY = CalScaleW0(yres, ysize); + + if((ScaleYRGBY>0x8000) || (ScaleYRGBY<0x200)) + { + return -EINVAL; // multiple of scale down or scale up can't exceed 8 + } + + return 0; +} + +static int fb1_set_par(struct fb_info *info) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct rk29fb_screen *screen = inf->cur_screen; + struct fb_var_screeninfo *var = &info->var; + struct fb_fix_screeninfo *fix = &info->fix; + struct win0_par *par = info->par; + + u8 format = 0; + u32 cblen=0, crlen=0, map_size=0, smem_len=0; + + u32 xact = var->xres; /* visible resolution */ + u32 yact = var->yres; + u32 xvir = var->xres_virtual; /* virtual resolution */ + u32 yvir = var->yres_virtual; + u32 xact_st = var->xoffset; /* offset from virtual to visible */ + u32 yact_st = var->yoffset; /* resolution */ + + u16 xpos = (var->nonstd>>8) & 0xfff; //visiable pos in panel + u16 ypos = (var->nonstd>>20) & 0xfff; + u16 xsize = (var->grayscale>>8) & 0xfff; //visiable size in panel + u16 ysize = (var->grayscale>>20) & 0xfff; + + u32 ScaleYrgbX=0x1000,ScaleYrgbY=0x1000; + u32 ScaleCbrX=0x1000, ScaleCbrY=0x1000; + + u8 data_format = var->nonstd&0x0f; + u32 win0_en = var->reserved[2]; + u32 y_addr = var->reserved[3]; //user alloc buf addr y + u32 uv_addr = var->reserved[4]; + + fbprintk(">>>>>> %s : %s\n", __FILE__, __FUNCTION__); + + CHK_SUSPEND(inf); + + xpos = (xpos * screen->x_res) / inf->panel1_info.x_res; + ypos = (ypos * screen->y_res) / inf->panel1_info.y_res; + xsize = (xsize * screen->x_res) / inf->panel1_info.x_res; + ysize = (ysize * screen->y_res) / inf->panel1_info.y_res; + + /* calculate y_offset,uv_offset,line_length,cblen and crlen */ + switch (data_format) + { + case 0: // rgb + switch(var->bits_per_pixel) + { + case 16: // rgb565 + format = 1; + fix->line_length = 2 * xvir; + par->y_offset = (yact_st*xvir + xact_st)*2; + break; + case 32: // rgb888 + format = 0; + fix->line_length = 4 * xvir; + par->y_offset = (yact_st*xvir + xact_st)*4; + break; + default: + return -EINVAL; + } + break; + case 1: // yuv422 + format = 2; + fix->line_length = xvir; + cblen = crlen = (xvir*yvir)/2; + par->y_offset = yact_st*xvir + xact_st; + par->uv_offset = yact_st*xvir + xact_st; + break; + case 2: // yuv4200 + format = 3; + fix->line_length = xvir; + cblen = crlen = (xvir*yvir)/4; + + par->y_offset = yact_st*xvir + xact_st; + par->uv_offset = (yact_st/2)*xvir + xact_st; + + break; + case 3: // yuv4201 + format = 4; + fix->line_length = xvir; + par->y_offset = (yact_st/2)*2*xvir + (xact_st)*2; + par->uv_offset = (yact_st/2)*xvir + xact_st; + cblen = crlen = (xvir*yvir)/4; + break; + case 4: // none + case 5: // yuv444 + format = 5; + fix->line_length = xvir; + par->y_offset = yact_st*xvir + xact_st; + par->uv_offset = yact_st*2*xvir + xact_st*2; + cblen = crlen = (xvir*yvir); + break; + default: + return -EINVAL; + } + + smem_len = fix->line_length * yvir + cblen + crlen; + map_size = PAGE_ALIGN(smem_len); + + fix->smem_start = y_addr; + fix->smem_len = smem_len; + fix->mmio_start = uv_addr; + + par->addr_seted = (((-1==(int)y_addr)&&(-1==(int)uv_addr))||((0==(int)y_addr)&&(0==(int)uv_addr))) ? 0 : 1; + fbprintk("buffer alloced by user fix->smem_start = %8x, fix->smem_len = %8x, fix->mmio_start = %8x \n", (u32)fix->smem_start, (u32)fix->smem_len, (u32)fix->mmio_start); + + par->format = format; + par->xpos = xpos; + par->ypos = ypos; + par->xsize = xsize; + par->ysize = ysize; + par->addr_seted = (par->addr_seted && win0_en); + win0_set_par(info); + + return 0; +} + +static int fb1_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct win0_par *par = info->par; + // enable win0 after the win0 addr is seted + par->par_seted = 1; + win0_pan(info); + return 0; +} + +int fb1_open(struct fb_info *info, int user) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct win0_par *par = info->par; + + fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); + + par->par_seted = 0; + par->addr_seted = 0; + inf->video_mode = 1; + + if(par->refcount) { + printk(">>>>>> fb1 has opened! \n"); + return -EACCES; + } else { + par->refcount++; + return 0; + } +} + +int fb1_release(struct fb_info *info, int user) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct win0_par *par = info->par; + struct fb_var_screeninfo *var0 = &info->var; + + fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); + + if(par->refcount) { + par->refcount--; + inf->video_mode = 0; + + win1_blank(FB_BLANK_POWERDOWN, info); + // wait for lcdc stop access memory + msleep(50); + + // unmap memory + info->screen_base = 0; + info->fix.smem_start = 0; + info->fix.smem_len = 0; + // clean the var param + memset(var0, 0, sizeof(struct fb_var_screeninfo)); + } + + return 0; +} + +static int fb1_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + struct rk29fb_inf *inf = dev_get_drvdata(info->device); + struct win0_par *par = info->par; + void __user *argp = (void __user *)arg; + + fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); + fbprintk("win0fb_ioctl cmd = %8x, arg = %8x \n", (u32)cmd, (u32)arg); + + CHK_SUSPEND(inf); + + switch(cmd) + { + case FB1_IOCTL_GET_PANEL_SIZE: //get panel size + { + u32 panel_size[2]; + if(inf->fb1->var.rotate == 270) { + panel_size[0] = inf->cur_screen->y_res; + panel_size[1] = inf->cur_screen->x_res; + } else { + panel_size[0] = inf->cur_screen->x_res; + panel_size[1] = inf->cur_screen->y_res; } + + if(copy_to_user(argp, panel_size, 8)) return -EFAULT; } + break; - /* Load the new device's param */ - switch(arg) + case FB1_IOCTL_SET_YUV_ADDR: //set y&uv address to register direct { - case 0: inf->cur_screen = &inf->lcd_info; break; //lcd - case 1: inf->cur_screen = &inf->tv_info[0]; break; //tv ntsc cvbs - case 2: inf->cur_screen = &inf->tv_info[1]; break; //tv pal cvbs - case 3: inf->cur_screen = &inf->tv_info[2]; break; //tv 480 ypbpr - case 4: inf->cur_screen = &inf->tv_info[3]; break; //tv 576 ypbpr - case 5: inf->cur_screen = &inf->tv_info[4]; break; //tv 720 ypbpr - case 6: inf->cur_screen = &inf->hdmi_info[0]; break; //hdmi 576 - case 7: inf->cur_screen = &inf->hdmi_info[1]; break; //hdmi 720 - default: break; + u32 yuv_phy[2]; + if (copy_from_user(yuv_phy, argp, 8)) + return -EFAULT; + + yuv_phy[0] += par->y_offset; + yuv_phy[1] += par->uv_offset; + + LcdWrReg(inf, WIN0_YRGB_MST, yuv_phy[0]); + LcdWrReg(inf, WIN0_CBR_MST, yuv_phy[1]); + LcdWrReg(inf, REG_CFG_DONE, 0x01); + // enable win0 after the win0 par is seted + par->addr_seted = 1; + if(par->par_seted) { + LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(1)); + mcu_refresh(inf); + } } - load_screen(info, 0); - mcu_refresh(inf); + break; + + case FB1_IOCTL_SET_ROTATE: //change MCU panel scan direction + fbprintk(">>>>>> change lcdc direction(%d) \n", (int)arg); + return -1; break; default: break; @@ -1554,14 +1595,28 @@ static int win1fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar return 0; } +static struct fb_ops fb1_ops = { + .owner = THIS_MODULE, + .fb_open = fb1_open, + .fb_release = fb1_release, + .fb_check_var = fb1_check_var, + .fb_set_par = fb1_set_par, + .fb_blank = fb1_blank, + .fb_pan_display = fb1_pan_display, + .fb_ioctl = fb1_ioctl, + .fb_setcolreg = fb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; -static struct fb_ops win1fb_ops = { +static struct fb_ops fb0_ops = { .owner = THIS_MODULE, - .fb_check_var = win1fb_check_var, - .fb_set_par = win1fb_set_par, - .fb_blank = win1fb_blank, - .fb_pan_display = win1fb_pan_display, - .fb_ioctl = win1fb_ioctl, + .fb_check_var = fb0_check_var, + .fb_set_par = fb0_set_par, + .fb_blank = fb0_blank, + .fb_pan_display = fb0_pan_display, + .fb_ioctl = fb0_ioctl, .fb_setcolreg = fb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -1569,6 +1624,41 @@ static struct fb_ops win1fb_ops = { //.fb_cursor = rk29_set_cursor, }; +/* +enable: 1, switch to tv or hdmi; 0, switch to lcd +*/ +int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ) +{ + struct rk29fb_inf *inf = platform_get_drvdata(g_pdev); + // struct rk29fb_info *mach_info = g_pdev->dev.platform_data; + + memcpy(&inf->panel2_info, screen, sizeof( struct rk29fb_screen )); + + if(enable)inf->cur_screen = &inf->panel2_info; + else inf->cur_screen = &inf->panel1_info; + + /* Black out, because some display device need clock to standby */ + //LcdMskReg(inf, DSP_CTRL_REG1, m_BLACK_OUT, v_BLACK_OUT(1)); + // LcdMskReg(inf, SYS_CONFIG, m_W0_ENABLE, v_W0_ENABLE(0)); + // LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE, v_W1_ENABLE(0)); + LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(1)); + LcdWrReg(inf, REG_CFG_DONE, 0x01); + msleep(20); + + if(inf->cur_screen->standby) inf->cur_screen->standby(1); + // operate the display_on pin to power down the lcd + set_lcd_pin(g_pdev, (enable==0)); + + load_screen(inf->fb0, 0); + mcu_refresh(inf); + + fb1_set_par(inf->fb1); + fb0_set_par(inf->fb0); + LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(0)); + LcdWrReg(inf, REG_CFG_DONE, 0x01); + + return 0; +} static irqreturn_t rk29fb_irq(int irq, void *dev_id) { @@ -1616,10 +1706,6 @@ static irqreturn_t rk29fb_irq(int irq, void *dev_id) } } -#if ANDROID_USE_THREE_BUFS - new_frame_seted = 1; -#endif - wq_condition = 1; wake_up_interruptible(&wq); @@ -1750,10 +1836,8 @@ static int __init rk29fb_probe (struct platform_device *pdev) mach_info = pdev->dev.platform_data; /* Fill screen info and set current screen */ fbprintk(">> Fill screen info and set current screen \n"); - set_lcd_info(&inf->lcd_info, mach_info->lcd_info); - set_tv_info(&inf->tv_info[0]); - set_hdmi_info(&inf->hdmi_info[0]); - inf->cur_screen = &inf->lcd_info; + set_lcd_info(&inf->panel1_info, mach_info->lcd_info); + inf->cur_screen = &inf->panel1_info; screen = inf->cur_screen; if(SCREEN_NULL==screen->type) { @@ -1792,59 +1876,59 @@ static int __init rk29fb_probe (struct platform_device *pdev) /* Prepare win1 info */ fbprintk(">> Prepare win1 info \n"); - inf->win1fb = framebuffer_alloc(sizeof(struct win1_par), &pdev->dev); - if(!inf->win1fb) + inf->fb0 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev); + if(!inf->fb0) { - dev_err(&pdev->dev, ">> win1fb framebuffer_alloc fail!"); - inf->win1fb = NULL; + dev_err(&pdev->dev, ">> fb0 framebuffer_alloc fail!"); + inf->fb0 = NULL; ret = -ENOMEM; goto release_win1fb; } - strcpy(inf->win1fb->fix.id, "win1fb"); - inf->win1fb->fix.type = FB_TYPE_PACKED_PIXELS; - inf->win1fb->fix.type_aux = 0; - inf->win1fb->fix.xpanstep = 1; - inf->win1fb->fix.ypanstep = 1; - inf->win1fb->fix.ywrapstep = 0; - inf->win1fb->fix.accel = FB_ACCEL_NONE; - inf->win1fb->fix.visual = FB_VISUAL_TRUECOLOR; - inf->win1fb->fix.smem_len = 0; - inf->win1fb->fix.line_length = 0; - inf->win1fb->fix.smem_start = 0; - - inf->win1fb->var.xres = screen->x_res; - inf->win1fb->var.yres = screen->y_res; - inf->win1fb->var.bits_per_pixel = 16; - inf->win1fb->var.xres_virtual = screen->x_res; - inf->win1fb->var.yres_virtual = screen->y_res; - inf->win1fb->var.width = screen->width; - inf->win1fb->var.height = screen->height; - inf->win1fb->var.pixclock = screen->pixclock; - inf->win1fb->var.left_margin = screen->left_margin; - inf->win1fb->var.right_margin = screen->right_margin; - inf->win1fb->var.upper_margin = screen->upper_margin; - inf->win1fb->var.lower_margin = screen->lower_margin; - inf->win1fb->var.vsync_len = screen->vsync_len; - inf->win1fb->var.hsync_len = screen->hsync_len; - inf->win1fb->var.red = def_rgb_16.red; - inf->win1fb->var.green = def_rgb_16.green; - inf->win1fb->var.blue = def_rgb_16.blue; - inf->win1fb->var.transp = def_rgb_16.transp; - - inf->win1fb->var.nonstd = 0; //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format) - inf->win1fb->var.grayscale = 0; //win1 transprent mode & value(mode<<8 + value) - inf->win1fb->var.activate = FB_ACTIVATE_NOW; - inf->win1fb->var.accel_flags = 0; - inf->win1fb->var.vmode = FB_VMODE_NONINTERLACED; - - inf->win1fb->fbops = &win1fb_ops; - inf->win1fb->flags = FBINFO_FLAG_DEFAULT; - inf->win1fb->pseudo_palette = ((struct win1_par*)inf->win1fb->par)->pseudo_pal; - inf->win1fb->screen_base = 0; - - memset(inf->win1fb->par, 0, sizeof(struct win1_par)); - ret = fb_alloc_cmap(&inf->win1fb->cmap, 256, 0); + strcpy(inf->fb0->fix.id, "fb0"); + inf->fb0->fix.type = FB_TYPE_PACKED_PIXELS; + inf->fb0->fix.type_aux = 0; + inf->fb0->fix.xpanstep = 1; + inf->fb0->fix.ypanstep = 1; + inf->fb0->fix.ywrapstep = 0; + inf->fb0->fix.accel = FB_ACCEL_NONE; + inf->fb0->fix.visual = FB_VISUAL_TRUECOLOR; + inf->fb0->fix.smem_len = 0; + inf->fb0->fix.line_length = 0; + inf->fb0->fix.smem_start = 0; + + inf->fb0->var.xres = screen->x_res; + inf->fb0->var.yres = screen->y_res; + inf->fb0->var.bits_per_pixel = 16; + inf->fb0->var.xres_virtual = screen->x_res; + inf->fb0->var.yres_virtual = screen->y_res; + inf->fb0->var.width = screen->width; + inf->fb0->var.height = screen->height; + inf->fb0->var.pixclock = screen->pixclock; + inf->fb0->var.left_margin = screen->left_margin; + inf->fb0->var.right_margin = screen->right_margin; + inf->fb0->var.upper_margin = screen->upper_margin; + inf->fb0->var.lower_margin = screen->lower_margin; + inf->fb0->var.vsync_len = screen->vsync_len; + inf->fb0->var.hsync_len = screen->hsync_len; + inf->fb0->var.red = def_rgb_16.red; + inf->fb0->var.green = def_rgb_16.green; + inf->fb0->var.blue = def_rgb_16.blue; + inf->fb0->var.transp = def_rgb_16.transp; + + inf->fb0->var.nonstd = 0; //win1 format & ypos & xpos (ypos<<20 + xpos<<8 + format) + inf->fb0->var.grayscale = 0; //win1 transprent mode & value(mode<<8 + value) + inf->fb0->var.activate = FB_ACTIVATE_NOW; + inf->fb0->var.accel_flags = 0; + inf->fb0->var.vmode = FB_VMODE_NONINTERLACED; + + inf->fb0->fbops = &fb0_ops; + inf->fb0->flags = FBINFO_FLAG_DEFAULT; + inf->fb0->pseudo_palette = ((struct win0_par*)inf->fb0->par)->pseudo_pal; + inf->fb0->screen_base = 0; + + memset(inf->fb0->par, 0, sizeof(struct win0_par)); + ret = fb_alloc_cmap(&inf->fb0->cmap, 256, 0); if (ret < 0) goto release_cmap; @@ -1856,70 +1940,70 @@ static int __init rk29fb_probe (struct platform_device *pdev) ret = -ENOENT; goto release_win1fb; } - inf->win1fb->fix.smem_start = res->start; - inf->win1fb->fix.smem_len = res->end - res->start; - inf->win1fb->screen_base = ioremap(res->start, inf->win1fb->fix.smem_len); - memset(inf->win1fb->screen_base, 0, inf->win1fb->fix.smem_len); + inf->fb0->fix.smem_start = res->start; + inf->fb0->fix.smem_len = res->end - res->start; + inf->fb0->screen_base = ioremap(res->start, inf->fb0->fix.smem_len); + memset(inf->fb0->screen_base, 0, inf->fb0->fix.smem_len); /* Prepare win0 info */ fbprintk(">> Prepare win0 info \n"); - inf->win0fb = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev); - if(!inf->win0fb) + inf->fb1 = framebuffer_alloc(sizeof(struct win0_par), &pdev->dev); + if(!inf->fb1) { - dev_err(&pdev->dev, ">> win0fb framebuffer_alloc fail!"); - inf->win0fb = NULL; + dev_err(&pdev->dev, ">> fb1 framebuffer_alloc fail!"); + inf->fb1 = NULL; ret = -ENOMEM; goto release_win0fb; } - strcpy(inf->win0fb->fix.id, "win0fb"); - inf->win0fb->fix.type = FB_TYPE_PACKED_PIXELS; - inf->win0fb->fix.type_aux = 0; - inf->win0fb->fix.xpanstep = 1; - inf->win0fb->fix.ypanstep = 1; - inf->win0fb->fix.ywrapstep = 0; - inf->win0fb->fix.accel = FB_ACCEL_NONE; - inf->win0fb->fix.visual = FB_VISUAL_TRUECOLOR; - inf->win0fb->fix.smem_len = 0; - inf->win0fb->fix.line_length = 0; - inf->win0fb->fix.smem_start = 0; - - inf->win0fb->var.xres = screen->x_res; - inf->win0fb->var.yres = screen->y_res; - inf->win0fb->var.bits_per_pixel = 16; - inf->win0fb->var.xres_virtual = screen->x_res; - inf->win0fb->var.yres_virtual = screen->y_res; - inf->win0fb->var.width = screen->width; - inf->win0fb->var.height = screen->height; - inf->win0fb->var.pixclock = screen->pixclock; - inf->win0fb->var.left_margin = screen->left_margin; - inf->win0fb->var.right_margin = screen->right_margin; - inf->win0fb->var.upper_margin = screen->upper_margin; - inf->win0fb->var.lower_margin = screen->lower_margin; - inf->win0fb->var.vsync_len = screen->vsync_len; - inf->win0fb->var.hsync_len = screen->hsync_len; - inf->win0fb->var.red = def_rgb_16.red; - inf->win0fb->var.green = def_rgb_16.green; - inf->win0fb->var.blue = def_rgb_16.blue; - inf->win0fb->var.transp = def_rgb_16.transp; - - inf->win0fb->var.nonstd = 0; //win0 format & ypos & xpos (ypos<<20 + xpos<<8 + format) - inf->win0fb->var.grayscale = ((inf->win0fb->var.yres<<20)&0xfff00000) + ((inf->win0fb->var.xres<<8)&0xfff00);//win0 xsize & ysize - inf->win0fb->var.activate = FB_ACTIVATE_NOW; - inf->win0fb->var.accel_flags = 0; - inf->win0fb->var.vmode = FB_VMODE_NONINTERLACED; - - inf->win0fb->fbops = &win0fb_ops; - inf->win0fb->flags = FBINFO_FLAG_DEFAULT; - inf->win0fb->pseudo_palette = ((struct win0_par*)inf->win0fb->par)->pseudo_pal; - inf->win0fb->screen_base = 0; - - memset(inf->win0fb->par, 0, sizeof(struct win0_par)); + strcpy(inf->fb1->fix.id, "fb1"); + inf->fb1->fix.type = FB_TYPE_PACKED_PIXELS; + inf->fb1->fix.type_aux = 0; + inf->fb1->fix.xpanstep = 1; + inf->fb1->fix.ypanstep = 1; + inf->fb1->fix.ywrapstep = 0; + inf->fb1->fix.accel = FB_ACCEL_NONE; + inf->fb1->fix.visual = FB_VISUAL_TRUECOLOR; + inf->fb1->fix.smem_len = 0; + inf->fb1->fix.line_length = 0; + inf->fb1->fix.smem_start = 0; + + inf->fb1->var.xres = screen->x_res; + inf->fb1->var.yres = screen->y_res; + inf->fb1->var.bits_per_pixel = 16; + inf->fb1->var.xres_virtual = screen->x_res; + inf->fb1->var.yres_virtual = screen->y_res; + inf->fb1->var.width = screen->width; + inf->fb1->var.height = screen->height; + inf->fb1->var.pixclock = screen->pixclock; + inf->fb1->var.left_margin = screen->left_margin; + inf->fb1->var.right_margin = screen->right_margin; + inf->fb1->var.upper_margin = screen->upper_margin; + inf->fb1->var.lower_margin = screen->lower_margin; + inf->fb1->var.vsync_len = screen->vsync_len; + inf->fb1->var.hsync_len = screen->hsync_len; + inf->fb1->var.red = def_rgb_16.red; + inf->fb1->var.green = def_rgb_16.green; + inf->fb1->var.blue = def_rgb_16.blue; + inf->fb1->var.transp = def_rgb_16.transp; + + inf->fb1->var.nonstd = 0; //win0 format & ypos & xpos (ypos<<20 + xpos<<8 + format) + inf->fb1->var.grayscale = ((inf->fb1->var.yres<<20)&0xfff00000) + ((inf->fb1->var.xres<<8)&0xfff00);//win0 xsize & ysize + inf->fb1->var.activate = FB_ACTIVATE_NOW; + inf->fb1->var.accel_flags = 0; + inf->fb1->var.vmode = FB_VMODE_NONINTERLACED; + + inf->fb1->fbops = &fb1_ops; + inf->fb1->flags = FBINFO_FLAG_DEFAULT; + inf->fb1->pseudo_palette = ((struct win0_par*)inf->fb1->par)->pseudo_pal; + inf->fb1->screen_base = 0; + + memset(inf->fb1->par, 0, sizeof(struct win0_par)); /* Init all lcdc and lcd before register_framebuffer. */ /* because after register_framebuffer, the win1fb_check_par and winfb_set_par execute immediately */ fbprintk(">> Init all lcdc and lcd before register_framebuffer \n"); - init_lcdc(inf->win1fb); + init_lcdc(inf->fb0); #ifdef CONFIG_CPU_FREQ // inf->freq_transition.notifier_call = rk29fb_freq_transition; @@ -1930,13 +2014,11 @@ static int __init rk29fb_probe (struct platform_device *pdev) if(mach_info) { struct rk29_fb_setting_info fb_setting; - if( OUT_P888==inf->lcd_info.face || - OUT_P888==inf->tv_info[0].face || - OUT_P888==inf->hdmi_info[0].face ) // set lcdc iomux + if( OUT_P888==inf->cur_screen->face ) // set lcdc iomux { fb_setting.data_num = 24; } - else if(OUT_P666 == inf->lcd_info.face ) + else if(OUT_P666 == inf->cur_screen->face ) { fb_setting.data_num = 18; } @@ -1948,7 +2030,7 @@ static int __init rk29fb_probe (struct platform_device *pdev) fb_setting.vsync_en = 1; fb_setting.disp_on_en = 1; fb_setting.standby_en = 1; - if( inf->lcd_info.mcu_usefmk ) + if( inf->cur_screen->mcu_usefmk ) fb_setting.mcu_fmk_en =1; mach_info->io_init(&fb_setting); } @@ -1958,23 +2040,23 @@ static int __init rk29fb_probe (struct platform_device *pdev) g_pdev = pdev; inf->mcu_usetimer = 1; inf->mcu_fmksync = 0; - load_screen(inf->win1fb, 1); + load_screen(inf->fb0, 1); - /* Register framebuffer(win1fb & win0fb) */ - fbprintk(">> Register framebuffer(win1fb) \n"); - ret = register_framebuffer(inf->win1fb); + /* Register framebuffer(fb0 & fb1) */ + fbprintk(">> Register framebuffer(fb0) \n"); + ret = register_framebuffer(inf->fb0); if(ret<0) { - printk(">> win1fb register_framebuffer fail!\n"); + printk(">> fb0 register_framebuffer fail!\n"); ret = -EINVAL; goto release_win0fb; } - fbprintk(">> Register framebuffer(win0fb) \n"); + fbprintk(">> Register framebuffer(fb1) \n"); - ret = register_framebuffer(inf->win0fb); + ret = register_framebuffer(inf->fb1); if(ret<0) { - printk(">> win0fb register_framebuffer fail!\n"); + printk(">> fb1 register_framebuffer fail!\n"); ret = -EINVAL; goto unregister_win1fb; } @@ -1999,7 +2081,7 @@ static int __init rk29fb_probe (struct platform_device *pdev) goto release_irq; } - if( inf->lcd_info.mcu_usefmk && (mach_info->mcu_fmk_pin != -1) ) + if( inf->cur_screen->mcu_usefmk && (mach_info->mcu_fmk_pin != -1) ) { ret = request_irq(gpio_to_irq(mach_info->mcu_fmk_pin), mcu_irqfmk, GPIOEdgelFalling, pdev->name, pdev); if (ret) @@ -2017,18 +2099,18 @@ release_irq: if(irq>=0) free_irq(irq, pdev); unregister_win1fb: - unregister_framebuffer(inf->win1fb); + unregister_framebuffer(inf->fb0); release_win0fb: - if(inf->win0fb) - framebuffer_release(inf->win0fb); - inf->win0fb = NULL; + if(inf->fb1) + framebuffer_release(inf->fb1); + inf->fb1 = NULL; release_cmap: - if(&inf->win1fb->cmap) - fb_dealloc_cmap(&inf->win1fb->cmap); + if(&inf->fb0->cmap) + fb_dealloc_cmap(&inf->fb0->cmap); release_win1fb: - if(inf->win1fb) - framebuffer_release(inf->win1fb); - inf->win1fb = NULL; + if(inf->fb0) + framebuffer_release(inf->fb0); + inf->fb0 = NULL; release_drvdata: if(inf && inf->reg_vir_base) iounmap(inf->reg_vir_base); @@ -2070,41 +2152,41 @@ static int rk29fb_remove(struct platform_device *pdev) set_lcd_pin(pdev, 0); // blank the lcdc - if(inf->win0fb) - win0fb_blank(FB_BLANK_POWERDOWN, inf->win0fb); - if(inf->win1fb) - win1fb_blank(FB_BLANK_POWERDOWN, inf->win1fb); + if(inf->fb1) + fb1_blank(FB_BLANK_POWERDOWN, inf->fb1); + if(inf->fb0) + fb0_blank(FB_BLANK_POWERDOWN, inf->fb0); // suspend the lcdc //rk29fb_suspend(pdev, msg); // unmap memory and release framebuffer - if(inf->win0fb) { - info = inf->win0fb; + if(inf->fb1) { + info = inf->fb1; if (info->screen_base) { //dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start); info->screen_base = 0; info->fix.smem_start = 0; info->fix.smem_len = 0; } - unregister_framebuffer(inf->win0fb); - framebuffer_release(inf->win0fb); - inf->win0fb = NULL; + unregister_framebuffer(inf->fb1); + framebuffer_release(inf->fb1); + inf->fb1 = NULL; } - if(inf->win1fb) { - info = inf->win1fb; + if(inf->fb0) { + info = inf->fb0; if (info->screen_base) { // dma_free_writecombine(NULL, PAGE_ALIGN(info->fix.smem_len),info->screen_base, info->fix.smem_start); info->screen_base = 0; info->fix.smem_start = 0; info->fix.smem_len = 0; } - unregister_framebuffer(inf->win1fb); - framebuffer_release(inf->win1fb); - inf->win1fb = NULL; + unregister_framebuffer(inf->fb0); + framebuffer_release(inf->fb0); + inf->fb0 = NULL; } #ifdef CONFIG_CPU_FREQ - cpufreq_unregister_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + // cpufreq_unregister_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); #endif if (inf->clk) diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h new file mode 100755 index 000000000000..648ed8d84ebb --- /dev/null +++ b/include/linux/hdmi.h @@ -0,0 +1,70 @@ +/* include/linux/hdmi.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#ifndef __LINUX_HDMI_CORE_H +#define __LINUX_HDMI_CORE_H + +#include +#include +#include + +#ifdef CONFIG_HDMI_DEBUG +#define hdmi_dbg(dev, format, arg...) \ + dev_printk(KERN_INFO , dev , format , ## arg) +#else +#define hdmi_dbg(dev, format, arg...) +#endif + + + +typedef int BOOL; + +#define TRUE 1 +#define FALSE 0 + +#define HDMI_1280x720p_50Hz 0 +#define HDMI_1280x720p_60Hz 1 +#define HDMI_720x576p_50Hz 2 + +#define HDMI_MAX_ID 32 + + +struct hdmi { + struct device *dev; + struct work_struct changed_work; + int id; + BOOL display_on; + BOOL plug; + BOOL auto_switch; + BOOL hdcp_on; + BOOL param_conf; + + u8 resolution; + u8 audio_fs; + + void *priv; + + int (*hdmi_display_on)(struct hdmi *); + int (*hdmi_display_off)(struct hdmi *); + int (*hdmi_set_param)(struct hdmi *); + int (*hdmi_core_init)(struct hdmi *); +}; + +extern void *hdmi_get_privdata(struct hdmi *hdmi); +extern void hdmi_set_privdata(struct hdmi *hdmi, void *data); +extern int hdmi_register(struct device *parent, struct hdmi *hdmi); +extern void hdmi_unregister(struct hdmi *hdmi); +extern void hdmi_changed(struct hdmi *hdmi, int plug); + +extern int hdmi_codec_set_audio_fs(unsigned char audio_fs); +extern int hdmi_fb_set_resolution(unsigned char resolution); + +extern int hdmi_switch_fb(int resolution, int type); + + +#endif -- 2.34.1