From: yzq Date: Wed, 28 Mar 2012 03:09:59 +0000 (-0700) Subject: rk610 hdmi lcd lvds tvout codec support X-Git-Tag: firefly_0821_release~9556 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cbba37b0bbb959a5229e677cf0b8780cce927128;p=firefly-linux-kernel-4.4.55.git rk610 hdmi lcd lvds tvout codec support --- diff --git a/arch/arm/mach-rk29/board-rk29-ddr3sdk.c b/arch/arm/mach-rk29/board-rk29-ddr3sdk.c index 4bae125b8657..0fbcc942a229 100755 --- a/arch/arm/mach-rk29/board-rk29-ddr3sdk.c +++ b/arch/arm/mach-rk29/board-rk29-ddr3sdk.c @@ -1705,6 +1705,35 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = { .platform_data = &bu92747guw_pdata, }, #endif +#ifdef CONFIG_MFD_RK610 + { + .type = "rk610_ctl", + .addr = 0x40, + .flags = 0, + }, +#endif +#ifdef CONFIG_RK610_TVOUT + { + .type = "rk610_tvout", + .addr = 0x42, + .flags = 0, + }, +#endif +#ifdef CONFIG_RK610_HDMI + { + .type = "rk610_hdmi", + .addr = 0x46, + .flags = 0, + .irq = RK29_PIN1_PD7, + }, +#endif +#ifdef CONFIG_SND_SOC_RK610 + { + .type = "rk610_i2c_codec", + .addr = 0x60, + .flags = 0, + }, +#endif }; #endif diff --git a/arch/arm/mach-rk29/clock.c b/arch/arm/mach-rk29/clock.c index d88ad3ac6ca7..f9fdc9985bd2 100755 --- a/arch/arm/mach-rk29/clock.c +++ b/arch/arm/mach-rk29/clock.c @@ -626,8 +626,8 @@ static const struct codec_pll_set codec_pll[] = { // rate parent band NR NF NO CODEC_PLL(108000, 24, LOW, 1, 18, 4), // for TV CODEC_PLL(648000, 24, HIGH, 1, 27, 1), - CODEC_PLL(148500, 27, LOW, 1, 22, 4), // for HDMI - CODEC_PLL(297000, 27, LOW, 1, 22, 2), + CODEC_PLL(148500, 27, LOW, 2, 88, 8), //change for jetta hdmi dclk jitter 20120322// for HDMI + CODEC_PLL(297000, 27, LOW, 2, 88, 4), //change for jetta hdmi dclk jitter 20120322// for HDMI CODEC_PLL(445500, 27, LOW, 2, 33, 1), CODEC_PLL(594000, 27, HIGH, 1, 22, 1), CODEC_PLL(891000, 27, HIGH, 1, 33, 1), diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b91fe3180fd6..af404a902e2f 100755 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -742,6 +742,13 @@ config MFD_TPS65910 config TPS65911_COMPARATOR tristate +config MFD_RK610 + bool "RK610(Jetta) Multimedia support" + depends on I2C=y && GPIOLIB + select MFD_CORE + help + if you say yes here you get support for the RK610, with func as + HDMI LCD LVDS TVOUT CODEC. endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 670e4c0fca63..d0188cbcf8d3 100755 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -96,3 +96,4 @@ obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o +obj-$(CONFIG_MFD_RK610) += rk610-core.o \ No newline at end of file diff --git a/drivers/mfd/rk610-core.c b/drivers/mfd/rk610-core.c new file mode 100644 index 000000000000..93e24d65c816 --- /dev/null +++ b/drivers/mfd/rk610-core.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RK610_RESET_PIN RK29_PIN6_PC1 + +static struct i2c_client *rk610_control_client = NULL; +#ifdef CONFIG_RK610_LCD +extern int rk610_lcd_init(struct i2c_client *client); +#else +int rk610_lcd_init(struct i2c_client *client){} +#endif +int rk610_control_send_byte(const char reg, const char data) +{ + int ret; + + printk("reg = 0x%02x, val=0x%02x\n", reg ,data); + + if(rk610_control_client == NULL) + return -1; + //i2c_master_reg8_send + ret = i2c_master_reg8_send(rk610_control_client, reg, &data, 1, 100*1000); + if (ret > 0) + ret = 0; + + return ret; +} + +#ifdef CONFIG_SND_SOC_RK610 +static unsigned int current_pll_value = 0; +int rk610_codec_pll_set(unsigned int rate) +{ + char N, M, NO, DIV; + unsigned int F; + char data; + + if(current_pll_value == rate) + return 0; + + // Input clock is 12MHz. + if(rate == 11289600) { + // For 11.2896MHz, N = 2 M= 75 F = 0.264(0x43958) NO = 8 + N = 2; + NO = 3; + M = 75; + F = 0x43958; + DIV = 5; + } + else if(rate == 12288000) { + // For 12.2888MHz, N = 2 M= 75 F = 0.92(0xEB851) NO = 8 + N = 2; + NO = 3; + M = 75; + F = 0xEB851; + DIV = 5; + } + else { + printk(KERN_ERR "[%s] not support such frequency\n", __FUNCTION__); + return -1; + } + + //Enable codec pll fractional number and power down. + data = 0x00; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data); + msleep(10); + + data = (N << 4) | NO; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON0, data); + // M + data = M; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON1, data); + // F + data = F & 0xFF; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON2, data); + data = (F >> 8) & 0xFF; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON3, data); + data = (F >> 16) & 0xFF; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON4, data); + + // i2s mclk = codec_pll/5; + i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000); + data &= ~CLOCK_CON1_I2S_DVIDER_MASK; + data |= (DIV - 1); + rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data); + + // Power up codec pll. + data |= C_PLL_POWER_ON; + rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data); + + current_pll_value = rate; + printk(KERN_ERR "[%s] rate %u\n", __FUNCTION__, rate); + + return 0; +} + +void rk610_control_init_codec(void) +{ + struct i2c_client *client = rk610_control_client; + char data = 0; + int ret; + + if(rk610_control_client == NULL) + return; + printk(KERN_ERR "[%s] start\n", __FUNCTION__); + + //gpio_set_value(RK610_RESET_PIN, GPIO_LOW); //reset rk601 + // mdelay(100); + //gpio_set_value(RK610_RESET_PIN, GPIO_HIGH); + //mdelay(100); + + // Set i2c glitch timeout. + data = 0x22; + ret = i2c_master_reg8_send(client, RK610_CONTROL_REG_I2C_CON, &data, 1, 20*1000); + +// rk610_codec_pll_set(11289600); + + //use internal codec, enable DAC ADC LRCK output. +// i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000); +// data = CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE | CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE; +// data = CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE; + data = 0; + rk610_control_send_byte(RK610_CONTROL_REG_CODEC_CON, data); + + // Select internal i2s clock from codec_pll. + i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000); +// data |= CLOCK_CON1_I2S_CLK_CODEC_PLL; + data = 0; + rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data); + + i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000); + printk(KERN_ERR "[%s] RK610_CONTROL_REG_CODEC_CON is %x\n", __FUNCTION__, data); + + i2c_master_reg8_recv(client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000); + printk(KERN_ERR "[%s] RK610_CONTROL_REG_CLOCK_CON1 is %x\n", __FUNCTION__, data); +} +#endif +#ifdef CONFIG_RK610_DEBUG +static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} + +static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} +static ssize_t rk610_show_reg_attrs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + + int i,size=0; + char val; + struct i2c_client *client=rk610_control_client; + + for(i=0;i<256;i++) + { + rk610_read_p0_reg(client, i, &val); + if(i%16==0) + size += sprintf(buf+size,"\n>>>rk610_hdmi %x:",i); + size += sprintf(buf+size," %2x",val); + } + + return size; +} +static ssize_t rk610_store_reg_attrs(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct i2c_client *client=NULL; + static char val=0,reg=0; + client = rk610_control_client; + printk("/**********rk610 reg config******/"); + + sscanf(buf, "%x%x", &val,®); + printk("reg=%x val=%x\n",reg,val); + rk610_write_p0_reg(client, reg, &val); + printk("val=%x\n",val); + return size; +} + +static struct device_attribute rk610_attrs[] = { + __ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs), +}; +#endif +static int rk610_control_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct clk *iis_clk; + + iis_clk = clk_get_sys("rk29_i2s.0", "i2s"); + if (IS_ERR(iis_clk)) { + printk("failed to get i2s clk\n"); + ret = PTR_ERR(iis_clk); + }else{ + printk("got i2s clk ok!\n"); + clk_enable(iis_clk); + clk_set_rate(iis_clk, 11289600); + rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK); + clk_put(iis_clk); + } + + rk610_control_client = client; + msleep(100); + if(RK610_RESET_PIN != INVALID_GPIO) { + ret = gpio_request(RK610_RESET_PIN, "rk610 reset"); + if (ret){ + printk(KERN_ERR "rk610_control_probe request gpio fail\n"); + } + else { + printk(KERN_ERR "rk610_control_probe request gpio ok\n"); + gpio_direction_output(RK610_RESET_PIN, GPIO_HIGH); + msleep(100); + gpio_direction_output(RK610_RESET_PIN, GPIO_LOW); + msleep(100); + gpio_set_value(RK610_RESET_PIN, GPIO_HIGH); + } + } + rk610_lcd_init(client); + #ifdef CONFIG_RK610_DEBUG + device_create_file(&(client->dev), &rk610_attrs[0]); + #endif + return 0; +} + +static int rk610_control_remove(struct i2c_client *client) +{ + return 0; +} + +static const struct i2c_device_id rk610_control_id[] = { + { "rk610_ctl", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rk610_control_id); + +static struct i2c_driver rk610_control_driver = { + .driver = { + .name = "rk610_ctl", + }, + .probe = rk610_control_probe, + .remove = rk610_control_remove, + .id_table = rk610_control_id, +}; + +static int __init rk610_control_init(void) +{ + return i2c_add_driver(&rk610_control_driver); +} + +static void __exit rk610_control_exit(void) +{ + i2c_del_driver(&rk610_control_driver); +} + +fs_initcall(rk610_control_init); +//module_init(rk610_control_init); +module_exit(rk610_control_exit); + + +MODULE_DESCRIPTION("RK610 control driver"); +MODULE_AUTHOR("Rock-chips, "); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig index 1b497d4c64fb..98ea0494b6bb 100644 --- a/drivers/video/display/Kconfig +++ b/drivers/video/display/Kconfig @@ -22,5 +22,8 @@ config DISPLAY_SUPPORT comment "Display hardware drivers" depends on DISPLAY_SUPPORT source "drivers/video/display/screen/Kconfig" +source "drivers/video/display/lcd/Kconfig" +source "drivers/video/display/tve/Kconfig" endmenu + diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile index c7d6d8b6b696..ad3bc7ff7c72 100644 --- a/drivers/video/display/Makefile +++ b/drivers/video/display/Makefile @@ -1,6 +1,8 @@ # Display drivers -display-objs := display-sysfs.o +display-objs := display-sys.o obj-$(CONFIG_DISPLAY_SUPPORT) += display.o obj-$(CONFIG_DISPLAY_SUPPORT) += screen/ +obj-y += lcd/ +obj-y += tve/ \ No newline at end of file diff --git a/drivers/video/display/display-sys.c b/drivers/video/display/display-sys.c new file mode 100644 index 000000000000..3501d40a379c --- /dev/null +++ b/drivers/video/display/display-sys.c @@ -0,0 +1,404 @@ +#include +#include +#include +#include +#include +#include + +static struct list_head display_device_list; + +static ssize_t display_show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name); +} + +static ssize_t display_show_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type); +} + +static ssize_t display_show_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + int enable; + if(dsp->ops && dsp->ops->getenable) + enable = dsp->ops->getenable(dsp); + else + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", enable); +} + +static ssize_t display_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + int enable; + + sscanf(buf, "%d", &enable); + if(dsp->ops && dsp->ops->setenable) + dsp->ops->setenable(dsp, enable); + return size; +} + +static ssize_t display_show_connect(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + int connect; + if(dsp->ops && dsp->ops->getstatus) + connect = dsp->ops->getstatus(dsp); + else + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", connect); +} + +static int mode_string(char *buf, unsigned int offset, + const struct fb_videomode *mode) +{ +// char m = 'U'; + char v = 'p'; + +// if (mode->flag & FB_MODE_IS_DETAILED) +// m = 'D'; +// if (mode->flag & FB_MODE_IS_VESA) +// m = 'V'; +// if (mode->flag & FB_MODE_IS_STANDARD) +// m = 'S'; + + if (mode->vmode & FB_VMODE_INTERLACED) + v = 'i'; + if (mode->vmode & FB_VMODE_DOUBLE) + v = 'd'; + + return snprintf(&buf[offset], PAGE_SIZE - offset, "%dx%d%c-%d\n", + mode->xres, mode->yres, v, mode->refresh); +} +static ssize_t display_show_modes(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + struct list_head *modelist, *pos; + struct fb_modelist *fb_modelist; + const struct fb_videomode *mode; + int i; + if(dsp->ops && dsp->ops->getmodelist) + { + if(dsp->ops->getmodelist(dsp, &modelist)) + return -EINVAL; + } + else + return 0; + + i = 0; + list_for_each(pos, modelist) { + fb_modelist = list_entry(pos, struct fb_modelist, list); + mode = &fb_modelist->mode; + i += mode_string(buf, i, mode); + } + return i; +} + +static ssize_t display_show_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + struct fb_videomode mode; + + if(dsp->ops && dsp->ops->getmode) + if(dsp->ops->getmode(dsp, &mode) == 0) + return mode_string(buf, 0, &mode); + return 0; +} + +static ssize_t display_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + char mstr[100]; + struct list_head *modelist, *pos; + struct fb_modelist *fb_modelist; + struct fb_videomode *mode; + size_t i; + + if(dsp->ops && dsp->ops->getmodelist) + { + if(dsp->ops && dsp->ops->getmodelist) + { + if(dsp->ops->getmodelist(dsp, &modelist)) + return -EINVAL; + } + list_for_each(pos, modelist) { + fb_modelist = list_entry(pos, struct fb_modelist, list); + mode = &fb_modelist->mode; + i = mode_string(mstr, 0, mode); + if (strncmp(mstr, buf, max(count, i)) == 0) { + if(dsp->ops && dsp->ops->setmode) + dsp->ops->setmode(dsp, mode); + return count; + } + } + } + return -EINVAL; +} + +static struct device_attribute display_attrs[] = { + __ATTR(name, S_IRUGO, display_show_name, NULL), + __ATTR(type, S_IRUGO, display_show_type, NULL), + __ATTR(enable, S_IRUGO | /*S_IWUGO*/S_IWUSR, display_show_enable, display_store_enable), + __ATTR(connect, S_IRUGO, display_show_connect, NULL), + __ATTR(modes, S_IRUGO, display_show_modes, NULL), + __ATTR(mode, S_IRUGO | /*S_IWUGO*/S_IWUSR, display_show_mode, display_store_mode) +}; + +static int display_suspend(struct device *dev, pm_message_t state) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + + mutex_lock(&dsp->lock); + if (likely(dsp->driver->suspend)) + dsp->driver->suspend(dsp, state); + mutex_unlock(&dsp->lock); + return 0; +}; + +static int display_resume(struct device *dev) +{ + struct rk_display_device *dsp = dev_get_drvdata(dev); + + mutex_lock(&dsp->lock); + if (likely(dsp->driver->resume)) + dsp->driver->resume(dsp); + mutex_unlock(&dsp->lock); + return 0; +}; + +void rk_display_device_enable(struct rk_display_device *ddev) +{ +#ifndef CONFIG_DISPLAY_AUTO_SWITCH + return; +#else + struct list_head *pos, *head = &display_device_list; + struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL; + int enable = 0,connect, has_connect = 0; + + list_for_each(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + enable = dev->ops->getenable(dev); + connect = dev->ops->getstatus(dev); + if(connect) + dev_enable = dev; + if(enable == 1) + dev_enabled = dev; + } + // If no device is connected, enable highest priority device. + if(dev_enable == NULL) { + dev->ops->setenable(dev, 1); + return; + } + + if(dev_enable == dev_enabled) { + if(dev_enable != ddev) + ddev->ops->setenable(ddev, 0); + } + else { + if(dev_enabled) + dev_enabled->ops->setenable(dev_enabled, 0); + dev_enable->ops->setenable(dev_enable, 1); + } + + +#endif +} +EXPORT_SYMBOL(rk_display_device_enable); + +void rk_display_device_enable_other(struct rk_display_device *ddev) +{ +#ifndef CONFIG_DISPLAY_AUTO_SWITCH + return; +#else + struct list_head *pos, *head = &display_device_list; + struct rk_display_device *dev; + int connect = 0; + + list_for_each_prev(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + if(dev != ddev) + { + connect = dev->ops->getstatus(dev); + if(connect) + { + dev->ops->setenable(dev, 1); + return; + } + } + } +#endif +} +EXPORT_SYMBOL(rk_display_device_enable_other); + +void rk_display_device_disable_other(struct rk_display_device *ddev) +{ +#ifndef CONFIG_DISPLAY_AUTO_SWITCH + return; +#else + struct list_head *pos, *head = &display_device_list; + struct rk_display_device *dev; + int enable = 0; + + list_for_each(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + if(dev != ddev) + { + enable = dev->ops->getenable(dev); + if(enable) + dev->ops->setenable(dev, 0); + } + } + ddev->ops->setenable(ddev, 1); +#endif +} +EXPORT_SYMBOL(rk_display_device_disable_other); + +void rk_display_device_select(int priority) +{ + struct list_head *pos, *head = &display_device_list; + struct rk_display_device *dev; + int enable, found = 0; + + list_for_each(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + if(dev->priority == priority) + found = 1; + } + + if(!found) + { + printk("[%s] select display interface %d not exist\n", __FUNCTION__, priority); + return; + } + + list_for_each(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + enable = dev->ops->getenable(dev); + if(dev->priority == priority) + { + if(!enable) + dev->ops->setenable(dev, 1); + } + else if(enable) + dev->ops->setenable(dev, 0); + } +} +EXPORT_SYMBOL(rk_display_device_select); +static struct mutex allocated_dsp_lock; +static DEFINE_IDR(allocated_dsp); +static struct class *display_class; + +struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver, + struct device *parent, void *devdata) +{ + struct rk_display_device *new_dev = NULL; + int ret = -EINVAL; + + if (unlikely(!driver)) + return ERR_PTR(ret); + + mutex_lock(&allocated_dsp_lock); + ret = idr_pre_get(&allocated_dsp, GFP_KERNEL); + mutex_unlock(&allocated_dsp_lock); + if (!ret) + return ERR_PTR(ret); + + new_dev = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL); + if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) { + // Reserve the index for this display + mutex_lock(&allocated_dsp_lock); + ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx); + mutex_unlock(&allocated_dsp_lock); + + if (!ret) { + new_dev->dev = device_create(display_class, parent, + MKDEV(0, 0), new_dev, + "%s", new_dev->type); + if (!IS_ERR(new_dev->dev)) { + new_dev->parent = parent; + new_dev->driver = driver; + new_dev->dev->driver = parent->driver; + mutex_init(&new_dev->lock); + // Add new device to display device list. + { + struct list_head *pos, *head = &display_device_list; + struct rk_display_device *dev; + + list_for_each(pos, head) { + dev = list_entry(pos, struct rk_display_device, list); + if(dev->priority > new_dev->priority) + break; + } + list_add_tail(&new_dev->list, pos); + } + return new_dev; + } + mutex_lock(&allocated_dsp_lock); + idr_remove(&allocated_dsp, new_dev->idx); + mutex_unlock(&allocated_dsp_lock); + ret = -EINVAL; + } + } + kfree(new_dev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(rk_display_device_register); + +void rk_display_device_unregister(struct rk_display_device *ddev) +{ + if (!ddev) + return; + // Free device + mutex_lock(&ddev->lock); + device_unregister(ddev->dev); + mutex_unlock(&ddev->lock); + // Mark device index as avaliable + mutex_lock(&allocated_dsp_lock); + idr_remove(&allocated_dsp, ddev->idx); + mutex_unlock(&allocated_dsp_lock); + list_del(&ddev->list); + kfree(ddev); +} +EXPORT_SYMBOL(rk_display_device_unregister); + +static int __init rk_display_class_init(void) +{ + display_class = class_create(THIS_MODULE, "display"); + if (IS_ERR(display_class)) { + printk(KERN_ERR "Failed to create display class\n"); + display_class = NULL; + return -EINVAL; + } + display_class->dev_attrs = display_attrs; + display_class->suspend = display_suspend; + display_class->resume = display_resume; + mutex_init(&allocated_dsp_lock); + INIT_LIST_HEAD(&display_device_list); + return 0; +} + +static void __exit rk_display_class_exit(void) +{ + class_destroy(display_class); +} + +subsys_initcall(rk_display_class_init); +module_exit(rk_display_class_exit); + + +MODULE_AUTHOR("zhengyang@rock-chips.com"); +MODULE_DESCRIPTION("Driver for rk display device"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c deleted file mode 100644 index 0c647d7af0ee..000000000000 --- a/drivers/video/display/display-sysfs.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * display-sysfs.c - Display output driver sysfs interface - * - * Copyright (C) 2007 James Simmons - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include -#include -#include -#include -#include - -static ssize_t display_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name); -} - -static ssize_t display_show_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type); -} - -static ssize_t display_show_contrast(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t rc = -ENXIO; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver) && dsp->driver->get_contrast) - rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp)); - mutex_unlock(&dsp->lock); - return rc; -} - -static ssize_t display_store_contrast(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t ret = -EINVAL, size; - int contrast; - char *endp; - - contrast = simple_strtoul(buf, &endp, 0); - size = endp - buf; - - if (isspace(*endp)) - size++; - - if (size != count) - return ret; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver && dsp->driver->set_contrast)) { - pr_debug("display: set contrast to %d\n", contrast); - dsp->driver->set_contrast(dsp, contrast); - ret = count; - } - mutex_unlock(&dsp->lock); - return ret; -} - -static ssize_t display_show_max_contrast(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t rc = -ENXIO; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver)) - rc = sprintf(buf, "%d\n", dsp->driver->max_contrast); - mutex_unlock(&dsp->lock); - return rc; -} - -static struct device_attribute display_attrs[] = { - __ATTR(name, S_IRUGO, display_show_name, NULL), - __ATTR(type, S_IRUGO, display_show_type, NULL), - __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast), - __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL), -}; - -static int display_suspend(struct device *dev, pm_message_t state) -{ - struct display_device *dsp = dev_get_drvdata(dev); - - mutex_lock(&dsp->lock); - if (likely(dsp->driver->suspend)) - dsp->driver->suspend(dsp, state); - mutex_unlock(&dsp->lock); - return 0; -}; - -static int display_resume(struct device *dev) -{ - struct display_device *dsp = dev_get_drvdata(dev); - - mutex_lock(&dsp->lock); - if (likely(dsp->driver->resume)) - dsp->driver->resume(dsp); - mutex_unlock(&dsp->lock); - return 0; -}; - -static struct mutex allocated_dsp_lock; -static DEFINE_IDR(allocated_dsp); -static struct class *display_class; - -struct display_device *display_device_register(struct display_driver *driver, - struct device *parent, void *devdata) -{ - struct display_device *new_dev = NULL; - int ret = -EINVAL; - - if (unlikely(!driver)) - return ERR_PTR(ret); - - mutex_lock(&allocated_dsp_lock); - ret = idr_pre_get(&allocated_dsp, GFP_KERNEL); - mutex_unlock(&allocated_dsp_lock); - if (!ret) - return ERR_PTR(ret); - - new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL); - if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) { - // Reserve the index for this display - mutex_lock(&allocated_dsp_lock); - ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx); - mutex_unlock(&allocated_dsp_lock); - - if (!ret) { - new_dev->dev = device_create(display_class, parent, - MKDEV(0, 0), new_dev, - "display%d", new_dev->idx); - if (!IS_ERR(new_dev->dev)) { - new_dev->parent = parent; - new_dev->driver = driver; - mutex_init(&new_dev->lock); - return new_dev; - } - mutex_lock(&allocated_dsp_lock); - idr_remove(&allocated_dsp, new_dev->idx); - mutex_unlock(&allocated_dsp_lock); - ret = -EINVAL; - } - } - kfree(new_dev); - return ERR_PTR(ret); -} -EXPORT_SYMBOL(display_device_register); - -void display_device_unregister(struct display_device *ddev) -{ - if (!ddev) - return; - // Free device - mutex_lock(&ddev->lock); - device_unregister(ddev->dev); - mutex_unlock(&ddev->lock); - // Mark device index as available - mutex_lock(&allocated_dsp_lock); - idr_remove(&allocated_dsp, ddev->idx); - mutex_unlock(&allocated_dsp_lock); - kfree(ddev); -} -EXPORT_SYMBOL(display_device_unregister); - -static int __init display_class_init(void) -{ - display_class = class_create(THIS_MODULE, "display"); - if (IS_ERR(display_class)) { - printk(KERN_ERR "Failed to create display class\n"); - display_class = NULL; - return -EINVAL; - } - display_class->dev_attrs = display_attrs; - display_class->suspend = display_suspend; - display_class->resume = display_resume; - mutex_init(&allocated_dsp_lock); - return 0; -} - -static void __exit display_class_exit(void) -{ - class_destroy(display_class); -} - -module_init(display_class_init); -module_exit(display_class_exit); - -MODULE_DESCRIPTION("Display Hardware handling"); -MODULE_AUTHOR("James Simmons "); -MODULE_LICENSE("GPL"); - diff --git a/drivers/video/display/lcd/Kconfig b/drivers/video/display/lcd/Kconfig new file mode 100644 index 000000000000..3d15a66d7974 --- /dev/null +++ b/drivers/video/display/lcd/Kconfig @@ -0,0 +1,6 @@ +config RK610_LCD + bool "RK610(Jetta) lcd support" + depends on MFD_RK610 + default y if MFD_RK610 + help + Support Jetta(RK610) to output LCD1 and LVDS. diff --git a/drivers/video/display/lcd/Makefile b/drivers/video/display/lcd/Makefile new file mode 100644 index 000000000000..a124d84e794f --- /dev/null +++ b/drivers/video/display/lcd/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the jetta tv control. +# +obj-$(CONFIG_RK610_LCD) += rk610_lcd.o diff --git a/drivers/video/display/lcd/rk610_lcd.c b/drivers/video/display/lcd/rk610_lcd.c new file mode 100644 index 000000000000..4a400b46aa14 --- /dev/null +++ b/drivers/video/display/lcd/rk610_lcd.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include + +#include +#include "rk610_lcd.h" +#include +#include "../../rk29_fb.h" +static struct i2c_client *rk610_g_lcd_client=NULL; +//static int rk610_scaler_read_p0_reg(struct i2c_client *client, char reg, char *val) +//{ + //return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +//} + +static int rk610_scaler_write_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} +static void rk610_scaler_pll_enable(struct i2c_client *client) +{ + char c; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + c = S_PLL_PWR(0)|S_PLL_RESET(0)|S_PLL_BYPASS(0); + rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c); +} +static void rk610_scaler_pll_disable(struct i2c_client *client) +{ + char c; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1); + rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c); +} +static void rk610_scaler_enable(struct i2c_client *client) +{ + char c; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + + c= SCL_BYPASS(0) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(ENABLE); + rk610_scaler_write_p0_reg(client, SCL_CON0, &c); +} +static void rk610_scaler_disable(struct i2c_client *client) +{ + char c; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + + c= SCL_BYPASS(1) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(DISABLE); + rk610_scaler_write_p0_reg(client, SCL_CON0, &c); +} +static int rk610_output_config(struct i2c_client *client,struct rk29fb_screen *screen,bool enable) +{ + char c=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + if(SCREEN_LVDS == screen->type){ + c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(1) |LVDS_PLL_PWR_PIN(0) \ + |LVDS_LANE_IN_FORMAT(DATA_D0_MSB) |LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL) \ + |LVDS_OUTPUT_FORMAT(screen->hw_format) ; + rk610_scaler_write_p0_reg(client, LVDS_CON0, &c); + c = LVDS_OUT_ENABLE(0x0) |LVDS_TX_PWR_ENABLE(0x0); + rk610_scaler_write_p0_reg(client, LVDS_CON1, &c); + }else if(SCREEN_RGB == screen->type){ + c = LCD1_OUT_ENABLE(LCD1_AS_OUT) | LCD1_OUT_SRC(enable?LCD1_FROM_SCL : LCD1_FROM_LCD0); + rk610_scaler_write_p0_reg(client, LCD1_CON, &c); + } + return 0; +} +#ifdef CONFIG_HDMI_DUAL_DISP +static int rk610_scaler_pll_set(struct i2c_client *client,struct rk29fb_screen *screen,u32 clkin ) +{ + char c=0; + char M=0,N=0,OD=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + /***************SET SCALER PLL FROM CLKIN ,DIV 0*/ + if(screen->s_pixclock != 0){ + OD = (screen->s_pixclock)&0x3; + N = (screen->s_pixclock >>4)&0xf; + M = (screen->s_pixclock >>8)&0xff; + }else { + RK610_ERR(&client->dev,"RK610 Scaler pll not support rate \n"); + } + c = S_PLL_FROM_DIV<<3 | S_PLL_DIV(0); + rk610_scaler_write_p0_reg(client, CLOCK_CON0, &c); + + c = S_DIV_N(N)| S_DIV_OD(OD); + rk610_scaler_write_p0_reg(client, S_PLL_CON0, &c); + c = S_DIV_M(M); + rk610_scaler_write_p0_reg(client, S_PLL_CON1, &c); + rk610_scaler_pll_enable(client); + return 0; +} + + +static int scale_hv_factor(struct i2c_client *client ,u32 Hin_act, u32 Hout_act, u32 Vin_act, u32 Vout_act) + { + char c; + u32 hfactor_f,vfactor_f,scl_factor_f; + int hfactor; + int vfactor; + struct scl_hv_info HV2; + hfactor_f = ((Hin_act-1)*4096)/(Hout_act-1); + if(hfactor_f==4096) + {hfactor = 0x1000;} + else if(hfactor_f>(int)hfactor_f) + {hfactor = (int)hfactor_f+1;} + else + {hfactor = (int)hfactor_f;} + + scl_factor_f = Vin_act/Vout_act; + if(scl_factor_f<2) + {vfactor_f = ((Vin_act-1)*4096)/(Vout_act-1);} + else + {vfactor_f = ((Vin_act-2)*4096)/(Vout_act-1);} + if(vfactor_f==4096) + {vfactor = 0x1000;} + else if(vfactor_f>(int)vfactor_f) + {vfactor = (int)vfactor_f+1;} + else + {vfactor = (int)vfactor_f;} + + HV2.scl_h= hfactor; + HV2.scl_v= vfactor; + /* SCL FACTOR */ + c = SCL_H_FACTOR_LSB(HV2.scl_h); + rk610_scaler_write_p0_reg(client, SCL_CON1, &c); + c = SCL_H_FACTOR_MSB(HV2.scl_h); + rk610_scaler_write_p0_reg(client, SCL_CON2, &c); + + c = SCL_V_FACTOR_LSB(HV2.scl_v); + rk610_scaler_write_p0_reg(client, SCL_CON3, &c); + c = SCL_V_FACTOR_MSB(HV2.scl_v); + rk610_scaler_write_p0_reg(client, SCL_CON4, &c); + return 0; + } + +static int rk610_scaler_fator_config(struct i2c_client *client ,struct rk29fb_screen *screen) +{ + switch(screen->hdmi_resolution){ + case HDMI_1920x1080p_60Hz: + case HDMI_1920x1080p_50Hz: + rk610_scaler_pll_set(client,screen,148500000); + /***************set scaler factor********************/ + scale_hv_factor(client,1920,screen->x_res,1080,screen->y_res); + break; + case HDMI_1280x720p_60Hz: + case HDMI_1280x720p_50Hz: + rk610_scaler_pll_set(client,screen,74250000); + /***************set scaler factor********************/ + scale_hv_factor(client,1280,screen->x_res,720,screen->y_res); + break; + case HDMI_720x576p_50Hz_16x9: + case HDMI_720x576p_50Hz_4x3: + rk610_scaler_pll_set(client,screen,27000000); + /***************set scaler factor********************/ + scale_hv_factor(client,720,screen->x_res,576,screen->y_res); + break; + case HDMI_720x480p_60Hz_16x9: + case HDMI_720x480p_60Hz_4x3: + rk610_scaler_pll_set(client,screen,27000000); + /***************set scaler factor********************/ + scale_hv_factor(client,720,screen->x_res,480,screen->y_res); + break; + default : + RK610_ERR(&client->dev,"RK610 not support dual display at hdmi resolution=%d \n",screen->hdmi_resolution); + return -1; + break; + } +} +static int rk610_scaler_output_timing_config(struct i2c_client *client,struct rk29fb_screen *screen) +{ + char c; + int h_st = screen->s_hsync_st; + int hs_end = screen->s_hsync_len; + int h_act_st = hs_end + screen->s_left_margin; + int xres = screen->x_res; + int h_act_end = h_act_st + xres; + int h_total = h_act_end + screen->s_right_margin; + int v_st = screen->s_vsync_st; + int vs_end = screen->s_vsync_len; + int v_act_st = vs_end + screen->s_upper_margin; + int yres = screen->y_res; + int v_act_end = v_act_st + yres; + int v_total = v_act_end + screen->s_lower_margin; + + /* SCL display Frame start point */ + c = SCL_DSP_HST_LSB(h_st); + rk610_scaler_write_p0_reg(client, SCL_CON5, &c); + c = SCL_DSP_HST_MSB(h_st); + rk610_scaler_write_p0_reg(client, SCL_CON6, &c); + + c = SCL_DSP_VST_LSB(v_st); + rk610_scaler_write_p0_reg(client, SCL_CON7, &c); + c = SCL_DSP_VST_MSB(v_st); + rk610_scaler_write_p0_reg(client, SCL_CON8, &c); + /* SCL output timing */ + + c = SCL_DSP_HTOTAL_LSB(h_total); + rk610_scaler_write_p0_reg(client, SCL_CON9, &c); + c = SCL_DSP_HTOTAL_MSB(h_total); + rk610_scaler_write_p0_reg(client, SCL_CON10, &c); + + c = SCL_DSP_HS_END(hs_end); + rk610_scaler_write_p0_reg(client, SCL_CON11, &c); + + c = SCL_DSP_HACT_ST_LSB(h_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON12, &c); + c = SCL_DSP_HACT_ST_MSB(h_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON13, &c); + + c = SCL_DSP_HACT_END_LSB(h_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON14, &c); + c = SCL_DSP_HACT_END_MSB(h_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON15, &c); + + c = SCL_DSP_VTOTAL_LSB(v_total); + rk610_scaler_write_p0_reg(client, SCL_CON16, &c); + c = SCL_DSP_VTOTAL_MSB(v_total); + rk610_scaler_write_p0_reg(client, SCL_CON17, &c); + + c = SCL_DSP_VS_END(vs_end); + rk610_scaler_write_p0_reg(client, SCL_CON18, &c); + + c = SCL_DSP_VACT_ST(v_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON19, &c); + + c = SCL_DSP_VACT_END_LSB(v_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON20, &c); + c = SCL_DSP_VACT_END_MSB(v_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON21, &c); + + c = SCL_H_BORD_ST_LSB(h_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON22, &c); + c = SCL_H_BORD_ST_MSB(h_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON23, &c); + + c = SCL_H_BORD_END_LSB(h_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON24, &c); + c = SCL_H_BORD_END_MSB(h_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON25, &c); + + c = SCL_V_BORD_ST(v_act_st); + rk610_scaler_write_p0_reg(client, SCL_CON26, &c); + + c = SCL_V_BORD_END_LSB(v_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON27, &c); + c = SCL_V_BORD_END_MSB(v_act_end); + rk610_scaler_write_p0_reg(client, SCL_CON28, &c); + + return 0; +} +static int rk610_scaler_chg(struct i2c_client *client ,struct rk29fb_screen *screen) +{ + + RK610_DBG(&client->dev,"%s screen->hdmi_resolution=%d\n",__FUNCTION__,screen->hdmi_resolution); + rk610_scaler_fator_config(client,screen); + rk610_scaler_enable(client); + rk610_scaler_output_timing_config(client,screen); + + return 0; + +} +#endif +static int rk610_lcd_scaler_bypass(struct i2c_client *client,bool enable)//enable:0 bypass 1: scale +{ + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + + rk610_scaler_pll_disable(client); + rk610_scaler_disable(client); + + return 0; +} +int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable )//enable:0 bypass 1: scale +{ + int ret=0; + struct i2c_client *client = rk610_g_lcd_client; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + if(client == NULL){ + RK610_ERR(&client->dev,"%s client == NULL FAIL\n",__FUNCTION__); + return -1; + } + +#ifdef CONFIG_HDMI_DUAL_DISP + if(enable == 1){ + rk610_output_config(client,screen,1); + ret = rk610_scaler_chg(client,screen); + } + else +#endif + { + rk610_output_config(client,screen,0); + ret = rk610_lcd_scaler_bypass(client,enable); + } + return ret; +} +int rk610_lcd_init(struct i2c_client *client) +{ + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + rk610_g_lcd_client = client; + return 0; +} diff --git a/drivers/video/display/lcd/rk610_lcd.h b/drivers/video/display/lcd/rk610_lcd.h new file mode 100644 index 000000000000..06880b3455b3 --- /dev/null +++ b/drivers/video/display/lcd/rk610_lcd.h @@ -0,0 +1,165 @@ +#ifndef _RK610_LCD_H +#define _RK610_LCD_H +#include "../screen/screen.h" +#define ENABLE 1 +#define DISABLE 0 +/* LVDS config */ +/* LVDS ÍⲿÁ¬Ïß½Ó·¨ */ +#define LVDS_8BIT_1 0x00 +#define LVDS_8BIT_2 0x01 +#define LVDS_8BIT_3 0x10 +#define LVDS_6BIT 0x11 +//LVDS lane input format +#define DATA_D0_MSB 0 +#define DATA_D7_MSB 1 +//LVDS input source +#define FROM_LCD1 0 +#define FROM_LCD0_OR_SCL 1 + +/* LCD1 config */ +#define LCD1_AS_IN 0 +#define LCD1_AS_OUT 1 + +//LCD1 output source +#define LCD1_FROM_LCD0 0 +#define LCD1_FROM_SCL 1 + +/* clock config */ +#define S_PLL_FROM_DIV 0 +#define S_PLL_FROM_CLKIN 1 +#define S_PLL_DIV(x) ((x)&0x7) +/*********S_PLL_CON************/ +//S_PLL_CON0 +#define S_DIV_N(x) (((x)&0xf)<<4) +#define S_DIV_OD(x) (((x)&3)<<0) +//S_PLL_CON1 +#define S_DIV_M(x) ((x)&0xff) +//S_PLL_CON2 +#define S_PLL_UNLOCK (0<<7) //0:unlock 1:pll_lock +#define S_PLL_LOCK (1<<7) //0:unlock 1:pll_lock +#define S_PLL_PWR(x) (((x)&1)<<2) //0:POWER UP 1:POWER DOWN +#define S_PLL_RESET(x) (((x)&1)<<1) //0:normal 1:reset M/N dividers +#define S_PLL_BYPASS(x) (((x)&1)<<0) //0:normal 1:bypass +//LVDS_CON0 +#define LVDS_OUT_CLK_PIN(x) (((x)&1)<<7) //clk enable pin, 0: enable +#define LVDS_OUT_CLK_PWR_PIN(x) (((x)&1)<<6) //clk pwr enable pin, 1: enable +#define LVDS_PLL_PWR_PIN(x) (((x)&1)<<5) //pll pwr enable pin, 0:enable +#define LVDS_LANE_IN_FORMAT(x) (((x)&1)<<3) //0: msb on D0 1:msb on D7 +#define LVDS_INPUT_SOURCE(x) (((x)&1)<<2) //0: from lcd1 1:from lcd0 or scaler +#define LVDS_OUTPUT_FORMAT(x) (((x)&3)<<0) //00:8bit format-1 01:8bit format-2 10:8bit format-3 11:6bit format +//LVDS_CON1 +#define LVDS_OUT_ENABLE(x) (((x)&0xf)<<4) //0:output enable 1:output disable +#define LVDS_TX_PWR_ENABLE(x) (((x)&0xf)<<0) //0:working mode 1:power down +//LCD1_CON +#define LCD1_OUT_ENABLE(x) (((x)&1)<<1) //0:lcd1 as input 1:lcd1 as output +#define LCD1_OUT_SRC(x) (((x)&1)<<0) //0:from lcd0 1:from scaler +//SCL_CON0 +#define SCL_BYPASS(x) (((x)&1)<<4) //0:not bypass 1:bypass +#define SCL_DEN_INV(x) (((x)&1)<<3) //scl_den_inv +#define SCL_H_V_SYNC_INV(x) (((x)&1)<<2) //scl_sync_inv +#define SCL_OUT_CLK_INV(x) (((x)&1)<<1) //scl_dclk_inv +#define SCL_ENABLE(x) (((x)&1)<<0) //scaler enable +//SCL_CON1 +#define SCL_H_FACTOR_LSB(x) ((x)&0xff) //scl_h_factor[7:0] +//SCL_CON2 +#define SCL_H_FACTOR_MSB(x) (((x)>>8)&0x3f) //scl_h_factor[13:8] +//SCL_CON3 +#define SCL_V_FACTOR_LSB(x) ((x)&0xff) //scl_v_factor[7:0] +//SCL_CON4 +#define SCL_V_FACTOR_MSB(x) (((x)>>8)&0x3f) //scl_v_factor[13:8] +//SCL_CON5 +#define SCL_DSP_HST_LSB(x) ((x)&0xff) //dsp_frame_hst[7:0] +//SCL_CON6 +#define SCL_DSP_HST_MSB(x) (((x)>>8)&0xf) //dsp_frame_hst[11:8] +//SCL_CON7 +#define SCL_DSP_VST_LSB(x) ((x)&0xff) //dsp_frame_vst[7:0] +//SCL_CON8 +#define SCL_DSP_VST_MSB(x) (((x)>>8)&0xf) //dsp_frame_vst[11:8] +//SCL_CON9 +#define SCL_DSP_HTOTAL_LSB(x) ((x)&0xff) //dsp_frame_htotal[7:0] +//SCL_CON10 +#define SCL_DSP_HTOTAL_MSB(x) (((x)>>8)&0xf) //dsp_frame_htotal[11:8] +//SCL_CON11 +#define SCL_DSP_HS_END(x) ((x)&0xff) //dsp_hs_end +//SCL_CON12 +#define SCL_DSP_HACT_ST_LSB(x) ((x)&0xff) //dsp_hact_st[7:0] +//SCL_CON13 +#define SCL_DSP_HACT_ST_MSB(x) (((x)>>8)&0x3) //dsp_hact_st[9:8] +//SCL_CON14 +#define SCL_DSP_HACT_END_LSB(x) ((x)&0xff) //dsp_hact_end[7:0] +//SCL_CON15 +#define SCL_DSP_HACT_END_MSB(x) (((x)>>8)&0xf) //dsp_frame_htotal[11:8] +//SCL_CON16 +#define SCL_DSP_VTOTAL_LSB(x) ((x)&0xff) //dsp_frame_vtotal[7:0] +//SCL_CON17 +#define SCL_DSP_VTOTAL_MSB(x) (((x)>>8)&0xf) //dsp_frame_vtotal[11:8] +//SCL_CON18 +#define SCL_DSP_VS_END(x) ((x)&0xff) //dsp_vs_end +//SCL_CON19 +#define SCL_DSP_VACT_ST(x) ((x)&0xff) //dsp_vact_st[7:0] +//SCL_CON20 +#define SCL_DSP_VACT_END_LSB(x) ((x)&0xff) //dsp_vact_end[7:0] +//SCL_CON21 +#define SCL_DSP_VACT_END_MSB(x) (((x)>>8)&0xf) //dsp_frame_vtotal[11:8] +//SCL_CON22 +#define SCL_H_BORD_ST_LSB(x) ((x)&0xff) //dsp_hbord_st[7:0] +//SCL_CON23 +#define SCL_H_BORD_ST_MSB(x) (((x)>>8)&0x3) //dsp_hbord_st[9:8] +//SCL_CON24 +#define SCL_H_BORD_END_LSB(x) ((x)&0xff) //dsp_hbord_end[7:0] +//SCL_CON25 +#define SCL_H_BORD_END_MSB(x) (((x)>>8)&0xf) //dsp_hbord_end[11:8] +//SCL_CON26 +#define SCL_V_BORD_ST(x) ((x)&0xff) //dsp_vbord_st[7:0] +//SCL_CON27 +#define SCL_V_BORD_END_LSB(x) ((x)&0xff) //dsp_vbord_end[7:0] +//SCL_CON25 +#define SCL_V_BORD_END_MSB(x) (((x)>>8)&0xf) //dsp_vbord_end[11:8] +#if 0 +/****************LCD STRUCT********/ +#define PLL_CLKOD(i) ((i) & 0x03) +#define PLL_NO_1 PLL_CLKOD(0) +#define PLL_NO_2 PLL_CLKOD(1) +#define PLL_NO_4 PLL_CLKOD(2) +#define PLL_NO_8 PLL_CLKOD(3) +#define SCALE_PLL(_parent_rate , _rate, _m, _n, _od) \ +{ \ + .parent_rate = _parent_rate, \ + .rate = _rate, \ + .m = _m, \ + .n = _n, \ + .od = _od, \ +} +#endif +struct rk610_pll_info{ + u32 parent_rate; + u32 rate; + int m; + int n; + int od; +}; +struct lcd_mode_inf{ + int h_pw; + int h_bp; + int h_vd; + int h_fp; + int v_pw; + int v_bp; + int v_vd; + int v_fp; + int f_hst; + int f_vst; + struct rk610_pll_info pllclk; +}; +struct scl_hv_info{ + int scl_h ; + int scl_v; + }; +struct rk610_lcd_info{ + int enable; + struct scl_hv_info scl; + struct lcd_mode_inf *lcd_mode; +}; +extern int rk610_lcd_init(struct i2c_client *client); +extern int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable ); +#endif diff --git a/drivers/video/display/screen/Kconfig b/drivers/video/display/screen/Kconfig index 83dc4da9b065..a93e42cb9ef6 100644 --- a/drivers/video/display/screen/Kconfig +++ b/drivers/video/display/screen/Kconfig @@ -68,6 +68,16 @@ config LCD_A050VL01 bool "RGB A050VL01" config LCD_B101EW05 bool "RGB lcd panel B101EW05" +config LCD_HDMI_1024x768 + depends on MFD_RK610 + bool "RGB Hannstar LCD_HDMI_1024X768" + ---help--- + if support RK610, this setting can support dual screen output +config LCD_HDMI_800x480 + depends on MFD_RK610 + bool "RGB Hannstar LCD_HDMI_800x480" + ---help--- + if support RK610, this setting can support dual screen output endchoice diff --git a/drivers/video/display/screen/Makefile b/drivers/video/display/screen/Makefile index b37569a13afc..fd03740b4aa5 100644 --- a/drivers/video/display/screen/Makefile +++ b/drivers/video/display/screen/Makefile @@ -22,6 +22,8 @@ obj-$(CONFIG_LCD_CPTCLAA038LA31XE) += lcd_CPTclaa038la31xe.o obj-$(CONFIG_LCD_HX8357) += lcd_hx8357.o obj-$(CONFIG_LCD_HSD100PXN) += lcd_hsd100pxn.o +obj-$(CONFIG_LCD_HDMI_1024x768) += lcd_hdmi_1024x768.o +obj-$(CONFIG_LCD_HDMI_800x480) += lcd_hdmi_800x480.o obj-$(CONFIG_LCD_HSD07PFW1) += lcd_hsd07pfw1.o obj-$(CONFIG_LCD_B101AW06) += lcd_B101AW06.o obj-$(CONFIG_LCD_NT35510) += lcd_nt35510.o diff --git a/drivers/video/display/screen/lcd_hdmi_1024x768.c b/drivers/video/display/screen/lcd_hdmi_1024x768.c new file mode 100644 index 000000000000..821cc59b74c7 --- /dev/null +++ b/drivers/video/display/screen/lcd_hdmi_1024x768.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include "screen.h" +#include +#include "../../rk29_fb.h" +#include "../lcd/rk610_lcd.h" + +/* Base */ +#define OUT_TYPE SCREEN_LVDS + +#define OUT_FORMAT LVDS_8BIT_3 +#define OUT_FACE OUT_D888_P666 +#define OUT_CLK 65000000 +#define LCDC_ACLK 500000000//312000000 //29 lcdc axi DMA ƵÂÊ + +/* Timing */ +#define H_PW 48 //10 +#define H_BP 88 //100 +#define H_VD 800 //1024 +#define H_FP 40 //210 + +#define V_PW 3 //10 +#define V_BP 32 //10 +#define V_VD 480 //768 +#define V_FP 13 //18 + +#define LCD_WIDTH 202 +#define LCD_HEIGHT 152 + +/* scaler Timing */ +//1920*1080*60 +#define S_OUT_CLK SCALE_RATE(148500000,66000000) +#define S_H_PW 100 +#define S_H_BP 100 +#define S_H_VD 1024 +#define S_H_FP 151 + +#define S_V_PW 5 +#define S_V_BP 15 +#define S_V_VD 768 +#define S_V_FP 12 + +#define S_H_ST 1757 +#define S_V_ST 14 + +//1920*1080*50 +#define S1_OUT_CLK SCALE_RATE(148500000,54000000) +#define S1_H_PW 100 +#define S1_H_BP 100 +#define S1_H_VD 1024 +#define S1_H_FP 126 + +#define S1_V_PW 5 +#define S1_V_BP 15 +#define S1_V_VD 768 +#define S1_V_FP 12 + +#define S1_H_ST 1757 +#define S1_V_ST 14 +/* Other */ +#define DCLK_POL 0 +#define SWAP_RB 0 +#ifdef CONFIG_HDMI_DUAL_DISP +static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution) +{ + switch(hdmi_resolution){ + case HDMI_1920x1080p_60Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S_OUT_CLK; + screen->s_hsync_len = S_H_PW; + screen->s_left_margin = S_H_BP; + screen->s_right_margin = S_H_FP; + screen->s_hsync_len = S_H_PW; + screen->s_upper_margin = S_V_BP; + screen->s_lower_margin = S_V_FP; + screen->s_vsync_len = S_V_PW; + screen->s_hsync_st = S_H_ST; + screen->s_vsync_st = S_V_ST; + break; + case HDMI_1920x1080p_50Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S1_OUT_CLK; + screen->s_hsync_len = S1_H_PW; + screen->s_left_margin = S1_H_BP; + screen->s_right_margin = S1_H_FP; + screen->s_hsync_len = S1_H_PW; + screen->s_upper_margin = S1_V_BP; + screen->s_lower_margin = S1_V_FP; + screen->s_vsync_len = S1_V_PW; + screen->s_hsync_st = S1_H_ST; + screen->s_vsync_st = S1_V_ST; + break; + default : + printk("%s lcd not support dual display at this hdmi resolution %d \n",__func__,hdmi_resolution); + return -1; + break; + } + + return 0; +} +#else +static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution){} +#endif + +void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info ) +{ + /* screen type & face */ + screen->type = OUT_TYPE; + screen->face = OUT_FACE; + + /* Screen size */ + screen->x_res = H_VD; + screen->y_res = V_VD; + + screen->width = LCD_WIDTH; + screen->height = LCD_HEIGHT; + + /* Timing */ + screen->lcdc_aclk = LCDC_ACLK; + 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 = NULL; + screen->standby = NULL; + screen->sscreen_get = set_scaler_info; +#ifdef CONFIG_RK610_LCD + screen->sscreen_set = rk610_lcd_scaler_set_param; +#endif +} \ No newline at end of file diff --git a/drivers/video/display/screen/lcd_hdmi_800x480.c b/drivers/video/display/screen/lcd_hdmi_800x480.c new file mode 100644 index 000000000000..925957702d49 --- /dev/null +++ b/drivers/video/display/screen/lcd_hdmi_800x480.c @@ -0,0 +1,271 @@ +#include +#include +#include +#include +#include +#include "screen.h" +#include +#include "../../rk29_fb.h" +#include "../lcd/rk610_lcd.h" + +/* Base */ +#define OUT_TYPE SCREEN_RGB + +#define OUT_FACE OUT_P888 +#define OUT_CLK 33000000 +#define LCDC_ACLK 150000000//312000000 //29 lcdc axi DMA ƵÂÊ + +/* Timing */ +#define H_PW 1 +#define H_BP 88 +#define H_VD 800 +#define H_FP 40 + +#define V_PW 3 +#define V_BP 29 +#define V_VD 480 +#define V_FP 13 + +#define LCD_WIDTH 154 +#define LCD_HEIGHT 85 + +/* scaler Timing */ +//1920*1080*60 + +#define S_OUT_CLK SCALE_RATE(148500000,33000000) +#define S_H_PW 1 +#define S_H_BP 88 +#define S_H_VD 800 +#define S_H_FP 211 + +#define S_V_PW 3 +#define S_V_BP 10 +#define S_V_VD 480 +#define S_V_FP 7 + +#define S_H_ST 244 +#define S_V_ST 11 + +//1920*1080*50 +#define S1_OUT_CLK SCALE_RATE(148500000,30375000) +#define S1_H_PW 1 +#define S1_H_BP 88 +#define S1_H_VD 800 +#define S1_H_FP 326 + +#define S1_V_PW 3 +#define S1_V_BP 9 +#define S1_V_VD 480 +#define S1_V_FP 8 + +#define S1_H_ST 270 +#define S1_V_ST 13 +//1280*720*60 +#define S2_OUT_CLK SCALE_RATE(74250000,33000000) +#define S2_H_PW 1 +#define S2_H_BP 88 +#define S2_H_VD 800 +#define S2_H_FP 211 + +#define S2_V_PW 3 +#define S2_V_BP 9 +#define S2_V_VD 480 +#define S2_V_FP 8 + +#define S2_H_ST 0 +#define S2_V_ST 8 +//1280*720*50 + +#define S3_OUT_CLK SCALE_RATE(74250000,30375000) +#define S3_H_PW 1 +#define S3_H_BP 88 +#define S3_H_VD 800 +#define S3_H_FP 326 + +#define S3_V_PW 3 +#define S3_V_BP 9 +#define S3_V_VD 480 +#define S3_V_FP 8 + +#define S3_H_ST 0 +#define S3_V_ST 8 + +//720*576*50 +#define S4_OUT_CLK SCALE_RATE(27000000,30000000) +#define S4_H_PW 1 +#define S4_H_BP 88 +#define S4_H_VD 800 +#define S4_H_FP 263 + +#define S4_V_PW 3 +#define S4_V_BP 9 +#define S4_V_VD 480 +#define S4_V_FP 28 + +#define S4_H_ST 0 +#define S4_V_ST 33 +//720*480*60 +#define S5_OUT_CLK SCALE_RATE(27000000,31500000) +#define S5_H_PW 1 +#define S5_H_BP 88 +#define S5_H_VD 800 +#define S5_H_FP 112 + +#define S5_V_PW 3 +#define S5_V_BP 9 +#define S5_V_VD 480 +#define S5_V_FP 28 + +#define S5_H_ST 0 +#define S5_V_ST 29 +/* Other */ +#define DCLK_POL 0 +#define SWAP_RB 0 + +#ifdef CONFIG_HDMI_DUAL_DISP +static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution) +{ + switch(hdmi_resolution){ + case HDMI_1920x1080p_60Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S_OUT_CLK; + screen->s_hsync_len = S_H_PW; + screen->s_left_margin = S_H_BP; + screen->s_right_margin = S_H_FP; + screen->s_hsync_len = S_H_PW; + screen->s_upper_margin = S_V_BP; + screen->s_lower_margin = S_V_FP; + screen->s_vsync_len = S_V_PW; + screen->s_hsync_st = S_H_ST; + screen->s_vsync_st = S_V_ST; + break; + case HDMI_1920x1080p_50Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S1_OUT_CLK; + screen->s_hsync_len = S1_H_PW; + screen->s_left_margin = S1_H_BP; + screen->s_right_margin = S1_H_FP; + screen->s_hsync_len = S1_H_PW; + screen->s_upper_margin = S1_V_BP; + screen->s_lower_margin = S1_V_FP; + screen->s_vsync_len = S1_V_PW; + screen->s_hsync_st = S1_H_ST; + screen->s_vsync_st = S1_V_ST; + break; + case HDMI_1280x720p_60Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S2_OUT_CLK; + screen->s_hsync_len = S2_H_PW; + screen->s_left_margin = S2_H_BP; + screen->s_right_margin = S2_H_FP; + screen->s_hsync_len = S2_H_PW; + screen->s_upper_margin = S2_V_BP; + screen->s_lower_margin = S2_V_FP; + screen->s_vsync_len = S2_V_PW; + screen->s_hsync_st = S2_H_ST; + screen->s_vsync_st = S2_V_ST; + break; + case HDMI_1280x720p_50Hz: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S3_OUT_CLK; + screen->s_hsync_len = S3_H_PW; + screen->s_left_margin = S3_H_BP; + screen->s_right_margin = S3_H_FP; + screen->s_hsync_len = S3_H_PW; + screen->s_upper_margin = S3_V_BP; + screen->s_lower_margin = S3_V_FP; + screen->s_vsync_len = S3_V_PW; + screen->s_hsync_st = S3_H_ST; + screen->s_vsync_st = S3_V_ST; + break; + case HDMI_720x576p_50Hz_4x3: + case HDMI_720x576p_50Hz_16x9: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S4_OUT_CLK; + screen->s_hsync_len = S4_H_PW; + screen->s_left_margin = S4_H_BP; + screen->s_right_margin = S4_H_FP; + screen->s_hsync_len = S4_H_PW; + screen->s_upper_margin = S4_V_BP; + screen->s_lower_margin = S4_V_FP; + screen->s_vsync_len = S4_V_PW; + screen->s_hsync_st = S4_H_ST; + screen->s_vsync_st = S4_V_ST; + break; + case HDMI_720x480p_60Hz_16x9: + case HDMI_720x480p_60Hz_4x3: + /* Scaler Timing */ + screen->hdmi_resolution = hdmi_resolution; + screen->s_pixclock = S5_OUT_CLK; + screen->s_hsync_len = S5_H_PW; + screen->s_left_margin = S5_H_BP; + screen->s_right_margin = S5_H_FP; + screen->s_hsync_len = S5_H_PW; + screen->s_upper_margin = S5_V_BP; + screen->s_lower_margin = S5_V_FP; + screen->s_vsync_len = S5_V_PW; + screen->s_hsync_st = S5_H_ST; + screen->s_vsync_st = S5_V_ST; + break; + default : + printk("%s lcd not support dual display at this hdmi resolution %d \n",__func__,hdmi_resolution); + return -1; + break; + } + + return 0; +} +#else +static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution){} +#endif + +void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info ) +{ + /* screen type & face */ + screen->type = OUT_TYPE; + screen->face = OUT_FACE; + + /* Screen size */ + screen->x_res = H_VD; + screen->y_res = V_VD; + + screen->width = LCD_WIDTH; + screen->height = LCD_HEIGHT; + + /* Timing */ + screen->lcdc_aclk = LCDC_ACLK; + 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 = NULL; + screen->standby = NULL; + screen->sscreen_get = set_scaler_info; +#ifdef CONFIG_RK610_LCD + screen->sscreen_set = rk610_lcd_scaler_set_param; +#endif +} + diff --git a/drivers/video/display/screen/lcd_hsd800x480.c b/drivers/video/display/screen/lcd_hsd800x480.c index 56ea15fee984..b55cd3fb707e 100644 --- a/drivers/video/display/screen/lcd_hsd800x480.c +++ b/drivers/video/display/screen/lcd_hsd800x480.c @@ -11,26 +11,26 @@ /* Base */ #define OUT_TYPE SCREEN_RGB #define OUT_FACE OUT_P888 -#define OUT_CLK 28000000 +#define OUT_CLK 33000000 #define LCDC_ACLK 150000000 //29 lcdc axi DMA ƵÂÊ /* Timing */ -#define H_PW 1 -#define H_BP 88 -#define H_VD 800 -#define H_FP 40 +#define H_PW 8 //10 +#define H_BP 88 //100 +#define H_VD 800 //1024 +#define H_FP 40 //210 -#define V_PW 3 -#define V_BP 29 -#define V_VD 480 -#define V_FP 13 +#define V_PW 3 //10 +#define V_BP 10 //10 +#define V_VD 480 //768 +#define V_FP 32 //18 /* Other */ -#define DCLK_POL 1 +#define DCLK_POL 0 #define SWAP_RB 0 -#define LCD_WIDTH 800 //need modify -#define LCD_HEIGHT 480 +#define LCD_WIDTH 154 //need modify +#define LCD_HEIGHT 85 #define TXD_PORT gLcd_info->txd_pin #define CLK_PORT gLcd_info->clk_pin diff --git a/drivers/video/display/screen/screen.h b/drivers/video/display/screen/screen.h index d07ad0692e7c..5096d7cda698 100755 --- a/drivers/video/display/screen/screen.h +++ b/drivers/video/display/screen/screen.h @@ -1,8 +1,51 @@ +#ifndef _SCREEN_H +#define _SCREEN_H #include +#ifdef CONFIG_HDMI_DUAL_DISP +/* Scaler PLL CONFIG */ +#define S_PLL_NO_1 0 +#define S_PLL_NO_2 1 +#define S_PLL_NO_4 2 +#define S_PLL_NO_8 3 +#define S_PLL_M(x) (((x)&0xff)<<8) +#define S_PLL_N(x) (((x)&0xf)<<4) +#define S_PLL_NO(x) ((S_PLL_NO_##x)&0x3) + +enum{ + HDMI_RATE_148500000, + HDMI_RATE_74250000, + HDMI_RATE_27000000, +}; +/* Scaler clk setting */ +#define SCALE_PLL(_parent_rate,_rate,_m,_n,_no) \ + HDMI_RATE_ ## _parent_rate ##_S_RATE_ ## _rate \ + = S_PLL_M(_m) | S_PLL_N(_n) | S_PLL_NO(_no) +#define SCALE_RATE(_parent_rate , _rate) \ + (HDMI_RATE_ ## _parent_rate ## _S_RATE_ ## _rate) + +enum{ + SCALE_PLL(148500000, 66000000, 16, 9, 4), + SCALE_PLL(148500000, 54000000, 16, 11, 4), + SCALE_PLL(148500000, 33000000, 16, 9, 8), + SCALE_PLL(148500000, 30375000, 18, 11, 8), + SCALE_PLL(148500000, 29700000, 16, 10, 8), + SCALE_PLL(148500000, 25312500, 15, 11, 8), + + SCALE_PLL(74250000, 66000000, 32, 9, 4), + SCALE_PLL(74250000, 54000000, 32, 11, 4), + SCALE_PLL(74250000, 33000000, 32, 9, 8), + SCALE_PLL(74250000, 30375000, 36, 11, 8), + SCALE_PLL(74250000, 25312500, 30, 11, 8), + + SCALE_PLL(27000000, 31500000, 28, 3, 8), + SCALE_PLL(27000000, 30000000, 80, 9, 8), +}; +#endif typedef enum _SCREEN_TYPE { SCREEN_NULL = 0, SCREEN_RGB, + SCREEN_LVDS, SCREEN_MCU, SCREEN_TVOUT, SCREEN_HDMI, @@ -37,8 +80,9 @@ typedef enum _MCU_STATUS { /* Screen description */ typedef struct rk29fb_screen { - /* screen type & out face */ + /* screen type & hardware connect format & out face */ u16 type; + u16 hw_format; u16 face; /* Screen size */ @@ -47,6 +91,7 @@ typedef struct rk29fb_screen { u16 width; u16 height; + u32 mode; /* Timing */ u32 pixclock; u16 left_margin; @@ -55,7 +100,19 @@ typedef struct rk29fb_screen { u16 upper_margin; u16 lower_margin; u16 vsync_len; - +#ifdef CONFIG_HDMI_DUAL_DISP + /* Scaler mode Timing */ + u32 s_pixclock; + u16 s_left_margin; + u16 s_right_margin; + u16 s_hsync_len; + u16 s_upper_margin; + u16 s_lower_margin; + u16 s_vsync_len; + u16 s_hsync_st; + u16 s_vsync_st; +#endif + u8 hdmi_resolution; /* mcu need */ u8 mcu_wrperiod; u8 mcu_usefmk; @@ -82,10 +139,12 @@ typedef struct rk29fb_screen { int (*refresh)(u8 arg); int (*scandir)(u16 dir); int (*disparea)(u8 area); - + int (*sscreen_get)(struct rk29fb_screen *screen, u8 resolution); + int (*sscreen_set)(struct rk29fb_screen *screen, bool type);// 1: use scaler 0:bypass } rk_screen; + extern void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info); extern void set_tv_info(struct rk29fb_screen *screen); extern void set_hdmi_info(struct rk29fb_screen *screen); - +#endif diff --git a/drivers/video/display/tve/Kconfig b/drivers/video/display/tve/Kconfig new file mode 100644 index 000000000000..68639bdd419b --- /dev/null +++ b/drivers/video/display/tve/Kconfig @@ -0,0 +1,13 @@ +config RK610_TVOUT + bool "RK610(Jetta) tvout support" + depends on MFD_RK610 + default y if MFD_RK610 + help + Support Jetta(RK610) to output YPbPr and CVBS. + +config RK610_TVOUT_YPbPr + bool "support YPbPr output" + depends on RK610_TVOUT +config RK610_TVOUT_CVBS + bool "support CVBS output" + depends on RK610_TVOUT diff --git a/drivers/video/display/tve/Makefile b/drivers/video/display/tve/Makefile new file mode 100644 index 000000000000..b7d457326d26 --- /dev/null +++ b/drivers/video/display/tve/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the jetta tv control. +# +obj-$(CONFIG_RK610_TVOUT) += rk610_tv.o +obj-$(CONFIG_RK610_TVOUT_YPbPr) += rk610_tv_ypbpr.o +obj-$(CONFIG_RK610_TVOUT_CVBS) += rk610_tv_cvbs.o \ No newline at end of file diff --git a/drivers/video/display/tve/rk610_tv.c b/drivers/video/display/tve/rk610_tv.c new file mode 100644 index 000000000000..03237ce4a410 --- /dev/null +++ b/drivers/video/display/tve/rk610_tv.c @@ -0,0 +1,246 @@ +/* + * rk610_tv.c + * + * Driver for rockchip rk610 tv control + * Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk610_tv.h" +#include "../../rk29_fb.h" + +#define DRV_NAME "rk610_tvout" +#define RK610_I2C_RATE 100*1000 + +volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT; +static struct i2c_client *rk610_tv_i2c_client = NULL; + +int rk610_tv_wirte_reg(u8 reg, u8 data) +{ + int ret; + if(rk610_tv_i2c_client == NULL) + return -1; + ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE); + if (ret > 0) + ret = 0; + return ret; +} + +int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode) +{ + struct rk29fb_screen *screen; + + if(modedb == NULL) + return -1; + screen = kzalloc(sizeof(struct rk29fb_screen), GFP_KERNEL); + if(screen == NULL) + return -1; + + memset(screen, 0, sizeof(struct rk29fb_screen)); + /* screen type & face */ + screen->type = SCREEN_HDMI; + screen->mode = modedb->vmode; + screen->face = modedb->flag; + /* Screen size */ + screen->x_res = modedb->xres; + screen->y_res = modedb->yres; + + /* Timing */ + screen->pixclock = modedb->pixclock; + + screen->lcdc_aclk = 500000000; + screen->left_margin = modedb->left_margin; + screen->right_margin = modedb->right_margin; + screen->hsync_len = modedb->hsync_len; + screen->upper_margin = modedb->upper_margin; + screen->lower_margin = modedb->lower_margin; + screen->vsync_len = modedb->vsync_len; + + /* Pin polarity */ + if(FB_SYNC_HOR_HIGH_ACT & modedb->sync) + screen->pin_hsync = 1; + else + screen->pin_hsync = 0; + if(FB_SYNC_VERT_HIGH_ACT & modedb->sync) + screen->pin_vsync = 1; + else + screen->pin_vsync = 0; + screen->pin_den = 0; + screen->pin_dclk = 0; + + /* Swap rule */ + screen->swap_rb = 0; + screen->swap_rg = 0; + screen->swap_gb = 0; + screen->swap_delta = 0; + screen->swap_dumy = 0; + + /* Operation function*/ + screen->init = NULL; + screen->standby = NULL; + + switch(tv_mode) + { +#ifdef CONFIG_RK610_TVOUT_CVBS + case TVOUT_CVBS_NTSC: + case TVOUT_CVBS_PAL: + screen->init = rk610_tv_cvbs_init;; + break; +#endif + +#ifdef CONFIG_RK610_TVOUT_YPbPr + case TVOUT_YPbPr_720x480p_60: + case TVOUT_YPbPr_720x576p_50: + case TVOUT_YPbPr_1280x720p_50: + case TVOUT_YPbPr_1280x720p_60: + //case TVOUT_YPbPr_1920x1080i_50: + case TVOUT_YPbPr_1920x1080i_60: + case TVOUT_YPbPr_1920x1080p_50: + case TVOUT_YPbPr_1920x1080p_60: + screen->init = rk610_tv_ypbpr_init; + break; +#endif + default:{ + kfree(screen); + return -1; + } + break; + } + rk610_tv_output_status = tv_mode; + FB_Switch_Screen(screen, 1); + kfree(screen); + return 0; +} + +int rk610_tv_standby(int type) +{ + int ret; + + switch(type) + { + #ifdef CONFIG_RK610_TVOUT_CVBS + case RK610_TVOUT_CVBS: + if(rk610_cvbs_monspecs.enable == 0) + return 0; + #ifdef CONFIG_RK610_TVOUT_YPbPr + if(rk610_ypbpr_monspecs.enable == 1) + return 0; + #endif + break; + #endif + #ifdef CONFIG_RK610_TVOUT_YPbPr + case RK610_TVOUT_YPBPR: + if(rk610_ypbpr_monspecs.enable == 0) + return 0; + #ifdef CONFIG_RK610_TVOUT_CVBS + if(rk610_cvbs_monspecs.enable == 1) + return 0; + #endif + break; + #endif + default: + break; + } + + ret = rk610_tv_wirte_reg(TVE_POWERCR, 0); + if(ret < 0){ + printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__); + return ret; + } + + ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0); + if(ret < 0){ + printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__); + return ret; + } + return 0; +} + +static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + int rc = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + rc = -ENODEV; + goto failout; + } + rk610_tv_i2c_client = client; + +#ifdef CONFIG_RK610_TVOUT_YPbPr + rk610_register_display_ypbpr(&client->dev); + if(rk610_tv_output_status > TVOUT_CVBS_PAL) + rk_display_device_enable(rk610_ypbpr_monspecs.ddev); +#endif + +#ifdef CONFIG_RK610_TVOUT_CVBS + rk610_register_display_cvbs(&client->dev); + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) + rk_display_device_enable(rk610_cvbs_monspecs.ddev); +#endif + + printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n"); + return 0; +failout: + kfree(client); + return rc; +} + +static int rk610_tv_remove(struct i2c_client *client) +{ + return 0; +} + + +static const struct i2c_device_id rk610_tv_id[] = { + { DRV_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rk610_tv_id); + +static struct i2c_driver rk610_tv_driver = { + .driver = { + .name = DRV_NAME, + }, + .id_table = rk610_tv_id, + .probe = rk610_tv_probe, + .remove = rk610_tv_remove, +}; + +static int __init rk610_tv_init(void) +{ + int ret = 0; + ret = i2c_add_driver(&rk610_tv_driver); + if(ret < 0){ + printk("i2c_add_driver err, ret = %d\n", ret); + } + return ret; +} + +static void __exit rk610_tv_exit(void) +{ + i2c_del_driver(&rk610_tv_driver); +} + +module_init(rk610_tv_init); +//late_initcall(rk610_tv_init); +module_exit(rk610_tv_exit); + +/* Module information */ +MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/video/display/tve/rk610_tv.h b/drivers/video/display/tve/rk610_tv.h new file mode 100644 index 000000000000..95ca56106cc0 --- /dev/null +++ b/drivers/video/display/tve/rk610_tv.h @@ -0,0 +1,129 @@ +#ifndef _RK610_TV_H +#define _RK610_TV_H +#include +#include +#include +#include +#include +#include "../screen/screen.h" +#include "../../rk29_fb.h" +#include + +#define TVE_VFCR 0x00 + #define TVE_VFCR_ENABLE_SUBCARRIER_RESET 0 << 6 + #define TVE_VFCR_DISABLE_SUBCARRIER_RESET 1 << 6 + #define TVE_VFCR_VIN_RANGE_16_235 0 << 3 + #define TVE_VFCR_VIN_RANGE_1_254 1 << 3 + #define TVE_VFCR_BLACK_7_5_IRE 0 << 2 + #define TVE_VFCR_BLACK_0_IRE 1 << 2 + #define TVE_VFCR_NTSC 0 + #define TVE_VFCR_PAL_M 1 + #define TVE_VFCR_PAL_B_N 2 + #define TVE_VFCR_PAL_NC 3 + +#define TVE_VINCR 0x01 + #define TVE_VINCR_PIX_DATA_DELAY(n) (n << 5) + #define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE 0 << 4 + #define TVE_VINCR_H_SYNC_POLARITY_POSITIVE 1 << 4 + #define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE 0 << 3 + #define TVE_VINCR_V_SYNC_POLARITY_POSITIVE 1 << 3 +enum { + INPUT_FORMAT_BT601_SLAVE = 0, + INPUT_FORMAT_BT656, + INPUT_FORMAT_BT601_MASTER, + INPUT_FORMAT_INTERNAL_COLLOR_BAR +}; + #define TVE_VINCR_INPUT_FORMAT(n) (n << 1) + #define TVE_VINCR_VSYNC_FUNCTION_VSYNC 0 + #define TVE_VINCR_VSYNC_FUNCTION_FIELD 1 + +#define TVE_VOUTCR 0x02 + #define TVE_VOUTCR_OUTPUT_CVBS 0 << 6 + #define TVE_VOUTCR_OUTPUT_YPBPR 1 << 6 + #define TVE_VOUTCR_OUTPUT_ENABLE_BLUE 1 << 5 + #define TVE_VOUTCR_OUTPUT_ENABLE_BLACK 1 << 4 + #define TVE_VOUTCR_DISABLE_CVBS_COLOR 1 << 3 + #define TVE_VOUTCR_CVBS_Y2C_DELAY(n) (n << 0) + +#define TVE_POWERCR 0x03 + #define TVE_PIX_CLK_INVERSE_ENABLE 1 << 4 + #define TVE_DAC_CLK_INVERSE_DISABLE 1 << 3 + #define TVE_DAC_Y_ENABLE 1 << 2 + #define TVE_DAC_U_ENABLE 1 << 1 + #define TVE_DAC_V_ENABLE 1 << 0 + +#define TVE_HDTVCR 0x05 + #define TVE_RESET 1 << 7 + #define TVE_FILTER(n) (n << 5) + #define TVE_COLOR_CONVERT_REC601 0 << 4 + #define TVE_COLOR_CONVERT_REC709 1 << 4 + #define TVE_INPUT_DATA_RGB 0 << 3 + #define TVE_INPUT_DATA_YUV 1 << 3 + #define TVE_OUTPUT_50HZ 0 << 2 + #define TVE_OUTPUT_60HZ 1 << 2 + #define TVE_OUTPUT_MODE_PAL_NTSC 0 + #define TVE_OUTPUT_MODE_576P 1 + #define TVE_OUTPUT_MODE_480P 2 + #define TVE_OUTPUT_MODE_720P 3 + +#define TVE_YADJCR 0x06 + #define TVE_OUTPUT_MODE_1080P 1 << 6 + #define TVE_OUTPUT_MODE_1080I 1 << 5 + #define TVE_Y_ADJ_VALUE(n) n +#define TVE_YCBADJCR 0x07 +#define TVE_YCRADJCR 0x08 + +/******************* TVOUT OUTPUT TYPE **********************/ +struct rk610_monspecs { + struct rk_display_device *ddev; + unsigned int enable; + struct fb_videomode *mode; + struct list_head modelist; + unsigned int mode_set; +}; + +enum { + TVOUT_CVBS_NTSC = 1, + TVOUT_CVBS_PAL, + TVOUT_YPbPr_720x480p_60, + TVOUT_YPbPr_720x576p_50, + TVOUT_YPbPr_1280x720p_50, + TVOUT_YPbPr_1280x720p_60, + //TVOUT_YPbPr_1920x1080i_50, + TVOUT_YPbPr_1920x1080i_60, + TVOUT_YPbPr_1920x1080p_50, + TVOUT_YPbPr_1920x1080p_60 +}; + +#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC + +enum { + RK610_TVOUT_CVBS = 0, + RK610_TVOUT_YC, + RK610_TVOUT_YPBPR, +}; + +extern volatile int rk610_tv_output_status; +extern struct rk_display_ops rk610_display_ops; + +extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ); + +extern int rk610_tv_wirte_reg(u8 reg, u8 data); +extern int rk610_tv_standby(int type); +extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode); +extern int rk610_register_display(struct device *parent); + +#ifdef CONFIG_RK610_TVOUT_YPbPr +extern int rk610_tv_ypbpr_init(void); +extern int rk610_register_display_ypbpr(struct device *parent); +extern struct rk610_monspecs rk610_ypbpr_monspecs; +#endif + +#ifdef CONFIG_RK610_TVOUT_CVBS +extern int rk610_tv_cvbs_init(void); +extern int rk610_register_display_cvbs(struct device *parent); +extern struct rk610_monspecs rk610_cvbs_monspecs; +#endif + +#endif + diff --git a/drivers/video/display/tve/rk610_tv_cvbs.c b/drivers/video/display/tve/rk610_tv_cvbs.c new file mode 100644 index 000000000000..ea0fe8a0d79c --- /dev/null +++ b/drivers/video/display/tve/rk610_tv_cvbs.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include "rk610_tv.h" + + +#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL +#define RK610_LED_CVBS_PIN RK29_PIN4_PD3 +#else +#define RK610_LED_CVBS_PIN INVALID_GPIO +#endif + +#ifdef USE_RGB2CCIR +static const struct fb_videomode rk610_cvbs_mode [] = { + //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag + { "NTSC", 60, 720, 480, 27000000, 116, 16, 25, 14, 6, 6, 0, 1, OUT_P888 }, + { "PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, OUT_P888 }, +}; +#else +static const struct fb_videomode rk610_cvbs_mode [] = { + //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag + { "NTSC", 60, 720, 480, 27000000, 116, 16, 16, 3, 6, 3, 0, 1, OUT_CCIR656 }, + { "PAL", 50, 720, 576, 27000000, 126, 12, 19, 2, 6, 3, 0, 1, OUT_CCIR656 }, +}; +#endif + +struct rk610_monspecs rk610_cvbs_monspecs; + + +int rk610_tv_cvbs_init(void) +{ + unsigned char TVE_Regs[9]; + unsigned char TVE_CON_Reg; + int ret, i; + + rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); + + memset(TVE_Regs, 0, 9); + TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE; + TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; + TVE_Regs[TVE_POWERCR] = TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; + TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_CVBS; + TVE_Regs[TVE_YADJCR] = 0x17; + TVE_Regs[TVE_YCBADJCR] = 0x10; + TVE_Regs[TVE_YCRADJCR] = 0x10; + + switch(rk610_tv_output_status) { + case TVOUT_CVBS_NTSC: + TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC; + #ifdef USE_RGB2CCIR + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; + TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE; + #else + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; + #endif + break; + case TVOUT_CVBS_PAL: + TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N; + #ifdef USE_RGB2CCIR + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC; + TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE; + #else + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC; + #endif + break; + default: + return -1; + } + + for(i = 0; i < sizeof(TVE_Regs); i++){ +// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); + ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); + if(ret < 0){ + printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i); + return ret; + } + } +// printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg); + rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); + #ifdef USE_RGB2CCIR + rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01); + #endif + return 0; +} + +static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable) +{ + if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status) + { + if(enable == 0) + { + rk610_tv_standby(RK610_TVOUT_CVBS); + rk610_cvbs_monspecs.enable = 0; + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); + } + else if(enable == 1) + { + rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set); + rk610_cvbs_monspecs.enable = 1; + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW); + } + } + return 0; +} + +static int rk610_cvbs_get_enable(struct rk_display_device *device) +{ + return rk610_cvbs_monspecs.enable; +} + +static int rk610_cvbs_get_status(struct rk_display_device *device) +{ + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) + return 1; + else + return 0; +} + +static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist) +{ + *modelist = &(rk610_cvbs_monspecs.modelist); + return 0; +} + +static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) + { + if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode)) + { + if( ((i + 1) != rk610_tv_output_status) ) + { + rk610_cvbs_monspecs.mode_set = i + 1; + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i]; + } + return 0; + } + } + + return -1; +} + +static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + *mode = *(rk610_cvbs_monspecs.mode); + return 0; +} + +static struct rk_display_ops rk610_cvbs_display_ops = { + .setenable = rk610_cvbs_set_enable, + .getenable = rk610_cvbs_get_enable, + .getstatus = rk610_cvbs_get_status, + .getmodelist = rk610_cvbs_get_modelist, + .setmode = rk610_cvbs_set_mode, + .getmode = rk610_cvbs_get_mode, +}; + +static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata) +{ + device->owner = THIS_MODULE; + strcpy(device->type, "TV"); + device->priority = DISPLAY_PRIORITY_TV; + device->priv_data = devdata; + device->ops = &rk610_cvbs_display_ops; + return 1; +} + +static struct rk_display_driver display_rk610_cvbs = { + .probe = rk610_display_cvbs_probe, +}; + +int rk610_register_display_cvbs(struct device *parent) +{ + int i; + + memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs)); + INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist); + for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++) + fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist); + if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) { + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]); + rk610_cvbs_monspecs.mode_set = rk610_tv_output_status; + } + else { + rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]); + rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC; + } + rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL); + if(RK610_LED_CVBS_PIN != INVALID_GPIO) + { + if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0) + { + gpio_free(RK610_LED_CVBS_PIN); + dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n "); + return -1; + } + gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp); + gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH); + } + return 0; +} diff --git a/drivers/video/display/tve/rk610_tv_ypbpr.c b/drivers/video/display/tve/rk610_tv_ypbpr.c new file mode 100644 index 000000000000..af74126f7604 --- /dev/null +++ b/drivers/video/display/tve/rk610_tv_ypbpr.c @@ -0,0 +1,229 @@ +#include +#include +#include +#include "rk610_tv.h" + + +#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL +#define RK610_LED_YPbPr_PIN RK29_PIN4_PD5 +#else +#define RK610_LED_YPbPr_PIN INVALID_GPIO +#endif +#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg) + +static const struct fb_videomode rk610_YPbPr_mode [] = { + //name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag + { "YPbPr480p", 60, 720, 480, 27000000, 55, 19, 37, 5, 64, 5, 0, 0, OUT_P888 }, + { "YPbPr576p", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, OUT_P888 }, + { "YPbPr720p@50", 50, 1280, 720, 74250000, 600, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, + { "YPbPr720p@60", 60, 1280, 720, 74250000, 270, 0, 20, 5, 100, 5, 0, 0, OUT_P888 }, + //{ "YPbPr1080i@50", 50, 1920, 1080, 148500000, 620, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, + { "YPbPr1080i@60", 60, 1920, 1080, 148500000, 180, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 }, + { "YPbPr1080p@50", 50, 1920, 1080, 148500000, 620, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, + { "YPbPr1080p@60", 60, 1920, 1080, 148500000, 180, 0, 36, 4, 100, 5, 0, 0, OUT_P888 }, +}; + +struct rk610_monspecs rk610_ypbpr_monspecs; + +int rk610_tv_ypbpr_init(void) +{ + unsigned char TVE_Regs[9]; + unsigned char TVE_CON_Reg; + int i, ret; + + rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET); + memset(TVE_Regs, 0, 9); + + TVE_CON_Reg = 0x00; + + TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC; + TVE_Regs[TVE_POWERCR] = TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE; + TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_YPBPR; + TVE_Regs[TVE_YADJCR] = 0x17; + TVE_Regs[TVE_YCBADJCR] = 0x10; + TVE_Regs[TVE_YCRADJCR] = 0x10; + + switch(rk610_tv_output_status) + { + case TVOUT_YPbPr_720x480p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P; + break; + case TVOUT_YPbPr_720x576p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P; + break; + case TVOUT_YPbPr_1280x720p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P; + break; + case TVOUT_YPbPr_1280x720p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P; + break; + /*case TVOUT_YPbPr_1920x1080i_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; + break; + */ + case TVOUT_YPbPr_1920x1080i_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I; + break; + case TVOUT_YPbPr_1920x1080p_50: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; + break; + case TVOUT_YPbPr_1920x1080p_60: + TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC; + TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE); + TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ; + TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P; + break; + default: + return -1; + } + + rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg); + + for(i = 0; i < sizeof(TVE_Regs); i++){ +// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]); + ret = rk610_tv_wirte_reg(i, TVE_Regs[i]); + if(ret < 0){ + E("rk610_tv_wirte_reg %d err!\n", i); + return ret; + } + } + return 0; +} + +static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable) +{ + if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status) + { + if(enable == 0) + { + rk610_tv_standby(RK610_TVOUT_YPBPR); + rk610_ypbpr_monspecs.enable = 0; + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); + } + else if(enable == 1) + { + rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set); + rk610_ypbpr_monspecs.enable = 1; + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW); + } + } + return 0; +} + +static int rk610_ypbpr_get_enable(struct rk_display_device *device) +{ + return rk610_ypbpr_monspecs.enable; +} + +static int rk610_ypbpr_get_status(struct rk_display_device *device) +{ + if(rk610_tv_output_status > TVOUT_CVBS_PAL) + return 1; + else + return 0; +} + +static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist) +{ + *modelist = &(rk610_ypbpr_monspecs.modelist); + return 0; +} + +static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) + { + if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode)) + { + if( (i + 3) != rk610_tv_output_status ) + { + rk610_ypbpr_monspecs.mode_set = i + 3; + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i]; + } + return 0; + } + } + + return -1; +} + +static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode) +{ + *mode = *(rk610_ypbpr_monspecs.mode); + return 0; +} + +static struct rk_display_ops rk610_ypbpr_display_ops = { + .setenable = rk610_ypbpr_set_enable, + .getenable = rk610_ypbpr_get_enable, + .getstatus = rk610_ypbpr_get_status, + .getmodelist = rk610_ypbpr_get_modelist, + .setmode = rk610_ypbpr_set_mode, + .getmode = rk610_ypbpr_get_mode, +}; + +static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata) +{ + device->owner = THIS_MODULE; + strcpy(device->type, "YPbPr"); + device->priority = DISPLAY_PRIORITY_YPbPr; + device->priv_data = devdata; + device->ops = &rk610_ypbpr_display_ops; + return 1; +} + +static struct rk_display_driver display_rk610_YPbPr = { + .probe = rk610_display_YPbPr_probe, +}; + +int rk610_register_display_ypbpr(struct device *parent) +{ + int i; + + memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs)); + INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist); + for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++) + fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist); + if(rk610_tv_output_status > TVOUT_CVBS_PAL) { + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]); + rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status; + } + else { + rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]); + rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60; + } + rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL); + if(RK610_LED_YPbPr_PIN != INVALID_GPIO) + { + if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0) + { + gpio_free(RK610_LED_YPbPr_PIN); + dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n "); + return -1; + } + gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp); + gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH); + } + return 0; +} diff --git a/drivers/video/hdmi/Kconfig b/drivers/video/hdmi/Kconfig index 2d68da6d7f92..fe8bf2f46697 100755 --- a/drivers/video/hdmi/Kconfig +++ b/drivers/video/hdmi/Kconfig @@ -14,11 +14,13 @@ config HDMI_SAVE_DATA bool "enable hdmi save data" help Enable hdmi save data in rtc register + +config HDMI_DUAL_DISP + bool "dual display support" + depends on RK610_HDMI + help + Support output lcd and hdmi at the same time. -#config HDMI_DUAL_DISP -# bool "hdmi support dual display" -# help -# nothing #config HDMI_DEBUG # bool "hdmi debug" endif diff --git a/drivers/video/hdmi/chips/Kconfig b/drivers/video/hdmi/chips/Kconfig index a1b838f76179..9ad25b699768 100755 --- a/drivers/video/hdmi/chips/Kconfig +++ b/drivers/video/hdmi/chips/Kconfig @@ -4,4 +4,9 @@ config ANX7150 bool "anx7150" config ANX9030 bool "anx9030" +config RK610_HDMI + bool "RK610(Jetta) hdmi support" + depends on MFD_RK610 + help + Support Jetta(RK610) to hdmi. endchoice diff --git a/drivers/video/hdmi/chips/Makefile b/drivers/video/hdmi/chips/Makefile index 92959ebe9772..48245f5cfe5b 100755 --- a/drivers/video/hdmi/chips/Makefile +++ b/drivers/video/hdmi/chips/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_ANX7150) += anx7150_hw.o anx7150.o - +obj-$(CONFIG_ANX7150) += anx7150/anx7150.o anx7150/anx7150_hw.o +obj-$(CONFIG_RK610_HDMI) += rk610/rk610_hdmi.o rk610/rk610_hdmi_hw.o diff --git a/drivers/video/hdmi/chips/anx7150.c b/drivers/video/hdmi/chips/anx7150.c deleted file mode 100755 index 8a6239cf1c19..000000000000 --- a/drivers/video/hdmi/chips/anx7150.c +++ /dev/null @@ -1,284 +0,0 @@ -#include -#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 anx7150_precent(struct hdmi *hdmi) -{ - struct anx7150_pdata *anx = hdmi_priv(hdmi); - - return gpio_get_value(anx->client->irq)?0:1; -} -static int anx7150_param_chg(struct anx7150_pdata *anx) -{ - int resolution_real; - - hdmi_switch_fb(anx->hdmi, HDMI_ENABLE); - resolution_real = ANX7150_Get_Optimal_resolution(anx->hdmi->resolution); - HDMI_Set_Video_Format(resolution_real); - HDMI_Set_Audio_Fs(anx->hdmi->audio_fs); - ANX7150_API_HDCP_ONorOFF(anx->hdmi->hdcp_on); - ANX7150_API_System_Config(); - ANX7150_Config_Video(anx->client); - - ANX7150_Config_Audio(anx->client); - ANX7150_Config_Packet(anx->client); - ANX7150_HDCP_Process(anx->client, anx->hdmi->display_on); - ANX7150_PLAYBACK_Process(); - - return 0; -} - -static int anx7150_insert(struct hdmi *hdmi) -{ - int tmo = 10; - struct anx7150_pdata *anx = hdmi_priv(hdmi); - - if(anx->init == 1) - return -1; - - anx7150_plug(anx->client); - hdmi_dbg(&anx->client->dev, "parse edid\n"); - if(ANX7150_Parse_EDID(anx->client,&anx->dev) < 0) - { - dev_info(hdmi->dev, "parse EDID error\n"); - anx7150_unplug(anx->client); - return -1; - } - - while(--tmo && ANX7150_GET_SENSE_STATE(anx->client) != 1) - mdelay(10); - if(tmo <= 0) - { - anx7150_unplug(anx->client); - dev_dbg(hdmi->dev, "get sense_state error\n"); - return -1; - } - hdmi_set_spk(HDMI_DISABLE); - hdmi_set_backlight(HDMI_DISABLE); - hdmi->scale = hdmi->scale_set; - anx7150_param_chg(anx); - return 0; -} -static int anx7150_remove(struct hdmi *hdmi) -{ - struct anx7150_pdata *anx = hdmi_priv(hdmi); - - if(anx->init == 1) - return -1; - - anx7150_unplug(anx->client); - hdmi->scale = 100; - hdmi_set_spk(HDMI_ENABLE); - hdmi_switch_fb(hdmi, HDMI_DISABLE); - hdmi_set_backlight(HDMI_ENABLE); - - return 0; -} - -static int anx7150_set_param(struct hdmi *hdmi) -{ - struct anx7150_pdata *anx = hdmi_priv(hdmi); - if(anx->init == 1) - return 0; - - anx7150_param_chg(anx); - return 0; -} - -static int anx7150_init(struct hdmi *hdmi) -{ - struct anx7150_pdata *anx = hdmi_priv(hdmi); -#ifdef CONFIG_HDMI_SAVE_DATA - int hdmi_data = hdmi_get_data(); - if(hdmi_data<0){ - hdmi_set_data((hdmi->resolution&0x7)|((hdmi->scale&0x1f)<<3)); - } - else{ - hdmi->resolution = hdmi_data&0x7; - hdmi->scale_set= ((hdmi_data>>3)&0x1f) + MIN_SCALE; - hdmi->scale = hdmi->scale_set; - } -#endif - anx->init = 0; - hdmi_changed(hdmi,1); - - return 0; -} -static void anx7150_init_work_func(struct work_struct *work) -{ - struct anx7150_pdata *anx = container_of(work, struct anx7150_pdata, work.work); - - if(anx!=NULL) - anx7150_init(anx->hdmi); - else - printk("anx7150_init_work_func err\n"); -} -static struct hdmi_ops anx7150_ops = { - .set_param = anx7150_set_param, - .hdmi_precent = anx7150_precent, - .insert = anx7150_insert, - .remove = anx7150_remove, - .init = anx7150_init, -}; -#ifdef CONFIG_HAS_EARLYSUSPEND -static void anx7150_early_suspend(struct early_suspend *h) -{ - struct anx7150_pdata *anx = container_of(h, - struct anx7150_pdata, - early_suspend); - dev_info(&anx->client->dev, "anx7150 enter early suspend\n"); - hdmi_suspend(anx->hdmi); - return; -} - -static void anx7150_early_resume(struct early_suspend *h) -{ - struct anx7150_pdata *anx = container_of(h, - struct anx7150_pdata, - early_suspend); - dev_info(&anx->client->dev, "anx7150 exit early suspend\n"); - hdmi_resume(anx->hdmi); - return; -} -#endif - -static int anx7150_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id) -{ - int ret = 0; - struct hdmi *hdmi = NULL; - struct anx7150_pdata *anx = NULL; - - struct hdmi_platform_data *pdata = client->dev.platform_data; - - if(pdata && pdata->io_init) - pdata->io_init(); - - hdmi = hdmi_register(sizeof(struct anx7150_pdata), &client->dev); - if (!hdmi) - { - dev_err(&client->dev, "fail to register hdmi\n"); - return -ENOMEM; - } - hdmi->ops = &anx7150_ops; - hdmi->display_on = HDMI_DEFAULT_MODE; - hdmi->hdcp_on = HDMI_DISABLE; - hdmi->audio_fs = HDMI_I2S_DEFAULT_Fs; - hdmi->resolution = HDMI_DEFAULT_RESOLUTION; - hdmi->dual_disp = DUAL_DISP_CAP; - hdmi->mode = DISP_ON_LCD; - hdmi->scale = 100; - hdmi->scale_set = 100; - - anx = hdmi_priv(hdmi); - anx->init = 1; - anx->hdmi = hdmi; - i2c_set_clientdata(client, anx); - anx->client = client; - - if((ret = gpio_request(client->irq, "hdmi gpio")) < 0) - { - dev_err(&client->dev, "fail to request gpio %d\n", client->irq); - goto err_hdmi_unregister; - } - //gpio_pull_updown(client->irq,0); - gpio_direction_input(client->irq); - - if(anx7150_detect_device(anx) < 0) - { - dev_err(&client->dev, "anx7150 is not exist\n"); - ret = -EIO; - goto err_gpio_free; - } - -#ifdef CONFIG_HAS_EARLYSUSPEND - anx->early_suspend.suspend = anx7150_early_suspend; - anx->early_suspend.resume = anx7150_early_resume; - anx->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1; - register_early_suspend(&anx->early_suspend); -#endif - anx7150_unplug(anx->client); - INIT_DELAYED_WORK(&anx->work,anx7150_init_work_func); - schedule_delayed_work(&anx->work, msecs_to_jiffies(2000)); - dev_info(&client->dev, "anx7150 i2c probe ok\n"); - return 0; -err_gpio_free: - gpio_free(client->irq); -err_hdmi_unregister: - hdmi_unregister(hdmi); - anx = NULL; - return ret; -} - -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->hdmi; - - gpio_free(client->irq); - hdmi_unregister(hdmi); - anx = NULL; - 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_module_init(void) -{ - return i2c_add_driver(&anx7150_i2c_driver); -} - -static void __exit anx7150_module_exit(void) -{ - i2c_del_driver(&anx7150_i2c_driver); -} - -module_init(anx7150_module_init); -//fs_initcall(anx7150_module_init); -module_exit(anx7150_module_exit); - - diff --git a/drivers/video/hdmi/chips/anx7150.h b/drivers/video/hdmi/chips/anx7150.h deleted file mode 100755 index b9c5ee329e2a..000000000000 --- a/drivers/video/hdmi/chips/anx7150.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _ANX7150_H -#define _ANX7150_H - -#include -#include - - -#define ANX7150_I2C_ADDR0 0X39 -#define ANX7150_I2C_ADDR1 0X3d - -#define ANX7150_SCL_RATE 100 * 1000 - - -/* 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 - -/* 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; - int is_early_suspend; - int is_changed; - struct delayed_work work; - struct hdmi *hdmi; - struct i2c_client *client; - struct anx7150_dev_s dev; -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif -}; - - - -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/anx7150.c b/drivers/video/hdmi/chips/anx7150/anx7150.c new file mode 100644 index 000000000000..8a6239cf1c19 --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150/anx7150.c @@ -0,0 +1,284 @@ +#include +#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 anx7150_precent(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_priv(hdmi); + + return gpio_get_value(anx->client->irq)?0:1; +} +static int anx7150_param_chg(struct anx7150_pdata *anx) +{ + int resolution_real; + + hdmi_switch_fb(anx->hdmi, HDMI_ENABLE); + resolution_real = ANX7150_Get_Optimal_resolution(anx->hdmi->resolution); + HDMI_Set_Video_Format(resolution_real); + HDMI_Set_Audio_Fs(anx->hdmi->audio_fs); + ANX7150_API_HDCP_ONorOFF(anx->hdmi->hdcp_on); + ANX7150_API_System_Config(); + ANX7150_Config_Video(anx->client); + + ANX7150_Config_Audio(anx->client); + ANX7150_Config_Packet(anx->client); + ANX7150_HDCP_Process(anx->client, anx->hdmi->display_on); + ANX7150_PLAYBACK_Process(); + + return 0; +} + +static int anx7150_insert(struct hdmi *hdmi) +{ + int tmo = 10; + struct anx7150_pdata *anx = hdmi_priv(hdmi); + + if(anx->init == 1) + return -1; + + anx7150_plug(anx->client); + hdmi_dbg(&anx->client->dev, "parse edid\n"); + if(ANX7150_Parse_EDID(anx->client,&anx->dev) < 0) + { + dev_info(hdmi->dev, "parse EDID error\n"); + anx7150_unplug(anx->client); + return -1; + } + + while(--tmo && ANX7150_GET_SENSE_STATE(anx->client) != 1) + mdelay(10); + if(tmo <= 0) + { + anx7150_unplug(anx->client); + dev_dbg(hdmi->dev, "get sense_state error\n"); + return -1; + } + hdmi_set_spk(HDMI_DISABLE); + hdmi_set_backlight(HDMI_DISABLE); + hdmi->scale = hdmi->scale_set; + anx7150_param_chg(anx); + return 0; +} +static int anx7150_remove(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_priv(hdmi); + + if(anx->init == 1) + return -1; + + anx7150_unplug(anx->client); + hdmi->scale = 100; + hdmi_set_spk(HDMI_ENABLE); + hdmi_switch_fb(hdmi, HDMI_DISABLE); + hdmi_set_backlight(HDMI_ENABLE); + + return 0; +} + +static int anx7150_set_param(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_priv(hdmi); + if(anx->init == 1) + return 0; + + anx7150_param_chg(anx); + return 0; +} + +static int anx7150_init(struct hdmi *hdmi) +{ + struct anx7150_pdata *anx = hdmi_priv(hdmi); +#ifdef CONFIG_HDMI_SAVE_DATA + int hdmi_data = hdmi_get_data(); + if(hdmi_data<0){ + hdmi_set_data((hdmi->resolution&0x7)|((hdmi->scale&0x1f)<<3)); + } + else{ + hdmi->resolution = hdmi_data&0x7; + hdmi->scale_set= ((hdmi_data>>3)&0x1f) + MIN_SCALE; + hdmi->scale = hdmi->scale_set; + } +#endif + anx->init = 0; + hdmi_changed(hdmi,1); + + return 0; +} +static void anx7150_init_work_func(struct work_struct *work) +{ + struct anx7150_pdata *anx = container_of(work, struct anx7150_pdata, work.work); + + if(anx!=NULL) + anx7150_init(anx->hdmi); + else + printk("anx7150_init_work_func err\n"); +} +static struct hdmi_ops anx7150_ops = { + .set_param = anx7150_set_param, + .hdmi_precent = anx7150_precent, + .insert = anx7150_insert, + .remove = anx7150_remove, + .init = anx7150_init, +}; +#ifdef CONFIG_HAS_EARLYSUSPEND +static void anx7150_early_suspend(struct early_suspend *h) +{ + struct anx7150_pdata *anx = container_of(h, + struct anx7150_pdata, + early_suspend); + dev_info(&anx->client->dev, "anx7150 enter early suspend\n"); + hdmi_suspend(anx->hdmi); + return; +} + +static void anx7150_early_resume(struct early_suspend *h) +{ + struct anx7150_pdata *anx = container_of(h, + struct anx7150_pdata, + early_suspend); + dev_info(&anx->client->dev, "anx7150 exit early suspend\n"); + hdmi_resume(anx->hdmi); + return; +} +#endif + +static int anx7150_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + int ret = 0; + struct hdmi *hdmi = NULL; + struct anx7150_pdata *anx = NULL; + + struct hdmi_platform_data *pdata = client->dev.platform_data; + + if(pdata && pdata->io_init) + pdata->io_init(); + + hdmi = hdmi_register(sizeof(struct anx7150_pdata), &client->dev); + if (!hdmi) + { + dev_err(&client->dev, "fail to register hdmi\n"); + return -ENOMEM; + } + hdmi->ops = &anx7150_ops; + hdmi->display_on = HDMI_DEFAULT_MODE; + hdmi->hdcp_on = HDMI_DISABLE; + hdmi->audio_fs = HDMI_I2S_DEFAULT_Fs; + hdmi->resolution = HDMI_DEFAULT_RESOLUTION; + hdmi->dual_disp = DUAL_DISP_CAP; + hdmi->mode = DISP_ON_LCD; + hdmi->scale = 100; + hdmi->scale_set = 100; + + anx = hdmi_priv(hdmi); + anx->init = 1; + anx->hdmi = hdmi; + i2c_set_clientdata(client, anx); + anx->client = client; + + if((ret = gpio_request(client->irq, "hdmi gpio")) < 0) + { + dev_err(&client->dev, "fail to request gpio %d\n", client->irq); + goto err_hdmi_unregister; + } + //gpio_pull_updown(client->irq,0); + gpio_direction_input(client->irq); + + if(anx7150_detect_device(anx) < 0) + { + dev_err(&client->dev, "anx7150 is not exist\n"); + ret = -EIO; + goto err_gpio_free; + } + +#ifdef CONFIG_HAS_EARLYSUSPEND + anx->early_suspend.suspend = anx7150_early_suspend; + anx->early_suspend.resume = anx7150_early_resume; + anx->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1; + register_early_suspend(&anx->early_suspend); +#endif + anx7150_unplug(anx->client); + INIT_DELAYED_WORK(&anx->work,anx7150_init_work_func); + schedule_delayed_work(&anx->work, msecs_to_jiffies(2000)); + dev_info(&client->dev, "anx7150 i2c probe ok\n"); + return 0; +err_gpio_free: + gpio_free(client->irq); +err_hdmi_unregister: + hdmi_unregister(hdmi); + anx = NULL; + return ret; +} + +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->hdmi; + + gpio_free(client->irq); + hdmi_unregister(hdmi); + anx = NULL; + 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_module_init(void) +{ + return i2c_add_driver(&anx7150_i2c_driver); +} + +static void __exit anx7150_module_exit(void) +{ + i2c_del_driver(&anx7150_i2c_driver); +} + +module_init(anx7150_module_init); +//fs_initcall(anx7150_module_init); +module_exit(anx7150_module_exit); + + diff --git a/drivers/video/hdmi/chips/anx7150/anx7150.h b/drivers/video/hdmi/chips/anx7150/anx7150.h new file mode 100644 index 000000000000..b9c5ee329e2a --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150/anx7150.h @@ -0,0 +1,99 @@ +#ifndef _ANX7150_H +#define _ANX7150_H + +#include +#include + + +#define ANX7150_I2C_ADDR0 0X39 +#define ANX7150_I2C_ADDR1 0X3d + +#define ANX7150_SCL_RATE 100 * 1000 + + +/* 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 + +/* 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; + int is_early_suspend; + int is_changed; + struct delayed_work work; + struct hdmi *hdmi; + struct i2c_client *client; + struct anx7150_dev_s dev; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + + + +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/anx7150_hw.c b/drivers/video/hdmi/chips/anx7150/anx7150_hw.c new file mode 100644 index 000000000000..bb9055f6e3cb --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150/anx7150_hw.c @@ -0,0 +1,4382 @@ +#include +#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 + //1080p-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*/, 0x24/*V_BP_LINE*/, + 0x04/*V_FP_LINE*/, 0x58/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, + //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}, + + //1080p-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*/, 0x24/*V_BP_LINE*/, + 0x04/*V_FP_LINE*/, 0x10/*H_FP_LOW*/, 0x02/*H_FP_HIGH*/, + ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_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 = NULL; +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_DDC_Mass_Read(struct i2c_client *client, u8 *buf, u16 len); + +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 0; + } + } + + hdmi_dbg(&anx->client->dev, "anx7150 not detected"); + return -1; +} +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: + dev_info(&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: + dev_info(&client->dev, "PLAY_BACK\n"); + break; + default: + hdmi_dbg(&client->dev, "unknown state\n"); + break; + } +} + +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 = 1; + 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 &= (0xfe); + 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_initial(struct i2c_client *client) +{ + ANX7150_Variable_Initial(); //simon + ANX7150_HW_Interface_Variable_Initial(); //simon + + anx7150_hardware_initial(client); //simon + return 0; +} +int anx7150_unplug(struct i2c_client *client) +{ + int rc = 0; + char c; + dev_info(&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; + + dev_info(&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; +} + +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; +} +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; + + 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 > 1){ + 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; + } + + anx->dev.HPD_change_cnt = 0; + anx->dev.HPD_status = hot_plug; + } + return state; + 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; + int rc = 0; + + anx7150_rst_ddcchannel(client); + + rc = anx7150_initddc_read(client, 0xa0, 0x00, 0x7e, 0x01, 0x00); + + mdelay(10); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &edid_data_length); + + ANX7150_edid_length = edid_data_length * 128 + 128; + + return rc; + +} +/*** DDC fetch and block validation ***/ + +static const u8 edid_header[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 +}; + + +/* + * Sanity check the EDID block (base or extension). Return 0 if the block + * doesn't check out, or 1 if it's valid. + */ + +int anx7150_edid_block_valid(struct i2c_client *client, u8 *raw_edid) +{ + int i; + u8 csum = 0; + struct edid *edid = (struct edid *)raw_edid; + + if (raw_edid[0] == 0x00) { + int score = 0; + + for (i = 0; i < sizeof(edid_header); i++) + if (raw_edid[i] == edid_header[i]) + score++; + + if (score == 8) ; + else if (score >= 6) { + hdmi_dbg(&client->dev, "Fixing EDID header, your hardware may be failing\n"); + memcpy(raw_edid, edid_header, sizeof(edid_header)); + } else { + goto bad; + } + } + +#if 0 + for (i = 0; i < EDID_LENGTH; i++) + csum += raw_edid[i]; + if (csum) { + hdmi_dbg(&client->dev, "EDID checksum is invalid, remainder is %d\n", csum); + + /* allow CEA to slide through, switches mangle this */ + if (raw_edid[0] != 0x02) + goto bad; + } +#endif + + /* per-block-type checks */ + switch (raw_edid[0]) { + case 0: /* base */ + if (edid->version != 1) { + dev_err(&client->dev, "EDID has major version %d, instead of 1\n", edid->version); + goto bad; + } + + if (edid->revision > 4) + dev_err(&client->dev,"EDID minor > 4, assuming backward compatibility\n"); + break; + + default: + break; + } + + return 1; + +bad: + if (raw_edid) { + dev_err(&client->dev, "Raw EDID:\n"); + print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); + printk("\n"); + } + return 0; +} +int ANX7150_DDC_EDID(struct i2c_client *client, u8 *buf, u8 block, u16 len) +{ + u8 offset; + u8 segment; + u8 len_low; + u8 len_high; + + offset = EDID_LENGTH * (block & 0x01); + segment = block >> 1; + len_low = len & 0xFF; + len_high = (len >> 8) & 0xFF; + + anx7150_initddc_read(client, 0xa0, segment, offset, len_low, len_high); + if(ANX7150_DDC_Mass_Read(client, buf, len) == len) + return 0; + else + return -1; +} +u8 *ANX7150_Read_EDID(struct i2c_client *client) +{ + u8 *block = NULL; + u8 *raw_edid = NULL; + u8 extend_block_num; + int i = 0; + int j = 0; + + anx7150_rst_ddcchannel(client); + + if ((block = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + return NULL; + + /* base block fetch */ + hdmi_dbg(&client->dev, "Read base block\n"); + for (i = 0; i < 4; i++) { + if(ANX7150_DDC_EDID(client, block, 0, EDID_LENGTH)) + goto out; + if(anx7150_edid_block_valid(client, block)) + break; + else + dev_err(&client->dev, "Read base block err, retry...\n"); + + mdelay(10); + } + + if(i == 4){ + dev_err(&client->dev, "Read base block failed\n"); + goto out; + } + + /* if there's no extensions, we're done */ + extend_block_num = block[0x7e]; + if(extend_block_num == 0) + goto out; + + dev_err(&client->dev, "extend_block_num = %d\n", extend_block_num); + + raw_edid = krealloc(block, (extend_block_num + 1) * EDID_LENGTH, GFP_KERNEL); + if(!raw_edid) + goto out; + + block = raw_edid; + + hdmi_dbg(&client->dev, "Read extend block\n"); + for(j=1; j<=extend_block_num; j++){ + for(i=0; i<4; i++){ + if(ANX7150_DDC_EDID(client, raw_edid + j * EDID_LENGTH, j, EDID_LENGTH)) + goto out; + if(anx7150_edid_block_valid(client, raw_edid + j * EDID_LENGTH)) + break; + else + dev_err(&client->dev, "Read extend block %d err, retry...\n", j); + + mdelay(10); + } + + if(i == 4){ + dev_err(&client->dev, "Read extend block %d failed\n", j); + goto out; + } + } + + dev_err(&client->dev, "\n\nRaw EDID(extend_block_num = %d, total_len = %d):\n\n", extend_block_num, EDID_LENGTH*(extend_block_num+1)); + print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH*(extend_block_num+1)); + printk("\n\n"); + + return raw_edid; + +out: + kfree(block); + return NULL; +} +int ANX7150_DDC_Mass_Read(struct i2c_client *client, u8 *buf, u16 len) +{ + int rc = 0; + u32 i, j; + char c, c1,ddc_empty_cnt; + + i = len; + 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) + break; + } + } + return (len - i); +} + +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; + + + ANX7150_EDID_Buf = ANX7150_Read_EDID(client); + + if(!ANX7150_EDID_Buf){ + ANX7150_edid_result.edid_errcode = ANX7150_EDID_BadHeader; + dev_err(&client->dev, "READ EDID ERROR\n"); + 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) + { + hdmi_dbg(&client->dev, "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_1080p_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080p_60Hz); + hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_1080p_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080p_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; + kfree(ANX7150_EDID_Buf); + ANX7150_EDID_Buf = NULL; + return 0; + +err: + if(ANX7150_EDID_Buf){ + kfree(ANX7150_EDID_Buf); + ANX7150_EDID_Buf = NULL; + } + 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_4x3: + if(ANX7150_edid_result.supported_576p_50Hz){ + resolution_real = HDMI_720x576p_50Hz_4x3; + find_resolution = 1; + } + break; + case HDMI_720x576p_50Hz_16x9: + if(ANX7150_edid_result.supported_576p_50Hz){ + resolution_real = HDMI_720x576p_50Hz_16x9; + find_resolution = 1; + } + break; + case HDMI_720x480p_60Hz_4x3: + if(ANX7150_edid_result.supported_720x480p_60Hz){ + resolution_real = HDMI_720x480p_60Hz_4x3; + find_resolution = 1; + } + break; + case HDMI_720x480p_60Hz_16x9: + if(ANX7150_edid_result.supported_720x480p_60Hz){ + resolution_real = HDMI_720x480p_60Hz_16x9; + find_resolution = 1; + } + break; + case HDMI_1920x1080p_50Hz: + if(ANX7150_edid_result.supported_1080p_50Hz){ + resolution_real = HDMI_1920x1080p_50Hz; + find_resolution = 1; + } + break; + case HDMI_1920x1080p_60Hz: + if(ANX7150_edid_result.supported_1080p_60Hz){ + resolution_real = HDMI_1920x1080p_60Hz; + 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_4x3; + else if(ANX7150_edid_result.supported_720x480p_60Hz) + resolution_real = HDMI_720x480p_60Hz_4x3; + else if(ANX7150_edid_result.supported_1080p_50Hz) + resolution_real = HDMI_1920x1080p_50Hz; + else if(ANX7150_edid_result.supported_1080p_60Hz) + resolution_real = HDMI_1920x1080p_60Hz; + 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; +} +int ANX7150_Blue_Screen(struct anx7150_pdata *anx) +{ + return anx7150_blue_screen_format_config(anx->client); +} +//******************************Video Config*************************************** +int ANX7150_Config_Video(struct i2c_client *client) +{ + int rc = 0; + int retry = 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"); + + retry = 0; + do{ + mdelay(60); + rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_STATUS_REG, &c); + if (c & ANX7150_VID_STATUS_VID_STABLE){ + hdmi_dbg(&client->dev, "Video stable, continue!\n"); + break; + } + else{ + hdmi_dbg(&client->dev,"Video not stable!, retry = %d\n", retry); + } + }while(retry++ < 5); + + 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); + if(ANX7150_HDCP_enable) + mdelay(100); //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"); + c = 0x00; + 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); + + // set the relation of MCLK and Fs xy 070117 + 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); + 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_V720x480p_60Hz_4x3: + case ANX7150_V720x480p_60Hz_16x9: + case ANX7150_V720x576p_50Hz_4x3: + case ANX7150_V720x576p_50Hz_16x9: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0x58; + break; + case ANX7150_V1280x720p_50Hz: + case ANX7150_V1280x720p_60Hz: + case ANX7150_V1920x1080p_50Hz: + case ANX7150_V1920x1080p_60Hz: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xa8; + break; + default: + s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xa8; + 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); + mdelay(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); + mdelay(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 + mdelay(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 enable) +{ + 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); + mdelay(10);//let unencrypted video play a while, required by HDCP CTS. SY//wen HDCP CTS + anx7150_set_avmute(client);//before auth, set_avmute//wen + mdelay(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"); + mdelay(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. + { + mdelay(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); + if(!enable) + anx7150_set_avmute(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_4x3: + g_video_format = ANX7150_V720x576p_50Hz_4x3; + break; + case HDMI_720x576p_50Hz_16x9: + g_video_format = ANX7150_V720x576p_50Hz_16x9; + break; + case HDMI_720x480p_60Hz_4x3: + g_video_format = ANX7150_V720x480p_60Hz_4x3; + break; + case HDMI_720x480p_60Hz_16x9: + g_video_format = ANX7150_V720x480p_60Hz_16x9; + break; + case HDMI_1920x1080p_50Hz: + g_video_format = ANX7150_V1920x1080p_50Hz; + break; + case HDMI_1920x1080p_60Hz: + g_video_format = ANX7150_V1920x1080p_60Hz; + 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/anx7150_hw.h b/drivers/video/hdmi/chips/anx7150/anx7150_hw.h new file mode 100644 index 000000000000..af8d900096e7 --- /dev/null +++ b/drivers/video/hdmi/chips/anx7150/anx7150_hw.h @@ -0,0 +1,1401 @@ +#ifndef _ANX7150_HW_H +#define _ANX7150_HW_H + +#include + +#define EDID_LENGTH 128 +struct est_timings { + u8 t1; + u8 t2; + u8 mfg_rsvd; +} __attribute__((packed)); + +struct std_timing { + u8 hsize; /* need to multiply by 8 then add 248 */ + u8 vfreq_aspect; +} __attribute__((packed)); + +/* If detailed data is pixel timing */ +struct detailed_pixel_timing { + u8 hactive_lo; + u8 hblank_lo; + u8 hactive_hblank_hi; + u8 vactive_lo; + u8 vblank_lo; + u8 vactive_vblank_hi; + u8 hsync_offset_lo; + u8 hsync_pulse_width_lo; + u8 vsync_offset_pulse_width_lo; + u8 hsync_vsync_offset_pulse_width_hi; + u8 width_mm_lo; + u8 height_mm_lo; + u8 width_height_mm_hi; + u8 hborder; + u8 vborder; + u8 misc; +} __attribute__((packed)); + +/* If it's not pixel timing, it'll be one of the below */ +struct detailed_data_string { + u8 str[13]; +} __attribute__((packed)); + +struct detailed_data_monitor_range { + u8 min_vfreq; + u8 max_vfreq; + u8 min_hfreq_khz; + u8 max_hfreq_khz; + u8 pixel_clock_mhz; /* need to multiply by 10 */ + __le16 sec_gtf_toggle; /* A000=use above, 20=use below */ + u8 hfreq_start_khz; /* need to multiply by 2 */ + u8 c; /* need to divide by 2 */ + __le16 m; + u8 k; + u8 j; /* need to divide by 2 */ +} __attribute__((packed)); + +struct detailed_data_wpindex { + u8 white_yx_lo; /* Lower 2 bits each */ + u8 white_x_hi; + u8 white_y_hi; + u8 gamma; /* need to divide by 100 then add 1 */ +} __attribute__((packed)); + +struct detailed_data_color_point { + u8 windex1; + u8 wpindex1[3]; + u8 windex2; + u8 wpindex2[3]; +} __attribute__((packed)); + +struct cvt_timing { + u8 code[3]; +} __attribute__((packed)); + +struct detailed_non_pixel { + u8 pad1; + u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name + fb=color point data, fa=standard timing data, + f9=undefined, f8=mfg. reserved */ + u8 pad2; + union { + struct detailed_data_string str; + struct detailed_data_monitor_range range; + struct detailed_data_wpindex color; + struct std_timing timings[6]; + struct cvt_timing cvt[4]; + } data; +} __attribute__((packed)); + +struct detailed_timing { + __le16 pixel_clock; /* need to multiply by 10 KHz */ + union { + struct detailed_pixel_timing pixel_data; + struct detailed_non_pixel other_data; + } data; +} __attribute__((packed)); + +struct edid { + u8 header[8]; + /* Vendor & product info */ + u8 mfg_id[2]; + u8 prod_code[2]; + u32 serial; /* FIXME: byte order */ + u8 mfg_week; + u8 mfg_year; + /* EDID version */ + u8 version; + u8 revision; + /* Display info: */ + u8 input; + u8 width_cm; + u8 height_cm; + u8 gamma; + u8 features; + /* Color characteristics */ + u8 red_green_lo; + u8 black_white_lo; + u8 red_x; + u8 red_y; + u8 green_x; + u8 green_y; + u8 blue_x; + u8 blue_y; + u8 white_x; + u8 white_y; + /* Est. timings and mfg rsvd timings*/ + struct est_timings established_timings; + /* Standard timings 1-8*/ + struct std_timing standard_timings[8]; + /* Detailing timings 1-4 */ + struct detailed_timing detailed_timings[4]; + /* Number of 128 byte ext. blocks */ + u8 extensions; + /* Checksum */ + u8 checksum; +} __attribute__((packed)); + +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_1920x1080p_60Hz[18]; + //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_1920x1080p_50Hz[18]; + /* 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 +*/ + int anx7150_get_hpd(struct i2c_client *client); + +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 enable); +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); +int ANX7150_Blue_Screen(struct anx7150_pdata *anx); +int anx7150_set_avmute(struct i2c_client *client); +int anx7150_initial(struct i2c_client *client); + +#endif diff --git a/drivers/video/hdmi/chips/anx7150_hw.c b/drivers/video/hdmi/chips/anx7150_hw.c deleted file mode 100644 index bb9055f6e3cb..000000000000 --- a/drivers/video/hdmi/chips/anx7150_hw.c +++ /dev/null @@ -1,4382 +0,0 @@ -#include -#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 - //1080p-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*/, 0x24/*V_BP_LINE*/, - 0x04/*V_FP_LINE*/, 0x58/*H_FP_LOW*/, 0x00/*H_FP_HIGH*/, - ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_Vsync_pol}, - //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}, - - //1080p-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*/, 0x24/*V_BP_LINE*/, - 0x04/*V_FP_LINE*/, 0x10/*H_FP_LOW*/, 0x02/*H_FP_HIGH*/, - ANX7150_Interlace, ANX7150_Pos_Hsync_pol, ANX7150_Pos_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 = NULL; -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_DDC_Mass_Read(struct i2c_client *client, u8 *buf, u16 len); - -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 0; - } - } - - hdmi_dbg(&anx->client->dev, "anx7150 not detected"); - return -1; -} -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: - dev_info(&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: - dev_info(&client->dev, "PLAY_BACK\n"); - break; - default: - hdmi_dbg(&client->dev, "unknown state\n"); - break; - } -} - -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 = 1; - 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 &= (0xfe); - 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_initial(struct i2c_client *client) -{ - ANX7150_Variable_Initial(); //simon - ANX7150_HW_Interface_Variable_Initial(); //simon - - anx7150_hardware_initial(client); //simon - return 0; -} -int anx7150_unplug(struct i2c_client *client) -{ - int rc = 0; - char c; - dev_info(&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; - - dev_info(&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; -} - -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; -} -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; - - 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 > 1){ - 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; - } - - anx->dev.HPD_change_cnt = 0; - anx->dev.HPD_status = hot_plug; - } - return state; - 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; - int rc = 0; - - anx7150_rst_ddcchannel(client); - - rc = anx7150_initddc_read(client, 0xa0, 0x00, 0x7e, 0x01, 0x00); - - mdelay(10); - rc = anx7150_i2c_read_p0_reg(client, ANX7150_DDC_FIFO_ACC_REG, &edid_data_length); - - ANX7150_edid_length = edid_data_length * 128 + 128; - - return rc; - -} -/*** DDC fetch and block validation ***/ - -static const u8 edid_header[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 -}; - - -/* - * Sanity check the EDID block (base or extension). Return 0 if the block - * doesn't check out, or 1 if it's valid. - */ - -int anx7150_edid_block_valid(struct i2c_client *client, u8 *raw_edid) -{ - int i; - u8 csum = 0; - struct edid *edid = (struct edid *)raw_edid; - - if (raw_edid[0] == 0x00) { - int score = 0; - - for (i = 0; i < sizeof(edid_header); i++) - if (raw_edid[i] == edid_header[i]) - score++; - - if (score == 8) ; - else if (score >= 6) { - hdmi_dbg(&client->dev, "Fixing EDID header, your hardware may be failing\n"); - memcpy(raw_edid, edid_header, sizeof(edid_header)); - } else { - goto bad; - } - } - -#if 0 - for (i = 0; i < EDID_LENGTH; i++) - csum += raw_edid[i]; - if (csum) { - hdmi_dbg(&client->dev, "EDID checksum is invalid, remainder is %d\n", csum); - - /* allow CEA to slide through, switches mangle this */ - if (raw_edid[0] != 0x02) - goto bad; - } -#endif - - /* per-block-type checks */ - switch (raw_edid[0]) { - case 0: /* base */ - if (edid->version != 1) { - dev_err(&client->dev, "EDID has major version %d, instead of 1\n", edid->version); - goto bad; - } - - if (edid->revision > 4) - dev_err(&client->dev,"EDID minor > 4, assuming backward compatibility\n"); - break; - - default: - break; - } - - return 1; - -bad: - if (raw_edid) { - dev_err(&client->dev, "Raw EDID:\n"); - print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); - printk("\n"); - } - return 0; -} -int ANX7150_DDC_EDID(struct i2c_client *client, u8 *buf, u8 block, u16 len) -{ - u8 offset; - u8 segment; - u8 len_low; - u8 len_high; - - offset = EDID_LENGTH * (block & 0x01); - segment = block >> 1; - len_low = len & 0xFF; - len_high = (len >> 8) & 0xFF; - - anx7150_initddc_read(client, 0xa0, segment, offset, len_low, len_high); - if(ANX7150_DDC_Mass_Read(client, buf, len) == len) - return 0; - else - return -1; -} -u8 *ANX7150_Read_EDID(struct i2c_client *client) -{ - u8 *block = NULL; - u8 *raw_edid = NULL; - u8 extend_block_num; - int i = 0; - int j = 0; - - anx7150_rst_ddcchannel(client); - - if ((block = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) - return NULL; - - /* base block fetch */ - hdmi_dbg(&client->dev, "Read base block\n"); - for (i = 0; i < 4; i++) { - if(ANX7150_DDC_EDID(client, block, 0, EDID_LENGTH)) - goto out; - if(anx7150_edid_block_valid(client, block)) - break; - else - dev_err(&client->dev, "Read base block err, retry...\n"); - - mdelay(10); - } - - if(i == 4){ - dev_err(&client->dev, "Read base block failed\n"); - goto out; - } - - /* if there's no extensions, we're done */ - extend_block_num = block[0x7e]; - if(extend_block_num == 0) - goto out; - - dev_err(&client->dev, "extend_block_num = %d\n", extend_block_num); - - raw_edid = krealloc(block, (extend_block_num + 1) * EDID_LENGTH, GFP_KERNEL); - if(!raw_edid) - goto out; - - block = raw_edid; - - hdmi_dbg(&client->dev, "Read extend block\n"); - for(j=1; j<=extend_block_num; j++){ - for(i=0; i<4; i++){ - if(ANX7150_DDC_EDID(client, raw_edid + j * EDID_LENGTH, j, EDID_LENGTH)) - goto out; - if(anx7150_edid_block_valid(client, raw_edid + j * EDID_LENGTH)) - break; - else - dev_err(&client->dev, "Read extend block %d err, retry...\n", j); - - mdelay(10); - } - - if(i == 4){ - dev_err(&client->dev, "Read extend block %d failed\n", j); - goto out; - } - } - - dev_err(&client->dev, "\n\nRaw EDID(extend_block_num = %d, total_len = %d):\n\n", extend_block_num, EDID_LENGTH*(extend_block_num+1)); - print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH*(extend_block_num+1)); - printk("\n\n"); - - return raw_edid; - -out: - kfree(block); - return NULL; -} -int ANX7150_DDC_Mass_Read(struct i2c_client *client, u8 *buf, u16 len) -{ - int rc = 0; - u32 i, j; - char c, c1,ddc_empty_cnt; - - i = len; - 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) - break; - } - } - return (len - i); -} - -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; - - - ANX7150_EDID_Buf = ANX7150_Read_EDID(client); - - if(!ANX7150_EDID_Buf){ - ANX7150_edid_result.edid_errcode = ANX7150_EDID_BadHeader; - dev_err(&client->dev, "READ EDID ERROR\n"); - 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) - { - hdmi_dbg(&client->dev, "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_1080p_60Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080p_60Hz); - hdmi_dbg(&client->dev,"ANX7150_edid_result.supported_1080p_50Hz = 0x%.2x\n",(u32)ANX7150_edid_result.supported_1080p_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; - kfree(ANX7150_EDID_Buf); - ANX7150_EDID_Buf = NULL; - return 0; - -err: - if(ANX7150_EDID_Buf){ - kfree(ANX7150_EDID_Buf); - ANX7150_EDID_Buf = NULL; - } - 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_4x3: - if(ANX7150_edid_result.supported_576p_50Hz){ - resolution_real = HDMI_720x576p_50Hz_4x3; - find_resolution = 1; - } - break; - case HDMI_720x576p_50Hz_16x9: - if(ANX7150_edid_result.supported_576p_50Hz){ - resolution_real = HDMI_720x576p_50Hz_16x9; - find_resolution = 1; - } - break; - case HDMI_720x480p_60Hz_4x3: - if(ANX7150_edid_result.supported_720x480p_60Hz){ - resolution_real = HDMI_720x480p_60Hz_4x3; - find_resolution = 1; - } - break; - case HDMI_720x480p_60Hz_16x9: - if(ANX7150_edid_result.supported_720x480p_60Hz){ - resolution_real = HDMI_720x480p_60Hz_16x9; - find_resolution = 1; - } - break; - case HDMI_1920x1080p_50Hz: - if(ANX7150_edid_result.supported_1080p_50Hz){ - resolution_real = HDMI_1920x1080p_50Hz; - find_resolution = 1; - } - break; - case HDMI_1920x1080p_60Hz: - if(ANX7150_edid_result.supported_1080p_60Hz){ - resolution_real = HDMI_1920x1080p_60Hz; - 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_4x3; - else if(ANX7150_edid_result.supported_720x480p_60Hz) - resolution_real = HDMI_720x480p_60Hz_4x3; - else if(ANX7150_edid_result.supported_1080p_50Hz) - resolution_real = HDMI_1920x1080p_50Hz; - else if(ANX7150_edid_result.supported_1080p_60Hz) - resolution_real = HDMI_1920x1080p_60Hz; - 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; -} -int ANX7150_Blue_Screen(struct anx7150_pdata *anx) -{ - return anx7150_blue_screen_format_config(anx->client); -} -//******************************Video Config*************************************** -int ANX7150_Config_Video(struct i2c_client *client) -{ - int rc = 0; - int retry = 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"); - - retry = 0; - do{ - mdelay(60); - rc = anx7150_i2c_read_p0_reg(client, ANX7150_VID_STATUS_REG, &c); - if (c & ANX7150_VID_STATUS_VID_STABLE){ - hdmi_dbg(&client->dev, "Video stable, continue!\n"); - break; - } - else{ - hdmi_dbg(&client->dev,"Video not stable!, retry = %d\n", retry); - } - }while(retry++ < 5); - - 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); - if(ANX7150_HDCP_enable) - mdelay(100); //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"); - c = 0x00; - 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); - - // set the relation of MCLK and Fs xy 070117 - 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); - 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_V720x480p_60Hz_4x3: - case ANX7150_V720x480p_60Hz_16x9: - case ANX7150_V720x576p_50Hz_4x3: - case ANX7150_V720x576p_50Hz_16x9: - s_ANX7150_packet_config.avi_info.pb_u8[2] = 0x58; - break; - case ANX7150_V1280x720p_50Hz: - case ANX7150_V1280x720p_60Hz: - case ANX7150_V1920x1080p_50Hz: - case ANX7150_V1920x1080p_60Hz: - s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xa8; - break; - default: - s_ANX7150_packet_config.avi_info.pb_u8[2] = 0xa8; - 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); - mdelay(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); - mdelay(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 - mdelay(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 enable) -{ - 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); - mdelay(10);//let unencrypted video play a while, required by HDCP CTS. SY//wen HDCP CTS - anx7150_set_avmute(client);//before auth, set_avmute//wen - mdelay(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"); - mdelay(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. - { - mdelay(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); - if(!enable) - anx7150_set_avmute(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_4x3: - g_video_format = ANX7150_V720x576p_50Hz_4x3; - break; - case HDMI_720x576p_50Hz_16x9: - g_video_format = ANX7150_V720x576p_50Hz_16x9; - break; - case HDMI_720x480p_60Hz_4x3: - g_video_format = ANX7150_V720x480p_60Hz_4x3; - break; - case HDMI_720x480p_60Hz_16x9: - g_video_format = ANX7150_V720x480p_60Hz_16x9; - break; - case HDMI_1920x1080p_50Hz: - g_video_format = ANX7150_V1920x1080p_50Hz; - break; - case HDMI_1920x1080p_60Hz: - g_video_format = ANX7150_V1920x1080p_60Hz; - 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 deleted file mode 100755 index af8d900096e7..000000000000 --- a/drivers/video/hdmi/chips/anx7150_hw.h +++ /dev/null @@ -1,1401 +0,0 @@ -#ifndef _ANX7150_HW_H -#define _ANX7150_HW_H - -#include - -#define EDID_LENGTH 128 -struct est_timings { - u8 t1; - u8 t2; - u8 mfg_rsvd; -} __attribute__((packed)); - -struct std_timing { - u8 hsize; /* need to multiply by 8 then add 248 */ - u8 vfreq_aspect; -} __attribute__((packed)); - -/* If detailed data is pixel timing */ -struct detailed_pixel_timing { - u8 hactive_lo; - u8 hblank_lo; - u8 hactive_hblank_hi; - u8 vactive_lo; - u8 vblank_lo; - u8 vactive_vblank_hi; - u8 hsync_offset_lo; - u8 hsync_pulse_width_lo; - u8 vsync_offset_pulse_width_lo; - u8 hsync_vsync_offset_pulse_width_hi; - u8 width_mm_lo; - u8 height_mm_lo; - u8 width_height_mm_hi; - u8 hborder; - u8 vborder; - u8 misc; -} __attribute__((packed)); - -/* If it's not pixel timing, it'll be one of the below */ -struct detailed_data_string { - u8 str[13]; -} __attribute__((packed)); - -struct detailed_data_monitor_range { - u8 min_vfreq; - u8 max_vfreq; - u8 min_hfreq_khz; - u8 max_hfreq_khz; - u8 pixel_clock_mhz; /* need to multiply by 10 */ - __le16 sec_gtf_toggle; /* A000=use above, 20=use below */ - u8 hfreq_start_khz; /* need to multiply by 2 */ - u8 c; /* need to divide by 2 */ - __le16 m; - u8 k; - u8 j; /* need to divide by 2 */ -} __attribute__((packed)); - -struct detailed_data_wpindex { - u8 white_yx_lo; /* Lower 2 bits each */ - u8 white_x_hi; - u8 white_y_hi; - u8 gamma; /* need to divide by 100 then add 1 */ -} __attribute__((packed)); - -struct detailed_data_color_point { - u8 windex1; - u8 wpindex1[3]; - u8 windex2; - u8 wpindex2[3]; -} __attribute__((packed)); - -struct cvt_timing { - u8 code[3]; -} __attribute__((packed)); - -struct detailed_non_pixel { - u8 pad1; - u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name - fb=color point data, fa=standard timing data, - f9=undefined, f8=mfg. reserved */ - u8 pad2; - union { - struct detailed_data_string str; - struct detailed_data_monitor_range range; - struct detailed_data_wpindex color; - struct std_timing timings[6]; - struct cvt_timing cvt[4]; - } data; -} __attribute__((packed)); - -struct detailed_timing { - __le16 pixel_clock; /* need to multiply by 10 KHz */ - union { - struct detailed_pixel_timing pixel_data; - struct detailed_non_pixel other_data; - } data; -} __attribute__((packed)); - -struct edid { - u8 header[8]; - /* Vendor & product info */ - u8 mfg_id[2]; - u8 prod_code[2]; - u32 serial; /* FIXME: byte order */ - u8 mfg_week; - u8 mfg_year; - /* EDID version */ - u8 version; - u8 revision; - /* Display info: */ - u8 input; - u8 width_cm; - u8 height_cm; - u8 gamma; - u8 features; - /* Color characteristics */ - u8 red_green_lo; - u8 black_white_lo; - u8 red_x; - u8 red_y; - u8 green_x; - u8 green_y; - u8 blue_x; - u8 blue_y; - u8 white_x; - u8 white_y; - /* Est. timings and mfg rsvd timings*/ - struct est_timings established_timings; - /* Standard timings 1-8*/ - struct std_timing standard_timings[8]; - /* Detailing timings 1-4 */ - struct detailed_timing detailed_timings[4]; - /* Number of 128 byte ext. blocks */ - u8 extensions; - /* Checksum */ - u8 checksum; -} __attribute__((packed)); - -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_1920x1080p_60Hz[18]; - //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_1920x1080p_50Hz[18]; - /* 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 -*/ - int anx7150_get_hpd(struct i2c_client *client); - -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 enable); -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); -int ANX7150_Blue_Screen(struct anx7150_pdata *anx); -int anx7150_set_avmute(struct i2c_client *client); -int anx7150_initial(struct i2c_client *client); - -#endif diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi.c b/drivers/video/hdmi/chips/rk610/rk610_hdmi.c new file mode 100644 index 000000000000..6c33f941d702 --- /dev/null +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi.c @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rk610_hdmi.h" +#include "rk610_hdmi_hw.h" + + +struct i2c_client *rk610_g_hdmi_client=NULL; +static bool hpd=0; + +static void rk610_handler(struct work_struct *work) +{ + struct i2c_client *client = rk610_g_hdmi_client; + if(client==NULL){ + printk(">>> %s client==NULL\n",__func__); + } + Rk610_hdmi_event_work(client,&hpd); +} + +static DECLARE_DELAYED_WORK(rk610_irq_work, rk610_handler); +static int rk610_hdmi_precent(struct hdmi *hdmi) +{ + //struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi); + schedule_delayed_work(&rk610_irq_work, msecs_to_jiffies(30)); + return hpd; +} + +static int rk610_hdmi_param_chg(struct rk610_hdmi_inf *rk610_hdmi) +{ + RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); + hdmi_switch_fb(rk610_hdmi->hdmi, rk610_hdmi->hdmi->display_on); + Rk610_hdmi_Set_Video(rk610_hdmi->hdmi->resolution); + Rk610_hdmi_Set_Audio(rk610_hdmi->hdmi->audio_fs); + Rk610_hdmi_Config_Done(rk610_hdmi->client); + return 0; +} + +static int rk610_hdmi_set_param(struct hdmi *hdmi) +{ + struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi); + RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); + if(rk610_hdmi->init == 1) + return 0; + + rk610_hdmi_param_chg(rk610_hdmi); + return 0; +} +static int rk610_hdmi_insert(struct hdmi *hdmi) +{ + struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi); + RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); + if(rk610_hdmi->init == 1) + return -1; + rk610_hdmi_param_chg(rk610_hdmi); + hdmi_set_spk(HDMI_DISABLE); + printk("rk610_hdmi_insert hdmi->display_on=%d\n",hdmi->display_on); + hdmi->scale = hdmi->scale_set; + return 0; +} +static int rk610_hdmi_remove(struct hdmi *hdmi) +{ + struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi); + RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); + if(rk610_hdmi->init == 1) + return -1; + hdmi_set_spk(HDMI_ENABLE); + hdmi_switch_fb(hdmi, HDMI_DISABLE); + printk("rk610_hdmi_remove hdmi->display_on=%d\n",hdmi->display_on); + return 0; +} +#ifdef CONFIG_HAS_EARLYSUSPEND +static void rk610_hdmi_early_suspend(struct early_suspend *h) +{ + struct rk610_hdmi_inf *rk610_hdmi = container_of(h, + struct rk610_hdmi_inf, + early_suspend); + printk( "rk610_hdmi enter early suspend\n"); + hdmi_suspend(rk610_hdmi->hdmi); + Rk610_hdmi_suspend(rk610_hdmi->client); + return; +} + +static void rk610_hdmi_early_resume(struct early_suspend *h) +{ + struct rk610_hdmi_inf *rk610_hdmi = container_of(h, + struct rk610_hdmi_inf, + early_suspend); + printk("rk610_hdmi exit early suspend\n"); + hdmi_resume(rk610_hdmi->hdmi); + Rk610_hdmi_resume(rk610_hdmi->client); + return; +} +#endif + +static int rk610_hdmi_init(struct hdmi *hdmi) +{ + struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi); +#ifdef CONFIG_HDMI_SAVE_DATA + int hdmi_data = hdmi_get_data(); + if(hdmi_data<0){ + hdmi_set_data((hdmi->resolution&0x7)|((hdmi->scale&0x1f)<<3)); + } + else{ + hdmi->resolution = hdmi_data&0x7; + hdmi->scale_set= ((hdmi_data>>3)&0x1f) + MIN_SCALE; + hdmi->scale = hdmi->scale_set; + } +#endif + RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__); + rk610_hdmi->init =0; + Rk610_hdmi_init(rk610_hdmi->client); + hdmi_changed(hdmi,1); + Rk610_hdmi_Set_Video(hdmi->resolution); + Rk610_hdmi_Set_Audio(hdmi->audio_fs); + Rk610_hdmi_Config_Done(rk610_hdmi->client); + return 0; +} +static struct hdmi_ops rk610_hdmi_ops = { + .set_param = rk610_hdmi_set_param, + .hdmi_precent = rk610_hdmi_precent, + .insert = rk610_hdmi_insert, + .remove = rk610_hdmi_remove, + .init = rk610_hdmi_init, +}; +#ifdef CONFIG_RK610_DEBUG +static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} + +static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} +static ssize_t rk610_show_reg_attrs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + + int i,size=0; + char val; + struct i2c_client *client=rk610_g_hdmi_client; + + for(i=0;i<256;i++) + { + rk610_read_p0_reg(client, i, &val); + if(i%16==0) + size += sprintf(buf+size,"\n>>>rk610_hdmi %x:",i); + size += sprintf(buf+size," %2x",val); + } + + return size; +} +static ssize_t rk610_store_reg_attrs(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct i2c_client *client=NULL; + char val,reg,addr; + client = rk610_g_hdmi_client; + printk("/**********rk610 reg config******/"); + + sscanf(buf, "%x%x%x", &val,®,&addr); + printk("addr=%x ,reg=%x val=%x\n",addr,reg,val); + rk610_write_p0_reg(client, reg, &val); + printk("val=%x\n",val); + return size; +} + +static struct device_attribute rk610_attrs[] = { + __ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs), +}; +#endif +#if 0 +static irqreturn_t rk610_hdmi_interrupt(int irq, void *dev_id) +{ + struct hdmi *hdmi = (struct hdmi *)dev_id; + unsigned long lock_flags = 0; + printk("The rk610_hdmi interrupt handeler is working..\n"); + return IRQ_HANDLED; +} +#endif + +static int rk610_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + int ret = 0; + struct hdmi *hdmi = NULL; + struct rk610_hdmi_inf *rk610_hdmi = NULL; + + struct hdmi_platform_data *pdata = client->dev.platform_data; + rk610_g_hdmi_client = client; + if(pdata && pdata->io_init) + { + printk("rk610_hdmi_i2c_probe io_init \n"); + pdata->io_init(); + } + hdmi = hdmi_register(sizeof(struct rk610_hdmi_inf), &client->dev); + if (!hdmi) + { + dev_err(&client->dev, "fail to register hdmi\n"); + return -ENOMEM; + } + hdmi->ops = &rk610_hdmi_ops; + hdmi->display_on = HDMI_DEFAULT_MODE; + hdmi->hdcp_on = HDMI_DISABLE; + hdmi->audio_fs = HDMI_I2S_DEFAULT_Fs; + hdmi->resolution = HDMI_DEFAULT_RESOLUTION; + hdmi->dual_disp = DUAL_DISP_CAP; + hdmi->mode = DISP_ON_LCD; + hdmi->scale = 100; + hdmi->scale_set = 100; + + rk610_hdmi = hdmi_priv(hdmi); + rk610_hdmi->init = 1; + rk610_hdmi->hdmi = hdmi; + i2c_set_clientdata(client, rk610_hdmi); + rk610_hdmi->client = client; + if((gpio_request(client->irq, "hdmi gpio")) < 0) + { + dev_err(&client->dev, "fail to request gpio %d\n", client->irq); + goto err_gpio_free; + } + rk610_hdmi->irq = gpio_to_irq(client->irq); + rk610_hdmi->gpio = client->irq; + + gpio_direction_input(client->irq); + #if 0 + if((ret = request_irq(rk610_hdmi->irq, rk610_hdmi_interrupt, IRQ_TYPE_EDGE_RISING,client->name, hdmi))<0){ + RK610_ERR(&client->dev, "fail to request gpio %d\n", client->irq); + goto err_gpio_free; + } + #endif +#ifdef CONFIG_HAS_EARLYSUSPEND + rk610_hdmi->early_suspend.suspend = rk610_hdmi_early_suspend; + rk610_hdmi->early_suspend.resume = rk610_hdmi_early_resume; + rk610_hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1; + register_early_suspend(&rk610_hdmi->early_suspend); +#endif +#ifdef CONFIG_RK610_DEBUG + device_create_file(&(client->dev), &rk610_attrs[0]); +#endif + rk610_hdmi_init(rk610_hdmi->hdmi); + dev_info(&client->dev, "rk610_hdmi i2c probe ok\n"); + return 0; +err_gpio_free: + gpio_free(client->irq); +err_hdmi_unregister: + hdmi_unregister(hdmi); + rk610_hdmi = NULL; + return ret; +} + +static int __devexit rk610_hdmi_i2c_remove(struct i2c_client *client) +{ + struct rk610_hdmi_inf *rk610_hdmi = (struct rk610_hdmi_inf *)i2c_get_clientdata(client); + struct hdmi *hdmi = rk610_hdmi->hdmi; + + gpio_free(client->irq); + hdmi_unregister(hdmi); + rk610_hdmi = NULL; + return 0; +} +static const struct i2c_device_id rk610_hdmi_id[] = { + { "rk610_hdmi", 0 }, + { } +}; + +static struct i2c_driver rk610_hdmi_i2c_driver = { + .driver = { + .name = "rk610_hdmi", + }, + .probe = &rk610_hdmi_i2c_probe, + .remove = &rk610_hdmi_i2c_remove, + .id_table = rk610_hdmi_id, +}; + +static int __init rk610_hdmi_module_init(void) +{ + return i2c_add_driver(&rk610_hdmi_i2c_driver); +} + +static void __exit rk610_hdmi_module_exit(void) +{ + i2c_del_driver(&rk610_hdmi_i2c_driver); +} + +late_initcall(rk610_hdmi_module_init); +//module_init(rk610_hdmi_module_init); +module_exit(rk610_hdmi_module_exit); diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi.h b/drivers/video/hdmi/chips/rk610/rk610_hdmi.h new file mode 100644 index 000000000000..03ae3c5a9190 --- /dev/null +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi.h @@ -0,0 +1,36 @@ +#ifndef _RK610_H +#define _RK610_H + +#include +#include + +/************RK610 device addr***********/ +#define RK610_CTRL_ADDR 0x40 +#define RK610_TVE_ADDR 0x42 +#define RK610_HDMI_ADDR 0x46 +#define RK610_CODEC_ADDR 0xc0 // 0x11xxxxxx + + +/****************HDMI STRUCT********************************/ + + +struct rk610_hdmi_inf{ + int irq; + int gpio; + int init; + struct i2c_client *client; + struct hdmi *hdmi; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +/******************TVE STRUCT **************/ + +/*************RK610 STRUCT**********************************/ +//struct rk610_pdata { +// struct rk610_hdmi_inf hdmi; +// struct rk610_lcd_info lcd; +//}; +/*****************END ***********************************/ +#endif diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c new file mode 100644 index 000000000000..ba34084b2a83 --- /dev/null +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c @@ -0,0 +1,1094 @@ +#include +#include +#include "rk610_hdmi.h" +#include "rk610_hdmi_hw.h" +static struct rk610_hdmi_hw_inf g_hw_inf; +static EDID_INF g_edid; +static byte edid_buf[EDID_BLOCK_SIZE]; +static int RK610_hdmi_soft_reset(struct i2c_client *client); +static int Rk610_hdmi_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} +static int Rk610_hdmi_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val) +{ + return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL; +} + +static int Rk610_hdmi_pwr_mode(struct i2c_client *client, int mode) +{ + char c; + int ret=0; + switch(mode){ + case NORMAL: + c=0x82; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c); + c=0x8e; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c); + break; + case LOWER_PWR: + c=0x02; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); + c=0x1c; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); + break; + case SHUTDOWN: + c=0x02; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c); + c=0x1c; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); + c=0x04; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c); + c=0x03; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c); + c=0x8c; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c); + break; + default: + RK610_ERR(&client->dev,"unkown rk610 hdmi pwr mode %d\n",mode); + } + return ret; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +int Rk610_hdmi_suspend(struct i2c_client *client) +{ + int ret = 0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + ret = Rk610_hdmi_pwr_mode(client,SHUTDOWN); + return ret; +} +int Rk610_hdmi_resume(struct i2c_client *client) +{ + int ret = 0; + RK610_DBG(&client->dev, "%s \n",__FUNCTION__); + ret = Rk610_hdmi_pwr_mode(client,NORMAL); + RK610_hdmi_soft_reset(client); + return ret; +} +#endif +static int Rk610_hdmi_sys_power_down(struct i2c_client *client) +{ + char c = 0; + int ret = 0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_OFF<<1 |RK610_INT_POL; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c); + return ret; +} +static int Rk610_hdmi_sys_power_up(struct i2c_client *client) +{ + char c = 0; + int ret = 0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_ON<<1 |RK610_INT_POL; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c); + return ret; +} +//X=11.2896M/(4*100k), X = {0x4c,0x4b} +static int RK610_DDC_BUS_CONFIG(struct i2c_client *client) +{ + char c = 0; + int ret = 0; + c= RK610_DDC_CONFIG&0xff; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4b, &c); + c= (RK610_DDC_CONFIG>>8)&0xff; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4c, &c); + return ret; +} +static int RK610_read_edid_block(struct i2c_client *client,u8 block, u8 * buf) +{ + char c = 0; + int ret = 0,i; + u8 Segment = 0; + u8 Offset = 0; + if(block%2) + Offset = EDID_BLOCK_SIZE; + if(block/2) + Segment = 1; + RK610_DBG(&client->dev,"EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int) Segment, (int) block, (int) Offset); + //set edid fifo first addr + c = 0x00; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x4f, &c); + //set edid word address 00/80 + c = Offset; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4e, &c); + //set edid segment pointer + c = Segment; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4d, &c); + + //enable edid interrupt + c=0xc6; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc0, &c); + //wait edid interrupt + msleep(100); + RK610_DBG(&client->dev,"Interrupt generated\n"); + c=0x00; + ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c); + RK610_DBG(&client->dev,"Interrupt reg=%x \n",c); + //clear EDID interrupt reg + c=0x04; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c); + msleep(100); + for(i=0; i Extension Tag Error\n"); + return EDID_EXT_TAG_ERROR; + } + + if (Data[EDID_REV_ADDR] != EDID_REV_THREE) + { + RK610_HDMI_ERR("EDID -> Revision Error\n")); + return EDID_REV_ADDR_ERROR; + } + + LongDescriptorOffset = Data[LONG_DESCR_PTR_IDX]; // block offset where long descriptors start + + g_edid.UnderScan = ((Data[MISC_SUPPORT_IDX]) >> 7) & LSBIT; // byte #3 of CEA extension version 3 + g_edid.BasicAudio = ((Data[MISC_SUPPORT_IDX]) >> 6) & LSBIT; + g_edid.YCbCr_4_4_4 = ((Data[MISC_SUPPORT_IDX]) >> 5) & LSBIT; + g_edid.YCbCr_4_2_2 = ((Data[MISC_SUPPORT_IDX]) >> 4) & LSBIT; + + DataIndex = EDID_DATA_START; // 4 + + while (DataIndex < LongDescriptorOffset) + { + TagCode = (Data[DataIndex] >> 5) & THREE_LSBITS; + DataBlockLength = Data[DataIndex++] & FIVE_LSBITS; + if ((DataIndex + DataBlockLength) > LongDescriptorOffset) + { + RK610_HDMI_ERR("EDID -> V Descriptor Overflow\n"); + return EDID_V_DESCR_OVERFLOW; + } + + i = 0; // num of short video descriptors in current data block + + switch (TagCode) + { + case VIDEO_D_BLOCK: + while ((i < DataBlockLength) && (i < MAX_V_DESCRIPTORS)) // each SVD is 1 byte long + { + g_edid.VideoDescriptor[V_DescriptorIndex++] = Data[DataIndex++]; + i++; + } + DataIndex += DataBlockLength - i; // if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex + + RK610_RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Block\n"); + break; + + case AUDIO_D_BLOCK: + while (i < DataBlockLength/3) // each SAD is 3 bytes long + { + j = 0; + while (j < AUDIO_DESCR_SIZE) // 3 + { + g_edid.AudioDescriptor[A_DescriptorIndex][j++] = Data[DataIndex++]; + } + A_DescriptorIndex++; + i++; + } + RK610_HDMI_DBG("EDID -> Short Descriptor Audio Block\n"); + break; + + case SPKR_ALLOC_D_BLOCK: + g_edid.SpkrAlloc[i++] = Data[DataIndex++]; // although 3 bytes are assigned to Speaker Allocation, only + DataIndex += 2; // the first one carries information, so the next two are ignored by this code. + RK610_HDMI_DBG("EDID -> Short Descriptor Speaker Allocation Block\n"); + break; + + case USE_EXTENDED_TAG: + ExtendedTagCode = Data[DataIndex++]; + + switch (ExtendedTagCode) + { + case VIDEO_CAPABILITY_D_BLOCK: + RK610_HDMI_DBG("EDID -> Short Descriptor Video Capability Block\n"); + + // TO BE ADDED HERE: Save "video capability" parameters in g_edid data structure + // Need to modify that structure definition + // In the meantime: just increment DataIndex by 1 + DataIndex += 1; // replace with reading and saving the proper data per CEA-861 sec. 7.5.6 while incrementing DataIndex + break; + + case COLORIMETRY_D_BLOCK: + g_edid.ColorimetrySupportFlags = Data[DataIndex++] & BITS_1_0; + g_edid.MetadataProfile = Data[DataIndex++] & BITS_2_1_0; + + RK610_HDMI_DBG("EDID -> Short Descriptor Colorimetry Block\n"); + break; + } + break; + + case VENDOR_SPEC_D_BLOCK: + VSDB_BaseOffset = DataIndex - 1; + + if ((Data[DataIndex++] == 0x03) && // check if sink is HDMI compatible + (Data[DataIndex++] == 0x0C) && + (Data[DataIndex++] == 0x00)) + + g_edid.RK610_HDMI_Sink = TRUE; + else + g_edid.RK610_HDMI_Sink = FALSE; + + g_edid.CEC_A_B = Data[DataIndex++]; // CEC Physical address + g_edid.CEC_C_D = Data[DataIndex++]; + +#ifdef DEV_SUPPORT_CEC + // Take the Address that was passed in the EDID and use this API + // to set the physical address for CEC. + { + word phyAddr; + phyAddr = (word)g_edid.CEC_C_D; // Low-order nibbles + phyAddr |= ((word)g_edid.CEC_A_B << 8); // Hi-order nibbles + // Is the new PA different from the current PA? + if (phyAddr != SI_CecGetDevicePA ()) + { + // Yes! So change the PA + SI_CecSetDevicePA (phyAddr); + } + } +#endif + + if ((DataIndex + 7) > VSDB_BaseOffset + DataBlockLength) // Offset of 3D_Present bit in VSDB + g_edid._3D_Supported = FALSE; + else if (Data[DataIndex + 7] >> 7) + g_edid._3D_Supported = TRUE; + else + g_edid._3D_Supported = FALSE; + + DataIndex += DataBlockLength - RK610_HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block + RK610_HDMI_DBG("EDID -> Short Descriptor Vendor Block\n"); + break; + + default: + RK610_HDMI_DBG("EDID -> Unknown Tag Code\n"); + return EDID_UNKNOWN_TAG_CODE; + + } // End, Switch statement + } // End, while (DataIndex < LongDescriptorOffset) statement + + return EDID_SHORT_DESCRIPTORS_OK; +} + +//------------------------------------------------------------------------------ +// Function Name: Parse861LongDescriptors() +// Function Description: Parse CEA-861 extension long descriptors of the EDID block +// passed as a parameter and printf() them to the screen. +// +// Accepts: A pointer to the EDID block being parsed +// Returns: An error code if no long descriptors found; EDID_PARSED_OK if descriptors found. +// Globals: none +//------------------------------------------------------------------------------ +byte Parse861LongDescriptors (byte *Data) +{ + byte LongDescriptorsOffset; + byte DescriptorNum = 1; + + LongDescriptorsOffset = Data[LONG_DESCR_PTR_IDX]; // EDID block offset 2 holds the offset + + if (!LongDescriptorsOffset) // per CEA-861-D, table 27 + { + TPI_DEBUG_PRINT(("EDID -> No Detailed Descriptors\n")); + return EDID_NO_DETAILED_DESCRIPTORS; + } + + // of the 1st 18-byte descriptor + while (LongDescriptorsOffset + LONG_DESCR_LEN < EDID_BLOCK_SIZE) + { + TPI_EDID_PRINT(("Parse Results - CEA-861 Long Descriptor #%d:\n", (int) DescriptorNum)); + TPI_EDID_PRINT(("===============================================================\n")); + +#if (CONF__TPI_EDID_PRINT == ENABLE) + if (!ParseDetailedTiming(Data, LongDescriptorsOffset, EDID_BLOCK_2_3)) + break; +#endif + LongDescriptorsOffset += LONG_DESCR_LEN; + DescriptorNum++; + } + + return EDID_LONG_DESCRIPTORS_OK; +} + +//------------------------------------------------------------------------------ +// Function Name: Parse861Extensions() +// Function Description: Parse CEA-861 extensions from EDID ROM (EDID blocks beyond +// block #0). Save short descriptors in global structure +// g_edid. printf() long descriptors to the screen. +// +// Accepts: The number of extensions in the EDID being parsed +// Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed. +// Globals: EDID data +// NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. +//------------------------------------------------------------------------------ +byte Parse861Extensions (struct i2c_client *client,byte NumOfExtensions) +{ + byte i,j,k; + + byte ErrCode; + +// byte V_DescriptorIndex = 0; +// byte A_DescriptorIndex = 0; + + byte Block = 0; + + g_edid.HDMI_Sink = FALSE; + + do + { + Block++; + HDMI_DBG("\n"); + + for (j=0, i=0; j<128; j++) + { + k = edid_buf[j]; + HDMI_DBG("%2.2X ", (int) k); + i++; + + if (i == 0x10) + { + HDMI_DBG("\n"); + i = 0; + } + } + HDMI_DBG("\n"); + RK610_read_edid_block(client,Block, edid_buf); + if ((NumOfExtensions > 1) && (Block == 1)) + { + continue; + } + + ErrCode = Parse861ShortDescriptors(edid_buf); + if (ErrCode != EDID_SHORT_DESCRIPTORS_OK) + { + return ErrCode; + } + + ErrCode = Parse861LongDescriptors(edid_buf); + if (ErrCode != EDID_LONG_DESCRIPTORS_OK) + { + return ErrCode; + } + + } while (Block < NumOfExtensions); + + return EDID_OK; +} + +//------------------------------------------------------------------------------ +// Function Name: ParseEDID() +// Function Description: Extract sink properties from its EDID file and save them in +// global structure g_edid. +// +// Accepts: none +// Returns: TRUE or FLASE +// Globals: EDID data +// NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. +//------------------------------------------------------------------------------ +static byte ParseEDID (byte *pEdid, byte *numExt) +{ + if (!CheckEDID_Header(pEdid)) + { + // first 8 bytes of EDID must be {0, FF, FF, FF, FF, FF, FF, 0} + HDMI_ERR("EDID -> Incorrect Header\n"); + return EDID_INCORRECT_HEADER; + } + + if (!DoEDID_Checksum(pEdid)) + { + // non-zero EDID checksum + HDMI_ERR("EDID -> Checksum Error\n"); + return EDID_CHECKSUM_ERROR; + } + + *numExt = pEdid[NUM_OF_EXTEN_ADDR]; // read # of extensions from offset 0x7E of block 0 + HDMI_DBG("EDID -> 861 Extensions = %d\n", (int) *numExt); + + if (!(*numExt)) + { + // No extensions to worry about + HDMI_DBG("EDID -> EDID_NO_861_EXTENSIONS\n"); + return EDID_NO_861_EXTENSIONS; + } + return EDID_OK; +} +#endif + +//------------------------------------------------------------------------------ +// Function Name: CheckEDID_Header() +// Function Description: Checks if EDID header is correct per VESA E-EDID standard +// +// Accepts: Pointer to 1st EDID block +// Returns: TRUE or FLASE +// Globals: EDID data +//------------------------------------------------------------------------------ +byte CheckEDID_Header (byte *Block) +{ + byte i = 0; + + if (Block[i]) // byte 0 must be 0 + return FALSE; + + for (i = 1; i < 1 + EDID_HDR_NO_OF_FF; i++) + { + if(Block[i] != 0xFF) // bytes [1..6] must be 0xFF + return FALSE; + } + + if (Block[i]) // byte 7 must be 0 + return FALSE; + + return TRUE; +} + +//------------------------------------------------------------------------------ +// Function Name: DoEDID_Checksum() +// Function Description: Calculte checksum of the 128 byte block pointed to by the +// pointer passed as parameter +// +// Accepts: Pointer to a 128 byte block whose checksum needs to be calculated +// Returns: TRUE or FLASE +// Globals: EDID data +//------------------------------------------------------------------------------ +byte DoEDID_Checksum (byte *Block) +{ + byte i; + byte CheckSum = 0; + + for (i = 0; i < EDID_BLOCK_SIZE; i++) + CheckSum += Block[i]; + + if (CheckSum) + return FALSE; + + return TRUE; +} +//------------------------------------------------------------------------------ +// Function Name: Parse861ShortDescriptors() +// Function Description: Parse CEA-861 extension short descriptors of the EDID block +// passed as a parameter and save them in global structure g_edid. +// +// Accepts: A pointer to the EDID 861 Extension block being parsed. +// Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed. +// Globals: EDID data +// NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. +//------------------------------------------------------------------------------ +byte Parse861ShortDescriptors (struct i2c_client *client,byte *Data) +{ + byte LongDescriptorOffset; + byte DataBlockLength; + byte DataIndex; + byte ExtendedTagCode; + byte VSDB_BaseOffset = 0; + + byte V_DescriptorIndex = 0; // static to support more than one extension + byte A_DescriptorIndex = 0; // static to support more than one extension + + byte TagCode; + + byte i; + byte j; + + if (Data[EDID_TAG_ADDR] != EDID_EXTENSION_TAG) + { + RK610_ERR(&client->dev,"EDID -> Extension Tag Error\n"); + return EDID_EXT_TAG_ERROR; + } + + if (Data[EDID_REV_ADDR] != EDID_REV_THREE) + { + RK610_ERR(&client->dev,"EDID -> Revision Error\n"); + return EDID_REV_ADDR_ERROR; + } + + LongDescriptorOffset = Data[LONG_DESCR_PTR_IDX]; // block offset where long descriptors start + + g_edid.UnderScan = ((Data[MISC_SUPPORT_IDX]) >> 7) & LSBIT; // byte #3 of CEA extension version 3 + g_edid.BasicAudio = ((Data[MISC_SUPPORT_IDX]) >> 6) & LSBIT; + g_edid.YCbCr_4_4_4 = ((Data[MISC_SUPPORT_IDX]) >> 5) & LSBIT; + g_edid.YCbCr_4_2_2 = ((Data[MISC_SUPPORT_IDX]) >> 4) & LSBIT; + + DataIndex = EDID_DATA_START; // 4 + + while (DataIndex < LongDescriptorOffset) + { + TagCode = (Data[DataIndex] >> 5) & THREE_LSBITS; + DataBlockLength = Data[DataIndex++] & FIVE_LSBITS; + if ((DataIndex + DataBlockLength) > LongDescriptorOffset) + { + RK610_ERR(&client->dev,"EDID -> V Descriptor Overflow\n"); + return EDID_V_DESCR_OVERFLOW; + } + + i = 0; // num of short video descriptors in current data block + + switch (TagCode) + { + case VIDEO_D_BLOCK: + while ((i < DataBlockLength) && (i < MAX_V_DESCRIPTORS)) // each SVD is 1 byte long + { + g_edid.VideoDescriptor[V_DescriptorIndex++] = Data[DataIndex++]; + i++; + } + DataIndex += DataBlockLength - i; // if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex + + RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Block\n"); + break; + + case AUDIO_D_BLOCK: + while (i < DataBlockLength/3) // each SAD is 3 bytes long + { + j = 0; + while (j < AUDIO_DESCR_SIZE) // 3 + { + g_edid.AudioDescriptor[A_DescriptorIndex][j++] = Data[DataIndex++]; + } + A_DescriptorIndex++; + i++; + } + RK610_DBG(&client->dev,"EDID -> Short Descriptor Audio Block\n"); + break; + + case SPKR_ALLOC_D_BLOCK: + g_edid.SpkrAlloc[i++] = Data[DataIndex++]; // although 3 bytes are assigned to Speaker Allocation, only + DataIndex += 2; // the first one carries information, so the next two are ignored by this code. + RK610_DBG(&client->dev,"EDID -> Short Descriptor Speaker Allocation Block\n"); + break; + + case USE_EXTENDED_TAG: + ExtendedTagCode = Data[DataIndex++]; + + switch (ExtendedTagCode) + { + case VIDEO_CAPABILITY_D_BLOCK: + RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Capability Block\n"); + + // TO BE ADDED HERE: Save "video capability" parameters in g_edid data structure + // Need to modify that structure definition + // In the meantime: just increment DataIndex by 1 + DataIndex += 1; // replace with reading and saving the proper data per CEA-861 sec. 7.5.6 while incrementing DataIndex + break; + + case COLORIMETRY_D_BLOCK: + g_edid.ColorimetrySupportFlags = Data[DataIndex++] & BITS_1_0; + g_edid.MetadataProfile = Data[DataIndex++] & BITS_2_1_0; + + RK610_DBG(&client->dev,"EDID -> Short Descriptor Colorimetry Block\n"); + break; + } + break; + + case VENDOR_SPEC_D_BLOCK: + VSDB_BaseOffset = DataIndex - 1; + + if ((Data[DataIndex++] == 0x03) && // check if sink is HDMI compatible + (Data[DataIndex++] == 0x0C) && + (Data[DataIndex++] == 0x00)) + + g_edid.HDMI_Sink = TRUE; + else + g_edid.HDMI_Sink = FALSE; + + g_edid.CEC_A_B = Data[DataIndex++]; // CEC Physical address + g_edid.CEC_C_D = Data[DataIndex++]; + +#ifdef DEV_SUPPORT_CEC + // Take the Address that was passed in the EDID and use this API + // to set the physical address for CEC. + { + word phyAddr; + phyAddr = (word)g_edid.CEC_C_D; // Low-order nibbles + phyAddr |= ((word)g_edid.CEC_A_B << 8); // Hi-order nibbles + // Is the new PA different from the current PA? + if (phyAddr != SI_CecGetDevicePA ()) + { + // Yes! So change the PA + SI_CecSetDevicePA (phyAddr); + } + } +#endif + + if ((DataIndex + 7) > VSDB_BaseOffset + DataBlockLength) // Offset of 3D_Present bit in VSDB + g_edid._3D_Supported = FALSE; + else if (Data[DataIndex + 7] >> 7) + g_edid._3D_Supported = TRUE; + else + g_edid._3D_Supported = FALSE; + + DataIndex += DataBlockLength - HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block + RK610_DBG(&client->dev,"EDID -> Short Descriptor Vendor Block\n"); + break; + + default: + RK610_ERR(&client->dev,"EDID -> Unknown Tag Code\n"); + return EDID_UNKNOWN_TAG_CODE; + + } // End, Switch statement + } // End, while (DataIndex < LongDescriptorOffset) statement + + return EDID_SHORT_DESCRIPTORS_OK; +} +//------------------------------------------------------------------------------ +// Function Name: ParseEDID() +// Function Description: Extract sink properties from its EDID file and save them in +// global structure g_edid. +// +// Accepts: none +// Returns: TRUE or FLASE +// Globals: EDID data +// NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. +//------------------------------------------------------------------------------ +static byte ParseEDID (struct i2c_client *client,byte *pEdid, byte *numExt) +{ + if (!CheckEDID_Header(pEdid)) + { + // first 8 bytes of EDID must be {0, FF, FF, FF, FF, FF, FF, 0} + RK610_ERR(&client->dev,"EDID -> Incorrect Header\n"); + return EDID_INCORRECT_HEADER; + } + + if (!DoEDID_Checksum(pEdid)) + { + // non-zero EDID checksum + RK610_ERR(&client->dev,"EDID -> Checksum Error\n"); + return EDID_CHECKSUM_ERROR; + } + + *numExt = pEdid[NUM_OF_EXTEN_ADDR]; // read # of extensions from offset 0x7E of block 0 + RK610_DBG(&client->dev,"EDID -> 861 Extensions = %d\n", (int) *numExt); + + if (!(*numExt)) + { + // No extensions to worry about + RK610_DBG(&client->dev,"EDID -> EDID_NO_861_EXTENSIONS\n"); + return EDID_NO_861_EXTENSIONS; + } + return EDID_OK; +} +byte DoEdidRead (struct i2c_client *client) +{ + u8 NumOfExtensions=0; + u8 Result; + u8 i,j; + // If we already have valid EDID data, ship this whole thing + if (g_edid.edidDataValid == FALSE) + { + Rk610_hdmi_sys_power_up(client); + // Request access to DDC bus from the receiver + RK610_DDC_BUS_CONFIG(client); + memset(edid_buf,0,EDID_BLOCK_SIZE); + RK610_read_edid_block(client,EDID_BLOCK0, edid_buf); // read first 128 bytes of EDID ROM + RK610_DBG(&client->dev,"/************first block*******/\n"); + for (j=0; jdev,"\n/************block %d*******/\n",i); + memset(edid_buf,0,EDID_BLOCK_SIZE); + RK610_read_edid_block(client,i, edid_buf); + Parse861ShortDescriptors(client,edid_buf); + for (j=0; jdev,"EDID -> No 861 Extensions\n"); + g_edid.HDMI_Sink = FALSE; + g_edid.YCbCr_4_4_4 = FALSE; + g_edid.YCbCr_4_2_2 = FALSE; + g_edid.CEC_A_B = 0x00; + g_edid.CEC_C_D = 0x00; + } + else + { + RK610_DBG(&client->dev,"EDID -> Parse FAILED\n"); + g_edid.HDMI_Sink = TRUE; + g_edid.YCbCr_4_4_4 = FALSE; + g_edid.YCbCr_4_2_2 = FALSE; + g_edid.CEC_A_B = 0x00; + g_edid.CEC_C_D = 0x00; + } + } + else + { + RK610_DBG(&client->dev,"EDID -> Parse OK\n"); + Result = Parse861Extensions(NumOfExtensions); // Parse 861 Extensions (short and long descriptors); + if (Result != EDID_OK) + { + RK610_DBG(&client->dev,"EDID -> Extension Parse FAILED\n"); + g_edid.HDMI_Sink = FALSE; + g_edid.YCbCr_4_4_4 = FALSE; + g_edid.YCbCr_4_2_2 = FALSE; + g_edid.CEC_A_B = 0x00; + g_edid.CEC_C_D = 0x00; + } + else + { + RK610_DBG(&client->dev,"EDID -> Extension Parse OK\n"); + g_edid.HDMI_Sink = TRUE; + } + } +#endif + RK610_DBG(&client->dev,"EDID -> NumOfExtensions = %d\n", NumOfExtensions); + RK610_DBG(&client->dev,"EDID -> g_edid.HDMI_Sink = %d\n", (int)g_edid.HDMI_Sink); + //RK610_DBG(&client->dev,"EDID -> g_edid.YCbCr_4_4_4 = %d\n", (int)g_edid.YCbCr_4_4_4); + //RK610_DBG(&client->dev,"EDID -> g_edid.YCbCr_4_2_2 = %d\n", (int)g_edid.YCbCr_4_2_2); + //RK610_DBG(&client->dev,"EDID -> g_edid.CEC_A_B = 0x%x\n", (int)g_edid.CEC_A_B); + //RK610_DBG(&client->dev,"EDID -> g_edid.CEC_C_D = 0x%x\n", (int)g_edid.CEC_C_D); + + g_edid.edidDataValid = TRUE; + } + return TRUE; +} +static int Rk610_hdmi_Display_switch(struct i2c_client *client) +{ + char c; + int ret=0; + int mode; + mode = (g_edid.HDMI_Sink == TRUE)? DISPLAY_HDMI:DISPLAY_DVI; + ret = Rk610_hdmi_i2c_read_p0_reg(client, 0x52, &c); + c &= ((~(1<<1))| mode<<1); + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x52, &c); + RK610_DBG(&client->dev,">>>%s mode=%d,c=%x",__func__,mode,c); + return ret; +} + +static int Rk610_hdmi_Config_audio_informat(struct i2c_client *client) +{ + char c; + int ret=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + //Select configure for Audio Info + c=0x08; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x9f, &c); + //Configure the Audio info to HDMI RX. + c=0x84; //HB0 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa0, &c); + c=0x01; //HB1 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa1, &c); + c=0x0a; //HB2 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa2, &c); + //c=0x00; //PB0 + //ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa3, &c); + c=0x11; //PB1 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa4, &c); + c=0x09; //PB2 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa5, &c); + c=0x00; //PB3 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa6, &c); + c=0x00; //PB4 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa7, &c); + c=0x01; //PB5 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa8, &c); + return ret; +} + +static int Rk610_hdmi_Config_Avi_informat(struct i2c_client *client ,u8 vic) +{ + char c; + int ret=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + //Select configure for AVI Info + c = 0x06; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x9f, &c); + + //Configure the AVI info to HDMI RX + c = 0x82; //HB0 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa0, &c); + c = 0x02; //HB1 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa1, &c); + c = 0x0d; //HB2 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa2, &c); + //c=0x00; //PB0 + //ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa3, &c); + c = 0x00; //PB1 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa4, &c); + c = 0x08; //PB2 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa5, &c); + c = 0x70; //PB3 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa6, &c); + c = vic; //PB4 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa7, &c); + c = 0x40; //PB5 + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa8, &c); + return ret; +} +static int Rk610_hdmi_Config_Video(struct i2c_client *client, u8 video_format) +{ + char vic; + int ret = 0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + switch(video_format){ + case HDMI_720x480p_60Hz_4x3: + case HDMI_720x480p_60Hz_16x9: + vic = 0x02; + break; + case HDMI_720x576p_50Hz_4x3: + case HDMI_720x576p_50Hz_16x9: + vic = 0x11; + break; + case HDMI_1280x720p_50Hz: + vic = 0x13; + break; + case HDMI_1280x720p_60Hz: + vic = 0x04; + break; + case HDMI_1920x1080p_50Hz: + vic = 0x1f; + break; + case HDMI_1920x1080p_60Hz: + vic = 0x10; + break; + default: + vic = 0x04; + break; + } + ret = Rk610_hdmi_Config_Avi_informat(client,vic); + return ret; +} +static int Rk610_hdmi_Config_Audio(struct i2c_client *client ,u8 audio_fs) +{ + char c=0; + int ret = 0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + c=0x01; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x35, &c); + c=0x3c; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x38, &c); + c=0x00; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x39, &c); + c=0x18; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x40, &c); + switch(audio_fs){ + case HDMI_I2S_Fs_44100: + c=0x80; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c); + break; + case HDMI_I2S_Fs_48000: + c=0x92; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c); + break; + default: + c=0x80; + ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c); + break; + } + Rk610_hdmi_Config_audio_informat(client); + return ret; +} + +int Rk610_hdmi_Set_Video(u8 video_format) +{ + if(g_hw_inf.video_format !=video_format){ + g_hw_inf.video_format = video_format; + g_hw_inf.config_param |= VIDEO_CHANGE; + } + return 0; +} +int Rk610_hdmi_Set_Audio(u8 audio_fs) +{ + if(g_hw_inf.audio_fs !=audio_fs){ + g_hw_inf.audio_fs = audio_fs; + g_hw_inf.config_param |= AUDIO_CHANGE; + } + return 0; +} +static int RK610_hdmi_Driver_mode(struct i2c_client *client) +{ + char c; + int ret=0; + c=0x8e; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c); + c=0x04; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe2, &c); + return 0; +} +static int RK610_hdmi_PLL_mode(struct i2c_client *client) +{ + char c; + int ret=0; + c=0x10; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe8, &c); + c=0x2c; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe6, &c); + c=0x00; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c); + return 0; +} +void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd) +{ + char c=0; + int ret=0; + + c=0x00; + ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c); + if(c & RK610_HPD_EVENT){ + RK610_DBG(&client->dev,">>>HPD EVENT\n"); + /**********clear hpd event******/ + c=RK610_HPD_EVENT; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c); + c=0x00; + ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c); + if(c & RK610_HPD_PLUG ){ + RK610_DBG(&client->dev,">>> hdmi plug \n"); + DoEdidRead(client); + Rk610_hdmi_Display_switch(client); + Rk610_hdmi_pwr_mode(client,NORMAL); + *hpd=1; + } + else{ + RK610_DBG(&client->dev,">>> hdmi unplug \n"); + g_edid.edidDataValid = FALSE; + Rk610_hdmi_pwr_mode(client,LOWER_PWR); + *hpd=0; + } + + } + if(c & RK610_EDID_EVENT){ + /**********clear hpd event******/ + c=RK610_EDID_EVENT; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c); + RK610_DBG(&client->dev,">>>EDID EVENT\n"); + /*************clear edid event*********/ + } +} +int Rk610_hdmi_Config_Done(struct i2c_client *client) +{ + char c; + int ret=0; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + + ret =Rk610_hdmi_sys_power_up(client); + + if(g_hw_inf.config_param != 0){ + c=0x08; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x04, &c); + c=0x01; + ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x01, &c); + if(g_hw_inf.config_param & VIDEO_CHANGE){ + Rk610_hdmi_Config_Video(client,g_hw_inf.video_format); + g_hw_inf.config_param &= (~VIDEO_CHANGE); + } + if(g_hw_inf.config_param & AUDIO_CHANGE){ + Rk610_hdmi_Config_Audio(client,g_hw_inf.audio_fs); + g_hw_inf.config_param &= (~AUDIO_CHANGE); + } + } + ret =Rk610_hdmi_sys_power_down(client); + ret =Rk610_hdmi_sys_power_up(client); + ret =Rk610_hdmi_sys_power_down(client); + + return ret; +} +#if 0 +int Rk610_hdmi_hpd(struct i2c_client *client) +{ + char c; + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + if(Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c)<0){ + RK610_ERR(">>>%s I2c trans err",__FUNCTION__); + return -1; + } + if() + return (c & RK610_HPD_PLUG)?1:0; +} +#endif +static int RK610_hdmi_soft_reset(struct i2c_client *client) +{ + char c; + int ret; + //soft reset + c=0x00; + ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xce, &c); + msleep(10); + c=0x01; + ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xce, &c); + msleep(100); + return ret; +} +static void Rk610_hdmi_Variable_Initial(void) +{ + memset(&g_hw_inf,0,sizeof(struct rk610_hdmi_hw_inf)); + g_edid.edidDataValid = FALSE; + g_hw_inf.edid_inf = &g_edid; + g_hw_inf.audio_fs = HDMI_I2S_DEFAULT_Fs; + g_hw_inf.video_format = HDMI_DEFAULT_RESOLUTION; + g_hw_inf.config_param = AUDIO_CHANGE | VIDEO_CHANGE; + +} +int Rk610_hdmi_init(struct i2c_client *client) +{ + RK610_DBG(&client->dev,"%s \n",__FUNCTION__); + Rk610_hdmi_Variable_Initial(); + RK610_hdmi_soft_reset(client); + RK610_hdmi_Driver_mode(client); + RK610_hdmi_PLL_mode(client); + Rk610_hdmi_Set_Video(g_hw_inf.video_format); + Rk610_hdmi_Set_Audio(g_hw_inf.audio_fs); + Rk610_hdmi_Config_Done(client); + + return 0; +} diff --git a/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h new file mode 100644 index 000000000000..59c296578f05 --- /dev/null +++ b/drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h @@ -0,0 +1,208 @@ +#ifndef _RK610_HDMI_HW_H +#define _RK610_HDMI_HW_H +#include + +#define MAX_V_DESCRIPTORS 20 +#define MAX_A_DESCRIPTORS 10 +#define MAX_SPEAKER_CONFIGURATIONS 4 +#define AUDIO_DESCR_SIZE 3 + +#define EDID_BLOCK_SIZE 128 +#define NUM_OF_EXTEN_ADDR 0x7e +#define EDID_HDR_NO_OF_FF 0x06 + +// Data Block Tag Codes +//==================================================== +#define AUDIO_D_BLOCK 0x01 +#define VIDEO_D_BLOCK 0x02 +#define VENDOR_SPEC_D_BLOCK 0x03 +#define SPKR_ALLOC_D_BLOCK 0x04 +#define USE_EXTENDED_TAG 0x07 +// Extended Data Block Tag Codes +//==================================================== +#define COLORIMETRY_D_BLOCK 0x05 + +#define HDMI_SIGNATURE_LEN 0x03 + +#define CEC_PHYS_ADDR_LEN 0x02 +#define EDID_EXTENSION_TAG 0x02 +#define EDID_REV_THREE 0x03 +#define EDID_DATA_START 0x04 + +#define EDID_BLOCK_0 0x00 +#define EDID_BLOCK_2_3 0x01 + +#define VIDEO_CAPABILITY_D_BLOCK 0x00 + +//#define DEV_SUPPORT_CEC +#if 1 +#define MSBIT 0x80 +#define LSBIT 0x01 + +#define TWO_LSBITS 0x03 +#define THREE_LSBITS 0x07 +#define FOUR_LSBITS 0x0F +#define FIVE_LSBITS 0x1F +#define SEVEN_LSBITS 0x7F +#define TWO_MSBITS 0xC0 +#define EIGHT_BITS 0xFF +#define BYTE_SIZE 0x08 +#define BITS_1_0 0x03 +#define BITS_2_1 0x06 +#define BITS_2_1_0 0x07 +#define BITS_3_2 0x0C +#define BITS_4_3_2 0x1C +#define BITS_5_4 0x30 +#define BITS_5_4_3 0x38 +#define BITS_6_5 0x60 +#define BITS_6_5_4 0x70 +#define BITS_7_6 0xC0 + +#define TPI_INTERNAL_PAGE_REG 0xBC +#define TPI_INDEXED_OFFSET_REG 0xBD +#define TPI_INDEXED_VALUE_REG 0xBE + +#define EDID_TAG_ADDR 0x00 +#define EDID_REV_ADDR 0x01 +#define EDID_TAG_IDX 0x02 +#define LONG_DESCR_PTR_IDX 0x02 +#define MISC_SUPPORT_IDX 0x03 + +#define ESTABLISHED_TIMING_INDEX 35 // Offset of Established Timing in EDID block +#define NUM_OF_STANDARD_TIMINGS 8 +#define STANDARD_TIMING_OFFSET 38 +#define LONG_DESCR_LEN 18 +#define NUM_OF_DETAILED_DESCRIPTORS 4 + +#define DETAILED_TIMING_OFFSET 0x36 +#endif +enum{ + EDID_BLOCK0=0, + EDID_BLOCK1, + EDID_BLOCK2, + EDID_BLOCK3, +}; +#define RK610_SYS_FREG_CLK 11289600 +#define RK610_SCL_RATE (100*1000) +#define RK610_DDC_CONFIG (RK610_SYS_FREG_CLK>>2)/RK610_SCL_RATE + +#define FALSE 0 +#define TRUE 1 + +//EVENT +#define RK610_HPD_EVENT 1<<7 +#define RK610_HPD_PLUG 1<<7 +#define RK610_EDID_EVENT 1<<2 + +//output mode 0x52 +#define DISPLAY_DVI 0 +#define DISPLAY_HDMI 1 + +//0x00 +#define RK610_INT_POL 1 +#define RK610_SYS_PWR_ON 1 +#define RK610_SYS_PWR_OFF 0 +#define RK610_PHY_CLK 0 +#define RK610_SYS_CLK 1 + +#define RK610_MCLK_FS 0x01 //256fs +//0x01 +// INPUT_VIDEO_FORMAT +#define RGB_YUV444 0x00 +#define DDR_RGB444_YUV444 0x05 +#define DDR_YUV422 0x06 + +//0x02 +//video output format +#define RGB444 0x00 +#define YUV444 0x01 +#define YUV422 0x02 + +//DATA WIDTH +#define DATA_12BIT 0X00 +#define DATA_10BIT 0X01 +#define DATA_8BIT 0X03 + +//0X04 +//1:after 0:not After 1st sof for external DE sample +#define DE_AFTER_SOF 0 +#define DE_NOAFTER_SOF 1 + +#define CSC_ENABLE 0 +#define CSC_DISABLE 1 + +//0X05 +#define CLEAR_AVMUTE(x) (x)<<7 +#define SET_AVMUTE(x) (x)<<6 +#define AUDIO_MUTE(x) (x)<<1 +#define VIDEO_BLACK(x) (x)<<0 //1:black 0:normal + +//0x08 +#define VSYNC_POL(x) (x)<<3 //0:Negative 1:Positive +#define HSYNC_POL(x) (x)<<2 //0:Negative 1:Positive +#define INTER_PROGRESSIVE(x) (x)<<1 //0: progressive 1:interlace +#define VIDEO_SET_ENABLE(x) (x)<<0 //0:disable 1: enable + +/**********CONFIG CHANGE ************/ +#define VIDEO_CHANGE 1<<0 +#define AUDIO_CHANGE 1<<1 + +#define byte u8 + +typedef struct edid_info +{ // for storing EDID parsed data + byte edidDataValid; + byte VideoDescriptor[MAX_V_DESCRIPTORS]; // maximum number of video descriptors + byte AudioDescriptor[MAX_A_DESCRIPTORS][3]; // maximum number of audio descriptors + byte SpkrAlloc[MAX_SPEAKER_CONFIGURATIONS]; // maximum number of speaker configurations + byte UnderScan; // "1" if DTV monitor underscans IT video formats by default + byte BasicAudio; // Sink supports Basic Audio + byte YCbCr_4_4_4; // Sink supports YCbCr 4:4:4 + byte YCbCr_4_2_2; // Sink supports YCbCr 4:2:2 + byte HDMI_Sink; // "1" if HDMI signature found + byte CEC_A_B; // CEC Physical address. See HDMI 1.3 Table 8-6 + byte CEC_C_D; + byte ColorimetrySupportFlags; // IEC 61966-2-4 colorimetry support: 1 - xvYCC601; 2 - xvYCC709 + byte MetadataProfile; + byte _3D_Supported; + +} EDID_INF; +enum EDID_ErrorCodes +{ + EDID_OK, + EDID_INCORRECT_HEADER, + EDID_CHECKSUM_ERROR, + EDID_NO_861_EXTENSIONS, + EDID_SHORT_DESCRIPTORS_OK, + EDID_LONG_DESCRIPTORS_OK, + EDID_EXT_TAG_ERROR, + EDID_REV_ADDR_ERROR, + EDID_V_DESCR_OVERFLOW, + EDID_UNKNOWN_TAG_CODE, + EDID_NO_DETAILED_DESCRIPTORS, + EDID_DDC_BUS_REQ_FAILURE, + EDID_DDC_BUS_RELEASE_FAILURE +}; +enum PWR_MODE{ + NORMAL, + LOWER_PWR, + SHUTDOWN, +}; +struct rk610_hdmi_hw_inf{ + struct i2c_client *client; + EDID_INF *edid_inf; + u8 video_format; + u8 audio_fs; + u8 config_param; +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +extern int Rk610_hdmi_suspend(struct i2c_client *client); +extern int Rk610_hdmi_resume(struct i2c_client *client); +#endif +extern int Rk610_hdmi_Set_Video(u8 video_format); +extern int Rk610_hdmi_Set_Audio(u8 audio_fs); +extern int Rk610_hdmi_Config_Done(struct i2c_client *client); +extern void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd); +extern int Rk610_hdmi_init(struct i2c_client *client); +#endif \ No newline at end of file diff --git a/drivers/video/hdmi/hdmi-core.c b/drivers/video/hdmi/hdmi-core.c index 6e16767e35ad..1b17185b6da9 100755 --- a/drivers/video/hdmi/hdmi-core.c +++ b/drivers/video/hdmi/hdmi-core.c @@ -31,18 +31,24 @@ static void __hdmi_changed(struct hdmi *hdmi) mutex_lock(&hdmi->lock); precent = hdmi->ops->hdmi_precent(hdmi); - - if(precent && hdmi->mode == DISP_ON_LCD && hdmi->display_on){ + if(precent && (hdmi->mode == DISP_ON_LCD) && hdmi->display_on){ if(hdmi->ops->insert(hdmi) == 0){ - hdmi->mode = DISP_ON_HDMI; + hdmi->mode = hdmi->display_on; kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE); } else hdmi_dbg(hdmi->dev, "insert error\n"); + hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE); + + } + else if(precent &&(hdmi->mode != hdmi->display_on)&& hdmi->display_on){ + hdmi->mode = hdmi->display_on; + hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE); } - else if((!precent || !hdmi->display_on) && hdmi->mode == DISP_ON_HDMI){ + else if((!precent || !hdmi->display_on) && hdmi->mode != DISP_ON_LCD){ if(hdmi->ops->remove(hdmi) == 0){ hdmi->mode = DISP_ON_LCD; + hdmi_set_backlight(HDMI_ENABLE); kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE); } else @@ -61,7 +67,7 @@ void hdmi_suspend(struct hdmi *hdmi) { del_timer(&hdmi->timer); flush_delayed_work(&hdmi->work); - if(hdmi->mode == DISP_ON_HDMI){ + if(hdmi->mode != DISP_ON_LCD){ hdmi->ops->remove(hdmi); hdmi->mode = DISP_ON_LCD; } @@ -93,7 +99,7 @@ static void hdmi_detect_timer(unsigned long data) int precent = hdmi->ops->hdmi_precent(hdmi); if((precent && hdmi->mode == DISP_ON_LCD) || - (!precent && hdmi->mode == DISP_ON_HDMI)) + (!precent && hdmi->mode != DISP_ON_LCD)) hdmi_changed(hdmi, 100); mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200)); } @@ -189,7 +195,7 @@ int hdmi_get_scale(void) struct hdmi* hdmi = get_hdmi_struct(0); if(!hdmi) return 100; - else if(hdmi->mode == DISP_ON_HDMI) + else if(hdmi->mode != DISP_ON_LCD) return hdmi->scale; else return 100; diff --git a/drivers/video/hdmi/hdmi-fb.c b/drivers/video/hdmi/hdmi-fb.c index 5d8b8da10a59..87269e7c6030 100755 --- a/drivers/video/hdmi/hdmi-fb.c +++ b/drivers/video/hdmi/hdmi-fb.c @@ -55,10 +55,10 @@ #define H_BP3 60 #define H_VD3 720 #define H_FP3 16 -#define V_PW3 5 -#define V_BP3 35 +#define V_PW3 6 +#define V_BP3 30 #define V_VD3 480 -#define V_FP3 5 +#define V_FP3 9 /* 1080p@50Hz Timing */ #define OUT_CLK5 148500000 @@ -67,9 +67,9 @@ #define H_VD4 1920 #define H_FP4 528 #define V_PW4 5 -#define V_BP4 35 +#define V_BP4 36 #define V_VD4 1080 -#define V_FP4 5 +#define V_FP4 4 /* 1080p@60Hz Timing */ #define OUT_CLK4 148500000 @@ -78,9 +78,9 @@ #define H_VD5 1920 #define H_FP5 88 #define V_PW5 5 -#define V_BP5 35 +#define V_BP5 36 #define V_VD5 1080 -#define V_FP5 5 +#define V_FP5 4 extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ); @@ -98,6 +98,7 @@ static int anx7150_standby(u8 enable) struct rk29fb_screen hdmi_info[] = { { + .hdmi_resolution = HDMI_1280x720p_50Hz, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD0, @@ -123,6 +124,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_1280x720p_50Hz { + .hdmi_resolution = HDMI_1280x720p_60Hz, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD1, @@ -148,6 +150,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_1280x720p_60Hz { + .hdmi_resolution = HDMI_720x576p_50Hz_4x3, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD2, @@ -173,6 +176,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_720x576p_50Hz_4x3 { + .hdmi_resolution = HDMI_720x576p_50Hz_16x9, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD2, @@ -198,6 +202,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_720x576p_50Hz_16x9 { + .hdmi_resolution = HDMI_720x480p_60Hz_4x3, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD3, @@ -223,6 +228,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_720x480p_60Hz_4x3 { + .hdmi_resolution = HDMI_720x480p_60Hz_16x9, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD3, @@ -248,6 +254,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_720x480p_60Hz_16x9 { + .hdmi_resolution = HDMI_1920x1080p_50Hz, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD4, @@ -260,8 +267,8 @@ struct rk29fb_screen hdmi_info[] = { .upper_margin = V_BP4, .lower_margin = V_FP4, .vsync_len = V_PW4, - .pin_hsync = 0, - .pin_vsync = 0, + .pin_hsync = 1, + .pin_vsync = 1, .pin_den = 0, .pin_dclk = DCLK_POL, .swap_rb = SWAP_RB, @@ -273,6 +280,7 @@ struct rk29fb_screen hdmi_info[] = { .standby = anx7150_standby, }, //HDMI_1920x1080p_50Hz { + .hdmi_resolution = HDMI_1920x1080p_60Hz, .type = OUT_TYPE, .face = OUT_FACE, .x_res = H_VD5, @@ -285,8 +293,8 @@ struct rk29fb_screen hdmi_info[] = { .upper_margin = V_BP5, .lower_margin = V_FP5, .vsync_len = V_PW5, - .pin_hsync = 0, - .pin_vsync = 0, + .pin_hsync = 1, + .pin_vsync = 1, .pin_den = 0, .pin_dclk = DCLK_POL, .swap_rb = SWAP_RB, diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index e36f6e21eb55..9db07658bcd2 100644 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -50,6 +50,7 @@ #include #endif + #include #include @@ -61,6 +62,9 @@ #include "./display/screen/screen.h" +#ifdef CONFIG_MFD_RK610 +#include "./display/lcd/rk610_lcd.h" +#endif #define ANDROID_USE_THREE_BUFS 0 //android use three buffers to accelerate UI display in rgb plane #define CURSOR_BUF_SIZE 256 //RK2818 cursor need 256B buf int rk29_cursor_buf[CURSOR_BUF_SIZE]; @@ -232,7 +236,18 @@ struct rk29fb_inf { #endif }; - +#ifdef CONFIG_BACKLIGHT_RK29_BL +/* drivers/video/backlight/rk29_backlight.c */ +extern void rk29_backlight_set(bool on); +#else +void rk29_backlight_set(bool on) +{ + /* please add backlight switching-related code here or on your backlight driver + parameter: on=1 ==> open spk + on=0 ==> close spk + */ +} +#endif typedef enum _TRSP_MODE { TRSP_CLOSE = 0, @@ -2922,10 +2937,13 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ) if(inf->cur_screen->standby) inf->cur_screen->standby(1); // operate the display_on pin to power down the lcd - +#ifdef CONFIG_HDMI_DUAL_DISP + inf->panel1_info.sscreen_get(&inf->panel1_info,inf->panel2_info.hdmi_resolution); + inf->panel1_info.sscreen_set(&inf->panel1_info,enable); +#else if(enable && mach_info->io_disable)mach_info->io_disable(); //close lcd out else if (mach_info->io_enable)mach_info->io_enable(); //open lcd out - +#endif load_screen(inf->fb0, 0); mcu_refresh(inf); @@ -2933,6 +2951,7 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ) fb0_set_par(inf->fb0); LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(0)); LcdWrReg(inf, REG_CFG_DONE, 0x01); + rk29fb_notify(inf, enable ? RK29FB_EVENT_HDMI_ON : RK29FB_EVENT_HDMI_OFF); return 0; } @@ -3204,6 +3223,7 @@ static int __devinit rk29fb_probe (struct platform_device *pdev) #else set_lcd_info(&inf->panel1_info, mach_info->lcd_info); #endif + inf->cur_screen = &inf->panel1_info; screen = inf->cur_screen; if(SCREEN_NULL==screen->type) @@ -3486,7 +3506,9 @@ static int __devinit rk29fb_probe (struct platform_device *pdev) goto release_irq; } } - + #ifdef CONFIG_MFD_RK610 + rk610_lcd_scaler_set_param(&inf->panel1_info,0); + #endif #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) fb0_set_par(inf->fb0); if (fb_prepare_logo(inf->fb0, FB_ROTATE_UR)) { diff --git a/include/linux/display-sys.h b/include/linux/display-sys.h new file mode 100644 index 000000000000..6eb0080398e0 --- /dev/null +++ b/include/linux/display-sys.h @@ -0,0 +1,69 @@ +#ifndef _LINUX_DISPLAY_RK_H +#define _LINUX_DISPLAY_RK_H + +#include +#include +#include + +struct rk_display_device; + +enum rk_display_priority { + DISPLAY_PRIORITY_TV = 0, + DISPLAY_PRIORITY_YPbPr, + DISPLAY_PRIORITY_VGA, + DISPLAY_PRIORITY_HDMI, + DISPLAY_PRIORITY_LCD, +}; + +/* This structure defines all the properties of a Display. */ +struct rk_display_driver { + void (*suspend)(struct rk_display_device *, pm_message_t state); + void (*resume)(struct rk_display_device *); + int (*probe)(struct rk_display_device *, void *); + int (*remove)(struct rk_display_device *); +}; + +struct rk_display_ops { + int (*setenable)(struct rk_display_device *, int enable); + int (*getenable)(struct rk_display_device *); + int (*getstatus)(struct rk_display_device *); + int (*getmodelist)(struct rk_display_device *, struct list_head **modelist); + int (*setmode)(struct rk_display_device *, struct fb_videomode *mode); + int (*getmode)(struct rk_display_device *, struct fb_videomode *mode); +}; + +struct rk_display_device { + struct module *owner; /* Owner module */ + struct rk_display_driver *driver; + struct device *parent; /* This is the parent */ + struct device *dev; /* This is this display device */ + struct mutex lock; + void *priv_data; + char type[16]; + char *name; + int idx; + struct rk_display_ops *ops; + int priority; + struct list_head list; +}; + +struct rk_display_devicelist { + struct list_head list; + struct rk_display_device *dev; +}; + +extern struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver, + struct device *dev, void *devdata); +extern void rk_display_device_unregister(struct rk_display_device *dev); + +extern void rk_display_device_enable(struct rk_display_device *ddev); + +extern void rk_display_device_enable_other(struct rk_display_device *ddev); +extern void rk_display_device_disable_other(struct rk_display_device *ddev); + + +extern void rk_display_device_select(int priority); + +#define to_rk_display_device(obj) container_of(obj, struct rk_display_device, class_dev) + +#endif diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 551d2694f0fa..27958ba9c6b0 100755 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -62,7 +62,7 @@ typedef int BOOL; #define HDMI_720x480p_60Hz_16x9 7 /* HDMI default resolution */ -#define HDMI_DEFAULT_RESOLUTION HDMI_1920x1080p_50Hz +#define HDMI_DEFAULT_RESOLUTION HDMI_1920x1080p_50Hz /* I2S Fs */ #define HDMI_I2S_Fs_44100 0 #define HDMI_I2S_Fs_48000 2 diff --git a/include/linux/mfd/rk610_core.h b/include/linux/mfd/rk610_core.h new file mode 100644 index 000000000000..bc1c50361233 --- /dev/null +++ b/include/linux/mfd/rk610_core.h @@ -0,0 +1,142 @@ +#ifndef __RK610_CONTROL_H_ +#define __RK610_CONTROL_H_ + +#define INVALID_GPIO -1 +#define RK610_DEBUG 1 + +#if RK610_DEBUG +#define RK610_DBG(dev, format, arg...) \ +do{\ + dev_printk(KERN_INFO , dev , format , ## arg);\ +}while(0) +#else +#define RK610_DBG(dev, format, arg...) +#endif +#define RK610_ERR(dev, format, arg...) \ +do{\ + dev_printk(KERN_ERR , dev , format , ## arg);\ +}while(0) + +#define RK610_CONTROL_REG_C_PLL_CON0 0x00 +#define RK610_CONTROL_REG_C_PLL_CON1 0x01 +#define RK610_CONTROL_REG_C_PLL_CON2 0x02 +#define RK610_CONTROL_REG_C_PLL_CON3 0x03 +#define RK610_CONTROL_REG_C_PLL_CON4 0x04 +#define RK610_CONTROL_REG_C_PLL_CON5 0x05 + #define C_PLL_DISABLE_FRAC 1 << 0 + #define C_PLL_BYPSS_ENABLE 1 << 1 + #define C_PLL_POWER_ON 1 << 2 + #define C_PLL_LOCLED 1 << 7 + +#define RK610_CONTROL_REG_TVE_CON 0x29 + #define TVE_CONTROL_VDAC_R_BYPASS_ENABLE 1 << 7 + #define TVE_CONTROL_VDAC_R_BYPASS_DISABLE 0 << 7 + #define TVE_CONTROL_CVBS_3_CHANNEL_ENALBE 1 << 6 + #define TVE_CONTROL_CVBS_3_CHANNEL_DISALBE 0 << 5 +enum { + INPUT_DATA_FORMAT_RGB888 = 0, + INPUT_DATA_FORMAT_RGB666, + INPUT_DATA_FORMAT_RGB565, + INPUT_DATA_FORMAT_YUV +}; + #define RGB2CCIR_INPUT_DATA_FORMAT(n) n << 4 + + #define RGB2CCIR_RGB_SWAP_ENABLE 1 << 3 + #define RGB2CCIR_RGB_SWAP_DISABLE 0 << 3 + + #define RGB2CCIR_INPUT_INTERLACE 1 << 2 + #define RGB2CCIR_INPUT_PROGRESSIVE 0 << 2 + + #define RGB2CCIR_CVBS_PAL 0 << 1 + #define RGB2CCIR_CVBS_NTSC 1 << 1 + + #define RGB2CCIR_DISABLE 0 + #define RGB2CCIR_ENABLE 1 + +#define RK610_CONTROL_REG_CCIR_RESET 0x2a + +#define RK610_CONTROL_REG_CLOCK_CON0 0x2b +#define RK610_CONTROL_REG_CLOCK_CON1 0x2c + #define CLOCK_CON1_I2S_CLK_CODEC_PLL 1 << 5 + #define CLOCK_CON1_I2S_DVIDER_MASK 0x1F +#define RK610_CONTROL_REG_CODEC_CON 0x2d + #define CODEC_CON_BIT_HDMI_BLCK_INTERANL 1<<4 + #define CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE 1<<3 + #define CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE 1<<2 + #define CODEC_CON_BIT_INTERAL_CODEC_DISABLE 1<<0 + +#define RK610_CONTROL_REG_I2C_CON 0x2e + +/******************************************************************** +** ½á¹¹¶¨Òå * +********************************************************************/ +/* RK610µÄ¼Ä´æÆ÷½á¹¹ */ +/* CODEC PLL REG */ +#define C_PLL_CON0 0x00 +#define C_PLL_CON1 0x01 +#define C_PLL_CON2 0x02 +#define C_PLL_CON3 0x03 +#define C_PLL_CON4 0x04 +#define C_PLL_CON5 0x05 + +/* SCALER PLL REG */ +#define S_PLL_CON0 0x06 +#define S_PLL_CON1 0x07 +#define S_PLL_CON2 0x08 + +/* LVDS REG */ +#define LVDS_CON0 0x09 +#define LVDS_CON1 0x0a + +/* LCD1 REG */ +#define LCD1_CON 0x0b + +/* SCALER REG */ +#define SCL_CON0 0x0c +#define SCL_CON1 0x0d +#define SCL_CON2 0x0e +#define SCL_CON3 0x0f +#define SCL_CON4 0x10 +#define SCL_CON5 0x11 +#define SCL_CON6 0x12 +#define SCL_CON7 0x13 +#define SCL_CON8 0x14 +#define SCL_CON9 0x15 +#define SCL_CON10 0x16 +#define SCL_CON11 0x17 +#define SCL_CON12 0x18 +#define SCL_CON13 0x19 +#define SCL_CON14 0x1a +#define SCL_CON15 0x1b +#define SCL_CON16 0x1c +#define SCL_CON17 0x1d +#define SCL_CON18 0x1e +#define SCL_CON19 0x1f +#define SCL_CON20 0x20 +#define SCL_CON21 0x21 +#define SCL_CON22 0x22 +#define SCL_CON23 0x23 +#define SCL_CON24 0x24 +#define SCL_CON25 0x25 +#define SCL_CON26 0x26 +#define SCL_CON27 0x27 +#define SCL_CON28 0x28 + +/* TVE REG */ +#define TVE_CON 0x29 + +/* CCIR REG */ +#define CCIR_RESET 0X2a + +/* CLOCK REG */ +#define CLOCK_CON0 0X2b +#define CLOCK_CON1 0X2c + +/* CODEC REG */ +#define CODEC_CON 0x2e +#define I2C_CON 0x2f + + +extern int rk610_control_send_byte(const char reg, const char data); + +#endif /*end of __RK610_CONTROL_H_*/ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 012792738795..594a1662839f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -78,6 +78,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5621 if I2C select SND_SOC_RT5631 if I2C select SND_SOC_RT5625 if I2C + select SND_SOC_RK610 if I2C select SND_SOC_WM8903 if I2C select SND_SOC_WM8904 if I2C select SND_SOC_WM8915 if I2C @@ -395,6 +396,10 @@ config SND_SOC_RK1000 tristate # depends on RK1000_CONTROL +config SND_SOC_RK610 + tristate + depends on MFD_RK610 + # Amp config SND_SOC_LM4857 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index e9d88b2d3ba5..3720639b5912 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -87,6 +87,7 @@ snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o snd-soc-rk1000-objs := rk1000_codec.o snd-soc-jz4740-codec-objs := jz4740.o +snd-soc-rk610-objs := rk610_codec.o # Amp snd-soc-lm4857-objs := lm4857.o @@ -184,7 +185,7 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o - +obj-$(CONFIG_SND_SOC_RK610) += snd-soc-rk610.o # Amp obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o diff --git a/sound/soc/codecs/rk610_codec.c b/sound/soc/codecs/rk610_codec.c new file mode 100644 index 000000000000..380309b31080 --- /dev/null +++ b/sound/soc/codecs/rk610_codec.c @@ -0,0 +1,1137 @@ +/* + * rk610.c -- RK610 ALSA SoC audio driver + * + * Copyright (C) 2009 rockchip lhh + * + * + * Based on RK610.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rk610_codec.h" + +#define RK610_SPK_CTRL_PIN RK29_PIN6_PB6 + + +/* + * Debug + */ +#if 0 +#define DBG(x...) printk(KERN_ERR x) +#else +#define DBG(x...) +#endif + +#define err(format, arg...) \ + printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) + +#define OUT_CAPLESS (0) //ÊÇ·ñΪÎÞµçÈÝÊä³ö£¬1:ÎÞµçÈÝÊä³ö£¬0:ÓеçÈÝÊä³ö + +static u32 gVolReg = 0x00; ///0x0f; //ÓÃÓڼǼÒôÁ¿¼Ä´æÆ÷ +//static u32 gCodecVol = 0x0f; +static u8 gR0AReg = 0; //ÓÃÓڼǼR0A¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0AÍ£Ö¹clk +static u8 gR0BReg = 0; //ÓÃÓڼǼR0B¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0BÍ£Ö¹interplateºÍdecimation +//static u8 gR1314Reg = 0; //ÓÃÓڼǼR13,R14¼Ä´æÆ÷µÄÖµ£¬ÓÃÓÚFMÒôÁ¿Îª0ʱ + +/* + * rk610 register cache + * We can't read the RK610 register space when we + * are using 2 wire for device control, so we cache them instead. + */ +static const u16 rk610_codec_reg[] = { + 0x0005, 0x0004, 0x00fd, 0x00f3, /* 0 */ + 0x0003, 0x0000, 0x0000, 0x0000, /* 4 */ + 0x0000, 0x0005, 0x0000, 0x0000, /* 8 */ + 0x0097, 0x0097, 0x0097, 0x0097, /* 12 */ + 0x0097, 0x0097, 0x00cc, 0x0000, /* 16 */ + 0x0000, 0x00f1, 0x0090, 0x00ff, /* 20 */ + 0x00ff, 0x00ff, 0x009c, 0x0000, /* 24 */ + 0x0000, 0x00ff, 0x00ff, 0x00ff, /* 28 */ +}; + +static struct snd_soc_codec *rk610_codec_codec; +/* codec private data */ +struct rk610_codec_priv { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + enum snd_soc_control_type control_type; +#endif + unsigned int sysclk; + struct snd_soc_codec codec; + struct snd_pcm_hw_constraint_list *sysclk_constraints; + u16 reg_cache[RK610_CODEC_NUM_REG]; +}; + +extern int rk610_control_init_codec(void); +extern int rk610_codec_pll_set(unsigned int rate); + +/* + * read rk610 register cache + */ +static inline unsigned int rk610_codec_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg > RK610_CACHE_REGNUM) + return -1; + return cache[reg]; +} + +static unsigned int rk610_codec_read(struct snd_soc_codec *codec, unsigned int r) +{ + struct i2c_msg xfer[1]; + u8 reg = r; + int ret; + struct i2c_client *client = codec->control_data; + + /* Read register */ + xfer[0].addr = (client->addr& 0x60)|(reg); + xfer[0].flags = I2C_M_RD; + xfer[0].len = 1; + xfer[0].buf = ® + xfer[0].scl_rate = 100000; + ret = i2c_transfer(client->adapter, xfer, 1); + if (ret != 1) { + dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); + return 0; + } + + return reg; +} +/* + * write rk610 register cache + */ +static inline void rk610_codec_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg > RK610_CACHE_REGNUM) + return; + cache[reg] = value; +} + +static int rk610_codec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + struct i2c_client *i2c; + DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value); + data[0] = value & 0x00ff; + rk610_codec_write_reg_cache (codec, reg, value); + i2c = (struct i2c_client *)codec->control_data; + i2c->addr = (i2c->addr & 0x60)|reg; + + if (codec->hw_write(codec->control_data, data, 1) == 1){ +// DBG("================%s %d Run OK================\n",__FUNCTION__,__LINE__); + return 0; + }else{ + DBG("================%s %d Run EIO================\n",__FUNCTION__,__LINE__); + return -EIO; + } +} + +void rk610_codec_reg_read(void) +{ + struct snd_soc_codec *codec = rk610_codec_codec; + int i; + unsigned int data; + + for (i=0; i<=0x1f; i++){ + data = rk610_codec_read(codec, i); + DBG("reg[0x%x]=0x%x\n",i,data); + } +} + +static const struct snd_kcontrol_new rk610_codec_snd_controls[] = { +SOC_DOUBLE_R("Capture Volume", ACCELCODEC_R0C, ACCELCODEC_R0D, 0, 15, 0), +SOC_DOUBLE_R("Capture Switch", ACCELCODEC_R0C, ACCELCODEC_R0D, 7, 1, 1), +SOC_DOUBLE_R("PCM Volume", ACCELCODEC_R0D, ACCELCODEC_R0E, 0, 7, 0), +//SOC_SINGLE("Left ADC Capture Volume", ACCELCODEC_R17, 0, 63, 0), +//SOC_SINGLE("Right ADC Capture Volume", ACCELCODEC_R18, 0, 63, 0), +}; + +/* Left Mixer */ +static const struct snd_kcontrol_new rk610_codec_left_mixer_controls[] = { +SOC_DAPM_SINGLE("Left Playback Switch", ACCELCODEC_R15, 6, 1, 0), +SOC_DAPM_SINGLE("Left Bypass Switch", ACCELCODEC_R15, 2, 1, 0), +}; + +/* Right Mixer */ +static const struct snd_kcontrol_new rk610_codec_right_mixer_controls[] = { +SOC_DAPM_SINGLE("Right Playback Switch", ACCELCODEC_R15, 7, 1, 0), +SOC_DAPM_SINGLE("Right Bypass Switch", ACCELCODEC_R15, 3, 1, 0), +}; + +static const struct snd_soc_dapm_widget rk610_codec_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, + &rk610_codec_left_mixer_controls[0], + ARRAY_SIZE(rk610_codec_left_mixer_controls)), + SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, + &rk610_codec_right_mixer_controls[0], + ARRAY_SIZE(rk610_codec_right_mixer_controls)), + + //SND_SOC_DAPM_PGA("Right Out 1", ACCELCODEC_R1E, 0, 0, NULL, 0), + //SND_SOC_DAPM_PGA("Left Out 1", ACCELCODEC_R1E, 1, 0, NULL, 0), + //SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ACCELCODEC_R1F, 1, 0), + //SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ACCELCODEC_R1F, 2, 0), + + SND_SOC_DAPM_ADC("ADC", "Capture", ACCELCODEC_R1D, 6, 1), + SND_SOC_DAPM_ADC("ADC BUFF", "Capture BUFF", ACCELCODEC_R1D, 2, 0), + + + SND_SOC_DAPM_OUTPUT("LOUT1"), + SND_SOC_DAPM_OUTPUT("ROUT1"), + + SND_SOC_DAPM_INPUT("LINPUT1"), + SND_SOC_DAPM_INPUT("RINPUT1"), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* left mixer */ + {"Left Mixer", "Left Playback Switch", "Left DAC"}, + {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, + {"Right Mixer", "Right Playback Switch", "Right DAC"}, + {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, + + /* left out 1 */ + {"Left Out 1", NULL, "Left Mixer"}, + {"LOUT1", NULL, "Left Out 1"}, + + + /* right out 1 */ + {"Right Out 1", NULL, "Right Mixer"}, + {"ROUT1", NULL, "Right Out 1"}, + + /* Left Line Mux */ + {"Left Line Mux", "Line 1", "LINPUT1"}, + {"Left Line Mux", "PGA", "Left PGA Mux"}, + {"Left Line Mux", "Differential", "Differential Mux"}, + + /* Right Line Mux */ + {"Right Line Mux", "Line 1", "RINPUT1"}, + {"Right Line Mux", "PGA", "Right PGA Mux"}, + {"Right Line Mux", "Differential", "Differential Mux"}, + + /* Left PGA Mux */ + {"Left PGA Mux", "Line 1", "LINPUT1"}, + {"Left PGA Mux", "Line 2", "LINPUT2"}, + {"Left PGA Mux", "Line 3", "LINPUT3"}, + {"Left PGA Mux", "Differential", "Differential Mux"}, + + /* Right PGA Mux */ + {"Right PGA Mux", "Line 1", "RINPUT1"}, + {"Right PGA Mux", "Differential", "Differential Mux"}, + + /* Differential Mux */ + {"Differential Mux", "Line 1", "LINPUT1"}, + {"Differential Mux", "Line 1", "RINPUT1"}, + + /* Left ADC Mux */ + {"Left ADC Mux", "Stereo", "Left PGA Mux"}, + {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, + {"Left ADC Mux", "Digital Mono", "Left PGA Mux"}, + + /* Right ADC Mux */ + {"Right ADC Mux", "Stereo", "Right PGA Mux"}, + {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, + {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, + + /* ADC */ + {"Left ADC", NULL, "Left ADC Mux"}, + {"Right ADC", NULL, "Right ADC Mux"}, + + /* terminator */ +// {NULL, NULL, NULL}, +}; + +struct _coeff_div { + u32 mclk; + u32 rate; + u16 fs; + u8 sr:5; + u8 usb:1; + u8 bclk; +}; + +/* codec hifi mclk clock divider coefficients */ +static const struct _coeff_div coeff_div[] = { + /* 8k */ + {12288000, 8000, 1536, 0x6, 0x0,ASC_BCLKDIV_16}, + {11289600, 8000, 1408, 0x16, 0x0,ASC_BCLKDIV_16}, + {18432000, 8000, 2304, 0x7, 0x0,ASC_BCLKDIV_16}, + {16934400, 8000, 2112, 0x17, 0x0,ASC_BCLKDIV_16}, + {8192000, 8000, 1024, 0x0, 0x0,ASC_BCLKDIV_16}, + {12000000, 8000, 1500, 0x6, 0x1,ASC_BCLKDIV_16}, + + /* 11.025k */ + {11289600, 11025, 1024, 0x18, 0x0,ASC_BCLKDIV_16}, + {16934400, 11025, 1536, 0x19, 0x0,ASC_BCLKDIV_16}, + {12000000, 11025, 1088, 0x19, 0x1,ASC_BCLKDIV_16}, + + /* 12k */ + {12288000, 12000, 1024, 0x8, 0x0,ASC_BCLKDIV_16}, + {18432000, 12000, 1536, 0x9, 0x0,ASC_BCLKDIV_16}, + {12000000, 12000, 1000, 0x8, 0x1,ASC_BCLKDIV_16}, + + /* 16k */ + {12288000, 16000, 768, 0xa, 0x0,ASC_BCLKDIV_8}, + {18432000, 16000, 1152, 0xb, 0x0,ASC_BCLKDIV_8}, + {12000000, 16000, 750, 0xa, 0x1,ASC_BCLKDIV_8}, + + /* 22.05k */ + {11289600, 22050, 512, 0x1a, 0x0,ASC_BCLKDIV_8}, + {16934400, 22050, 768, 0x1b, 0x0,ASC_BCLKDIV_8}, + {12000000, 22050, 544, 0x1b, 0x1,ASC_BCLKDIV_8}, + + /* 24k */ + {12288000, 24000, 512, 0x1c, 0x0,ASC_BCLKDIV_8}, + {18432000, 24000, 768, 0x1d, 0x0,ASC_BCLKDIV_8}, + {12000000, 24000, 500, 0x1c, 0x1,ASC_BCLKDIV_8}, + + /* 32k */ + {12288000, 32000, 384, 0xc, 0x0,ASC_BCLKDIV_8}, + {18432000, 32000, 576, 0xd, 0x0,ASC_BCLKDIV_8}, + {12000000, 32000, 375, 0xa, 0x1,ASC_BCLKDIV_8}, + + /* 44.1k */ + {11289600, 44100, 256, 0x10, 0x0,ASC_BCLKDIV_4}, + {16934400, 44100, 384, 0x11, 0x0,ASC_BCLKDIV_8}, + {12000000, 44100, 272, 0x11, 0x1,ASC_BCLKDIV_8}, + + /* 48k */ + {12288000, 48000, 256, 0x0, 0x0,ASC_BCLKDIV_4}, + {18432000, 48000, 384, 0x1, 0x0,ASC_BCLKDIV_4}, + {12000000, 48000, 250, 0x0, 0x1,ASC_BCLKDIV_4}, + + /* 88.2k */ + {11289600, 88200, 128, 0x1e, 0x0,ASC_BCLKDIV_4}, + {16934400, 88200, 192, 0x1f, 0x0,ASC_BCLKDIV_4}, + {12000000, 88200, 136, 0x1f, 0x1,ASC_BCLKDIV_4}, + + /* 96k */ + {12288000, 96000, 128, 0xe, 0x0,ASC_BCLKDIV_4}, + {18432000, 96000, 192, 0xf, 0x0,ASC_BCLKDIV_4}, + {12000000, 96000, 125, 0xe, 0x1,ASC_BCLKDIV_4}, +}; + +static inline int get_coeff(int mclk, int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { + if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) + return i; + } + + return -EINVAL; +} + +/* The set of rates we can generate from the above for each SYSCLK */ + +static unsigned int rates_12288[] = { + 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_12288 = { + .count = ARRAY_SIZE(rates_12288), + .list = rates_12288, +}; + +static unsigned int rates_112896[] = { + 8000, 11025, 22050, 44100, +}; + +static struct snd_pcm_hw_constraint_list constraints_112896 = { + .count = ARRAY_SIZE(rates_112896), + .list = rates_112896, +}; + +static unsigned int rates_12[] = { + 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, + 48000, 88235, 96000, +}; + +static struct snd_pcm_hw_constraint_list constraints_12 = { + .count = ARRAY_SIZE(rates_12), + .list = rates_12, +}; + +/* + * Note that this should be called from init rather than from hw_params. + */ +static int rk610_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); +#else + struct rk610_codec_priv *rk610_codec = codec->private_data; +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + +// if(rk610_codec_pll_set(freq)) +// return -EINVAL; + + switch (freq) { + case 11289600: + case 18432000: + case 22579200: + case 36864000: + rk610_codec->sysclk_constraints = &constraints_112896; + rk610_codec->sysclk = freq; + break; + + case 12288000: + case 16934400: + case 24576000: + case 33868800: + rk610_codec->sysclk_constraints = &constraints_12288; + rk610_codec->sysclk = freq; + break; + + case 12000000: + case 24000000: + rk610_codec->sysclk_constraints = &constraints_12; + rk610_codec->sysclk = freq; + break; + default: + return -EINVAL; + } + return 0; +} + +static int rk610_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 iface = 0; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iface = 0x0040; + break; + case SND_SOC_DAIFMT_CBS_CFS: + iface = 0x0000; + break; + default: + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + iface |= 0x0002; + break; + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + iface |= 0x0001; + break; + case SND_SOC_DAIFMT_DSP_A: + iface |= 0x0003; + break; + case SND_SOC_DAIFMT_DSP_B: + iface |= 0x0013; + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + iface |= 0x0090; + break; + case SND_SOC_DAIFMT_IB_NF: + iface |= 0x0080; + break; + case SND_SOC_DAIFMT_NB_IF: + iface |= 0x0010; + break; + default: + return -EINVAL; + } + + DBG("Enter::%s----%d iface=%x\n",__FUNCTION__,__LINE__,iface); + rk610_codec_write(codec, ACCELCODEC_R09, iface); + return 0; +} + +static int rk610_codec_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_codec *codec = rtd->codec; + struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); +#else + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->card->codec; + struct rk610_codec_priv *rk610_codec = codec->private_data; +#endif + u16 iface = rk610_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3; + u16 srate = rk610_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180; + int coeff; + + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if (params->flags == HW_PARAMS_FLAG_EQVOL_ON) + { + u16 r17 = rk610_codec_read_reg_cache(codec, ACCELCODEC_R17); + u16 r18 = rk610_codec_read_reg_cache(codec, ACCELCODEC_R18); + + r17 &= (~0x3f); //6db + r18 &= (~0x3f); //6db + + rk610_codec_write(codec, ACCELCODEC_R17, r17); + rk610_codec_write(codec, ACCELCODEC_R18, r18); + + return 0; + } + else if (params->flags == HW_PARAMS_FLAG_EQVOL_OFF) + { + u16 r17 = rk610_codec_read_reg_cache(codec, ACCELCODEC_R17); + u16 r18 = rk610_codec_read_reg_cache(codec, ACCELCODEC_R18); + + r17 &= (~0x3f); + r17 |= 0x0f; //0db + + r18 &= (~0x3f); + r18 |= 0x0f; //0db + + rk610_codec_write(codec, ACCELCODEC_R17, r17); + rk610_codec_write(codec, ACCELCODEC_R18, r18); + return 0; + } + + coeff = get_coeff(rk610_codec->sysclk, params_rate(params)); + DBG("Enter::%s----%d rk610_codec->sysclk=%d coeff = %d\n",__FUNCTION__,__LINE__,rk610_codec->sysclk, coeff); + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + iface |= 0x0004; + break; + case SNDRV_PCM_FORMAT_S24_LE: + iface |= 0x0008; + break; + case SNDRV_PCM_FORMAT_S32_LE: + iface |= 0x000c; + break; + } + DBG("Enter::%s----%d iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params)); + +// rk610_codec_write(codec,ACCELCODEC_R0C, 0x17); + rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute + //±ØÐëÏȽ«clkºÍEN_INT¶¼disableµô£¬·ñÔòÇл»bclk·ÖƵֵ¿ÉÄܵ¼ÖÂcodecÄÚ²¿Ê±Ðò»ìÂÒµô£¬ + //±íÏÖ³öÀ´µÄÏÖÏóÊÇ£¬ÒÔºóµÄÒôÀÖ¶¼±ä³ÉÁËÔëÒô£¬¶øÇÒ¾ÍËã°ÑÊäÈëcodecµÄI2S_DATAOUT¶Ï¿ªÒ²Ò»Ñù³öÔëÒô + rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00 + + /* set iface & srate */ + #ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER + iface |= ASC_INVERT_BCLK;//·­×ªBCLK master״̬ËͳöµÄÉÙÁ˰ë¸öʱÖÓ£¬µ¼ÖÂδµ½×î´óÒôÁ¿µÄʱºòÆÆÒô¡¢ + #endif + rk610_codec_write(codec, ACCELCODEC_R09, iface); + if (coeff >= 0){ + rk610_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk); + rk610_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE); + } + rk610_codec_write(codec,ACCELCODEC_R0B, gR0BReg); + + return 0; +} + +void PhaseOut(struct snd_soc_codec *codec,u32 nStep, u32 us) +{ + DBG("%s[%d]\n",__FUNCTION__,__LINE__); + rk610_codec_write(codec,ACCELCODEC_R17, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL + rk610_codec_write(codec,ACCELCODEC_R18, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR + udelay(us); +} + +void PhaseIn(struct snd_soc_codec *codec,u32 nStep, u32 us) +{ + DBG("%s[%d]\n",__FUNCTION__,__LINE__); + rk610_codec_write(codec,ACCELCODEC_R17, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL + rk610_codec_write(codec,ACCELCODEC_R18, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR + udelay(us); +} + +static int rk610_codec_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + + DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute); + + if (mute) + { + PhaseOut(codec,1, 5000); + rk610_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM + rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute + //add for standby + if(!dai->capture_active) + { + rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE); + rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); + rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); + } + } + else + { + rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down + rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE); + + #if OUT_CAPLESS + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); + #else + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); + #endif + + PhaseIn(codec,1, 5000); + //if(gCodecVol != 0) + //{ + rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); + //} + rk610_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM +#if 0 + /*disable speaker */ + gpio_set_value(RK29_PIN6_PB6, GPIO_LOW); +#endif + rk610_codec_reg_read(); + } + + return 0; +} + +static int rk610_codec_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + DBG("Enter::%s----%d level =%d\n",__FUNCTION__,__LINE__,level); + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + /* VREF, VMID=2x50k, digital enabled */ + // rk610_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080); + break; + + case SND_SOC_BIAS_STANDBY: + printk("rk610 standby\n"); + rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE); + rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); + rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); + break; + + case SND_SOC_BIAS_OFF: + printk("rk610 power off\n"); + rk610_codec_write(codec, ACCELCODEC_R1D, 0xFF); + rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); + rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); + break; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + codec->dapm.bias_level = level; +#else + codec->bias_level = level; +#endif + return 0; +} + +#define RK610_CODEC_RATES SNDRV_PCM_RATE_8000_96000 + +#define RK610_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_ops rk610_codec_ops = { + .hw_params = rk610_codec_pcm_hw_params, + .set_fmt = rk610_codec_set_dai_fmt, + .set_sysclk = rk610_codec_set_dai_sysclk, + .digital_mute = rk610_codec_mute, +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static struct snd_soc_dai_driver rk610_codec_dai = +#else +struct snd_soc_dai rk610_codec_dai = +#endif +{ + .name = "rk610_codec_xx", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RK610_CODEC_RATES, + .formats = RK610_CODEC_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RK610_CODEC_RATES, + .formats = RK610_CODEC_FORMATS, + }, + .ops = &rk610_codec_ops, + .symmetric_rates = 1, +}; +EXPORT_SYMBOL_GPL(rk610_codec_dai); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk610_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) +#else +static int rk610_codec_suspend(struct platform_device *pdev, pm_message_t state) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); + rk610_codec_reg_read(); + + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk610_codec_resume(struct snd_soc_codec *codec) +#else +static int rk610_codec_resume(struct platform_device *pdev) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; +#endif + int i; + u8 data[2]; + struct i2c_client *i2c; + u16 *cache = codec->reg_cache; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Sync reg_cache with the hardware */ + for (i = 0; i < RK610_CODEC_NUM_REG; i++) { + data[0] = cache[i] & 0x00ff; + i2c = (struct i2c_client *)codec->control_data; + i2c->addr = (i2c->addr & 0x60)|i; + codec->hw_write(codec->control_data, data, 1); + } + + rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +#if 1 +#define USE_MIC_IN +#define USE_LPF 1 +void rk610_codec_reg_set(void) +{ + struct snd_soc_codec *codec = rk610_codec_codec; + unsigned int digital_gain; + + rk610_codec_write(codec,ACCELCODEC_R1D, 0xFF); + rk610_codec_write(codec,ACCELCODEC_R1E, 0xFF); + rk610_codec_write(codec,ACCELCODEC_R1F, 0xFF); + +#if USE_LPF + // Route R-LPF->R-Mixer, L-LPF->L-Mixer + rk610_codec_write(codec,ACCELCODEC_R15, 0xC1); +#else + // Route RDAC->R-Mixer, LDAC->L->Mixer + rk610_codec_write(codec,ACCELCODEC_R15, 0x0C); +#endif + // With Cap Output, VMID ramp up slow + rk610_codec_write(codec,ACCELCODEC_R1A, 0x14); + mdelay(10); + + rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB); //LIL + rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB); //LIR + rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|ASC_INPUT_VOL_0DB); //MIC +#ifdef USE_MIC_IN + rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB); //Select MIC input + rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); //0x00); //use default value +#else + rk610_codec_write(codec,ACCELCODEC_R12, 0x4c); //Select Line input +#endif + // Diable route PGA->R/L Mixer, PGA gain 0db. + rk610_codec_write(codec,ACCELCODEC_R13, 0x05 | 0 << 3); + rk610_codec_write(codec,ACCELCODEC_R14, 0x05 | 0 << 3); + + //2soft mute + rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute + + //2set default SR and clk + rk610_codec_write(codec,ACCELCODEC_R0A, ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE); + gR0AReg = ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE; + //2Config audio interface + rk610_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_MASTER_MODE|ASC_NORMAL_BCLK); + rk610_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_DISABLE|ASC_SCRAMBLE_DISABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_4); + //2volume,input,output + digital_gain = 0xE42; + rk610_codec_write(codec,ACCELCODEC_R05, (digital_gain >> 8) & 0xFF); + rk610_codec_write(codec,ACCELCODEC_R06, digital_gain & 0xFF); + rk610_codec_write(codec,ACCELCODEC_R07, (digital_gain >> 8) & 0xFF); + rk610_codec_write(codec,ACCELCODEC_R08, digital_gain & 0xFF); +// rk610_codec_write(codec,ACCELCODEC_R05, 0x0e); +// rk610_codec_write(codec,ACCELCODEC_R06, 0x42); +// rk610_codec_write(codec,ACCELCODEC_R07, 0x0e); +// rk610_codec_write(codec,ACCELCODEC_R08, 0x42); + + rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_ENABLE|ASC_INT_ENABLE); + gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE; //ASC_DEC_DISABLE|ASC_INT_ENABLE; + + rk610_codec_write(codec,ACCELCODEC_R1D, 0x30); + rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); + #if OUT_CAPLESS + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); + #else + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); + #endif +} +#else +void rk610_codec_reg_set(void) +{ + struct snd_soc_codec *codec = rk610_codec_codec; + int reg; + int i; + unsigned int data; + + rk610_codec_write(codec,ACCELCODEC_R1D, 0x00); + rk610_codec_write(codec,ACCELCODEC_R17, 0xFF); //AOL + rk610_codec_write(codec,ACCELCODEC_R18, 0xFF); //AOR + rk610_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM + + rk610_codec_write(codec,ACCELCODEC_R1F, 0xDF); + mdelay(10); + rk610_codec_write(codec,ACCELCODEC_R1F, 0x5F); + rk610_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM + rk610_codec_write(codec,ACCELCODEC_R15, 0xC1);//rk610_codec_write(codec,ACCELCODEC_R15, 0xCD);//by Vincent Hsiung + rk610_codec_write(codec,ACCELCODEC_R1A, 0x1C); + mdelay(100); + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09); + rk610_codec_write(codec,ACCELCODEC_R1E, 0x00); + mdelay(10); + rk610_codec_write(codec,ACCELCODEC_R1A, 0x14); + rk610_codec_write(codec,ACCELCODEC_R1D, 0xFE); + rk610_codec_write(codec,ACCELCODEC_R17, 0xBF); //AOL + rk610_codec_write(codec,ACCELCODEC_R18, 0xBF); //AOR + rk610_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM + rk610_codec_write(codec,ACCELCODEC_R1F, 0xDF); + + //2soft mute + rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute + + //2set default SR and clk + rk610_codec_write(codec,ACCELCODEC_R0A, ASC_USB_MODE|FREQ48kHz|ASC_CLKNODIV|ASC_CLK_DISABLE); + gR0AReg = ASC_USB_MODE|FREQ48kHz|ASC_CLKNODIV|ASC_CLK_DISABLE; + //2Config audio interface + rk610_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_MASTER_MODE|ASC_NORMAL_BCLK); + rk610_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_DISABLE|ASC_SCRAMBLE_ENABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_8); //BCLK div 8 + //2volume,input,outpu + rk610_codec_write(codec,ACCELCODEC_R05, 0x0e); + rk610_codec_write(codec,ACCELCODEC_R06, 0x42); + rk610_codec_write(codec,ACCELCODEC_R07, 0x0e); + rk610_codec_write(codec,ACCELCODEC_R08, 0x42); + + rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB|ASC_INPUT_MUTE); //LIL + rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB); //LIR + rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|ASC_INPUT_VOL_0DB); //MIC + rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB); //mic input and boost 20dB + rk610_codec_write(codec,ACCELCODEC_R13, ASC_LPGAMX_DISABLE|ASC_ALMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0); + rk610_codec_write(codec,ACCELCODEC_R14, ASC_RPGAMX_DISABLE|ASC_ARMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0); + gR1314Reg = ASC_RPGAMX_DISABLE|ASC_ARMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0; + + //2other + rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00 + gR0BReg = ASC_DEC_DISABLE|ASC_INT_DISABLE; + rk610_codec_write(codec,ACCELCODEC_R15, \ + 0x01|ASC_RLPFMX_DISABLE|ASC_LLPFMX_DISABLE|ASC_LDAMX_DISABLE|ASC_RDAMX_DISABLE|ASC_LSCF_ACTIVE|ASC_RSCF_ACTIVE); //0x3c + rk610_codec_write(codec,ACCELCODEC_R1B, 0x32); + rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); ///0x00); //use default value + + ///dac mode + rk610_codec_write(codec,ACCELCODEC_R17, 0xBF); //AOL ÒôÁ¿×îµÍ + rk610_codec_write(codec,ACCELCODEC_R18, 0xBF); //AOR + + //2power down useless module + rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a|ASC_PDSDL_ENABLE|ASC_PDBSTL_ENABLE|ASC_PDPGAL_ENABLE); //setup Vmid and Vref, other module power down + rk610_codec_write(codec,ACCELCODEC_R1E, 0x40|ASC_PDASDML_ENABLE); + #if OUT_CAPLESS + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE); + #else + rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); + #endif + + //2other + rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); + gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE; //ASC_DEC_DISABLE|ASC_INT_ENABLE; + rk610_codec_write(codec,ACCELCODEC_R15, 0xC1);//rk610_codec_write(codec,ACCELCODEC_R15, 0xCD);//by Vincent Hsiung + rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB); //LIL + rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB); //LIR + rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|ASC_INPUT_VOL_0DB); //MIC +// rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB); //mic input and boost 20dB + rk610_codec_write(codec,ACCELCODEC_R12, 0x4c); //line input and boost 20dB + rk610_codec_write(codec,ACCELCODEC_R13, 0x00); + rk610_codec_write(codec,ACCELCODEC_R14, 0x00); + gR1314Reg = 0x00; + rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); //0x00); //use default value +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk610_codec_probe(struct snd_soc_codec *codec) +{ + struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + int ret; + + rk610_codec_codec = codec; + printk(KERN_ERR "[%s] start\n", __FUNCTION__); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, rk610_codec->control_type); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + //For RK610, i2c write&read method is special, do not use system default method. + codec->write = rk610_codec_write; + codec->read = rk610_codec_read; + codec->hw_write = (hw_write_t)i2c_master_send; +#else +static int rk610_codec_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; +#endif + if (rk610_codec_codec == NULL) { + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + dev_err(codec->dev, "Codec device not registered\n"); + #else + dev_err(&pdev->dev, "Codec device not registered\n"); + #endif + return -ENODEV; + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) + socdev->card->codec = rk610_codec_codec; + codec = rk610_codec_codec; + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(codec->dev, "failed to create pcms: %d\n", ret); + goto pcm_err; + } +#endif + + snd_soc_add_controls(codec, rk610_codec_snd_controls, + ARRAY_SIZE(rk610_codec_snd_controls)); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) + snd_soc_dapm_new_controls(codec, rk610_codec_dapm_widgets, + ARRAY_SIZE(rk610_codec_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_new_widgets(codec); + + ret = snd_soc_init_card(socdev); + if (ret < 0) { + dev_err(codec->dev, "failed to register card: %d\n", ret); + goto card_err; + } +#else + snd_soc_dapm_new_controls(dapm, rk610_codec_dapm_widgets, + ARRAY_SIZE(rk610_codec_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + +#endif + +#if defined(RK610_SPK_CTRL_PIN) + ret = gpio_request(RK610_SPK_CTRL_PIN, "rk610 spk_ctrl"); + if (ret){ + printk("rk610_control request gpio fail\n"); + //goto err1; + } + gpio_set_value(RK610_SPK_CTRL_PIN, GPIO_HIGH); + gpio_direction_output(RK610_SPK_CTRL_PIN, GPIO_HIGH); +#endif + + rk610_control_init_codec(); + + rk610_codec_reg_set(); + rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return ret; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + return ret; +#endif +} + +/* power down chip */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk610_codec_remove(struct snd_soc_codec *codec) +{ + rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} +#else +static int rk610_codec_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + printk("rk610_codec_remove\n"); + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + return 0; +} +#endif + +static struct snd_soc_codec_driver soc_codec_dev_rk610_codec = { + .probe = rk610_codec_probe, + .remove = rk610_codec_remove, + .suspend = rk610_codec_suspend, + .resume = rk610_codec_resume, + .set_bias_level = rk610_codec_set_bias_level, +// .volatile_register = wm8900_volatile_register, + .reg_cache_size = ARRAY_SIZE(rk610_codec_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = rk610_codec_reg, + .dapm_widgets = rk610_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk610_codec_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), +}; + +EXPORT_SYMBOL_GPL(soc_codec_dev_rk610_codec); + + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static int rk610_codec_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rk610_codec_priv *rk610_codec; + int ret; + printk("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %s start $$$$$$$$$$$$$$$$$$$$$$$$$$$\n", __FUNCTION__); + rk610_codec = kzalloc(sizeof(struct rk610_codec_priv), GFP_KERNEL); + if (rk610_codec == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rk610_codec); + rk610_codec->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_rk610_codec, &rk610_codec_dai, 1); + if (ret < 0) { + printk("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %s: snd_soc_register_codec error!!!!\n", __FUNCTION__); + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); + kfree(rk610_codec); + } + return ret; +} + + +static int rk610_codec_i2c_remove(struct i2c_client *client) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); +#else + struct rk610_codec_priv *rk610_codec = i2c_get_clientdata(client); + rk610_codec_unregister(rk610_codec); +#endif + return 0; +} + +#ifdef CONFIG_PM +static int rk610_codec_i2c_suspend(struct i2c_client *client, pm_message_t msg) +{ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + return 0; + #else + return snd_soc_suspend_device(&client->dev); + #endif +} + +static int rk610_codec_i2c_resume(struct i2c_client *client) +{ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + return 0; + #else + return snd_soc_resume_device(&client->dev); + #endif +} +#else +#define rk610_codec_i2c_suspend NULL +#define rk610_codec_i2c_resume NULL +#endif + +static const struct i2c_device_id rk610_codec_i2c_id[] = { + { "rk610_i2c_codec", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rk610_codec_i2c_id); + +/* corgi i2c codec control layer */ +static struct i2c_driver rk610_codec_i2c_driver = { + .driver = { + .name = "RK610_CODEC", + .owner = THIS_MODULE, + }, + .probe = rk610_codec_i2c_probe, + .remove = rk610_codec_i2c_remove, + //.suspend = rk610_codec_i2c_suspend, + //.resume = rk610_codec_i2c_resume, + .id_table = rk610_codec_i2c_id, +}; +#endif + +static int __init rk610_codec_modinit(void) +{ + int ret; +// DBG("[%s] start\n", __FUNCTION__); + ret = i2c_add_driver(&rk610_codec_i2c_driver); + if (ret != 0) + pr_err("rk610 codec: Unable to register I2C driver: %d\n", ret); + return ret; +} +module_init(rk610_codec_modinit); + +static void __exit rk610_codec_exit(void) +{ + i2c_del_driver(&rk610_codec_i2c_driver); +} +module_exit(rk610_codec_exit); + +MODULE_DESCRIPTION("ASoC RK610 CODEC driver"); +MODULE_AUTHOR("rk@rock-chips.com"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rk610_codec.h b/sound/soc/codecs/rk610_codec.h new file mode 100644 index 000000000000..1e31047c4688 --- /dev/null +++ b/sound/soc/codecs/rk610_codec.h @@ -0,0 +1,267 @@ +/* + * + * Copyright (C) 2009 rockchip lhh + * + * Based on WM8750.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 _RK610_CODEC_H +#define _RK610_CODEC_H + +/* RK610 register space */ + +#define ACCELCODEC_R00 0x00 //ADC High Pass Filter / DSM +#define ACCELCODEC_R01 0x01 //DITHER power +#define ACCELCODEC_R02 0x02 //DITHER power +#define ACCELCODEC_R03 0x03 //DITHER power +#define ACCELCODEC_R04 0x04 //Soft mute / sidetone gain control +#define ACCELCODEC_R05 0x05 //Right interpolate filter volume control (MSB) +#define ACCELCODEC_R06 0x06 //Right interpolate filter volume control (LSB) +#define ACCELCODEC_R07 0x07 //Left interpolate filter volume control (MSB) +#define ACCELCODEC_R08 0x08 //Left interpolate filter volume control (LSB) +#define ACCELCODEC_R09 0x09 //Audio interface control +#define ACCELCODEC_R0A 0x0A //Sample Rate / CLK control +#define ACCELCODEC_R0B 0x0B //Decimation filter / Interpolate filter enable +#define ACCELCODEC_R0C 0x0C //LIN volume +#define ACCELCODEC_R0D 0x0D //LIP volume +#define ACCELCODEC_R0E 0x0E //AL volume +//#define ACCELCODEC_R0F 0x0F //RIN volume +//#define ACCELCODEC_R10 0x10 //RIP volume +//#define ACCELCODEC_R11 0x11 //AR volume +#define ACCELCODEC_R12 0x12 //Input volume +#define ACCELCODEC_R13 0x13 //Left out mix +#define ACCELCODEC_R14 0x14 //Right out mix +#define ACCELCODEC_R15 0x15 //LPF out mix / SCF +#define ACCELCODEC_R16 0x16 //SCF control +#define ACCELCODEC_R17 0x17 //LOUT (AOL) volume +#define ACCELCODEC_R18 0x18 //ROUT (AOR) volume +#define ACCELCODEC_R19 0x19 //MONOOUT (AOM) volume +#define ACCELCODEC_R1A 0x1A //MONOOUT / Reference control +#define ACCELCODEC_R1B 0x1B //Bias Current control +#define ACCELCODEC_R1C 0x1C //ADC control +#define ACCELCODEC_R1D 0x1D //Power Mrg 1 +#define ACCELCODEC_R1E 0x1E //Power Mrg 2 +#define ACCELCODEC_R1F 0x1F //Power Mrg 3 + +#define RK610_CACHE_REGNUM 0x1F + +//ACCELCODEC_R00 +#define ASC_HPF_ENABLE (0x1) //high_pass filter +#define ASC_HPF_DISABLE (0x0) + +#define ASC_DSM_MODE_ENABLE (0x1 << 1) +#define ASC_DSM_MODE_DISABLE (0x0 << 1) + +#define ASC_SCRAMBLE_ENABLE (0x1 << 2) +#define ASC_SCRAMBLE_DISABLE (0x0 << 2) + +#define ASC_DITHER_ENABLE (0x1 << 3) +#define ASC_DITHER_DISABLE (0x0 << 3) + +#define ASC_BCLKDIV_4 (0x1 << 4) +#define ASC_BCLKDIV_8 (0x2 << 4) +#define ASC_BCLKDIV_16 (0x3 << 4) + +//ACCECODEC_R04 +#define ASC_INT_MUTE_L (0x1) +#define ASC_INT_ACTIVE_L (0x0) +#define ASC_INT_MUTE_R (0x1 << 1) +#define ASC_INT_ACTIVE_R (0x0 << 1) + +#define ASC_SIDETONE_L_OFF (0x0 << 2) +#define ASC_SIDETONE_L_GAIN_MAX (0x1 << 2) +#define ASC_SIDETONE_R_OFF (0x0 << 5) +#define ASC_SIDETONE_R_GAIN_MAX (0x1 << 5) + + +//ACCELCODEC_R05 +#define ASC_INT_VOL_0DB (0x0) + + +//ACCELCODEC_R09 +#define ASC_DSP_MODE (0x3) +#define ASC_I2S_MODE (0x2) +#define ASC_LEFT_MODE (0x1) +//#define ASC_RIGHT_MODE (0x0) + +#define ASC_32BIT_MODE (0x3 << 2) +#define ASC_24BIT_MODE (0x2 << 2) +#define ASC_20BIT_MODE (0x1 << 2) +#define ASC_16BIT_MODE (0x0 << 2) + +#define ASC_INVERT_LRCLK (0x1 << 4) +#define ASC_NORMAL_LRCLK (0x0 << 4) + +#define ASC_LRSWAP_ENABLE (0x1 << 5) +#define ASC_LRSWAP_DISABLE (0x0 << 5) + +#define ASC_MASTER_MODE (0x1 << 6) +#define ASC_SLAVE_MODE (0x0 << 6) + +#define ASC_INVERT_BCLK (0x1 << 7) +#define ASC_NORMAL_BCLK (0x0 << 7) + +//ACCELCODEC_R0A +#define ASC_USB_MODE (0x1) +#define ASC_NORMAL_MODE (0x0) + +#define FREQ96kHz (0x0e << 1) +#define FREQ48kHz (0x00 << 1) +#define FREQ441kHz (0x11 << 1) +#define FREQ32kHz (0x0c << 1) +#define FREQ24kHz (0x1c << 1) +#define FREQ2205kHz (0x1B << 1) +#define FREQ16kHz (0x0a << 1) +#define FREQ12kHz (0x08 << 1) +#define FREQ11025kHz (0x19 << 1) +//#define FREQ9k6Hz 0x09 +#define FREQ8kHz (0x06<<1) + +#define ASC_CLKDIV2 (0x1 << 6) +#define ASC_CLKNODIV (0x0 << 6) + +#define ASC_CLK_ENABLE (0x1 << 7) +#define ASC_CLK_DISABLE (0x0 << 7) + +//ACCELCODEC_R0B +#define ASC_DEC_ENABLE (0x1) //decimation filter enable +#define ASC_DEC_DISABLE (0x0) +#define ASC_INT_ENABLE (0x1 << 1) //interpolate filter enable +#define ASC_INT_DISABLE (0x0 << 1) + +//Input +#define ASC_INPUT_MUTE (0x1 << 7) +#define ASC_INPUT_ACTIVE (0x0 << 7) +#define ASC_INPUT_VOL_0DB (0x0) + +//ACCELCODEC_R12 +#define ASC_LINE_INPUT (0) +#define ASC_MIC_INPUT (1 << 7) + +#define ASC_MIC_BOOST_0DB (0) +#define ASC_MIC_BOOST_20DB (1 << 5) + +//ACCELCODEC_R13 +#define ASC_LPGAMXVOL_0DB (0x5) +#define ASC_LPGAMX_ENABLE (0x1 << 3) //the left channel PGA output is directly fed into the left mixer +#define ASC_LPGAMX_DISABLE (0x0 << 3) +#define ASC_ALMXVOL_0DB (0x5 << 4) +#define ASC_ALMX_ENABLE (0x1 << 7) //the left second line input is directly fed into the left mixer +#define ASC_ALMX_DISABLE (0x0 << 7) + +//ACCELCODEC_R14 +#define ASC_RPGAMXVOL_0DB (0x5) +#define ASC_RPGAMX_ENABLE (0x1 << 3) //the right channel PGA output is directly fed into the right mixer +#define ASC_RPGAMX_DISABLE (0x0 << 3) +#define ASC_ARMXVOL_0DB (0x5 << 4) +#define ASC_ARMX_ENABLE (0x1 << 7) //)the right second line input is directly fed into the right mixer +#define ASC_ARMX_DISABLE (0x0 << 7) + +//ACCELCODEC_R15 +#define ASC_LDAMX_ENABLE (0x1 << 2) //the left differential signal from DAC is directly fed into the left mixer +#define ASC_LDAMX_DISABLE (0x0 << 2) +#define ASC_RDAMX_ENABLE (0x1 << 3) //the right differential signal from DAC is directly fed into the right mixer +#define ASC_RDAMX_DISABLE (0x0 << 3) +#define ASC_LSCF_MUTE (0x1 << 4) //the left channel LPF is mute +#define ASC_LSCF_ACTIVE (0x0 << 4) +#define ASC_RSCF_MUTE (0x1 << 5) //the right channel LPF is mute +#define ASC_RSCF_ACTIVE (0x0 << 5) +#define ASC_LLPFMX_ENABLE (0x1 << 6) //the left channel LPF output is fed into the left into the mixer +#define ASC_LLPFMX_DISABLE (0x0 << 6) +#define ASC_RLPFMX_ENABLE (0x1 << 7) //the right channel LPF output is fed into the right into the mixer. +#define ASC_RLPFMX_DISABLE (0x0 << 7) + +//ACCELCODEC_R17/R18 +#define ASC_OUTPUT_MUTE (0x1 << 6) +#define ASC_OUTPUT_ACTIVE (0x0 << 6) +#define ASC_CROSSZERO_EN (0x1 << 7) +#define ASC_OUTPUT_VOL_0DB (0x0F) +//ACCELCODEC_R19 +#define ASC_MONO_OUTPUT_MUTE (0x1 << 7) +#define ASC_MONO_OUTPUT_ACTIVE (0x0 << 7) +#define ASC_MONO_CROSSZERO_EN (0x1 << 6) + +//ACCELCODEC_R1A +#define ASC_VMDSCL_SLOWEST (0x0 << 2) +#define ASC_VMDSCL_SLOW (0x1 << 2) +#define ASC_VMDSCL_FAST (0x2 << 2) +#define ASC_VMDSCL_FASTEST (0x3 << 2) + +#define ASC_MICBIAS_09 (0x1 << 4) +#define ASC_MICBIAS_06 (0x0 << 4) + +#define ASC_L2M_ENABLE (0x1 << 5) //the right channel LPF output is fed to mono PA +#define ASC_L2M_DISABLE (0x0 << 5) +#define ASC_R2M_ENABLE (0x1 << 6) //the left channel LPF output is fed to mono PA +#define ASC_R2M_DISABLE (0x0 << 6) +#define ASC_CAPLESS_ENABLE (0x1 << 7) //the capless connection is enable +#define ASC_CAPLESS_DISABLE (0x0 << 7) + +//ACCELCODEC_R1C +#define ASC_DITH_0_DIV (0x0 << 3) //the amplitude setting of the ASDM dither(div=vdd/48) +#define ASC_DITH_2_DIV (0x1 << 3) +#define ASC_DITH_4_DIV (0x2 << 3) +#define ASC_DITH_8_DIV (0x3 << 3) + +#define ASC_DITH_ENABLE (0x1 << 5) //the ASDM dither is enabled +#define ASC_DITH_DISABLE (0x0 << 5) + +#define ASC_DEM_ENABLE (0x1 << 7) //the ASDM DEM is enabled +#define ASC_DEM_DISABLE (0x0 << 7) + +//ACCELCODEC_R1D +#define ASC_PDVMID_ENABLE (0x1) //the VMID reference is powered down. VMID is connected to GND +#define ASC_PDVMID_DISABLE (0x0) +#define ASC_PDSDL_ENABLE (0x1 << 2) //the PGA S2D buffer is power down +#define ASC_PDSDL_DISABLE (0x0 << 2) +#define ASC_PDBSTL_ENABLE (0x1 << 4) //the micphone input Op-Amp is power down +#define ASC_PDBSTL_DISABLE (0x0 << 4) +#define ASC_PDPGAL_ENABLE (0x1 << 6) //the PGA is power down +#define ASC_PDPGAL_DISABLE (0x0 << 6) +#define ASC_PDREF_ENABLE (0x1 << 7) //reference generator is power down +#define ASC_PDREF_DISABLE (0x0 << 7) + +//ACCELCODEC_R1E +#define ASC_PDPAR_ENABLE (0x1) //the right channel PA is power down +#define ASC_PDPAR_DISABLE (0x0) +#define ASC_PDPAL_ENABLE (0x1 << 1) //the left channel power amplifier is power down +#define ASC_PDPAL_DISABLE (0x0 << 1) +#define ASC_PDMIXR_ENABLE (0x1 << 2) //the right mixer is power down +#define ASC_PDMIXR_DISABLE (0x0 << 2) +#define ASC_PDMIXL_ENABLE (0x1 << 3) //the left mixer is power down +#define ASC_PDMIXL_DISABLE (0x0 << 3) +#define ASC_PDLPFR_ENABLE (0x1 << 4) //the right RC LPF is power down +#define ASC_PDLPFR_DISABLE (0x0 << 4) +#define ASC_PDLPFL_ENABLE (0x1 << 5) //the left channel RC LPF is power down +#define ASC_PDLPFL_DISABLE (0x0 << 5) +#define ASC_PDASDML_ENABLE (0x1 << 7) //the ASDM is power down +#define ASC_PDASDML_DISABLE (0x0 << 7) + +//ACCELCODEC_R1F +#define ASC_PDSCFR_ENABLE (0x1 << 1) //the right channel DAC is power down +#define ASC_PDSCFR_DISABLE (0x0 << 1) +#define ASC_PDSCFL_ENABLE (0x1 << 2) //the left channel DAC is power down +#define ASC_PDSCFL_DISABLE (0x0 << 2) +#define ASC_PDMICB_ENABLE (0x1 << 4) //the micbias is power down +#define ASC_PDMICB_DISABLE (0x0 << 4) +#define ASC_PDIB_ENABLE (0x1 << 5) //the left channel LPF is power down +#define ASC_PDIB_DISABLE (0x0 << 5) +#define ASC_PDMIXM_ENABLE (0x1 << 6) //the mon mixer is power down +#define ASC_PDMIXM_DISABLE (0x0 << 6) +#define ASC_PDPAM_ENABLE (0x1 << 7) //the mono PA is power down. +#define ASC_PDPAM_DISABLE (0x0 << 7) + +#define LINE_2_MIXER_GAIN (0x5) //left and right PA gain +#define RK610_CODEC_NUM_REG 0x20 + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) +extern struct snd_soc_dai rk610_codec_dai; +extern struct snd_soc_codec_device soc_codec_dev_rk610_codec; +#endif + +#endif diff --git a/sound/soc/rk29/Kconfig b/sound/soc/rk29/Kconfig index 98169399de09..fcfb95479a21 100755 --- a/sound/soc/rk29/Kconfig +++ b/sound/soc/rk29/Kconfig @@ -42,6 +42,12 @@ choice endchoice endif +config SND_RK29_SOC_SPDIF + bool "Soc RK29 SPDIF support" + depends on SND_RK29_SOC + depends on SND_RK29_SOC_I2S + help + This supports the use of SPDIF interface on rk29 processors config SND_RK29_SOC_WM8988 tristate "SoC I2S Audio support for rockchip - WM8988" depends on SND_RK29_SOC @@ -136,8 +142,23 @@ config SND_RK29_SOC_RK1000 help Say Y if you want to add support for SoC audio on rockchip with the RK1000. +config SND_RK29_SOC_HDMI + tristate "SoC I2S Audio support for rockchip - HDMI" + depends on SND_RK29_SOC && HDMI_ITV + select SND_RK29_SOC_I2S + help + Say Y if you want to add support for SoC audio on rockchip + with the HDMI. +config SND_RK29_SOC_RK610 + tristate "SoC I2S Audio support for rockchip - RK610" + depends on SND_RK29_SOC && MFD_RK610 && I2C_RK29 + select SND_RK29_SOC_I2S + select SND_SOC_RK610 + help + Say Y if you want to add support for SoC audio on rockchip + with the RK610(JETTA). -if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_RT5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 || SND_RK29_SOC_AIC3111 +if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_RT5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 || SND_RK29_SOC_AIC3111 || SND_RK29_SOC_HDMI || SND_RK29_SOC_RK610 choice bool "Set i2s type" default SND_RK29_CODEC_SOC_SLAVE diff --git a/sound/soc/rk29/Makefile b/sound/soc/rk29/Makefile index 06bed425d071..81759578ebfb 100644 --- a/sound/soc/rk29/Makefile +++ b/sound/soc/rk29/Makefile @@ -6,9 +6,11 @@ endif ifdef CONFIG_ARCH_RK30 snd-soc-rockchip-i2s-objs := rk30_i2s.o endif +snd-soc-rockchip-spdif-objs := rk29_spdif.o obj-$(CONFIG_SND_RK29_SOC) += snd-soc-rockchip.o obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o +obj-$(CONFIG_SND_RK29_SOC_SPDIF) += snd-soc-rockchip-spdif.o # ROCKCHIP Machine Support snd-soc-wm8900-objs := rk29_wm8900.o @@ -20,6 +22,8 @@ snd-soc-aic3111-objs := rk29_aic3111.o snd-soc-wm8988-objs := rk29_wm8988.o snd-soc-rk1000-objs := rk29_rk1000codec.o snd-soc-wm8994-objs := rk29_wm8994.o +snd-soc-hdmi-objs := rk29_hdmi.o +snd-soc-rk610-objs := rk29_jetta_codec.o obj-$(CONFIG_SND_RK29_SOC_WM8994) += snd-soc-wm8994.o obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o @@ -30,3 +34,5 @@ obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o obj-$(CONFIG_SND_RK29_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_RK29_SOC_AIC3111) += snd-soc-aic3111.o +obj-$(CONFIG_SND_RK29_SOC_HDMI) += snd-soc-hdmi.o +obj-$(CONFIG_SND_RK29_SOC_RK610) += snd-soc-rk610.o \ No newline at end of file diff --git a/sound/soc/rk29/rk29_jetta_codec.c b/sound/soc/rk29/rk29_jetta_codec.c new file mode 100644 index 000000000000..c657f7a2124d --- /dev/null +++ b/sound/soc/rk29/rk29_jetta_codec.c @@ -0,0 +1,280 @@ +/* + * rk29_wm8988.c -- SoC audio for rockchip + * + * Driver for rockchip wm8988 audio + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/rk610_codec.h" +#include "rk29_pcm.h" +#include "rk29_i2s.h" + +#if 0 +#define DBG(x...) printk(KERN_ERR x) +#else +#define DBG(x...) +#endif + +static int rk29_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +#else + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +#endif + int ret; + unsigned int pll_out = 0; + int div_bclk,div_mclk; +// struct clk *general_pll; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + #else + ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent + #endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + /* set codec DAI configuration */ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #else + ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #endif + #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #else + ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + #endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + #else + ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + #endif + #endif + #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #else + ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #endif + if (ret < 0) + return ret; + } + + switch(params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 32000: + case 48000: + case 96000: + pll_out = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + pll_out = 11289600; + break; + case 176400: + pll_out = 11289600*2; + break; + case 192000: + pll_out = 12288000*2; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + break; + } + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + +// #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) +// snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); +// #endif + #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) + div_bclk = 63; + div_mclk = pll_out/(params_rate(params)*64) - 1; + + DBG("func is%s,pll_out=%ld,div_mclk=%ld div_bclk=%ld\n", + __FUNCTION__,pll_out,div_mclk, div_bclk); + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); +// DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + #endif + return 0; +} + +static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]= { + + {"Audio Out", NULL, "LOUT1"}, + {"Audio Out", NULL, "ROUT1"}, + {"Line in", NULL, "RINPUT1"}, + {"Line in", NULL, "LINPUT1"}, +// {"Micn", NULL, "RINPUT2"}, +// {"Micp", NULL, "LINPUT2"}, +}; + +/* + * Logic for a RK610 codec as connected on a rockchip board. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk29_RK610_codec_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, + ARRAY_SIZE(rk29_dapm_widgets)); + + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_sync(dapm); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + return 0; +} +#else +static int rk29_RK610_codec_init(struct snd_soc_codec *codec) { +// struct snd_soc_dai *codec_dai = &codec->dai[0]; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + +// ret = snd_soc_dai_set_sysclk(codec_dai, 0, +// 11289600, SND_SOC_CLOCK_IN); +// if (ret < 0) { +// printk(KERN_ERR "Failed to set WM8988 SYSCLK: %d\n", ret); +// return ret; +// } + + /* Add specific widgets */ + snd_soc_dapm_new_controls(codec, rk29_dapm_widgets, + ARRAY_SIZE(rk29_dapm_widgets)); + + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(codec); + + return 0; +} +#endif +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "RK610", + .stream_name = "RK610 CODEC PCM", + .codec_name = "RK610_CODEC.1-0060", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) + .cpu_dai_name = "rk29_i2s.0", +#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) + .cpu_dai_name = "rk29_i2s.1", +#endif + .codec_dai_name = "rk610_codec_xx", + .init = rk29_RK610_codec_init, + .ops = &rk29_ops, +}; +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK29_RK610", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + printk(KERN_ERR "[%s] start\n", __FUNCTION__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("[%s] platform device allocation failed\n", __FUNCTION__); + ret = -ENOMEM; + return ret; + } + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + #else + platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata); + rk29_snd_devdata.dev = &rk29_snd_device->dev; + #endif + ret = platform_device_add(rk29_snd_device); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL");