Device-Tree bindings for rockchip hdmi driver
Required properties:
-- compatible: value should be "rockchip,rk3288-hdmi".
+- compatible: value should be following value:
+ "rockchip,rk3288-hdmi",
+ "rockchip,rk3368-hdmi",
+ "rockchip,rk3036-hdmi",
+ "rockchip,rk312x-hdmi",
- reg: physical base address of the hdmi and length of memory mapped
region.
- interrupts: interrupt number to the cpu.
clock-names property.
- clocks-names: list of clock names sorted in the same order as the clocks
property. Must contain "pclk_hdmi" and "hdcp_clk_hdmi".
-- rockchips,hdmi_audio_source: hdmi audio source that is described as follow
+- rockchip,hdmi_audio_source: hdmi audio source that is described as follow
<0>: hdmi audio source from the I2S interface
<1>: hdmi audio source from the SPDIF interface
-
+- rockchip,hdmi_video_source: hdmi video source that is described as follow
+ <DISPLAY_SOURCE_LCDC0> hdmi video source from LCDC0/VOP0
+ <DISPLAY_SOURCE_LCDC1> hdmi video source from LCDC1/VOP1
+- rockchip,hdcp_enable: hdmi hdcp function is described as follow
+ <0>: hdcp function is disabled.
+ <1>: hdcp function is enabled.
+- rockchip,cec_enable: hdmi cec function is described as follow
+ <0>: cec function is disabled.
+ <1>: cec function is enabled.
Example:
hdmi: hdmi@ff980000 {
pinctrl-1 = <&i2c5_gpio>;
clocks = <&clk_gates16 9>, <&clk_gates5 12>;
clock-names = "pclk_hdmi", "hdcp_clk_hdmi";
- rockchips,hdmi_audio_source = <0>;
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC0>;
+ rockchip,hdmi_audio_source = <0>;
+ rockchip,hdcp_enable = <0>;
+ rockchip,cec_enable = <0>;
};
pinctrl-1 = <&hdmi_gpio>;
clocks = <&clk_gates3 8>, <&pd_hdmi>;
clock-names = "pclk_hdmi", "pd_hdmi";
+ rockchip,hdcp_enable = <0>;
+ rockchip,cec_enable = <0>;
status = "disabled";
};
&hdmi {
status = "okay";
- rockchips,hdmi_audio_source = <0>;
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
};
&adc {
&hdmi {
status = "okay";
- rockchips,hdmi_audio_source = <0>;
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
};
&adc {
&hdmi {
status = "okay";
- rockchips,hdmi_audio_source = <0>;
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
};
&adc {
&hdmi {
status = "okay";
- rockchips,hdmi_audio_source = <0>;
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
};
&adc {
pinctrl-1 = <&i2c5_gpio>;
clocks = <&clk_gates16 9>, <&clk_gates5 12>, <&clk_gates5 11>;
clock-names = "pclk_hdmi", "hdcp_clk_hdmi", "cec_clk_hdmi";
+ rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC0>;
+ rockchip,hdmi_audio_source = <0>;
+ rockchip,hdcp_enable = <0>;
+ rockchip,cec_enable = <0>;
status = "disabled";
};
#include <linux/kdev_t.h>
#include <linux/display-sys.h>
-static struct list_head display_device_list;
+static struct list_head main_display_device_list;
+static struct list_head aux_display_device_list;
static ssize_t display_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
}
+static ssize_t display_show_property(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", dsp->property);
+}
+
static ssize_t display_show_enable(struct device *dev,
struct device_attribute *attr, char *buf)
{
{
char v = 'p';
+ if (mode->xres == 0 && mode->yres == 0)
+ return snprintf(&buf[offset], PAGE_SIZE - offset, "auto\n");
/*
if (mode->flag & FB_MODE_IS_DETAILED)
m = 'D';
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);
+ if (mode->flag)
+ return snprintf(&buf[offset], PAGE_SIZE - offset,
+ "%dx%d%c-%d(YCbCr420)\n",
+ mode->xres, mode->yres, v, mode->refresh);
+ else
+ 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;
+ struct display_modelist *display_modelist;
const struct fb_videomode *mode;
int i;
return 0;
}
i = 0;
+ if (dsp->priority == DISPLAY_PRIORITY_HDMI)
+ i += snprintf(buf, PAGE_SIZE, "auto\n");
+
list_for_each(pos, modelist) {
- fb_modelist = list_entry(pos, struct fb_modelist, list);
- mode = &fb_modelist->mode;
+ display_modelist = list_entry(pos,
+ struct display_modelist,
+ list);
+ mode = &display_modelist->mode;
i += mode_string(buf, i, mode);
}
return i;
struct rk_display_device *dsp = dev_get_drvdata(dev);
char mstr[100];
struct list_head *modelist, *pos;
- struct fb_modelist *fb_modelist;
+ struct display_modelist *display_modelist;
struct fb_videomode *mode;
size_t i;
+ if (!memcmp(buf, "auto", 4)) {
+ if (dsp->ops && dsp->ops->setmode)
+ dsp->ops->setmode(dsp, NULL);
+ return count;
+ }
+
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;
+ display_modelist = list_entry(pos,
+ struct display_modelist,
+ list);
+ mode = &display_modelist->mode;
i = mode_string(mstr, 0, mode);
if (strncmp(mstr, buf, max(count, i)) == 0) {
if (dsp->ops && dsp->ops->setmode)
return -EINVAL;
}
-static ssize_t display_show_debug(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t display_show_3dmode(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+ struct list_head *modelist, *pos;
+ struct display_modelist *display_modelist;
+ struct fb_videomode mode;
+ int i = 0, cur_3d_mode = -1;
+
+ if (dsp->ops && dsp->ops->getmodelist) {
+ if (dsp->ops->getmodelist(dsp, &modelist))
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+
+ if (dsp->ops && dsp->ops->getmode) {
+ if (dsp->ops->getmode(dsp, &mode))
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+
+ list_for_each(pos, modelist) {
+ display_modelist = list_entry(pos,
+ struct display_modelist,
+ list);
+ if (fb_mode_is_equal(&mode, &display_modelist->mode))
+ break;
+ else
+ display_modelist = NULL;
+ }
+ if (display_modelist)
+ i = snprintf(buf, PAGE_SIZE, "3dmodes=%d\n",
+ display_modelist->format_3d);
+ else
+ i = snprintf(buf, PAGE_SIZE, "3dmodes=0\n");
+
+ if (dsp->ops && dsp->ops->get3dmode)
+ cur_3d_mode = dsp->ops->get3dmode(dsp);
+ i += snprintf(buf + i, PAGE_SIZE - i, "cur3dmode=%d", cur_3d_mode);
+ return i;
+}
+
+static ssize_t display_store_3dmode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+ int mode;
+
+ if (dsp->ops && dsp->ops->set3dmode) {
+ if (!kstrtoint(buf, 0, &mode))
+ dsp->ops->set3dmode(dsp, mode);
+ return count;
+ }
return -EINVAL;
}
-static ssize_t display_store_debug(struct device *dev,
+static ssize_t display_show_color(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+
+ if(dsp->ops && dsp->ops->getcolor)
+ return dsp->ops->getcolor(dsp, buf);
+ else
+ return 0;
+}
+
+static ssize_t display_store_color(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- int cmd;
struct rk_display_device *dsp = dev_get_drvdata(dev);
- if (dsp->ops && dsp->ops->setdebug) {
- if (kstrtoint(buf, 0, &cmd) != -1)
- dsp->ops->setdebug(dsp, cmd);
- return count;
+ if(dsp->ops && dsp->ops->setcolor) {
+ if (!dsp->ops->setcolor(dsp, buf, count));
+ return count;
}
return -EINVAL;
}
return -EINVAL;
}
-
-
static ssize_t display_show_monspecs(struct device *dev,
struct device_attribute *attr, char *buf)
{
return -EINVAL;
}
+static ssize_t display_show_debug(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return -EINVAL;
+}
+
+static ssize_t display_store_debug(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int cmd;
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+
+ if(dsp->ops && dsp->ops->setdebug) {
+ if (sscanf(buf, "%d", &cmd) != -1)
+ dsp->ops->setdebug(dsp, cmd);
+ 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, 0664, display_show_enable, display_store_enable),
+ __ATTR(property, S_IRUGO, display_show_property, NULL),
+ __ATTR(enable, 0666, display_show_enable, display_store_enable),
__ATTR(connect, S_IRUGO, display_show_connect, NULL),
__ATTR(modes, S_IRUGO, display_show_modes, NULL),
- __ATTR(mode, 0664, display_show_mode, display_store_mode),
- __ATTR(scale, 0664, display_show_scale, display_store_scale),
- __ATTR(debug, 0664, display_show_debug, display_store_debug),
+ __ATTR(mode, 0666, display_show_mode, display_store_mode),
+ __ATTR(scale, 0666, display_show_scale, display_store_scale),
+ __ATTR(3dmode, 0666, display_show_3dmode, display_store_3dmode),
+ __ATTR(color, 0666, display_show_color, display_store_color),
__ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
__ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
+ __ATTR(debug, 0664, display_show_debug, display_store_debug),
__ATTR_NULL
};
return 0;
};
+int display_add_videomode(const struct fb_videomode *mode,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct display_modelist *modelist;
+ struct fb_videomode *m;
+ int found = 0;
+
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct display_modelist, list);
+ m = &modelist->mode;
+ if (fb_mode_is_equal(m, mode)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ modelist = kmalloc(sizeof(*modelist),
+ GFP_KERNEL);
+
+ if (!modelist)
+ return -ENOMEM;
+ modelist->mode = *mode;
+ list_add(&modelist->list, head);
+ }
+ return 0;
+}
+
void rk_display_device_enable(struct rk_display_device *ddev)
{
struct list_head *pos, *head;
struct rk_display_device *dev_enable = NULL;
int enable = 0, connect;
- head = &display_device_list;
+ if (ddev->property == DISPLAY_MAIN)
+ head = &main_display_device_list;
+ else
+ head = &aux_display_device_list;
+
list_for_each(pos, head) {
dev = list_entry(pos, struct rk_display_device, list);
enable = dev->ops->getenable(dev);
#ifndef CONFIG_DISPLAY_AUTO_SWITCH
return;
#else
- struct list_head *pos, *head = &display_device_list;
+ struct list_head *pos, *head;
struct rk_display_device *dev;
int connect = 0;
+ if (ddev->property == DISPLAY_MAIN)
+ head = &main_display_device_list;
+ else
+ head = &aux_display_device_list;
+
list_for_each_prev(pos, head) {
dev = list_entry(pos, struct rk_display_device, list);
if (dev != ddev) {
#ifndef CONFIG_DISPLAY_AUTO_SWITCH
return;
#else
- struct list_head *pos, *head = &display_device_list;
+ struct list_head *pos, *head;
struct rk_display_device *dev;
int enable = 0;
+ if (ddev->property == DISPLAY_MAIN)
+ head = &main_display_device_list;
+ else
+ head = &aux_display_device_list;
+
list_for_each(pos, head) {
dev = list_entry(pos, struct rk_display_device, list);
if (dev != ddev) {
}
EXPORT_SYMBOL(rk_display_device_disable_other);
-void rk_display_device_select(int priority)
+void rk_display_device_select(int property, int priority)
{
- struct list_head *pos, *head = &display_device_list;
+ struct list_head *pos, *head;
struct rk_display_device *dev;
int enable, found = 0;
+ if (property == DISPLAY_MAIN)
+ head = &main_display_device_list;
+ else
+ head = &aux_display_device_list;
+
list_for_each(pos, head) {
dev = list_entry(pos, struct rk_display_device, list);
if (dev->priority == priority)
mutex_unlock(&allocated_dsp_lock);
if (new_dev->idx >= 0) {
- new_dev->dev = device_create(display_class, parent,
- MKDEV(0, 0), new_dev,
- "%s", new_dev->type);
+ if (new_dev->property == DISPLAY_MAIN)
+ new_dev->dev =
+ device_create(display_class, parent,
+ MKDEV(0, 0), new_dev,
+ "%s", new_dev->type);
+ else
+ new_dev->dev =
+ device_create(display_class, parent,
+ MKDEV(0, 0), new_dev,
+ "display%d.%s",
+ new_dev->property,
+ new_dev->type);
if (!IS_ERR(new_dev->dev)) {
new_dev->parent = parent;
new_dev->driver = driver;
struct list_head *pos, *head;
struct rk_display_device *dev;
- head = &display_device_list;
+ if (new_dev->property == DISPLAY_MAIN)
+ head = &main_display_device_list;
+ else
+ head = &aux_display_device_list;
+
list_for_each(pos, head) {
dev =
list_entry(pos,
display_class->suspend = display_suspend;
display_class->resume = display_resume;
mutex_init(&allocated_dsp_lock);
- INIT_LIST_HEAD(&display_device_list);
+ INIT_LIST_HEAD(&main_display_device_list);
+ INIT_LIST_HEAD(&aux_display_device_list);
return 0;
}
menuconfig RK_HDMI
bool "Rockchip HDMI support"
- depends on FB_ROCKCHIP || DRM_ROCKCHIP
+ depends on FB_ROCKCHIP
select FB_MODE_HELPERS
-if RK_HDMI
-source "drivers/video/rockchip/hdmi/chips/Kconfig"
-endif
+source "drivers/video/rockchip/hdmi/rockchip-hdmiv1/Kconfig"
+source "drivers/video/rockchip/hdmi/rockchip-hdmiv2/Kconfig"
config RK_HDMI_DEBUG
- bool "Rockchip HDMI Debugging"
+ bool "Rockchip HDMI Debugging"
depends on RK_HDMI
default n
- help
- Enableds verbose debugging the the HDMI drivers
+ help
+ Enableds verbose debugging the the HDMI drivers
+
ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-obj-$(CONFIG_RK_HDMI) += rk_hdmi_edid.o rk_hdmi_lcdc.o rk_hdmi_task.o rk_hdmi_sysfs.o rk_hdmi_parse_dt.o
-obj-$(CONFIG_RK_HDMI) += chips/
+obj-$(CONFIG_RK_HDMI) += rockchip-hdmi-core.o rockchip-hdmi-lcdc.o rockchip-hdmi-edid.o rockchip-hdmi-sysfs.o rockchip-hdmi-cec.o
+obj-$(CONFIG_RK_HDMI_V2) += rockchip-hdmiv2/
+obj-$(CONFIG_RK_HDMI_V1) += rockchip-hdmiv1/
+++ /dev/null
-config HDMI_RK30
- bool "RK30 HDMI support"
- depends on LCDC_RK30
- help
- Support rk30 hdmi if you say y here
-
-if HDMI_RK30
-source "drivers/video/rockchip/hdmi/chips/rk30/Kconfig"
-endif
-
-config HDMI_RK2928
- bool "RK2928 HDMI support"
- depends on LCDC_RK2928
- help
- Support rk2928 hdmi if you say y here
-
-if HDMI_RK2928
-source "drivers/video/rockchip/hdmi/chips/rk2928/Kconfig"
-endif
-
-config HDMI_CAT66121
- bool "CAT66121 HDMI support"
- help
- Support cat66121 hdmi if you say y here
-
-if HDMI_CAT66121
-source "drivers/video/rockchip/hdmi/chips/cat66121/Kconfig"
-endif
-
-config HDMI_RK610
- bool "RK610 HDMI support"
- depends on MFD_RK610
- help
- Support rk610 hdmi if you say y here
-
-if HDMI_RK610
-source "drivers/video/rockchip/hdmi/chips/rk610/Kconfig"
-endif
-
-config HDMI_RK616
- bool "RK616 HDMI support"
-depends on MFD_RK616 || ARCH_RK3026
- default y
- help
- Support rk616 hdmi if you say y here
-
-if HDMI_RK616
-source "drivers/video/rockchip/hdmi/chips/rk616/Kconfig"
-endif
-
-config HDMI_RK3288
- bool "RK3288 HDMI support"
- default y
- help
- Support rk3288 hdmi if you say y here
-
-config HDMI_RK3036
- bool "RK3036 HDMI support"
- default y
- help
- Support rk3036 hdmi if you say y here
-
-if HDMI_RK3036
-source "drivers/video/rockchip/hdmi/chips/rk3036/Kconfig"
-endif
-
-choice
- prompt "HDMI Source LCDC select"
-config HDMI_SOURCE_LCDC0
- bool "lcdc0"
-config HDMI_SOURCE_LCDC1
- bool "lcdc1"
-endchoice
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
-
-obj-$(CONFIG_HDMI_RK30) += rk30/
-obj-$(CONFIG_HDMI_RK2928) += rk2928/
-obj-$(CONFIG_HDMI_RK610) += rk610/
-obj-$(CONFIG_HDMI_CAT66121) += cat66121/
-obj-$(CONFIG_HDMI_RK616) += rk616/
-obj-$(CONFIG_HDMI_RK3036) += rk3036/
-obj-$(CONFIG_HDMI_RK3288) += rk3288/
+++ /dev/null
-config SUPPORT_HDCP
- bool "HDCP support"
- depends on HDMI_CAT66121
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-
+++ /dev/null
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-
-obj-$(CONFIG_HDMI_CAT66121) += cat66121_hdmi.o \
- cat66121_hdmi_hw.o \
- hdmitx_input.o \
- hdmitx_drv.o \
- csc.o
-
-obj-$(CONFIG_SUPPORT_HDCP) += hdmitx_hdcp.o \
- sha1.o
-
+++ /dev/null
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/uaccess.h>
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#endif
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-
-#include "cat66121_hdmi.h"
-#include "cat66121_hdmi_hw.h"
-
-#define HDMI_POLL_MDELAY 50//100
-struct cat66121_hdmi_pdata *cat66121_hdmi = NULL;
-struct hdmi *hdmi=NULL;
-
-extern struct rk_lcdc_driver * rk_get_lcdc_drv(char *name);
-extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
-extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
-static void cat66121_irq_work_func(struct work_struct *work);
-#if 0
-int cat66121_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void))
-{
- hdmi->hdcp_cb = hdcp_cb;
- hdmi->hdcp_irq_cb = hdcp_irq_cb;
- hdmi->hdcp_power_on_cb = hdcp_power_on_cb;
- hdmi->hdcp_power_off_cb = hdcp_power_off_cb;
-
- return HDMI_ERROR_SUCESS;
-}
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void hdmi_early_suspend(struct early_suspend *h)
-{
- hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
- flush_delayed_work(&hdmi->delay_work);
- mutex_lock(&hdmi->enable_mutex);
- hdmi->suspend = 1;
- if(!hdmi->enable) {
- mutex_unlock(&hdmi->enable_mutex);
- return;
- }
-
- if(hdmi->irq != INVALID_GPIO)
- disable_irq(hdmi->irq);
-
- mutex_unlock(&hdmi->enable_mutex);
- hdmi->command = HDMI_CONFIG_ENABLE;
- init_completion(&hdmi->complete);
- hdmi->wait = 1;
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
- wait_for_completion_interruptible_timeout(&hdmi->complete,
- msecs_to_jiffies(5000));
- flush_delayed_work(&hdmi->delay_work);
- return;
-}
-
-static void hdmi_early_resume(struct early_suspend *h)
-{
- hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
- mutex_lock(&hdmi->enable_mutex);
-
- hdmi->suspend = 0;
- if(hdmi->irq == INVALID_GPIO){
- queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, HDMI_POLL_MDELAY);
- }else if(hdmi->enable){
- enable_irq(hdmi->irq);
- }
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
- mutex_unlock(&hdmi->enable_mutex);
- return;
-}
-#endif
-
-static void cat66121_irq_work_func(struct work_struct *work)
-{
- if(hdmi->suspend == 0) {
- if(hdmi->enable == 1) {
- cat66121_hdmi_interrupt(hdmi);
- if(hdmi->hdcp_irq_cb)
- hdmi->hdcp_irq_cb(0);
- }
- if(!gpio_is_valid(hdmi->irq)){
- queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, HDMI_POLL_MDELAY);
- }
- }
-}
-
-static irqreturn_t cat66121_thread_interrupt(int irq, void *dev_id)
-{
- cat66121_irq_work_func(NULL);
- msleep(HDMI_POLL_MDELAY);
- hdmi_dbg(hdmi->dev, "%s irq=%d\n", __func__,irq);
- return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-static int hdmi_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; //TODO Daisen
- return 0;
-}
-
-static int hdmi_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; //TODO Daisen
- return 0;
-}
-static int hdmi_reg_show(struct seq_file *s, void *v)
-{
-
- int i;
- char val;
- struct i2c_client *client=cat66121_hdmi->client;
-
- for(i=0;i<256;i++)
- {
- hdmi_read_p0_reg(client, i, &val);
- if(i%16==0)
- seq_printf(s,"\n>>>hdmi_hdmi %x:",i);
- seq_printf(s," %2x",val);
- }
- seq_printf(s,"\n");
-
- return 0;
-}
-
-static ssize_t hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
- struct i2c_client *client=NULL;
- u32 reg,val;
- char kbuf[25];
- client = cat66121_hdmi->client;
-
- if (copy_from_user(kbuf, buf, count))
- return -EFAULT;
- sscanf(kbuf, "%x%x", ®,&val);
- hdmi_write_p0_reg(client, reg, (u8*)&val);
-
- return count;
-}
-
-static int hdmi_reg_open(struct inode *inode, struct file *file)
-{
- return single_open(file,hdmi_reg_show,hdmi);
-}
-
-static const struct file_operations hdmi_reg_fops = {
- .owner = THIS_MODULE,
- .open = hdmi_reg_open,
- .read = seq_read,
- .write = hdmi_reg_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-static int rk_hdmi_drv_init(struct hdmi *hdmi_drv)
-{
- int ret = 0;
- struct rk_screen screen;
-
- rk_fb_get_prmry_screen(&screen);
- if(screen.lcdc_id == 1)
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
- else
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
- if(hdmi_drv->lcdc == NULL)
- {
- dev_err(hdmi_drv->dev, "can not connect to video source lcdc\n");
- ret = -ENXIO;
- return ret;
- }
-
-#ifdef SUPPORT_HDCP
- hdmi_drv->irq = INVALID_GPIO;
-#endif
-
- hdmi_sys_init(hdmi_drv);
- hdmi_drv->xscale = 100;
- hdmi_drv->yscale = 100;
- hdmi_drv->insert = cat66121_hdmi_sys_insert;
- hdmi_drv->remove = cat66121_hdmi_sys_remove;
- hdmi_drv->control_output = cat66121_hdmi_sys_enalbe_output;
- hdmi_drv->config_video = cat66121_hdmi_sys_config_video;
- hdmi_drv->config_audio = cat66121_hdmi_sys_config_audio;
- hdmi_drv->detect_hotplug = cat66121_hdmi_sys_detect_hpd;
- hdmi_drv->read_edid = cat66121_hdmi_sys_read_edid;
-
- #ifdef CONFIG_HAS_EARLYSUSPEND
- hdmi_drv->early_suspend.suspend = hdmi_early_suspend;
- hdmi_drv->early_suspend.resume = hdmi_early_resume;
- hdmi_drv->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
- register_early_suspend(&hdmi_drv->early_suspend);
- #endif
-
- hdmi_register_display_sysfs(hdmi_drv, NULL);
-
- #ifdef CONFIG_SWITCH
- hdmi_drv->switch_hdmi.name="hdmi";
- switch_dev_register(&(hdmi_drv->switch_hdmi));
- #endif
-
- spin_lock_init(&hdmi_drv->irq_lock);
- mutex_init(&hdmi_drv->enable_mutex);
-
- return 0;
-}
-
-#if defined(CONFIG_OF)
-static const struct of_device_id cat66121_dt_ids[] = {
- {.compatible = "ite,cat66121",},
- {}
-};
-MODULE_DEVICE_TABLE(of, cat66121_dt_ids);
-#endif
-
-static int cat66121_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
-{
- int rc = 0;
-
- printk("%s,line=%d\n", __func__,__LINE__);
-
- if (client->dev.of_node) {
- if (!of_match_device(cat66121_dt_ids, &client->dev)) {
- dev_err(&client->dev,"Failed to find matching dt id\n");
- return -EINVAL;
- }
- }
-
- cat66121_hdmi = kzalloc(sizeof(struct cat66121_hdmi_pdata), GFP_KERNEL);
- if(!cat66121_hdmi)
- {
- dev_err(&client->dev, "no memory for state\n");
- return -ENOMEM;
- }
- cat66121_hdmi->client = client;
- i2c_set_clientdata(client, cat66121_hdmi);
-
- hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);
- if(!hdmi)
- {
- dev_err(&client->dev, "cat66121 hdmi kmalloc fail!");
- goto err_kzalloc_hdmi;
- }
- memset(hdmi, 0, sizeof(struct hdmi));
- hdmi->dev = &client->dev;
-
- rk_hdmi_parse_dt(hdmi);
- //power on
- rk_hdmi_pwr_enable(hdmi);
-
- if(cat66121_detect_device()!=1){
- dev_err(hdmi->dev, "can't find it66121 device \n");
- rc = -ENXIO;
- goto err_request_lcdc;
- }
-
- cat66121_hdmi->plug_status = -1;
- rk_hdmi_drv_init(hdmi);
- cat66121_hdmi_sys_init(hdmi);
-
- hdmi->workqueue = create_singlethread_workqueue("hdmi");
- INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
-
- if(gpio_is_valid(hdmi->irq)) {
- //cat66121_irq_work_func(NULL);
- if((rc = gpio_request(hdmi->irq, "hdmi gpio")) < 0)
- {
- dev_err(&client->dev, "fail to request gpio %d\n", hdmi->irq);
- goto err_request_lcdc;
- }
-
- cat66121_hdmi->gpio = hdmi->irq;
- //gpio_pull_updown(hdmi->irq, GPIOPullUp); //TODO Daisen
- gpio_direction_input(hdmi->irq);
- hdmi->irq = gpio_to_irq(hdmi->irq);
- if(hdmi->irq <= 0) {
- dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
- goto err_request_irq;
- }
-
- if((rc = request_threaded_irq(hdmi->irq, NULL ,cat66121_thread_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, dev_name(&client->dev), hdmi)) < 0)
- {
- dev_err(&client->dev, "fail to request hdmi irq\n");
- goto err_request_irq;
- }
- }else{
- cat66121_hdmi->workqueue = create_singlethread_workqueue("cat66121 irq");
- INIT_DELAYED_WORK(&(cat66121_hdmi->delay_work), cat66121_irq_work_func);
- cat66121_irq_work_func(NULL);
- }
-
-#if defined(CONFIG_DEBUG_FS)
- {
- struct dentry *debugfs_dir = debugfs_create_dir("it66121", NULL);
- if (IS_ERR(debugfs_dir))
- {
- dev_err(&client->dev,"failed to create debugfs dir for it66121!\n");
- }
- else
- debugfs_create_file("hdmi", S_IRUSR,debugfs_dir,hdmi,&hdmi_reg_fops);
- }
-#endif
-
- dev_info(&client->dev, "cat66121 hdmi i2c probe ok\n");
-
- return 0;
-
-err_request_irq:
- gpio_free(hdmi->irq);
-err_request_lcdc:
- kfree(hdmi);
- hdmi = NULL;
-err_kzalloc_hdmi:
- kfree(cat66121_hdmi);
- cat66121_hdmi = NULL;
- dev_err(&client->dev, "cat66121 hdmi probe error\n");
- return rc;
-
-}
-
-static int cat66121_hdmi_i2c_remove(struct i2c_client *client)
-{
- hdmi_dbg(hdmi->dev, "%s\n", __func__);
- if(hdmi) {
- mutex_lock(&hdmi->enable_mutex);
- if(!hdmi->suspend && hdmi->enable && hdmi->irq)
- disable_irq(hdmi->irq);
- mutex_unlock(&hdmi->enable_mutex);
- if(hdmi->irq)
- free_irq(hdmi->irq, NULL);
- flush_workqueue(hdmi->workqueue);
- destroy_workqueue(hdmi->workqueue);
- #ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi->switch_hdmi));
- #endif
- hdmi_unregister_display_sysfs(hdmi);
- #ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi->early_suspend);
- #endif
- fb_destroy_modelist(&hdmi->edid.modelist);
- if(hdmi->edid.audio)
- kfree(hdmi->edid.audio);
- if(hdmi->edid.specs)
- {
- if(hdmi->edid.specs->modedb)
- kfree(hdmi->edid.specs->modedb);
- kfree(hdmi->edid.specs);
- }
- kfree(hdmi);
- hdmi = NULL;
- }
- return 0;
-}
-
-static void cat66121_hdmi_i2c_shutdown(struct i2c_client *client)
-{
- if(hdmi) {
- #ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi->early_suspend);
- #endif
- }
- printk(KERN_INFO "cat66121 hdmi shut down.\n");
-}
-
-static const struct i2c_device_id cat66121_hdmi_id[] = {
- { "cat66121_hdmi", 0 },
- { }
-};
-
-static struct i2c_driver cat66121_hdmi_i2c_driver = {
- .driver = {
- .name = "cat66121_hdmi",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(cat66121_dt_ids),
- },
- .probe = cat66121_hdmi_i2c_probe,
- .remove = cat66121_hdmi_i2c_remove,
- .shutdown = cat66121_hdmi_i2c_shutdown,
- .id_table = cat66121_hdmi_id,
-};
-
-static int __init cat66121_hdmi_init(void)
-{
- return i2c_add_driver(&cat66121_hdmi_i2c_driver);
-}
-
-static void __exit cat66121_hdmi_exit(void)
-{
- i2c_del_driver(&cat66121_hdmi_i2c_driver);
-}
-
-//module_init(cat66121_hdmi_init);
-device_initcall_sync(cat66121_hdmi_init);
-module_exit(cat66121_hdmi_exit);
+++ /dev/null
-#ifndef __cat66121_HDMI_H__
-#define __cat66121_HDMI_H__
-#include "../../rk_hdmi.h"
-
-#if defined(CONFIG_HDMI_SOURCE_LCDC1)
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC1
-#else
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC0
-#endif
-
-
-struct cat66121_hdmi_pdata {
- int gpio;
- struct i2c_client *client;
- struct delayed_work delay_work;
- struct workqueue_struct *workqueue;
- int plug_status;
-};
-
-extern struct cat66121_hdmi_pdata *cat66121_hdmi;
-
-extern int cat66121_detect_device(void);
-extern int cat66121_hdmi_sys_init(struct hdmi *hdmi_drv);
-extern void cat66121_hdmi_interrupt(struct hdmi *hdmi_drv);
-extern int cat66121_hdmi_sys_detect_hpd(struct hdmi *hdmi_drv);
-extern int cat66121_hdmi_sys_insert(struct hdmi *hdmi_drv);
-extern int cat66121_hdmi_sys_remove(struct hdmi *hdmi_drv);
-extern int cat66121_hdmi_sys_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff);
-extern int cat66121_hdmi_sys_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara);
-extern int cat66121_hdmi_sys_config_audio(struct hdmi *hdmi_drv,struct hdmi_audio *audio);
-extern void cat66121_hdmi_sys_enalbe_output(struct hdmi *hdmi_drv, int enable);
-extern int cat66121_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-#endif
+++ /dev/null
-#include <linux/delay.h>
-#include "cat66121_hdmi.h"
-#include "cat66121_hdmi_hw.h"
-#include <asm/atomic.h>
-//#include <mach/io.h>
-//#include <mach/gpio.h>
-#include "hdmitx.h"
-
-extern HDMITXDEV hdmiTxDev[HDMITX_MAX_DEV_COUNT] ;
-#define HDMITX_INPUT_SIGNAL_TYPE 0 // for default(Sync Sep Mode)
-#define INPUT_SPDIF_ENABLE 0
-/*******************************
- * Global Data
- ******************************/
-_XDATA unsigned char CommunBuff[128] ;
-static unsigned int pixelrep;
-static BYTE bInputColorMode = INPUT_COLOR_MODE;
-static char bOutputColorMode = F_MODE_RGB444;
-#ifdef SUPPORT_HDCP
-static void hdcp_delay_work_func(struct work_struct *work);
-static DECLARE_DELAYED_WORK(hdcp_delay_work,hdcp_delay_work_func);
-#endif
-static DEFINE_MUTEX(handler_mutex);
-
-HDMITXDEV InstanceData =
-{
-
- 0, // BYTE I2C_DEV ;
- HDMI_TX_I2C_SLAVE_ADDR, // BYTE I2C_ADDR ;
-
- /////////////////////////////////////////////////
- // Interrupt Type
- /////////////////////////////////////////////////
- 0x40, // BYTE bIntType ; // = 0 ;
- /////////////////////////////////////////////////
- // Video Property
- /////////////////////////////////////////////////
- INPUT_SIGNAL_TYPE ,// BYTE bInputVideoSignalType ; // for Sync Embedded,CCIR656,InputDDR
-
- /////////////////////////////////////////////////
- // Audio Property
- /////////////////////////////////////////////////
- I2S_FORMAT, // BYTE bOutputAudioMode ; // = 0 ;
- FALSE , // BYTE bAudioChannelSwap ; // = 0 ;
- 0x01, // BYTE bAudioChannelEnable ;
- INPUT_SAMPLE_FREQ ,// BYTE bAudFs ;
- 0, // unsigned long TMDSClock ;
- FALSE, // BYTE bAuthenticated:1 ;
- FALSE, // BYTE bHDMIMode: 1;
- FALSE, // BYTE bIntPOL:1 ; // 0 = Low Active
- FALSE, // BYTE bHPD:1 ;
-};
-
-/* I2C read/write funcs */
-BYTE HDMITX_ReadI2C_Byte(BYTE RegAddr)
-{
- struct i2c_msg msgs[2];
- SYS_STATUS ret = -1;
- BYTE buf[1];
-
- buf[0] = RegAddr;
-
- /* Write device addr fisrt */
- msgs[0].addr = cat66121_hdmi->client->addr;
- msgs[0].flags = !I2C_M_RD;
- msgs[0].len = 1;
- msgs[0].buf = &buf[0];
- msgs[0].scl_rate= 100*1000;
- /* Then, begin to read data */
- msgs[1].addr = cat66121_hdmi->client->addr;
- msgs[1].flags = I2C_M_RD;
- msgs[1].len = 1;
- msgs[1].buf = &buf[0];
- msgs[1].scl_rate= 100*1000;
-
- ret = i2c_transfer(cat66121_hdmi->client->adapter, msgs, 2);
- if(ret != 2)
- printk("I2C transfer Error! ret = %d\n", ret);
-
- //ErrorF("Reg%02xH: 0x%02x\n", RegAddr, buf[0]);
- return buf[0];
-}
-
-SYS_STATUS HDMITX_WriteI2C_Byte(BYTE RegAddr, BYTE data)
-{
- struct i2c_msg msg;
- SYS_STATUS ret = -1;
- BYTE buf[2];
-
- buf[0] = RegAddr;
- buf[1] = data;
-
- msg.addr = cat66121_hdmi->client->addr;
- msg.flags = !I2C_M_RD;
- msg.len = 2;
- msg.buf = buf;
- msg.scl_rate= 100*1000;
-
- ret = i2c_transfer(cat66121_hdmi->client->adapter, &msg, 1);
- if(ret != 1)
- printk("I2C transfer Error!\n");
-
- return ret;
-}
-
-SYS_STATUS HDMITX_ReadI2C_ByteN(BYTE RegAddr, BYTE *pData, int N)
-{
- struct i2c_msg msgs[2];
- SYS_STATUS ret = -1;
-
- pData[0] = RegAddr;
-
- msgs[0].addr = cat66121_hdmi->client->addr;
- msgs[0].flags = !I2C_M_RD;
- msgs[0].len = 1;
- msgs[0].buf = &pData[0];
- msgs[0].scl_rate= 100*1000;
-
- msgs[1].addr = cat66121_hdmi->client->addr;
- msgs[1].flags = I2C_M_RD;
- msgs[1].len = N;
- msgs[1].buf = pData;
- msgs[1].scl_rate= 100*1000;
-
- ret = i2c_transfer(cat66121_hdmi->client->adapter, msgs, 2);
- if(ret != 2)
- printk("I2C transfer Error! ret = %d\n", ret);
-
- return ret;
-}
-
-SYS_STATUS HDMITX_WriteI2C_ByteN(BYTE RegAddr, BYTE *pData, int N)
-{
- struct i2c_msg msg;
- SYS_STATUS ret = -1;
- BYTE buf[N + 1];
-
- buf[0] = RegAddr;
- memcpy(&buf[1], pData, N);
-
- msg.addr = cat66121_hdmi->client->addr;
- msg.flags = !I2C_M_RD;
- msg.len = N + 1;
- msg.buf = buf; // gModify.Exp."Include RegAddr"
- msg.scl_rate= 100*1000;
-
- ret = i2c_transfer(cat66121_hdmi->client->adapter, &msg, 1);
- if(ret != 1)
- printk("I2C transfer Error! ret = %d\n", ret);
-
- return ret;
-}
-SYS_STATUS HDMITX_SetI2C_Byte(BYTE Reg,BYTE Mask,BYTE Value)
-{
- BYTE Temp;
- if( Mask != 0xFF )
- {
- Temp=HDMITX_ReadI2C_Byte(Reg);
- Temp&=(~Mask);
- Temp|=Value&Mask;
- }
- else
- {
- Temp=Value;
- }
- return HDMITX_WriteI2C_Byte(Reg,Temp);
-}
-
-int cat66121_detect_device(void)
-{
- uint8_t VendorID0, VendorID1, DeviceID0, DeviceID1;
-
- Switch_HDMITX_Bank(0);
- VendorID0 = HDMITX_ReadI2C_Byte(REG_TX_VENDOR_ID0);
- VendorID1 = HDMITX_ReadI2C_Byte(REG_TX_VENDOR_ID1);
- DeviceID0 = HDMITX_ReadI2C_Byte(REG_TX_DEVICE_ID0);
- DeviceID1 = HDMITX_ReadI2C_Byte(REG_TX_DEVICE_ID1);
- printk("CAT66121: Reg[0-3] = 0x[%02x].[%02x].[%02x].[%02x]\n",
- VendorID0, VendorID1, DeviceID0, DeviceID1);
- if( (VendorID0 == 0x54) && (VendorID1 == 0x49))
- // &&(DeviceID0 == 0x12) && (DeviceID1 == 0x16) )
- return 1;
-
- printk("[CAT66121] Device not found!\n");
-
- return 0;
-}
-int cat66121_hdmi_sys_init(struct hdmi *hdmi_drv)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __FUNCTION__);
- HDMITX_InitTxDev(&InstanceData);
- InitHDMITX();
- msleep(1);
- return HDMI_ERROR_SUCESS;
-}
-
-#ifdef SUPPORT_HDCP
-static void hdcp_delay_work_func(struct work_struct *work)
-{
- if(0==(B_TXVIDSTABLE&HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS)))
- {
- schedule_delayed_work(&hdcp_delay_work, msecs_to_jiffies(100));
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate(): Video not stable\n"));
- }else{
- HDMITX_EnableHDCP(TRUE);
- }
-}
-#endif
-void cat66121_InterruptClr(void)
-{
- char intclr3,intdata4;
- intdata4= HDMITX_ReadI2C_Byte(0xEE);
- HDMITX_DEBUG_PRINTF(("REG_TX_INT_STAT4=%x \n",intdata4));
- intclr3 = (HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS))|B_TX_CLR_AUD_CTS | B_TX_INTACTDONE ;
- if( intdata4 )
- {
- HDMITX_WriteI2C_Byte(0xEE,intdata4); // clear ext interrupt ;
- HDMITX_DEBUG_PRINTF(("%s%s%s%s%s%s%s\n",
- (intdata4&0x40)?"video parameter change \n":"",
- (intdata4&0x20)?"HDCP Pj check done \n":"",
- (intdata4&0x10)?"HDCP Ri check done \n":"",
- (intdata4&0x8)? "DDC bus hang \n":"",
- (intdata4&0x4)? "Video input FIFO auto reset \n":"",
- (intdata4&0x2)? "No audio input interrupt \n":"",
- (intdata4&0x1)? "Audio decode error interrupt \n":""));
- }
-
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0xFF);
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0xFF);
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3); // clear interrupt.
- intclr3 &= ~(B_TX_INTACTDONE);
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3); // INTACTDONE reset to zero.
-}
-void cat66121_hdmi_interrupt(struct hdmi *hdmi_drv)
-{
- char sysstat = 0;
- mutex_lock(&handler_mutex);
- sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);
- if((sysstat & B_TX_INT_ACTIVE) || ((B_TX_HPDETECT & cat66121_hdmi->plug_status) != (B_TX_HPDETECT & sysstat))) {
- char intdata1,intdata2,intdata3;
- intdata1 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1);
- intdata2 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2);
- intdata3 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT3);
- HDMITX_DEBUG_PRINTF(("REG_TX_INT_STAT1=%x \n",intdata1));
- HDMITX_DEBUG_PRINTF(("REG_TX_INT_STAT2=%x \n",intdata2));
- HDMITX_DEBUG_PRINTF(("REG_TX_INT_STAT3=%x \n",intdata3));
- if(getHDMI_PowerStatus()==FALSE){
- HDMITX_PowerOn();
- }
-
- /******* Clear interrupt **********/
- cat66121_InterruptClr();
- /******** handler interrupt event ********/
-
- if(intdata1 & B_TX_INT_DDCFIFO_ERR)
- {
- HDMITX_DEBUG_PRINTF(("DDC FIFO Error.\n"));
- hdmitx_ClearDDCFIFO();
- }
- if(intdata1 & B_TX_INT_DDC_BUS_HANG)
- {
- HDMITX_DEBUG_PRINTF(("DDC BUS HANG.\n"));
- hdmitx_AbortDDC();
-#ifdef SUPPORT_HDCP
- if(hdmiTxDev[0].bAuthenticated)
- {
- HDMITX_DEBUG_PRINTF(("when DDC hang,and aborted DDC,the HDCP authentication need to restart.\n"));
- hdmitx_hdcp_ResumeAuthentication();
- }
-#endif
- }
- if(intdata1 & B_TX_INT_AUD_OVERFLOW ){
- HDMITX_DEBUG_PRINTF(("AUDIO FIFO OVERFLOW.\n"));
- HDMITX_OrReg_Byte(REG_TX_SW_RST,(B_HDMITX_AUD_RST|B_TX_AREF_RST));
- HDMITX_AndReg_Byte(REG_TX_SW_RST,~(B_HDMITX_AUD_RST|B_TX_AREF_RST));
- }
-
- if(intdata3 & B_TX_INT_VIDSTABLE)
- {
- sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);
- if(sysstat & B_TXVIDSTABLE)
- {
- hdmitx_FireAFE();
- }
- }
-
-#ifdef SUPPORT_HDCP
- if(intdata2 & B_TX_INT_AUTH_FAIL){
- hdmiTxDev[0].bAuthenticated = FALSE;
- hdmitx_AbortDDC();
-#if 0
- if(getHDMITX_LinkStatus())
- {
- // AudioModeDetect();
- if(getHDMITX_AuthenticationDone() ==FALSE)
- {
- HDMITX_DEBUG_PRINTF(("getHDMITX_AuthenticationDone() ==FALSE\n") );
- HDMITX_EnableHDCP(TRUE);
- setHDMITX_AVMute(FALSE);
- }
- }
-#endif
- }else if(intdata2 & B_TX_INT_AUTH_DONE){
- HDMITX_SetI2C_Byte(REG_TX_INT_MASK2, B_TX_AUTH_DONE_MASK, B_TX_AUTH_DONE_MASK);
- HDMITX_DEBUG_PRINTF(("getHDMITX_AuthenticationDone() ==SUCCESS\n") );
- }
-#endif
- if((intdata1 & B_TX_INT_HPD_PLUG)|| ((B_TX_HPDETECT & cat66121_hdmi->plug_status) != (B_TX_HPDETECT & sysstat))) {
- hdmiTxDev[0].bAuthenticated = FALSE;
- if(sysstat & B_TX_HPDETECT){
- HDMITX_DEBUG_PRINTF(("HPD plug\n") );
- }else{
- HDMITX_DEBUG_PRINTF(("HPD unplug\n") );
- }
- cat66121_hdmi->plug_status = sysstat;
- if(hdmi_drv->state == HDMI_SLEEP)
- hdmi_drv->state = WAIT_HOTPLUG;
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, msecs_to_jiffies(0));
- }
- if(intdata1 & (B_TX_INT_RX_SENSE)) {
- hdmiTxDev[0].bAuthenticated = FALSE;
- }
- }
-
-#ifdef SUPPORT_HDCP
- if(hdmi_drv->display == HDMI_ENABLE)
- {
- if(getHDMITX_LinkStatus())
- {
- // AudioModeDetect();
- if(getHDMITX_AuthenticationDone() ==FALSE)
- {
- HDMITX_DEBUG_PRINTF(("getHDMITX_AuthenticationDone() ==FALSE\n") );
- HDMITX_EnableHDCP(TRUE);
- setHDMITX_AVMute(FALSE);
- }
- }
- }
-#endif
-
- mutex_unlock(&handler_mutex);
-}
-
-int cat66121_hdmi_sys_detect_hpd(struct hdmi *hdmi_drv)
-{
- char HPD= 0;
- BYTE sysstat;
-
-
-#ifdef SUPPORT_HDCP
- if((cat66121_hdmi->plug_status != 0) && (cat66121_hdmi->plug_status != 1))
- cat66121_hdmi->plug_status = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);
-
- sysstat = cat66121_hdmi->plug_status;
-#else
- sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);
-#endif
-
- HPD = ((sysstat & B_TX_HPDETECT) == B_TX_HPDETECT)?TRUE:FALSE;
- if(HPD)
- return HDMI_HPD_ACTIVED;
- else
- return HDMI_HPD_REMOVED;
-}
-
-int cat66121_hdmi_sys_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __FUNCTION__);
- return (getHDMITX_EDIDBlock(block, buff) == TRUE)?HDMI_ERROR_SUCESS:HDMI_ERROR_FALSE;
-}
-
-void ConfigfHdmiVendorSpecificInfoFrame(BYTE _3D_Stru)
-{
- VendorSpecific_InfoFrame *VS_Info;
-
- VS_Info=(VendorSpecific_InfoFrame *)CommunBuff ;
-
- VS_Info->pktbyte.VS_HB[0] = VENDORSPEC_INFOFRAME_TYPE|0x80;
- VS_Info->pktbyte.VS_HB[1] = VENDORSPEC_INFOFRAME_VER;
- VS_Info->pktbyte.VS_HB[2] = (_3D_Stru == Side_by_Side)?6:5;
- VS_Info->pktbyte.VS_DB[0] = 0x03;
- VS_Info->pktbyte.VS_DB[1] = 0x0C;
- VS_Info->pktbyte.VS_DB[2] = 0x00;
- VS_Info->pktbyte.VS_DB[3] = 0x40;
- switch(_3D_Stru)
- {
- case Side_by_Side:
- case Frame_Pcaking:
- case Top_and_Botton:
- VS_Info->pktbyte.VS_DB[4] = (_3D_Stru<<4);
- break;
- default:
- VS_Info->pktbyte.VS_DB[4] = (Frame_Pcaking<<4);
- break ;
- }
- VS_Info->pktbyte.VS_DB[5] = 0x00;
- HDMITX_EnableVSInfoFrame(TRUE,(BYTE *)VS_Info);
-}
-
-static void cat66121_sys_config_avi(int VIC, int bOutputColorMode, int aspec, int Colorimetry, int pixelrep)
-{
- AVI_InfoFrame *AviInfo;
- //hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
- AviInfo = (AVI_InfoFrame *)CommunBuff ;
-
- AviInfo->pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ;
- AviInfo->pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ;
- AviInfo->pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ;
-
- switch(bOutputColorMode)
- {
- case F_MODE_YUV444:
- // AviInfo->info.ColorMode = 2 ;
- AviInfo->pktbyte.AVI_DB[0] = (2<<5)|(1<<4);
- break ;
- case F_MODE_YUV422:
- // AviInfo->info.ColorMode = 1 ;
- AviInfo->pktbyte.AVI_DB[0] = (1<<5)|(1<<4);
- break ;
- case F_MODE_RGB444:
- default:
- // AviInfo->info.ColorMode = 0 ;
- AviInfo->pktbyte.AVI_DB[0] = (0<<5)|(1<<4);
- break ;
- }
- AviInfo->pktbyte.AVI_DB[0] |= 0x02 ;
- AviInfo->pktbyte.AVI_DB[1] = 8 ;
- AviInfo->pktbyte.AVI_DB[1] |= (aspec != HDMI_16x9)?(1<<4):(2<<4); // 4:3 or 16:9
- AviInfo->pktbyte.AVI_DB[1] |= (Colorimetry != HDMI_ITU709)?(1<<6):(2<<6); // 4:3 or 16:9
- AviInfo->pktbyte.AVI_DB[2] = 0 ;
- AviInfo->pktbyte.AVI_DB[3] = VIC ;
- AviInfo->pktbyte.AVI_DB[4] = pixelrep & 3 ;
- AviInfo->pktbyte.AVI_DB[5] = 0 ;
- AviInfo->pktbyte.AVI_DB[6] = 0 ;
- AviInfo->pktbyte.AVI_DB[7] = 0 ;
- AviInfo->pktbyte.AVI_DB[8] = 0 ;
- AviInfo->pktbyte.AVI_DB[9] = 0 ;
- AviInfo->pktbyte.AVI_DB[10] = 0 ;
- AviInfo->pktbyte.AVI_DB[11] = 0 ;
- AviInfo->pktbyte.AVI_DB[12] = 0 ;
-
- HDMITX_EnableAVIInfoFrame(TRUE, (unsigned char *)AviInfo);
-
-}
-
-int cat66121_hdmi_sys_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
-{
- struct fb_videomode *mode;
- HDMI_Aspec aspec ;
- HDMI_Colorimetry Colorimetry ;
- VIDEOPCLKLEVEL level ;
-
- if(vpara == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] input parameter error\n", __FUNCTION__);
- return -1;
- }
-
-#ifdef SUPPORT_HDCP
- HDMITX_EnableHDCP(FALSE);
-#endif
-
- // output Color mode
-#ifndef DISABLE_HDMITX_CSC
- switch(vpara->output_color)
- {
- case HDMI_COLOR_YCbCr444:
- bOutputColorMode = F_MODE_YUV444 ;
- break ;
- case HDMI_COLOR_YCbCr422:
- bOutputColorMode = F_MODE_YUV422 ;
- break ;
- case HDMI_COLOR_RGB:
- default:
- bOutputColorMode = F_MODE_RGB444 ;
- break ;
- }
-#else
- bOutputColorMode = F_MODE_RGB444 ;
-#endif
-
- // Set ext video
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if(mode == NULL)
- {
- hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
- return -ENOENT;
- }
-
- hdmi_drv->tmdsclk = mode->pixclock;
- switch(vpara->vic)
- {
- case HDMI_640x480p60:
- pixelrep = 0 ;
- aspec = HDMI_4x3 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_480p60:
- pixelrep = 0 ;
- aspec = HDMI_4x3 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_480p60_16x9:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_720p60:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_1080i60:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_480i60:
- pixelrep = 1 ;
- aspec = HDMI_4x3 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_480i60_16x9:
- pixelrep = 1 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_1080p60:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_576p50:
- pixelrep = 0 ;
- aspec = HDMI_4x3 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_576p50_16x9:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_720p50:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_1080i50:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_576i50:
- pixelrep = 1 ;
- aspec = HDMI_4x3 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_576i50_16x9:
- pixelrep = 1 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU601 ;
- break ;
- case HDMI_1080p50:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_1080p24:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_1080p25:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
- case HDMI_1080p30:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- break ;
-
- case HDMI_720p30:
- pixelrep = 0 ;
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- default:
- aspec = HDMI_16x9 ;
- Colorimetry = HDMI_ITU709 ;
- }
- if( Colorimetry == HDMI_ITU709 )
- {
- bInputColorMode |= F_VIDMODE_ITU709 ;
- }
- else
- {
- bInputColorMode &= ~F_VIDMODE_ITU709 ;
- }
- if( vpara->vic != HDMI_640x480p60)
- {
- bInputColorMode |= F_VIDMODE_16_235 ;
- }
- else
- {
- bInputColorMode &= ~F_VIDMODE_16_235 ;
- }
-
- if( (hdmi_drv->tmdsclk*(pixelrep+1))>80000000L )
- {
- level = PCLK_HIGH ;
- }
- else if((hdmi_drv->tmdsclk*(pixelrep+1))>20000000L)
- {
- level = PCLK_MEDIUM ;
- }
- else
- {
- level = PCLK_LOW ;
- }
-
- HDMITX_EnableVideoOutput(level,bInputColorMode,bOutputColorMode ,vpara->output_mode);
-
- if(vpara->output_mode == OUTPUT_HDMI) {
- cat66121_sys_config_avi(vpara->vic, bOutputColorMode, aspec, Colorimetry, pixelrep);
-#ifdef OUTPUT_3D_MODE
- ConfigfHdmiVendorSpecificInfoFrame(OUTPUT_3D_MODE);
-#endif
-
- }
- else {
- HDMITX_EnableAVIInfoFrame(FALSE ,NULL);
- HDMITX_EnableVSInfoFrame(FALSE,NULL);
- }
- setHDMITX_VideoSignalType(INPUT_SIGNAL_TYPE);
-#ifdef SUPPORT_SYNCEMBEDDED
- if(INPUT_SIGNAL_TYPE & T_MODE_SYNCEMB)
- {
- setHDMITX_SyncEmbeddedByVIC(vpara->vic,INPUT_SIGNAL_TYPE);
- }
-#endif
-
- return HDMI_ERROR_SUCESS;
-}
-
-static void cat66121_hdmi_config_aai(void)
-{
- int i ;
- Audio_InfoFrame *AudioInfo ;
- AudioInfo = (Audio_InfoFrame *)CommunBuff ;
-
- AudioInfo->pktbyte.AUD_HB[0] = AUDIO_INFOFRAME_TYPE ;
- AudioInfo->pktbyte.AUD_HB[1] = 1 ;
- AudioInfo->pktbyte.AUD_HB[2] = AUDIO_INFOFRAME_LEN ;
- AudioInfo->pktbyte.AUD_DB[0] = 1 ;
- for( i = 1 ;i < AUDIO_INFOFRAME_LEN ; i++ )
- {
- AudioInfo->pktbyte.AUD_DB[i] = 0 ;
- }
- HDMITX_EnableAudioInfoFrame(TRUE, (unsigned char *)AudioInfo);
-}
-
-int cat66121_hdmi_sys_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
-{
- cat66121_hdmi_config_aai();
- HDMITX_EnableAudioOutput(
- CNOFIG_INPUT_AUDIO_TYPE,
- CONFIG_INPUT_AUDIO_SPDIF,
- INPUT_SAMPLE_FREQ_HZ,
- audio->channel,
- NULL, // pointer to cahnnel status.
- hdmi_drv->tmdsclk*(pixelrep+1));
- return HDMI_ERROR_SUCESS;
-}
-
-void cat66121_hdmi_sys_enalbe_output(struct hdmi *hdmi_drv, int enable)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __FUNCTION__);
-
- if(enable){
-#if 0//def SUPPORT_HDCP
- cancel_delayed_work_sync(&hdcp_delay_work);
- schedule_delayed_work(&hdcp_delay_work, msecs_to_jiffies(100));
-#endif
- setHDMITX_AVMute(FALSE);
- }else{
- setHDMITX_AVMute(TRUE);
- }
- DumpHDMITXReg() ;
-}
-
-int cat66121_hdmi_sys_insert(struct hdmi *hdmi_drv)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __FUNCTION__);
- if(getHDMI_PowerStatus()==FALSE)
- HDMITX_PowerOn();
-
- HDMITX_DisableAudioOutput();
- return 0;
-}
-
-int cat66121_hdmi_sys_remove(struct hdmi *hdmi_drv)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __FUNCTION__);
-#if 0//def SUPPORT_HDCP
- cancel_delayed_work_sync(&hdcp_delay_work);
- HDMITX_EnableHDCP(FALSE);
-#endif
- HDMITX_DisableVideoOutput();
- if(getHDMI_PowerStatus()==TRUE)
- HDMITX_PowerDown();
- return 0;
-}
+++ /dev/null
-#ifndef _CAT6611_HDMI_HW_H
-#define _CAT6611_HDMI_HW_H
-
-#include "typedef.h"
-#include "config.h"
-#include "debug.h"
-#include "hdmitx_drv.h"
-#define CAT6611_SCL_RATE 100 * 1000
-#define I2S 0
-#define SPDIF 1
-
-#ifndef I2S_FORMAT
-#define I2S_FORMAT 0x01 // 32bit audio
-#endif
-
-#ifndef INPUT_SAMPLE_FREQ
- #define INPUT_SAMPLE_FREQ AUDFS_48KHz
-#endif //INPUT_SAMPLE_FREQ
-
-#ifndef INPUT_SAMPLE_FREQ_HZ
- #define INPUT_SAMPLE_FREQ_HZ 44100L
-#endif //INPUT_SAMPLE_FREQ_HZ
-
-#ifndef OUTPUT_CHANNEL
- #define OUTPUT_CHANNEL 2
-#endif //OUTPUT_CHANNEL
-
-#ifndef CNOFIG_INPUT_AUDIO_TYPE
- #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_LPCM
- // #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_NLPCM
- // #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_HBR
-#endif //CNOFIG_INPUT_AUDIO_TYPE
-
-#ifndef CONFIG_INPUT_AUDIO_SPDIF
- #define CONFIG_INPUT_AUDIO_SPDIF I2S
- // #define CONFIG_INPUT_AUDIO_SPDIF SPDIF
-#endif //CONFIG_INPUT_AUDIO_SPDIF
-
-#ifndef INPUT_SIGNAL_TYPE
-#define INPUT_SIGNAL_TYPE 0 // 24 bit sync seperate
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-// Internal Data Type
-////////////////////////////////////////////////////////////////////////////////
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
- };
-typedef enum tagHDMI_Video_Type {
- HDMI_Unkown = 0 ,
- HDMI_640x480p60 = 1 ,
- HDMI_480p60,
- HDMI_480p60_16x9,
- HDMI_720p60,
- HDMI_1080i60,
- HDMI_480i60,
- HDMI_480i60_16x9,
- HDMI_1080p60 = 16,
- HDMI_576p50,
- HDMI_576p50_16x9,
- HDMI_720p50,
- HDMI_1080i50,
- HDMI_576i50,
- HDMI_576i50_16x9,
- HDMI_1080p50 = 31,
- HDMI_1080p24,
- HDMI_1080p25,
- HDMI_1080p30,
- HDMI_720p30 = 61,
-} HDMI_Video_Type ;
-
-typedef enum tagHDMI_Aspec {
- HDMI_4x3 ,
- HDMI_16x9
-} HDMI_Aspec;
-
-typedef enum tagHDMI_OutputColorMode {
- HDMI_RGB444,
- HDMI_YUV444,
- HDMI_YUV422
-} HDMI_OutputColorMode ;
-
-typedef enum tagHDMI_Colorimetry {
- HDMI_ITU601,
- HDMI_ITU709
-} HDMI_Colorimetry ;
-
-struct VideoTiming {
- ULONG VideoPixelClock ;
- BYTE VIC ;
- BYTE pixelrep ;
- BYTE outputVideoMode ;
-} ;
-
-
-
-typedef enum _TXVideo_State_Type {
- TXVSTATE_Unplug = 0,
- TXVSTATE_HPD,
- TXVSTATE_WaitForMode,
- TXVSTATE_WaitForVStable,
- TXVSTATE_VideoInit,
- TXVSTATE_VideoSetup,
- TXVSTATE_VideoOn,
- TXVSTATE_Reserved
-} TXVideo_State_Type ;
-
-
-typedef enum _TXAudio_State_Type {
- TXASTATE_AudioOff = 0,
- TXASTATE_AudioPrepare,
- TXASTATE_AudioOn,
- TXASTATE_AudioFIFOFail,
- TXASTATE_Reserved
-} TXAudio_State_Type ;
-/////////////////////////////////////////
-// RX Capability.
-/////////////////////////////////////////
-typedef struct {
- BYTE b16bit:1 ;
- BYTE b20bit:1 ;
- BYTE b24bit:1 ;
- BYTE Rsrv:5 ;
-} LPCM_BitWidth ;
-
-typedef enum {
- AUD_RESERVED_0 = 0 ,
- AUD_LPCM,
- AUD_AC3,
- AUD_MPEG1,
- AUD_MP3,
- AUD_MPEG2,
- AUD_AAC,
- AUD_DTS,
- AUD_ATRAC,
- AUD_ONE_BIT_AUDIO,
- AUD_DOLBY_DIGITAL_PLUS,
- AUD_DTS_HD,
- AUD_MAT_MLP,
- AUD_DST,
- AUD_WMA_PRO,
- AUD_RESERVED_15
-} AUDIO_FORMAT_CODE ;
-
-typedef union {
- struct {
- BYTE channel:3 ;
- BYTE AudioFormatCode:4 ;
- BYTE Rsrv1:1 ;
-
- BYTE b32KHz:1 ;
- BYTE b44_1KHz:1 ;
- BYTE b48KHz:1 ;
- BYTE b88_2KHz:1 ;
- BYTE b96KHz:1 ;
- BYTE b176_4KHz:1 ;
- BYTE b192KHz:1 ;
- BYTE Rsrv2:1 ;
- BYTE ucCode ;
- } s ;
- BYTE uc[3] ;
-} AUDDESCRIPTOR ;
-
-typedef union {
- struct {
- BYTE FL_FR:1 ;
- BYTE LFE:1 ;
- BYTE FC:1 ;
- BYTE RL_RR:1 ;
- BYTE RC:1 ;
- BYTE FLC_FRC:1 ;
- BYTE RLC_RRC:1 ;
- BYTE Reserve:1 ;
- BYTE Unuse[2] ;
- } s ;
- BYTE uc[3] ;
-} SPK_ALLOC ;
-
-#define CEA_SUPPORT_UNDERSCAN (1<<7)
-#define CEA_SUPPORT_AUDIO (1<<6)
-#define CEA_SUPPORT_YUV444 (1<<5)
-#define CEA_SUPPORT_YUV422 (1<<4)
-#define CEA_NATIVE_MASK 0xF
-
-
-#define HDMI_DC_SUPPORT_AI (1<<7)
-#define HDMI_DC_SUPPORT_48 (1<<6)
-#define HDMI_DC_SUPPORT_36 (1<<5)
-#define HDMI_DC_SUPPORT_30 (1<<4)
-#define HDMI_DC_SUPPORT_Y444 (1<<3)
-#define HDMI_DC_SUPPORT_DVI_DUAL 1
-
-typedef union _tag_DCSUPPORT {
- struct {
- BYTE DVI_Dual:1 ;
- BYTE Rsvd:2 ;
- BYTE DC_Y444:1 ;
- BYTE DC_30Bit:1 ;
- BYTE DC_36Bit:1 ;
- BYTE DC_48Bit:1 ;
- BYTE SUPPORT_AI:1 ;
- } info ;
- BYTE uc ;
-} DCSUPPORT ;
-
-typedef union _LATENCY_SUPPORT{
- struct {
- BYTE Rsvd:6 ;
- BYTE I_Latency_Present:1 ;
- BYTE Latency_Present:1 ;
- } info ;
- BYTE uc ;
-} LATENCY_SUPPORT ;
-
-#define HDMI_IEEEOUI 0x0c03
-#define MAX_VODMODE_COUNT 32
-#define MAX_AUDDES_COUNT 4
-
-typedef struct _RX_CAP{
- BYTE VideoMode ;
- BYTE NativeVDOMode ;
- BYTE VDOMode[8] ;
- BYTE AUDDesCount ;
- AUDDESCRIPTOR AUDDes[MAX_AUDDES_COUNT] ;
- BYTE PA[2] ;
- ULONG IEEEOUI ;
- DCSUPPORT dc ;
- BYTE MaxTMDSClock ;
- LATENCY_SUPPORT lsupport ;
- SPK_ALLOC SpeakerAllocBlk ;
- BYTE ValidCEA:1 ;
- BYTE ValidHDMI:1 ;
- BYTE Valid3D:1 ;
-} RX_CAP ;
-
-///////////////////////////////////////////////////////////////////////
-// Output Mode Type
-///////////////////////////////////////////////////////////////////////
-
-#define RES_ASPEC_4x3 0
-#define RES_ASPEC_16x9 1
-#define F_MODE_REPT_NO 0
-#define F_MODE_REPT_TWICE 1
-#define F_MODE_REPT_QUATRO 3
-#define F_MODE_CSC_ITU601 0
-#define F_MODE_CSC_ITU709 1
-
-BYTE HDMITX_ReadI2C_Byte(BYTE RegAddr);
-SYS_STATUS HDMITX_WriteI2C_Byte(BYTE RegAddr,BYTE d);
-SYS_STATUS HDMITX_ReadI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);
-SYS_STATUS HDMITX_WriteI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);
-SYS_STATUS HDMITX_SetI2C_Byte(BYTE Reg,BYTE Mask,BYTE Value);
-
-void InitHDMITX_Variable(void);
-#if 0
-//void HDMITX_ChangeDisplayOption(HDMI_Video_Type VideoMode, HDMI_OutputColorMode OutputColorMode);
-//void HDMITX_SetOutput();
-//int HDMITX_DevLoopProc();
-//void ConfigfHdmiVendorSpecificInfoFrame(BYTE _3D_Stru);
-void HDMITX_ChangeAudioOption(BYTE Option, BYTE channelNum, BYTE AudioFs);
-void HDMITX_SetAudioOutput();
-void HDMITX_ChangeColorDepth(BYTE colorDepth);
-#endif
-#endif
+++ /dev/null
-///*****************************************
-// Copyright (C) 2009-2014
-// ITE Tech. Inc. All Rights Reserved
-// Proprietary and Confidential
-///*****************************************
-// @file <config.h>
-// @author Jau-Chih.Tseng@ite.com.tw
-// @date 2012/12/20
-// @fileversion: ITE_HDMITX_SAMPLE_3.14
-//******************************************/
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-//#pragma message("config.h")
-
-#ifdef EXTERN_HDCPROM
-#pragma message("Defined EXTERN_HDCPROM")
-#endif // EXTERN_HDCPROM
-
-#define SUPPORT_EDID
-//#define SUPPORT_AUDIO_MONITOR
-#define AudioOutDelayCnt 250
-
-#ifdef CONFIG_SUPPORT_HDCP
-#define SUPPORT_HDCP
-#define SUPPORT_SHA
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Video Configuration
-//////////////////////////////////////////////////////////////////////////////////////////
-// 2010/01/26 added a option to disable HDCP.
-#define SUPPORT_OUTPUTYUV
-#define SUPPORT_OUTPUTRGB
-#define DISABLE_HDMITX_CSC
-
-#define SUPPORT_INPUTRGB
-#define SUPPORT_INPUTYUV444
-#define SUPPORT_INPUTYUV422
-// #define SUPPORT_SYNCEMBEDDED
-// #define SUPPORT_DEGEN
-#define NON_SEQUENTIAL_YCBCR422
-
-
-
-#define INPUT_COLOR_MODE F_MODE_RGB444
-//#define INPUT_COLOR_MODE F_MODE_YUV422
-//#define INPUT_COLOR_MODE F_MODE_YUV444
-
-#define INPUT_COLOR_DEPTH 24
-// #define INPUT_COLOR_DEPTH 30
-// #define INPUT_COLOR_DEPTH 36
-
-//#define OUTPUT_COLOR_MODE F_MODE_YUV422
-//#define OUTPUT_COLOR_MODE F_MODE_YUV444
-#define OUTPUT_COLOR_MODE F_MODE_RGB444
-
-//#define OUTPUT_3D_MODE Frame_Pcaking
-//#define OUTPUT_3D_MODE Top_and_Botton
-//#define OUTPUT_3D_MODE Side_by_Side
-
-// #define INV_INPUT_ACLK
-#define INV_INPUT_PCLK
-
-#ifdef SUPPORT_SYNCEMBEDDED
- // #define INPUT_SIGNAL_TYPE (T_MODE_SYNCEMB) // 16 bit sync embedded
- // #define INPUT_SIGNAL_TYPE (T_MODE_SYNCEMB | T_MODE_CCIR656) // 8 bit sync embedded
- #define INPUT_SIGNAL_TYPE (T_MODE_SYNCEMB|T_MODE_INDDR|T_MODE_PCLKDIV2) // 16 bit sync embedded DDR
- // #define INPUT_SIGNAL_TYPE (T_MODE_SYNCEMB|T_MODE_INDDR) // 8 bit sync embedded DDR
-
- #define SUPPORT_INPUTYUV422
- #ifdef INPUT_COLOR_MODE
- #undef INPUT_COLOR_MODE
- #endif // INPUT_COLOR_MODE
- #define INPUT_COLOR_MODE F_MODE_YUV422
-#else
-// #pragma message ("Defined seperated sync.")
- #define INPUT_SIGNAL_TYPE 0 // 24 bit sync seperate
- //#define INPUT_SIGNAL_TYPE ( T_MODE_DEGEN )
- //#define INPUT_SIGNAL_TYPE ( T_MODE_INDDR)
- //#define INPUT_SIGNAL_TYPE ( T_MODE_SYNCEMB)
- //#define INPUT_SIGNAL_TYPE ( T_MODE_CCIR656 | T_MODE_SYNCEMB )
-#endif
-
-
-#if defined(SUPPORT_INPUTYUV444) || defined(SUPPORT_INPUTYUV422)
-#define SUPPORT_INPUTYUV
-#endif
-
-#ifdef SUPPORT_SYNCEMBEDDED
-#pragma message("defined SUPPORT_SYNCEMBEDDED for Sync Embedded timing input or CCIR656 input.")
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Audio Configuration
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// #define SUPPORT_HBR_AUDIO
-#define USE_SPDIF_CHSTAT
-#ifndef SUPPORT_HBR_AUDIO
- #define INPUT_SAMPLE_FREQ AUDFS_48KHz
- #define INPUT_SAMPLE_FREQ_HZ 44100L
- #define OUTPUT_CHANNEL 2 // 3 // 4 // 5//6 //7 //8
-
- #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_LPCM
- // #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_NLPCM
- #define CONFIG_INPUT_AUDIO_SPDIF FALSE // I2S
- // #define CONFIG_INPUT_AUDIO_SPDIF TRUE // SPDIF
-
- // #define I2S_FORMAT 0x00 // 24bit I2S audio
- #define I2S_FORMAT 0x01 // 32bit I2S audio
- // #define I2S_FORMAT 0x02 // 24bit I2S audio, right justify
- // #define I2S_FORMAT 0x03 // 32bit I2S audio, right justify
-
-#else // SUPPORT_HBR_AUDIO
-
- #define INPUT_SAMPLE_FREQ AUDFS_768KHz
- #define INPUT_SAMPLE_FREQ_HZ 768000L
- #define OUTPUT_CHANNEL 8
- #define CNOFIG_INPUT_AUDIO_TYPE T_AUDIO_HBR
- #define CONFIG_INPUT_AUDIO_SPDIF FALSE // I2S
- // #define CONFIG_INPUT_AUDIO_SPDIF TRUE // SPDIF
- #define I2S_FORMAT 0x47 // 32bit audio
-#endif
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Audio Monitor Configuration
-//////////////////////////////////////////////////////////////////////////////////////////
-// #define HDMITX_AUTO_MONITOR_INPUT
-// #define HDMITX_INPUT_INFO
-
-#ifdef HDMITX_AUTO_MONITOR_INPUT
-#define HDMITX_INPUT_INFO
-#endif
-
-
-#endif
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <csc.c>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/01/06\r
-// @fileversion: COMMON_2.00\r
-//******************************************/\r
-\r
-#include "config.h"\r
-#include "typedef.h"\r
-\r
-#if (defined (SUPPORT_OUTPUTYUV)) && (defined (SUPPORT_INPUTRGB))\r
-\r
- BYTE _CODE bCSCMtx_RGB2YUV_ITU601_16_235[] =\r
- {\r
- 0x00,0x80,0x00,\r
- 0xB2,0x04,0x65,0x02,0xE9,0x00,\r
- 0x93,0x3C,0x18,0x04,0x55,0x3F,\r
- 0x49,0x3D,0x9F,0x3E,0x18,0x04\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_RGB2YUV_ITU601_0_255[] =\r
- {\r
- 0x10,0x80,0x10,\r
- 0x09,0x04,0x0E,0x02,0xC9,0x00,\r
- 0x0F,0x3D,0x84,0x03,0x6D,0x3F,\r
- 0xAB,0x3D,0xD1,0x3E,0x84,0x03\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_RGB2YUV_ITU709_16_235[] =\r
- {\r
- 0x00,0x80,0x00,\r
- 0xB8,0x05,0xB4,0x01,0x94,0x00,\r
- 0x4a,0x3C,0x17,0x04,0x9F,0x3F,\r
- 0xD9,0x3C,0x10,0x3F,0x17,0x04\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_RGB2YUV_ITU709_0_255[] =\r
- {\r
- 0x10,0x80,0x10,\r
- 0xEa,0x04,0x77,0x01,0x7F,0x00,\r
- 0xD0,0x3C,0x83,0x03,0xAD,0x3F,\r
- 0x4B,0x3D,0x32,0x3F,0x83,0x03\r
- } ;\r
-#endif\r
-\r
-#if (defined (SUPPORT_OUTPUTRGB)) && (defined (SUPPORT_INPUTYUV))\r
-\r
- BYTE _CODE bCSCMtx_YUV2RGB_ITU601_16_235[] =\r
- {\r
- 0x00,0x00,0x00,\r
- 0x00,0x08,0x6B,0x3A,0x50,0x3D,\r
- 0x00,0x08,0xF5,0x0A,0x02,0x00,\r
- 0x00,0x08,0xFD,0x3F,0xDA,0x0D\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_YUV2RGB_ITU601_0_255[] =\r
- {\r
- 0x04,0x00,0xA7,\r
- 0x4F,0x09,0x81,0x39,0xDD,0x3C,\r
- 0x4F,0x09,0xC4,0x0C,0x01,0x00,\r
- 0x4F,0x09,0xFD,0x3F,0x1F,0x10\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_YUV2RGB_ITU709_16_235[] =\r
- {\r
- 0x00,0x00,0x00,\r
- 0x00,0x08,0x55,0x3C,0x88,0x3E,\r
- 0x00,0x08,0x51,0x0C,0x00,0x00,\r
- 0x00,0x08,0x00,0x00,0x84,0x0E\r
- } ;\r
-\r
- BYTE _CODE bCSCMtx_YUV2RGB_ITU709_0_255[] =\r
- {\r
- 0x04,0x00,0xA7,\r
- 0x4F,0x09,0xBA,0x3B,0x4B,0x3E,\r
- 0x4F,0x09,0x57,0x0E,0x02,0x00,\r
- 0x4F,0x09,0xFE,0x3F,0xE8,0x10\r
- } ;\r
-#endif\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <debug.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-#ifndef _DEBUG_H_\r
-#define _DEBUG_H_\r
-\r
-#ifdef CONFIG_RK_HDMI_DEBUG\r
-#define Debug_message 1\r
-#else\r
-#define Debug_message 0\r
-#endif\r
-\r
-//#pragma message("debug.h")\r
-\r
-#if Debug_message\r
-\r
- #define HDMITX_DEBUG_PRINTF(x) printk x\r
- #define HDCP_DEBUG_PRINTF(x) printk x\r
- #define EDID_DEBUG_PRINTF(x) printk x\r
- #define HDMITX_DEBUG_INFO(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF(x)\r
- #define HDCP_DEBUG_PRINTF(x)\r
- #define EDID_DEBUG_PRINTF(x)\r
- #define HDMITX_DEBUG_INFO(x)\r
-#endif\r
-\r
-\r
-#if( Debug_message & (1<<1))\r
- #define HDMITX_DEBUG_PRINTF1(x) printk x\r
- #define HDCP_DEBUG_PRINTF1(x) printk x\r
- #define EDID_DEBUG_PRINTF1(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF1(x)\r
- #define HDCP_DEBUG_PRINTF1(x)\r
- #define EDID_DEBUG_PRINTF1(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<2))\r
- #define HDMITX_DEBUG_PRINTF2(x) printk x\r
- #define HDCP_DEBUG_PRINTF2(x) printk x\r
- #define EDID_DEBUG_PRINTF2(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF2(x)\r
- #define HDCP_DEBUG_PRINTF2(x)\r
- #define EDID_DEBUG_PRINTF2(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<3))\r
- #define HDMITX_DEBUG_PRINTF3(x) printk x\r
- #define HDCP_DEBUG_PRINTF3(x) printk x\r
- #define EDID_DEBUG_PRINTF3(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF3(x)\r
- #define HDCP_DEBUG_PRINTF3(x)\r
- #define EDID_DEBUG_PRINTF3(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<4))\r
- #define HDMITX_DEBUG_PRINTF4(x) printk x\r
- #define HDCP_DEBUG_PRINTF4(x) printk x\r
- #define EDID_DEBUG_PRINTF4(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF4(x)\r
- #define HDCP_DEBUG_PRINTF4(x)\r
- #define EDID_DEBUG_PRINTF4(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<5))\r
- #define HDMITX_DEBUG_PRINTF5(x) printk x\r
- #define HDCP_DEBUG_PRINTF5(x) printk x\r
- #define EDID_DEBUG_PRINTF5(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF5(x)\r
- #define HDCP_DEBUG_PRINTF5(x)\r
- #define EDID_DEBUG_PRINTF5(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<6))\r
- #define HDMITX_DEBUG_PRINTF6(x) printk x\r
- #define HDCP_DEBUG_PRINTF6(x) printk x\r
- #define EDID_DEBUG_PRINTF6(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF6(x)\r
- #define HDCP_DEBUG_PRINTF6(x)\r
- #define EDID_DEBUG_PRINTF6(x)\r
-#endif\r
-\r
-#if( Debug_message & (1<<7))\r
- #define HDMITX_DEBUG_PRINTF7(x) printk x\r
- #define HDCP_DEBUG_PRINTF7(x) printk x\r
- #define EDID_DEBUG_PRINTF7(x) printk x\r
-#else\r
- #define HDMITX_DEBUG_PRINTF7(x)\r
- #define HDCP_DEBUG_PRINTF7(x)\r
- #define EDID_DEBUG_PRINTF7(x)\r
-#endif\r
-\r
-\r
-#endif// _DEBUG_H_\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-\r
-#ifndef _HDMITX_H_\r
-#define _HDMITX_H_\r
-#include <linux/kernel.h>\r
-#include <linux/delay.h>\r
-#include <linux/module.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/i2c.h>\r
-\r
-#include "debug.h"\r
-#include "config.h"\r
-#include "typedef.h"\r
-#include "hdmitx_drv.h"\r
-\r
-#define HDMITX_MAX_DEV_COUNT 1\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////\r
-// Output Mode Type\r
-///////////////////////////////////////////////////////////////////////\r
-\r
-#define RES_ASPEC_4x3 0\r
-#define RES_ASPEC_16x9 1\r
-#define F_MODE_REPT_NO 0\r
-#define F_MODE_REPT_TWICE 1\r
-#define F_MODE_REPT_QUATRO 3\r
-#define F_MODE_CSC_ITU601 0\r
-#define F_MODE_CSC_ITU709 1\r
-\r
-\r
-#define TIMER_LOOP_LEN 10\r
-#define MS(x) (((x)+(TIMER_LOOP_LEN-1))/TIMER_LOOP_LEN); // for timer loop\r
-\r
-// #define SUPPORT_AUDI_AudSWL 16 // Jeilin case.\r
-#define SUPPORT_AUDI_AudSWL 24 // Jeilin case.\r
-\r
-#if(SUPPORT_AUDI_AudSWL==16)\r
- #define CHTSTS_SWCODE 0x02\r
-#elif(SUPPORT_AUDI_AudSWL==18)\r
- #define CHTSTS_SWCODE 0x04\r
-#elif(SUPPORT_AUDI_AudSWL==20)\r
- #define CHTSTS_SWCODE 0x03\r
-#else\r
- #define CHTSTS_SWCODE 0x0B\r
-#endif\r
-\r
-#endif // _HDMITX_H_\r
-\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_drv.c>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-// HDMITX.C\r
-// Driver code for platform independent\r
-/////////////////////////////////////////////////////////////////////\r
-#include "hdmitx.h"\r
-#include "hdmitx_drv.h"\r
-#define FALLING_EDGE_TRIGGER\r
-\r
-#define MSCOUNT 1000\r
-#define LOADING_UPDATE_TIMEOUT (3000/32) // 3sec\r
-// USHORT u8msTimer = 0 ;\r
-// USHORT TimerServF = TRUE ;\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Authentication status\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-// #define TIMEOUT_WAIT_AUTH MS(2000)\r
-\r
-HDMITXDEV hdmiTxDev[HDMITX_MAX_DEV_COUNT] ;\r
-\r
-#ifndef INV_INPUT_PCLK\r
-#define PCLKINV 0\r
-#else\r
-#define PCLKINV B_TX_VDO_LATCH_EDGE\r
-#endif\r
-\r
-#ifndef INV_INPUT_ACLK\r
- #define InvAudCLK 0\r
-#else\r
- #define InvAudCLK B_TX_AUDFMT_FALL_EDGE_SAMPLE_WS\r
-#endif\r
-\r
-#define INIT_CLK_HIGH\r
-// #define INIT_CLK_LOW\r
-\r
-_CODE RegSetEntry HDMITX_Init_Table[] = {\r
-\r
- {0x0F, 0x40, 0x00},\r
-\r
- {0x62, 0x08, 0x00},\r
- {0x64, 0x04, 0x00},\r
- {0x01,0x00,0x00},//idle(100);\r
-\r
- {0x04, 0x20, 0x20},\r
- {0x04, 0x1D, 0x1D},\r
- {0x01,0x00,0x00},//idle(100);\r
- {0x0F, 0x01, 0x00}, // bank 0 ;\r
- #ifdef INIT_CLK_LOW\r
- {0x62, 0x90, 0x10},\r
- {0x64, 0x89, 0x09},\r
- {0x68, 0x10, 0x10},\r
- #endif\r
-\r
- {0xD1, 0x0E, 0x0C},\r
- {0x65, 0x03, 0x00},\r
- #ifdef NON_SEQUENTIAL_YCBCR422 // for ITE HDMIRX\r
- {0x71, 0xFC, 0x1C},\r
- #else\r
- {0x71, 0xFC, 0x18},\r
- #endif\r
-\r
- {0x8D, 0xFF, CEC_I2C_SLAVE_ADDR},\r
- {0x0F, 0x08, 0x08},\r
-\r
- {0xF8,0xFF,0xC3},\r
- {0xF8,0xFF,0xA5},\r
- {0x20, 0x80, 0x80},\r
- {0x37, 0x01, 0x00},\r
- {0x20, 0x80, 0x00},\r
- {0xF8,0xFF,0xFF},\r
-\r
- {0x59, 0xD8, 0x40|PCLKINV},\r
- {0xE1, 0x20, InvAudCLK},\r
- {0x05, 0xC0, 0x40},\r
- {REG_TX_INT_MASK1, 0xFF, ~(B_TX_RXSEN_MASK|B_TX_HPD_MASK)},\r
- {REG_TX_INT_MASK2, 0xFF, ~(B_TX_KSVLISTCHK_MASK|B_TX_AUTH_DONE_MASK|B_TX_AUTH_FAIL_MASK)},\r
- {REG_TX_INT_MASK3, 0xFF, ~(0x0)},\r
- {0x0C, 0xFF, 0xFF},\r
- {0x0D, 0xFF, 0xFF},\r
- {0x0E, 0x03, 0x03},\r
-\r
- {0x0C, 0xFF, 0x00},\r
- {0x0D, 0xFF, 0x00},\r
- {0x0E, 0x02, 0x00},\r
- {0x09, 0x03, 0x00}, // Enable HPD and RxSen Interrupt\r
- {0,0,0}\r
-};\r
-\r
-_CODE RegSetEntry HDMITX_DefaultVideo_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default output format.\r
- ////////////////////////////////////////////////////\r
- {0x72, 0xff, 0x00},\r
- {0x70, 0xff, 0x00},\r
-#ifndef DEFAULT_INPUT_YCBCR\r
-// GenCSC\RGB2YUV_ITU709_16_235.c\r
- {0x72, 0xFF, 0x02},\r
- {0x73, 0xFF, 0x00},\r
- {0x74, 0xFF, 0x80},\r
- {0x75, 0xFF, 0x00},\r
- {0x76, 0xFF, 0xB8},\r
- {0x77, 0xFF, 0x05},\r
- {0x78, 0xFF, 0xB4},\r
- {0x79, 0xFF, 0x01},\r
- {0x7A, 0xFF, 0x93},\r
- {0x7B, 0xFF, 0x00},\r
- {0x7C, 0xFF, 0x49},\r
- {0x7D, 0xFF, 0x3C},\r
- {0x7E, 0xFF, 0x18},\r
- {0x7F, 0xFF, 0x04},\r
- {0x80, 0xFF, 0x9F},\r
- {0x81, 0xFF, 0x3F},\r
- {0x82, 0xFF, 0xD9},\r
- {0x83, 0xFF, 0x3C},\r
- {0x84, 0xFF, 0x10},\r
- {0x85, 0xFF, 0x3F},\r
- {0x86, 0xFF, 0x18},\r
- {0x87, 0xFF, 0x04},\r
-#else\r
-// GenCSC\YUV2RGB_ITU709_16_235.c\r
- {0x0F, 0x01, 0x00},\r
- {0x72, 0xFF, 0x03},\r
- {0x73, 0xFF, 0x00},\r
- {0x74, 0xFF, 0x80},\r
- {0x75, 0xFF, 0x00},\r
- {0x76, 0xFF, 0x00},\r
- {0x77, 0xFF, 0x08},\r
- {0x78, 0xFF, 0x53},\r
- {0x79, 0xFF, 0x3C},\r
- {0x7A, 0xFF, 0x89},\r
- {0x7B, 0xFF, 0x3E},\r
- {0x7C, 0xFF, 0x00},\r
- {0x7D, 0xFF, 0x08},\r
- {0x7E, 0xFF, 0x51},\r
- {0x7F, 0xFF, 0x0C},\r
- {0x80, 0xFF, 0x00},\r
- {0x81, 0xFF, 0x00},\r
- {0x82, 0xFF, 0x00},\r
- {0x83, 0xFF, 0x08},\r
- {0x84, 0xFF, 0x00},\r
- {0x85, 0xFF, 0x00},\r
- {0x86, 0xFF, 0x87},\r
- {0x87, 0xFF, 0x0E},\r
-#endif\r
- // 2012/12/20 added by Keming's suggestion test\r
- {0x88, 0xF0, 0x00},\r
- //~jauchih.tseng@ite.com.tw\r
- {0x04, 0x08, 0x00},\r
- {0,0,0}\r
-};\r
-_CODE RegSetEntry HDMITX_SetHDMI_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default HDMI Mode\r
- ////////////////////////////////////////////////////\r
- {0xC0, 0x01, 0x01},\r
- {0xC1, 0x03, 0x03},\r
- {0xC6, 0x03, 0x03},\r
- {0,0,0}\r
-};\r
-\r
-_CODE RegSetEntry HDMITX_SetDVI_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default HDMI Mode\r
- ////////////////////////////////////////////////////\r
- {0x0F, 0x01, 0x01},\r
- {0x58, 0xFF, 0x00},\r
- {0x0F, 0x01, 0x00},\r
- {0xC0, 0x01, 0x00},\r
- {0xC1, 0x03, 0x02},\r
- {0xC6, 0x03, 0x00},\r
- {0,0,0}\r
-};\r
-\r
-_CODE RegSetEntry HDMITX_DefaultAVIInfo_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default avi infoframe\r
- ////////////////////////////////////////////////////\r
- {0x0F, 0x01, 0x01},\r
- {0x58, 0xFF, 0x10},\r
- {0x59, 0xFF, 0x08},\r
- {0x5A, 0xFF, 0x00},\r
- {0x5B, 0xFF, 0x00},\r
- {0x5C, 0xFF, 0x00},\r
- {0x5D, 0xFF, 0x57},\r
- {0x5E, 0xFF, 0x00},\r
- {0x5F, 0xFF, 0x00},\r
- {0x60, 0xFF, 0x00},\r
- {0x61, 0xFF, 0x00},\r
- {0x62, 0xFF, 0x00},\r
- {0x63, 0xFF, 0x00},\r
- {0x64, 0xFF, 0x00},\r
- {0x65, 0xFF, 0x00},\r
- {0x0F, 0x01, 0x00},\r
- {0xCD, 0x03, 0x03},\r
- {0,0,0}\r
-};\r
-_CODE RegSetEntry HDMITX_DeaultAudioInfo_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default audio infoframe\r
- ////////////////////////////////////////////////////\r
- {0x0F, 0x01, 0x01},\r
- {0x68, 0xFF, 0x00},\r
- {0x69, 0xFF, 0x00},\r
- {0x6A, 0xFF, 0x00},\r
- {0x6B, 0xFF, 0x00},\r
- {0x6C, 0xFF, 0x00},\r
- {0x6D, 0xFF, 0x71},\r
- {0x0F, 0x01, 0x00},\r
- {0xCE, 0x03, 0x03},\r
-\r
- {0,0,0}\r
-};\r
-\r
-_CODE RegSetEntry HDMITX_Aud_CHStatus_LPCM_20bit_48Khz[] =\r
-{\r
- {0x0F, 0x01, 0x01},\r
- {0x33, 0xFF, 0x00},\r
- {0x34, 0xFF, 0x18},\r
- {0x35, 0xFF, 0x00},\r
- {0x91, 0xFF, 0x00},\r
- {0x92, 0xFF, 0x00},\r
- {0x93, 0xFF, 0x01},\r
- {0x94, 0xFF, 0x00},\r
- {0x98, 0xFF, 0x02},\r
- {0x99, 0xFF, 0xDA},\r
- {0x0F, 0x01, 0x00},\r
- {0,0,0}//end of table\r
-} ;\r
-\r
-_CODE RegSetEntry HDMITX_AUD_SPDIF_2ch_24bit[] =\r
-{\r
- {0x0F, 0x11, 0x00},\r
- {0x04, 0x14, 0x04},\r
- {0xE0, 0xFF, 0xD1},\r
- {0xE1, 0xFF, 0x01},\r
- {0xE2, 0xFF, 0xE4},\r
- {0xE3, 0xFF, 0x10},\r
- {0xE4, 0xFF, 0x00},\r
- {0xE5, 0xFF, 0x00},\r
- {0x04, 0x14, 0x00},\r
- {0,0,0}//end of table\r
-} ;\r
-\r
-_CODE RegSetEntry HDMITX_AUD_I2S_2ch_24bit[] =\r
-{\r
- {0x0F, 0x11, 0x00},\r
- {0x04, 0x14, 0x04},\r
- {0xE0, 0xFF, 0xC1},\r
- {0xE1, 0xFF, 0x01},\r
- {0xE2, 0xFF, 0xE4},\r
- {0xE3, 0xFF, 0x00},\r
- {0xE4, 0xFF, 0x00},\r
- {0xE5, 0xFF, 0x00},\r
- {0x04, 0x14, 0x00},\r
- {0,0,0}//end of table\r
-} ;\r
-\r
-_CODE RegSetEntry HDMITX_DefaultAudio_Table[] = {\r
-\r
- ////////////////////////////////////////////////////\r
- // Config default audio output format.\r
- ////////////////////////////////////////////////////\r
- {0x0F, 0x21, 0x00},\r
- {0x04, 0x14, 0x04},\r
- {0xE0, 0xFF, 0xC1},\r
- {0xE1, 0xFF, 0x01},\r
- {0xE2, 0xFF, 0xE4},\r
- {0xE3, 0xFF, 0x00},\r
- {0xE4, 0xFF, 0x00},\r
- {0xE5, 0xFF, 0x00},\r
- {0x0F, 0x01, 0x01},\r
- {0x33, 0xFF, 0x00},\r
- {0x34, 0xFF, 0x18},\r
- {0x35, 0xFF, 0x00},\r
- {0x91, 0xFF, 0x00},\r
- {0x92, 0xFF, 0x00},\r
- {0x93, 0xFF, 0x01},\r
- {0x94, 0xFF, 0x00},\r
- {0x98, 0xFF, 0x02},\r
- {0x99, 0xFF, 0xDB},\r
- {0x0F, 0x01, 0x00},\r
- {0x04, 0x14, 0x00},\r
-\r
- {0x00, 0x00, 0x00} // End of Table.\r
-} ;\r
-\r
-_CODE RegSetEntry HDMITX_PwrDown_Table[] = {\r
- // Enable GRCLK\r
- {0x0F, 0x40, 0x00},\r
- // PLL Reset\r
- {0x61, 0x10, 0x10}, // DRV_RST\r
- {0x62, 0x08, 0x00}, // XP_RESETB\r
- {0x64, 0x04, 0x00}, // IP_RESETB\r
- {0x01, 0x00, 0x00}, // idle(100);\r
-\r
- // PLL PwrDn\r
- {0x61, 0x20, 0x20}, // PwrDn DRV\r
- {0x62, 0x44, 0x44}, // PwrDn XPLL\r
- {0x64, 0x40, 0x40}, // PwrDn IPLL\r
-\r
- // HDMITX PwrDn\r
- {0x05, 0x01, 0x01}, // PwrDn PCLK\r
- {0x0F, 0x78, 0x78}, // PwrDn GRCLK\r
- {0x00, 0x00, 0x00} // End of Table.\r
-};\r
-\r
-_CODE RegSetEntry HDMITX_PwrOn_Table[] = {\r
- {0x0F, 0x78, 0x38}, // PwrOn GRCLK\r
- {0x05, 0x01, 0x00}, // PwrOn PCLK\r
-\r
- // PLL PwrOn\r
- {0x61, 0x20, 0x00}, // PwrOn DRV\r
- {0x62, 0x44, 0x00}, // PwrOn XPLL\r
- {0x64, 0x40, 0x00}, // PwrOn IPLL\r
-\r
- // PLL Reset OFF\r
- {0x61, 0x10, 0x00}, // DRV_RST\r
- {0x62, 0x08, 0x08}, // XP_RESETB\r
- {0x64, 0x04, 0x04}, // IP_RESETB\r
- {0x0F, 0x78, 0x08}, // PwrOn IACLK\r
- {0x00, 0x00, 0x00} // End of Table.\r
-};\r
-\r
-#ifdef DETECT_VSYNC_CHG_IN_SAV\r
-BOOL EnSavVSync = FALSE ;\r
-#endif\r
-static bool PowerStatus=FALSE;\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function Prototype\r
-//////////////////////////////////////////////////////////////////////\r
-void hdmitx_LoadRegSetting(RegSetEntry table[]);\r
-\r
-void HDMITX_InitTxDev(HDMITXDEV *pInstance)\r
-{\r
- if(pInstance && 0 < HDMITX_MAX_DEV_COUNT)\r
- {\r
- hdmiTxDev[0] = *pInstance ;\r
- }\r
-}\r
-\r
-void InitHDMITX()\r
-{\r
- hdmitx_LoadRegSetting(HDMITX_Init_Table);\r
-// HDMITX_WriteI2C_Byte(REG_TX_PLL_CTRL,0xff);\r
- hdmiTxDev[0].bIntPOL = (hdmiTxDev[0].bIntType&B_TX_INTPOL_ACTH)?TRUE:FALSE ;\r
-\r
- // Avoid power loading in un play status.\r
- //////////////////////////////////////////////////////////////////\r
- // Setup HDCP ROM\r
- //////////////////////////////////////////////////////////////////\r
-#ifdef HDMITX_INPUT_INFO\r
- hdmiTxDev[0].RCLK = CalcRCLK();\r
-#endif\r
- hdmitx_LoadRegSetting(HDMITX_DefaultVideo_Table);\r
- hdmitx_LoadRegSetting(HDMITX_SetHDMI_Table);\r
- hdmitx_LoadRegSetting(HDMITX_DefaultAVIInfo_Table);\r
- hdmitx_LoadRegSetting(HDMITX_DeaultAudioInfo_Table);\r
- hdmitx_LoadRegSetting(HDMITX_Aud_CHStatus_LPCM_20bit_48Khz);\r
- hdmitx_LoadRegSetting(HDMITX_AUD_SPDIF_2ch_24bit);\r
- HDMITX_PowerDown();\r
-\r
- HDMITX_DEBUG_PRINTF((\r
- "-----------------------------------------------------\n"\r
- "Init HDMITX\n"\r
- "-----------------------------------------------------\n"));\r
-\r
- DumpHDMITXReg();\r
-}\r
-\r
-BOOL getHDMITX_LinkStatus()\r
-{\r
- if(B_TX_RXSENDETECT & HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS))\r
- {\r
- if(0==HDMITX_ReadI2C_Byte(REG_TX_AFE_DRV_CTRL))\r
- {\r
- //HDMITX_DEBUG_PRINTF(("getHDMITX_LinkStatus()!!\n") );\r
- return TRUE;\r
- }\r
- }\r
- //HDMITX_DEBUG_PRINTF(("GetTMDS not Ready()!!\n") );\r
-\r
- return FALSE;\r
-}\r
-\r
-#if 0\r
-BYTE CheckHDMITX(BYTE *pHPD,BYTE *pHPDChange)\r
-{\r
- BYTE intdata1,intdata2,intdata3,sysstat;\r
- BYTE intclr3 = 0 ;\r
- BYTE PrevHPD = hdmiTxDev[0].bHPD ;\r
- BYTE HPD ;\r
- sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);\r
- // HDMITX_DEBUG_PRINTF(("REG_TX_SYS_STATUS = %X \n",sysstat));\r
-\r
- if((sysstat & (B_TX_HPDETECT/*|B_TX_RXSENDETECT*/)) == (B_TX_HPDETECT/*|B_TX_RXSENDETECT*/))\r
- {\r
- HPD = TRUE;\r
- }\r
- else\r
- {\r
- HPD = FALSE;\r
- }\r
- // CheckClockStable(sysstat);\r
- // 2007/06/20 added by jj_tseng@chipadvanced.com\r
-\r
- if(pHPDChange)\r
- {\r
- *pHPDChange = (HPD!=PrevHPD)?TRUE:FALSE ; // default give pHPDChange value compared to previous HPD value.\r
-\r
- }\r
- //~jj_tseng@chipadvanced.com 2007/06/20\r
-\r
- if(HPD==FALSE)\r
- {\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
- }\r
- if(sysstat & B_TX_INT_ACTIVE)\r
- {\r
- HDMITX_DEBUG_PRINTF(("REG_TX_SYS_STATUS = 0x%02X \n",(int)sysstat));\r
-\r
- intdata1 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1);\r
- HDMITX_DEBUG_PRINTF(("INT_Handler: reg%X = %X\n",(int)REG_TX_INT_STAT1,(int)intdata1));\r
- if(intdata1 & B_TX_INT_AUD_OVERFLOW)\r
- {\r
- HDMITX_DEBUG_PRINTF(("B_TX_INT_AUD_OVERFLOW.\n"));\r
- HDMITX_OrReg_Byte(REG_TX_SW_RST,(B_HDMITX_AUD_RST|B_TX_AREF_RST));\r
- HDMITX_AndReg_Byte(REG_TX_SW_RST,~(B_HDMITX_AUD_RST|B_TX_AREF_RST));\r
- //AudioDelayCnt=AudioOutDelayCnt;\r
- //LastRefaudfreqnum=0;\r
- }\r
- if(intdata1 & B_TX_INT_DDCFIFO_ERR)\r
- {\r
- HDMITX_DEBUG_PRINTF(("DDC FIFO Error.\n"));\r
- hdmitx_ClearDDCFIFO();\r
- hdmiTxDev[0].bAuthenticated= FALSE ;\r
- }\r
- if(intdata1 & B_TX_INT_DDC_BUS_HANG)\r
- {\r
- HDMITX_DEBUG_PRINTF(("DDC BUS HANG.\n"));\r
- hdmitx_AbortDDC();\r
-\r
- if(hdmiTxDev[0].bAuthenticated)\r
- {\r
- HDMITX_DEBUG_PRINTF(("when DDC hang,and aborted DDC,the HDCP authentication need to restart.\n"));\r
- #ifdef SUPPORT_HDCP\r
- hdmitx_hdcp_ResumeAuthentication();\r
- #endif\r
- }\r
- }\r
- if(intdata1 & (B_TX_INT_HPD_PLUG/*|B_TX_INT_RX_SENSE*/))\r
- {\r
-\r
- if(pHPDChange)\r
- {\r
- *pHPDChange = TRUE ;\r
- }\r
- if(HPD == FALSE)\r
- {\r
- /*\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_TX_AREF_RST|B_HDMITX_VID_RST|B_HDMITX_AUD_RST|B_TX_HDCP_RST_HDMITX);\r
- delay1ms(1);\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_TX_AFE_DRV_RST|B_TX_AFE_DRV_PWD);\r
- */\r
- //HDMITX_DEBUG_PRINTF(("Unplug,%x %x\n",(int)HDMITX_ReadI2C_Byte(REG_TX_SW_RST),(int)HDMITX_ReadI2C_Byte(REG_TX_AFE_DRV_CTRL)));\r
- }\r
- }\r
- if(intdata1 & (B_TX_INT_RX_SENSE))\r
- {\r
- hdmiTxDev[0].bAuthenticated = FALSE;\r
- }\r
- intdata2 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2);\r
- HDMITX_DEBUG_PRINTF(("INT_Handler: reg%X = %X\n",(int)REG_TX_INT_STAT2,(int)intdata2));\r
-\r
- #ifdef SUPPORT_HDCP\r
- if(intdata2 & B_TX_INT_AUTH_DONE)\r
- {\r
- HDMITX_DEBUG_PRINTF(("interrupt Authenticate Done.\n"));\r
- HDMITX_OrReg_Byte(REG_TX_INT_MASK2,(BYTE)B_TX_AUTH_DONE_MASK);\r
- //hdmiTxDev[0].bAuthenticated = TRUE ;\r
- //setHDMITX_AVMute(FALSE);\r
- }\r
- if(intdata2 & B_TX_INT_AUTH_FAIL)\r
- {\r
- hdmiTxDev[0].bAuthenticated = FALSE;\r
- //HDMITX_DEBUG_PRINTF(("interrupt Authenticate Fail.\n"));\r
- hdmitx_AbortDDC(); // @emily add\r
- //hdmitx_hdcp_ResumeAuthentication();\r
- }\r
- #endif // SUPPORT_HDCP\r
-\r
-#if 1\r
- intdata3 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT3);\r
- HDMITX_DEBUG_PRINTF(("INT_Handler: reg%X = %X\n",(int)REG_TX_INT_STAT3,(int)intdata3));\r
- if(intdata3 & B_TX_INT_VIDSTABLE)\r
- {\r
- sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS);\r
- if(sysstat & B_TXVIDSTABLE)\r
- {\r
- hdmitx_FireAFE();\r
- }\r
- }\r
-#endif\r
- intdata3= HDMITX_ReadI2C_Byte(0xEE);\r
- if( intdata3 )\r
- {\r
- HDMITX_WriteI2C_Byte(0xEE,intdata3); // clear ext interrupt ;\r
- HDMITX_DEBUG_PRINTF(("%s%s%s%s%s%s%s\n",\r
- (intdata3&0x40)?"video parameter change \n":"",\r
- (intdata3&0x20)?"HDCP Pj check done \n":"",\r
- (intdata3&0x10)?"HDCP Ri check done \n":"",\r
- (intdata3&0x8)? "DDC bus hang \n":"",\r
- (intdata3&0x4)? "Video input FIFO auto reset \n":"",\r
- (intdata3&0x2)? "No audio input interrupt \n":"",\r
- (intdata3&0x1)? "Audio decode error interrupt \n":""));\r
- }\r
-\r
- intclr3 = (HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS))|B_TX_CLR_AUD_CTS | B_TX_INTACTDONE ;\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3); // clear interrupt.\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0xFF);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0xFF);\r
- intclr3 &= ~(B_TX_INTACTDONE);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3); // INTACTDONE reset to zero.\r
- }\r
- //\r
- // else\r
- // {\r
- // if(pHPDChange)\r
- // {\r
- // if(HPD != PrevHPD)\r
- // {\r
- // *pHPDChange = TRUE;\r
- // }\r
- // else\r
- // {\r
- // *pHPDChange = FALSE;\r
- // }\r
- // }\r
- // }\r
- if(pHPDChange)\r
- {\r
- if((*pHPDChange==TRUE) &&(HPD==FALSE))\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_TX_AFE_DRV_RST|B_TX_AFE_DRV_PWD);\r
- }\r
- }\r
- if(pHPD)\r
- {\r
- *pHPD = HPD ;\r
- }\r
- hdmiTxDev[0].bHPD = HPD ;\r
- return HPD ;\r
-}\r
-#endif\r
-void HDMITX_PowerOn()\r
-{\r
- PowerStatus = TRUE;\r
- hdmitx_LoadRegSetting(HDMITX_PwrOn_Table);\r
-}\r
-\r
-void HDMITX_PowerDown()\r
-{\r
- PowerStatus = FALSE;\r
- hdmitx_LoadRegSetting(HDMITX_PwrDown_Table);\r
-}\r
-BOOL getHDMI_PowerStatus()\r
-{\r
- return PowerStatus;\r
-}\r
-\r
-void setHDMITX_AVMute(BYTE bEnable)\r
-{\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_SetI2C_Byte(REG_TX_GCP,B_TX_SETAVMUTE, bEnable?B_TX_SETAVMUTE:0 );\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_LoadRegSetting()\r
-// Input: RegSetEntry SettingTable[] ;\r
-// Return: N/A\r
-// Remark: if an entry {0, 0, 0} will be terminated.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_LoadRegSetting(RegSetEntry table[])\r
-{\r
- int i ;\r
-\r
- for( i = 0 ; ; i++ )\r
- {\r
- if( table[i].offset == 0 && table[i].invAndMask == 0 && table[i].OrMask == 0 )\r
- {\r
- return ;\r
- }\r
- else if( table[i].invAndMask == 0 && table[i].OrMask == 0 )\r
- {\r
- HDMITX_DEBUG_PRINTF2(("delay(%d)\n",(int)table[i].offset));\r
- delay1ms(table[i].offset);\r
- }\r
- else if( table[i].invAndMask == 0xFF )\r
- {\r
- HDMITX_DEBUG_PRINTF2(("HDMITX_WriteI2C_Byte(%02x,%02x)\n",(int)table[i].offset,(int)table[i].OrMask));\r
- HDMITX_WriteI2C_Byte(table[i].offset,table[i].OrMask);\r
- }\r
- else\r
- {\r
- HDMITX_DEBUG_PRINTF2(("HDMITX_SetI2C_Byte(%02x,%02x,%02x)\n",(int)table[i].offset,(int)table[i].invAndMask,(int)table[i].OrMask));\r
- HDMITX_SetI2C_Byte(table[i].offset,table[i].invAndMask,table[i].OrMask);\r
- }\r
- }\r
-}\r
-\r
-///*****************************************\r
-// @file <hdmitx_ddc.c>\r
-//******************************************/\r
-\r
-BOOL getHDMITX_EDIDBlock(int EDIDBlockID,BYTE *pEDIDData)\r
-{\r
- if(!pEDIDData)\r
- {\r
- return FALSE ;\r
- }\r
- if(getHDMITX_EDIDBytes(pEDIDData,EDIDBlockID/2,(EDIDBlockID%2)*128,128) == ER_FAIL)\r
- {\r
- return FALSE ;\r
- }\r
-#if Debug_message\r
- {\r
- int j=0;\r
- EDID_DEBUG_PRINTF(("------BlockID=%d------\n",EDIDBlockID));\r
- for( j = 0 ; j < 128 ; j++ )\r
- {\r
- EDID_DEBUG_PRINTF(("%02X%c",(int)pEDIDData[j],(7 == (j&7))?'\n':' '));\r
- }\r
- }\r
-#endif\r
- return TRUE ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: getHDMITX_EDIDBytes\r
-// Parameter: pData - the pointer of buffer to receive EDID ucdata.\r
-// bSegment - the segment of EDID readback.\r
-// offset - the offset of EDID ucdata in the segment. in byte.\r
-// count - the read back bytes count,cannot exceed 32\r
-// Return: ER_SUCCESS if successfully getting EDID. ER_FAIL otherwise.\r
-// Remark: function for read EDID ucdata from reciever.\r
-// Side-Effect: DDC master will set to be HOST. DDC FIFO will be used and dirty.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS getHDMITX_EDIDBytes(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count)\r
-{\r
- SHORT RemainedCount,ReqCount ;\r
- BYTE bCurrOffset ;\r
- SHORT TimeOut ;\r
- BYTE *pBuff = pData ;\r
- BYTE ucdata ;\r
-\r
- // HDMITX_DEBUG_PRINTF(("getHDMITX_EDIDBytes(%08lX,%d,%d,%d)\n",(ULONG)pData,(int)bSegment,(int)offset,(int)Count));\r
- if(!pData)\r
- {\r
-// HDMITX_DEBUG_PRINTF(("getHDMITX_EDIDBytes(): Invallid pData pointer %08lX\n",(ULONG)pData));\r
- return ER_FAIL ;\r
- }\r
- if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_TX_INT_DDC_BUS_HANG)\r
- {\r
- HDMITX_DEBUG_PRINTF(("Called hdmitx_AboutDDC()\n"));\r
- hdmitx_AbortDDC();\r
-\r
- }\r
- // HDMITX_OrReg_Byte(REG_TX_INT_CTRL,(1<<1));\r
-\r
- hdmitx_ClearDDCFIFO();\r
-\r
- RemainedCount = Count ;\r
- bCurrOffset = offset ;\r
-\r
- Switch_HDMITX_Bank(0);\r
-\r
- while(RemainedCount > 0)\r
- {\r
-\r
- ReqCount = (RemainedCount > DDC_FIFO_MAXREQ)?DDC_FIFO_MAXREQ:RemainedCount ;\r
- HDMITX_DEBUG_PRINTF(("getHDMITX_EDIDBytes(): ReqCount = %d,bCurrOffset = %d\n",(int)ReqCount,(int)bCurrOffset));\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR);\r
-\r
- for(TimeOut = 0 ; TimeOut < 200 ; TimeOut++)\r
- {\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
-\r
- if(ucdata&B_TX_DDC_DONE)\r
- {\r
- break ;\r
- }\r
- if((ucdata & B_TX_DDC_ERROR)||(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_TX_INT_DDC_BUS_HANG))\r
- {\r
- HDMITX_DEBUG_PRINTF(("Called hdmitx_AboutDDC()\n"));\r
- hdmitx_AbortDDC();\r
- return ER_FAIL ;\r
- }\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_EDID_ADDRESS); // for EDID ucdata get\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,bCurrOffset);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,(BYTE)ReqCount);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_EDIDSEG,bSegment);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_EDID_READ);\r
-\r
- bCurrOffset += ReqCount ;\r
- RemainedCount -= ReqCount ;\r
-\r
- for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- delay1ms(1);\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
- if(ucdata & B_TX_DDC_DONE)\r
- {\r
- break ;\r
- }\r
- if(ucdata & B_TX_DDC_ERROR)\r
- {\r
- HDMITX_DEBUG_PRINTF(("getHDMITX_EDIDBytes(): DDC_STATUS = %02X,fail.\n",(int)ucdata));\r
- // HDMITX_AndReg_Byte(REG_TX_INT_CTRL,~(1<<1));\r
- return ER_FAIL ;\r
- }\r
- }\r
- if(TimeOut == 0)\r
- {\r
- HDMITX_DEBUG_PRINTF(("getHDMITX_EDIDBytes(): DDC TimeOut %d . \n",(int)ucdata));\r
- // HDMITX_AndReg_Byte(REG_TX_INT_CTRL,~(1<<1));\r
- return ER_FAIL ;\r
- }\r
- do\r
- {\r
- *(pBuff++) = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO);\r
- ReqCount -- ;\r
- }while(ReqCount > 0);\r
-\r
- }\r
- // HDMITX_AndReg_Byte(REG_TX_INT_CTRL,~(1<<1));\r
- return ER_SUCCESS ;\r
-}\r
-\r
-/////////////////////////////\r
-// DDC Function.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_ClearDDCFIFO\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: clear the DDC FIFO.\r
-// Side-Effect: DDC master will set to be HOST.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_ClearDDCFIFO()\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR);\r
-}\r
-\r
-void hdmitx_GenerateDDCSCLK()\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_GEN_SCLCLK);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_AbortDDC\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: Force abort DDC and reset DDC bus.\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_AbortDDC()\r
-{\r
- BYTE CPDesire,SWReset,DDCMaster ;\r
- BYTE uc, timeout, i ;\r
- // save the SW reset,DDC master,and CP Desire setting.\r
- SWReset = HDMITX_ReadI2C_Byte(REG_TX_SW_RST);\r
- CPDesire = HDMITX_ReadI2C_Byte(REG_TX_HDCP_DESIRE);\r
- DDCMaster = HDMITX_ReadI2C_Byte(REG_TX_DDC_MASTER_CTRL);\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,CPDesire&(~B_TX_CPDESIRE)); // @emily change order\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST,SWReset|B_TX_HDCP_RST_HDMITX); // @emily change order\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
-\r
- // 2009/01/15 modified by Jau-Chih.Tseng@ite.com.tw\r
- // do abort DDC twice.\r
- for( i = 0 ; i < 2 ; i++ )\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_ABORT);\r
-\r
- for( timeout = 0 ; timeout < 200 ; timeout++ )\r
- {\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
- if (uc&B_TX_DDC_DONE)\r
- {\r
- break ; // success\r
- }\r
- if( uc & (B_TX_DDC_NOACK|B_TX_DDC_WAITBUS|B_TX_DDC_ARBILOSE) )\r
- {\r
-// HDMITX_DEBUG_PRINTF(("hdmitx_AbortDDC Fail by reg16=%02X\n",(int)uc));\r
- break ;\r
- }\r
- delay1ms(1); // delay 1 ms to stable.\r
- }\r
- }\r
- //~Jau-Chih.Tseng@ite.com.tw\r
-\r
-}\r
-\r
-///*****************************************\r
-// @file <hdmitx_vid.c>\r
-//******************************************/\r
-\r
-extern HDMITXDEV hdmiTxDev[HDMITX_MAX_DEV_COUNT] ;\r
-\r
-void WaitTxVidStable(void);\r
-void hdmitx_SetInputMode(BYTE InputMode,BYTE bInputSignalType);\r
-void hdmitx_SetCSCScale(BYTE bInputMode,BYTE bOutputMode);\r
-void hdmitx_SetupAFE(VIDEOPCLKLEVEL PCLKLevel);\r
-void hdmitx_FireAFE(void);\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// utility function for main..\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#ifndef DISABLE_HDMITX_CSC\r
- #if (defined (SUPPORT_OUTPUTYUV)) && (defined (SUPPORT_INPUTRGB))\r
- extern _CODE BYTE bCSCMtx_RGB2YUV_ITU601_16_235[] ;\r
- extern _CODE BYTE bCSCMtx_RGB2YUV_ITU601_0_255[] ;\r
- extern _CODE BYTE bCSCMtx_RGB2YUV_ITU709_16_235[] ;\r
- extern _CODE BYTE bCSCMtx_RGB2YUV_ITU709_0_255[] ;\r
- #endif\r
-\r
- #if (defined (SUPPORT_OUTPUTRGB)) && (defined (SUPPORT_INPUTYUV))\r
- extern _CODE BYTE bCSCMtx_YUV2RGB_ITU601_16_235[] ;\r
- extern _CODE BYTE bCSCMtx_YUV2RGB_ITU601_0_255[] ;\r
- extern _CODE BYTE bCSCMtx_YUV2RGB_ITU709_16_235[] ;\r
- extern _CODE BYTE bCSCMtx_YUV2RGB_ITU709_0_255[] ;\r
-\r
- #endif\r
-#endif// DISABLE_HDMITX_CSC\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function Body.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void HDMITX_DisableVideoOutput()\r
-{\r
- BYTE uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_HDMITX_VID_RST ;\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc);\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_TX_AFE_DRV_RST|B_TX_AFE_DRV_PWD);\r
- HDMITX_SetI2C_Byte(0x62, 0x90, 0x00);\r
- HDMITX_SetI2C_Byte(0x64, 0x89, 0x00);\r
-}\r
-\r
-BOOL HDMITX_EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI)\r
-{\r
- // bInputVideoMode,bOutputVideoMode,hdmiTxDev[0].bInputVideoSignalType,bAudioInputType,should be configured by upper F/W or loaded from EEPROM.\r
- // should be configured by initsys.c\r
- // VIDEOPCLKLEVEL level ;\r
- switch(level)\r
- {\r
- case PCLK_HIGH:\r
- HDMITX_WriteI2C_Byte(REG_TX_PLL_CTRL,0x30 /*0xff*/);\r
- break ;\r
- default:\r
- HDMITX_WriteI2C_Byte(REG_TX_PLL_CTRL,0x00);\r
- break ;\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_HDMITX_VID_RST|B_HDMITX_AUD_RST|B_TX_AREF_RST|B_TX_HDCP_RST_HDMITX);\r
-\r
- hdmiTxDev[0].bHDMIMode = (BYTE)bHDMI ;\r
- // 2009/12/09 added by jau-chih.tseng@ite.com.tw\r
- Switch_HDMITX_Bank(1);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB1,0x00);\r
- Switch_HDMITX_Bank(0);\r
- //~jau-chih.tseng@ite.com.tw\r
-\r
- if(hdmiTxDev[0].bHDMIMode)\r
- {\r
- setHDMITX_AVMute(TRUE);\r
- }\r
- hdmitx_SetInputMode(inputColorMode,hdmiTxDev[0].bInputVideoSignalType);\r
-\r
- hdmitx_SetCSCScale(inputColorMode,outputColorMode);\r
-\r
- if(hdmiTxDev[0].bHDMIMode)\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_HDMI_MODE);\r
- }\r
- else\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_DVI_MODE);\r
- }\r
-#ifdef INVERT_VID_LATCHEDGE\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1);\r
- uc |= B_TX_VDO_LATCH_EDGE ;\r
- HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, uc);\r
-#endif\r
-\r
- hdmitx_SetupAFE(level); // pass if High Freq request\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST, B_HDMITX_AUD_RST|B_TX_AREF_RST|B_TX_HDCP_RST_HDMITX);\r
-\r
- hdmitx_FireAFE();\r
-\r
- return TRUE ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// export this for dynamic change input signal\r
-//////////////////////////////////////////////////////////////////////\r
-BOOL setHDMITX_VideoSignalType(BYTE inputSignalType)\r
-{\r
- hdmiTxDev[0].bInputVideoSignalType = inputSignalType ;\r
- // hdmitx_SetInputMode(inputColorMode,hdmiTxDev[0].bInputVideoSignalType);\r
- return TRUE ;\r
-}\r
-\r
-void WaitTxVidStable()\r
-{\r
-#if 0\r
- BYTE i ;\r
- for( i = 0 ; i < 20 ; i++ )\r
- {\r
- delay1ms(15);\r
- if((HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) == 0 )\r
- {\r
- continue ;\r
- }\r
- delay1ms(15);\r
- if((HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) == 0 )\r
- {\r
- continue ;\r
- }\r
- delay1ms(15);\r
- if((HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) == 0 )\r
- {\r
- continue ;\r
- }\r
- delay1ms(15);\r
- if((HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) == 0 )\r
- {\r
- continue ;\r
- }\r
- break ;\r
- }\r
-#endif\r
-}\r
-// void CheckClockStable(BYTE SystemStat)\r
-// {\r
-// static BYTE Stablecnt=20;\r
-// if(0==(SystemStat&B_TXVIDSTABLE))\r
-// {\r
-// if(0==Stablecnt--)\r
-// {\r
-// HDMITX_ToggleBit(0x59,3);\r
-// Stablecnt=20;\r
-// }\r
-// }\r
-// else\r
-// {\r
-// Stablecnt=20;\r
-// }\r
-// }\r
-\r
-void setHDMITX_ColorDepthPhase(BYTE ColorDepth,BYTE bPhase)\r
-{\r
-#ifdef IT6615\r
- BYTE uc ;\r
- BYTE bColorDepth ;\r
-\r
- if(ColorDepth == 30)\r
- {\r
- bColorDepth = B_TX_CD_30 ;\r
- HDMITX_DEBUG_PRINTF(("bColorDepth = B_TX_CD_30\n"));\r
- }\r
- else if (ColorDepth == 36)\r
- {\r
- bColorDepth = B_TX_CD_36 ;\r
- HDMITX_DEBUG_PRINTF(("bColorDepth = B_TX_CD_36\n"));\r
- }\r
- /*\r
- else if (ColorDepth == 24)\r
- {\r
- bColorDepth = B_TX_CD_24 ;\r
- //bColorDepth = 0 ;//modify JJ by mail 20100423 1800 // not indicated\r
- }\r
- */\r
- else\r
- {\r
- bColorDepth = 0 ; // not indicated\r
- }\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_SetI2C_Byte(REG_TX_GCP,B_TX_COLOR_DEPTH_MASK ,bColorDepth);\r
- HDMITX_DEBUG_PRINTF(("setHDMITX_ColorDepthPhase(%02X), regC1 = %02X\n",(int)bColorDepth,(int)HDMITX_ReadI2C_Byte(REG_TX_GCP))) ;\r
-#endif\r
-}\r
-\r
-#ifdef SUPPORT_SYNCEMBEDDED\r
-\r
-struct CRT_TimingSetting {\r
- BYTE fmt;\r
- WORD HActive;\r
- WORD VActive;\r
- WORD HTotal;\r
- WORD VTotal;\r
- WORD H_FBH;\r
- WORD H_SyncW;\r
- WORD H_BBH;\r
- WORD V_FBH;\r
- WORD V_SyncW;\r
- WORD V_BBH;\r
- BYTE Scan:1;\r
- BYTE VPolarity:1;\r
- BYTE HPolarity:1;\r
-};\r
-\r
-// VDEE_L, VDEE_H, VRS2S_L, VRS2S_H, VRS2E_L, VRS2E_H, HalfL_L, HalfL_H, VDE2S_L, VDE2S_H, HVP&Progress\r
-_CODE struct CRT_TimingSetting TimingTable[] =\r
-{\r
- // VIC H V HTotal VTotal HFT HSW HBP VF VSW VB\r
- { 1, 640, 480, 800, 525, 16, 96, 48, 10, 2, 33, PROG, Vneg, Hneg},// 640x480@60Hz - CEA Mode [ 1]\r
- { 2, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@60Hz - CEA Mode [ 2]\r
- { 3, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@60Hz - CEA Mode [ 3]\r
- { 4, 1280, 720, 1650, 750, 110, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@60Hz - CEA Mode [ 4]\r
- { 5, 1920, 540, 2200, 562, 88, 44, 148, 2, 5, 15, INTERLACE, Vpos, Hpos},// 1920x1080(I)@60Hz - CEA Mode [ 5]\r
- { 6, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [ 6]\r
- { 7, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [ 7]\r
- // { 8, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, PROG, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [ 8]\r
- // { 9, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, PROG, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [ 9]\r
- // { 10, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [10]\r
- // { 11, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [11]\r
- // { 12, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, PROG, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [12]\r
- // { 13, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, PROG, Vneg, Hneg},// 720x480(I)@60Hz - CEA Mode [13]\r
- // { 14, 1440, 480, 1716, 525, 32, 124, 120, 9, 6, 30, PROG, Vneg, Hneg},// 1440x480@60Hz - CEA Mode [14]\r
- // { 15, 1440, 480, 1716, 525, 32, 124, 120, 9, 6, 30, PROG, Vneg, Hneg},// 1440x480@60Hz - CEA Mode [15]\r
- { 16, 1920, 1080, 2200, 1125, 88, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@60Hz - CEA Mode [16]\r
- { 17, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@50Hz - CEA Mode [17]\r
- { 18, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@50Hz - CEA Mode [18]\r
- { 19, 1280, 720, 1980, 750, 440, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@50Hz - CEA Mode [19]\r
- { 20, 1920, 540, 2640, 562, 528, 44, 148, 2, 5, 15, INTERLACE, Vpos, Hpos},// 1920x1080(I)@50Hz - CEA Mode [20]\r
- { 21, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@50Hz - CEA Mode [21]\r
- { 22, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@50Hz - CEA Mode [22]\r
- // { 23, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, PROG, Vneg, Hneg},// 1440x288@50Hz - CEA Mode [23]\r
- // { 24, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, PROG, Vneg, Hneg},// 1440x288@50Hz - CEA Mode [24]\r
- // { 25, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@50Hz - CEA Mode [25]\r
- // { 26, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@50Hz - CEA Mode [26]\r
- // { 27, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, PROG, Vneg, Hneg},// 1440x288@50Hz - CEA Mode [27]\r
- // { 28, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, PROG, Vneg, Hneg},// 1440x288@50Hz - CEA Mode [28]\r
- // { 29, 1440, 576, 1728, 625, 24, 128, 136, 5, 5, 39, PROG, Vpos, Hneg},// 1440x576@50Hz - CEA Mode [29]\r
- // { 30, 1440, 576, 1728, 625, 24, 128, 136, 5, 5, 39, PROG, Vpos, Hneg},// 1440x576@50Hz - CEA Mode [30]\r
- { 31, 1920, 1080, 2640, 1125, 528, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@50Hz - CEA Mode [31]\r
- { 32, 1920, 1080, 2750, 1125, 638, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@24Hz - CEA Mode [32]\r
- { 33, 1920, 1080, 2640, 1125, 528, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@25Hz - CEA Mode [33]\r
- { 34, 1920, 1080, 2200, 1125, 88, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@30Hz - CEA Mode [34]\r
- // { 35, 2880, 480, 1716*2, 525, 32*2, 124*2, 120*2, 9, 6, 30, PROG, Vneg, Hneg},// 2880x480@60Hz - CEA Mode [35]\r
- // { 36, 2880, 480, 1716*2, 525, 32*2, 124*2, 120*2, 9, 6, 30, PROG, Vneg, Hneg},// 2880x480@60Hz - CEA Mode [36]\r
- // { 37, 2880, 576, 3456, 625, 24*2, 128*2, 136*2, 5, 5, 39, PROG, Vneg, Hneg},// 2880x576@50Hz - CEA Mode [37]\r
- // { 38, 2880, 576, 3456, 625, 24*2, 128*2, 136*2, 5, 5, 39, PROG, Vneg, Hneg},// 2880x576@50Hz - CEA Mode [38]\r
- // { 39, 1920, 540, 2304, 625, 32, 168, 184, 23, 5, 57, INTERLACE, Vneg, Hpos},// 1920x1080@50Hz - CEA Mode [39]\r
- // { 40, 1920, 540, 2640, 562, 528, 44, 148, 2, 5, 15, INTERLACE, Vpos, Hpos},// 1920x1080(I)@100Hz - CEA Mode [40]\r
- // { 41, 1280, 720, 1980, 750, 440, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@100Hz - CEA Mode [41]\r
- // { 42, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@100Hz - CEA Mode [42]\r
- // { 43, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@100Hz - CEA Mode [43]\r
- // { 44, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@100Hz - CEA Mode [44]\r
- // { 45, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@100Hz - CEA Mode [45]\r
- // { 46, 1920, 540, 2200, 562, 88, 44, 148, 2, 5, 15, INTERLACE, Vpos, Hpos},// 1920x1080(I)@120Hz - CEA Mode [46]\r
- // { 47, 1280, 720, 1650, 750, 110, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@120Hz - CEA Mode [47]\r
- // { 48, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@120Hz - CEA Mode [48]\r
- // { 49, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@120Hz - CEA Mode [49]\r
- // { 50, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@120Hz - CEA Mode [50]\r
- // { 51, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@120Hz - CEA Mode [51]\r
- // { 52, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@200Hz - CEA Mode [52]\r
- // { 53, 720, 576, 864, 625, 12, 64, 68, 5, 5, 39, PROG, Vneg, Hneg},// 720x576@200Hz - CEA Mode [53]\r
- // { 54, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@200Hz - CEA Mode [54]\r
- // { 55, 720, 288, 864, 312, 12, 63, 69, 2, 3, 19, INTERLACE, Vneg, Hneg},// 1440x576(I)@200Hz - CEA Mode [55]\r
- // { 56, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@120Hz - CEA Mode [56]\r
- // { 57, 720, 480, 858, 525, 16, 62, 60, 9, 6, 30, PROG, Vneg, Hneg},// 720x480@120Hz - CEA Mode [57]\r
- // { 58, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@120Hz - CEA Mode [58]\r
- // { 59, 720, 240, 858, 262, 19, 62, 57, 4, 3, 15, INTERLACE, Vneg, Hneg},// 720x480(I)@120Hz - CEA Mode [59]\r
- { 60, 1280, 720, 3300, 750, 1760, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@24Hz - CEA Mode [60]\r
- { 61, 1280, 720, 3960, 750, 2420, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@25Hz - CEA Mode [61]\r
- { 62, 1280, 720, 3300, 750, 1760, 40, 220, 5, 5, 20, PROG, Vpos, Hpos},// 1280x720@30Hz - CEA Mode [62]\r
- // { 63, 1920, 1080, 2200, 1125, 88, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@120Hz - CEA Mode [63]\r
- // { 64, 1920, 1080, 2640, 1125, 528, 44, 148, 4, 5, 36, PROG, Vpos, Hpos},// 1920x1080@100Hz - CEA Mode [64]\r
-};\r
-\r
-#define MaxIndex (sizeof(TimingTable)/sizeof(struct CRT_TimingSetting))\r
-BOOL setHDMITX_SyncEmbeddedByVIC(BYTE VIC,BYTE bInputType)\r
-{\r
- int i ;\r
- BYTE fmt_index=0;\r
-\r
- // if Embedded Video,need to generate timing with pattern register\r
- Switch_HDMITX_Bank(0);\r
-\r
- HDMITX_DEBUG_PRINTF(("setHDMITX_SyncEmbeddedByVIC(%d,%x)\n",(int)VIC,(int)bInputType));\r
- if( VIC > 0 )\r
- {\r
- for(i=0;i< MaxIndex;i ++)\r
- {\r
- if(TimingTable[i].fmt==VIC)\r
- {\r
- fmt_index=i;\r
- HDMITX_DEBUG_PRINTF(("fmt_index=%02x)\n",(int)fmt_index));\r
- HDMITX_DEBUG_PRINTF(("***Fine Match Table ***\n"));\r
- break;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- HDMITX_DEBUG_PRINTF(("***No Match VIC == 0 ***\n"));\r
- return FALSE ;\r
- }\r
-\r
- if(i>=MaxIndex)\r
- {\r
- //return FALSE;\r
- HDMITX_DEBUG_PRINTF(("***No Match VIC ***\n"));\r
- return FALSE ;\r
- }\r
- //if( bInputSignalType & T_MODE_SYNCEMB )\r
- {\r
- int HTotal, HDES, VTotal, VDES;\r
- int HDEW, VDEW, HFP, HSW, VFP, VSW;\r
- int HRS, HRE;\r
- int VRS, VRE;\r
- int H2ndVRRise;\r
- int VRS2nd, VRE2nd;\r
- BYTE Pol;\r
-\r
- HTotal =TimingTable[fmt_index].HTotal;\r
- HDEW =TimingTable[fmt_index].HActive;\r
- HFP =TimingTable[fmt_index].H_FBH;\r
- HSW =TimingTable[fmt_index].H_SyncW;\r
- HDES =HSW+TimingTable[fmt_index].H_BBH;\r
- VTotal =TimingTable[fmt_index].VTotal;\r
- VDEW =TimingTable[fmt_index].VActive;\r
- VFP =TimingTable[fmt_index].V_FBH;\r
- VSW =TimingTable[fmt_index].V_SyncW;\r
- VDES =VSW+TimingTable[fmt_index].V_BBH;\r
-\r
- Pol = (TimingTable[fmt_index].HPolarity==Hpos)?(1<<1):0 ;\r
- Pol |= (TimingTable[fmt_index].VPolarity==Vpos)?(1<<2):0 ;\r
-\r
- // SyncEmb case=====\r
- if( bInputType & T_MODE_CCIR656)\r
- {\r
- HRS = HFP - 1;\r
- }\r
- else\r
- {\r
- HRS = HFP - 2;\r
- /*\r
- if(VIC==HDMI_1080p60 ||\r
- VIC==HDMI_1080p50 )\r
- {\r
- HDMITX_OrReg_Byte(0x59, (1<<3));\r
- }\r
- else\r
- {\r
- HDMITX_AndReg_Byte(0x59, ~(1<<3));\r
- }\r
- */\r
- }\r
- HRE = HRS + HSW;\r
- H2ndVRRise = HRS+ HTotal/2;\r
-\r
- VRS = VFP;\r
- VRE = VRS + VSW;\r
-\r
- // VTotal>>=1;\r
-\r
- if(PROG == TimingTable[fmt_index].Scan)\r
- { // progressive mode\r
- VRS2nd = 0xFFF;\r
- VRE2nd = 0x3F;\r
- }\r
- else\r
- { // interlaced mode\r
- if(39 == TimingTable[fmt_index].fmt)\r
- {\r
- VRS2nd = VRS + VTotal - 1;\r
- VRE2nd = VRS2nd + VSW;\r
- }\r
- else\r
- {\r
- VRS2nd = VRS + VTotal;\r
- VRE2nd = VRS2nd + VSW;\r
- }\r
- }\r
- #ifdef DETECT_VSYNC_CHG_IN_SAV\r
- if( EnSavVSync )\r
- {\r
- VRS -= 1;\r
- VRE -= 1;\r
- if( !pSetVTiming->ScanMode ) // interlaced mode\r
- {\r
- VRS2nd -= 1;\r
- VRE2nd -= 1;\r
- }\r
- }\r
- #endif // DETECT_VSYNC_CHG_IN_SAV\r
- HDMITX_SetI2C_Byte(0x90, 0x06, Pol);\r
- // write H2ndVRRise\r
- HDMITX_SetI2C_Byte(0x90, 0xF0, (H2ndVRRise&0x0F)<<4);\r
- HDMITX_WriteI2C_Byte(0x91, (H2ndVRRise&0x0FF0)>>4);\r
- // write HRS/HRE\r
- HDMITX_WriteI2C_Byte(0x95, HRS&0xFF);\r
- HDMITX_WriteI2C_Byte(0x96, HRE&0xFF);\r
- HDMITX_WriteI2C_Byte(0x97, ((HRE&0x0F00)>>4)+((HRS&0x0F00)>>8));\r
- // write VRS/VRE\r
- HDMITX_WriteI2C_Byte(0xa0, VRS&0xFF);\r
- HDMITX_WriteI2C_Byte(0xa1, ((VRE&0x0F)<<4)+((VRS&0x0F00)>>8));\r
- HDMITX_WriteI2C_Byte(0xa2, VRS2nd&0xFF);\r
- HDMITX_WriteI2C_Byte(0xa6, (VRE2nd&0xF0)+((VRE&0xF0)>>4));\r
- HDMITX_WriteI2C_Byte(0xa3, ((VRE2nd&0x0F)<<4)+((VRS2nd&0xF00)>>8));\r
- HDMITX_WriteI2C_Byte(0xa4, H2ndVRRise&0xFF);\r
- HDMITX_WriteI2C_Byte(0xa5, (/*EnDEOnly*/0<<5)+((TimingTable[fmt_index].Scan==INTERLACE)?(1<<4):0)+((H2ndVRRise&0xF00)>>8));\r
- HDMITX_SetI2C_Byte(0xb1, 0x51, ((HRE&0x1000)>>6)+((HRS&0x1000)>>8)+((HDES&0x1000)>>12));\r
- HDMITX_SetI2C_Byte(0xb2, 0x05, ((H2ndVRRise&0x1000)>>10)+((H2ndVRRise&0x1000)>>12));\r
- }\r
- return TRUE ;\r
-}\r
-\r
-#endif // SUPPORT_SYNCEMBEDDED\r
-\r
-//~jj_tseng@chipadvanced.com 2007/01/02\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetInputMode\r
-// Parameter: InputMode,bInputSignalType\r
-// InputMode - use [1:0] to identify the color space for reg70[7:6],\r
-// definition:\r
-// #define F_MODE_RGB444 0\r
-// #define F_MODE_YUV422 1\r
-// #define F_MODE_YUV444 2\r
-// #define F_MODE_CLRMOD_MASK 3\r
-// bInputSignalType - defined the CCIR656 D[0],SYNC Embedded D[1],and\r
-// DDR input in D[2].\r
-// Return: N/A\r
-// Remark: program Reg70 with the input value.\r
-// Side-Effect: Reg70.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_SetInputMode(BYTE InputColorMode,BYTE bInputSignalType)\r
-{\r
- BYTE ucData ;\r
-\r
- ucData = HDMITX_ReadI2C_Byte(REG_TX_INPUT_MODE);\r
- ucData &= ~(M_TX_INCOLMOD|B_TX_2X656CLK|B_TX_SYNCEMB|B_TX_INDDR|B_TX_PCLKDIV2);\r
- ucData |= 0x01;//input clock delay 1 for 1080P DDR\r
-\r
- switch(InputColorMode & F_MODE_CLRMOD_MASK)\r
- {\r
- case F_MODE_YUV422:\r
- ucData |= B_TX_IN_YUV422 ;\r
- break ;\r
- case F_MODE_YUV444:\r
- ucData |= B_TX_IN_YUV444 ;\r
- break ;\r
- case F_MODE_RGB444:\r
- default:\r
- ucData |= B_TX_IN_RGB ;\r
- break ;\r
- }\r
- if(bInputSignalType & T_MODE_PCLKDIV2)\r
- {\r
- ucData |= B_TX_PCLKDIV2 ; HDMITX_DEBUG_PRINTF(("PCLK Divided by 2 mode\n"));\r
- }\r
- if(bInputSignalType & T_MODE_CCIR656)\r
- {\r
- ucData |= B_TX_2X656CLK ; HDMITX_DEBUG_PRINTF(("CCIR656 mode\n"));\r
- }\r
- if(bInputSignalType & T_MODE_SYNCEMB)\r
- {\r
- ucData |= B_TX_SYNCEMB ; HDMITX_DEBUG_PRINTF(("Sync Embedded mode\n"));\r
- }\r
- if(bInputSignalType & T_MODE_INDDR)\r
- {\r
- ucData |= B_TX_INDDR ; HDMITX_DEBUG_PRINTF(("Input DDR mode\n"));\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_INPUT_MODE,ucData);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetCSCScale\r
-// Parameter: bInputMode -\r
-// D[1:0] - Color Mode\r
-// D[4] - Colorimetry 0: ITU_BT601 1: ITU_BT709\r
-// D[5] - Quantization 0: 0_255 1: 16_235\r
-// D[6] - Up/Dn Filter 'Required'\r
-// 0: no up/down filter\r
-// 1: enable up/down filter when csc need.\r
-// D[7] - Dither Filter 'Required'\r
-// 0: no dither enabled.\r
-// 1: enable dither and dither free go "when required".\r
-// bOutputMode -\r
-// D[1:0] - Color mode.\r
-// Return: N/A\r
-// Remark: reg72~reg8D will be programmed depended the input with table.\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_SetCSCScale(BYTE bInputMode,BYTE bOutputMode)\r
-{\r
- BYTE ucData = 0,csc = B_HDMITX_CSC_BYPASS ;\r
- BYTE i ;\r
- BYTE filter = 0 ; // filter is for Video CTRL DN_FREE_GO,EN_DITHER,and ENUDFILT\r
-\r
- // (1) YUV422 in,RGB/YUV444 output (Output is 8-bit,input is 12-bit)\r
- // (2) YUV444/422 in,RGB output (CSC enable,and output is not YUV422)\r
- // (3) RGB in,YUV444 output (CSC enable,and output is not YUV422)\r
- //\r
- // YUV444/RGB24 <-> YUV422 need set up/down filter.\r
- HDMITX_DEBUG_PRINTF(("hdmitx_SetCSCScale(BYTE bInputMode = %x,BYTE bOutputMode = %x)\n", (int)bInputMode, (int)bOutputMode)) ;\r
- switch(bInputMode&F_MODE_CLRMOD_MASK)\r
- {\r
- #ifdef SUPPORT_INPUTYUV444\r
- case F_MODE_YUV444:\r
- HDMITX_DEBUG_PRINTF(("Input mode is YUV444 "));\r
- switch(bOutputMode&F_MODE_CLRMOD_MASK)\r
- {\r
- case F_MODE_YUV444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV444\n"));\r
- csc = B_HDMITX_CSC_BYPASS ;\r
- break ;\r
-\r
- case F_MODE_YUV422:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV422\n"));\r
- if(bInputMode & F_VIDMODE_EN_UDFILT) // YUV444 to YUV422 need up/down filter for processing.\r
- {\r
- filter |= B_TX_EN_UDFILTER ;\r
- }\r
- csc = B_HDMITX_CSC_BYPASS ;\r
- break ;\r
- case F_MODE_RGB444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is RGB24\n"));\r
- csc = B_HDMITX_CSC_YUV2RGB ;\r
- if(bInputMode & F_VIDMODE_EN_DITHER) // YUV444 to RGB24 need dither\r
- {\r
- filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ;\r
- }\r
- break ;\r
- }\r
- break ;\r
- #endif\r
-\r
- #ifdef SUPPORT_INPUTYUV422\r
- case F_MODE_YUV422:\r
- HDMITX_DEBUG_PRINTF(("Input mode is YUV422\n"));\r
- switch(bOutputMode&F_MODE_CLRMOD_MASK)\r
- {\r
- case F_MODE_YUV444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV444\n"));\r
- csc = B_HDMITX_CSC_BYPASS ;\r
- if(bInputMode & F_VIDMODE_EN_UDFILT) // YUV422 to YUV444 need up filter\r
- {\r
- filter |= B_TX_EN_UDFILTER ;\r
- }\r
- if(bInputMode & F_VIDMODE_EN_DITHER) // YUV422 to YUV444 need dither\r
- {\r
- filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ;\r
- }\r
- break ;\r
- case F_MODE_YUV422:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV422\n"));\r
- csc = B_HDMITX_CSC_BYPASS ;\r
-\r
- break ;\r
-\r
- case F_MODE_RGB444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is RGB24\n"));\r
- csc = B_HDMITX_CSC_YUV2RGB ;\r
- if(bInputMode & F_VIDMODE_EN_UDFILT) // YUV422 to RGB24 need up/dn filter.\r
- {\r
- filter |= B_TX_EN_UDFILTER ;\r
- }\r
- if(bInputMode & F_VIDMODE_EN_DITHER) // YUV422 to RGB24 need dither\r
- {\r
- filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ;\r
- }\r
- break ;\r
- }\r
- break ;\r
- #endif\r
-\r
- #ifdef SUPPORT_INPUTRGB\r
- case F_MODE_RGB444:\r
- HDMITX_DEBUG_PRINTF(("Input mode is RGB24\n"));\r
- switch(bOutputMode&F_MODE_CLRMOD_MASK)\r
- {\r
- case F_MODE_YUV444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV444\n"));\r
- csc = B_HDMITX_CSC_RGB2YUV ;\r
-\r
- if(bInputMode & F_VIDMODE_EN_DITHER) // RGB24 to YUV444 need dither\r
- {\r
- filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ;\r
- }\r
- break ;\r
-\r
- case F_MODE_YUV422:\r
- HDMITX_DEBUG_PRINTF(("Output mode is YUV422\n"));\r
- if(bInputMode & F_VIDMODE_EN_UDFILT) // RGB24 to YUV422 need down filter.\r
- {\r
- filter |= B_TX_EN_UDFILTER ;\r
- }\r
- if(bInputMode & F_VIDMODE_EN_DITHER) // RGB24 to YUV422 need dither\r
- {\r
- filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ;\r
- }\r
- csc = B_HDMITX_CSC_RGB2YUV ;\r
- break ;\r
-\r
- case F_MODE_RGB444:\r
- HDMITX_DEBUG_PRINTF(("Output mode is RGB24\n"));\r
- csc = B_HDMITX_CSC_BYPASS ;\r
- break ;\r
- }\r
- break ;\r
- #endif\r
- }\r
-#ifndef DISABLE_HDMITX_CSC\r
-\r
- #ifdef SUPPORT_INPUTRGB\r
- // set the CSC metrix registers by colorimetry and quantization\r
- if(csc == B_HDMITX_CSC_RGB2YUV)\r
- {\r
- HDMITX_DEBUG_PRINTF(("CSC = RGB2YUV %x ",csc));\r
- switch(bInputMode&(F_VIDMODE_ITU709|F_VIDMODE_16_235))\r
- {\r
- case F_VIDMODE_ITU709|F_VIDMODE_16_235:\r
- HDMITX_DEBUG_PRINTF(("ITU709 16-235 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_RGB2YUV_ITU709_16_235[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_RGB2YUV_ITU709_16_235[i]));}\r
- break ;\r
- case F_VIDMODE_ITU709|F_VIDMODE_0_255:\r
- HDMITX_DEBUG_PRINTF(("ITU709 0-255 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_RGB2YUV_ITU709_0_255[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_RGB2YUV_ITU709_0_255[i]));}\r
- break ;\r
- case F_VIDMODE_ITU601|F_VIDMODE_16_235:\r
- HDMITX_DEBUG_PRINTF(("ITU601 16-235 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_RGB2YUV_ITU601_16_235[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_RGB2YUV_ITU601_16_235[i]));}\r
- break ;\r
- case F_VIDMODE_ITU601|F_VIDMODE_0_255:\r
- default:\r
- HDMITX_DEBUG_PRINTF(("ITU601 0-255 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_RGB2YUV_ITU601_0_255[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_RGB2YUV_ITU601_0_255[i]));}\r
- break ;\r
- }\r
- }\r
- #endif\r
-\r
- #ifdef SUPPORT_INPUTYUV\r
- if (csc == B_HDMITX_CSC_YUV2RGB)\r
- {\r
- HDMITX_DEBUG_PRINTF(("CSC = YUV2RGB %x ",csc));\r
-\r
- switch(bInputMode&(F_VIDMODE_ITU709|F_VIDMODE_16_235))\r
- {\r
- case F_VIDMODE_ITU709|F_VIDMODE_16_235:\r
- HDMITX_DEBUG_PRINTF(("ITU709 16-235 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_YUV2RGB_ITU709_16_235[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_YUV2RGB_ITU709_16_235[i]));}\r
- break ;\r
- case F_VIDMODE_ITU709|F_VIDMODE_0_255:\r
- HDMITX_DEBUG_PRINTF(("ITU709 0-255 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_YUV2RGB_ITU709_0_255[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_YUV2RGB_ITU709_0_255[i]));}\r
- break ;\r
- case F_VIDMODE_ITU601|F_VIDMODE_16_235:\r
- HDMITX_DEBUG_PRINTF(("ITU601 16-235 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_YUV2RGB_ITU601_16_235[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_YUV2RGB_ITU601_16_235[i]));}\r
- break ;\r
- case F_VIDMODE_ITU601|F_VIDMODE_0_255:\r
- default:\r
- HDMITX_DEBUG_PRINTF(("ITU601 0-255 "));\r
- for( i = 0 ; i < SIZEOF_CSCMTX ; i++ ){ HDMITX_WriteI2C_Byte(REG_TX_CSC_YOFF+i,bCSCMtx_YUV2RGB_ITU601_0_255[i]) ; HDMITX_DEBUG_PRINTF(("reg%02X <- %02X\n",(int)(i+REG_TX_CSC_YOFF),(int)bCSCMtx_YUV2RGB_ITU601_0_255[i]));}\r
- break ;\r
- }\r
- }\r
- #endif\r
-#else// DISABLE_HDMITX_CSC\r
- csc = B_HDMITX_CSC_BYPASS ;\r
-#endif// DISABLE_HDMITX_CSC\r
-\r
- if( csc == B_HDMITX_CSC_BYPASS )\r
- {\r
- HDMITX_SetI2C_Byte(0xF, 0x10, 0x10);\r
- }\r
- else\r
- {\r
- HDMITX_SetI2C_Byte(0xF, 0x10, 0x00);\r
- }\r
- ucData = HDMITX_ReadI2C_Byte(REG_TX_CSC_CTRL) & ~(M_TX_CSC_SEL|B_TX_DNFREE_GO|B_TX_EN_DITHER|B_TX_EN_UDFILTER);\r
- ucData |= filter|csc ;\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_CSC_CTRL,ucData);\r
-\r
- // set output Up/Down Filter,Dither control\r
-\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetupAFE\r
-// Parameter: VIDEOPCLKLEVEL level\r
-// PCLK_LOW - for 13.5MHz (for mode less than 1080p)\r
-// PCLK MEDIUM - for 25MHz~74MHz\r
-// PCLK HIGH - PCLK > 80Hz (for 1080p mode or above)\r
-// Return: N/A\r
-// Remark: set reg62~reg65 depended on HighFreqMode\r
-// reg61 have to be programmed at last and after video stable input.\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_SetupAFE(VIDEOPCLKLEVEL level)\r
-{\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_TX_AFE_DRV_RST);/* 0x10 */\r
- switch(level)\r
- {\r
- case PCLK_HIGH:\r
- HDMITX_SetI2C_Byte(0x62, 0x90, 0x80);\r
- HDMITX_SetI2C_Byte(0x64, 0x89, 0x80);\r
- HDMITX_SetI2C_Byte(0x68, 0x10, 0x80);\r
- HDMITX_DEBUG_PRINTF(("hdmitx_SetupAFE()===================HIGHT\n"));\r
- break ;\r
- default:\r
- HDMITX_SetI2C_Byte(0x62, 0x90, 0x10);\r
- HDMITX_SetI2C_Byte(0x64, 0x89, 0x09);\r
- HDMITX_SetI2C_Byte(0x68, 0x10, 0x10);\r
- HDMITX_DEBUG_PRINTF(("hdmitx_SetupAFE()===================LOW\n"));\r
- break ;\r
- }\r
- HDMITX_SetI2C_Byte(REG_TX_SW_RST,B_TX_REF_RST_HDMITX|B_HDMITX_VID_RST,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0);\r
- delay1ms(1);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_FireAFE\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: write reg61 with 0x04\r
-// When program reg61 with 0x04,then audio and video circuit work.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_FireAFE()\r
-{\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0);\r
-}\r
-\r
-///*****************************************\r
-// @file <hdmitx_aud.c>\r
-//******************************************/\r
-\r
-BYTE AudioDelayCnt=0;\r
-BYTE LastRefaudfreqnum=0;\r
-BOOL bForceCTS = FALSE;\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Audio Output\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void setHDMITX_ChStat(BYTE ucIEC60958ChStat[])\r
-{\r
- BYTE uc ;\r
-\r
- Switch_HDMITX_Bank(1);\r
- uc = (ucIEC60958ChStat[0] <<1)& 0x7C ;\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,uc);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,ucIEC60958ChStat[1]); // 192, audio CATEGORY\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,ucIEC60958ChStat[2]&0xF);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,(ucIEC60958ChStat[2]>>4)&0xF);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,ucIEC60958ChStat[3]); // choose clock\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,ucIEC60958ChStat[4]);\r
- Switch_HDMITX_Bank(0);\r
-}\r
-\r
-void setHDMITX_UpdateChStatFs(ULONG Fs)\r
-{\r
- BYTE uc ;\r
-\r
- /////////////////////////////////////\r
- // Fs should be the following value.\r
- // #define AUDFS_22p05KHz 4\r
- // #define AUDFS_44p1KHz 0\r
- // #define AUDFS_88p2KHz 8\r
- // #define AUDFS_176p4KHz 12\r
- //\r
- // #define AUDFS_24KHz 6\r
- // #define AUDFS_48KHz 2\r
- // #define AUDFS_96KHz 10\r
- // #define AUDFS_192KHz 14\r
- //\r
- // #define AUDFS_768KHz 9\r
- //\r
- // #define AUDFS_32KHz 3\r
- // #define AUDFS_OTHER 1\r
- /////////////////////////////////////\r
-\r
- Switch_HDMITX_Bank(1);\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_AUDCHST_CA_FS); // choose clock\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,uc); // choose clock\r
- uc &= 0xF0 ;\r
- uc |= (Fs&0xF);\r
-\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_AUDCHST_OFS_WL);\r
- uc &= 0xF ;\r
- uc |= ((~Fs) << 4)&0xF0 ;\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,uc);\r
-\r
- Switch_HDMITX_Bank(0);\r
-}\r
-\r
-void setHDMITX_LPCMAudio(BYTE AudioSrcNum, BYTE AudSWL, BOOL bSPDIF)\r
-{\r
-\r
- BYTE AudioEnable, AudioFormat ;\r
-\r
- AudioEnable = 0 ;\r
- AudioFormat = hdmiTxDev[0].bOutputAudioMode ;\r
-\r
- switch(AudSWL)\r
- {\r
- case 16:\r
- AudioEnable |= M_TX_AUD_16BIT ;\r
- break ;\r
- case 18:\r
- AudioEnable |= M_TX_AUD_18BIT ;\r
- break ;\r
- case 20:\r
- AudioEnable |= M_TX_AUD_20BIT ;\r
- break ;\r
- case 24:\r
- default:\r
- AudioEnable |= M_TX_AUD_24BIT ;\r
- break ;\r
- }\r
- if( bSPDIF )\r
- {\r
- AudioFormat &= ~0x40 ;\r
- AudioEnable |= B_TX_AUD_SPDIF|B_TX_AUD_EN_I2S0 ;\r
- }\r
- else\r
- {\r
- AudioFormat |= 0x40 ;\r
- switch(AudioSrcNum)\r
- {\r
- case 4:\r
- AudioEnable |= B_TX_AUD_EN_I2S3|B_TX_AUD_EN_I2S2|B_TX_AUD_EN_I2S1|B_TX_AUD_EN_I2S0 ;\r
- break ;\r
-\r
- case 3:\r
- AudioEnable |= B_TX_AUD_EN_I2S2|B_TX_AUD_EN_I2S1|B_TX_AUD_EN_I2S0 ;\r
- break ;\r
-\r
- case 2:\r
- AudioEnable |= B_TX_AUD_EN_I2S1|B_TX_AUD_EN_I2S0 ;\r
- break ;\r
-\r
- case 1:\r
- default:\r
- AudioFormat &= ~0x40 ;\r
- AudioEnable |= B_TX_AUD_EN_I2S0 ;\r
- break ;\r
-\r
- }\r
- }\r
- AudioFormat|=0x01;//mingchih add\r
- hdmiTxDev[0].bAudioChannelEnable=AudioEnable;\r
-\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable&0xF0);\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,AudioFormat); // regE1 bOutputAudioMode should be loaded from ROM image.\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4); // default mapping.\r
-#ifdef USE_SPDIF_CHSTAT\r
- if( bSPDIF )\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,B_TX_CHSTSEL);\r
- }\r
- else\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,0);\r
- }\r
-#else // not USE_SPDIF_CHSTAT\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,0);\r
-#endif // USE_SPDIF_CHSTAT\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,0x00);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_HDAUDIO,0x00); // regE5 = 0 ;\r
-\r
- if( bSPDIF )\r
- {\r
- BYTE i ;\r
- HDMITX_OrReg_Byte(0x5c,(1<<6));\r
- for( i = 0 ; i < 100 ; i++ )\r
- {\r
- if(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_TX_OSF_LOCK)\r
- {\r
- break ; // stable clock.\r
- }\r
- }\r
- }\r
-}\r
-\r
-void setHDMITX_NLPCMAudio(BOOL bSPDIF) // no Source Num, no I2S.\r
-{\r
- BYTE AudioEnable, AudioFormat ;\r
- BYTE i ;\r
-\r
- AudioFormat = 0x01 ; // NLPCM must use standard I2S mode.\r
- if( bSPDIF )\r
- {\r
- AudioEnable = M_TX_AUD_24BIT|B_TX_AUD_SPDIF;\r
- }\r
- else\r
- {\r
- AudioEnable = M_TX_AUD_24BIT;\r
- }\r
-\r
- Switch_HDMITX_Bank(0);\r
- // HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT|B_TX_AUD_SPDIF);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, AudioEnable);\r
- //HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_HDMITX_AUD_RST|B_TX_AREF_RST));\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,0x01); // regE1 bOutputAudioMode should be loaded from ROM image.\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4); // default mapping.\r
-\r
-#ifdef USE_SPDIF_CHSTAT\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,B_TX_CHSTSEL);\r
-#else // not USE_SPDIF_CHSTAT\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,0);\r
-#endif // USE_SPDIF_CHSTAT\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,0x00);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_HDAUDIO,0x00); // regE5 = 0 ;\r
-\r
- if( bSPDIF )\r
- {\r
- for( i = 0 ; i < 100 ; i++ )\r
- {\r
- if(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_TX_OSF_LOCK)\r
- {\r
- break ; // stable clock.\r
- }\r
- }\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, AudioEnable|B_TX_AUD_EN_I2S0);\r
-}\r
-\r
-void setHDMITX_HBRAudio(BOOL bSPDIF)\r
-{\r
- // BYTE rst;\r
- Switch_HDMITX_Bank(0);\r
-\r
- // rst = HDMITX_ReadI2C_Byte(REG_TX_SW_RST);\r
- // rst &= ~(B_HDMITX_AUD_RST|B_TX_AREF_RST);\r
-\r
- // HDMITX_WriteI2C_Byte(REG_TX_SW_RST, rst | B_HDMITX_AUD_RST );\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,0x47); // regE1 bOutputAudioMode should be loaded from ROM image.\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4); // default mapping.\r
-\r
- if( bSPDIF )\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT|B_TX_AUD_SPDIF);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,B_TX_CHSTSEL);\r
- }\r
- else\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,0);\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,0x08);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_HDAUDIO,B_TX_HBR); // regE5 = 0 ;\r
-\r
- //uc = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1);\r
- //uc &= ~M_TX_AUD_DIV ;\r
- //HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, uc);\r
-\r
- if( bSPDIF )\r
- {\r
- BYTE i ;\r
- for( i = 0 ; i < 100 ; i++ )\r
- {\r
- if(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_TX_OSF_LOCK)\r
- {\r
- break ; // stable clock.\r
- }\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT|B_TX_AUD_SPDIF|B_TX_AUD_EN_SPDIF);\r
- }\r
- else\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT|B_TX_AUD_EN_I2S3|B_TX_AUD_EN_I2S2|B_TX_AUD_EN_I2S1|B_TX_AUD_EN_I2S0);\r
- }\r
- HDMITX_AndReg_Byte(0x5c,~(1<<6));\r
- hdmiTxDev[0].bAudioChannelEnable=HDMITX_ReadI2C_Byte(REG_TX_AUDIO_CTRL0);\r
- // HDMITX_WriteI2C_Byte(REG_TX_SW_RST, rst );\r
-}\r
-\r
-void setHDMITX_DSDAudio()\r
-{\r
- // to be continue\r
- // BYTE rst;\r
- // rst = HDMITX_ReadI2C_Byte(REG_TX_SW_RST);\r
-\r
- //HDMITX_WriteI2C_Byte(REG_TX_SW_RST, rst | (B_HDMITX_AUD_RST|B_TX_AREF_RST) );\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,0x41); // regE1 bOutputAudioMode should be loaded from ROM image.\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4); // default mapping.\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,0);\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,0x00);\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_HDAUDIO,B_TX_DSD); // regE5 = 0 ;\r
- //HDMITX_WriteI2C_Byte(REG_TX_SW_RST, rst & ~(B_HDMITX_AUD_RST|B_TX_AREF_RST) );\r
-\r
- //uc = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1);\r
- //uc &= ~M_TX_AUD_DIV ;\r
- //HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, uc);\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, M_TX_AUD_24BIT|B_TX_AUD_EN_I2S3|B_TX_AUD_EN_I2S2|B_TX_AUD_EN_I2S1|B_TX_AUD_EN_I2S0);\r
-}\r
-\r
-void HDMITX_DisableAudioOutput()\r
-{\r
- //BYTE uc = (HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | (B_HDMITX_AUD_RST | B_TX_AREF_RST));\r
- //HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc);\r
- AudioDelayCnt=AudioOutDelayCnt;\r
- LastRefaudfreqnum=0;\r
- HDMITX_SetI2C_Byte(REG_TX_SW_RST, (B_HDMITX_AUD_RST | B_TX_AREF_RST), (B_HDMITX_AUD_RST | B_TX_AREF_RST) );\r
- HDMITX_SetI2C_Byte(0x0F, 0x10, 0x10 );\r
-}\r
-\r
-void HDMITX_EnableAudioOutput(BYTE AudioType, BOOL bSPDIF, ULONG SampleFreq, BYTE ChNum, BYTE *pIEC60958ChStat, ULONG TMDSClock)\r
-{\r
- static _IDATA BYTE ucIEC60958ChStat[5] ;\r
-\r
- BYTE Fs ;\r
- AudioDelayCnt=36;\r
- LastRefaudfreqnum=0;\r
- hdmiTxDev[0].TMDSClock=TMDSClock;\r
- hdmiTxDev[0].bAudioChannelEnable=0;\r
- hdmiTxDev[0].bSPDIF_OUT=bSPDIF;\r
-\r
- HDMITX_DEBUG_PRINTF1(("HDMITX_EnableAudioOutput(%02X, %s, %ld, %d, %p, %ld);\n",\r
- AudioType, bSPDIF?"SPDIF":"I2S",SampleFreq, ChNum, pIEC60958ChStat, TMDSClock\r
- ));\r
-\r
- HDMITX_OrReg_Byte(REG_TX_SW_RST,(B_HDMITX_AUD_RST | B_TX_AREF_RST));\r
- HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL0,B_TX_AUTO_OVER_SAMPLING_CLOCK|B_TX_EXT_256FS|0x01);\r
-\r
- HDMITX_SetI2C_Byte(0x0F, 0x10, 0x00 ); // power on the ACLK\r
-\r
- if(bSPDIF)\r
- {\r
- if(AudioType==T_AUDIO_HBR)\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL0,0x81);\r
- }\r
- HDMITX_OrReg_Byte(REG_TX_AUDIO_CTRL0,B_TX_AUD_SPDIF);\r
- }\r
- else\r
- {\r
- HDMITX_AndReg_Byte(REG_TX_AUDIO_CTRL0,(~B_TX_AUD_SPDIF));\r
- }\r
- if( AudioType != T_AUDIO_DSD)\r
- {\r
- // one bit audio have no channel status.\r
- switch(SampleFreq)\r
- {\r
- case 44100L: Fs = AUDFS_44p1KHz ; break ;\r
- case 88200L: Fs = AUDFS_88p2KHz ; break ;\r
- case 176400L: Fs = AUDFS_176p4KHz ; break ;\r
- case 32000L: Fs = AUDFS_32KHz ; break ;\r
- case 48000L: Fs = AUDFS_48KHz ; break ;\r
- case 96000L: Fs = AUDFS_96KHz ; break ;\r
- case 192000L: Fs = AUDFS_192KHz ; break ;\r
- case 768000L: Fs = AUDFS_768KHz ; break ;\r
- default:\r
- SampleFreq = 48000L ;\r
- Fs = AUDFS_48KHz ;\r
- break ; // default, set Fs = 48KHz.\r
- }\r
- #ifdef SUPPORT_AUDIO_MONITOR\r
- hdmiTxDev[0].bAudFs=AUDFS_OTHER;\r
- #else\r
- hdmiTxDev[0].bAudFs=Fs;\r
- #endif\r
- setHDMITX_NCTS(hdmiTxDev[0].bAudFs);\r
- if( pIEC60958ChStat == NULL )\r
- {\r
- ucIEC60958ChStat[0] = 0 ;\r
- ucIEC60958ChStat[1] = 0 ;\r
- ucIEC60958ChStat[2] = (ChNum+1)/2 ;\r
-\r
- if(ucIEC60958ChStat[2]<1)\r
- {\r
- ucIEC60958ChStat[2] = 1 ;\r
- }\r
- else if( ucIEC60958ChStat[2] >4 )\r
- {\r
- ucIEC60958ChStat[2] = 4 ;\r
- }\r
- ucIEC60958ChStat[3] = Fs ;\r
- ucIEC60958ChStat[4] = (((~Fs)<<4) & 0xF0) | CHTSTS_SWCODE ; // Fs | 24bit word length\r
- pIEC60958ChStat = ucIEC60958ChStat ;\r
- }\r
- }\r
- HDMITX_SetI2C_Byte(REG_TX_SW_RST,(B_HDMITX_AUD_RST|B_TX_AREF_RST),B_TX_AREF_RST);\r
-\r
- switch(AudioType)\r
- {\r
- case T_AUDIO_HBR:\r
- HDMITX_DEBUG_PRINTF(("T_AUDIO_HBR\n"));\r
- pIEC60958ChStat[0] |= 1<<1 ;\r
- pIEC60958ChStat[2] = 0;\r
- pIEC60958ChStat[3] &= 0xF0 ;\r
- pIEC60958ChStat[3] |= AUDFS_768KHz ;\r
- pIEC60958ChStat[4] |= (((~AUDFS_768KHz)<<4) & 0xF0)| 0xB ;\r
- setHDMITX_ChStat(pIEC60958ChStat);\r
- setHDMITX_HBRAudio(bSPDIF);\r
-\r
- break ;\r
- case T_AUDIO_DSD:\r
- HDMITX_DEBUG_PRINTF(("T_AUDIO_DSD\n"));\r
- setHDMITX_DSDAudio();\r
- break ;\r
- case T_AUDIO_NLPCM:\r
- HDMITX_DEBUG_PRINTF(("T_AUDIO_NLPCM\n"));\r
- pIEC60958ChStat[0] |= 1<<1 ;\r
- setHDMITX_ChStat(pIEC60958ChStat);\r
- setHDMITX_NLPCMAudio(bSPDIF);\r
- break ;\r
- case T_AUDIO_LPCM:\r
- HDMITX_DEBUG_PRINTF(("T_AUDIO_LPCM\n"));\r
- pIEC60958ChStat[0] &= ~(1<<1);\r
-\r
- setHDMITX_ChStat(pIEC60958ChStat);\r
- setHDMITX_LPCMAudio((ChNum+1)/2, SUPPORT_AUDI_AudSWL, bSPDIF);\r
- // can add auto adjust\r
- break ;\r
- }\r
- HDMITX_AndReg_Byte(REG_TX_INT_MASK1,(~B_TX_AUDIO_OVFLW_MASK));\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, hdmiTxDev[0].bAudioChannelEnable);\r
-\r
- HDMITX_SetI2C_Byte(REG_TX_SW_RST,(B_HDMITX_AUD_RST|B_TX_AREF_RST),0);\r
-}\r
-\r
-void hdmitx_AutoAdjustAudio()\r
-{\r
- unsigned long SampleFreq,cTMDSClock ;\r
- unsigned long N ;\r
- ULONG aCTS=0;\r
- BYTE fs, uc,LoopCnt=10;\r
- if(bForceCTS)\r
- {\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(0xF8, 0xC3);\r
- HDMITX_WriteI2C_Byte(0xF8, 0xA5);\r
- HDMITX_AndReg_Byte(REG_TX_PKT_SINGLE_CTRL,~B_TX_SW_CTS); // D[1] = 0, HW auto count CTS\r
- HDMITX_WriteI2C_Byte(0xF8, 0xFF);\r
- }\r
- //delay1ms(50);\r
- Switch_HDMITX_Bank(1);\r
- N = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN2)&0xF) << 16 ;\r
- N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN1)) <<8 ;\r
- N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN0));\r
-\r
- while(LoopCnt--)\r
- { ULONG TempCTS=0;\r
- aCTS = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt2)) << 12 ;\r
- aCTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt1)) <<4 ;\r
- aCTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt0)&0xf0)>>4 ;\r
- if(aCTS==TempCTS)\r
- {break;}\r
- TempCTS=aCTS;\r
- }\r
- Switch_HDMITX_Bank(0);\r
- if( aCTS == 0)\r
- {\r
- HDMITX_DEBUG_PRINTF(("aCTS== 0"));\r
- return;\r
- }\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_GCP);\r
-\r
- cTMDSClock = hdmiTxDev[0].TMDSClock ;\r
- //TMDSClock=GetInputPclk();\r
- HDMITX_DEBUG_PRINTF(("PCLK = %u0,000\n",(WORD)(cTMDSClock/10000)));\r
- switch(uc & 0x70)\r
- {\r
- case 0x50:\r
- cTMDSClock *= 5 ;\r
- cTMDSClock /= 4 ;\r
- break ;\r
- case 0x60:\r
- cTMDSClock *= 3 ;\r
- cTMDSClock /= 2 ;\r
- }\r
- SampleFreq = cTMDSClock/aCTS ;\r
- SampleFreq *= N ;\r
- SampleFreq /= 128 ;\r
- //SampleFreq=48000;\r
-\r
- HDMITX_DEBUG_PRINTF(("SampleFreq = %u0\n",(WORD)(SampleFreq/10)));\r
- if( SampleFreq>31000L && SampleFreq<=38050L ){fs = AUDFS_32KHz ;}\r
- else if (SampleFreq < 46550L ) {fs = AUDFS_44p1KHz ;}//46050\r
- else if (SampleFreq < 68100L ) {fs = AUDFS_48KHz ;}\r
- else if (SampleFreq < 92100L ) {fs = AUDFS_88p2KHz ;}\r
- else if (SampleFreq < 136200L ) {fs = AUDFS_96KHz ;}\r
- else if (SampleFreq < 184200L ) {fs = AUDFS_176p4KHz ;}\r
- else if (SampleFreq < 240200L ) {fs = AUDFS_192KHz ;}\r
- else if (SampleFreq < 800000L ) {fs = AUDFS_768KHz ;}\r
- else\r
- {\r
- fs = AUDFS_OTHER;\r
- HDMITX_DEBUG_PRINTF(("fs = AUDFS_OTHER\n"));\r
- }\r
- if(hdmiTxDev[0].bAudFs != fs)\r
- {\r
- hdmiTxDev[0].bAudFs=fs;\r
- setHDMITX_NCTS(hdmiTxDev[0].bAudFs); // set N, CTS by new generated clock.\r
- //CurrCTS=0;\r
- return;\r
- }\r
- return;\r
-}\r
-\r
-BOOL hdmitx_IsAudioChang()\r
-{\r
- //ULONG pCTS=0;\r
- BYTE FreDiff=0,Refaudfreqnum;\r
-\r
- //Switch_HDMITX_Bank(1);\r
- //pCTS = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt2)) << 12 ;\r
- //pCTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt1)) <<4 ;\r
- //pCTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt0)&0xf0)>>4 ;\r
- //Switch_HDMITX_Bank(0);\r
- Switch_HDMITX_Bank(0);\r
- Refaudfreqnum=HDMITX_ReadI2C_Byte(0x60);\r
- //HDMITX_DEBUG_PRINTF(("Refaudfreqnum=%X pCTS= %u",(WORD)Refaudfreqnum,(WORD)(pCTS/10000)));\r
- //if((pCTS%10000)<1000)HDMITX_DEBUG_PRINTF(("0"));\r
- //if((pCTS%10000)<100)HDMITX_DEBUG_PRINTF(("0"));\r
- //if((pCTS%10000)<10)HDMITX_DEBUG_PRINTF(("0"));\r
- //HDMITX_DEBUG_PRINTF(("%u\n",(WORD)(pCTS%10000)));\r
- if((1<<4)&HDMITX_ReadI2C_Byte(0x5f))\r
- {\r
- //printf("=======XXXXXXXXXXX=========\n");\r
- return FALSE;\r
- }\r
- if(LastRefaudfreqnum>Refaudfreqnum)\r
- {FreDiff=LastRefaudfreqnum-Refaudfreqnum;}\r
- else\r
- {FreDiff=Refaudfreqnum-LastRefaudfreqnum;}\r
- LastRefaudfreqnum=Refaudfreqnum;\r
- if(3<FreDiff)\r
- {\r
- HDMITX_DEBUG_PRINTF(("Aduio FreDiff=%d\n",(int)FreDiff));\r
- HDMITX_OrReg_Byte(REG_TX_PKT_SINGLE_CTRL,(1<<5));\r
- HDMITX_AndReg_Byte(REG_TX_AUDIO_CTRL0,0xF0);\r
- return TRUE;\r
- }\r
- else\r
- {\r
- return FALSE;\r
- }\r
-}\r
-\r
-void setHDMITX_AudioChannelEnable(BOOL EnableAudio_b)\r
-{\r
- static BOOL AudioOutStatus=FALSE;\r
- if(EnableAudio_b)\r
- {\r
- if(AudioDelayCnt==0)\r
- {\r
- //if(hdmiTxDev[0].bAuthenticated==FALSE)\r
- //{HDMITX_EnableHDCP(TRUE);}\r
- #ifdef SUPPORT_AUDIO_MONITOR\r
- if(hdmitx_IsAudioChang())\r
- {\r
- hdmitx_AutoAdjustAudio();\r
- #else\r
- if(AudioOutStatus==FALSE)\r
- {\r
- setHDMITX_NCTS(hdmiTxDev[0].bAudFs);\r
- #endif\r
- HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,0);\r
- HDMITX_OrReg_Byte(REG_TX_PKT_SINGLE_CTRL,(1<<5));\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, hdmiTxDev[0].bAudioChannelEnable);\r
- //HDMITX_OrREG_Byte(0x59,(1<<2)); //for test\r
- HDMITX_AndReg_Byte(REG_TX_PKT_SINGLE_CTRL,(~0x3C));\r
- HDMITX_AndReg_Byte(REG_TX_PKT_SINGLE_CTRL,(~(1<<5)));\r
- printk("Audio Out Enable\n");\r
- #ifndef SUPPORT_AUDIO_MONITOR\r
- AudioOutStatus=TRUE;\r
- #endif\r
- }\r
- }\r
- else\r
- {\r
- AudioOutStatus=FALSE;\r
- if(0==(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2)&0x10))\r
- {\r
- AudioDelayCnt--;\r
- }\r
- else\r
- {\r
- AudioDelayCnt=AudioOutDelayCnt;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- // CurrCTS=0;\r
- }\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: setHDMITX_NCTS\r
-// Parameter: PCLK - video clock in Hz.\r
-// Fs - Encoded audio sample rate\r
-// AUDFS_22p05KHz 4\r
-// AUDFS_44p1KHz 0\r
-// AUDFS_88p2KHz 8\r
-// AUDFS_176p4KHz 12\r
-//\r
-// AUDFS_24KHz 6\r
-// AUDFS_48KHz 2\r
-// AUDFS_96KHz 10\r
-// AUDFS_192KHz 14\r
-//\r
-// AUDFS_768KHz 9\r
-//\r
-// AUDFS_32KHz 3\r
-// AUDFS_OTHER 1\r
-// Return: ER_SUCCESS if success\r
-// Remark: set N value,the CTS will be auto generated by HW.\r
-// Side-Effect: register bank will reset to bank 0.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void setHDMITX_NCTS(BYTE Fs)\r
-{\r
- ULONG n;\r
- BYTE LoopCnt=255,CTSStableCnt=0;\r
- ULONG diff;\r
- ULONG CTS=0,LastCTS=0;\r
- BOOL HBR_mode;\r
- // BYTE aVIC;\r
-\r
- if(B_TX_HBR & HDMITX_ReadI2C_Byte(REG_TX_AUD_HDAUDIO))\r
- {\r
- HBR_mode=TRUE;\r
- }\r
- else\r
- {\r
- HBR_mode=FALSE;\r
- }\r
- switch(Fs)\r
- {\r
- case AUDFS_32KHz: n = 4096; break;\r
- case AUDFS_44p1KHz: n = 6272; break;\r
- case AUDFS_48KHz: n = 6144; break;\r
- case AUDFS_88p2KHz: n = 12544; break;\r
- case AUDFS_96KHz: n = 12288; break;\r
- case AUDFS_176p4KHz: n = 25088; break;\r
- case AUDFS_192KHz: n = 24576; break;\r
- case AUDFS_768KHz: n = 24576; break ;\r
- default: n = 6144;\r
- }\r
- // tr_printf((" n = %ld\n",n));\r
- Switch_HDMITX_Bank(1);\r
- HDMITX_WriteI2C_Byte(REGPktAudN0,(BYTE)((n)&0xFF));\r
- HDMITX_WriteI2C_Byte(REGPktAudN1,(BYTE)((n>>8)&0xFF));\r
- HDMITX_WriteI2C_Byte(REGPktAudN2,(BYTE)((n>>16)&0xF));\r
-\r
- if(bForceCTS)\r
- {\r
- ULONG SumCTS=0;\r
- while(LoopCnt--)\r
- {\r
- delay1ms(30);\r
- CTS = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt2)) << 12 ;\r
- CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt1)) <<4 ;\r
- CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt0)&0xf0)>>4 ;\r
- if( CTS == 0)\r
- {\r
- continue;\r
- }\r
- else\r
- {\r
- if(LastCTS>CTS )\r
- {diff=LastCTS-CTS;}\r
- else\r
- {diff=CTS-LastCTS;}\r
- //HDMITX_DEBUG_PRINTF(("LastCTS= %u%u",(WORD)(LastCTS/10000),(WORD)(LastCTS%10000)));\r
- //HDMITX_DEBUG_PRINTF((" CTS= %u%u\n",(WORD)(CTS/10000),(WORD)(CTS%10000)));\r
- LastCTS=CTS;\r
- if(5>diff)\r
- {\r
- CTSStableCnt++;\r
- SumCTS+=CTS;\r
- }\r
- else\r
- {\r
- CTSStableCnt=0;\r
- SumCTS=0;\r
- continue;\r
- }\r
- if(CTSStableCnt>=32)\r
- {\r
- LastCTS=(SumCTS>>5);\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- HDMITX_WriteI2C_Byte(REGPktAudCTS0,(BYTE)((LastCTS)&0xFF));\r
- HDMITX_WriteI2C_Byte(REGPktAudCTS1,(BYTE)((LastCTS>>8)&0xFF));\r
- HDMITX_WriteI2C_Byte(REGPktAudCTS2,(BYTE)((LastCTS>>16)&0xF));\r
- Switch_HDMITX_Bank(0);\r
-#ifdef Force_CTS\r
- bForceCTS = TRUE;\r
-#endif\r
- HDMITX_WriteI2C_Byte(0xF8, 0xC3);\r
- HDMITX_WriteI2C_Byte(0xF8, 0xA5);\r
- if(bForceCTS)\r
- {\r
- HDMITX_OrReg_Byte(REG_TX_PKT_SINGLE_CTRL,B_TX_SW_CTS); // D[1] = 0, HW auto count CTS\r
- }\r
- else\r
- {\r
- HDMITX_AndReg_Byte(REG_TX_PKT_SINGLE_CTRL,~B_TX_SW_CTS); // D[1] = 0, HW auto count CTS\r
- }\r
- HDMITX_WriteI2C_Byte(0xF8, 0xFF);\r
-\r
- if(FALSE==HBR_mode) //LPCM\r
- {\r
- BYTE uData;\r
- Switch_HDMITX_Bank(1);\r
- Fs = AUDFS_768KHz ;\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|Fs);\r
- Fs = ~Fs ; // OFS is the one's complement of FS\r
- uData = (0x0f&HDMITX_ReadI2C_Byte(REG_TX_AUDCHST_OFS_WL));\r
- HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(Fs<<4)|uData);\r
- Switch_HDMITX_Bank(0);\r
- }\r
-}\r
-\r
-///*****************************************\r
-// @file <hdmitx_pkt.c>\r
-//******************************************/\r
-\r
-BOOL HDMITX_EnableVSInfoFrame(BYTE bEnable,BYTE *pVSInfoFrame)\r
-{\r
- if(!bEnable)\r
- {\r
- hdmitx_DISABLE_VSDB_PKT();\r
- return TRUE ;\r
- }\r
- if(hdmitx_SetVSIInfoFrame((VendorSpecific_InfoFrame *)pVSInfoFrame) == ER_SUCCESS)\r
- {\r
- return TRUE ;\r
- }\r
- return FALSE ;\r
-}\r
-\r
-BOOL HDMITX_EnableAVIInfoFrame(BYTE bEnable,BYTE *pAVIInfoFrame)\r
-{\r
- if(!bEnable)\r
- {\r
- hdmitx_DISABLE_AVI_INFOFRM_PKT();\r
- return TRUE ;\r
- }\r
- if(hdmitx_SetAVIInfoFrame((AVI_InfoFrame *)pAVIInfoFrame) == ER_SUCCESS)\r
- {\r
- return TRUE ;\r
- }\r
- return FALSE ;\r
-}\r
-\r
-BOOL HDMITX_EnableAudioInfoFrame(BYTE bEnable,BYTE *pAudioInfoFrame)\r
-{\r
- if(!bEnable)\r
- {\r
- hdmitx_DISABLE_AVI_INFOFRM_PKT();\r
- return TRUE ;\r
- }\r
- if(hdmitx_SetAudioInfoFrame((Audio_InfoFrame *)pAudioInfoFrame) == ER_SUCCESS)\r
- {\r
- return TRUE ;\r
- }\r
- return FALSE ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetAVIInfoFrame()\r
-// Parameter: pAVIInfoFrame - the pointer to HDMI AVI Infoframe ucData\r
-// Return: N/A\r
-// Remark: Fill the AVI InfoFrame ucData,and count checksum,then fill into\r
-// AVI InfoFrame registers.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame)\r
-{\r
- int i ;\r
- byte checksum ;\r
-\r
- if(!pAVIInfoFrame)\r
- {\r
- return ER_FAIL ;\r
- }\r
- Switch_HDMITX_Bank(1);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB1,pAVIInfoFrame->pktbyte.AVI_DB[0]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB2,pAVIInfoFrame->pktbyte.AVI_DB[1]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB3,pAVIInfoFrame->pktbyte.AVI_DB[2]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB4,pAVIInfoFrame->pktbyte.AVI_DB[3]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB5,pAVIInfoFrame->pktbyte.AVI_DB[4]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB6,pAVIInfoFrame->pktbyte.AVI_DB[5]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB7,pAVIInfoFrame->pktbyte.AVI_DB[6]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB8,pAVIInfoFrame->pktbyte.AVI_DB[7]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB9,pAVIInfoFrame->pktbyte.AVI_DB[8]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB10,pAVIInfoFrame->pktbyte.AVI_DB[9]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB11,pAVIInfoFrame->pktbyte.AVI_DB[10]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB12,pAVIInfoFrame->pktbyte.AVI_DB[11]);\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB13,pAVIInfoFrame->pktbyte.AVI_DB[12]);\r
- for(i = 0,checksum = 0; i < 13 ; i++)\r
- {\r
- checksum -= pAVIInfoFrame->pktbyte.AVI_DB[i] ;\r
- }\r
- /*\r
- HDMITX_DEBUG_PRINTF(("SetAVIInfo(): "));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB1)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB2)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB3)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB4)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB5)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB6)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB7)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB8)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB9)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB10)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB11)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB12)));\r
- HDMITX_DEBUG_PRINTF(("%02X ",(int)HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB13)));\r
- HDMITX_DEBUG_PRINTF(("\n"));\r
- */\r
- checksum -= AVI_INFOFRAME_VER+AVI_INFOFRAME_TYPE+AVI_INFOFRAME_LEN ;\r
- HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_SUM,checksum);\r
-\r
- Switch_HDMITX_Bank(0);\r
- hdmitx_ENABLE_AVI_INFOFRM_PKT();\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetAudioInfoFrame()\r
-// Parameter: pAudioInfoFrame - the pointer to HDMI Audio Infoframe ucData\r
-// Return: N/A\r
-// Remark: Fill the Audio InfoFrame ucData,and count checksum,then fill into\r
-// Audio InfoFrame registers.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame)\r
-{\r
- BYTE checksum ;\r
-\r
- if(!pAudioInfoFrame)\r
- {\r
- return ER_FAIL ;\r
- }\r
- Switch_HDMITX_Bank(1);\r
- checksum = 0x100-(AUDIO_INFOFRAME_VER+AUDIO_INFOFRAME_TYPE+AUDIO_INFOFRAME_LEN );\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CC,pAudioInfoFrame->pktbyte.AUD_DB[0]);\r
- checksum -= HDMITX_ReadI2C_Byte(REG_TX_PKT_AUDINFO_CC); checksum &= 0xFF ;\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SF,pAudioInfoFrame->pktbyte.AUD_DB[1]);\r
- checksum -= HDMITX_ReadI2C_Byte(REG_TX_PKT_AUDINFO_SF); checksum &= 0xFF ;\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CA,pAudioInfoFrame->pktbyte.AUD_DB[3]);\r
- checksum -= HDMITX_ReadI2C_Byte(REG_TX_PKT_AUDINFO_CA); checksum &= 0xFF ;\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_DM_LSV,pAudioInfoFrame->pktbyte.AUD_DB[4]);\r
- checksum -= HDMITX_ReadI2C_Byte(REG_TX_PKT_AUDINFO_DM_LSV); checksum &= 0xFF ;\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SUM,checksum);\r
-\r
- Switch_HDMITX_Bank(0);\r
- hdmitx_ENABLE_AUD_INFOFRM_PKT();\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetSPDInfoFrame()\r
-// Parameter: pSPDInfoFrame - the pointer to HDMI SPD Infoframe ucData\r
-// Return: N/A\r
-// Remark: Fill the SPD InfoFrame ucData,and count checksum,then fill into\r
-// SPD InfoFrame registers.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame)\r
-{\r
- int i ;\r
- BYTE ucData ;\r
-\r
- if(!pSPDInfoFrame)\r
- {\r
- return ER_FAIL ;\r
- }\r
- Switch_HDMITX_Bank(1);\r
- for(i = 0,ucData = 0 ; i < 25 ; i++)\r
- {\r
- ucData -= pSPDInfoFrame->pktbyte.SPD_DB[i] ;\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_PB1+i,pSPDInfoFrame->pktbyte.SPD_DB[i]);\r
- }\r
- ucData -= SPD_INFOFRAME_VER+SPD_INFOFRAME_TYPE+SPD_INFOFRAME_LEN ;\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_SUM,ucData); // checksum\r
- Switch_HDMITX_Bank(0);\r
- hdmitx_ENABLE_SPD_INFOFRM_PKT();\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_SetMPEGInfoFrame()\r
-// Parameter: pMPEGInfoFrame - the pointer to HDMI MPEG Infoframe ucData\r
-// Return: N/A\r
-// Remark: Fill the MPEG InfoFrame ucData,and count checksum,then fill into\r
-// MPEG InfoFrame registers.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame)\r
-{\r
- int i ;\r
- BYTE ucData ;\r
-\r
- if(!pMPGInfoFrame)\r
- {\r
- return ER_FAIL ;\r
- }\r
- Switch_HDMITX_Bank(1);\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_PKT_MPGINFO_FMT,pMPGInfoFrame->info.FieldRepeat|(pMPGInfoFrame->info.MpegFrame<<1));\r
- HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB0,pMPGInfoFrame->pktbyte.MPG_DB[0]);\r
- HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB1,pMPGInfoFrame->pktbyte.MPG_DB[1]);\r
- HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB2,pMPGInfoFrame->pktbyte.MPG_DB[2]);\r
- HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB3,pMPGInfoFrame->pktbyte.MPG_DB[3]);\r
-\r
- for(ucData = 0,i = 0 ; i < 5 ; i++)\r
- {\r
- ucData -= pMPGInfoFrame->pktbyte.MPG_DB[i] ;\r
- }\r
- ucData -= MPEG_INFOFRAME_VER+MPEG_INFOFRAME_TYPE+MPEG_INFOFRAME_LEN ;\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_SUM,ucData);\r
-\r
- Switch_HDMITX_Bank(0);\r
- hdmitx_ENABLE_SPD_INFOFRM_PKT();\r
-\r
- return ER_SUCCESS ;\r
-}\r
-\r
-// 2009/12/04 added by Ming-chih.lung@ite.com.tw\r
-\r
-SYS_STATUS hdmitx_SetVSIInfoFrame(VendorSpecific_InfoFrame *pVSIInfoFrame)\r
-{\r
- BYTE ucData=0 ;\r
-\r
- if(!pVSIInfoFrame)\r
- {\r
- return ER_FAIL ;\r
- }\r
-\r
- Switch_HDMITX_Bank(1);\r
- HDMITX_WriteI2C_Byte(0x80,pVSIInfoFrame->pktbyte.VS_DB[3]);\r
- HDMITX_WriteI2C_Byte(0x81,pVSIInfoFrame->pktbyte.VS_DB[4]);\r
-\r
- ucData -= pVSIInfoFrame->pktbyte.VS_DB[3] ;\r
- ucData -= pVSIInfoFrame->pktbyte.VS_DB[4] ;\r
-\r
- if( pVSIInfoFrame->pktbyte.VS_DB[4] & (1<<7 ))\r
- {\r
- ucData -= pVSIInfoFrame->pktbyte.VS_DB[5] ;\r
- HDMITX_WriteI2C_Byte(0x82,pVSIInfoFrame->pktbyte.VS_DB[5]);\r
- ucData -= VENDORSPEC_INFOFRAME_TYPE + VENDORSPEC_INFOFRAME_VER + 6 + 0x0C + 0x03 ;\r
- }\r
- else\r
- {\r
- ucData -= VENDORSPEC_INFOFRAME_TYPE + VENDORSPEC_INFOFRAME_VER + 5 + 0x0C + 0x03 ;\r
- }\r
-\r
- pVSIInfoFrame->pktbyte.CheckSum=ucData;\r
-\r
- HDMITX_WriteI2C_Byte(0x83,pVSIInfoFrame->pktbyte.CheckSum);\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(REG_TX_3D_INFO_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT);\r
- return ER_SUCCESS ;\r
-}\r
-\r
-SYS_STATUS hdmitx_Set_GeneralPurpose_PKT(BYTE *pData)\r
-{\r
- int i ;\r
-\r
- if( pData == NULL )\r
- {\r
- return ER_FAIL ;\r
-\r
- }\r
- Switch_HDMITX_Bank(1);\r
- for( i = 0x38 ; i <= 0x56 ; i++)\r
- {\r
- HDMITX_WriteI2C_Byte(i, pData[i-0x38] );\r
- }\r
- Switch_HDMITX_Bank(0);\r
- hdmitx_ENABLE_GeneralPurpose_PKT();\r
- //hdmitx_ENABLE_NULL_PKT();\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: DumpHDMITXReg()\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: Debug function,dumps the registers of CAT6611.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#if Debug_message\r
-void DumpHDMITXReg()\r
-{\r
- int i,j ;\r
- BYTE ucData ;\r
-\r
- printk( "[%s]\n", __FUNCTION__);\r
- HDMITX_DEBUG_PRINTF((" "));\r
- for(j = 0 ; j < 16 ; j++)\r
- {\r
- HDMITX_DEBUG_PRINTF((" %02X",(int)j));\r
- if((j == 3)||(j==7)||(j==11))\r
- {\r
- HDMITX_DEBUG_PRINTF((" "));\r
- }\r
- }\r
- HDMITX_DEBUG_PRINTF(("\n -----------------------------------------------------\n"));\r
-\r
- Switch_HDMITX_Bank(0);\r
-\r
- for(i = 0 ; i < 0x100 ; i+=16)\r
- {\r
- HDMITX_DEBUG_PRINTF(("[%3X] ",i));\r
- for(j = 0 ; j < 16 ; j++)\r
- {\r
- if( (i+j)!= 0x17)\r
- {\r
- ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF));\r
- HDMITX_DEBUG_PRINTF((" %02X",(int)ucData));\r
- }\r
- else\r
- {\r
- HDMITX_DEBUG_PRINTF((" XX")); // for DDC FIFO\r
- }\r
- if((j == 3)||(j==7)||(j==11))\r
- {\r
- HDMITX_DEBUG_PRINTF((" -"));\r
- }\r
- }\r
- HDMITX_DEBUG_PRINTF(("\n"));\r
- if((i % 0x40) == 0x30)\r
- {\r
- HDMITX_DEBUG_PRINTF((" -----------------------------------------------------\n"));\r
- }\r
- }\r
- Switch_HDMITX_Bank(1);\r
- for(i = 0x130; i < 0x200 ; i+=16)\r
- {\r
- HDMITX_DEBUG_PRINTF(("[%3X] ",i));\r
- for(j = 0 ; j < 16 ; j++)\r
- {\r
- ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF));\r
- HDMITX_DEBUG_PRINTF((" %02X",(int)ucData));\r
- if((j == 3)||(j==7)||(j==11))\r
- {\r
- HDMITX_DEBUG_PRINTF((" -"));\r
- }\r
- }\r
- HDMITX_DEBUG_PRINTF(("\n"));\r
- if((i % 0x40) == 0x20)\r
- {\r
- HDMITX_DEBUG_PRINTF((" -----------------------------------------------------\n"));\r
- }\r
- }\r
- HDMITX_DEBUG_PRINTF((" -----------------------------------------------------\n"));\r
- Switch_HDMITX_Bank(0);\r
-}\r
-\r
-#endif\r
-\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_drv.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-\r
-#ifndef _HDMITX_DRV_H_\r
-#define _HDMITX_DRV_H_\r
-\r
-//#define EXTERN_HDCPROM\r
-/////////////////////////////////////////\r
-// DDC Address\r
-/////////////////////////////////////////\r
-#define DDC_HDCP_ADDRESS 0x74\r
-#define DDC_EDID_ADDRESS 0xA0\r
-#define DDC_FIFO_MAXREQ 0x20\r
-\r
-// I2C address\r
-\r
-#define _80MHz 80000000\r
-#define HDMI_TX_I2C_SLAVE_ADDR 0x98\r
-#define CEC_I2C_SLAVE_ADDR 0x9C\r
-\r
-//#define DISABLE_HDMITX_CSC\r
-///////////////////////////////////////////////////////////////////////\r
-// Register offset\r
-///////////////////////////////////////////////////////////////////////\r
-\r
-#define REG_TX_VENDOR_ID0 0x00\r
-#define REG_TX_VENDOR_ID1 0x01\r
-#define REG_TX_DEVICE_ID0 0x02\r
-#define REG_TX_DEVICE_ID1 0x03\r
-\r
- #define O_TX_DEVID 0\r
- #define M_TX_DEVID 0xF\r
- #define O_TX_REVID 4\r
- #define M_TX_REVID 0xF\r
-\r
-#define REG_TX_SW_RST 0x04\r
- #define B_TX_ENTEST (1<<7)\r
- #define B_TX_REF_RST_HDMITX (1<<5)\r
- #define B_TX_AREF_RST (1<<4)\r
- #define B_HDMITX_VID_RST (1<<3)\r
- #define B_HDMITX_AUD_RST (1<<2)\r
- #define B_TX_HDMI_RST (1<<1)\r
- #define B_TX_HDCP_RST_HDMITX (1<<0)\r
-\r
-#define REG_TX_INT_CTRL 0x05\r
- #define B_TX_INTPOL_ACTL 0\r
- #define B_TX_INTPOL_ACTH (1<<7)\r
- #define B_TX_INT_PUSHPULL 0\r
- #define B_TX_INT_OPENDRAIN (1<<6)\r
-\r
-#define REG_TX_INT_STAT1 0x06\r
- #define B_TX_INT_AUD_OVERFLOW (1<<7)\r
- #define B_TX_INT_ROMACQ_NOACK (1<<6)\r
- #define B_TX_INT_RDDC_NOACK (1<<5)\r
- #define B_TX_INT_DDCFIFO_ERR (1<<4)\r
- #define B_TX_INT_ROMACQ_BUS_HANG (1<<3)\r
- #define B_TX_INT_DDC_BUS_HANG (1<<2)\r
- #define B_TX_INT_RX_SENSE (1<<1)\r
- #define B_TX_INT_HPD_PLUG (1<<0)\r
-\r
-#define REG_TX_INT_STAT2 0x07\r
- #define B_TX_INT_HDCP_SYNC_DET_FAIL (1<<7)\r
- #define B_TX_INT_VID_UNSTABLE (1<<6)\r
- #define B_TX_INT_PKTACP (1<<5)\r
- #define B_TX_INT_PKTNULL (1<<4)\r
- #define B_TX_INT_PKTGENERAL (1<<3)\r
- #define B_TX_INT_KSVLIST_CHK (1<<2)\r
- #define B_TX_INT_AUTH_DONE (1<<1)\r
- #define B_TX_INT_AUTH_FAIL (1<<0)\r
-\r
-#define REG_TX_INT_STAT3 0x08\r
- #define B_TX_INT_AUD_CTS (1<<6)\r
- #define B_TX_INT_VSYNC (1<<5)\r
- #define B_TX_INT_VIDSTABLE (1<<4)\r
- #define B_TX_INT_PKTMPG (1<<3)\r
- #define B_TX_INT_PKTSPD (1<<2)\r
- #define B_TX_INT_PKTAUD (1<<1)\r
- #define B_TX_INT_PKTAVI (1<<0)\r
-\r
-#define REG_TX_INT_MASK1 0x09\r
- #define B_TX_AUDIO_OVFLW_MASK (1<<7)\r
- #define B_TX_DDC_NOACK_MASK (1<<5)\r
- #define B_TX_DDC_FIFO_ERR_MASK (1<<4)\r
- #define B_TX_DDC_BUS_HANG_MASK (1<<2)\r
- #define B_TX_RXSEN_MASK (1<<1)\r
- #define B_TX_HPD_MASK (1<<0)\r
-\r
-#define REG_TX_INT_MASK2 0x0A\r
- #define B_TX_PKT_AVI_MASK (1<<7)\r
- #define B_TX_PKT_VID_UNSTABLE_MASK (1<<6)\r
- #define B_TX_PKT_ACP_MASK (1<<5)\r
- #define B_TX_PKT_NULL_MASK (1<<4)\r
- #define B_TX_PKT_GEN_MASK (1<<3)\r
- #define B_TX_KSVLISTCHK_MASK (1<<2)\r
- #define B_TX_AUTH_DONE_MASK (1<<1)\r
- #define B_TX_AUTH_FAIL_MASK (1<<0)\r
-\r
-#define REG_TX_INT_MASK3 0x0B\r
- #define B_TX_HDCP_SYNC_DET_FAIL_MASK (1<<6)\r
- #define B_TX_AUDCTS_MASK (1<<5)\r
- #define B_TX_VSYNC_MASK (1<<4)\r
- #define B_TX_VIDSTABLE_MASK (1<<3)\r
- #define B_TX_PKT_MPG_MASK (1<<2)\r
- #define B_TX_PKT_SPD_MASK (1<<1)\r
- #define B_TX_PKT_AUD_MASK (1<<0)\r
-\r
-#define REG_TX_INT_CLR0 0x0C\r
- #define B_TX_CLR_PKTACP (1<<7)\r
- #define B_TX_CLR_PKTNULL (1<<6)\r
- #define B_TX_CLR_PKTGENERAL (1<<5)\r
- #define B_TX_CLR_KSVLISTCHK (1<<4)\r
- #define B_TX_CLR_AUTH_DONE (1<<3)\r
- #define B_TX_CLR_AUTH_FAIL (1<<2)\r
- #define B_TX_CLR_RXSENSE (1<<1)\r
- #define B_TX_CLR_HPD (1<<0)\r
-\r
-#define REG_TX_INT_CLR1 0x0D\r
- #define B_TX_CLR_VSYNC (1<<7)\r
- #define B_TX_CLR_VIDSTABLE (1<<6)\r
- #define B_TX_CLR_PKTMPG (1<<5)\r
- #define B_TX_CLR_PKTSPD (1<<4)\r
- #define B_TX_CLR_PKTAUD (1<<3)\r
- #define B_TX_CLR_PKTAVI (1<<2)\r
- #define B_TX_CLR_HDCP_SYNC_DET_FAIL (1<<1)\r
- #define B_TX_CLR_VID_UNSTABLE (1<<0)\r
-\r
-#define REG_TX_SYS_STATUS 0x0E\r
- // readonly\r
- #define B_TX_INT_ACTIVE (1<<7)\r
- #define B_TX_HPDETECT (1<<6)\r
- #define B_TX_RXSENDETECT (1<<5)\r
- #define B_TXVIDSTABLE (1<<4)\r
- // read/write\r
- #define O_TX_CTSINTSTEP 2\r
- #define M_TX_CTSINTSTEP (3<<2)\r
- #define B_TX_CLR_AUD_CTS (1<<1)\r
- #define B_TX_INTACTDONE (1<<0)\r
-\r
-#define REG_TX_BANK_CTRL 0x0F\r
- #define B_TX_BANK0 0\r
- #define B_TX_BANK1 1\r
-\r
-// DDC\r
-\r
-#define REG_TX_DDC_MASTER_CTRL 0x10\r
- #define B_TX_MASTERROM (1<<1)\r
- #define B_TX_MASTERDDC (0<<1)\r
- #define B_TX_MASTERHOST (1<<0)\r
- #define B_TX_MASTERHDCP (0<<0)\r
-\r
-#define REG_TX_DDC_HEADER 0x11\r
-#define REG_TX_DDC_REQOFF 0x12\r
-#define REG_TX_DDC_REQCOUNT 0x13\r
-#define REG_TX_DDC_EDIDSEG 0x14\r
-#define REG_TX_DDC_CMD 0x15\r
- #define CMD_DDC_SEQ_BURSTREAD 0\r
- #define CMD_LINK_CHKREAD 2\r
- #define CMD_EDID_READ 3\r
- #define CMD_FIFO_CLR 9\r
- #define CMD_GEN_SCLCLK 0xA\r
- #define CMD_DDC_ABORT 0xF\r
-\r
-#define REG_TX_DDC_STATUS 0x16\r
- #define B_TX_DDC_DONE (1<<7)\r
- #define B_TX_DDC_ACT (1<<6)\r
- #define B_TX_DDC_NOACK (1<<5)\r
- #define B_TX_DDC_WAITBUS (1<<4)\r
- #define B_TX_DDC_ARBILOSE (1<<3)\r
- #define B_TX_DDC_ERROR (B_TX_DDC_NOACK|B_TX_DDC_WAITBUS|B_TX_DDC_ARBILOSE)\r
- #define B_TX_DDC_FIFOFULL (1<<2)\r
- #define B_TX_DDC_FIFOEMPTY (1<<1)\r
-\r
-#define REG_TX_DDC_READFIFO 0x17\r
-#define REG_TX_ROM_STARTADDR 0x18\r
-#define REG_TX_HDCP_HEADER 0x19\r
-#define REG_TX_ROM_HEADER 0x1A\r
-#define REG_TX_BUSHOLD_T 0x1B\r
-#define REG_TX_ROM_STAT 0x1C\r
- #define B_TX_ROM_DONE (1<<7)\r
- #define B_TX_ROM_ACTIVE (1<<6)\r
- #define B_TX_ROM_NOACK (1<<5)\r
- #define B_TX_ROM_WAITBUS (1<<4)\r
- #define B_TX_ROM_ARBILOSE (1<<3)\r
- #define B_TX_ROM_BUSHANG (1<<2)\r
-\r
-// HDCP\r
-#define REG_TX_AN_GENERATE 0x1F\r
- #define B_TX_START_CIPHER_GEN 1\r
- #define B_TX_STOP_CIPHER_GEN 0\r
-\r
-#define REG_TX_CLK_CTRL0 0x58\r
- #define O_TX_OSCLK_SEL 5\r
- #define M_TX_OSCLK_SEL 3\r
- #define B_TX_AUTO_OVER_SAMPLING_CLOCK (1<<4)\r
- #define O_TX_EXT_MCLK_SEL 2\r
- #define M_TX_EXT_MCLK_SEL (3<<O_TX_EXT_MCLK_SEL)\r
- #define B_TX_EXT_128FS (0<<O_TX_EXT_MCLK_SEL)\r
- #define B_TX_EXT_256FS (1<<O_TX_EXT_MCLK_SEL)\r
- #define B_TX_EXT_512FS (2<<O_TX_EXT_MCLK_SEL)\r
- #define B_TX_EXT_1024FS (3<<O_TX_EXT_MCLK_SEL)\r
-\r
-#define REG_TX_SHA_SEL 0x50\r
-#define REG_TX_SHA_RD_BYTE1 0x51\r
-#define REG_TX_SHA_RD_BYTE2 0x52\r
-#define REG_TX_SHA_RD_BYTE3 0x53\r
-#define REG_TX_SHA_RD_BYTE4 0x54\r
-#define REG_TX_AKSV_RD_BYTE5 0x55\r
-\r
-\r
-#define REG_TX_CLK_CTRL1 0x59\r
- #define B_TX_EN_TXCLK_COUNT (1<<5)\r
- #define B_TX_VDO_LATCH_EDGE (1<<3)\r
-\r
-#define REG_TX_CLK_STATUS1 0x5E\r
-#define REG_TX_CLK_STATUS2 0x5F\r
- #define B_TX_IP_LOCK (1<<7)\r
- #define B_TX_XP_LOCK (1<<6)\r
- #define B_TX_OSF_LOCK (1<<5)\r
-\r
-#define REG_TX_AUD_COUNT 0x60\r
-#define REG_TX_AFE_DRV_CTRL 0x61\r
-\r
- #define B_TX_AFE_DRV_PWD (1<<5)\r
- #define B_TX_AFE_DRV_RST (1<<4)\r
-\r
-#define REG_TX_PLL_CTRL 0x6A\r
-\r
-// Input Data Format Register\r
-#define REG_TX_INPUT_MODE 0x70\r
- #define O_TX_INCLKDLY 0\r
- #define M_TX_INCLKDLY 3\r
- #define B_TX_INDDR (1<<2)\r
- #define B_TX_SYNCEMB (1<<3)\r
- #define B_TX_2X656CLK (1<<4)\r
- #define B_TX_PCLKDIV2 (1<<5)\r
- #define M_TX_INCOLMOD (3<<6)\r
- #define B_TX_IN_RGB 0\r
- #define B_TX_IN_YUV422 (1<<6)\r
- #define B_TX_IN_YUV444 (2<<6)\r
-\r
-#define REG_TX_TXFIFO_RST 0x71\r
- #define B_TX_ENAVMUTERST 1\r
- #define B_TXFFRST (1<<1)\r
-\r
-#define REG_TX_CSC_CTRL 0x72\r
- #define B_HDMITX_CSC_BYPASS 0\r
- #define B_HDMITX_CSC_RGB2YUV 2\r
- #define B_HDMITX_CSC_YUV2RGB 3\r
- #define M_TX_CSC_SEL 3\r
- #define B_TX_EN_DITHER (1<<7)\r
- #define B_TX_EN_UDFILTER (1<<6)\r
- #define B_TX_DNFREE_GO (1<<5)\r
-\r
-#define SIZEOF_CSCMTX 21\r
-#define SIZEOF_CSCGAIN 6\r
-#define SIZEOF_CSCOFFSET 3\r
-\r
-\r
-#define REG_TX_CSC_YOFF 0x73\r
-#define REG_TX_CSC_COFF 0x74\r
-#define REG_TX_CSC_RGBOFF 0x75\r
-\r
-#define REG_TX_CSC_MTX11_L 0x76\r
-#define REG_TX_CSC_MTX11_H 0x77\r
-#define REG_TX_CSC_MTX12_L 0x78\r
-#define REG_TX_CSC_MTX12_H 0x79\r
-#define REG_TX_CSC_MTX13_L 0x7A\r
-#define REG_TX_CSC_MTX13_H 0x7B\r
-#define REG_TX_CSC_MTX21_L 0x7C\r
-#define REG_TX_CSC_MTX21_H 0x7D\r
-#define REG_TX_CSC_MTX22_L 0x7E\r
-#define REG_TX_CSC_MTX22_H 0x7F\r
-#define REG_TX_CSC_MTX23_L 0x80\r
-#define REG_TX_CSC_MTX23_H 0x81\r
-#define REG_TX_CSC_MTX31_L 0x82\r
-#define REG_TX_CSC_MTX31_H 0x83\r
-#define REG_TX_CSC_MTX32_L 0x84\r
-#define REG_TX_CSC_MTX32_H 0x85\r
-#define REG_TX_CSC_MTX33_L 0x86\r
-#define REG_TX_CSC_MTX33_H 0x87\r
-\r
-#define REG_TX_CSC_GAIN1V_L 0x88\r
-#define REG_TX_CSC_GAIN1V_H 0x89\r
-#define REG_TX_CSC_GAIN2V_L 0x8A\r
-#define REG_TX_CSC_GAIN2V_H 0x8B\r
-#define REG_TX_CSC_GAIN3V_L 0x8C\r
-#define REG_TX_CSC_GAIN3V_H 0x8D\r
-\r
-#define REG_TX_HVPol 0x90\r
-#define REG_TX_HfPixel 0x91\r
-#define REG_TX_HSSL 0x95\r
-#define REG_TX_HSEL 0x96\r
-#define REG_TX_HSH 0x97\r
-#define REG_TX_VSS1 0xA0\r
-#define REG_TX_VSE1 0xA1\r
-#define REG_TX_VSS2 0xA2\r
-#define REG_TX_VSE2 0xA3\r
-\r
-// HDMI General Control Registers\r
-\r
-#define REG_TX_HDMI_MODE 0xC0\r
- #define B_TX_HDMI_MODE 1\r
- #define B_TX_DVI_MODE 0\r
-#define REG_TX_AV_MUTE 0xC1\r
-#define REG_TX_GCP 0xC1\r
- #define B_TX_CLR_AVMUTE 0\r
- #define B_TX_SET_AVMUTE 1\r
- #define B_TX_SETAVMUTE (1<<0)\r
- #define B_TX_BLUE_SCR_MUTE (1<<1)\r
- #define B_TX_NODEF_PHASE (1<<2)\r
- #define B_TX_PHASE_RESYNC (1<<3)\r
-\r
- #define O_TX_COLOR_DEPTH 4\r
- #define M_TX_COLOR_DEPTH 7\r
- #define B_TX_COLOR_DEPTH_MASK (M_TX_COLOR_DEPTH<<O_TX_COLOR_DEPTH)\r
- #define B_TX_CD_NODEF 0\r
- #define B_TX_CD_24 (4<<4)\r
- #define B_TX_CD_30 (5<<4)\r
- #define B_TX_CD_36 (6<<4)\r
- #define B_TX_CD_48 (7<<4)\r
-#define REG_TX_PKT_GENERAL_CTRL 0xC6\r
-\r
-#define REG_TX_OESS_CYCLE 0xC3\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-// Macro\r
-/////////////////////////////////////////////////////////////////////\r
-#define Switch_HDMITX_Bank(x) HDMITX_SetI2C_Byte(0x0f,1, (x)&1)\r
-#define HDMITX_OrReg_Byte(reg,ormask) HDMITX_SetI2C_Byte(reg,(ormask),(ormask))\r
-#define HDMITX_AndReg_Byte(reg,andmask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) & (andmask)))\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-// data structure\r
-/////////////////////////////////////////////////////////////////////\r
-typedef struct _HDMITXDEV_STRUCT {\r
-\r
- BYTE I2C_DEV ;\r
- BYTE I2C_ADDR ;\r
-\r
- /////////////////////////////////////////////////\r
- // Interrupt Type\r
- /////////////////////////////////////////////////\r
- BYTE bIntType ; // = 0 ;\r
- /////////////////////////////////////////////////\r
- // Video Property\r
- /////////////////////////////////////////////////\r
- BYTE bInputVideoSignalType ; // for Sync Embedded,CCIR656,InputDDR\r
- /////////////////////////////////////////////////\r
- // Audio Property\r
- /////////////////////////////////////////////////\r
- BYTE bOutputAudioMode ; // = 0 ;\r
- BYTE bAudioChannelSwap ; // = 0 ;\r
- BYTE bAudioChannelEnable ;\r
- BYTE bAudFs ;\r
- unsigned long TMDSClock ;\r
- unsigned long RCLK ;\r
- BYTE bAuthenticated:1 ;\r
- BYTE bHDMIMode: 1;\r
- BYTE bIntPOL:1 ; // 0 = Low Active\r
- BYTE bHPD:1 ;\r
- // 2009/11/11 added by jj_tseng@ite.com.tw\r
- BYTE bSPDIF_OUT;\r
- BYTE TxEMEMStatus:1 ;\r
- //~jau-chih.tseng@ite.com.tw 2009/11/11\r
-} HDMITXDEV ;\r
-\r
-\r
-\r
-//~jj_tseng@chipadvanced.com\r
-\r
-typedef struct structRegSetEntry {\r
- BYTE offset ;\r
- BYTE invAndMask ;\r
- BYTE OrMask ;\r
-} RegSetEntry;\r
-\r
-#include "hdmitx_hdcp.h"\r
-#include "hdmitx_input.h"\r
-\r
-\r
-// Audio Channel Control\r
-#define REG_TX_AUDIO_CTRL0 0xE0\r
- #define M_TX_AUD_SWL (3<<6)\r
- #define M_TX_AUD_16BIT (0<<6)\r
- #define M_TX_AUD_18BIT (1<<6)\r
- #define M_TX_AUD_20BIT (2<<6)\r
- #define M_TX_AUD_24BIT (3<<6)\r
-\r
- #define B_TX_SPDIFTC (1<<5)\r
-\r
- #define B_TX_AUD_SPDIF (1<<4)\r
- #define B_TX_AUD_I2S (0<<4)\r
- #define B_TX_AUD_EN_I2S3 (1<<3)\r
- #define B_TX_AUD_EN_I2S2 (1<<2)\r
- #define B_TX_AUD_EN_I2S1 (1<<1)\r
- #define B_TX_AUD_EN_I2S0 (1<<0)\r
- #define B_TX_AUD_EN_SPDIF 1\r
-\r
-#define REG_TX_AUDIO_CTRL1 0xE1\r
- #define B_TX_AUD_FULLPKT (1<<6)\r
-\r
- #define B_TX_AUDFMT_STD_I2S (0<<0)\r
- #define B_TX_AUDFMT_32BIT_I2S (1<<0)\r
- #define B_TX_AUDFMT_LEFT_JUSTIFY (0<<1)\r
- #define B_TX_AUDFMT_RIGHT_JUSTIFY (1<<1)\r
- #define B_TX_AUDFMT_DELAY_1T_TO_WS (0<<2)\r
- #define B_TX_AUDFMT_NO_DELAY_TO_WS (1<<2)\r
- #define B_TX_AUDFMT_WS0_LEFT (0<<3)\r
- #define B_TX_AUDFMT_WS0_RIGHT (1<<3)\r
- #define B_TX_AUDFMT_MSB_SHIFT_FIRST (0<<4)\r
- #define B_TX_AUDFMT_LSB_SHIFT_FIRST (1<<4)\r
- #define B_TX_AUDFMT_RISE_EDGE_SAMPLE_WS (0<<5)\r
- #define B_TX_AUDFMT_FALL_EDGE_SAMPLE_WS (1<<5)\r
-\r
-#define REG_TX_AUDIO_FIFOMAP 0xE2\r
- #define O_TX_FIFO3SEL 6\r
- #define O_TX_FIFO2SEL 4\r
- #define O_TX_FIFO1SEL 2\r
- #define O_TX_FIFO0SEL 0\r
- #define B_TX_SELSRC3 3\r
- #define B_TX_SELSRC2 2\r
- #define B_TX_SELSRC1 1\r
- #define B_TX_SELSRC0 0\r
-\r
-#define REG_TX_AUDIO_CTRL3 0xE3\r
- #define B_TX_AUD_MULCH (1<<7)\r
- #define B_TX_EN_ZERO_CTS (1<<6)\r
- #define B_TX_CHSTSEL (1<<4)\r
- #define B_TX_S3RLCHG (1<<3)\r
- #define B_TX_S2RLCHG (1<<2)\r
- #define B_TX_S1RLCHG (1<<1)\r
- #define B_TX_S0RLCHG (1<<0)\r
-\r
-#define REG_TX_AUD_SRCVALID_FLAT 0xE4\r
- #define B_TX_AUD_SPXFLAT_SRC3 (1<<7)\r
- #define B_TX_AUD_SPXFLAT_SRC2 (1<<6)\r
- #define B_TX_AUD_SPXFLAT_SRC1 (1<<5)\r
- #define B_TX_AUD_SPXFLAT_SRC0 (1<<4)\r
- #define B_TX_AUD_ERR2FLAT (1<<3)\r
- #define B_TX_AUD_S3VALID (1<<2)\r
- #define B_TX_AUD_S2VALID (1<<1)\r
- #define B_TX_AUD_S1VALID (1<<0)\r
-\r
-#define REG_TX_AUD_HDAUDIO 0xE5\r
-#define B_TX_HBR (1<<3)\r
-#define B_TX_DSD (1<<1)\r
-\r
-//////////////////////////////////////////\r
-// Bank 1\r
-//////////////////////////////////////////\r
-\r
-#define REGPktAudCTS0 0x30 // 7:0\r
-#define REGPktAudCTS1 0x31 // 15:8\r
-#define REGPktAudCTS2 0x32 // 19:16\r
-#define REGPktAudN0 0x33 // 7:0\r
-#define REGPktAudN1 0x34 // 15:8\r
-#define REGPktAudN2 0x35 // 19:16\r
-#define REGPktAudCTSCnt0 0x35 // 3:0\r
-#define REGPktAudCTSCnt1 0x36 // 11:4\r
-#define REGPktAudCTSCnt2 0x37 // 19:12\r
-\r
-\r
-#define REG_TX_AUDCHST_MODE 0x91 // 191 REG_TX_AUD_CHSTD[2:0] 6:4\r
- // REG_TX_AUD_CHSTC 3\r
- // REG_TX_AUD_NLPCM 2\r
- // REG_TX_AUD_MONO 0\r
-#define REG_TX_AUDCHST_CAT 0x92 // 192 REG_TX_AUD_CHSTCAT 7:0\r
-#define REG_TX_AUDCHST_SRCNUM 0x93 // 193 REG_TX_AUD_CHSTSRC 3:0\r
-#define REG_TX_AUD0CHST_CHTNUM 0x94 // 194 REG_TX_AUD0_CHSTCHR 7:4\r
- // REG_TX_AUD0_CHSTCHL 3:0\r
-#define REG_TX_AUD1CHST_CHTNUM 0x95 // 195 REG_TX_AUD1_CHSTCHR 7:4\r
- // REG_TX_AUD1_CHSTCHL 3:0\r
-#define REG_TX_AUD2CHST_CHTNUM 0x96 // 196 REG_TX_AUD2_CHSTCHR 7:4\r
- // REG_TX_AUD2_CHSTCHL 3:0\r
-#define REG_TX_AUD3CHST_CHTNUM 0x97 // 197 REG_TX_AUD3_CHSTCHR 7:4\r
- // REG_TX_AUD3_CHSTCHL 3:0\r
-#define REG_TX_AUDCHST_CA_FS 0x98 // 198 REG_TX_AUD_CHSTCA 5:4\r
- // REG_TX_AUD_CHSTFS 3:0\r
-#define REG_TX_AUDCHST_OFS_WL 0x99 // 199 REG_TX_AUD_CHSTOFS 7:4\r
- // REG_TX_AUD_CHSTWL 3:0\r
-\r
-#define REG_TX_PKT_SINGLE_CTRL 0xC5\r
- #define B_TX_SINGLE_PKT 1\r
- #define B_TX_BURST_PKT\r
- #define B_TX_SW_CTS (1<<1)\r
-\r
-#define REG_TX_NULL_CTRL 0xC9\r
-#define REG_TX_ACP_CTRL 0xCA\r
-#define REG_TX_ISRC1_CTRL 0xCB\r
-#define REG_TX_ISRC2_CTRL 0xCC\r
-#define REG_TX_AVI_INFOFRM_CTRL 0xCD\r
-#define REG_TX_AUD_INFOFRM_CTRL 0xCE\r
-#define REG_TX_SPD_INFOFRM_CTRL 0xCF\r
-#define REG_TX_MPG_INFOFRM_CTRL 0xD0\r
- #define B_TX_ENABLE_PKT 1\r
- #define B_TX_REPEAT_PKT (1<<1)\r
-\r
-#define REG_TX_3D_INFO_CTRL 0xD2\r
-\r
-//////////////////////////////////////////\r
-// COMMON PACKET for NULL,ISRC1,ISRC2,SPD\r
-//////////////////////////////////////////\r
-\r
-#define REG_TX_PKT_HB00 0x38\r
-#define REG_TX_PKT_HB01 0x39\r
-#define REG_TX_PKT_HB02 0x3A\r
-\r
-#define REG_TX_PKT_PB00 0x3B\r
-#define REG_TX_PKT_PB01 0x3C\r
-#define REG_TX_PKT_PB02 0x3D\r
-#define REG_TX_PKT_PB03 0x3E\r
-#define REG_TX_PKT_PB04 0x3F\r
-#define REG_TX_PKT_PB05 0x40\r
-#define REG_TX_PKT_PB06 0x41\r
-#define REG_TX_PKT_PB07 0x42\r
-#define REG_TX_PKT_PB08 0x43\r
-#define REG_TX_PKT_PB09 0x44\r
-#define REG_TX_PKT_PB10 0x45\r
-#define REG_TX_PKT_PB11 0x46\r
-#define REG_TX_PKT_PB12 0x47\r
-#define REG_TX_PKT_PB13 0x48\r
-#define REG_TX_PKT_PB14 0x49\r
-#define REG_TX_PKT_PB15 0x4A\r
-#define REG_TX_PKT_PB16 0x4B\r
-#define REG_TX_PKT_PB17 0x4C\r
-#define REG_TX_PKT_PB18 0x4D\r
-#define REG_TX_PKT_PB19 0x4E\r
-#define REG_TX_PKT_PB20 0x4F\r
-#define REG_TX_PKT_PB21 0x50\r
-#define REG_TX_PKT_PB22 0x51\r
-#define REG_TX_PKT_PB23 0x52\r
-#define REG_TX_PKT_PB24 0x53\r
-#define REG_TX_PKT_PB25 0x54\r
-#define REG_TX_PKT_PB26 0x55\r
-#define REG_TX_PKT_PB27 0x56\r
-\r
-#define REG_TX_AVIINFO_DB1 0x58\r
-#define REG_TX_AVIINFO_DB2 0x59\r
-#define REG_TX_AVIINFO_DB3 0x5A\r
-#define REG_TX_AVIINFO_DB4 0x5B\r
-#define REG_TX_AVIINFO_DB5 0x5C\r
-#define REG_TX_AVIINFO_DB6 0x5E\r
-#define REG_TX_AVIINFO_DB7 0x5F\r
-#define REG_TX_AVIINFO_DB8 0x60\r
-#define REG_TX_AVIINFO_DB9 0x61\r
-#define REG_TX_AVIINFO_DB10 0x62\r
-#define REG_TX_AVIINFO_DB11 0x63\r
-#define REG_TX_AVIINFO_DB12 0x64\r
-#define REG_TX_AVIINFO_DB13 0x65\r
-#define REG_TX_AVIINFO_SUM 0x5D\r
-\r
-#define REG_TX_PKT_AUDINFO_CC 0x68 // [2:0]\r
-#define REG_TX_PKT_AUDINFO_SF 0x69 // [4:2]\r
-#define REG_TX_PKT_AUDINFO_CA 0x6B // [7:0]\r
-\r
-#define REG_TX_PKT_AUDINFO_DM_LSV 0x6C // [7][6:3]\r
-#define REG_TX_PKT_AUDINFO_SUM 0x6D // [7:0]\r
-\r
-// Source Product Description Info Frame\r
-#define REG_TX_PKT_SPDINFO_SUM 0x70\r
-#define REG_TX_PKT_SPDINFO_PB1 0x71\r
-#define REG_TX_PKT_SPDINFO_PB2 0x72\r
-#define REG_TX_PKT_SPDINFO_PB3 0x73\r
-#define REG_TX_PKT_SPDINFO_PB4 0x74\r
-#define REG_TX_PKT_SPDINFO_PB5 0x75\r
-#define REG_TX_PKT_SPDINFO_PB6 0x76\r
-#define REG_TX_PKT_SPDINFO_PB7 0x77\r
-#define REG_TX_PKT_SPDINFO_PB8 0x78\r
-#define REG_TX_PKT_SPDINFO_PB9 0x79\r
-#define REG_TX_PKT_SPDINFO_PB10 0x7A\r
-#define REG_TX_PKT_SPDINFO_PB11 0x7B\r
-#define REG_TX_PKT_SPDINFO_PB12 0x7C\r
-#define REG_TX_PKT_SPDINFO_PB13 0x7D\r
-#define REG_TX_PKT_SPDINFO_PB14 0x7E\r
-#define REG_TX_PKT_SPDINFO_PB15 0x7F\r
-#define REG_TX_PKT_SPDINFO_PB16 0x80\r
-#define REG_TX_PKT_SPDINFO_PB17 0x81\r
-#define REG_TX_PKT_SPDINFO_PB18 0x82\r
-#define REG_TX_PKT_SPDINFO_PB19 0x83\r
-#define REG_TX_PKT_SPDINFO_PB20 0x84\r
-#define REG_TX_PKT_SPDINFO_PB21 0x85\r
-#define REG_TX_PKT_SPDINFO_PB22 0x86\r
-#define REG_TX_PKT_SPDINFO_PB23 0x87\r
-#define REG_TX_PKT_SPDINFO_PB24 0x88\r
-#define REG_TX_PKT_SPDINFO_PB25 0x89\r
-\r
-#define REG_TX_PKT_MPGINFO_FMT 0x8A\r
-#define B_TX_MPG_FR 1\r
-#define B_TX_MPG_MF_I (1<<1)\r
-#define B_TX_MPG_MF_B (2<<1)\r
-#define B_TX_MPG_MF_P (3<<1)\r
-#define B_TX_MPG_MF_MASK (3<<1)\r
-#define REG_TX_PKG_MPGINFO_DB0 0x8B\r
-#define REG_TX_PKG_MPGINFO_DB1 0x8C\r
-#define REG_TX_PKG_MPGINFO_DB2 0x8D\r
-#define REG_TX_PKG_MPGINFO_DB3 0x8E\r
-#define REG_TX_PKG_MPGINFO_SUM 0x8F\r
-\r
-#define Frame_Pcaking 0\r
-#define Top_and_Botton 6\r
-#define Side_by_Side 8\r
-\r
-////////////////////////////////////////////////////\r
-// Function Prototype\r
-////////////////////////////////////////////////////\r
-#define hdmitx_ENABLE_NULL_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_ACP_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_ISRC1_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_ISRC2_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_AVI_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_AUD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_SPD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_MPG_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_ENABLE_GeneralPurpose_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,B_TX_ENABLE_PKT|B_TX_REPEAT_PKT); }\r
-#define hdmitx_DISABLE_VSDB_PKT() { HDMITX_WriteI2C_Byte(REG_TX_3D_INFO_CTRL,0); }\r
-#define hdmitx_DISABLE_NULL_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,0); }\r
-#define hdmitx_DISABLE_ACP_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,0); }\r
-#define hdmitx_DISABLE_ISRC1_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,0); }\r
-#define hdmitx_DISABLE_ISRC2_PKT() { HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,0); }\r
-#define hdmitx_DISABLE_AVI_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,0); }\r
-#define hdmitx_DISABLE_AUD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,0); }\r
-#define hdmitx_DISABLE_SPD_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,0); }\r
-#define hdmitx_DISABLE_MPG_INFOFRM_PKT() { HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,0); }\r
-#define hdmitx_DISABLE_GeneralPurpose_PKT() { HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,0); }\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// External Interface\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-typedef enum {\r
- PCLK_LOW = 0 ,\r
- PCLK_MEDIUM,\r
- PCLK_HIGH\r
-} VIDEOPCLKLEVEL ;\r
-\r
-// 2008/08/18 added by jj_tseng@chipadvanced.com\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-void InitHDMITX(void);\r
-void HDMITX_InitTxDev(HDMITXDEV *pInstance);\r
-BYTE CheckHDMITX(BYTE *pHPD,BYTE *pHPDChange);\r
-BOOL getHDMITX_LinkStatus(void);\r
-BOOL getHDMI_PowerStatus(void);\r
-void HDMITX_PowerOn(void);\r
-void HDMITX_PowerDown(void);\r
-\r
-void hdmitx_LoadRegSetting(RegSetEntry table[]);\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX video function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-void HDMITX_DisableVideoOutput(void);\r
-BOOL HDMITX_EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI);\r
-BOOL setHDMITX_VideoSignalType(BYTE inputSignalType);\r
-void setHDMITX_ColorDepthPhase(BYTE ColorDepth,BYTE bPhase);\r
-\r
-// TBD ...\r
-// #ifdef SUPPORT_DEGEN\r
-// BOOL ProgramDEGenModeByID(MODE_ID id,BYTE bInputSignalType);\r
-// #endif // SUPPORT_DEGEN\r
-\r
-#ifdef SUPPORT_SYNCEMBEDDED\r
- BOOL setHDMITX_SyncEmbeddedByVIC(BYTE VIC,BYTE bInputSignalType);\r
-#endif\r
-\r
-\r
-void hdmitx_SetInputMode(BYTE InputMode,BYTE bInputSignalType);\r
-void hdmitx_SetCSCScale(BYTE bInputMode,BYTE bOutputMode);\r
-void hdmitx_SetupAFE(VIDEOPCLKLEVEL level);\r
-void hdmitx_FireAFE(void);\r
-\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX audio function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-void HDMITX_DisableAudioOutput(void);\r
-void HDMITX_EnableAudioOutput(BYTE AudioType, BOOL bSPDIF, ULONG SampleFreq, BYTE ChNum, BYTE *pIEC60958ChStat, ULONG TMDSClock);\r
-\r
-void setHDMITX_AudioChannelEnable(BOOL EnableAudio_b);\r
-void setHDMITX_ChStat(BYTE ucIEC60958ChStat[]);\r
-void setHDMITX_DSDAudio(void);\r
-void setHDMITX_HBRAudio(BOOL bSPDIF);\r
-void setHDMITX_LPCMAudio(BYTE AudioSrcNum, BYTE AudSWL, BOOL bSPDIF);\r
-void setHDMITX_NCTS(BYTE Fs);\r
-void setHDMITX_NLPCMAudio(BOOL bSPDIF);\r
-void setHDMITX_UpdateChStatFs(ULONG Fs);\r
-\r
-BOOL hdmitx_IsAudioChang(void);\r
-void hdmitx_AutoAdjustAudio(void);\r
-\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX hdcp function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-BOOL HDMITX_EnableHDCP(BYTE bEnable);\r
-BOOL getHDMITX_AuthenticationDone(void);\r
-\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX pkt/infoframe function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-void setHDMITX_AVMute(BYTE bEnable);\r
-BOOL HDMITX_EnableAVIInfoFrame(BYTE bEnable,BYTE *pAVIInfoFrame);\r
-BOOL HDMITX_EnableAudioInfoFrame(BYTE bEnable,BYTE *pAudioInfoFrame);\r
-BOOL HDMITX_EnableVSInfoFrame(BYTE bEnable,BYTE *pVSInfoFrame);\r
-\r
-SYS_STATUS hdmitx_SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame);\r
-SYS_STATUS hdmitx_SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame);\r
-SYS_STATUS hdmitx_SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame);\r
-SYS_STATUS hdmitx_SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame);\r
-SYS_STATUS hdmitx_SetVSIInfoFrame(VendorSpecific_InfoFrame *pVSIInfoFrame);\r
-SYS_STATUS hdmitx_Set_GeneralPurpose_PKT(BYTE *pData);\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-// HDMITX ddc/edid function prototype\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-BOOL getHDMITX_EDIDBlock(int EDIDBlockID,BYTE *pEDIDData);\r
-SYS_STATUS getHDMITX_EDIDBytes(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count);\r
-\r
-void hdmitx_GenerateDDCSCLK(void);\r
-void hdmitx_ClearDDCFIFO(void);\r
-void hdmitx_AbortDDC(void);\r
-\r
-#if defined(Debug_message) && (Debug_message==1)\r
- void DumpHDMITXReg(void);\r
-#else\r
- #define DumpHDMITXReg()\r
-#endif\r
-\r
-#define delay1ms(x) mdelay(x)\r
-////////////////////////////////////////////////////////////////////\r
-// Required Interfance\r
-////////////////////////////////////////////////////////////////////\r
-BYTE HDMITX_ReadI2C_Byte(BYTE RegAddr);\r
-SYS_STATUS HDMITX_WriteI2C_Byte(BYTE RegAddr,BYTE d);\r
-SYS_STATUS HDMITX_ReadI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);\r
-SYS_STATUS HDMITX_WriteI2C_ByteN(BYTE RegAddr,BYTE *pData,int N);\r
-SYS_STATUS HDMITX_SetI2C_Byte(BYTE Reg,BYTE Mask,BYTE Value);\r
-//SYS_STATUS HDMITX_ToggleBit(BYTE Reg,BYTE n);\r
-\r
-\r
-#endif // _HDMITX_DRV_H_\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_hdcp.c>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-#include "hdmitx.h"\r
-#include "hdmitx_drv.h"\r
-#include "sha1.h"\r
-\r
-static BYTE countbit(BYTE b);\r
-\r
-extern HDMITXDEV hdmiTxDev[HDMITX_MAX_DEV_COUNT] ;\r
-\r
-#ifdef SUPPORT_SHA\r
-_XDATA BYTE SHABuff[64] ;\r
-_XDATA BYTE V[20] ;\r
-_XDATA BYTE KSVList[32] ;\r
-_XDATA BYTE Vr[20] ;\r
-_XDATA BYTE M0[8] ;\r
-#endif\r
-\r
-BOOL HDMITX_EnableHDCP(BYTE bEnable)\r
-{\r
-#ifdef SUPPORT_HDCP\r
- if(bEnable)\r
- {\r
- if(ER_FAIL == hdmitx_hdcp_Authenticate())\r
- {\r
- HDCP_DEBUG_PRINTF(("ER_FAIL == hdmitx_hdcp_Authenticate\n"));\r
- hdmitx_hdcp_ResetAuth();\r
- return FALSE ;\r
- }\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate SUCCESS\n"));\r
- }\r
- else\r
- {\r
- hdmiTxDev[0].bAuthenticated=FALSE;\r
- hdmitx_hdcp_ResetAuth();\r
- }\r
-#endif\r
- return TRUE ;\r
-}\r
-\r
-#ifdef SUPPORT_HDCP\r
-\r
-BOOL getHDMITX_AuthenticationDone(void)\r
-{\r
- //HDCP_DEBUG_PRINTF((" getHDMITX_AuthenticationDone() = %s\n",hdmiTxDev[0].bAuthenticated?"TRUE":"FALSE" ));\r
- return hdmiTxDev[0].bAuthenticated;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Authentication\r
-//////////////////////////////////////////////////////////////////////\r
-void hdmitx_hdcp_ClearAuthInterrupt(void)\r
-{\r
- // BYTE uc ;\r
- // uc = HDMITX_ReadI2C_Byte(REG_TX_INT_MASK2) & (~(B_TX_KSVLISTCHK_MASK|B_TX_AUTH_DONE_MASK|B_TX_AUTH_FAIL_MASK));\r
- HDMITX_SetI2C_Byte(REG_TX_INT_MASK2, B_TX_KSVLISTCHK_MASK|B_TX_AUTH_DONE_MASK|B_TX_AUTH_FAIL_MASK, 0);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_TX_CLR_AUTH_FAIL|B_TX_CLR_AUTH_DONE|B_TX_CLR_KSVLISTCHK);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_TX_INTACTDONE);\r
-}\r
-\r
-void hdmitx_hdcp_ResetAuth(void)\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,0);\r
- HDMITX_OrReg_Byte(REG_TX_SW_RST,B_TX_HDCP_RST_HDMITX);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- hdmitx_hdcp_ClearAuthInterrupt();\r
- hdmitx_AbortDDC();\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_Auth_Fire()\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: write anything to reg21 to enable HDCP authentication by HW\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_Auth_Fire(void)\r
-{\r
- // HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Auth_Fire():\n"));\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHDCP); // MASTERHDCP,no need command but fire.\r
- HDMITX_WriteI2C_Byte(REG_TX_AUTHFIRE,1);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_StartAnCipher\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: Start the Cipher to free run for random number. When stop,An is\r
-// ready in Reg30.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_StartAnCipher(void)\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_TX_START_CIPHER_GEN);\r
- delay1ms(1); // delay 1 ms\r
-}\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_StopAnCipher\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: Stop the Cipher,and An is ready in Reg30.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_StopAnCipher(void)\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_TX_STOP_CIPHER_GEN);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_GenerateAn\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: start An ciper random run at first,then stop it. Software can get\r
-// an in reg30~reg38,the write to reg28~2F\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_GenerateAn(void)\r
-{\r
- BYTE Data[8];\r
- BYTE i=0;\r
-#if 1\r
- hdmitx_hdcp_StartAnCipher();\r
- // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_TX_START_CIPHER_GEN);\r
- // delay1ms(1); // delay 1 ms\r
- // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_TX_STOP_CIPHER_GEN);\r
-\r
- hdmitx_hdcp_StopAnCipher();\r
-\r
- Switch_HDMITX_Bank(0);\r
- // new An is ready in reg30\r
- HDMITX_ReadI2C_ByteN(REG_TX_AN_GEN,Data,8);\r
-#else\r
- Data[0] = 0 ;Data[1] = 0 ;Data[2] = 0 ;Data[3] = 0 ;\r
- Data[4] = 0 ;Data[5] = 0 ;Data[6] = 0 ;Data[7] = 0 ;\r
-#endif\r
- for(i=0;i<8;i++)\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_AN+i,Data[i]);\r
- }\r
- //HDMITX_WriteI2C_ByteN(REG_TX_AN,Data,8);\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_GetBCaps\r
-// Parameter: pBCaps - pointer of byte to get BCaps.\r
-// pBStatus - pointer of two bytes to get BStatus\r
-// Return: ER_SUCCESS if successfully got BCaps and BStatus.\r
-// Remark: get B status and capability from HDCP reciever via DDC bus.\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_hdcp_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus)\r
-{\r
- BYTE ucdata ;\r
- BYTE TimeOut ;\r
-\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x40); // BCaps offset\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,3);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD);\r
-\r
- for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- delay1ms(1);\r
-\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
-\r
- if(ucdata & B_TX_DDC_DONE)\r
- {\r
- //HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps(): DDC Done.\n"));\r
- break ;\r
- }\r
- if(ucdata & B_TX_DDC_ERROR)\r
- {\r
-// HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps(): DDC fail by reg16=%02X.\n",ucdata));\r
- return ER_FAIL ;\r
- }\r
- }\r
- if(TimeOut == 0)\r
- {\r
- return ER_FAIL ;\r
- }\r
-#if 1\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_BSTAT+1);\r
-\r
- *pBStatus = (USHORT)ucdata ;\r
- *pBStatus <<= 8 ;\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_BSTAT);\r
- *pBStatus |= ((USHORT)ucdata&0xFF);\r
- *pBCaps = HDMITX_ReadI2C_Byte(REG_TX_BCAP);\r
-#else\r
- *pBCaps = HDMITX_ReadI2C_Byte(0x17);\r
- *pBStatus = HDMITX_ReadI2C_Byte(0x17) & 0xFF ;\r
- *pBStatus |= (int)(HDMITX_ReadI2C_Byte(0x17)&0xFF)<<8;\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps(): ucdata = %02X\n",(int)HDMITX_ReadI2C_Byte(0x16)));\r
-#endif\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_GetBKSV\r
-// Parameter: pBKSV - pointer of 5 bytes buffer for getting BKSV\r
-// Return: ER_SUCCESS if successfuly got BKSV from Rx.\r
-// Remark: Get BKSV from HDCP reciever.\r
-// Side-Effect: N/A\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_hdcp_GetBKSV(BYTE *pBKSV)\r
-{\r
- BYTE ucdata ;\r
- BYTE TimeOut ;\r
-\r
- Switch_HDMITX_Bank(0);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x00); // BKSV offset\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,5);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD);\r
-\r
- for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- delay1ms(1);\r
-\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
- if(ucdata & B_TX_DDC_DONE)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps(): DDC Done.\n"));\r
- break ;\r
- }\r
- if(ucdata & B_TX_DDC_ERROR)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps(): DDC No ack or arbilose,%x,maybe cable did not connected. Fail.\n",ucdata));\r
- return ER_FAIL ;\r
- }\r
- }\r
- if(TimeOut == 0)\r
- {\r
- return ER_FAIL ;\r
- }\r
- HDMITX_ReadI2C_ByteN(REG_TX_BKSV,(PBYTE)pBKSV,5);\r
-\r
- return ER_SUCCESS ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function:hdmitx_hdcp_Authenticate\r
-// Parameter: N/A\r
-// Return: ER_SUCCESS if Authenticated without error.\r
-// Remark: do Authentication with Rx\r
-// Side-Effect:\r
-// 1. hdmiTxDev[0].bAuthenticated global variable will be TRUE when authenticated.\r
-// 2. Auth_done interrupt and AUTH_FAIL interrupt will be enabled.\r
-//////////////////////////////////////////////////////////////////////\r
-static BYTE countbit(BYTE b)\r
-{\r
- BYTE i,count ;\r
- for( i = 0, count = 0 ; i < 8 ; i++ )\r
- {\r
- if( b & (1<<i) )\r
- {\r
- count++ ;\r
- }\r
- }\r
- return count ;\r
-}\r
-\r
-void hdmitx_hdcp_Reset(void)\r
-{\r
- BYTE uc ;\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_TX_HDCP_RST_HDMITX ;\r
- HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc);\r
- HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERHOST);\r
- hdmitx_ClearDDCFIFO();\r
- hdmitx_AbortDDC();\r
-}\r
-\r
-SYS_STATUS hdmitx_hdcp_Authenticate()\r
-{\r
- BYTE ucdata ;\r
- BYTE BCaps ;\r
- USHORT BStatus ;\r
- USHORT TimeOut ;\r
-\r
- // BYTE revoked = FALSE ;\r
- BYTE BKSV[5] ;\r
-\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
- if(0==(B_TXVIDSTABLE&HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS)))\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate(): Video not stable\n"));\r
- return ER_FAIL;\r
- }\r
- // Authenticate should be called after AFE setup up.\r
-\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate():\n"));\r
- hdmitx_hdcp_Reset();\r
-\r
- Switch_HDMITX_Bank(0);\r
-\r
- for( TimeOut = 0 ; TimeOut < 80 ; TimeOut++ )\r
- {\r
- delay1ms(15);\r
-\r
- if(hdmitx_hdcp_GetBCaps(&BCaps,&BStatus) != ER_SUCCESS)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetBCaps fail.\n"));\r
- return ER_FAIL ;\r
- }\r
- // HDCP_DEBUG_PRINTF(("(%d)Reg16 = %02X\n",idx++,(int)HDMITX_ReadI2C_Byte(0x16)));\r
-\r
- if(B_TX_HDMI_MODE == (HDMITX_ReadI2C_Byte(REG_TX_HDMI_MODE) & B_TX_HDMI_MODE ))\r
- {\r
- if((BStatus & B_TX_CAP_HDMI_MODE)==B_TX_CAP_HDMI_MODE)\r
- {\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- if((BStatus & B_TX_CAP_HDMI_MODE)!=B_TX_CAP_HDMI_MODE)\r
- {\r
- break;\r
- }\r
- }\r
- }\r
- /*\r
- if((BStatus & M_TX_DOWNSTREAM_COUNT)> 6)\r
- {\r
- HDCP_DEBUG_PRINTF(("Down Stream Count %d is over maximum supported number 6,fail.\n",(int)(BStatus & M_TX_DOWNSTREAM_COUNT)));\r
- return ER_FAIL ;\r
- }\r
- */\r
- HDCP_DEBUG_PRINTF(("BCAPS = %02X BSTATUS = %04X\n", (int)BCaps, BStatus));\r
- hdmitx_hdcp_GetBKSV(BKSV);\r
- HDCP_DEBUG_PRINTF(("BKSV %02X %02X %02X %02X %02X\n",(int)BKSV[0],(int)BKSV[1],(int)BKSV[2],(int)BKSV[3],(int)BKSV[4]));\r
-\r
- for(TimeOut = 0, ucdata = 0 ; TimeOut < 5 ; TimeOut ++)\r
- {\r
- ucdata += countbit(BKSV[TimeOut]);\r
- }\r
- if( ucdata != 20 )\r
- {\r
- HDCP_DEBUG_PRINTF(("countbit error\n"));\r
- return ER_FAIL ;\r
-\r
- }\r
- Switch_HDMITX_Bank(0); // switch bank action should start on direct register writting of each function.\r
-\r
- HDMITX_AndReg_Byte(REG_TX_SW_RST,~(B_TX_HDCP_RST_HDMITX));\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,B_TX_CPDESIRE);\r
- hdmitx_hdcp_ClearAuthInterrupt();\r
-\r
- hdmitx_hdcp_GenerateAn();\r
- HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0);\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
-\r
- hdmitx_ClearDDCFIFO();\r
-\r
- if((BCaps & B_TX_CAP_HDMI_REPEATER) == 0)\r
- {\r
- hdmitx_hdcp_Auth_Fire();\r
- // wait for status ;\r
-\r
- for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- delay1ms(5); // delay 1ms\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_AUTH_STAT);\r
- // HDCP_DEBUG_PRINTF(("reg46 = %02x reg16 = %02x\n",(int)ucdata,(int)HDMITX_ReadI2C_Byte(0x16)));\r
-\r
- if(ucdata & B_TX_AUTH_DONE)\r
- {\r
- hdmiTxDev[0].bAuthenticated = TRUE ;\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate()-receiver: Authenticate SUCESS\n"));\r
- break ;\r
- }\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2);\r
- if(ucdata & B_TX_INT_AUTH_FAIL)\r
- {\r
-\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_TX_CLR_AUTH_FAIL);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_TX_INTACTDONE);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0);\r
-\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate()-receiver: Authenticate fail\n"));\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
- return ER_FAIL ;\r
- }\r
- }\r
- if(TimeOut == 0)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate()-receiver: Time out. return fail\n"));\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
- return ER_FAIL ;\r
- }\r
- return ER_SUCCESS ;\r
- }\r
- return hdmitx_hdcp_Authenticate_Repeater();\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_VerifyIntegration\r
-// Parameter: N/A\r
-// Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail.\r
-// Remark: no used now.\r
-// Side-Effect:\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-SYS_STATUS hdmitx_hdcp_VerifyIntegration()\r
-{\r
- // if any interrupt issued a Auth fail,returned the Verify Integration fail.\r
-\r
- if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_TX_INT_AUTH_FAIL)\r
- {\r
- hdmitx_hdcp_ClearAuthInterrupt();\r
- hdmiTxDev[0].bAuthenticated = FALSE ;\r
- return ER_FAIL ;\r
- }\r
- if(hdmiTxDev[0].bAuthenticated == TRUE)\r
- {\r
- return ER_SUCCESS ;\r
- }\r
- return ER_FAIL ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_Authenticate_Repeater\r
-// Parameter: BCaps and BStatus\r
-// Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail.\r
-// Remark:\r
-// Side-Effect: as Authentication\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_CancelRepeaterAuthenticate()\r
-{\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_CancelRepeaterAuthenticate"));\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERDDC|B_TX_MASTERHOST);\r
- hdmitx_AbortDDC();\r
- HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_TX_LISTFAIL|B_TX_LISTDONE);\r
- hdmitx_hdcp_ClearAuthInterrupt();\r
-}\r
-\r
-void hdmitx_hdcp_ResumeRepeaterAuthenticate()\r
-{\r
- HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_TX_LISTDONE);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERHDCP);\r
-}\r
-\r
-#if 0 // def SUPPORT_SHA\r
-// #define SHA_BUFF_COUNT 17\r
-// _XDATA ULONG w[SHA_BUFF_COUNT];\r
-//\r
-// _XDATA ULONG sha[5] ;\r
-//\r
-// #define rol(x,y) (((x) << (y)) | (((ULONG)x) >> (32-y)))\r
-//\r
-// void SHATransform(ULONG * h)\r
-// {\r
-// int t,i;\r
-// ULONG tmp ;\r
-//\r
-// h[0] = 0x67452301 ;\r
-// h[1] = 0xefcdab89;\r
-// h[2] = 0x98badcfe;\r
-// h[3] = 0x10325476;\r
-// h[4] = 0xc3d2e1f0;\r
-// for( t = 0 ; t < 80 ; t++ )\r
-// {\r
-// if((t>=16)&&(t<80)) {\r
-// i=(t+SHA_BUFF_COUNT-3)%SHA_BUFF_COUNT;\r
-// tmp = w[i];\r
-// i=(t+SHA_BUFF_COUNT-8)%SHA_BUFF_COUNT;\r
-// tmp ^= w[i];\r
-// i=(t+SHA_BUFF_COUNT-14)%SHA_BUFF_COUNT;\r
-// tmp ^= w[i];\r
-// i=(t+SHA_BUFF_COUNT-16)%SHA_BUFF_COUNT;\r
-// tmp ^= w[i];\r
-// w[t%SHA_BUFF_COUNT] = rol(tmp,1);\r
-// //HDCP_DEBUG_PRINTF(("w[%2d] = %08lX\n",t,w[t%SHA_BUFF_COUNT]));\r
-// }\r
-//\r
-// if((t>=0)&&(t<20)) {\r
-// tmp = rol(h[0],5) + ((h[1] & h[2]) | (h[3] & ~h[1])) + h[4] + w[t%SHA_BUFF_COUNT] + 0x5a827999;\r
-// //HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-//\r
-// h[4] = h[3];\r
-// h[3] = h[2];\r
-// h[2] = rol(h[1],30);\r
-// h[1] = h[0];\r
-// h[0] = tmp;\r
-//\r
-// }\r
-// if((t>=20)&&(t<40)) {\r
-// tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t%SHA_BUFF_COUNT] + 0x6ed9eba1;\r
-// //HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-// h[4] = h[3];\r
-// h[3] = h[2];\r
-// h[2] = rol(h[1],30);\r
-// h[1] = h[0];\r
-// h[0] = tmp;\r
-// }\r
-// if((t>=40)&&(t<60)) {\r
-// tmp = rol(h[0], 5) + ((h[1] & h[2]) | (h[1] & h[3]) | (h[2] & h[3])) + h[4] + w[t%SHA_BUFF_COUNT] +\r
-// 0x8f1bbcdc;\r
-// //HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-// h[4] = h[3];\r
-// h[3] = h[2];\r
-// h[2] = rol(h[1],30);\r
-// h[1] = h[0];\r
-// h[0] = tmp;\r
-// }\r
-// if((t>=60)&&(t<80)) {\r
-// tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t%SHA_BUFF_COUNT] + 0xca62c1d6;\r
-// //HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-// h[4] = h[3];\r
-// h[3] = h[2];\r
-// h[2] = rol(h[1],30);\r
-// h[1] = h[0];\r
-// h[0] = tmp;\r
-// }\r
-// }\r
-// HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-//\r
-// h[0] += 0x67452301 ;\r
-// h[1] += 0xefcdab89;\r
-// h[2] += 0x98badcfe;\r
-// h[3] += 0x10325476;\r
-// h[4] += 0xc3d2e1f0;\r
-// // HDCP_DEBUG_PRINTF(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-// }\r
-//\r
-// /* ----------------------------------------------------------------------\r
-// * Outer SHA algorithm: take an arbitrary length byte string,\r
-// * convert it into 16-word blocks with the prescribed padding at\r
-// * the end,and pass those blocks to the core SHA algorithm.\r
-// */\r
-//\r
-// void SHA_Simple(void *p,LONG len,BYTE *output)\r
-// {\r
-// // SHA_State s;\r
-// int i, t ;\r
-// ULONG c ;\r
-// char *pBuff = p ;\r
-//\r
-// for(i=0;i < len;i+=4)\r
-// {\r
-//\r
-// t=i/4;\r
-// w[t]=0;\r
-// *((char *)&c)= pBuff[i];\r
-// *((char *)&c+1)= pBuff[i+1];\r
-// *((char *)&c+2)= pBuff[i+2];\r
-// *((char *)&c+3)= pBuff[i+3];\r
-// w[t]=c;\r
-// }\r
-//\r
-// c=0x80;\r
-// c<<=((3-len%4)*8);\r
-// w[t] |= c;\r
-//\r
-// /*\r
-// for( i = 0 ; i < len ; i++ )\r
-// {\r
-// t = i/4 ;\r
-// if( i%4 == 0 )\r
-// {\r
-// w[t] = 0 ;\r
-// }\r
-// c = pBuff[i] ;\r
-// c &= 0xFF ;\r
-// c <<= (3-(i%4))*8 ;\r
-// w[t] |= c ;\r
-// // HDCP_DEBUG_PRINTF(("pBuff[%d] = %02x, c = %08lX, w[%d] = %08lX\n",i,pBuff[i],c,t,w[t]));\r
-// }\r
-//\r
-// t = i/4 ;\r
-// if( i%4 == 0 )\r
-// {\r
-// w[t] = 0 ;\r
-// }\r
-// c = 0x80;\r
-// c <<= ((3-i%4)*8);\r
-// w[t]|= c ;\r
-// */\r
-// t++ ;\r
-// for( ; t < 15 ; t++ )\r
-// {\r
-// w[t] = 0 ;\r
-// }\r
-// w[15] = len*8 ;\r
-//\r
-// for( t = 0 ; t< 16 ; t++ )\r
-// {\r
-// HDCP_DEBUG_PRINTF(("w[%2d] = %08lX\n",t,w[t]));\r
-// }\r
-//\r
-// SHATransform(sha);\r
-//\r
-// for( i = 0 ; i < 5 ; i++ )\r
-// {\r
-// output[i*4] = (BYTE)(sha[i]&0xFF);\r
-// output[i*4+1] = (BYTE)((sha[i]>>8)&0xFF);\r
-// output[i*4+2] = (BYTE)((sha[i]>>16)&0xFF);\r
-// output[i*4+3] = (BYTE)((sha[i]>>24)&0xFF);\r
-// }\r
-// }\r
-#endif // 0\r
-\r
-#ifdef SUPPORT_SHA\r
-\r
-SYS_STATUS hdmitx_hdcp_CheckSHA(BYTE pM0[],USHORT BStatus,BYTE pKSVList[],int cDownStream,BYTE Vr[])\r
-{\r
- int i,n ;\r
-\r
- for(i = 0 ; i < cDownStream*5 ; i++)\r
- {\r
- SHABuff[i] = pKSVList[i] ;\r
- }\r
- SHABuff[i++] = BStatus & 0xFF ;\r
- SHABuff[i++] = (BStatus>>8) & 0xFF ;\r
- for(n = 0 ; n < 8 ; n++,i++)\r
- {\r
- SHABuff[i] = pM0[n] ;\r
- }\r
- n = i ;\r
- // SHABuff[i++] = 0x80 ; // end mask\r
- for(; i < 64 ; i++)\r
- {\r
- SHABuff[i] = 0 ;\r
- }\r
- // n = cDownStream * 5 + 2 /* for BStatus */ + 8 /* for M0 */ ;\r
- // n *= 8 ;\r
- // SHABuff[62] = (n>>8) & 0xff ;\r
- // SHABuff[63] = (n>>8) & 0xff ;\r
-/*\r
- for(i = 0 ; i < 64 ; i++)\r
- {\r
- if(i % 16 == 0)\r
- {\r
- HDCP_DEBUG_PRINTF(("SHA[]: "));\r
- }\r
- HDCP_DEBUG_PRINTF((" %02X",SHABuff[i]));\r
- if((i%16)==15)\r
- {\r
- HDCP_DEBUG_PRINTF(("\n"));\r
- }\r
- }\r
- */\r
- SHA_Simple(SHABuff,n,V);\r
- for(i = 0 ; i < 20 ; i++)\r
- {\r
- if(V[i] != Vr[i])\r
- {\r
- HDCP_DEBUG_PRINTF(("V[] ="));\r
- for(i = 0 ; i < 20 ; i++)\r
- {\r
- HDCP_DEBUG_PRINTF((" %02X",(int)V[i]));\r
- }\r
- HDCP_DEBUG_PRINTF(("\nVr[] ="));\r
- for(i = 0 ; i < 20 ; i++)\r
- {\r
- HDCP_DEBUG_PRINTF((" %02X",(int)Vr[i]));\r
- }\r
- return ER_FAIL ;\r
- }\r
- }\r
- return ER_SUCCESS ;\r
-}\r
-\r
-#endif // SUPPORT_SHA\r
-\r
-SYS_STATUS hdmitx_hdcp_GetKSVList(BYTE *pKSVList,BYTE cDownStream)\r
-{\r
- BYTE TimeOut = 100 ;\r
- BYTE ucdata ;\r
-\r
- if( cDownStream == 0 )\r
- {\r
- return ER_SUCCESS ;\r
- }\r
- if( /* cDownStream == 0 || */ pKSVList == NULL)\r
- {\r
- return ER_FAIL ;\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x43);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,cDownStream * 5);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD);\r
-\r
- for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --)\r
- {\r
-\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
- if(ucdata & B_TX_DDC_DONE)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetKSVList(): DDC Done.\n"));\r
- break ;\r
- }\r
- if(ucdata & B_TX_DDC_ERROR)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetKSVList(): DDC Fail by REG_TX_DDC_STATUS = %x.\n",ucdata));\r
- return ER_FAIL ;\r
- }\r
- delay1ms(5);\r
- }\r
- if(TimeOut == 0)\r
- {\r
- return ER_FAIL ;\r
- }\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetKSVList(): KSV"));\r
- for(TimeOut = 0 ; TimeOut < cDownStream * 5 ; TimeOut++)\r
- {\r
- pKSVList[TimeOut] = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO);\r
- HDCP_DEBUG_PRINTF((" %02X",(int)pKSVList[TimeOut]));\r
- }\r
- HDCP_DEBUG_PRINTF(("\n"));\r
- return ER_SUCCESS ;\r
-}\r
-\r
-SYS_STATUS hdmitx_hdcp_GetVr(BYTE *pVr)\r
-{\r
- BYTE TimeOut ;\r
- BYTE ucdata ;\r
-\r
- if(pVr == NULL)\r
- {\r
- return ER_FAIL ;\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_TX_MASTERHOST);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x20);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,20);\r
- HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD);\r
-\r
- for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS);\r
- if(ucdata & B_TX_DDC_DONE)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetVr(): DDC Done.\n"));\r
- break ;\r
- }\r
- if(ucdata & B_TX_DDC_ERROR)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetVr(): DDC fail by REG_TX_DDC_STATUS = %x.\n",(int)ucdata));\r
- return ER_FAIL ;\r
- }\r
- delay1ms(5);\r
- }\r
- if(TimeOut == 0)\r
- {\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_GetVr(): DDC fail by timeout.\n"));\r
- return ER_FAIL ;\r
- }\r
- Switch_HDMITX_Bank(0);\r
-\r
- for(TimeOut = 0 ; TimeOut < 5 ; TimeOut++)\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL ,TimeOut);\r
- pVr[TimeOut*4] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1);\r
- pVr[TimeOut*4+1] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2);\r
- pVr[TimeOut*4+2] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3);\r
- pVr[TimeOut*4+3] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4);\r
-// HDCP_DEBUG_PRINTF(("V' = %02X %02X %02X %02X\n",(int)pVr[TimeOut*4],(int)pVr[TimeOut*4+1],(int)pVr[TimeOut*4+2],(int)pVr[TimeOut*4+3]));\r
- }\r
- return ER_SUCCESS ;\r
-}\r
-\r
-SYS_STATUS hdmitx_hdcp_GetM0(BYTE *pM0)\r
-{\r
- int i ;\r
-\r
- if(!pM0)\r
- {\r
- return ER_FAIL ;\r
- }\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,5); // read m0[31:0] from reg51~reg54\r
- pM0[0] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1);\r
- pM0[1] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2);\r
- pM0[2] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3);\r
- pM0[3] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4);\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,0); // read m0[39:32] from reg55\r
- pM0[4] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5);\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,1); // read m0[47:40] from reg55\r
- pM0[5] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5);\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,2); // read m0[55:48] from reg55\r
- pM0[6] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5);\r
- HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,3); // read m0[63:56] from reg55\r
- pM0[7] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5);\r
-\r
- HDCP_DEBUG_PRINTF(("M[] ="));\r
- for(i = 0 ; i < 8 ; i++)\r
- {\r
- HDCP_DEBUG_PRINTF(("0x%02x,",(int)pM0[i]));\r
- }\r
- HDCP_DEBUG_PRINTF(("\n"));\r
- return ER_SUCCESS ;\r
-}\r
-\r
-SYS_STATUS hdmitx_hdcp_Authenticate_Repeater()\r
-{\r
- BYTE uc ,ii;\r
- // BYTE revoked ;\r
- // int i ;\r
- BYTE cDownStream ;\r
-\r
- BYTE BCaps;\r
- USHORT BStatus ;\r
- USHORT TimeOut ;\r
-\r
- HDCP_DEBUG_PRINTF(("Authentication for repeater\n"));\r
- // emily add for test,abort HDCP\r
- // 2007/10/01 marked by jj_tseng@chipadvanced.com\r
- // HDMITX_WriteI2C_Byte(0x20,0x00);\r
- // HDMITX_WriteI2C_Byte(0x04,0x01);\r
- // HDMITX_WriteI2C_Byte(0x10,0x01);\r
- // HDMITX_WriteI2C_Byte(0x15,0x0F);\r
- // delay1ms(100);\r
- // HDMITX_WriteI2C_Byte(0x04,0x00);\r
- // HDMITX_WriteI2C_Byte(0x10,0x00);\r
- // HDMITX_WriteI2C_Byte(0x20,0x01);\r
- // delay1ms(100);\r
- // test07 = HDMITX_ReadI2C_Byte(0x7);\r
- // test06 = HDMITX_ReadI2C_Byte(0x6);\r
- // test08 = HDMITX_ReadI2C_Byte(0x8);\r
- //~jj_tseng@chipadvanced.com\r
- // end emily add for test\r
- //////////////////////////////////////\r
- // Authenticate Fired\r
- //////////////////////////////////////\r
-\r
- hdmitx_hdcp_GetBCaps(&BCaps,&BStatus);\r
- delay1ms(2);\r
- if((B_TX_INT_HPD_PLUG|B_TX_INT_RX_SENSE)&HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1))\r
- {\r
- HDCP_DEBUG_PRINTF(("HPD Before Fire Auth\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- hdmitx_hdcp_Auth_Fire();\r
- //delay1ms(550); // emily add for test\r
- for(ii=0;ii<55;ii++) //delay1ms(550); // emily add for test\r
- {\r
- if((B_TX_INT_HPD_PLUG|B_TX_INT_RX_SENSE)&HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1))\r
- {\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- delay1ms(10);\r
- }\r
- for(TimeOut = /*250*6*/10 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- HDCP_DEBUG_PRINTF(("TimeOut = %d wait part 1\n",TimeOut));\r
- if((B_TX_INT_HPD_PLUG|B_TX_INT_RX_SENSE)&HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1))\r
- {\r
- HDCP_DEBUG_PRINTF(("HPD at wait part 1\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1);\r
- if(uc & B_TX_INT_DDC_BUS_HANG)\r
- {\r
- HDCP_DEBUG_PRINTF(("DDC Bus hang\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2);\r
-\r
- if(uc & B_TX_INT_AUTH_FAIL)\r
- {\r
- /*\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_TX_CLR_AUTH_FAIL);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_TX_INTACTDONE);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0);\r
- */\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate_Repeater(): B_TX_INT_AUTH_FAIL.\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- // emily add for test\r
- // test =(HDMITX_ReadI2C_Byte(0x7)&0x4)>>2 ;\r
- if(uc & B_TX_INT_KSVLIST_CHK)\r
- {\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_TX_CLR_KSVLISTCHK);\r
- HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_TX_INTACTDONE);\r
- HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0);\r
- HDCP_DEBUG_PRINTF(("B_TX_INT_KSVLIST_CHK\n"));\r
- break ;\r
- }\r
- delay1ms(5);\r
- }\r
- if(TimeOut == 0)\r
- {\r
- HDCP_DEBUG_PRINTF(("Time out for wait KSV List checking interrupt\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- ///////////////////////////////////////\r
- // clear KSVList check interrupt.\r
- ///////////////////////////////////////\r
-\r
- for(TimeOut = 500 ; TimeOut > 0 ; TimeOut --)\r
- {\r
- HDCP_DEBUG_PRINTF(("TimeOut=%d at wait FIFO ready\n",TimeOut));\r
- if((B_TX_INT_HPD_PLUG|B_TX_INT_RX_SENSE)&HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1))\r
- {\r
- HDCP_DEBUG_PRINTF(("HPD at wait FIFO ready\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- if(hdmitx_hdcp_GetBCaps(&BCaps,&BStatus) == ER_FAIL)\r
- {\r
- HDCP_DEBUG_PRINTF(("Get BCaps fail\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- if(BCaps & B_TX_CAP_KSV_FIFO_RDY)\r
- {\r
- HDCP_DEBUG_PRINTF(("FIFO Ready\n"));\r
- break ;\r
- }\r
- delay1ms(5);\r
-\r
- }\r
- if(TimeOut == 0)\r
- {\r
- HDCP_DEBUG_PRINTF(("Get KSV FIFO ready TimeOut\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- HDCP_DEBUG_PRINTF(("Wait timeout = %d\n",TimeOut));\r
-\r
- hdmitx_ClearDDCFIFO();\r
- hdmitx_GenerateDDCSCLK();\r
- cDownStream = (BStatus & M_TX_DOWNSTREAM_COUNT);\r
-\r
- if(/*cDownStream == 0 ||*/ cDownStream > 6 || BStatus & (B_TX_MAX_CASCADE_EXCEEDED|B_TX_DOWNSTREAM_OVER))\r
- {\r
- HDCP_DEBUG_PRINTF(("Invalid Down stream count,fail\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
-#ifdef SUPPORT_SHA\r
- if(hdmitx_hdcp_GetKSVList(KSVList,cDownStream) == ER_FAIL)\r
- {\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
-#if 0\r
- for(i = 0 ; i < cDownStream ; i++)\r
- {\r
- revoked=FALSE ; uc = 0 ;\r
- for( TimeOut = 0 ; TimeOut < 5 ; TimeOut++ )\r
- {\r
- // check bit count\r
- uc += countbit(KSVList[i*5+TimeOut]);\r
- }\r
- if( uc != 20 ) revoked = TRUE ;\r
-\r
- if(revoked)\r
- {\r
-// HDCP_DEBUG_PRINTF(("KSVFIFO[%d] = %02X %02X %02X %02X %02X is revoked\n",i,(int)KSVList[i*5],(int)KSVList[i*5+1],(int)KSVList[i*5+2],(int)KSVList[i*5+3],(int)KSVList[i*5+4]));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- }\r
-#endif\r
-\r
- if(hdmitx_hdcp_GetVr(Vr) == ER_FAIL)\r
- {\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- if(hdmitx_hdcp_GetM0(M0) == ER_FAIL)\r
- {\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- // do check SHA\r
- if(hdmitx_hdcp_CheckSHA(M0,BStatus,KSVList,cDownStream,Vr) == ER_FAIL)\r
- {\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
- if((B_TX_INT_HPD_PLUG|B_TX_INT_RX_SENSE)&HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1))\r
- {\r
- HDCP_DEBUG_PRINTF(("HPD at Final\n"));\r
- goto hdmitx_hdcp_Repeater_Fail ;\r
- }\r
-#endif // SUPPORT_SHA\r
-\r
- HDCP_DEBUG_PRINTF(("hdmitx_hdcp_Authenticate()-receiver: Authenticate SUCESS\n"));\r
- hdmitx_hdcp_ResumeRepeaterAuthenticate();\r
- hdmiTxDev[0].bAuthenticated = TRUE ;\r
- return ER_SUCCESS ;\r
-\r
-hdmitx_hdcp_Repeater_Fail:\r
- hdmitx_hdcp_CancelRepeaterAuthenticate();\r
- return ER_FAIL ;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Function: hdmitx_hdcp_ResumeAuthentication\r
-// Parameter: N/A\r
-// Return: N/A\r
-// Remark: called by interrupt handler to restart Authentication and Encryption.\r
-// Side-Effect: as Authentication and Encryption.\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void hdmitx_hdcp_ResumeAuthentication()\r
-{\r
- setHDMITX_AVMute(TRUE);\r
- if(hdmitx_hdcp_Authenticate() == ER_SUCCESS)\r
- {\r
- }\r
- setHDMITX_AVMute(FALSE);\r
-}\r
-\r
-#endif // SUPPORT_HDCP\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_hdcp.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-#ifndef _HDMITX_HDCP_H_\r
-#define _HDMITX_HDCP_H_\r
-\r
-\r
-#define REG_TX_HDCP_DESIRE 0x20\r
- #define B_TX_ENABLE_HDPC11 (1<<1)\r
- #define B_TX_CPDESIRE (1<<0)\r
-\r
-#define REG_TX_AUTHFIRE 0x21\r
-#define REG_TX_LISTCTRL 0x22\r
- #define B_TX_LISTFAIL (1<<1)\r
- #define B_TX_LISTDONE (1<<0)\r
-\r
-#define REG_TX_AKSV 0x23\r
-#define REG_TX_AKSV0 0x23\r
-#define REG_TX_AKSV1 0x24\r
-#define REG_TX_AKSV2 0x25\r
-#define REG_TX_AKSV3 0x26\r
-#define REG_TX_AKSV4 0x27\r
-\r
-#define REG_TX_AN 0x28\r
-#define REG_TX_AN_GEN 0x30\r
-#define REG_TX_ARI 0x38\r
-#define REG_TX_ARI0 0x38\r
-#define REG_TX_ARI1 0x39\r
-#define REG_TX_APJ 0x3A\r
-\r
-#define REG_TX_BKSV 0x3B\r
-#define REG_TX_BRI 0x40\r
-#define REG_TX_BRI0 0x40\r
-#define REG_TX_BRI1 0x41\r
-#define REG_TX_BPJ 0x42\r
-#define REG_TX_BCAP 0x43\r
- #define B_TX_CAP_HDMI_REPEATER (1<<6)\r
- #define B_TX_CAP_KSV_FIFO_RDY (1<<5)\r
- #define B_TX_CAP_HDMI_FAST_MODE (1<<4)\r
- #define B_CAP_HDCP_1p1 (1<<1)\r
- #define B_TX_CAP_FAST_REAUTH (1<<0)\r
-#define REG_TX_BSTAT 0x44\r
-#define REG_TX_BSTAT0 0x44\r
-#define REG_TX_BSTAT1 0x45\r
- #define B_TX_CAP_HDMI_MODE (1<<12)\r
- #define B_TX_CAP_DVI_MODE (0<<12)\r
- #define B_TX_MAX_CASCADE_EXCEEDED (1<<11)\r
- #define M_TX_REPEATER_DEPTH (0x7<<8)\r
- #define O_TX_REPEATER_DEPTH 8\r
- #define B_TX_DOWNSTREAM_OVER (1<<7)\r
- #define M_TX_DOWNSTREAM_COUNT 0x7F\r
-\r
-#define REG_TX_AUTH_STAT 0x46\r
-#define B_TX_AUTH_DONE (1<<7)\r
-////////////////////////////////////////////////////\r
-// Function Prototype\r
-////////////////////////////////////////////////////\r
-\r
-BOOL getHDMITX_AuthenticationDone(void);\r
-void hdmitx_hdcp_ClearAuthInterrupt(void);\r
-void hdmitx_hdcp_ResetAuth(void);\r
-void hdmitx_hdcp_Auth_Fire(void);\r
-void hdmitx_hdcp_StartAnCipher(void);\r
-void hdmitx_hdcp_StopAnCipher(void);\r
-void hdmitx_hdcp_GenerateAn(void);\r
-SYS_STATUS hdmitx_hdcp_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus);\r
-SYS_STATUS hdmitx_hdcp_GetBKSV(BYTE *pBKSV);\r
-\r
-void hdmitx_hdcp_Reset(void);\r
-SYS_STATUS hdmitx_hdcp_Authenticate(void);\r
-SYS_STATUS hdmitx_hdcp_VerifyIntegration(void);\r
-void hdmitx_hdcp_CancelRepeaterAuthenticate(void);\r
-void hdmitx_hdcp_ResumeRepeaterAuthenticate(void);\r
-SYS_STATUS hdmitx_hdcp_CheckSHA(BYTE pM0[],USHORT BStatus,BYTE pKSVList[],int cDownStream,BYTE Vr[]);\r
-SYS_STATUS hdmitx_hdcp_GetKSVList(BYTE *pKSVList,BYTE cDownStream);\r
-SYS_STATUS hdmitx_hdcp_GetVr(BYTE *pVr);\r
-SYS_STATUS hdmitx_hdcp_GetM0(BYTE *pM0);\r
-SYS_STATUS hdmitx_hdcp_Authenticate_Repeater(void);\r
-void hdmitx_hdcp_ResumeAuthentication(void);\r
-#endif // _HDMITX_HDCP_H_\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_input.c>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-#include "hdmitx.h"\r
-#include "hdmitx_drv.h"\r
-\r
-#ifdef HDMITX_INPUT_INFO\r
-extern HDMITXDEV hdmiTxDev[HDMITX_MAX_DEV_COUNT] ;\r
-\r
-LONG CalcRCLK();\r
-LONG CalcAudFS();\r
-LONG CalcRCLK();\r
-\r
-#define InitCEC() HDMITX_SetI2C_Byte(0x0F, 0x08, 0x00)\r
-#define DisableCEC() HDMITX_SetI2C_Byte(0x0F, 0x08, 0x08)\r
-\r
-LONG CalcAudFS()\r
-{\r
- // LONG RCLK ;\r
- LONG Cnt ;\r
- LONG FS ;\r
-\r
- // RCLK = CalcRCLK();\r
- Switch_HDMITX_Bank(0);\r
- Cnt = (LONG)HDMITX_ReadI2C_Byte(0x60);\r
- FS = hdmiTxDev[0].RCLK / 2 ;\r
- FS /= Cnt ;\r
- HDMITX_DEBUG_PRINTF1(("FS = %ld RCLK = %ld, Cnt = %ld\n",FS,hdmiTxDev[0].RCLK,Cnt)) ;\r
- return FS ;\r
-}\r
-\r
-LONG CalcPCLK()\r
-{\r
- BYTE uc, div ;\r
- int i ;\r
- long sum , count, PCLK ;\r
-\r
- Switch_HDMITX_Bank(0);\r
- uc = HDMITX_ReadI2C_Byte(0x5F) & 0x80 ;\r
-\r
- if( ! uc )\r
- {\r
- return 0 ;\r
- }\r
- // InitCEC();\r
- // // uc = CEC_ReadI2C_Byte(0x09) & 0xFE ;\r
- // CEC_WriteI2C_Byte(0x09, 1);\r
- // delay1ms(100);\r
- // CEC_WriteI2C_Byte(0x09, 0);\r
- // RCLK = CEC_ReadI2C_Byte(0x47);\r
- // RCLK <<= 8 ;\r
- // RCLK |= CEC_ReadI2C_Byte(0x46);\r
- // RCLK <<= 8 ;\r
- // RCLK |= CEC_ReadI2C_Byte(0x45);\r
- // DisableCEC();\r
- // // RCLK *= 160 ; // RCLK /= 100 ;\r
- // // RCLK in KHz.\r
-\r
- HDMITX_SetI2C_Byte(0xD7, 0xF0, 0x80);\r
- delay1ms(1);\r
- HDMITX_SetI2C_Byte(0xD7, 0x80, 0x00);\r
-\r
- count = HDMITX_ReadI2C_Byte(0xD7) & 0xF ;\r
- count <<= 8 ;\r
- count |= HDMITX_ReadI2C_Byte(0xD8);\r
-\r
- for( div = 7 ; div > 0 ; div-- )\r
- {\r
- // printf("div = %d\n",(int)div) ;\r
- if(count < (1<<(11-div)) )\r
- {\r
- break ;\r
- }\r
- }\r
- HDMITX_SetI2C_Byte(0xD7, 0x70, div<<4);\r
-\r
- uc = HDMITX_ReadI2C_Byte(0xD7) & 0x7F ;\r
- for( i = 0 , sum = 0 ; i < 100 ; i ++ )\r
- {\r
- HDMITX_WriteI2C_Byte(0xD7, uc|0x80) ;\r
- delay1ms(1);\r
- HDMITX_WriteI2C_Byte(0xD7, uc) ;\r
-\r
- count = HDMITX_ReadI2C_Byte(0xD7) & 0xF ;\r
- count <<= 8 ;\r
- count |= HDMITX_ReadI2C_Byte(0xD8);\r
- sum += count ;\r
- }\r
- sum /= 100 ; count = sum ;\r
-\r
- HDMITX_DEBUG_PRINTF1(("RCLK(in GetPCLK) = %ld\n",hdmiTxDev[0].RCLK));\r
- HDMITX_DEBUG_PRINTF1(("div = %d, count = %d\n",(int)div,(int)count) );\r
- HDMITX_DEBUG_PRINTF1(("count = %ld\n",count) );\r
-\r
- PCLK = hdmiTxDev[0].RCLK * 128 / count * 16 ;\r
- PCLK *= (1<<div);\r
-\r
- if( HDMITX_ReadI2C_Byte(0x70) & 0x10 )\r
- {\r
- PCLK /= 2 ;\r
- }\r
-\r
- HDMITX_DEBUG_PRINTF1(("PCLK = %ld\n",PCLK) );\r
- return PCLK ;\r
-}\r
-\r
-LONG CalcRCLK()\r
-{\r
- // BYTE uc ;\r
- int i ;\r
- long sum, RCLKCNT ;\r
-\r
- InitCEC();\r
- sum = 0 ;\r
- for( i = 0 ; i < 5 ; i++ )\r
- {\r
- // uc = CEC_ReadI2C_Byte(0x09) & 0xFE ;\r
- CEC_WriteI2C_Byte(0x09, 1);\r
- delay1ms(100);\r
- CEC_WriteI2C_Byte(0x09, 0);\r
- RCLKCNT = CEC_ReadI2C_Byte(0x47);\r
- RCLKCNT <<= 8 ;\r
- RCLKCNT |= CEC_ReadI2C_Byte(0x46);\r
- RCLKCNT <<= 8 ;\r
- RCLKCNT |= CEC_ReadI2C_Byte(0x45);\r
- // HDMITX_DEBUG_PRINTF1(("RCLK = %ld\n",RCLKCNT) );\r
- sum += RCLKCNT ;\r
- }\r
- DisableCEC();\r
- RCLKCNT = sum * 32 ;\r
- HDMITX_DEBUG_PRINTF(("RCLK = %ld,%03ld,%03ld\n",RCLKCNT/1000000,(RCLKCNT%1000000)/1000,RCLKCNT%1000));\r
- return RCLKCNT ;\r
-}\r
-\r
-USHORT hdmitx_getInputHTotal()\r
-{\r
- BYTE uc ;\r
- USHORT hTotal ;\r
- HDMITX_SetI2C_Byte(0x0F,1,0) ;\r
- HDMITX_SetI2C_Byte(0xA8,8,8) ;\r
-\r
- uc = HDMITX_ReadI2C_Byte(0xB2) ;\r
- hTotal = (uc&1)?(1<<12):0 ;\r
- uc = HDMITX_ReadI2C_Byte(0x91) ;\r
- hTotal |= ((USHORT)uc)<<4 ;\r
- uc = HDMITX_ReadI2C_Byte(0x90) ;\r
- hTotal |= (uc&0xF0) >> 4 ;\r
- HDMITX_SetI2C_Byte(0xA8,8,0) ;\r
- return hTotal ;\r
-}\r
-\r
-USHORT hdmitx_getInputVTotal()\r
-{\r
- BYTE uc ;\r
- USHORT vTotal ;\r
- HDMITX_SetI2C_Byte(0x0F,1,0) ;\r
- HDMITX_SetI2C_Byte(0xA8,8,8) ;\r
-\r
- uc = HDMITX_ReadI2C_Byte(0x99) ;\r
- vTotal = ((USHORT)uc&0xF)<<8 ;\r
- uc = HDMITX_ReadI2C_Byte(0x98) ;\r
- vTotal |= uc;\r
- HDMITX_SetI2C_Byte(0xA8,8,0) ;\r
- return vTotal ;\r
-}\r
-\r
-BOOL hdmitx_isInputInterlace()\r
-{\r
- BYTE uc ;\r
-\r
- HDMITX_SetI2C_Byte(0x0F,1,0) ;\r
- HDMITX_SetI2C_Byte(0xA8,8,8) ;\r
-\r
- uc = HDMITX_ReadI2C_Byte(0xA5) ;\r
- HDMITX_SetI2C_Byte(0xA8,8,0) ;\r
- return uc&(1<<4)?TRUE:FALSE ;\r
-}\r
-\r
-BYTE hdmitx_getAudioCount()\r
-{\r
- return HDMITX_ReadI2C_Byte(REG_TX_AUD_COUNT) ;\r
-}\r
-#endif\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <hdmitx_input.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-#ifndef _HDMITX_DEBUG_H_\r
-#define _HDMITX_DEBUG_H_\r
-\r
-\r
-#ifdef HDMITX_INPUT_INFO\r
-LONG CalcPCLK();\r
-LONG CalcAudFS();\r
-LONG CalcRCLK();\r
-BYTE hdmitx_getAudioCount() ;\r
-\r
-USHORT hdmitx_getInputHTotal();\r
-USHORT hdmitx_getInputVTotal();\r
-BOOL hdmitx_isInputInterlace();\r
-#endif\r
-\r
-#endif\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <sha1.c>\r
-// @author Hermes.Wu@ite.com.tw\r
-// @date 2011/08/26\r
-// @fileversion: COMMON_FILE_1.01\r
-//******************************************/\r
-\r
-#include "sha1.h"\r
-\r
-\r
-#ifndef DISABLE_HDCP\r
-\r
-#define WCOUNT 17\r
-ULONG VH[5];\r
-ULONG w[WCOUNT];\r
-\r
-#define rol(x,y)(((x)<< (y))| (((ULONG)x)>> (32-y)))\r
-\r
-\r
-void SHATransform(ULONG * h)\r
-{\r
- int t;\r
- ULONG tmp;\r
-\r
-\r
- h[0]=0x67452301;\r
- h[1]=0xefcdab89;\r
- h[2]=0x98badcfe;\r
- h[3]=0x10325476;\r
- h[4]=0xc3d2e1f0;\r
-\r
- for (t=0; t < 20; t++){\r
- if(t>=16)\r
- {\r
- tmp=w[(t - 3)% WCOUNT] ^ w[(t - 8)% WCOUNT] ^ w[(t - 14)% WCOUNT] ^ w[(t - 16)% WCOUNT];\r
- w[(t)% WCOUNT]=rol(tmp,1);\r
- }\r
- HDCP_DEBUG_PRINTF2(("w[%d]=%08lX\n",t,w[(t)% WCOUNT]));\r
-\r
- tmp=rol(h[0],5)+ ((h[1] & h[2])| (h[3] & ~h[1]))+ h[4] + w[(t)% WCOUNT] + 0x5a827999;\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-\r
- h[4]=h[3];\r
- h[3]=h[2];\r
- h[2]=rol(h[1],30);\r
- h[1]=h[0];\r
- h[0]=tmp;\r
-\r
- }\r
- for (t=20; t < 40; t++){\r
- tmp=w[(t - 3)% WCOUNT] ^ w[(t - 8)% WCOUNT] ^ w[(t - 14)% WCOUNT] ^ w[(t - 16)% WCOUNT];\r
- w[(t)% WCOUNT]=rol(tmp,1);\r
- HDCP_DEBUG_PRINTF2(("w[%d]=%08lX\n",t,w[(t)% WCOUNT]));\r
- tmp=rol(h[0],5)+ (h[1] ^ h[2] ^ h[3])+ h[4] + w[(t)% WCOUNT] + 0x6ed9eba1;\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
- h[4]=h[3];\r
- h[3]=h[2];\r
- h[2]=rol(h[1],30);\r
- h[1]=h[0];\r
- h[0]=tmp;\r
- }\r
- for (t=40; t < 60; t++){\r
- tmp=w[(t - 3)% WCOUNT] ^ w[(t - 8)% WCOUNT] ^ w[(t - 14)% WCOUNT] ^ w[(t - 16)% WCOUNT];\r
- w[(t)% WCOUNT]=rol(tmp,1);\r
- HDCP_DEBUG_PRINTF2(("w[%d]=%08lX\n",t,w[(t)% WCOUNT]));\r
- tmp=rol(h[0],5)+ ((h[1] & h[2])| (h[1] & h[3])| (h[2] & h[3]))+ h[4] + w[(t)% WCOUNT] + 0x8f1bbcdc;\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
- h[4]=h[3];\r
- h[3]=h[2];\r
- h[2]=rol(h[1],30);\r
- h[1]=h[0];\r
- h[0]=tmp;\r
- }\r
- for (t=60; t < 80; t++)\r
- {\r
- tmp=w[(t - 3)% WCOUNT] ^ w[(t - 8)% WCOUNT] ^ w[(t - 14)% WCOUNT] ^ w[(t - 16)% WCOUNT];\r
- w[(t)% WCOUNT]=rol(tmp,1);\r
- HDCP_DEBUG_PRINTF2(("w[%d]=%08lX\n",t,w[(t)% WCOUNT]));\r
- tmp=rol(h[0],5)+ (h[1] ^ h[2] ^ h[3])+ h[4] + w[(t)% WCOUNT] + 0xca62c1d6;\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
- h[4]=h[3];\r
- h[3]=h[2];\r
- h[2]=rol(h[1],30);\r
- h[1]=h[0];\r
- h[0]=tmp;\r
- }\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
- h[0] +=0x67452301;\r
- h[1] +=0xefcdab89;\r
- h[2] +=0x98badcfe;\r
- h[3] +=0x10325476;\r
- h[4] +=0xc3d2e1f0;\r
-\r
- HDCP_DEBUG_PRINTF2(("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]));\r
-}\r
-\r
-void SHA_Simple(void *p,WORD len,BYTE *output)\r
-{\r
- // SHA_State s;\r
- WORD i,t;\r
- ULONG c;\r
- BYTE *pBuff=p;\r
-\r
- for(i=0;i < len;i++)\r
- {\r
- t=i/4;\r
- if(i%4==0)\r
- {\r
- w[t]=0;\r
- }\r
- c=pBuff[i];\r
- c <<=(3-(i%4))*8;\r
- w[t] |=c;\r
- HDCP_DEBUG_PRINTF2(("pBuff[%d]=%02X,c=%08lX,w[%d]=%08lX\n",(int)i,(int)pBuff[i],c,(int)t,w[t]));\r
- }\r
- t=i/4;\r
- if(i%4==0)\r
- {\r
- w[t]=0;\r
- }\r
- //c=0x80 << ((3-i%4)*24);\r
- c=0x80;\r
- c <<=((3-i%4)*8);\r
- w[t]|=c;t++;\r
- for(; t < 15;t++)\r
- {\r
- w[t]=0;\r
- }\r
- w[15]=len*8;\r
-\r
- for(i = 0 ; i < 16 ; i++)\r
- {\r
- HDCP_DEBUG_PRINTF2(("w[%d] = %08lX\n",i,w[i]));\r
- }\r
-\r
- SHATransform(VH);\r
-\r
- for(i=0;i < 5;i++)\r
- {\r
- output[i*4+3]=(BYTE)((VH[i]>>24)&0xFF);\r
- output[i*4+2]=(BYTE)((VH[i]>>16)&0xFF);\r
- output[i*4+1]=(BYTE)((VH[i]>>8)&0xFF);\r
- output[i*4+0]=(BYTE)(VH[i]&0xFF);\r
- }\r
-}\r
-#endif\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C)2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <sha1.h>\r
-// @author Jau-chih.Tseng@ite.com.tw\r
-// @date 2010/06/04\r
-// @fileversion: COMMON_FILE_1.01\r
-//******************************************/\r
-\r
-#ifndef _SHA_1_H_\r
-#define _SHA_1_H_\r
-\r
-#include "config.h"\r
-#include "typedef.h"\r
-\r
-#ifndef HDCP_DEBUG_PRINTF\r
- #define HDCP_DEBUG_PRINTF(x)\r
-#endif //HDCP_DEBUG_PRINTF\r
-\r
-#ifndef HDCP_DEBUG_PRINTF1\r
- #define HDCP_DEBUG_PRINTF1(x)\r
-#endif //HDCP_DEBUG_PRINTF1\r
-\r
-#ifndef HDCP_DEBUG_PRINTF2\r
- #define HDCP_DEBUG_PRINTF2(x)\r
-#endif //HDCP_DEBUG_PRINTF2\r
-\r
-\r
-#ifndef DISABLE_HDCP\r
-void SHA_Simple(void *p,WORD len,BYTE *output);\r
-void SHATransform(ULONG * h);\r
-#endif\r
-\r
-#endif // _SHA_1_H_\r
+++ /dev/null
-///*****************************************\r
-// Copyright (C) 2009-2014\r
-// ITE Tech. Inc. All Rights Reserved\r
-// Proprietary and Confidential\r
-///*****************************************\r
-// @file <typedef.h>\r
-// @author Jau-Chih.Tseng@ite.com.tw\r
-// @date 2012/12/20\r
-// @fileversion: ITE_HDMITX_SAMPLE_3.14\r
-//******************************************/\r
-\r
-#ifndef _TYPEDEF_H_\r
-#define _TYPEDEF_H_\r
-\r
-//////////////////////////////////////////////////\r
-// data type\r
-//////////////////////////////////////////////////\r
-#ifdef _MCU_8051_\r
- #define _CODE code\r
- #define _DATA data\r
- #define _XDATA xdata\r
- #define _IDATA idata\r
- typedef bit BOOL ;\r
-#else\r
- #define _CODE //const\r
- #define _DATA\r
- #define _IDATA\r
- #define _XDATA\r
- typedef int BOOL ;\r
-#endif // _MCU_8051_\r
-\r
-typedef _CODE unsigned char cBYTE;\r
-\r
-\r
-typedef char CHAR,*PCHAR ;\r
-typedef unsigned char uchar,*puchar ;\r
-typedef unsigned char UCHAR,*PUCHAR ;\r
-typedef unsigned char byte,*pbyte ;\r
-typedef unsigned char BYTE,*PBYTE ;\r
-\r
-typedef short SHORT,*PSHORT ;\r
-typedef unsigned short *pushort ;\r
-typedef unsigned short USHORT,*PUSHORT ;\r
-typedef unsigned short word,*pword ;\r
-typedef unsigned short WORD,*PWORD ;\r
-typedef unsigned int UINT,*PUINT ;\r
-\r
-typedef long LONG,*PLONG ;\r
-typedef unsigned long *pulong ;\r
-typedef unsigned long ULONG,*PULONG ;\r
-typedef unsigned long dword,*pdword ;\r
-typedef unsigned long DWORD,*PDWORD ;\r
-\r
-#define FALSE 0\r
-#define TRUE 1\r
-\r
-#define SUCCESS 0\r
-#define FAIL -1\r
-\r
-#define ON 1\r
-#define OFF 0\r
-\r
-#define LO_ACTIVE TRUE\r
-#define HI_ACTIVE FALSE\r
-\r
-\r
-typedef enum _SYS_STATUS {\r
- ER_SUCCESS = 0,\r
- ER_FAIL,\r
- ER_RESERVED\r
-} SYS_STATUS ;\r
-\r
-#define ABS(x) (((x)>=0)?(x):(-(x)))\r
-\r
-\r
-\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////\r
-// Video Data Type\r
-///////////////////////////////////////////////////////////////////////\r
-\r
-#define F_MODE_RGB444 0\r
-#define F_MODE_YUV422 1\r
-#define F_MODE_YUV444 2\r
-#define F_MODE_CLRMOD_MASK 3\r
-\r
-\r
-#define F_MODE_INTERLACE 1\r
-\r
-#define F_VIDMODE_ITU709 (1<<4)\r
-#define F_VIDMODE_ITU601 0\r
-\r
-#define F_VIDMODE_0_255 0\r
-#define F_VIDMODE_16_235 (1<<5)\r
-\r
-#define F_VIDMODE_EN_UDFILT (1<<6)\r
-#define F_VIDMODE_EN_DITHER (1<<7)\r
-\r
-#define T_MODE_CCIR656 (1<<0)\r
-#define T_MODE_SYNCEMB (1<<1)\r
-#define T_MODE_INDDR (1<<2)\r
-#define T_MODE_PCLKDIV2 (1<<3)\r
-#define T_MODE_DEGEN (1<<4)\r
-#define T_MODE_SYNCGEN (1<<5)\r
-/////////////////////////////////////////////////////////////////////\r
-// Packet and Info Frame definition and datastructure.\r
-/////////////////////////////////////////////////////////////////////\r
-\r
-\r
-#define VENDORSPEC_INFOFRAME_TYPE 0x81\r
-#define AVI_INFOFRAME_TYPE 0x82\r
-#define SPD_INFOFRAME_TYPE 0x83\r
-#define AUDIO_INFOFRAME_TYPE 0x84\r
-#define MPEG_INFOFRAME_TYPE 0x85\r
-\r
-#define VENDORSPEC_INFOFRAME_VER 0x01\r
-#define AVI_INFOFRAME_VER 0x02\r
-#define SPD_INFOFRAME_VER 0x01\r
-#define AUDIO_INFOFRAME_VER 0x01\r
-#define MPEG_INFOFRAME_VER 0x01\r
-\r
-#define VENDORSPEC_INFOFRAME_LEN 5\r
-#define AVI_INFOFRAME_LEN 13\r
-#define SPD_INFOFRAME_LEN 25\r
-#define AUDIO_INFOFRAME_LEN 10\r
-#define MPEG_INFOFRAME_LEN 10\r
-\r
-#define ACP_PKT_LEN 9\r
-#define ISRC1_PKT_LEN 16\r
-#define ISRC2_PKT_LEN 16\r
-\r
-typedef union _VendorSpecific_InfoFrame\r
-{\r
- struct {\r
- BYTE Type ;\r
- BYTE Ver ;\r
- BYTE Len ;\r
-\r
- BYTE CheckSum;\r
-\r
- BYTE IEEE_0;//PB1\r
- BYTE IEEE_1;//PB2\r
- BYTE IEEE_2;//PB3\r
-\r
- BYTE Rsvd:5 ;//PB4\r
- BYTE HDMI_Video_Format:3 ;\r
-\r
- BYTE Reserved_PB5:4 ;//PB5\r
- BYTE _3D_Structure:4 ;\r
-\r
- BYTE Reserved_PB6:4 ;//PB6\r
- BYTE _3D_Ext_Data:4 ;\r
- } info ;\r
- struct {\r
- BYTE VS_HB[3] ;\r
- BYTE CheckSum;\r
- BYTE VS_DB[28] ;\r
- } pktbyte ;\r
-} VendorSpecific_InfoFrame ;\r
-\r
-typedef union _AVI_InfoFrame\r
-{\r
-\r
- struct {\r
- BYTE Type;\r
- BYTE Ver;\r
- BYTE Len;\r
-\r
- BYTE checksum ;\r
-\r
- BYTE Scan:2;\r
- BYTE BarInfo:2;\r
- BYTE ActiveFmtInfoPresent:1;\r
- BYTE ColorMode:2;\r
- BYTE FU1:1;\r
-\r
- BYTE ActiveFormatAspectRatio:4;\r
- BYTE PictureAspectRatio:2;\r
- BYTE Colorimetry:2;\r
-\r
- BYTE Scaling:2;\r
- BYTE FU2:6;\r
-\r
- BYTE VIC:7;\r
- BYTE FU3:1;\r
-\r
- BYTE PixelRepetition:4;\r
- BYTE FU4:4;\r
-\r
- short Ln_End_Top;\r
- short Ln_Start_Bottom;\r
- short Pix_End_Left;\r
- short Pix_Start_Right;\r
- } info;\r
-\r
- struct {\r
- BYTE AVI_HB[3];\r
- BYTE checksum ;\r
- BYTE AVI_DB[AVI_INFOFRAME_LEN];\r
- } pktbyte;\r
-} AVI_InfoFrame;\r
-\r
-typedef union _Audio_InfoFrame {\r
-\r
- struct {\r
- BYTE Type;\r
- BYTE Ver;\r
- BYTE Len;\r
- BYTE checksum ;\r
-\r
- BYTE AudioChannelCount:3;\r
- BYTE RSVD1:1;\r
- BYTE AudioCodingType:4;\r
-\r
- BYTE SampleSize:2;\r
- BYTE SampleFreq:3;\r
- BYTE Rsvd2:3;\r
-\r
- BYTE FmtCoding;\r
-\r
- BYTE SpeakerPlacement;\r
-\r
- BYTE Rsvd3:3;\r
- BYTE LevelShiftValue:4;\r
- BYTE DM_INH:1;\r
- } info;\r
-\r
- struct {\r
- BYTE AUD_HB[3];\r
- BYTE checksum ;\r
- BYTE AUD_DB[5];\r
- } pktbyte;\r
-\r
-} Audio_InfoFrame;\r
-\r
-typedef union _MPEG_InfoFrame {\r
- struct {\r
- BYTE Type;\r
- BYTE Ver;\r
- BYTE Len;\r
- BYTE checksum ;\r
-\r
- ULONG MpegBitRate;\r
-\r
- BYTE MpegFrame:2;\r
- BYTE Rvsd1:2;\r
- BYTE FieldRepeat:1;\r
- BYTE Rvsd2:3;\r
- } info;\r
- struct {\r
- BYTE MPG_HB[3];\r
- BYTE checksum ;\r
- BYTE MPG_DB[MPEG_INFOFRAME_LEN];\r
- } pktbyte;\r
-} MPEG_InfoFrame;\r
-\r
-typedef union _SPD_InfoFrame {\r
- struct {\r
- BYTE Type;\r
- BYTE Ver;\r
- BYTE Len;\r
- BYTE checksum ;\r
-\r
- char VN[8];\r
- char PD[16];\r
- BYTE SourceDeviceInfomation;\r
- } info;\r
- struct {\r
- BYTE SPD_HB[3];\r
- BYTE checksum ;\r
- BYTE SPD_DB[SPD_INFOFRAME_LEN];\r
- } pktbyte;\r
-} SPD_InfoFrame;\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-// Using for interface.\r
-///////////////////////////////////////////////////////////////////////////\r
-\r
-#define PROG 1\r
-#define INTERLACE 0\r
-#define Vneg 0\r
-#define Hneg 0\r
-#define Vpos 1\r
-#define Hpos 1\r
-\r
-typedef struct {\r
- WORD H_ActiveStart;\r
- WORD H_ActiveEnd;\r
- WORD H_SyncStart;\r
- WORD H_SyncEnd;\r
- WORD V_ActiveStart;\r
- WORD V_ActiveEnd;\r
- WORD V_SyncStart;\r
- WORD V_SyncEnd;\r
- WORD V2_ActiveStart;\r
- WORD V2_ActiveEnd;\r
- WORD HTotal;\r
- WORD VTotal;\r
-} CEAVTiming;\r
-\r
-typedef struct {\r
- BYTE VIC ;\r
- BYTE PixelRep ;\r
- WORD HActive;\r
- WORD VActive;\r
- WORD HTotal;\r
- WORD VTotal;\r
- ULONG PCLK;\r
- BYTE xCnt;\r
- WORD HFrontPorch;\r
- WORD HSyncWidth;\r
- WORD HBackPorch;\r
- BYTE VFrontPorch;\r
- BYTE VSyncWidth;\r
- BYTE VBackPorch;\r
- BYTE ScanMode:1;\r
- BYTE VPolarity:1;\r
- BYTE HPolarity:1;\r
-} HDMI_VTiming;\r
-\r
-//////////////////////////////////////////////////////////////////\r
-// Audio relate definition and macro.\r
-//////////////////////////////////////////////////////////////////\r
-\r
-// 2008/08/15 added by jj_tseng@chipadvanced\r
-#define F_AUDIO_ON (1<<7)\r
-#define F_AUDIO_HBR (1<<6)\r
-#define F_AUDIO_DSD (1<<5)\r
-#define F_AUDIO_NLPCM (1<<4)\r
-#define F_AUDIO_LAYOUT_1 (1<<3)\r
-#define F_AUDIO_LAYOUT_0 (0<<3)\r
-\r
-// HBR - 1100\r
-// DSD - 1010\r
-// NLPCM - 1001\r
-// LPCM - 1000\r
-\r
-#define T_AUDIO_MASK 0xF0\r
-#define T_AUDIO_OFF 0\r
-#define T_AUDIO_HBR (F_AUDIO_ON|F_AUDIO_HBR)\r
-#define T_AUDIO_DSD (F_AUDIO_ON|F_AUDIO_DSD)\r
-#define T_AUDIO_NLPCM (F_AUDIO_ON|F_AUDIO_NLPCM)\r
-#define T_AUDIO_LPCM (F_AUDIO_ON)\r
-\r
-// for sample clock\r
-#define AUDFS_22p05KHz 4\r
-#define AUDFS_44p1KHz 0\r
-#define AUDFS_88p2KHz 8\r
-#define AUDFS_176p4KHz 12\r
-\r
-#define AUDFS_24KHz 6\r
-#define AUDFS_48KHz 2\r
-#define AUDFS_96KHz 10\r
-#define AUDFS_192KHz 14\r
-\r
-#define AUDFS_768KHz 9\r
-\r
-#define AUDFS_32KHz 3\r
-#define AUDFS_OTHER 1\r
-\r
-// Audio Enable\r
-#define ENABLE_SPDIF (1<<4)\r
-#define ENABLE_I2S_SRC3 (1<<3)\r
-#define ENABLE_I2S_SRC2 (1<<2)\r
-#define ENABLE_I2S_SRC1 (1<<1)\r
-#define ENABLE_I2S_SRC0 (1<<0)\r
-\r
-#define AUD_SWL_NOINDICATE 0x0\r
-#define AUD_SWL_16 0x2\r
-#define AUD_SWL_17 0xC\r
-#define AUD_SWL_18 0x4\r
-#define AUD_SWL_20 0xA // for maximum 20 bit\r
-#define AUD_SWL_21 0xD\r
-#define AUD_SWL_22 0x5\r
-#define AUD_SWL_23 0x9\r
-#define AUD_SWL_24 0xB\r
-\r
-\r
-#endif // _TYPEDEF_H_\r
+++ /dev/null
-config HDCP_RK2928
- bool "RK2928 HDCP support"
- depends on HDMI_RK2928
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-config HDCP_RK2928_DEBUG
- bool "RK2928 HDCP Debugging"
- depends on HDCP_RK2928
- default n
- help
- Enableds verbose debugging the the HDCP drivers
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-ccflags-$(CONFIG_HDCP_RK2928_DEBUG) = -DHDCP_DEBUG
-
-obj-$(CONFIG_HDMI_RK2928) += rk2928_hdmi_hw.o rk2928_hdmi.o
-obj-$(CONFIG_HDCP_RK2928) += rk2928_hdmi_hdcp.o rk2928_hdcp.o
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/miscdevice.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include "rk2928_hdmi.h"
-#include "rk2928_hdcp.h"
-
-struct hdcp *hdcp = NULL;
-
-static void hdcp_work_queue(struct work_struct *work);
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_submit_work
- *-----------------------------------------------------------------------------
- */
-static struct delayed_work *hdcp_submit_work(int event, int delay)
-{
- struct hdcp_delayed_work *work;
-
- DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
-
- work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
- work->event = event;
- queue_delayed_work(hdcp->workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- printk(KERN_WARNING "HDCP: Cannot allocate memory to "
- "create work\n");
- return 0;
- }
-
- return &work->work;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_cancel_work
- *-----------------------------------------------------------------------------
- */
-static void hdcp_cancel_work(struct delayed_work **work)
-{
- int ret = 0;
-
- if (*work) {
- ret = cancel_delayed_work(*work);
- if (ret != 1) {
- ret = cancel_work_sync(&((*work)->work));
- printk(KERN_INFO "Canceling work failed - "
- "cancel_work_sync done %d\n", ret);
- }
- kfree(*work);
- *work = 0;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_failure
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_failure(void)
-{
- if (hdcp->hdmi_state == HDMI_STOPPED) {
- return;
- }
-
- rk2928_hdcp_disable();
- rk2928_hdmi_control_output(false);
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
- if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
- hdcp->retry_cnt--;
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying, attempts=%d\n",
- hdcp->retry_cnt);
- } else
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying\n");
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
- HDCP_REAUTH_DELAY);
- } else {
- printk(KERN_INFO "HDCP: authentication failed - "
- "HDCP disabled\n");
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
-
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_start_authentication
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_start_authentication(void)
-{
- int status = HDCP_OK;
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- DBG("HDCP: authentication start");
-
- status = rk2928_hdcp_start_authentication();
-
- if (status != HDCP_OK) {
- DBG("HDCP: authentication failed");
- hdcp_wq_authentication_failure();
- } else {
- hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
-// hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_bksv
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_check_bksv(void)
-{
- int status = HDCP_OK;
-
- DBG("Check BKSV start");
-
- status = rk2928_hdcp_check_bksv();
-
- if (status != HDCP_OK) {
- printk(KERN_INFO "HDCP: Check BKSV failed");
- hdcp->retry_cnt = 0;
- hdcp_wq_authentication_failure();
- }
- else {
- DBG("HDCP: Check BKSV successful");
-
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
-
- /* Restore retry counter */
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_sucess
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_sucess(void)
-{
- rk2928_hdmi_control_output(true);
- printk(KERN_INFO "HDCP: authentication pass");
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_disable
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_disable(int event)
-{
- printk(KERN_INFO "HDCP: disabled");
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
- rk2928_hdcp_disable();
- if(event == HDCP_DISABLE_CTL) {
- hdcp->hdcp_state = HDCP_DISABLED;
- if(hdcp->hdmi_state == HDMI_STARTED)
- rk2928_hdmi_control_output(true);
- }
- else if(event == HDCP_STOP_FRAME_EVENT)
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_work_queue
- *-----------------------------------------------------------------------------
- */
-static void hdcp_work_queue(struct work_struct *work)
-{
- struct hdcp_delayed_work *hdcp_w =
- container_of(work, struct hdcp_delayed_work, work.work);
- int event = hdcp_w->event;
-
- mutex_lock(&hdcp->lock);
-
- DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
- jiffies_to_msecs(jiffies),
- hdcp->hdmi_state,
- hdcp->hdcp_state,
- (event & 0xFF00) >> 8,
- event & 0xFF);
-
- if(event == HDCP_STOP_FRAME_EVENT) {
- hdcp->hdmi_state = HDMI_STOPPED;
- }
-
- if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
- hdcp_wq_disable(event);
- }
-
- if (event & HDCP_WORKQUEUE_SRC)
- hdcp->pending_wq_event = 0;
-
- /* First handle HDMI state */
- if (event == HDCP_START_FRAME_EVENT) {
- hdcp->pending_start = 0;
- hdcp->hdmi_state = HDMI_STARTED;
- }
-
- /**********************/
- /* HDCP state machine */
- /**********************/
- switch (hdcp->hdcp_state) {
- case HDCP_DISABLED:
- /* HDCP enable control or re-authentication event */
- if (event == HDCP_ENABLE_CTL) {
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- if (hdcp->hdmi_state == HDMI_STARTED)
- hdcp_wq_start_authentication();
- else
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
- break;
-
- case HDCP_ENABLE_PENDING:
- /* HDMI start frame event */
- if (event == HDCP_START_FRAME_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_AUTHENTICATION_START:
- /* Re-authentication */
- if (event == HDCP_AUTH_REATT_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_WAIT_KSV_LIST:
- /* KSV failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: KSV switch failure\n");
-
- hdcp_wq_authentication_failure();
- }
- /* KSV list ready event */
- else if (event == HDCP_KSV_LIST_RDY_EVENT)
- hdcp_wq_check_bksv();
- break;
-
- case HDCP_LINK_INTEGRITY_CHECK:
- /* Ri failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: Ri check failure\n");
- hdcp_wq_authentication_failure();
- }
- else if(event == HDCP_AUTH_PASS_EVENT)
- hdcp_wq_authentication_sucess();
- break;
-
- default:
- printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
- break;
- }
-
- kfree(hdcp_w);
- if(event == HDCP_STOP_FRAME_EVENT)
- complete(&hdcp->complete);
-
- mutex_unlock(&hdcp->lock);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_start_frame_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_start_frame_cb(void)
-{
- DBG("hdcp_start_frame_cb()");
-
- /* Cancel any pending work */
- if (hdcp->pending_start)
- hdcp_cancel_work(&hdcp->pending_start);
- if (hdcp->pending_wq_event)
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_irq_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_irq_cb(int status)
-{
- char interrupt1;
- char interrupt2;
-
- rk2928_hdcp_interrupt(&interrupt1, &interrupt2);
- DBG("%s 0x%02x 0x%02x", __FUNCTION__, interrupt1, interrupt2);
- if(interrupt1 & m_INT_HDCP_ERR)
- {
- if( (hdcp->hdcp_state != HDCP_DISABLED) &&
- (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
- {
- hdcp_submit_work(HDCP_FAIL_EVENT, 0);
- }
- }
- else if(interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
- hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
- else if(interrupt1 & m_INT_AUTH_SUCCESS)
- hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_on_cb
- *-----------------------------------------------------------------------------
- */
-static int hdcp_power_on_cb(void)
-{
- DBG("%s", __FUNCTION__);
-// return rk2928_hdcp_load_key2mem(hdcp->keys);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_off_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_power_off_cb(void)
-{
- DBG("%s", __FUNCTION__);
- if(!hdcp->enable)
- return;
-
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- init_completion(&hdcp->complete);
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
- wait_for_completion_interruptible_timeout(&hdcp->complete,
- msecs_to_jiffies(5000));
-}
-
-// Load HDCP key to external HDCP memory
-static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
-{
- if (!fw) {
- pr_err("HDCP: failed to load keys\n");
- return;
- }
-
- if(fw->size < HDCP_KEY_SIZE) {
- pr_err("HDCP: firmware wrong size %d\n", fw->size);
- return;
- }
-
- hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->keys == NULL) {
- pr_err("HDCP: can't allocated space for keys\n");
- return;
- }
-
- memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
-
- printk(KERN_INFO "HDCP: load hdcp key success\n");
-
- if(fw->size > HDCP_KEY_SIZE) {
- DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
- if((fw->size - HDCP_KEY_SIZE) % 5) {
- pr_err("HDCP: failed to load invalid keys\n");
- return;
- }
- hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->invalidkeys == NULL) {
- pr_err("HDCP: can't allocated space for invalid keys\n");
- return;
- }
- memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
- hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
- printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
- }
-}
-
-static ssize_t hdcp_enable_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int enable = 0;
-
- if(hdcp)
- enable = hdcp->enable;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t hdcp_enable_write(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int enable;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &enable);
- if(hdcp->enable != enable)
- {
- /* Post event to workqueue */
- if(enable) {
- if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- else {
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- hdcp->enable = enable;
- }
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
-
-static ssize_t hdcp_trytimes_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int trytimes = 0;
-
- if(hdcp)
- trytimes = hdcp->retry_times;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
-}
-
-static ssize_t hdcp_trytimes_wrtie(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int trytimes;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &trytimes);
- if(hdcp->retry_times != trytimes)
- hdcp->retry_times = trytimes;
-
- return count;
-}
-
-
-static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
-
-
-static struct miscdevice mdev;
-
-static int __init rk2928_hdcp_init(void)
-{
- int ret;
-
- DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
-
- hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
- if(!hdcp)
- {
- printk(KERN_ERR ">>HDCP: kmalloc fail!");
- ret = -ENOMEM;
- goto error0;
- }
- memset(hdcp, 0, sizeof(struct hdcp));
- mutex_init(&hdcp->lock);
-
- mdev.minor = MISC_DYNAMIC_MINOR;
- mdev.name = "hdcp";
- mdev.mode = 0666;
- if (misc_register(&mdev)) {
- printk(KERN_ERR "HDCP: Could not add character driver\n");
- ret = HDMI_ERROR_FALSE;
- goto error1;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_enable);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file enable\n");
- ret = -EINVAL;
- goto error2;
- }
-
- ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
- ret = -EINVAL;
- goto error3;
- }
-
- hdcp->workqueue = create_singlethread_workqueue("hdcp");
- if (hdcp->workqueue == NULL) {
- printk(KERN_ERR "HDCP,: create workqueue failed.\n");
- goto error4;
- }
-
-
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "hdcp.keys", mdev.this_device, GFP_KERNEL,
- hdcp, hdcp_load_keys_cb);
- if (ret < 0) {
- printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
- goto error5;
- }
-
- rk2928_hdmi_register_hdcp_callbacks(hdcp_start_frame_cb,
- hdcp_irq_cb,
- hdcp_power_on_cb,
- hdcp_power_off_cb);
-
- DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
- return 0;
-
-error5:
- destroy_workqueue(hdcp->workqueue);
-error4:
- device_remove_file(mdev.this_device, &dev_attr_trytimes);
-error3:
- device_remove_file(mdev.this_device, &dev_attr_enable);
-error2:
- misc_deregister(&mdev);
-error1:
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-error0:
- return ret;
-}
-
-static void __exit rk2928_hdcp_exit(void)
-{
- device_remove_file(mdev.this_device, &dev_attr_enable);
- misc_deregister(&mdev);
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-}
-
-module_init(rk2928_hdcp_init);
-module_exit(rk2928_hdcp_exit);
+++ /dev/null
-#ifndef __RK2928_HDCP_H__
-#define __RK2928_HDCP_H__
-
-/***************************/
-/* Definitions */
-/***************************/
-
-/* Status / error codes */
-#define HDCP_OK 0
-#define HDCP_KEY_ERR 1
-#define HDCP_KSV_ERR 2
-
-/* Delays */
-#define HDCP_ENABLE_DELAY 300
-#define HDCP_REAUTH_DELAY 100
-
-/* Event source */
-#define HDCP_SRC_SHIFT 8
-#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
-#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
-#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
-#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
-
-/* Event */
-#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
-#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
-#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
-#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
-#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 4)
-#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 5)
-#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 6)
-#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 7)
-
-/* Key size */
-#define HDCP_KEY_SIZE 308
-
-/* HDCP DDC Clock */
-#define HDCP_DDC_CLK 100000
-
-/* Authentication retry times */
-#define HDCP_INFINITE_REAUTH 0x100
-
-/* HDCP Regs */
-#define HDCP_CTRL1 0x52
- #define m_AUTH_START (1 << 7)
- #define m_BKSV_VALID (1 << 6)
- #define m_BKSV_INVALID (1 << 5)
- #define m_ENCRYPT_ENABLE (1 << 4)
- #define m_AUTH_STOP (1 << 3)
- #define m_ADVANED_ENABLE (1 << 2)
- #define m_HDMI_DVI (1 << 1)
- #define m_HDCP_RESET (1 << 0)
-
- #define v_AUTH_START(n) (n << 7)
- #define v_BKSV_VALID(n) (n << 6)
- #define v_BKSV_INVALID(n) (n << 5)
- #define v_ENCRYPT_ENABLE(n) (n << 4)
- #define v_AUTH_STOP(n) (n << 3)
- #define v_ADVANED_ENABLE(n) (n << 2)
- #define v_HDMI_DVI(n) (n << 1)
- #define v_HDCP_RESET(n) (n << 0)
-
-#define HDCP_CTRL2 0x53
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_ENABLE_PJ_CHECK (1 << 5)
- #define m_DISABLE_DEVICE_NUMBER_CHECK (1 << 4)
- #define m_DELAY_RI_1_CLK (1 << 3)
- #define m_USE_PRESET_AN (1 << 2)
- #define m_KEY_COMBINATION (3 << 0)
-
- #define v_DISABLE_127_CHECK(n) (n << 7)
- #define v_SKIP_BKSV_CHECK(n) (n << 6)
- #define v_ENABLE_PJ_CHECK(n) (n << 5)
- #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
- #define v_DELAY_RI_1_CLK(n) (n << 3)
- #define v_USE_PRESET_AN(n) (n << 2)
- #define v_KEY_COMBINATION(n) (n << 0)
-
-#define HDCP_KEY_STATUS 0x54
- #define m_KEY_READY (1 << 0)
-
-#define HDCP_CTRL_SOFT 0x57
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_NOT_AUTHENTICATED (1 << 5)
- #define m_ENCRYPTED (1 << 4)
- #define m_ADVANCED_CIPHER (1 << 3)
-
-#define HDCP_BCAPS_RX 0x58
-#define HDCP_TIMER_100MS 0x63
-#define HDCP_TIMER_5S 0x64
-#define HDCP_ERROR 0x65
- #define m_DDC_NO_ACK (1 << 3)
- #define m_PJ_MISMACH (1 << 2)
- #define m_RI_MISMACH (1 << 1)
- #define m_BKSV_WRONG (1 << 0)
-
-#define HDCP_KSV_BYTE0 0x66
-#define HDCP_KSV_BYTE1 0x67
-#define HDCP_KSV_BYTE2 0x68
-#define HDCP_KSV_BYTE3 0x69
-#define HDCP_KSV_BYTE4 0x6a
-
-#define HDCP_AN_SEED 0x6c
-
-#define HDCP_BCAPS_TX 0x80
-#define HDCP_BSTATE_0 0x81
-#define HDCP_BSTATE_1 0x82
-
-#define HDCP_KEY_FIFO 0x98
-
-#define HDCP_INT_MASK1 0xc2
-#define HDCP_INT_STATUS1 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_READY (1 << 6)
- #define m_INT_BKSV_UPDATE (1 << 5)
- #define m_INT_AUTH_SUCCESS (1 << 4)
- #define m_INT_AUTH_READY (1 << 3)
-
-#define HDCP_INT_MASK2 0xc4
-#define HDCP_INT_STATUS2 0xc5
- #define m_INT_SOFT_MODE_READY (1 << 7)
- #define m_INT_AUTH_M0_REDAY (1 << 6)
- #define m_INT_1st_FRAME_ARRIVE (1 << 5)
- #define m_INT_AN_READY (1 << 4)
- #define m_INT_ENCRYPTED (1 << 2)
- #define m_INT_NOT_ENCRYPTED_AVMUTE (1 << 1)
- #define m_INT_NOT_ENCRYPTED_AVUNMUTE (1 << 0)
-
-enum hdcp_states {
- HDCP_DISABLED,
- HDCP_ENABLE_PENDING,
- HDCP_AUTHENTICATION_START,
- HDCP_WAIT_KSV_LIST,
- HDCP_LINK_INTEGRITY_CHECK,
-};
-
-enum hdmi_states {
- HDMI_STOPPED,
- HDMI_STARTED
-};
-
-#define HDCP_PRIVATE_KEY_SIZE 280
-#define HDCP_KEY_SHA_SIZE 20
-
-struct hdcp_keys{
- u8 KSV[8];
- u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
- u8 sha1[HDCP_KEY_SHA_SIZE];
-};
-
-struct hdcp_delayed_work {
- struct delayed_work work;
- int event;
-};
-
-struct hdcp {
- int enable;
- int retry_times;
- struct hdcp_keys *keys;
- int invalidkey;
- char *invalidkeys;
- struct mutex lock;
- struct completion complete;
- struct workqueue_struct *workqueue;
-
- enum hdmi_states hdmi_state;
- enum hdcp_states hdcp_state;
-
- struct delayed_work *pending_start;
- struct delayed_work *pending_wq_event;
- int retry_cnt;
-};
-
-extern struct hdcp *hdcp;
-
-#ifdef HDCP_DEBUG
-#define DBG(format, ...) \
- printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-extern void rk2928_hdcp_disable(void);
-extern int rk2928_hdcp_start_authentication(void);
-extern int rk2928_hdcp_check_bksv(void);
-extern int rk2928_hdcp_load_key2mem(struct hdcp_keys *key);
-extern void rk2928_hdcp_interrupt(char *status1, char *status2);
-#endif /* __rk2928_HDCP_H__ */
\ No newline at end of file
+++ /dev/null
-#include <linux/module.h>\r
-#include <linux/kernel.h>\r
-#include <linux/errno.h>\r
-#include <linux/string.h>\r
-#include <linux/mm.h>\r
-#include <linux/slab.h>\r
-#include <linux/delay.h>\r
-#include <linux/device.h>\r
-#include <linux/init.h>\r
-#include <linux/dma-mapping.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/clk.h>\r
-\r
-#include <mach/board.h>\r
-#include <mach/io.h>\r
-#include <mach/gpio.h>\r
-#include <mach/iomux.h>\r
-#include "rk2928_hdmi.h"\r
-#include "rk2928_hdmi_hw.h"\r
-\r
-struct hdmi *hdmi = NULL;\r
-\r
-extern irqreturn_t hdmi_irq(int irq, void *priv);\r
-extern void hdmi_work(struct work_struct *work);\r
-extern struct rk_lcdc_driver * rk_get_lcdc_drv(char *name);
-extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
-extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
-\r
-int rk2928_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
- void (*hdcp_irq_cb)(int status),\r
- int (*hdcp_power_on_cb)(void),\r
- void (*hdcp_power_off_cb)(void))\r
-{\r
- if(hdmi == NULL)\r
- return HDMI_ERROR_FALSE;\r
-\r
- hdmi->hdcp_cb = hdcp_cb;\r
- hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
- hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
- hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
- \r
- return HDMI_ERROR_SUCESS;\r
-}\r
-\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-static void hdmi_early_suspend(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
-\r
- rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_GPIO0A7);\r
- rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_GPIO0A6);\r
- \r
- flush_delayed_work(&hdmi->delay_work); \r
- mutex_lock(&hdmi->enable_mutex);\r
- hdmi->suspend = 1;\r
- if(!hdmi->enable) {\r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
- }\r
- disable_irq(hdmi->irq);\r
- mutex_unlock(&hdmi->enable_mutex);\r
- hdmi->command = HDMI_CONFIG_ENABLE;\r
- init_completion(&hdmi->complete);\r
- hdmi->wait = 1;\r
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
- wait_for_completion_interruptible_timeout(&hdmi->complete,\r
- msecs_to_jiffies(5000));\r
- flush_delayed_work(&hdmi->delay_work);\r
-\r
- return;\r
-}\r
-\r
-static void hdmi_early_resume(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
- mutex_lock(&hdmi->enable_mutex);\r
- \r
- rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);\r
- rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);\r
- \r
- hdmi->suspend = 0;\r
- rk2928_hdmi_initial();\r
- if(hdmi->enable) {\r
- enable_irq(hdmi->irq);\r
- }\r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
-}\r
-#endif\r
-\r
-static inline void hdmi_io_remap(void)\r
-{\r
- unsigned int value;\r
- \r
- // Remap HDMI IO Pin\r
- rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);\r
- rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);\r
- rk30_mux_api_set(GPIO0B7_HDMI_HOTPLUGIN_NAME, GPIO0B_HDMI_HOTPLUGIN);\r
- \r
- // Select LCDC0 as video source and enabled.\r
-// value = (HDMI_SOURCE_DEFAULT << 14) | (1 << 30);\r
-// writel(value, GRF_SOC_CON0 + rk2928_GRF_BASE);\r
-}\r
-\r
-static int __devinit rk2928_hdmi_probe (struct platform_device *pdev)\r
-{\r
- int ret;\r
- struct resource *res;\r
- struct resource *mem;\r
- \r
- hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
- if(!hdmi)\r
- {\r
- dev_err(&pdev->dev, ">>rk2928 hdmi kmalloc fail!");\r
- return -ENOMEM;\r
- }\r
- memset(hdmi, 0, sizeof(struct hdmi));\r
- hdmi->dev = &pdev->dev;\r
- platform_set_drvdata(pdev, hdmi);\r
-\r
- if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
- else\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
- if(hdmi->lcdc == NULL)\r
- {\r
- dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- hdmi->xscale = 100;\r
- hdmi->yscale = 100;\r
-#if 1 \r
- hdmi->hclk = clk_get(NULL,"pclk_hdmi");\r
- if(IS_ERR(hdmi->hclk))\r
- {\r
- dev_err(hdmi->dev, "Unable to get hdmi hclk\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- clk_enable(hdmi->hclk);\r
-#endif \r
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
- if (!res) {\r
- dev_err(hdmi->dev, "Unable to get register resource\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- hdmi->regbase_phy = res->start;\r
- hdmi->regsize_phy = (res->end - res->start) + 1;\r
- mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);\r
- if (!mem)\r
- {\r
- dev_err(hdmi->dev, "failed to request mem region for hdmi\n");\r
- ret = -ENOENT;\r
- goto err0;\r
- }\r
-\r
- \r
- hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);\r
- if (!hdmi->regbase) {\r
- dev_err(hdmi->dev, "cannot ioremap registers\n");\r
- ret = -ENXIO;\r
- goto err1;\r
- }\r
- \r
- ret = rk2928_hdmi_initial();\r
- if(ret != HDMI_ERROR_SUCESS)\r
- goto err1;\r
- \r
- hdmi_io_remap();\r
- hdmi_sys_init();\r
- \r
- hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
- INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
-\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- hdmi->early_suspend.suspend = hdmi_early_suspend;\r
- hdmi->early_suspend.resume = hdmi_early_resume;\r
- hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
- register_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- \r
- hdmi_register_display_sysfs(hdmi, NULL);\r
- #ifdef CONFIG_SWITCH\r
- hdmi->switch_hdmi.name="hdmi";\r
- switch_dev_register(&(hdmi->switch_hdmi));\r
- #endif\r
- \r
- spin_lock_init(&hdmi->irq_lock);\r
- mutex_init(&hdmi->enable_mutex);\r
- \r
- /* get the IRQ */\r
- hdmi->irq = platform_get_irq(pdev, 0);\r
- if(hdmi->irq <= 0) {\r
- dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);\r
- ret = -ENXIO;\r
- goto err2;\r
- }\r
-\r
- /* request the IRQ */\r
- ret = request_irq(hdmi->irq, hdmi_irq, 0, dev_name(&pdev->dev), hdmi);\r
- if (ret)\r
- {\r
- dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);\r
- goto err2;\r
- }\r
-\r
- dev_info(hdmi->dev, "rk2928 hdmi probe success.\n");\r
- return 0;\r
-err2:\r
- #ifdef CONFIG_SWITCH\r
- switch_dev_unregister(&(hdmi->switch_hdmi));\r
- #endif\r
- hdmi_unregister_display_sysfs(hdmi);\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- iounmap((void*)hdmi->regbase);\r
-err1:\r
- release_mem_region(res->start,(res->end - res->start) + 1);\r
-#if 0\r
- clk_disable(hdmi->hclk);\r
-#endif\r
-err0:\r
- hdmi_dbg(hdmi->dev, "rk2928 hdmi probe error.\n");\r
- kfree(hdmi);\r
- hdmi = NULL;\r
- return ret;\r
-}\r
-\r
-static int __devexit rk2928_hdmi_remove(struct platform_device *pdev)\r
-{\r
- if(hdmi) {\r
- mutex_lock(&hdmi->enable_mutex);\r
- if(!hdmi->suspend && hdmi->enable)\r
- disable_irq(hdmi->irq);\r
- mutex_unlock(&hdmi->enable_mutex);\r
- free_irq(hdmi->irq, NULL);\r
- flush_workqueue(hdmi->workqueue);\r
- destroy_workqueue(hdmi->workqueue);\r
- #ifdef CONFIG_SWITCH\r
- switch_dev_unregister(&(hdmi->switch_hdmi));\r
- #endif\r
- hdmi_unregister_display_sysfs(hdmi);\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- iounmap((void*)hdmi->regbase);\r
- release_mem_region(hdmi->regbase_phy, hdmi->regsize_phy);\r
- #if 0\r
- clk_disable(hdmi->hclk);\r
- #endif\r
- fb_destroy_modelist(&hdmi->edid.modelist);\r
- if(hdmi->edid.audio)\r
- kfree(hdmi->edid.audio);\r
- if(hdmi->edid.specs)\r
- {\r
- if(hdmi->edid.specs->modedb)\r
- kfree(hdmi->edid.specs->modedb);\r
- kfree(hdmi->edid.specs);\r
- }\r
- kfree(hdmi);\r
- hdmi = NULL;\r
- }\r
- printk(KERN_INFO "rk2928 hdmi removed.\n");\r
- return 0;\r
-}\r
-\r
-static void rk2928_hdmi_shutdown(struct platform_device *pdev)\r
-{\r
- if(hdmi) {\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- }\r
- printk(KERN_INFO "rk2928 hdmi shut down.\n");\r
-}\r
-\r
-static struct platform_driver rk2928_hdmi_driver = {\r
- .probe = rk2928_hdmi_probe,\r
- .remove = __devexit_p(rk2928_hdmi_remove),\r
- .driver = {\r
- .name = "rk2928-hdmi",\r
- .owner = THIS_MODULE,\r
- },\r
- .shutdown = rk2928_hdmi_shutdown,\r
-};\r
-\r
-static int __init rk2928_hdmi_init(void)\r
-{\r
- return platform_driver_register(&rk2928_hdmi_driver);\r
-}\r
-\r
-static void __exit rk2928_hdmi_exit(void)\r
-{\r
- platform_driver_unregister(&rk2928_hdmi_driver);\r
-}\r
-\r
-\r
-//fs_initcall(rk2928_hdmi_init);\r
-late_initcall(rk2928_hdmi_init);\r
-module_exit(rk2928_hdmi_exit);\r
+++ /dev/null
-#ifndef __RK30_HDMI_H__
-#define __RK30_HDMI_H__
-
-#include "../../rk_hdmi.h"
-
-#if defined(CONFIG_HDMI_SOURCE_LCDC1)
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC1
-#else
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC0
-#endif
-
-extern void rk2928_hdmi_control_output(int enable);
-extern int rk2928_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-#endif /* __RK30_HDMI_H__ */
+++ /dev/null
-#include <linux/delay.h>\r
-#include "rk2928_hdmi.h"\r
-#include "rk2928_hdmi_hw.h"\r
-#include "rk2928_hdcp.h"\r
-\r
-#define HDCPWrReg HDMIWrReg\r
-#define HDCPRdReg HDMIRdReg\r
-#define HDCPMskReg(temp, addr, msk, val) \\r
- temp = HDCPRdReg(addr) & (0xFF - (msk)) ; \\r
- HDCPWrReg(addr, temp | ( (val) & (msk) )); \r
- \r
-void rk2928_hdcp_disable(void)\r
-{\r
- char temp;\r
- \r
- // Diable HDCP Interrupt\r
- HDCPWrReg(HDCP_INT_MASK1, 0x00);\r
- // Stop and Reset HDCP\r
- HDCPMskReg(temp, HDCP_CTRL1, m_ENCRYPT_ENABLE | m_AUTH_STOP | m_HDCP_RESET, \r
- v_ENCRYPT_ENABLE(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1) )\r
-}\r
-\r
-int rk2928_hdcp_load_key2mem(struct hdcp_keys *key)\r
-{\r
- int i;\r
- DBG("HDCP: rk2928_hdcp_load_key2mem start");\r
- // Write 40 private key\r
- for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->DeviceKey[i]);\r
- \r
- // Write 1st aksv\r
- for(i = 0; i < 5; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
- \r
- // Write 2nd aksv\r
- for(i = 0; i < 5; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
- DBG("HDCP: rk2928_hdcp_load_key2mem end");\r
- return HDCP_OK;\r
-}\r
-\r
-int rk2928_hdcp_start_authentication(void)\r
-{\r
- char temp;\r
- int retry = 0;\r
-\r
- if(hdcp->keys == NULL) {\r
- printk(KERN_ERR "HDCP: key is not loaded\n");\r
- return HDCP_KEY_ERR;\r
- }\r
- \r
- // Select TMDS CLK to configure regs\r
- HDCPMskReg(temp, SYS_CTRL, m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);\r
- \r
- temp = HDCPRdReg(HDCP_KEY_STATUS);\r
- while( ( temp & m_KEY_READY) == 0 ) {\r
- if(retry > 10) {\r
- printk(KERN_ERR "HDCP: loaded key error\n");\r
- return HDCP_KEY_ERR;\r
- }\r
- rk2928_hdcp_load_key2mem(hdcp->keys);\r
- msleep(1);\r
- temp = HDCPRdReg(HDCP_KEY_STATUS);\r
- }\r
- \r
- // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)\r
- DBG("TMDS frequency %d", hdmi->tmdsclk);\r
- retry = hdmi->tmdsclk/(HDCP_DDC_CLK*4);\r
- HDCPWrReg(DDC_CLK_L, retry & 0xFF);\r
- HDCPWrReg(DDC_CLK_H, (retry >> 8) & 0xFF);\r
- \r
- HDCPWrReg(HDCP_CTRL2, 0x00);\r
- \r
- //Enable interrupt\r
- HDCPWrReg(HDCP_INT_MASK1, m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE | m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);\r
-// HDCPWrReg(HDCP_INT_MASK2, 0xFF);\r
- //Start authentication\r
- HDCPMskReg(temp, HDCP_CTRL1, m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE, v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) | v_ADVANED_ENABLE(0));\r
- \r
- return HDCP_OK;\r
-}\r
-\r
-int rk2928_hdcp_check_bksv(void)\r
-{\r
- int i, j;\r
- char temp = 0, bksv[5];\r
- char *invalidkey;\r
- \r
- for(i = 0; i < 5; i++) {\r
- bksv[i] = HDCPRdReg(HDCP_KSV_BYTE0 + (4 - i)) & 0xFF;\r
- }\r
- DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);\r
- \r
- for (i = 0; i < 5; i++)\r
- {\r
- for (j = 0; j < 8; j++)\r
- {\r
- if (bksv[i] & 0x01)\r
- {\r
- temp++;\r
- }\r
- bksv[i] >>= 1;\r
- }\r
- }\r
- if (temp != 20)\r
- return HDCP_KSV_ERR;\r
- \r
- for(i = 0; i < hdcp->invalidkey; i++)\r
- {\r
- invalidkey = hdcp->invalidkeys + i *5;\r
- if(memcmp(bksv, invalidkey, 5) == 0) {\r
- printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");\r
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE, v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));\r
- return HDCP_KSV_ERR;\r
- }\r
- }\r
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE, v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));\r
- return HDCP_OK;\r
-}\r
-\r
-void rk2928_hdcp_interrupt(char *status1, char *status2)\r
-{\r
- char interrupt1 = HDCPRdReg(HDCP_INT_STATUS1);\r
- char interrupt2 = HDCPRdReg(HDCP_INT_STATUS2);\r
- if(interrupt1) {\r
- HDCPWrReg(HDCP_INT_STATUS1, interrupt1);\r
- if(interrupt1 & m_INT_HDCP_ERR)\r
- printk(KERN_INFO "HDCP: Error 0x%02x\n", HDCPRdReg(HDCP_ERROR));\r
- }\r
- if(interrupt2)\r
- HDCPWrReg(HDCP_INT_STATUS2, interrupt2);\r
- \r
- *status1 = interrupt1;\r
- *status2 = interrupt2;\r
-}
\ No newline at end of file
+++ /dev/null
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <mach/io.h>
-#include "rk2928_hdmi.h"
-#include "rk2928_hdmi_hw.h"
-
-static char edid_result = 0;
-static bool analog_sync = 0;
-
-static inline void delay100us(void)
-{
- msleep(1);
-}
-
-
-static void rk2928_hdmi_av_mute(bool enable)
-{
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
-}
-
-static void rk2928_hdmi_sys_power_up(void)
-{
- hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH);
-}
-static void rk2928_hdmi_sys_power_down(void)
-{
- hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_OFF | v_INT_POL_HIGH);
-}
-
-
-
-static void rk2928_hdmi_set_pwr_mode(int mode)
-{
- hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
- if(hdmi->pwr_mode == mode)
- return;
- switch(mode){
- case NORMAL:
- rk2928_hdmi_sys_power_down();
- HDMIWrReg(0xe0, 0x0a);
- HDMIWrReg(0xe1, 0x03);
- HDMIWrReg(0xe2, 0x99);
- HDMIWrReg(0xe3, 0x0f);
- HDMIWrReg(0xe4, 0x00);
- HDMIWrReg(0xec, 0x02);
- HDMIWrReg(0xce, 0x00);
- HDMIWrReg(0xce, 0x01);
- rk2928_hdmi_av_mute(1);
- rk2928_hdmi_sys_power_up();
- analog_sync = 1;
- break;
- case LOWER_PWR:
- rk2928_hdmi_av_mute(0);
- rk2928_hdmi_sys_power_down();
- HDMIWrReg(0xe0, 0x3a);
- HDMIWrReg(0xe1, 0x00);
- HDMIWrReg(0xe2, 0x00);
- HDMIWrReg(0xe3, 0x00);
- HDMIWrReg(0xe4, 0x03);
- HDMIWrReg(0xec, 0x03);
- break;
- default:
- hdmi_dbg(hdmi->dev,"unkown rk2928 hdmi pwr mode %d\n",mode);
- }
- hdmi->pwr_mode = mode;
-}
-
-
-int rk2928_hdmi_detect_hotplug(void)
-{
- int value = HDMIRdReg(HDMI_STATUS);
-
- hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
- value &= m_HOTPLUG;
- if(value == m_HOTPLUG)
- return HDMI_HPD_ACTIVED;
- else if(value)
- return HDMI_HPD_INSERT;
- else
- return HDMI_HPD_REMOVED;
-}
-
-#define HDMI_SYS_FREG_CLK 11289600
-#define HDMI_SCL_RATE (100*1000)
-#define HDMI_DDC_CONFIG (HDMI_SYS_FREG_CLK>>2)/HDMI_SCL_RATE
-#define DDC_BUS_FREQ_L 0x4b
-#define DDC_BUS_FREQ_H 0x4c
-
-int rk2928_hdmi_read_edid(int block, unsigned char *buff)
-{
- int value, ret = -1, ddc_bus_freq = 0;
- char interrupt = 0, trytime = 2;
- unsigned long flags;
-
- hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
- spin_lock_irqsave(&hdmi->irq_lock, flags);
- edid_result = 0;
- spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
- //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
-
- ddc_bus_freq = HDMI_DDC_CONFIG;
- HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
- HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-
- // Enable edid interrupt
- HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG | m_INT_EDID_READY);
-
- while(trytime--) {
- // Config EDID block and segment addr
- HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);
- HDMIWrReg(EDID_SEGMENT_POINTER, block/2);
-
- value = 10;
- while(value--)
- {
- spin_lock_irqsave(&hdmi->irq_lock, flags);
- interrupt = edid_result;
- edid_result = 0;
- spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- if(interrupt & (m_INT_EDID_READY))
- break;
- msleep(10);
- }
- hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
- if(interrupt & m_INT_EDID_READY)
- {
- for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++)
- buff[value] = HDMIRdReg(EDID_FIFO_ADDR);
- ret = 0;
-
- hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__);
-#ifdef HDMI_DEBUG
- for(value = 0; value < 128; value++) {
- printk("%02x ,", buff[value]);
- if( (value + 1) % 16 == 0)
- printk("\n");
- }
-#endif
- break;
- }else
- hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
-
- hdmi_dbg(hdmi->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
- msleep(100);
- }
- // Disable edid interrupt
- HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG);
-// msleep(100);
- return ret;
-}
-
-static void rk2928_hdmi_config_avi(unsigned char vic, unsigned char output_color)
-{
- int i;
- char info[SIZE_AVI_INFOFRAME];
-
- memset(info, 0, SIZE_AVI_INFOFRAME);
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
- info[0] = 0x82;
- info[1] = 0x02;
- info[2] = 0x0D;
- info[3] = info[0] + info[1] + info[2];
- info[4] = (AVI_COLOR_MODE_RGB << 5);
- info[5] = (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
- info[6] = 0;
- info[7] = vic;
- info[8] = 0;
-
- // Calculate AVI InfoFrame ChecKsum
- for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
- {
- info[3] += info[i];
- }
- info[3] = 0x100 - info[3];
-
- for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
- HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk2928_hdmi_config_video(struct hdmi_video_para *vpara)
-{
- int value;
- struct fb_videomode *mode;
-
- hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
- if(vpara == NULL) {
- hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
- return -1;
- }
-
- if(hdmi->hdcp_power_off_cb)
- hdmi->hdcp_power_off_cb();
- // Diable video and audio output
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
-
- // Input video mode is SDR RGB24bit, Data enable signal from external
- HDMIWrReg(VIDEO_CONTRL1, v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) | v_DE_EXTERNAL);
- HDMIWrReg(VIDEO_CONTRL2, v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | (vpara->output_color & 0xFF));
-
- // Set HDMI Mode
- HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
-
- // Enable or disalbe color space convert
- if(vpara->input_color != vpara->output_color) {
- value = v_SOF_DISABLE | v_CSC_ENABLE;
- }
- else
- value = v_SOF_DISABLE;
- HDMIWrReg(VIDEO_CONTRL3, value);
-
- // Set ext video
-#if 1
- HDMIWrReg(VIDEO_TIMING_CTL, 0);
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if(mode == NULL)
- {
- hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
- return -ENOENT;
- }
- hdmi->tmdsclk = mode->pixclock;
-#else
- value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
- if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
- value |= v_HSYNC_POLARITY(1);
- if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
- value |= v_VSYNC_POLARITY(1);
- HDMIWrReg(VIDEO_TIMING_CTL, value);
-
- value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
- HDMIWrReg(VIDEO_EXT_HTOTAL_L, value & 0xFF);
- HDMIWrReg(VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->right_margin + mode->hsync_len;
- HDMIWrReg(VIDEO_EXT_HBLANK_L, value & 0xFF);
- HDMIWrReg(VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->hsync_len;
- HDMIWrReg(VIDEO_EXT_HDELAY_L, value & 0xFF);
- HDMIWrReg(VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
-
- value = mode->hsync_len;
- HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF);
- HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
- HDMIWrReg(VIDEO_EXT_VTOTAL_L, value & 0xFF);
- HDMIWrReg(VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
- HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF);
-
- if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
- value = 42;
- else
- value = mode->upper_margin + mode->vsync_len;
-
- HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF);
-
- value = mode->vsync_len;
- HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF);
-#endif
-
- if(vpara->output_mode == OUTPUT_HDMI) {
- rk2928_hdmi_config_avi(vpara->vic, vpara->output_color);
- hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
- }
- else {
- hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__);
- }
-
- if(hdmi->tmdsclk >= 148500000) {
- HDMIWrReg(0xe3, 0x4f);
- }
- else {
- HDMIWrReg(0xe3, 0x0f);
- }
- return 0;
-}
-
-static void rk2928_hdmi_config_aai(void)
-{
- int i;
- char info[SIZE_AUDIO_INFOFRAME];
-
- memset(info, 0, SIZE_AUDIO_INFOFRAME);
-
- info[0] = 0x84;
- info[1] = 0x01;
- info[2] = 0x0A;
-
- info[3] = info[0] + info[1] + info[2];
- for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
- for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
- HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk2928_hdmi_config_audio(struct hdmi_audio *audio)
-{
- int rate, N, channel, mclk_fs;
-
- if(audio->channel < 3)
- channel = I2S_CHANNEL_1_2;
- else if(audio->channel < 5)
- channel = I2S_CHANNEL_3_4;
- else if(audio->channel < 7)
- channel = I2S_CHANNEL_5_6;
- else
- channel = I2S_CHANNEL_7_8;
-
- switch(audio->rate)
- {
- case HDMI_AUDIO_FS_32000:
- rate = AUDIO_32K;
- N = N_32K;
- mclk_fs = MCLK_384FS;
- break;
- case HDMI_AUDIO_FS_44100:
- rate = AUDIO_441K;
- N = N_441K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_48000:
- rate = AUDIO_48K;
- N = N_48K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_88200:
- rate = AUDIO_882K;
- N = N_882K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_96000:
- rate = AUDIO_96K;
- N = N_96K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_176400:
- rate = AUDIO_1764K;
- N = N_1764K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_192000:
- rate = AUDIO_192K;
- N = N_192K;
- mclk_fs = MCLK_128FS;
- break;
- default:
- dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
- return -ENOENT;
- }
-
- //set_audio source I2S
- HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK
- HDMIWrReg(AUDIO_SAMPLE_RATE, rate);
- HDMIWrReg(AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel) );
- HDMIWrReg(AUDIO_I2S_MAP, 0x00);
- HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap
-
- //Set N value
- HDMIWrReg(AUDIO_N_H, (N >> 16) & 0x0F);
- HDMIWrReg(AUDIO_N_M, (N >> 8) & 0xFF);
- HDMIWrReg(AUDIO_N_L, N & 0xFF);
- rk2928_hdmi_config_aai();
-
- return 0;
-}
-
-void rk2928_hdmi_control_output(int enable)
-{
- char mutestatus = 0;
-
- if(enable) {
- if(hdmi->pwr_mode == LOWER_PWR)
- rk2928_hdmi_set_pwr_mode(NORMAL);
- mutestatus = HDMIRdReg(AV_MUTE);
- if(mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
- rk2928_hdmi_sys_power_up();
- rk2928_hdmi_sys_power_down();
- rk2928_hdmi_sys_power_up();
- if(analog_sync){
- HDMIWrReg(0xce, 0x00);
- delay100us();
- HDMIWrReg(0xce, 0x01);
- analog_sync = 0;
- }
- }
- }
- else {
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
- }
-}
-
-int rk2928_hdmi_removed(void)
-{
-
- dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
- rk2928_hdmi_set_pwr_mode(LOWER_PWR);
-
- return HDMI_ERROR_SUCESS;
-}
-
-
-irqreturn_t hdmi_irq(int irq, void *priv)
-{
- char interrupt1 = 0;
- unsigned long flags;
- spin_lock_irqsave(&hdmi->irq_lock,flags);
- interrupt1 = HDMIRdReg(INTERRUPT_STATUS1);
- HDMIWrReg(INTERRUPT_STATUS1, interrupt1);
-#if 1
- hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x \n",\
- __FUNCTION__, interrupt1);
-#endif
- if(interrupt1 & m_INT_HOTPLUG ){
- if(hdmi->state == HDMI_SLEEP)
- hdmi->state = WAIT_HOTPLUG;
- if(hdmi->pwr_mode == LOWER_PWR)
- rk2928_hdmi_set_pwr_mode(NORMAL);
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
- }else if(interrupt1 & m_INT_EDID_READY) {
- edid_result = interrupt1;
- }else if(hdmi->state == HDMI_SLEEP) {
- hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
- rk2928_hdmi_set_pwr_mode(LOWER_PWR);
- }
-#if 0
- if(hdmi->hdcp_irq_cb)
- hdmi->hdcp_irq_cb(interrupt2);
-#endif
- spin_unlock_irqrestore(&hdmi->irq_lock,flags);
- return IRQ_HANDLED;
-}
-
-static void rk2928_hdmi_reset(void)
-{
- writel_relaxed(0x00010001,RK2928_CRU_BASE+ 0x128);
- msleep(100);
- writel_relaxed(0x00010000, RK2928_CRU_BASE + 0x128);
- rk2928_hdmi_set_pwr_mode(LOWER_PWR);
-}
-
-int rk2928_hdmi_initial(void)
-{
- int rc = HDMI_ERROR_SUCESS;
-
- hdmi->pwr_mode = NORMAL;
- hdmi->remove = rk2928_hdmi_removed ;
- hdmi->control_output = rk2928_hdmi_control_output;
- hdmi->config_video = rk2928_hdmi_config_video;
- hdmi->config_audio = rk2928_hdmi_config_audio;
- hdmi->detect_hotplug = rk2928_hdmi_detect_hotplug;
- hdmi->read_edid = rk2928_hdmi_read_edid;
-
- rk2928_hdmi_reset();
-
- if(hdmi->hdcp_power_on_cb)
- rc = hdmi->hdcp_power_on_cb();
-
- return rc;
-}
+++ /dev/null
-#ifndef _RK2928_HDMI_HW_H
-#define _RK2928_HDMI_HW_H
-
-enum PWR_MODE{
- NORMAL,
- LOWER_PWR,
-};
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
- };
-#define SYS_CTRL 0x00
- #define m_INT_POL (1 << 0)
- #define m_POWER (1 << 1)
- #define m_REG_CLK_SOURCE (1 << 2)
- #define v_INT_POL_HIGH 1
- #define v_INT_POL_LOW 0
- #define v_PWR_ON (0 << 1)
- #define v_PWR_OFF (1 << 1)
- #define v_REG_CLK_SOURCE_TMDS (0 << 2)
- #define v_REG_CLK_SOURCE_IIS (1 << 2)
-#define VIDEO_CONTRL1 0x01
- #define m_VIDEO_INPUT_FORMAT (7 << 1)
- #define m_DE_SOURCE (1 << 0)
- enum {
- VIDEO_INPUT_SDR_RGB444 = 0,
- VIDEO_INPUT_DDR_RGB444 = 5,
- VIDEO_INPUT_DDR_YCBCR422 = 6
- };
- #define v_VIDEO_INPUT_FORMAT(n) (n << 1)
- #define v_DE_EXTERNAL 1
- #define v_DE_INTERANL 0
-
-#define VIDEO_CONTRL2 0x02
- #define m_VIDEO_OUTPUT_FORMAT (3 << 6)
- #define m_VIDEO_INPUT_BITS (3 << 4)
- #define v_VIDEO_OUTPUT_FORMAT(n)(n << 6)
- #define v_VIDEO_INPUT_BITS(n) (n << 4)
- enum{
- VIDEO_INPUT_12BITS = 0,
- VIDEO_INPUT_10BITS,
- VIDEO_INPUT_8BITS
- };
-#define VIDEO_CONTRL3 0x04
- #define m_SOF (1 << 3)
- #define m_CSC (1 << 0)
- #define v_SOF_ENABLE (0 << 3)
- #define v_SOF_DISABLE (1 << 3)
- #define v_CSC_ENABLE 1
- #define v_CSC_DISABLE 0
-
-#define AV_MUTE 0x05
- #define m_AVMUTE_CLEAR (1 << 7)
- #define m_AVMUTE_ENABLE (1 << 6)
- #define m_AUDIO_MUTE (1 << 1)
- #define m_VIDEO_BLACK (1 << 0)
- #define v_AUDIO_MUTE(n) (n << 1)
- #define v_VIDEO_MUTE(n) (n << 0)
-
-#define VIDEO_TIMING_CTL 0x08
- #define v_HSYNC_POLARITY(n) (n << 3)
- #define v_VSYNC_POLARITY(n) (n << 2)
- #define v_INETLACE(n) (n << 1)
- #define v_EXTERANL_VIDEO(n) (n << 0)
-
-#define VIDEO_EXT_HTOTAL_L 0x09
-#define VIDEO_EXT_HTOTAL_H 0x0a
-#define VIDEO_EXT_HBLANK_L 0x0b
-#define VIDEO_EXT_HBLANK_H 0x0c
-#define VIDEO_EXT_HDELAY_L 0x0d
-#define VIDEO_EXT_HDELAY_H 0x0e
-#define VIDEO_EXT_HDURATION_L 0x0f
-#define VIDEO_EXT_HDURATION_H 0x10
-#define VIDEO_EXT_VTOTAL_L 0x11
-#define VIDEO_EXT_VTOTAL_H 0x12
-#define VIDEO_EXT_VBLANK 0x13
-#define VIDEO_EXT_VDELAY 0x14
-#define VIDEO_EXT_VDURATION 0x15
-
-#define AUDIO_CTRL1 0x35
- enum {
- CTS_SOURCE_INTERNAL = 0,
- CTS_SOURCE_EXTERNAL
- };
- #define v_CTS_SOURCE(n) (n << 7)
- enum {
- DOWNSAMPLE_DISABLE = 0,
- DOWNSAMPLE_1_2,
- DOWNSAMPLE_1_4
- };
- #define v_DOWN_SAMPLE(n) (n << 5)
- enum {
- AUDIO_SOURCE_IIS = 0,
- AUDIO_SOURCE_SPDIF
- };
- #define v_AUDIO_SOURCE(n) (n << 3)
- #define v_MCLK_ENABLE(n) (n << 2)
- enum {
- MCLK_128FS = 0,
- MCLK_256FS,
- MCLK_384FS,
- MCLK_512FS
- };
- #define v_MCLK_RATIO(n) (n)
-
-#define AUDIO_SAMPLE_RATE 0x37
- enum {
- AUDIO_32K = 0x3,
- AUDIO_441K = 0x0,
- AUDIO_48K = 0x2,
- AUDIO_882K = 0x8,
- AUDIO_96K = 0xa,
- AUDIO_1764K = 0xc,
- AUDIO_192K = 0xe,
- };
-
-#define AUDIO_I2S_MODE 0x38
- enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
- };
- #define v_I2S_CHANNEL(n) ((n) << 2)
- enum {
- I2S_STANDARD = 0,
- I2S_LEFT_JUSTIFIED,
- I2S_RIGHT_JUSTIFIED
- };
- #define v_I2S_MODE(n) (n)
-
-#define AUDIO_I2S_MAP 0x39
-#define AUDIO_I2S_SWAPS_SPDIF 0x3a
- #define v_SPIDF_FREQ(n) (n)
-
-#define N_32K 0x1000
-#define N_441K 0x1880
-#define N_882K 0x3100
-#define N_1764K 0x6200
-#define N_48K 0x1800
-#define N_96K 0x3000
-#define N_192K 0x6000
-
-#define AUDIO_N_H 0x3f
-#define AUDIO_N_M 0x40
-#define AUDIO_N_L 0x41
-
-#define AUDIO_CTS_H 0x45
-#define AUDIO_CTS_M 0x46
-#define AUDIO_CTS_L 0x47
-
-
-#define DDC_CLK_L 0x4b
-#define DDC_CLK_H 0x4c
-
-#define EDID_SEGMENT_POINTER 0x4d
-#define EDID_WORD_ADDR 0x4e
-#define EDID_FIFO_OFFSET 0x4f
-#define EDID_FIFO_ADDR 0x50
-
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX 0x9f
-enum {
- INFOFRAME_AVI = 0x06,
- INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_ADDR 0xa0
-
-
-#define SIZE_AVI_INFOFRAME 0x11 // 14 bytes
-#define SIZE_AUDIO_INFOFRAME 0x0F // 15 bytes
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-
-#define HDCP_CTRL 0x52
- #define m_HDMI_DVI (1 << 1)
- #define v_HDMI_DVI(n) (n << 1)
-
-#define INTERRUPT_MASK1 0xc0
-#define INTERRUPT_STATUS1 0xc1
- #define m_INT_HOTPLUG (1 << 7)
- #define m_INT_ACTIVE_VSYNC (1 << 6)
- #define m_INT_EDID_READY (1 << 2)
-
-#define INTERRUPT_MASK2 0xc2
-#define INTERRUPT_STATUS2 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_FLAG (1 << 6)
- #define m_INT_HDCP_OK (1 << 4)
-
-#define HDMI_STATUS 0xc8
- #define m_HOTPLUG (1 << 7)
- #define m_DDC_SDA (1 << 5)
- #define m_DDC_SDC (1 << 4)
-
-#define PHY_SYNC 0xce //sync phy parameter
-
-#define PHY_DRIVER 0xe1
- #define v_MAIN_DRIVER(n) (n << 4)
- #define v_PRE_DRIVER(n) (n << 2)
- #define v_TX_ENABLE(n) (n << 1)
-
-#define PHY_PRE_EMPHASIS 0xe2
- #define v_PRE_EMPHASIS(n) (n << 4)
- #define v_TMDS_PWRDOWN(n) (n)
-
-#define PHY_PLL_TEST 0xe3
-#define PHY_BANDGAP_PWR 0xe4
- #define v_BANDGAP_PWR_DOWN 0x03
- #define v_BANDGAP_PWR_UP 0
-
-#define PHY_PLL_CTRL 0xe5
- #define v_PLL_DISABLE(n) (n << 4)
- #define v_PLL_RESET(n) (n << 3)
- #define v_TMDS_RESET(n) (n << 2)
-
-#define PHY_PLL_LDO_PWR 0xe7
- #define v_LDO_PWR_DOWN(n) (n << 2)
-
-#define HDMIRdReg(addr) readl_relaxed(hdmi->regbase + (addr) * 0x04)
-#define HDMIWrReg(addr, val) writel_relaxed((val), hdmi->regbase + (addr) * 0x04)
-#define HDMIMskReg(temp, addr, msk, val) \
- temp = readl_relaxed(hdmi->regbase + (addr) * 0x04) & (0xFF - (msk)) ; \
- writel_relaxed(temp | ( (val) & (msk) ), hdmi->regbase + (addr) * 0x04);
-
-extern int rk2928_hdmi_initial(void);
-
-#endif
+++ /dev/null
-source "drivers/video/rockchip/hdmi/chips/rk30/hdcp/Kconfig"
\ No newline at end of file
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-
-obj-$(CONFIG_HDMI_RK30) += rk30_hdmi_hw.o rk30_hdmi.o
-obj-$(CONFIG_HDCP_RK30) += hdcp/
+++ /dev/null
-config HDCP_RK30
- bool "RK30 HDCP support"
- depends on LCDC_RK30 && HDMI_RK30
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-config HDCP_RK30_DEBUG
- bool "RK30 HDCP Debugging"
- depends on HDCP_RK30
- default n
- help
- Enableds verbose debugging the the HDCP drivers
+++ /dev/null
-#
-# Makefile for HDCP linux kernel module.
-#
-
-ccflags-$(CONFIG_HDCP_RK30_DEBUG) = -DDEBUG -DHDCP_DEBUG
-
-obj-$(CONFIG_HDCP_RK30) += hdcp.o
-hdcp-y := rk30_hdcp.o rk30_hdmi_hdcp.o
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/miscdevice.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include "../rk30_hdmi.h"
-#include "../rk30_hdmi_hw.h"
-#include "rk30_hdmi_hdcp.h"
-
-static struct hdcp *hdcp = NULL;
-
-static void hdcp_work_queue(struct work_struct *work);
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_submit_work
- *-----------------------------------------------------------------------------
- */
-struct delayed_work *hdcp_submit_work(int event, int delay)
-{
- struct hdcp_delayed_work *work;
-
- HDCP_DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
-
- work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
- work->event = event;
- queue_delayed_work(hdcp->workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- printk(KERN_WARNING "HDCP: Cannot allocate memory to "
- "create work\n");
- return 0;
- }
-
- return &work->work;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_cancel_work
- *-----------------------------------------------------------------------------
- */
-static void hdcp_cancel_work(struct delayed_work **work)
-{
- int ret = 0;
-
- return;
- if (*work) {
- ret = cancel_delayed_work(*work);
- if (ret != 1) {
- ret = cancel_work_sync(&((*work)->work));
- printk(KERN_INFO "Canceling work failed - "
- "cancel_work_sync done %d\n", ret);
- }
- kfree(*work);
- *work = 0;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_failure
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_failure(void)
-{
- HDCP_DBG("%s hdcp->retry_cnt %d \n", __FUNCTION__, hdcp->retry_cnt);
- if (hdcp->hdmi_state == HDMI_STOPPED) {
- return;
- }
-
- rk30_hdcp_disable(hdcp);
- rk30_hdmi_control_output(false);
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
- if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
- hdcp->retry_cnt--;
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying, attempts=%d\n",
- hdcp->retry_cnt);
- } else
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying\n");
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
- HDCP_REAUTH_DELAY);
- } else {
- printk(KERN_INFO "HDCP: authentication failed - "
- "HDCP disabled\n");
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
-
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_start_authentication
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_start_authentication(void)
-{
- int status = HDCP_OK;
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- HDCP_DBG("HDCP: authentication start");
-
- status = rk30_hdcp_start_authentication(hdcp);
-
- if (status != HDCP_OK) {
- HDCP_DBG("HDCP: authentication failed");
- hdcp_wq_authentication_failure();
- } else {
- hdcp->hdcp_state = HDCP_AUTHENTICATION_1ST;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_1st
- *-----------------------------------------------------------------------------
- */
-static int hdcp_wq_authentication_1st(void)
-{
- int status = HDCP_OK;
-
- HDCP_DBG("1st authen start");
-
- status = rk30_hdcp_authentication_1st(hdcp);
-
- if (status == -HDCP_DDC_ERROR)
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_START_1ST, 1000);
- else if (status != HDCP_OK) {
- printk(KERN_INFO "HDCP: 1st authen failed %d", status);
-// hdcp->retry_cnt = 0;
- hdcp_wq_authentication_failure();
- }
- else {
- HDCP_DBG("HDCP: 1st Authentication successful");
- hdcp->hdcp_state = HDCP_WAIT_R0_DELAY;
-// hdcp.auth_state = HDCP_STATE_AUTH_1ST_STEP;
- }
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_r0
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_check_r0(void)
-{
- int status = rk30_hdcp_lib_step1_r0_check(hdcp);
-
- if (status == -HDCP_CANCELLED_AUTH) {
- HDCP_DBG("Authentication step 1/R0 cancelled.");
- return;
- } else if (status < 0)
- hdcp_wq_authentication_failure();
- else {
- if (hdcp_lib_check_repeater_bit_in_tx(hdcp)) {
- /* Repeater */
- printk(KERN_INFO "HDCP: authentication step 1 "
- "successful - Repeater\n");
-
- hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
-// hdcp.auth_state = HDCP_STATE_AUTH_2ND_STEP;
-
- hdcp->pending_wq_event =
- hdcp_submit_work(HDCP_AUTH_START_2ND, 0);
-
- } else {
- /* Receiver */
- printk(KERN_INFO "HDCP: authentication step 1 "
- "successful - Receiver\n");
-
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
- }
-}
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_bksv
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_step2_authentication(void)
-{
- int status = HDCP_OK;
-
- HDCP_DBG("%s", __FUNCTION__);
-
- status = rk30_hdcp_authentication_2nd(hdcp);
-
- if (status == -HDCP_CANCELLED_AUTH) {
- HDCP_DBG("Authentication step 2nd cancelled.");
- return;
- }
- else if (status < 0) {
- printk(KERN_INFO "HDCP: step2 authentication failed");
- hdcp_wq_authentication_failure();
- }
- else {
- HDCP_DBG("HDCP: step2 authentication successful");
-
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_3rd
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_3rd(void)
-{
- int status = rk30_hdcp_lib_step3_r0_check(hdcp);
-
- if (status == -HDCP_CANCELLED_AUTH) {
- HDCP_DBG("Authentication step 3/Ri cancelled.");
- return;
- } else if (status < 0)
- hdcp_wq_authentication_failure();
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_disable
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_disable(int event)
-{
- printk(KERN_INFO "HDCP: disabled");
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
- rk30_hdcp_disable(hdcp);
- if(event == HDCP_DISABLE_CTL) {
- hdcp->hdcp_state = HDCP_DISABLED;
- if(hdcp->hdmi_state == HDMI_STARTED)
- rk30_hdmi_control_output(true);
- }
- else if(event == HDCP_STOP_FRAME_EVENT)
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_work_queue
- *-----------------------------------------------------------------------------
- */
-static void hdcp_work_queue(struct work_struct *work)
-{
- struct hdcp_delayed_work *hdcp_w =
- container_of(work, struct hdcp_delayed_work, work.work);
- int event = hdcp_w->event;
-
- mutex_lock(&hdcp->lock);
-
- HDCP_DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
- jiffies_to_msecs(jiffies),
- hdcp->hdmi_state,
- hdcp->hdcp_state,
- (event & 0xFF00) >> 8,
- event & 0xFF);
-
- if(event == HDCP_STOP_FRAME_EVENT) {
- hdcp->hdmi_state = HDMI_STOPPED;
- }
-
- if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
- hdcp_wq_disable(event);
- }
-
- if (event & HDCP_WORKQUEUE_SRC)
- hdcp->pending_wq_event = 0;
-
- /* First handle HDMI state */
- if (event == HDCP_START_FRAME_EVENT) {
- hdcp->pending_start = 0;
- hdcp->hdmi_state = HDMI_STARTED;
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- }
-
- /**********************/
- /* HDCP state machine */
- /**********************/
- switch (hdcp->hdcp_state) {
- case HDCP_DISABLED:
- /* HDCP enable control or re-authentication event */
- if (event == HDCP_ENABLE_CTL) {
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- if (hdcp->hdmi_state == HDMI_STARTED)
- hdcp_wq_start_authentication();
- else
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
- break;
-
- case HDCP_ENABLE_PENDING:
- /* HDMI start frame event */
- if (event == HDCP_START_FRAME_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_AUTHENTICATION_START:
- /* Re-authentication */
- if (event == HDCP_AUTH_REATT_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_AUTHENTICATION_1ST:
- if(event == HDCP_AUTH_START_1ST)
- hdcp_wq_authentication_1st();
- break;
-
- case HDCP_WAIT_R0_DELAY:
- if(event == HDCP_R0_EXP_EVENT)
- hdcp_wq_check_r0();
- break;
-
- case HDCP_WAIT_KSV_LIST:
- /* KSV failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: KSV switch failure\n");
-
- hdcp_wq_authentication_failure();
- }
- /* KSV list ready event */
- else if (event == HDCP_AUTH_START_2ND)
- hdcp_wq_step2_authentication();
- break;
-
- case HDCP_LINK_INTEGRITY_CHECK:
- /* Ri failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: Ri check failure\n");
- hdcp_wq_authentication_failure();
- }
- else if(event == HDCP_RI_EXP_EVENT)
- hdcp_wq_authentication_3rd();
- break;
-
- default:
- printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
- break;
- }
-
- kfree(hdcp_w);
- if(event == HDCP_STOP_FRAME_EVENT)
- complete(&hdcp->complete);
-
- mutex_unlock(&hdcp->lock);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_start_frame_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_start_frame_cb(void)
-{
- HDCP_DBG("hdcp_start_frame_cb()");
-
- /* Cancel any pending work */
- if (hdcp->pending_start)
- hdcp_cancel_work(&hdcp->pending_start);
- if (hdcp->pending_wq_event)
- hdcp_cancel_work(&hdcp->pending_wq_event);
- hdcp->pending_disable = 0;
- hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_irq_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_irq_cb(int interrupt)
-{
- rk30_hdcp_irq(hdcp);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_on_cb
- *-----------------------------------------------------------------------------
- */
-static int hdcp_power_on_cb(void)
-{
- HDCP_DBG("%s", __FUNCTION__);
- return rk30_hdcp_load_key2mem(hdcp, hdcp->keys);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_off_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_power_off_cb(void)
-{
- HDCP_DBG("%s", __FUNCTION__);
- if(!hdcp->enable)
- return;
-
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- hdcp->pending_disable = 1;
- init_completion(&hdcp->complete);
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
- wait_for_completion_interruptible_timeout(&hdcp->complete,
- msecs_to_jiffies(2000));
-}
-
-// Load HDCP key to external HDCP memory
-static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
-{
- if (!fw) {
- pr_err("HDCP: failed to load keys\n");
- return;
- }
-
- if(fw->size < HDCP_KEY_SIZE) {
- pr_err("HDCP: firmware wrong size %d\n", fw->size);
- return;
- }
-
- hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->keys == NULL) {
- pr_err("HDCP: can't allocated space for keys\n");
- return;
- }
-
- memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
-
- rk30_hdcp_load_key2mem(hdcp, hdcp->keys);
- printk(KERN_INFO "HDCP: loaded hdcp key success\n");
-
- if(fw->size > HDCP_KEY_SIZE) {
- HDCP_DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
- if((fw->size - HDCP_KEY_SIZE) % 5) {
- pr_err("HDCP: failed to load invalid keys\n");
- return;
- }
- hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->invalidkeys == NULL) {
- pr_err("HDCP: can't allocated space for invalid keys\n");
- return;
- }
- memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
- hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
- printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
- }
-}
-
-static ssize_t hdcp_enable_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int enable = 0;
-
- if(hdcp)
- enable = hdcp->enable;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t hdcp_enable_write(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int enable;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &enable);
- if(hdcp->enable != enable)
- {
- /* Post event to workqueue */
- if(enable) {
- if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- else {
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- hdcp->enable = enable;
- }
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
-
-static ssize_t hdcp_trytimes_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int trytimes = 0;
-
- if(hdcp)
- trytimes = hdcp->retry_times;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
-}
-
-static ssize_t hdcp_trytimes_wrtie(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int trytimes;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &trytimes);
- if(hdcp->retry_times != trytimes)
- hdcp->retry_times = trytimes;
-
- return count;
-}
-
-
-static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
-
-
-static struct miscdevice mdev;
-
-static int __init rk30_hdcp_init(void)
-{
- int ret;
-
- HDCP_DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
-
- hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
- if(!hdcp)
- {
- printk(KERN_ERR ">>HDCP: kmalloc fail!");
- ret = -ENOMEM;
- goto error0;
- }
- memset(hdcp, 0, sizeof(struct hdcp));
- mutex_init(&hdcp->lock);
-
- mdev.minor = MISC_DYNAMIC_MINOR;
- mdev.name = "hdcp";
- mdev.mode = 0666;
- if (misc_register(&mdev)) {
- printk(KERN_ERR "HDCP: Could not add character driver\n");
- ret = HDMI_ERROR_FALSE;
- goto error1;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_enable);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file enable\n");
- ret = -EINVAL;
- goto error2;
- }
-
- ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
- ret = -EINVAL;
- goto error3;
- }
-
- hdcp->workqueue = create_singlethread_workqueue("hdcp");
- if (hdcp->workqueue == NULL) {
- printk(KERN_ERR "HDCP,: create workqueue failed.\n");
- goto error4;
- }
-
-
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "hdcp.keys", mdev.this_device, GFP_KERNEL,
- hdcp, hdcp_load_keys_cb);
- if (ret < 0) {
- printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
- goto error5;
- }
-
- hdcp->hdmi = rk30_hdmi_register_hdcp_callbacks( hdcp_start_frame_cb,
- hdcp_irq_cb,
- hdcp_power_on_cb,
- hdcp_power_off_cb);
-
- HDCP_DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
- return 0;
-
-error5:
- destroy_workqueue(hdcp->workqueue);
-error4:
- device_remove_file(mdev.this_device, &dev_attr_trytimes);
-error3:
- device_remove_file(mdev.this_device, &dev_attr_enable);
-error2:
- misc_deregister(&mdev);
-error1:
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-error0:
- return ret;
-}
-
-static void __exit rk30_hdcp_exit(void)
-{
- if(hdcp) {
- mutex_lock(&hdcp->lock);
- rk30_hdmi_register_hdcp_callbacks(0, 0, 0, 0);
- device_remove_file(mdev.this_device, &dev_attr_enable);
- misc_deregister(&mdev);
- destroy_workqueue(hdcp->workqueue);
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- mutex_unlock(&hdcp->lock);
- kfree(hdcp);
- }
-}
-
-//module_init(rk30_hdcp_init);
-device_initcall_sync(rk30_hdcp_init);
-module_exit(rk30_hdcp_exit);
\ No newline at end of file
+++ /dev/null
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <mach/io.h>
-#include "../rk30_hdmi.h"
-#include "../rk30_hdmi_hw.h"
-#include "rk30_hdmi_hdcp.h"
-
-static int an_ready = 0, sha_ready = 0, i2c_ack = 9;
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_lib_check_ksv
- *-----------------------------------------------------------------------------
- */
-static int hdcp_lib_check_ksv(uint8_t ksv[5])
-{
- int i, j;
- int zero = 0, one = 0;
-
- for (i = 0; i < 5; i++) {
- /* Count number of zero / one */
- for (j = 0; j < 8; j++) {
- if (ksv[i] & (0x01 << j))
- one++;
- else
- zero++;
- }
- }
-
- if (one == zero)
- return 0;
- else
- return -1;
-}
-
-static void rk30_hdcp_write_mem(int addr_8, char value)
-{
- int temp;
- int addr_32 = addr_8 - addr_8%4;
- int shift = (addr_8%4) * 8;
-
- temp = HDMIRdReg(addr_32);
- temp &= ~(0xff << shift);
- temp |= value << shift;
-// printk("temp is %08x\n", temp);
- HDMIWrReg(addr_32, temp);
-}
-
-int rk30_hdcp_load_key2mem(struct hdcp *hdcp, struct hdcp_keys *key)
-{
- int i;
-
- if(key == NULL) return HDMI_ERROR_FALSE;
-
- HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
-
- for(i = 0; i < 7; i++)
- rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV1 + i, key->KSV[i]);
- for(i = 0; i < 7; i++)
- rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV2 + i, key->KSV[i]);
- for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
- rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + i, key->DeviceKey[i]);
- for(i = 0; i < HDCP_KEY_SHA_SIZE; i++)
- rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + HDCP_PRIVATE_KEY_SIZE + i, key->sha1[i]);
-
- HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV | 0x20);
- return HDCP_OK;
-}
-
-void rk30_hdcp_disable(struct hdcp *hdcp)
-{
- int temp;
-
- // Diable Encrypt
- HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED, v_HDCP_FRAMED_ENCRYPED(0));
-
- // Diable HDCP Interrupt
- HDMIWrReg(SOFT_HDCP_INT_MASK1, 0x00);
- HDMIWrReg(SOFT_HDCP_INT_MASK2, 0x00);
-
- // Stop and Reset HDCP
- HDMIWrReg(SOFT_HDCP_CTRL1, 0x00);
-}
-
-static int rk30_hdcp_load_key(struct hdcp *hdcp)
-{
- int value, temp = 0;
-
- if(hdcp->keys == NULL) {
- pr_err("[%s] HDCP key not loaded.\n", __FUNCTION__);
- return HDCP_KEY_ERR;
- }
-
- value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
- //Check HDCP key loaded from external HDCP memory
- while((value & (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) != (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) {
- if(temp > 10) {
- pr_err("[%s] loaded hdcp key is incorrectable %02x\n", __FUNCTION__, value & 0xFF);
- return HDCP_KEY_ERR;
- }
- //Load HDCP Key from external HDCP memory
- HDMIWrReg(HDCP_KEY_ACCESS_CTRL2, m_LOAD_HDCP_KEY);
- msleep(1);
- value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
- temp++;
- }
-
- return HDCP_OK;
-}
-
-static int rk30_hdcp_ddc_read(struct hdcp *hdcp, u16 no_bytes, u8 addr, u8 *pdata)
-{
- int i, temp;
-
- i2c_ack = 0;
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0xC0);
- HDMIWrReg(HDCP_DDC_ACCESS_LENGTH, no_bytes);
- HDMIWrReg(HDCP_DDC_OFFSET_ADDR, addr);
- HDMIWrReg(HDCP_DDC_CTRL, m_DDC_READ);
-
- while(1) {
- if(i2c_ack & 0xc0) {
- break;
- }
- msleep(100);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
-
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0x00);
- if(i2c_ack & m_I2C_NO_ACK)
- return -HDCP_DDC_ERROR;
-
- if(i2c_ack & m_I2C_ACK) {
- for(i = 0; i < no_bytes; i++)
- pdata[i] = HDMIRdReg(HDCP_DDC_READ_BUFF + i * 4);
- }
-
- return HDCP_OK;
-}
-
-static int rk30_hdcp_ddc_write(struct hdcp *hdcp, u16 no_bytes, u8 addr, u8 *pdata)
-{
- int i, temp;
-
- for(i = 0; i < no_bytes; i++)
- HDMIWrReg(HDCP_DDC_WRITE_BUFF + i * 4, pdata[i]);
-
- i2c_ack = 0;
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0xC0);
- HDMIWrReg(HDCP_DDC_ACCESS_LENGTH, no_bytes);
- HDMIWrReg(HDCP_DDC_OFFSET_ADDR, addr);
- HDMIWrReg(HDCP_DDC_CTRL, m_DDC_WRITE);
-
- while(1) {
- if(i2c_ack & 0xc0) {
- break;
- }
- msleep(100);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0x00);
- if(i2c_ack & m_I2C_NO_ACK)
- return -HDCP_DDC_ERROR;
-
- return HDCP_OK;
-}
-
-int rk30_hdcp_start_authentication(struct hdcp *hdcp)
-{
- int rc, temp;
- struct hdmi* hdmi = hdcp->hdmi;
-
- rc = rk30_hdcp_load_key(hdcp);
- if(rc != HDCP_OK)
- return rc;
-
- // Config DDC Clock
- temp = (hdmi->tmdsclk/HDCP_DDC_CLK)/4;
- HDMIWrReg(DDC_BUS_FREQ_L, temp & 0xFF);
- HDMIWrReg(DDC_BUS_FREQ_H, (temp >> 8) & 0xFF);
-
- // Enable Software HDCP INT
- HDMIWrReg(INTR_MASK2, 0x00);
- HDMIWrReg(SOFT_HDCP_INT_MASK1, m_SF_MODE_READY);
- HDMIWrReg(SOFT_HDCP_INT_MASK2, 0x00);
-
- // Diable Encrypt
- HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED, v_HDCP_FRAMED_ENCRYPED(0));
-
- // Enable Software HDCP
- HDMIWrReg(SOFT_HDCP_CTRL1, v_SOFT_HDCP_AUTH_EN(1));
-
- return HDCP_OK;
-}
-
-static int rk30_hdcp_generate_an(struct hdcp *hdcp, uint8_t ksv[8])
-{
- int temp;
-
- HDCP_DBG("%s", __FUNCTION__);
-
- an_ready = 0;
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK1, (1 << 4), (1 << 4));
- HDMIWrReg(SOFT_HDCP_CTRL1, v_SOFT_HDCP_AUTH_EN(1) | v_SOFT_HDCP_PREP_AN(1));
-
- while(1) {
- if(an_ready)
- break;
- msleep(100);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK1, (1 << 4), 0);
- for(temp = 0; temp < 8; temp++)
- ksv[temp] = HDMIRdReg(HDCP_AN_BUFF + temp * 4);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_lib_read_aksv
- *-----------------------------------------------------------------------------
- */
-static void rk30_hdcp_read_aksv(struct hdcp *hdcp, u8 *ksv_data)
-{
- u8 i;
- int temp;
-
- // Load AKSV to Reg
- HDMIMskReg(temp, HDCP_KEY_MEM_CTRL, (1 << 4), (1 << 4));
-
- for (i = 0; i < 5; i++) {
- ksv_data[i] = HDMIRdReg(HDCP_AKSV_BUFF + i * 4);
- }
-}
-
-int rk30_hdcp_authentication_1st(struct hdcp *hdcp)
-{
- /* HDCP authentication steps:
- * 1) Read Bksv - check validity (is HDMI Rx supporting HDCP ?)
- * 2) Initializes HDCP (CP reset release)
- * 3) Read Bcaps - is HDMI Rx a repeater ?
- * *** First part authentication ***
- * 4) Read Bksv - check validity (is HDMI Rx supporting HDCP ?)
- * 5) Generates An
- * 6) DDC: Writes An, Aksv
- * 7) DDC: Write Bksv
- */
- uint8_t an_ksv_data[8];
- uint8_t rx_type;
- uint8_t trytimes = 5;
- int temp, status;
- /* Generate An */
- status = rk30_hdcp_generate_an(hdcp, an_ksv_data);
- if(status < 0)
- return status;
- HDCP_DBG("AN: %02x %02x %02x %02x %02x %02x %02x %02x", an_ksv_data[0], an_ksv_data[1],
- an_ksv_data[2], an_ksv_data[3],
- an_ksv_data[4], an_ksv_data[5],
- an_ksv_data[6], an_ksv_data[7]);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- /* DDC: Write An */
- status = rk30_hdcp_ddc_write(hdcp, DDC_AN_LEN, DDC_AN_ADDR , an_ksv_data);
- if (status < 0)
- return status;
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- /* Read AKSV from IP: (HDCP AKSV register) */
- rk30_hdcp_read_aksv(hdcp, an_ksv_data);
-
- HDCP_DBG("AKSV: %02x %02x %02x %02x %02x", an_ksv_data[0], an_ksv_data[1],
- an_ksv_data[2], an_ksv_data[3],
- an_ksv_data[4]);
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- if (hdcp_lib_check_ksv(an_ksv_data)) {
- printk(KERN_INFO "HDCP: AKSV error (number of 0 and 1)\n");
- return -HDCP_AKSV_ERROR;
- }
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- /* DDC: Write AKSV */
- status = rk30_hdcp_ddc_write(hdcp, DDC_AKSV_LEN, DDC_AKSV_ADDR, an_ksv_data);
- if (status < 0)
- return status;
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- /* Read BCAPS to determine if HDCP RX is a repeater */
- status = rk30_hdcp_ddc_read(hdcp, DDC_BCAPS_LEN, DDC_BCAPS_ADDR, &rx_type);
- if (status < 0)
- return status;
-
- HDCP_DBG("bcaps is %02x", rx_type);
-
- HDMIWrReg(SOFT_HDCP_BCAPS, rx_type);
-
- if(rx_type & m_REPEATER) {
- HDCP_DBG("Downstream device is a repeater");
- HDMIMskReg(temp, SOFT_HDCP_CTRL1, m_SOFT_HDCP_REPEATER, v_SOFT_HDCP_REPEATER(1));
- }
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- /* DDC: Read BKSV from RX */
- while(trytimes--) {
- status = rk30_hdcp_ddc_read(hdcp, DDC_BKSV_LEN, DDC_BKSV_ADDR, an_ksv_data);
- if (status < 0)
- return status;
-
- HDCP_DBG("BKSV: %02x %02x %02x %02x %02x", an_ksv_data[0], an_ksv_data[1],
- an_ksv_data[2], an_ksv_data[3],
- an_ksv_data[4]);
-
- if (hdcp_lib_check_ksv(an_ksv_data) == 0)
- break;
- else {
- HDCP_DBG("BKSV error (number of 0 and 1)");
- }
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
- if(trytimes == 0)
- return -HDCP_BKSV_ERROR;
-
- for(trytimes = 0; trytimes < 5; trytimes++)
- HDMIWrReg(HDCP_BKSV_BUFF + trytimes * 4, an_ksv_data[trytimes]);
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK1, (1 << 6), (1 << 6));
- HDMIMskReg(temp, SOFT_HDCP_CTRL1, m_SOFT_HDCP_GEN_RI, v_SOFT_HDCP_GEN_RI(1));
- return HDCP_OK;
-}
-
-static int rk30_hdcp_r0_check(struct hdcp *hdcp)
-{
- u8 ro_rx[2], ro_tx[2];
- int status;
-
- HDCP_DBG("%s()", __FUNCTION__);
-
- HDMIMskReg(status, SOFT_HDCP_INT_MASK1, (1 << 6), 0);
-
- /* DDC: Read Ri' from RX */
- status = rk30_hdcp_ddc_read(hdcp, DDC_Ri_LEN, DDC_Ri_ADDR , (u8 *)&ro_rx);
- if (status < 0)
- return status;
-
- /* Read Ri in HDCP IP */
- ro_tx[0] = HDMIRdReg(HDCP_RI_BUFF);
-
- ro_tx[1] = HDMIRdReg(HDCP_RI_BUFF + 4);
-
- /* Compare values */
- HDCP_DBG("ROTX: %x%x RORX:%x%x", ro_tx[0], ro_tx[1], ro_rx[0], ro_rx[1]);
-
- if ((ro_rx[0] == ro_tx[0]) && (ro_rx[1] == ro_tx[1]))
- return HDCP_OK;
- else
- return -HDCP_AUTH_FAILURE;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_lib_check_repeater_bit_in_tx
- *-----------------------------------------------------------------------------
- */
-u8 hdcp_lib_check_repeater_bit_in_tx(struct hdcp *hdcp)
-{
- return (HDMIRdReg(HDCP_BCAPS) & m_REPEATER);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: rk30_hdcp_lib_step1_r0_check
- *-----------------------------------------------------------------------------
- */
-int rk30_hdcp_lib_step1_r0_check(struct hdcp *hdcp)
-{
- int status = HDCP_OK, temp;
-
- /* HDCP authentication steps:
- * 1) DDC: Read M0'
- * 2) Compare M0 and M0'
- * if Rx is a receiver: switch to authentication step 3
- * 3) Enable encryption / auto Ri check / disable AV mute
- * if Rx is a repeater: switch to authentication step 2
- * 3) Get M0 from HDMI IP and store it for further processing (V)
- * 4) Enable encryption / auto Ri check / auto BCAPS RDY polling
- * Disable AV mute
- */
-
- HDCP_DBG("hdcp_lib_step1_r0_check() %u", jiffies_to_msecs(jiffies));
-
- status = rk30_hdcp_r0_check(hdcp);
- if(status < 0)
- return status;
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- if (hdcp_lib_check_repeater_bit_in_tx(hdcp)) {
-
- } else {
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, (1 << 4) | (1 << 5), (1 << 4) | (1 << 5));
- /* Receiver: enable encryption */
- HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED, v_HDCP_FRAMED_ENCRYPED(1));
- HDMIMskReg(temp, SOFT_HDCP_CTRL1, m_SOFT_HDCP_AUTH_START, m_SOFT_HDCP_AUTH_START);
- }
-
- return HDCP_OK;
-}
-
-static int rk30_hdcp_read_ksvlist(struct hdcp *hdcp, int num)
-{
- int i, temp;
- uint8_t an_ksv_data[5];
-
- i2c_ack = 0;
-
- HDCP_DBG("%s", __FUNCTION__);
-
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0xC0);
- HDMIWrReg(HDCP_DDC_ACCESS_LENGTH, num * 5);
- HDMIWrReg(HDCP_DDC_OFFSET_ADDR, DDC_KSV_FIFO_ADDR);
- HDMIWrReg(HDCP_DDC_CTRL, m_DDC_READ | (1 << 2));
-
- while(1) {
- if(i2c_ack & 0xc0) {
- break;
- }
- msleep(100);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
-
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK2, m_I2C_ACK|m_I2C_NO_ACK, 0x00);
- if(i2c_ack & m_I2C_NO_ACK)
- return -HDCP_DDC_ERROR;
-
- if(i2c_ack & m_I2C_ACK) {
- for(i = 0; i < num * 5; i++) {
- temp = HDMIRdReg(0x80 * 4);
- an_ksv_data[i%5] = temp;
- if((i+1) % 5 == 0) {
- HDCP_DBG("BKSV: %02x %02x %02x %02x %02x", an_ksv_data[0], an_ksv_data[1],
- an_ksv_data[2], an_ksv_data[3],
- an_ksv_data[4]);
- if (hdcp_lib_check_ksv(an_ksv_data))
- return -HDCP_AUTH_FAILURE;
-// for(temp = 0; temp < 5; temp++)
-// HDMIWrReg(HDCP_BKSV_BUFF + temp * 4, an_ksv_data[temp]);
- }
- }
- }
- return HDCP_OK;
-}
-
-static int rk30_hdcp_check_sha(struct hdcp *hdcp)
-{
- int temp, status;
- uint8_t asha[4], bsha[4], i;
-
- HDCP_DBG("%s", __FUNCTION__);
-
- // Calculate SHA1
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK1, (1 << 3), (1 << 3));
- HDMIMskReg(temp, SOFT_HDCP_CTRL1, m_SOFT_HDCP_CAL_SHA, v_SOFT_HDCP_CAL_SHA(1));
-
- while(1) {
- if(sha_ready)
- break;
- msleep(100);
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
- }
-
- HDMIMskReg(temp, SOFT_HDCP_INT_MASK1, (1 << 3), 0);
-
- for(temp = 0; temp < 5; temp++) {
- for(i = 0; i < 4; i++) {
- HDMIWrReg(HDCP_SHA_INDEX, i);
- asha[i] = HDMIRdReg(HDCP_SHA_BUF + 4 * temp);
- }
- HDCP_DBG("ASHA%d %02x %02x %02x %02x\n", temp, asha[0], asha[1], asha[2], asha[3]);
-
- status = rk30_hdcp_ddc_read(hdcp, DDC_V_LEN, DDC_V_ADDR + temp * 4, bsha);
- if(status < 0)
- return status;
-
- HDCP_DBG("BSHA%d %02x %02x %02x %02x\n", temp, bsha[0], bsha[1], bsha[2], bsha[3]);
-
- if( (asha[0] != bsha[0]) || (asha[1] != bsha[1]) || (asha[2] != bsha[2]) || (asha[3] != bsha[3]) )
- return -HDCP_AUTH_FAILURE;
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
-
- }
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: rk30_hdcp_authentication_2nd
- *-----------------------------------------------------------------------------
- */
-int rk30_hdcp_authentication_2nd(struct hdcp *hdcp)
-{
- int status = HDCP_OK;
- struct timeval ts_start, ts;
- uint32_t delta = 0, num_dev;
- uint8_t bstatus[2];
-
- HDCP_DBG("\n%s", __FUNCTION__);
-
- do_gettimeofday(&ts_start);
- while(delta <= 5000000) {
- /* Poll BCAPS */
- status = rk30_hdcp_ddc_read(hdcp, DDC_BCAPS_LEN, DDC_BCAPS_ADDR, bstatus);
- if( (status == HDCP_OK) && (bstatus[0] & (1 << 5)) )
- break;
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- do_gettimeofday(&ts);
- delta = (ts.tv_sec - ts_start.tv_sec) * 1000000 + (ts.tv_usec - ts_start.tv_usec);
- msleep(100);
- }
- if(delta > 5000000) {
- HDCP_DBG("Poll BKSV list out of time");
- return -HDCP_BKSVLIST_TIMEOUT;
- }
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- status = rk30_hdcp_ddc_read(hdcp, DDC_BSTATUS_LEN, DDC_BSTATUS_ADDR, bstatus);
- if(status < 0)
- return status;
-
- HDCP_DBG("bstatus %02x %02x\n", bstatus[1], bstatus[0]);
-
- if( bstatus[0] & (1 << 7) ) {
- HDCP_DBG("MAX_DEVS_EXCEEDED");
- return -HDCP_AUTH_FAILURE;
- }
-
- if( bstatus[1] & (1 << 3) ) {
- HDCP_DBG("MAX_CASCADE_EXCEEDED");
- return -HDCP_AUTH_FAILURE;
- }
-
- num_dev = bstatus[0] & 0x7F;
- if( num_dev > (MAX_DOWNSTREAM_DEVICE_NUM)) {
- HDCP_DBG("Out of MAX_DOWNSTREAM_DEVICE_NUM");
- return -HDCP_AUTH_FAILURE;
- }
-
- HDMIWrReg(HDCP_BSTATUS_BUFF, bstatus[0]);
- HDMIWrReg(HDCP_BSTATUS_BUFF + 4, bstatus[1]);
-
- HDMIWrReg(HDCP_NUM_DEV, num_dev);
-
- // Read KSV List
- if(num_dev) {
- status = rk30_hdcp_read_ksvlist(hdcp, num_dev);
- if(status < 0)
- return status;
- }
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- status = rk30_hdcp_check_sha(hdcp);
- if(status < 0)
- return status;
-
- if (hdcp->pending_disable)
- return -HDCP_CANCELLED_AUTH;
-
- HDMIMskReg(status, SOFT_HDCP_INT_MASK2, (1 << 4) | (1 << 5), (1 << 4) | (1 << 5));
- /* Receiver: enable encryption */
- HDMIMskReg(status, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED, v_HDCP_FRAMED_ENCRYPED(1));
- HDMIMskReg(status, SOFT_HDCP_CTRL1, m_SOFT_HDCP_AUTH_START, m_SOFT_HDCP_AUTH_START);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: rk30_hdcp_lib_step3_r0_check
- *-----------------------------------------------------------------------------
- */
-int rk30_hdcp_lib_step3_r0_check(struct hdcp *hdcp)
-{
- return rk30_hdcp_r0_check(hdcp);
-}
-
-void rk30_hdcp_irq(struct hdcp *hdcp)
-{
- int soft_int1, soft_int2;
-
- soft_int1 = HDMIRdReg(INTR_STATUS3);
- soft_int2 = HDMIRdReg(INTR_STATUS4);
- HDMIWrReg(INTR_STATUS3, soft_int1);
- HDMIWrReg(INTR_STATUS4, soft_int2);
- HDCP_DBG("soft_int1 %x soft_int2 %x\n", soft_int1, soft_int2);
- if(soft_int1 & m_SF_MODE_READY)
- hdcp_submit_work(HDCP_AUTH_START_1ST, 0);
- if(soft_int1 & m_SOFT_HDCP_AN_READY)
- an_ready = 1;
- if(soft_int1 & m_SOFT_HDCP_SHA_READY)
- sha_ready = 1;
- if(soft_int1 & m_SOFT_HDCP_RI_READY)
- hdcp->pending_wq_event =
- hdcp_submit_work(HDCP_R0_EXP_EVENT,
- HDCP_R0_DELAY);
- if(soft_int2 & 0xc0)
- i2c_ack = soft_int2 & 0xc0;
- if(soft_int2 & m_SOFT_HDCP_RI_SAVED)
- hdcp->pending_wq_event =
- hdcp_submit_work(HDCP_RI_EXP_EVENT,
- 0);
-}
\ No newline at end of file
+++ /dev/null
-#ifndef __RK30_HDMI_HDCP_H__
-#define __RK30_HDMI_HDCP_H__
-
-/***************************/
-/* Definitions */
-/***************************/
-
-/* Status / error codes */
-enum {
- HDCP_OK,
- HDCP_KEY_ERR,
- HDCP_DDC_ERROR,
- HDCP_AUTH_FAILURE,
- HDCP_AKSV_ERROR,
- HDCP_BKSV_ERROR,
- HDCP_CANCELLED_AUTH,
- HDCP_BKSVLIST_TIMEOUT,
-};
-
-/* Delays */
-#define HDCP_ENABLE_DELAY 300
-#define HDCP_REAUTH_DELAY 100
-#define HDCP_R0_DELAY 120
-#define HDCP_KSV_TIMEOUT_DELAY 5000
-/***********************/
-/* HDCP DDC addresses */
-/***********************/
-
-#define DDC_BKSV_ADDR 0x00
-#define DDC_Ri_ADDR 0x08
-#define DDC_AKSV_ADDR 0x10
-#define DDC_AN_ADDR 0x18
-#define DDC_V_ADDR 0x20
-#define DDC_BCAPS_ADDR 0x40
-#define DDC_BSTATUS_ADDR 0x41
-#define DDC_KSV_FIFO_ADDR 0x43
-
-#define DDC_BKSV_LEN 5
-#define DDC_Ri_LEN 2
-#define DDC_AKSV_LEN 5
-#define DDC_AN_LEN 8
-#define DDC_V_LEN 4//20
-#define DDC_BCAPS_LEN 1
-#define DDC_BSTATUS_LEN 2
-
-/* Event source */
-#define HDCP_SRC_SHIFT 8
-#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
-#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
-#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
-#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
-
-/* Event */
-#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
-#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
-#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
-#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
-#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 4)
-#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 5)
-#define HDCP_AUTH_START_1ST (HDCP_IRQ_SRC | 6)
-#define HDCP_RI_EXP_EVENT (HDCP_IRQ_SRC | 7)
-#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 8)
-#define HDCP_R0_EXP_EVENT (HDCP_WORKQUEUE_SRC | 9)
-#define HDCP_AUTH_START_2ND (HDCP_WORKQUEUE_SRC | 10)
-
-/* Key size */
-#define HDCP_KEY_SIZE 308
-
-/* Authentication retry times */
-#define HDCP_INFINITE_REAUTH 0x100
-
-/* Max downstream device number */
-#define MAX_DOWNSTREAM_DEVICE_NUM 1
-
-enum hdcp_states {
- HDCP_DISABLED,
- HDCP_ENABLE_PENDING,
- HDCP_AUTHENTICATION_START,
- HDCP_AUTHENTICATION_1ST,
- HDCP_WAIT_R0_DELAY,
- HDCP_WAIT_KSV_LIST,
- HDCP_LINK_INTEGRITY_CHECK,
-};
-
-enum hdmi_states {
- HDMI_STOPPED,
- HDMI_STARTED
-};
-
-#define HDCP_PRIVATE_KEY_SIZE 280
-#define HDCP_KEY_SHA_SIZE 20
-#define HDCP_DDC_CLK 100000
-
-struct hdcp_keys{
- u8 KSV[8];
- u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
- u8 sha1[HDCP_KEY_SHA_SIZE];
-};
-
-struct hdcp_delayed_work {
- struct delayed_work work;
- int event;
-};
-
-struct hdcp {
- int enable;
- int retry_times;
- struct hdcp_keys *keys;
- int invalidkey;
- char *invalidkeys;
- struct mutex lock;
- struct completion complete;
- struct workqueue_struct *workqueue;
-
- enum hdmi_states hdmi_state;
- enum hdcp_states hdcp_state;
-
- struct delayed_work *pending_start;
- struct delayed_work *pending_wq_event;
- int retry_cnt;
- int pending_disable;
- struct hdmi* hdmi;
-};
-
-#define SOFT_HDCP_INT_MASK1 0x96 * 4
- #define m_SF_MODE_READY (1 << 7)
-
-#define SOFT_HDCP_INT_MASK2 0x97 * 4
- #define m_I2C_ACK (1 << 7)
- #define m_I2C_NO_ACK (1 << 6)
-
-#define SOFT_HDCP_INT1 0x98 * 4
- #define m_SOFT_HDCP_READY (1 << 7)
- #define m_SOFT_HDCP_RI_READY (1 << 6)
- #define m_SOFT_HDCP_AN_READY (1 << 4)
- #define m_SOFT_HDCP_SHA_READY (1 << 3)
-
-#define SOFT_HDCP_INT2 0x99 * 4
- #define m_SOFT_HDCP_RI_SAVED (1 << 5)
- #define m_SOFT_HDCP_PJ_SAVED (1 << 4)
-
-#define SOFT_HDCP_CTRL1 0x9A * 4
- #define m_SOFT_HDCP_AUTH_EN (1 << 7) // enable software hdcp
- #define m_SOFT_HDCP_AUTH_START (1 << 5)
- #define m_SOFT_HDCP_PREP_AN (1 << 4)
- #define m_SOFT_HDCP_REPEATER (1 << 2)
- #define m_SOFT_HDCP_GEN_RI (1 << 1)
- #define m_SOFT_HDCP_CAL_SHA (1 << 0)
- #define v_SOFT_HDCP_AUTH_EN(n) (n << 7)
- #define v_SOFT_HDCP_PREP_AN(n) (n << 4)
- #define v_SOFT_HDCP_REPEATER(n) (n << 2)
- #define v_SOFT_HDCP_GEN_RI(n) (n << 1)
- #define v_SOFT_HDCP_CAL_SHA(n) (n << 0)
-
-#define HDCP_DDC_ACCESS_LENGTH 0x9E * 4
-#define HDCP_DDC_OFFSET_ADDR 0xA0 * 4
-#define HDCP_DDC_CTRL 0xA1 * 4
- #define m_DDC_READ (1 << 0)
- #define m_DDC_WRITE (1 << 1)
-
-#define SOFT_HDCP_BCAPS 0xE0 * 4
-
-#define HDCP_DDC_READ_BUFF 0xA2 * 4
-#define HDCP_DDC_WRITE_BUFF 0xA7 * 4
-#define HDCP_AN_BUFF 0xE8 * 4
-#define HDCP_AKSV_BUFF 0xBF * 4
-#define HDCP_BKSV_BUFF 0xE3 * 4
-#define HDCP_RI_BUFF 0xD9 * 4
-#define HDCP_BSTATUS_BUFF 0xE1 * 4
-
-#define HDCP_NUM_DEV 0xDC * 4
-#define HDCP_SHA_BUF 0xB9 * 4
-#define HDCP_SHA_INDEX 0xD8 * 4
-
-#ifdef HDCP_DEBUG
-#define HDCP_DBG(format, ...) \
- printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
-#else
-#define HDCP_DBG(format, ...)
-#endif
-
-extern struct delayed_work *hdcp_submit_work(int event, int delay);
-extern void rk30_hdcp_disable(struct hdcp *hdcp);
-extern int rk30_hdcp_start_authentication(struct hdcp *hdcp);
-extern int rk30_hdcp_check_bksv(struct hdcp *hdcp);
-extern int rk30_hdcp_load_key2mem(struct hdcp *hdcp, struct hdcp_keys *key);
-extern int rk30_hdcp_authentication_1st(struct hdcp *hdcp);
-extern int rk30_hdcp_authentication_2nd(struct hdcp *hdcp);
-extern void rk30_hdcp_irq(struct hdcp *hdcp);
-extern int rk30_hdcp_lib_step1_r0_check(struct hdcp *hdcp);
-extern int rk30_hdcp_lib_step3_r0_check(struct hdcp *hdcp);
-extern u8 hdcp_lib_check_repeater_bit_in_tx(struct hdcp *hdcp);
-#endif /* __RK30_HDMI_HDCP_H__ */
\ No newline at end of file
+++ /dev/null
-#include <linux/module.h>\r
-#include <linux/kernel.h>\r
-#include <linux/errno.h>\r
-#include <linux/string.h>\r
-#include <linux/mm.h>\r
-#include <linux/slab.h>\r
-#include <linux/delay.h>\r
-#include <linux/device.h>\r
-#include <linux/init.h>\r
-#include <linux/dma-mapping.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/clk.h>\r
-\r
-#include <mach/board.h>\r
-#include <mach/io.h>\r
-#include <mach/gpio.h>\r
-#include <mach/iomux.h>\r
-#include "rk30_hdmi.h"\r
-#include "rk30_hdmi_hw.h"\r
-\r
-struct hdmi *hdmi = NULL;\r
-\r
-extern irqreturn_t hdmi_irq(int irq, void *priv);\r
-extern void hdmi_work(struct work_struct *work);\r
-extern struct rk_lcdc_driver * rk_get_lcdc_drv(char *name);
-extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
-extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
-\r
-struct hdmi* rk30_hdmi_register_hdcp_callbacks( \r
- void (*hdcp_cb)(void),\r
- void (*hdcp_irq_cb)(int status),\r
- int (*hdcp_power_on_cb)(void),\r
- void (*hdcp_power_off_cb)(void))\r
-{\r
- if(hdmi == NULL)\r
- return HDMI_ERROR_FALSE;\r
-\r
- hdmi->hdcp_cb = hdcp_cb;\r
- hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
- hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
- hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
- \r
- return hdmi;\r
-}\r
-\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-static void hdmi_early_suspend(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
- // When HDMI 1.1V and 2.5V power off, DDC channel will be pull down, current is produced\r
- // from VCC_IO which is pull up outside soc. We need to switch DDC IO to GPIO.\r
- rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_GPIO0A2);\r
- rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_GPIO0A1);\r
- flush_delayed_work(&hdmi->delay_work); \r
- mutex_lock(&hdmi->enable_mutex);\r
- hdmi->suspend = 1;\r
- if(!hdmi->enable) {\r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
- }\r
- disable_irq(hdmi->irq);\r
- mutex_unlock(&hdmi->enable_mutex);\r
- hdmi->command = HDMI_CONFIG_ENABLE;\r
- init_completion(&hdmi->complete);\r
- hdmi->wait = 1;\r
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
- wait_for_completion_interruptible_timeout(&hdmi->complete,\r
- msecs_to_jiffies(5000));\r
- flush_delayed_work(&hdmi->delay_work);\r
- return;\r
-}\r
-\r
-static void hdmi_early_resume(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
- mutex_lock(&hdmi->enable_mutex);\r
- \r
- rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
- rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
- \r
- hdmi->suspend = 0;\r
- rk30_hdmi_initial();\r
- if(hdmi->enable) {\r
- enable_irq(hdmi->irq);\r
- }\r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
-}\r
-#endif\r
-\r
-static inline void hdmi_io_remap(void)\r
-{\r
- unsigned int value;\r
- \r
- // Remap HDMI IO Pin\r
- rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
- rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
- rk30_mux_api_set(GPIO0A0_HDMIHOTPLUGIN_NAME, GPIO0A_HDMI_HOT_PLUG_IN);\r
- \r
- // Select LCDC0 as video source and enabled.\r
- value = (HDMI_SOURCE_DEFAULT << 14) | (1 << 30);\r
- writel(value, GRF_SOC_CON0 + RK30_GRF_BASE);\r
-}\r
-\r
-static int __devinit rk30_hdmi_probe (struct platform_device *pdev)\r
-{\r
- int ret;\r
- struct resource *res;\r
- struct resource *mem;\r
- \r
- hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
- if(!hdmi)\r
- {\r
- dev_err(&pdev->dev, ">>rk30 hdmi kmalloc fail!");\r
- return -ENOMEM;\r
- }\r
- memset(hdmi, 0, sizeof(struct hdmi));\r
- hdmi->dev = &pdev->dev;\r
- platform_set_drvdata(pdev, hdmi);\r
-\r
- if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
- else\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
- if(hdmi->lcdc == NULL)\r
- {\r
- dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- hdmi->xscale = 95;\r
- hdmi->yscale = 95;\r
- \r
- hdmi->hclk = clk_get(NULL,"hclk_hdmi");\r
- if(IS_ERR(hdmi->hclk))\r
- {\r
- dev_err(hdmi->dev, "Unable to get hdmi hclk\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- clk_enable(hdmi->hclk);\r
- \r
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
- if (!res) {\r
- dev_err(hdmi->dev, "Unable to get register resource\n");\r
- ret = -ENXIO;\r
- goto err0;\r
- }\r
- hdmi->regbase_phy = res->start;\r
- hdmi->regsize_phy = (res->end - res->start) + 1;\r
- mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);\r
- if (!mem)\r
- {\r
- dev_err(hdmi->dev, "failed to request mem region for hdmi\n");\r
- ret = -ENOENT;\r
- goto err0;\r
- }\r
-\r
- \r
- hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);\r
- if (!hdmi->regbase) {\r
- dev_err(hdmi->dev, "cannot ioremap registers\n");\r
- ret = -ENXIO;\r
- goto err1;\r
- }\r
- \r
- ret = rk30_hdmi_initial();\r
- if(ret != HDMI_ERROR_SUCESS)\r
- goto err1;\r
- \r
- hdmi_io_remap();\r
- hdmi_sys_init();\r
- \r
- hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
- INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
-\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- hdmi->early_suspend.suspend = hdmi_early_suspend;\r
- hdmi->early_suspend.resume = hdmi_early_resume;\r
- hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
- register_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- \r
- hdmi_register_display_sysfs(hdmi, NULL);\r
- #ifdef CONFIG_SWITCH\r
- hdmi->switch_hdmi.name="hdmi";\r
- switch_dev_register(&(hdmi->switch_hdmi));\r
- #endif\r
- \r
- spin_lock_init(&hdmi->irq_lock);\r
- mutex_init(&hdmi->enable_mutex);\r
- \r
- /* get the IRQ */\r
- hdmi->irq = platform_get_irq(pdev, 0);\r
- if(hdmi->irq <= 0) {\r
- dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);\r
- ret = -ENXIO;\r
- goto err2;\r
- }\r
-\r
- /* request the IRQ */\r
- ret = request_irq(hdmi->irq, hdmi_irq, 0, dev_name(&pdev->dev), hdmi);\r
- if (ret)\r
- {\r
- dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);\r
- goto err2;\r
- }\r
-\r
- hdmi_dbg(hdmi->dev, "rk30 hdmi probe sucess.\n");\r
- return 0;\r
-err2:\r
- #ifdef CONFIG_SWITCH\r
- switch_dev_unregister(&(hdmi->switch_hdmi));\r
- #endif\r
- hdmi_unregister_display_sysfs(hdmi);\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- iounmap((void*)hdmi->regbase);\r
-err1:\r
- release_mem_region(res->start,(res->end - res->start) + 1);\r
- clk_disable(hdmi->hclk);\r
-err0:\r
- hdmi_dbg(hdmi->dev, "rk30 hdmi probe error.\n");\r
- kfree(hdmi);\r
- hdmi = NULL;\r
- return ret;\r
-}\r
-\r
-static int __devexit rk30_hdmi_remove(struct platform_device *pdev)\r
-{\r
- if(hdmi) {\r
- mutex_lock(&hdmi->enable_mutex);\r
- if(!hdmi->suspend && hdmi->enable)\r
- disable_irq(hdmi->irq);\r
- mutex_unlock(&hdmi->enable_mutex);\r
- free_irq(hdmi->irq, NULL);\r
- flush_workqueue(hdmi->workqueue);\r
- destroy_workqueue(hdmi->workqueue);\r
- #ifdef CONFIG_SWITCH\r
- switch_dev_unregister(&(hdmi->switch_hdmi));\r
- #endif\r
- hdmi_unregister_display_sysfs(hdmi);\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- iounmap((void*)hdmi->regbase);\r
- release_mem_region(hdmi->regbase_phy, hdmi->regsize_phy);\r
- clk_disable(hdmi->hclk);\r
- fb_destroy_modelist(&hdmi->edid.modelist);\r
- if(hdmi->edid.audio)\r
- kfree(hdmi->edid.audio);\r
- if(hdmi->edid.specs)\r
- {\r
- if(hdmi->edid.specs->modedb)\r
- kfree(hdmi->edid.specs->modedb);\r
- kfree(hdmi->edid.specs);\r
- }\r
- kfree(hdmi);\r
- hdmi = NULL;\r
- }\r
- printk(KERN_INFO "rk30 hdmi removed.\n");\r
- return 0;\r
-}\r
-\r
-static void rk30_hdmi_shutdown(struct platform_device *pdev)\r
-{\r
- if(hdmi) {\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- }\r
- printk(KERN_INFO "rk30 hdmi shut down.\n");\r
-}\r
-\r
-static struct platform_driver rk30_hdmi_driver = {\r
- .probe = rk30_hdmi_probe,\r
- .remove = __devexit_p(rk30_hdmi_remove),\r
- .driver = {\r
- .name = "rk30-hdmi",\r
- .owner = THIS_MODULE,\r
- },\r
- .shutdown = rk30_hdmi_shutdown,\r
-};\r
-\r
-static int __init rk30_hdmi_init(void)\r
-{\r
- return platform_driver_register(&rk30_hdmi_driver);\r
-}\r
-\r
-static void __exit rk30_hdmi_exit(void)\r
-{\r
- platform_driver_unregister(&rk30_hdmi_driver);\r
-}\r
-\r
-\r
-//fs_initcall(rk30_hdmi_init);\r
-device_initcall_sync(rk30_hdmi_init);\r
-module_exit(rk30_hdmi_exit);\r
+++ /dev/null
-#ifndef __RK30_HDMI_H__
-#define __RK30_HDMI_H__
-
-#include "../../rk_hdmi.h"
-
-#if defined(CONFIG_HDMI_SOURCE_LCDC1)
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC1
-#else
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC0
-#endif
-
-extern struct hdmi* rk30_hdmi_register_hdcp_callbacks(
- void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-#endif /* __RK30_HDMI_H__ */
+++ /dev/null
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <mach/io.h>
-#include "rk30_hdmi.h"
-#include "rk30_hdmi_hw.h"
-
-static char edid_result = 0;
-
-static inline void delay100us(void)
-{
- udelay(100);
-}
-
-int rk30_hdmi_initial(void)
-{
- int rc = HDMI_ERROR_SUCESS;
-
- hdmi->pwr_mode = PWR_SAVE_MODE_A;
- hdmi->remove = rk30_hdmi_removed ;
- hdmi->control_output = rk30_hdmi_control_output;
- hdmi->config_video = rk30_hdmi_config_video;
- hdmi->config_audio = rk30_hdmi_config_audio;
- hdmi->detect_hotplug = rk30_hdmi_detect_hotplug;
- hdmi->read_edid = rk30_hdmi_read_edid;
- // internal hclk = hdmi_hclk/20
- HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
-
- if(hdmi->hdcp_power_on_cb)
- rc = hdmi->hdcp_power_on_cb();
-
- return rc;
-}
-
-static void rk30_hdmi_set_pwr_mode(int mode)
-{
- if(hdmi->pwr_mode == mode)
- return;
- hdmi_dbg(hdmi->dev, "[%s] mode %d\n", __FUNCTION__, mode);
- switch(mode)
- {
- case PWR_SAVE_MODE_A:
- HDMIWrReg(SYS_CTRL, 0x10);
- break;
- case PWR_SAVE_MODE_B:
- HDMIWrReg(SYS_CTRL, 0x20);
- break;
- case PWR_SAVE_MODE_D:
- // reset PLL A&B
- HDMIWrReg(SYS_CTRL, 0x4C);
- delay100us();
- // release PLL A reset
- HDMIWrReg(SYS_CTRL, 0x48);
- delay100us();
- // release PLL B reset
- HDMIWrReg(SYS_CTRL, 0x40);
- break;
- case PWR_SAVE_MODE_E:
- HDMIWrReg(SYS_CTRL, 0x80);
- break;
- }
- hdmi->pwr_mode = mode;
- if(mode != PWR_SAVE_MODE_A)
- msleep(10);
- hdmi_dbg(hdmi->dev, "[%s] curmode %02x\n", __FUNCTION__, HDMIRdReg(SYS_CTRL));
-}
-
-int rk30_hdmi_detect_hotplug(void)
-{
- int value = HDMIRdReg(HPD_MENS_STA);
-
- hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
- #if 0
- // When HPD and TMDS_CLK was high, HDMI is actived.
- value &= m_HOTPLUG_STATUS | m_MSEN_STATUS;
- if(value == (m_HOTPLUG_STATUS | m_MSEN_STATUS) )
- return HDMI_HPD_ACTIVED;
- else if(value)
- return HDMI_HPD_INSERT;
- else
- return HDMI_HPD_REMOVED;
- #else
- // When HPD was high, HDMI is actived.
- if(value & m_HOTPLUG_STATUS)
- return HDMI_HPD_ACTIVED;
- else if(value & m_MSEN_STATUS)
- return HDMI_HPD_INSERT;
- else
- return HDMI_HPD_REMOVED;
- #endif
-}
-
-#define HDMI_EDID_DDC_CLK 90000
-int rk30_hdmi_read_edid(int block, unsigned char *buff)
-{
- int value, ret = -1, ddc_bus_freq = 0;
- char interrupt = 0, trytime = 2;
- unsigned long flags;
-
- hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
- spin_lock_irqsave(&hdmi->irq_lock, flags);
- edid_result = 0;
- spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
- //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
- ddc_bus_freq = (30000000/HDMI_EDID_DDC_CLK)/4;
- HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
- HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-
- // Enable edid interrupt
- HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS | m_INT_EDID_ERR | m_INT_EDID_READY);
-
- while(trytime--) {
- // Config EDID block and segment addr
- HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);
- HDMIWrReg(EDID_SEGMENT_POINTER, block/2);
-
- value = 100;
- while(value--)
- {
- spin_lock_irqsave(&hdmi->irq_lock, flags);
- interrupt = edid_result;
- edid_result = 0;
- spin_unlock_irqrestore(&hdmi->irq_lock, flags);
- if(interrupt & (m_INT_EDID_ERR | m_INT_EDID_READY))
- break;
- msleep(10);
- }
- hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
- if(interrupt & m_INT_EDID_READY)
- {
- for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++)
- buff[value] = HDMIRdReg(DDC_READ_FIFO_ADDR);
- ret = 0;
-
- hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__);
-#ifdef HDMI_DEBUG
- for(value = 0; value < 128; value++) {
- printk("%02x ,", buff[value]);
- if( (value + 1) % 16 == 0)
- printk("\n");
- }
-#endif
- break;
- }
- if(interrupt & m_INT_EDID_ERR)
- hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
-
- hdmi_dbg(hdmi->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
- msleep(100);
- }
- // Disable edid interrupt
- HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
- return ret;
-}
-
-static inline void rk30_hdmi_config_phy_reg(int reg, int value)
-{
- HDMIWrReg(reg, value);
- HDMIWrReg(SYS_CTRL, 0x2C);
- delay100us();
- HDMIWrReg(SYS_CTRL, 0x20);
- msleep(1);
-}
-
-static void rk30_hdmi_config_phy(unsigned char vic)
-{
- HDMIWrReg(DEEP_COLOR_MODE, 0x22); // tmds frequency same as input dlck
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
- switch(vic)
- {
- case HDMI_1920x1080p_60Hz:
- case HDMI_1920x1080p_50Hz:
- rk30_hdmi_config_phy_reg(0x158, 0x0E);
- rk30_hdmi_config_phy_reg(0x15c, 0x00);
- rk30_hdmi_config_phy_reg(0x160, 0x60);
- rk30_hdmi_config_phy_reg(0x164, 0x00);
- rk30_hdmi_config_phy_reg(0x168, 0xDA);
- rk30_hdmi_config_phy_reg(0x16c, 0xA1);
- rk30_hdmi_config_phy_reg(0x170, 0x0e);
- rk30_hdmi_config_phy_reg(0x174, 0x22);
- rk30_hdmi_config_phy_reg(0x178, 0x00);
- break;
-
- case HDMI_1920x1080i_60Hz:
- case HDMI_1920x1080i_50Hz:
- case HDMI_1280x720p_60Hz:
- case HDMI_1280x720p_50Hz:
- rk30_hdmi_config_phy_reg(0x158, 0x06);
- rk30_hdmi_config_phy_reg(0x15c, 0x00);
- rk30_hdmi_config_phy_reg(0x160, 0x60);
- rk30_hdmi_config_phy_reg(0x164, 0x00);
- rk30_hdmi_config_phy_reg(0x168, 0xCA);
- rk30_hdmi_config_phy_reg(0x16c, 0xA3);
- rk30_hdmi_config_phy_reg(0x170, 0x0e);
- rk30_hdmi_config_phy_reg(0x174, 0x20);
- rk30_hdmi_config_phy_reg(0x178, 0x00);
- break;
-
- case HDMI_720x576p_50Hz_4_3:
- case HDMI_720x576p_50Hz_16_9:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x480p_60Hz_16_9:
- rk30_hdmi_config_phy_reg(0x158, 0x02);
- rk30_hdmi_config_phy_reg(0x15c, 0x00);
- rk30_hdmi_config_phy_reg(0x160, 0x60);
- rk30_hdmi_config_phy_reg(0x164, 0x00);
- rk30_hdmi_config_phy_reg(0x168, 0xC2);
- rk30_hdmi_config_phy_reg(0x16c, 0xA2);
- rk30_hdmi_config_phy_reg(0x170, 0x0e);
- rk30_hdmi_config_phy_reg(0x174, 0x20);
- rk30_hdmi_config_phy_reg(0x178, 0x00);
- break;
- default:
- hdmi_err(hdmi->dev, "not support such vic %d\n", vic);
- break;
- }
-}
-
-static void rk30_hdmi_config_avi(unsigned char vic, unsigned char output_color)
-{
- int i, clolorimetry, aspect_ratio;
- char info[SIZE_AVI_INFOFRAME];
-
- memset(info, 0, SIZE_AVI_INFOFRAME);
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
- info[0] = 0x82;
- info[1] = 0x02;
- info[2] = 0x0D;
- info[3] = info[0] + info[1] + info[2];
-
- if(output_color == VIDEO_OUTPUT_YCBCR444)
- info[4] = (AVI_COLOR_MODE_YCBCR444 << 5);
- else if(output_color == VIDEO_OUTPUT_YCBCR422)
- info[4] = (AVI_COLOR_MODE_YCBCR422 << 5);
- else
- info[4] = (AVI_COLOR_MODE_RGB << 5);
- info[4] |= (1 << 4); //Enable active format data bits is present in info[2]
-
- switch(vic)
- {
- case HDMI_720x480i_60Hz_4_3:
- case HDMI_720x576i_50Hz_4_3:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x576p_50Hz_4_3:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
- clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
- break;
- case HDMI_720x480i_60Hz_16_9:
- case HDMI_720x576i_50Hz_16_9:
- case HDMI_720x480p_60Hz_16_9:
- case HDMI_720x576p_50Hz_16_9:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
- clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
- break;
- default:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
- clolorimetry = AVI_COLORIMETRY_ITU709;
- }
-
- if(output_color == VIDEO_OUTPUT_RGB444)
- clolorimetry = AVI_COLORIMETRY_NO_DATA;
-
- info[5] = (clolorimetry << 6) | (aspect_ratio << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
- info[6] = 0;
- info[7] = vic;
- info[8] = 0;
-
- // Calculate AVI InfoFrame ChecKsum
- for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
- {
- info[3] += info[i];
- }
- info[3] = 0x100 - info[3];
-
- for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
- HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
-}
-
-static char coeff_csc[][24] = {
- //G B R Bias
- { //CSC_RGB_0_255_TO_ITU601_16_235
- 0x11, 0xb6, 0x02, 0x0b, 0x10, 0x55, 0x00, 0x80, //Cr
- 0x02, 0x59, 0x01, 0x32, 0x00, 0x75, 0x00, 0x10, //Y
- 0x11, 0x5b, 0x10, 0xb0, 0x02, 0x0b, 0x00, 0x80, //Cb
- },
- { //CSC_RGB_0_255_TO_ITU709_16_235
- 0x11, 0xdb, 0x02, 0x0b, 0x10, 0x30, 0x00, 0x80, //Cr
- 0x02, 0xdc, 0x00, 0xda, 0x00, 0x4a, 0x00, 0x10, //Y
- 0x11, 0x93, 0x10, 0x78, 0x02, 0x0b, 0x00, 0x80, //Cb
- },
- //Y Cr Cb Bias
- { //CSC_ITU601_16_235_TO_RGB_16_235
- 0x04, 0x00, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xaf, //R
- 0x04, 0x00, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x84, //G
- 0x04, 0x00, 0x00, 0x00, 0x06, 0xee, 0x02, 0xde, //B
- },
- { //CSC_ITU709_16_235_TO_RGB_16_235
- 0x04, 0x00, 0x06, 0x29, 0x00, 0x00, 0x02, 0xc5, //R
- 0x04, 0x00, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x52, //G
- 0x04, 0x00, 0x00, 0x00, 0x07, 0x44, 0x02, 0xe8, //B
- },
- { //CSC_ITU601_16_235_TO_RGB_0_255
- 0x04, 0xa8, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xc2, //R
- 0x04, 0xa8, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x72, //G
- 0x04, 0xa8, 0x00, 0x00, 0x06, 0xee, 0x02, 0xf0, //B
- },
- { //CSC_ITU709_16_235_TO_RGB_0_255
- 0x04, 0xa8, 0x06, 0x29, 0x00, 0x00, 0x02, 0xd8, //R
- 0x04, 0xa8, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x40, //G
- 0x04, 0xa8, 0x00, 0x00, 0x07, 0x44, 0x02, 0xfb, //B
- },
-
-};
-
-static void rk30_hdmi_config_csc(struct hdmi_video_para *vpara)
-{
- int i, mode;
- char *coeff = NULL;
-
- if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) ||
- ((vpara->input_color != VIDEO_INPUT_COLOR_RGB) && (vpara->output_color != VIDEO_OUTPUT_RGB444) ))
- {
- return;
- }
- switch(vpara->vic)
- {
- case HDMI_720x480i_60Hz_4_3:
- case HDMI_720x576i_50Hz_4_3:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x576p_50Hz_4_3:
- case HDMI_720x480i_60Hz_16_9:
- case HDMI_720x576i_50Hz_16_9:
- case HDMI_720x480p_60Hz_16_9:
- case HDMI_720x576p_50Hz_16_9:
- if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
- mode = CSC_RGB_0_255_TO_ITU601_16_235;
- else if(vpara->output_mode == OUTPUT_HDMI)
- mode = CSC_ITU601_16_235_TO_RGB_16_235;
- else
- mode = CSC_ITU601_16_235_TO_RGB_0_255;
- break;
- default:
- if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
- mode = CSC_RGB_0_255_TO_ITU709_16_235;
- else if(vpara->output_mode == OUTPUT_HDMI)
- mode = CSC_ITU709_16_235_TO_RGB_16_235;
- else
- mode = CSC_ITU709_16_235_TO_RGB_0_255;
- break;
- }
-
- coeff = coeff_csc[mode];
-
- HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_MANUAL) | v_CSC_BRSWAP_DIABLE(1));
-
- for(i = 0; i < 24; i++)
- HDMIWrReg(CSC_PARA_C0_H + i*4, coeff[i]);
-
- HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(1));
-}
-
-int rk30_hdmi_config_video(struct hdmi_video_para *vpara)
-{
- int value;
- struct fb_videomode *mode;
-
- hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
- if(vpara == NULL) {
- hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
- return -1;
- }
- if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
- if(hdmi->pwr_mode == PWR_SAVE_MODE_D || hdmi->pwr_mode == PWR_SAVE_MODE_A)
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
-
- if(hdmi->hdcp_power_off_cb)
- hdmi->hdcp_power_off_cb();
-
- // Input video mode is RGB24bit, Data enable signal from external
- HDMIMskReg(value, AV_CTRL1, m_INPUT_VIDEO_MODE | m_DE_SIGNAL_SELECT, \
- v_INPUT_VIDEO_MODE(vpara->input_mode) | EXTERNAL_DE)
- HDMIMskReg(value, VIDEO_CTRL1, m_VIDEO_OUTPUT_MODE | m_VIDEO_INPUT_DEPTH | m_VIDEO_INPUT_COLOR_MODE, \
- v_VIDEO_OUTPUT_MODE(vpara->output_color) | v_VIDEO_INPUT_DEPTH(VIDEO_INPUT_DEPTH_8BIT) | vpara->input_color)
- HDMIWrReg(DEEP_COLOR_MODE, 0x20);
- // color space convert
- rk30_hdmi_config_csc(vpara);
- // Set HDMI Mode
- HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
-
- // Set ext video
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if(mode == NULL)
- {
- hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
- return -ENOENT;
- }
- hdmi->tmdsclk = mode->pixclock;
-
- if( (vpara->vic == HDMI_720x480p_60Hz_4_3) || (vpara->vic == HDMI_720x480p_60Hz_16_9) )
- value = v_VSYNC_OFFSET(6);
- else
- value = v_VSYNC_OFFSET(0);
- value |= v_EXT_VIDEO_ENABLE(1) | v_INTERLACE(mode->vmode);
- if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
- value |= v_HSYNC_POLARITY(1);
- if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
- value |= v_VSYNC_POLARITY(1);
- HDMIWrReg(EXT_VIDEO_PARA, value);
- value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_L, value & 0xFF);
- HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->right_margin + mode->hsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_HBLANK_L, value & 0xFF);
- HDMIWrReg(EXT_VIDEO_PARA_HBLANK_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->hsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_HDELAY_L, value & 0xFF);
- HDMIWrReg(EXT_VIDEO_PARA_HDELAY_H, (value >> 8) & 0xFF);
-
- value = mode->hsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_L, value & 0xFF);
- HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_L, value & 0xFF);
- HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
- HDMIWrReg(EXT_VIDEO_PARA_VBLANK_L, value & 0xFF);
-
- if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
- value = 42;
- else
- value = mode->upper_margin + mode->vsync_len;
-
- HDMIWrReg(EXT_VIDEO_PARA_VDELAY, value & 0xFF);
-
- value = mode->vsync_len;
- HDMIWrReg(EXT_VIDEO_PARA_VSYNCWIDTH, value & 0xFF);
-
- if(vpara->output_mode == OUTPUT_HDMI) {
- rk30_hdmi_config_avi(vpara->vic, vpara->output_color);
- hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
- }
- else {
- hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__);
- }
-
- rk30_hdmi_config_phy(vpara->vic);
- rk30_hdmi_control_output(0);
- return 0;
-}
-
-static void rk30_hdmi_config_aai(void)
-{
- int i;
- char info[SIZE_AUDIO_INFOFRAME];
-
- memset(info, 0, SIZE_AUDIO_INFOFRAME);
-
- info[0] = 0x84;
- info[1] = 0x01;
- info[2] = 0x0A;
-
- info[3] = info[0] + info[1] + info[2];
- for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
- for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
- HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
-}
-
-int rk30_hdmi_config_audio(struct hdmi_audio *audio)
-{
- int value, rate, N;
- char word_length, channel;
-
- if(audio->channel < 3)
- channel = I2S_CHANNEL_1_2;
- else if(audio->channel < 5)
- channel = I2S_CHANNEL_3_4;
- else if(audio->channel < 7)
- channel = I2S_CHANNEL_5_6;
- else
- channel = I2S_CHANNEL_7_8;
-
- switch(audio->rate)
- {
- case HDMI_AUDIO_FS_32000:
- rate = AUDIO_32K;
- N = N_32K;
- break;
- case HDMI_AUDIO_FS_44100:
- rate = AUDIO_441K;
- N = N_441K;
- break;
- case HDMI_AUDIO_FS_48000:
- rate = AUDIO_48K;
- N = N_48K;
- break;
- case HDMI_AUDIO_FS_88200:
- rate = AUDIO_882K;
- N = N_882K;
- break;
- case HDMI_AUDIO_FS_96000:
- rate = AUDIO_96K;
- N = N_96K;
- break;
- case HDMI_AUDIO_FS_176400:
- rate = AUDIO_1764K;
- N = N_1764K;
- break;
- case HDMI_AUDIO_FS_192000:
- rate = AUDIO_192K;
- N = N_192K;
- break;
- default:
- hdmi_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
- return -ENOENT;
- }
-// switch(audio->word_length)
-// {
-// case HDMI_AUDIO_WORD_LENGTH_16bit:
-// word_length = 0x02;
-// break;
-// case HDMI_AUDIO_WORD_LENGTH_20bit:
-// word_length = 0x0a;
-// break;
-// case HDMI_AUDIO_WORD_LENGTH_24bit:
-// word_length = 0x0b;
-// break;
-// default:
-// hdmi_err(hdmi->dev, "[%s] not support such word length %d\n", __FUNCTION__, audio->word_length);
-// return -ENOENT;
-// }
- //set_audio_if I2S
- HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK
- HDMIWrReg(AUDIO_CTRL2, 0x40);
- HDMIWrReg(I2S_AUDIO_CTRL, v_I2S_MODE(I2S_MODE_STANDARD) | v_I2S_CHANNEL(channel) );
- HDMIWrReg(I2S_INPUT_SWAP, 0x00); //no swap
- HDMIMskReg(value, AV_CTRL1, m_AUDIO_SAMPLE_RATE, v_AUDIO_SAMPLE_RATE(rate))
-// HDMIWrReg(SRC_NUM_AUDIO_LEN, word_length);
-
- //Set N value 6144, fs=48kHz
- HDMIWrReg(N_1, N & 0xFF);
- HDMIWrReg(N_2, (N >> 8) & 0xFF);
- HDMIWrReg(LR_SWAP_N3, (N >> 16) & 0x0F);
-
- rk30_hdmi_config_aai();
- return 0;
-}
-
-static void rk30_hdmi_audio_reset(void)
-{
- int value;
-
- HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, AUDIO_CAPTURE_RESET)
- msleep(1);
- HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, 0)
-}
-
-void rk30_hdmi_control_output(int enable)
-{
- hdmi_dbg(hdmi->dev, "[%s] %d\n", __FUNCTION__, enable);
- if(enable == 0) {
- HDMIWrReg(VIDEO_SETTING2, 0x03);
- }
- else {
- if(hdmi->pwr_mode == PWR_SAVE_MODE_B) {
- // Switch to power save mode_d
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
- }
- if(hdmi->pwr_mode == PWR_SAVE_MODE_D) {
- // Switch to power save mode_e
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_E);
- }
- HDMIWrReg(VIDEO_SETTING2, 0x00);
- rk30_hdmi_audio_reset();
- }
-}
-
-int rk30_hdmi_removed(void)
-{
- if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
- {
- HDMIWrReg(VIDEO_SETTING2, 0x00);
- rk30_hdmi_audio_reset();
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
- }
- if(hdmi->pwr_mode == PWR_SAVE_MODE_D)
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
- if(hdmi->pwr_mode == PWR_SAVE_MODE_B && hdmi->state == HDMI_SLEEP)
- {
- HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
- HDMIWrReg(INTR_MASK2, 0);
- HDMIWrReg(INTR_MASK3, 0);
- HDMIWrReg(INTR_MASK4, 0);
- // Disable color space convertion
- HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(0));
- HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_AUTO) | v_CSC_BRSWAP_DIABLE(1));
- if(hdmi->hdcp_power_off_cb)
- hdmi->hdcp_power_off_cb();
- rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_A);
- }
- dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
- return HDMI_ERROR_SUCESS;
-}
-
-
-irqreturn_t hdmi_irq(int irq, void *priv)
-{
- char interrupt1 = 0, interrupt2 = 0, interrupt3 = 0, interrupt4 = 0;
-
- if(hdmi->pwr_mode == PWR_SAVE_MODE_A)
- {
- HDMIWrReg(SYS_CTRL, 0x20);
- hdmi->pwr_mode = PWR_SAVE_MODE_B;
-
- hdmi_dbg(hdmi->dev, "hdmi irq wake up\n");
- // HDMI was inserted when system is sleeping, irq was triggered only once
- // when wake up. So we need to check hotplug status.
- if(HDMIRdReg(HPD_MENS_STA) & (m_HOTPLUG_STATUS | m_MSEN_STATUS)) {
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
- }
- }
- else
- {
- interrupt1 = HDMIRdReg(INTR_STATUS1);
- interrupt2 = HDMIRdReg(INTR_STATUS2);
- interrupt3 = HDMIRdReg(INTR_STATUS3);
- interrupt4 = HDMIRdReg(INTR_STATUS4);
- HDMIWrReg(INTR_STATUS1, interrupt1);
-// HDMIWrReg(INTR_STATUS2, interrupt2);
-// HDMIWrReg(INTR_STATUS3, interrupt3);
-// HDMIWrReg(INTR_STATUS4, interrupt4);
-#if 0
- hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x interrupt2 %02x interrupt3 %02x interrupt4 %02x\n",\
- __FUNCTION__, interrupt1, interrupt2, interrupt3, interrupt4);
-#endif
- if(interrupt1 & (m_INT_HOTPLUG | m_INT_MSENS))
- {
- if(hdmi->state == HDMI_SLEEP)
- hdmi->state = WAIT_HOTPLUG;
- interrupt1 &= ~(m_INT_HOTPLUG | m_INT_MSENS);
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
- }
- else if(interrupt1 & (m_INT_EDID_READY | m_INT_EDID_ERR)) {
- spin_lock(&hdmi->irq_lock);
- edid_result = interrupt1;
- spin_unlock(&hdmi->irq_lock);
- }
-// else if(hdmi->state == HDMI_SLEEP) {
-// RK30DBG( "hdmi return to sleep mode\n");
-// HDMIWrReg(SYS_CTRL, 0x10);
-// rk30_hdmi->pwr_mode = PWR_SAVE_MODE_A;
-// }
- if(hdmi->hdcp_irq_cb)
- hdmi->hdcp_irq_cb(interrupt2);
- }
- return IRQ_HANDLED;
-}
-
+++ /dev/null
-#ifndef __RK30_HDMI_HW_H__
-#define __RK30_HDMI_HW_H__
-
-/* HDMI_SYS_CONTROL */
-#define SYS_CTRL 0x0
-
-enum {
- PWR_SAVE_MODE_A = 1,
- PWR_SAVE_MODE_B = 2,
- PWR_SAVE_MODE_D = 4,
- PWR_SAVE_MODE_E = 8
-};
-#define m_PWR_SAVE_MODE 0xF0
-#define v_PWR_SAVE_MODE(n) (n << 4)
-#define PLL_B_RESET (1 << 3)
-
-#define N_32K 0x1000
-#define N_441K 0x1880
-#define N_882K 0x3100
-#define N_1764K 0x6200
-#define N_48K 0x1800
-#define N_96K 0x3000
-#define N_192K 0x6000
-
-#define LR_SWAP_N3 0x04
-#define N_2 0x08
-#define N_1 0x0c
-
-#define AUDIO_CTRL1 0x28
-#define AUDIO_CTRL2 0x2c
-#define I2S_AUDIO_CTRL 0x30
-enum {
- I2S_MODE_STANDARD = 0,
- I2S_MODE_RIGHT_JUSTIFIED,
- I2S_MODE_LEFT_JUSTIFIED
-};
-#define v_I2S_MODE(n) n
-enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
-};
-#define v_I2S_CHANNEL(n) ( (n) << 2 )
-
-#define I2S_INPUT_SWAP 0x40
-
-#define SRC_NUM_AUDIO_LEN 0x50
-
-/* HDMI_AV_CTRL1*/
-#define AV_CTRL1 0x54
-enum {
- AUDIO_32K = 0x3,
- AUDIO_441K = 0x0,
- AUDIO_48K = 0x2,
- AUDIO_882K = 0x8,
- AUDIO_96K = 0xa,
- AUDIO_1764K = 0xc,
- AUDIO_192K = 0xe,
-};
-#define m_AUDIO_SAMPLE_RATE 0xF0
-#define v_AUDIO_SAMPLE_RATE(n) (n << 4)
-#define m_INPUT_VIDEO_MODE (7 << 1)
-#define v_INPUT_VIDEO_MODE(n) (n << 1)
-enum {
- INTERNAL_DE = 0,
- EXTERNAL_DE
-};
-#define m_DE_SIGNAL_SELECT (1 << 0)
-
-/* HDMI_AV_CTRL2 */
-#define AV_CTRL2 0xec
-#define m_CSC_ENABLE (1 << 0)
-#define v_CSC_ENABLE(n) (n)
-
-/* HDMI_VIDEO_CTRL1 */
-#define VIDEO_CTRL1 0x58
-
-#define m_VIDEO_OUTPUT_MODE (0x3 << 6)
-#define v_VIDEO_OUTPUT_MODE(n) (n << 6)
-enum {
- VIDEO_INPUT_DEPTH_12BIT = 0,
- VIDEO_INPUT_DEPTH_10BIT = 0x1,
- VIDEO_INPUT_DEPTH_8BIT = 0x3
-};
-#define m_VIDEO_INPUT_DEPTH (3 << 4)
-#define v_VIDEO_INPUT_DEPTH(n) (n << 4)
-enum {
- VIDEO_EMBEDDED_SYNC_LOCATION_0 = 0,
- VIDEO_EMBEDDED_SYNC_LOCATION_1,
- VIDEO_EMBEDDED_SYNC_LOCATION_2
-};
-#define m_VIDEO_EMBEDDED_SYNC_LOCATION (3 << 2)
-#define VIDEO_EMBEDDED_SYNC_LOCATION(n) (n << 2)
-#define m_VIDEO_INPUT_COLOR_MODE (1 << 0)
-
-/* DEEP_COLOR_MODE */
-#define DEEP_COLOR_MODE 0x5c
-enum{
- TMDS_CLOCK_MODE_8BIT = 0,
- TMDS_CLOKK_MODE_10BIT,
- TMDS_CLOKK_MODE_12BIT
-};
-#define TMDS_CLOCK_MODE_MASK 0x3 << 6
-#define TMDS_CLOCK_MODE(n) (n) << 6
-
-/* VIDEO_CTRL2 */
-#define VIDEO_SETTING2 0x114
-#define m_UNMUTE (1 << 7)
-#define m_MUTE (1 << 6)
-#define m_AUDIO_RESET (1 << 2)
-#define m_NOT_SEND_AUDIO (1 << 1)
-#define m_NOT_SEND_VIDEO (1 << 0)
-#define AV_UNMUTE (1 << 7) // Unmute video and audio, send normal video and audio data
-#define AV_MUTE (1 << 6) // Mute video and audio, send black video data and silent audio data
-#define AUDIO_CAPTURE_RESET (1 << 2) // Reset audio process logic, only available in pwr_e mode.
-#define NOT_SEND_AUDIO (1 << 1) // Send silent audio data
-#define NOT_SEND_VIDEO (1 << 0) // Send black video data
-
-/* Color Space Convertion Parameter*/
-#define CSC_PARA_C0_H 0x60
-#define CSC_PARA_C0_L 0x64
-#define CSC_PARA_C1_H 0x68
-#define CSC_PARA_C1_L 0x6c
-#define CSC_PARA_C2_H 0x70
-#define CSC_PARA_C2_L 0x74
-#define CSC_PARA_C3_H 0x78
-#define CSC_PARA_C3_L 0x7c
-#define CSC_PARA_C4_H 0x80
-#define CSC_PARA_C4_L 0x84
-#define CSC_PARA_C5_H 0x88
-#define CSC_PARA_C5_L 0x8c
-#define CSC_PARA_C6_H 0x90
-#define CSC_PARA_C6_L 0x94
-#define CSC_PARA_C7_H 0x98
-#define CSC_PARA_C7_L 0x9c
-#define CSC_PARA_C8_H 0xa0
-#define CSC_PARA_C8_L 0xa4
-#define CSC_PARA_C9_H 0xa8
-#define CSC_PARA_C9_L 0xac
-#define CSC_PARA_C10_H 0xac
-#define CSC_PARA_C10_L 0xb4
-#define CSC_PARA_C11_H 0xb8
-#define CSC_PARA_C11_L 0xbc
-
-#define CSC_CONFIG1 0x34c
-#define m_CSC_MODE (1 << 7)
-#define m_CSC_COEF_MODE (0xF << 3) //Only used in auto csc mode
-#define m_CSC_STATUS (1 << 2)
-#define m_CSC_VID_SELECT (1 << 1)
-#define m_CSC_BRSWAP_DIABLE (1)
-
-enum {
- CSC_MODE_MANUAL = 0,
- CSC_MODE_AUTO
-};
-#define v_CSC_MODE(n) (n << 7)
-enum {
- COE_SDTV_LIMITED_RANGE = 0x08,
- COE_SDTV_FULL_RANGE = 0x04,
- COE_HDTV_60Hz = 0x2,
- COE_HDTV_50Hz = 0x1
-};
-#define v_CSC_COE_MODE(n) (n << 3)
-enum {
- CSC_INPUT_VID_5_19 = 0,
- CSC_INPUT_VID_28_29
-};
-#define v_CSC_VID_SELECT(n) (n << 1)
-#define v_CSC_BRSWAP_DIABLE(n) (n)
-
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX 0x17c
-enum {
- INFOFRAME_AVI = 0x06,
- INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_HB0 0x180
-#define CONTROL_PACKET_HB1 0x184
-#define CONTROL_PACKET_HB2 0x188
-#define CONTROL_PACKET_PB_ADDR 0x18c
-#define SIZE_AVI_INFOFRAME 0x11 // 17 bytes
-#define SIZE_AUDIO_INFOFRAME 0x0F // 15 bytes
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-
-/* External Video Parameter Setting*/
-#define EXT_VIDEO_PARA 0xC0
-#define m_VSYNC_OFFSET (0xF << 4)
-#define m_VSYNC_POLARITY (1 << 3)
-#define m_HSYNC_POLARITY (1 << 2)
-#define m_INTERLACE (1 << 1)
-#define m_EXT_VIDEO_ENABLE (1 << 0)
-
-#define v_VSYNC_OFFSET(n) (n << 4)
-#define v_VSYNC_POLARITY(n) (n << 3)
-#define v_HSYNC_POLARITY(n) (n << 2)
-#define v_INTERLACE(n) (n << 1)
-#define v_EXT_VIDEO_ENABLE(n) (n << 0)
-
-#define EXT_VIDEO_PARA_HTOTAL_L 0xC4
-#define EXT_VIDEO_PARA_HTOTAL_H 0xC8
-#define EXT_VIDEO_PARA_HBLANK_L 0xCC
-#define EXT_VIDEO_PARA_HBLANK_H 0xD0
-#define EXT_VIDEO_PARA_HDELAY_L 0xD4
-#define EXT_VIDEO_PARA_HDELAY_H 0xD8
-#define EXT_VIDEO_PARA_HSYNCWIDTH_L 0xDC
-#define EXT_VIDEO_PARA_HSYNCWIDTH_H 0xE0
-
-#define EXT_VIDEO_PARA_VTOTAL_L 0xE4
-#define EXT_VIDEO_PARA_VTOTAL_H 0xE8
-#define EXT_VIDEO_PARA_VBLANK_L 0xF4
-#define EXT_VIDEO_PARA_VDELAY 0xF8
-#define EXT_VIDEO_PARA_VSYNCWIDTH 0xFC
-
-#define PHY_PLL_SPEED 0x158
- #define v_TEST_EN(n) (n << 6)
- #define v_PLLA_BYPASS(n) (n << 4)
- #define v_PLLB_SPEED(n) (n << 2)
- #define v_PLLA_SPEED(n) (n)
- enum {
- PLL_SPEED_LOWEST = 0,
- PLL_SPEED_MIDLOW,
- PLL_SPEED_MIDHIGH,
- PLL_SPEED_HIGHEST
- };
-
-#define PHY_PLL_17 0x15c // PLL A & B config bit 17
- #define v_PLLA_BIT17(n) (n << 2)
- #define v_PLLB_BIT17(n) (n << 1)
-
-#define PHY_BGR 0x160
- #define v_BGR_DISCONNECT(n) (n << 7)
- #define v_BGR_V_OFFSET(n) (n << 4)
- #define v_BGR_I_OFFSET(n) (n)
-
-#define PHY_PLLA_1 0x164
-#define PHY_PLLA_2 0x168
-#define PHY_PLLB_1 0x16c
-#define PHY_PLLB_2 0x170
-
-#define PHY_DRIVER_PREEMPHASIS 0x174
- #define v_TMDS_SWING(n) (n << 4)
- #define v_PRE_EMPHASIS(n) (n)
-
-#define PHY_PLL_16_AML 0x178 // PLL A & B config bit 16 and AML control
- #define v_PLLA_BIT16(n) (n << 5)
- #define v_PLLB_BIT16(n) (n << 4)
- #define v_AML(n) (n)
-
-/* Interrupt Setting */
-#define INTR_MASK1 0x248
-#define INTR_STATUS1 0x250
- #define m_INT_HOTPLUG (1 << 7)
- #define m_INT_MSENS (1 << 6)
- #define m_INT_VSYNC (1 << 5)
- #define m_INT_AUDIO_FIFO_FULL (1 << 4)
- #define m_INT_EDID_READY (1 << 2)
- #define m_INT_EDID_ERR (1 << 1)
-#define INTR_MASK2 0x24c
-#define INTR_STATUS2 0x254
- #define m_INT_HDCP_ERR (1 << 7) // HDCP error detected
- #define m_INT_BKSV_RPRDY (1 << 6) // BKSV list ready from repeater
- #define m_INT_BKSV_RCRDY (1 << 5) // BKSV list ready from receiver
- #define m_INT_AUTH_DONE (1 << 4) // HDCP authentication done
- #define m_INT_AUTH_READY (1 << 3) // HDCP authentication ready
-#define INTR_MASK3 0x258
-#define INTR_STATUS3 0x260
-
-#define INTR_MASK4 0x25c
-#define INTR_STATUS4 0x264
-
-#define DDC_READ_FIFO_ADDR 0x200
-#define DDC_BUS_FREQ_L 0x204
-#define DDC_BUS_FREQ_H 0x208
-#define DDC_BUS_CTRL 0x2dc
-#define DDC_I2C_LEN 0x278
-#define DDC_I2C_OFFSET 0x280
-#define DDC_I2C_CTRL 0x284
-#define DDC_I2C_READ_BUF0 0x288
-#define DDC_I2C_READ_BUF1 0x28c
-#define DDC_I2C_READ_BUF2 0x290
-#define DDC_I2C_READ_BUF3 0x294
-#define DDC_I2C_WRITE_BUF0 0x298
-#define DDC_I2C_WRITE_BUF1 0x29c
-#define DDC_I2C_WRITE_BUF2 0x2a0
-#define DDC_I2C_WRITE_BUF3 0x2a4
-#define DDC_I2C_WRITE_BUF4 0x2ac
-#define DDC_I2C_WRITE_BUF5 0x2b0
-#define DDC_I2C_WRITE_BUF6 0x2b4
-
-#define EDID_SEGMENT_POINTER 0x310
-#define EDID_WORD_ADDR 0x314
-#define EDID_FIFO_ADDR 0x318
-
-#define HPD_MENS_STA 0x37c
-#define m_HOTPLUG_STATUS (1 << 7)
-#define m_MSEN_STATUS (1 << 6)
-
-/* HDCP_CTRL */
-#define HDCP_CTRL 0x2bc
- enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
- };
- #define m_HDCP_AUTH_START (1 << 7) // start hdcp
- #define m_HDCP_BKSV_PASS (1 << 6) // bksv valid
- #define m_HDCP_BKSV_FAILED (1 << 5) // bksv invalid
- #define m_HDCP_FRAMED_ENCRYPED (1 << 4)
- #define m_HDCP_AUTH_STOP (1 << 3) // stop hdcp
- #define m_HDCP_ADV_CIPHER (1 << 2) // advanced cipher mode
- #define m_HDMI_DVI (1 << 1)
- #define m_HDCP_RESET (1 << 0) // reset hdcp
- #define v_HDCP_AUTH_START(n) (n << 7)
- #define v_HDCP_BKSV_PASS(n) (n << 6)
- #define v_HDCP_BKSV_FAILED(n) (n << 5)
- #define v_HDCP_FRAMED_ENCRYPED(n) (n << 4)
- #define v_HDCP_AUTH_STOP(n) (n << 3)
- #define v_HDCP_ADV_CIPHER(n) (n << 2)
- #define v_HDMI_DVI(n) (n << 1)
- #define v_HDCP_RESET(n) (n << 0)
-#define HDCP_CTRL2 0x340
-
-/* HDCP Key Memory Access Control */
-#define HDCP_KEY_ACCESS_CTRL1 0x338
-#define HDCP_KEY_ACCESS_CTRL2 0x33c
- #define m_LOAD_FACSIMILE_HDCP_KEY (1 << 1)
- #define m_LOAD_HDCP_KEY (1 << 0)
-/* HDCP Key Memory Control */
-#define HDCP_KEY_MEM_CTRL 0x348
- #define m_USE_KEY1 (1 << 6)
- #define m_USE_KEY2 (1 << 5)
- #define m_LOAD_AKSV (1 << 4)
- #define m_KSV_SELECTED (1 << 3)
- #define m_KSV_VALID (1 << 2)
- #define m_KEY_VALID (1 << 1)
- #define m_KEY_READY (1 << 0)
- #define v_USE_KEY1(n) (n << 6)
- #define v_USE_KEY2(n) (n << 5)
- #define v_LOAD_AKSV(n) (n << 4)
-
-/* HDCP B device capacity */
-#define HDCP_BCAPS 0x2f8
- #define m_HDMI_RECEIVED (1 << 7) //If HDCP receiver support HDMI, this bit must be 1.
- #define m_REPEATER (1 << 6)
- #define m_KSV_FIFO_READY (1 << 5)
- #define m_DDC_FAST (1 << 4)
- #define m_1_1_FEATURE (1 << 1)
- #define m_FAST_REAUTHENTICATION (1 << 0) //For HDMI, this function is supported whether this bit is enabled or not.
-
-/* HDCP KSV Value */
-#define HDCP_KSV_BYTE0 0x2fc
-#define HDCP_KSV_BYTE1 0x300
-#define HDCP_KSV_BYTE2 0x304
-#define HDCP_KSV_BYTE3 0x308
-#define HDCP_KSV_BYTE4 0x30c
-
-/* HDCP error status */
-#define HDCP_ERROR 0x320
-
-/* HDCP 100 ms timer */
-#define HDCP_TIMER_100MS 0x324
-/* HDCP 5s timer */
-#define HDCP_TIMER_5S 0x328
-
-/* HDCP Key ram address */
-#define HDCP_RAM_KEY_KSV1 0x400
-#define HDCP_RAM_KEY_KSV2 0x407
-#define HDCP_RAM_KEY_PRIVATE 0x40e
-#define HDCP_KEY_LENGTH 0x13C
-
-
-#define HDCP_ENABLE_HW_AUTH // Enable hardware authentication mode
-#define HDMI_INTERANL_CLK_DIV 0x19
-
-#define HDMIRdReg(addr) __raw_readl(hdmi->regbase + addr)
-#define HDMIWrReg(addr, val) __raw_writel((val), hdmi->regbase + addr);
-#define HDMIMskReg(temp, addr, msk, val) \
- temp = __raw_readl(hdmi->regbase + addr) & (0xFF - (msk)) ; \
- __raw_writel(temp | ( (val) & (msk) ), hdmi->regbase + addr);
-
-
-
-/* Color Space Convertion Mode */
-enum {
- CSC_RGB_0_255_TO_ITU601_16_235 = 0, //RGB 0-255 input to YCbCr 16-235 output according BT601
- CSC_RGB_0_255_TO_ITU709_16_235, //RGB 0-255 input to YCbCr 16-235 output accroding BT709
- CSC_ITU601_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT601
- CSC_ITU709_16_235_TO_RGB_16_235, //YCbCr 16-235 input to RGB 16-235 output according BT709
- CSC_ITU601_16_235_TO_RGB_0_255, //YCbCr 16-235 input to RGB 0-255 output according BT601
- CSC_ITU709_16_235_TO_RGB_0_255 //YCbCr 16-235 input to RGB 0-255 output according BT709
-};
-
-extern int rk30_hdmi_initial(void);
-extern int rk30_hdmi_detect_hotplug(void);
-extern int rk30_hdmi_read_edid(int block, unsigned char *buff);
-extern int rk30_hdmi_removed(void);
-extern int rk30_hdmi_config_video(struct hdmi_video_para *vpara);
-extern int rk30_hdmi_config_audio(struct hdmi_audio *audio);
-extern void rk30_hdmi_control_output(int enable);
-
-#endif
+++ /dev/null
-config HDCP_RK3036
- bool "RK3036 HDCP support"
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-config HDCP_RK3036_DEBUG
- bool "RK3036 HDCP Debugging"
- depends on HDCP_RK3036
- default n
- help
- Enableds verbose debugging the the HDCP drivers
-
-config CEC_RK3036
- bool "RK3036 CEC support"
- default n
- help
- CEC Interface. This adds the HDMI CEC Interface.
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-ccflags-$(CONFIG_HDCP_RK616_DEBUG) = -DHDCP_DEBUG
-
-obj-$(CONFIG_HDMI_RK3036) += rk3036_hdmi_hw.o rk3036_hdmi.o
-obj-$(CONFIG_HDCP_RK3036) += rk3036_hdmi_hdcp.o rk3036_hdcp.o
-obj-$(CONFIG_CEC_RK3036) += rk3036_hdmi_cec.o
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/miscdevice.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include "rk3036_hdmi.h"
-#include "rk3036_hdcp.h"
-
-struct hdcp *hdcp = NULL;
-
-static void hdcp_work_queue(struct work_struct *work);
-
-#define AUTH_TIMEOUT (2*HZ)
-static struct timer_list auth_timer;
-static int timer_state;
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_submit_work
- *-----------------------------------------------------------------------------
- */
-static struct delayed_work *hdcp_submit_work(int event, int delay)
-{
- struct hdcp_delayed_work *work;
-
- DBG("%s event %04x delay %d\n", __func__, event, delay);
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
- work->event = event;
- queue_delayed_work(hdcp->workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- HDCP_WARN("HDCP:Cannot allocate memory to create work\n");
- return 0;
- }
-
- return &work->work;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_cancel_work
- *-----------------------------------------------------------------------------
- */
-static void hdcp_cancel_work(struct delayed_work **work)
-{
- int ret = 0;
-
- if (*work) {
- ret = cancel_delayed_work(*work);
- if (ret != 1) {
- ret = cancel_work_sync(&((*work)->work));
- HDCP_WARN("Canceling sync work failed %d\n", ret);
- }
- kfree(*work);
- *work = 0;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: auth_timer_func
- *-----------------------------------------------------------------------------
- */
-static void auth_timer_func(unsigned long data)
-{
- HDCP_WARN("hdcp auth 2 second timeout\n");
- if (hdcp->auth_state == 0) {
- mod_timer(&auth_timer, jiffies + AUTH_TIMEOUT);
- if ((hdcp->hdcp_state != HDCP_DISABLED) &&
- (hdcp->hdcp_state != HDCP_ENABLE_PENDING)) {
- if (is_1b_03_test())
- return;
- hdcp_submit_work(HDCP_FAIL_EVENT, 0);
- }
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_failure
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_failure(void)
-{
- if (hdcp->hdmi_state == HDMI_STOPPED)
- return;
-
- rk3036_hdcp_disable();
-/*
- rk3036_hdmi_control_output(false);
- */
- rk3036_set_colorbar(1);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
- if (hdcp->retry_cnt <= HDCP_INFINITE_REAUTH) {
- hdcp->retry_cnt--;
- HDCP_WARN("authentication failed attempts=%d\n",
- hdcp->retry_cnt);
- } else
- HDCP_WARN("authentication failed retrying\n");
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- if (hdcp->auth_state == 1 && timer_state == 0) {
- DBG("add auth timer\n");
- hdcp->auth_state = 0;
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- auth_timer.expires = jiffies + AUTH_TIMEOUT;
- add_timer(&auth_timer);
- timer_state = 1;
- }
-
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
- HDCP_REAUTH_DELAY);
- } else {
- HDCP_WARN("authentication failed HDCP disabled\n");
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
-
- if (timer_state == 1) {
- DBG("delete auth timer\n");
- del_timer_sync(&auth_timer);
- timer_state = 0;
- }
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_start_authentication
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_start_authentication(void)
-{
- int status = HDCP_OK;
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
- DBG("HDCP: authentication start\n");
- status = rk3036_hdcp_start_authentication();
- if (status != HDCP_OK) {
- DBG("HDCP: authentication failed\n");
- hdcp_wq_authentication_failure();
- } else {
- /*hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;*/
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
-}
-#if 0
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_bksv
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_check_bksv(void)
-{
- int status = HDCP_OK;
-
- DBG("Check BKSV start");
- status = rk3036_hdcp_check_bksv();
- if (status != HDCP_OK) {
- HDCP_WARN("HDCP: Check BKSV failed");
- hdcp->retry_cnt = 0;
- hdcp_wq_authentication_failure();
- } else {
- DBG("HDCP: Check BKSV successful");
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- /* Restore retry counter */
- if (hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- }
-}
-#endif
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_sucess
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_sucess(void)
-{
- hdcp->auth_state = 1;
- if (timer_state == 1) {
- DBG("delete auth timer\n");
- timer_state = 0;
- del_timer_sync(&auth_timer);
- }
-/*
- rk616_hdmi_control_output(true);
- */
- rk3036_set_colorbar(0);
- HDCP_WARN("HDCP: authentication pass\n");
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_disable
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_disable(int event)
-{
- HDCP_WARN("HDCP: disabled\n");
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
- rk3036_hdcp_disable();
- if (event == HDCP_DISABLE_CTL) {
- hdcp->hdcp_state = HDCP_DISABLED;
- if (hdcp->hdmi_state == HDMI_STARTED)
- rk3036_set_colorbar(0);
- } else if (event == HDCP_STOP_FRAME_EVENT) {
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_work_queue
- *-----------------------------------------------------------------------------
- */
-static void hdcp_work_queue(struct work_struct *work)
-{
- struct hdcp_delayed_work *hdcp_w =
- container_of(work, struct hdcp_delayed_work, work.work);
- int event = hdcp_w->event;
-
- mutex_lock(&hdcp->lock);
- DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d\n",
- jiffies_to_msecs(jiffies),
- hdcp->hdmi_state,
- hdcp->hdcp_state,
- (event & 0xFF00) >> 8,
- event & 0xFF);
-
- if (event == HDCP_STOP_FRAME_EVENT)
- hdcp->hdmi_state = HDMI_STOPPED;
- if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT)
- hdcp_wq_disable(event);
- if (event & HDCP_WORKQUEUE_SRC)
- hdcp->pending_wq_event = 0;
- /* First handle HDMI state */
- if (event == HDCP_START_FRAME_EVENT) {
- hdcp->pending_start = 0;
- hdcp->hdmi_state = HDMI_STARTED;
- }
-
- /**********************/
- /* HDCP state machine */
- /**********************/
- switch (hdcp->hdcp_state) {
- case HDCP_DISABLED:
- /* HDCP enable control or re-authentication event */
- if (event == HDCP_ENABLE_CTL) {
- /*if (hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;*/
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- if (hdcp->hdmi_state == HDMI_STARTED)
- hdcp_wq_start_authentication();
- else
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
- break;
- case HDCP_ENABLE_PENDING:
- /* HDMI start frame event */
- if (event == HDCP_START_FRAME_EVENT)
- hdcp_wq_start_authentication();
- break;
- case HDCP_AUTHENTICATION_START:
- /* Re-authentication */
- if (event == HDCP_AUTH_REATT_EVENT)
- hdcp_wq_start_authentication();
- break;
-#if 0
- case HDCP_WAIT_KSV_LIST:
- /* KSV failure */
- if (event == HDCP_FAIL_EVENT) {
- HDCP_WARN("HDCP: KSV switch failure\n");
- hdcp_wq_authentication_failure();
- }
- /* KSV list ready event */
- else if (event == HDCP_KSV_LIST_RDY_EVENT)
- hdcp_wq_check_bksv();
- break;
-#endif
- case HDCP_LINK_INTEGRITY_CHECK:
- /* authentication failure */
- if (event == HDCP_FAIL_EVENT) {
- HDCP_WARN("HDCP: Ri check failure\n");
- hdcp_wq_authentication_failure();
- } else if (event == HDCP_AUTH_PASS_EVENT)
- hdcp_wq_authentication_sucess();
- break;
- default:
- HDCP_WARN("HDCP: error - unknow HDCP state\n");
- break;
- }
- kfree(hdcp_w);
- if (event == HDCP_STOP_FRAME_EVENT)
- complete(&hdcp->complete);
- mutex_unlock(&hdcp->lock);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_start_frame_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_start_frame_cb(void)
-{
- DBG("hdcp_start_frame_cb()\n");
-
- /* Cancel any pending work */
- if (hdcp->pending_start)
- hdcp_cancel_work(&hdcp->pending_start);
- if (hdcp->pending_wq_event)
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- if (timer_state == 0) {
- DBG("add auth timer\n");
- auth_timer.expires = jiffies + AUTH_TIMEOUT;
- add_timer(&auth_timer);
- timer_state = 1;
- }
-
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_irq_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_irq_cb(int status)
-{
- char interrupt1;
- char interrupt2;
-
- rk3036_hdcp_interrupt(&interrupt1, &interrupt2);
- DBG("%s 0x%02x 0x%02x\n", __func__, interrupt1, interrupt2);
- if (interrupt1 & m_INT_HDCP_ERR) {
- if ((hdcp->hdcp_state != HDCP_DISABLED) &&
- (hdcp->hdcp_state != HDCP_ENABLE_PENDING))
- hdcp_submit_work(HDCP_FAIL_EVENT, 0);
- }
-/*
- else if (interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
- hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
- */
- else if (interrupt1 & m_INT_AUTH_SUCCESS)
- hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_on_cb
- *-----------------------------------------------------------------------------
- */
-static int hdcp_power_on_cb(void)
-{
- DBG("%s", __func__);
- return rk3036_hdcp_load_key2mem(hdcp->keys);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_off_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_power_off_cb(void)
-{
- DBG("%s\n", __func__);
- if (timer_state == 1) {
- DBG("delete auth timer\n");
- timer_state = 0;
- del_timer_sync(&auth_timer);
- }
- hdcp->auth_state = 0;
-
- if (!hdcp->enable)
- return;
- rk3036_hdcp_stop_authentication();
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- init_completion(&hdcp->complete);
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
- wait_for_completion_interruptible_timeout(&hdcp->complete,
- msecs_to_jiffies(5000));
-}
-
-/*
- * Load HDCP key to external HDCP memory
- */
-static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
-{
- if (!fw) {
- pr_err("HDCP: failed to load keys\n");
- return;
- }
- if (fw->size < HDCP_KEY_SIZE) {
- pr_err("HDCP: firmware wrong size %d\n", fw->size);
- return;
- }
- hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
- if (hdcp->keys == NULL) {
- pr_err("HDCP: can't allocated space for keys\n");
- return;
- }
- memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
- HDCP_WARN("HDCP: load hdcp key success\n");
-
- if (fw->size > HDCP_KEY_SIZE) {
- DBG("%s invalid key size %d\n", __func__,
- fw->size - HDCP_KEY_SIZE);
- if ((fw->size - HDCP_KEY_SIZE) % 5) {
- pr_err("HDCP: failed to load invalid keys\n");
- return;
- }
- hdcp->invalidkeys =
- kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
- if (hdcp->invalidkeys == NULL) {
- pr_err("HDCP: can't allocated space for invalid keys\n");
- return;
- }
- memcpy(hdcp->invalidkeys, fw->data +
- HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
- hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
- HDCP_WARN("HDCP: loaded hdcp invalid key success\n");
- }
-}
-
-static ssize_t hdcp_enable_read(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- int enable = 0;
-
- if (hdcp)
- enable = hdcp->enable;
- return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t hdcp_enable_write(struct device *device,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int enable;
-
- if (hdcp == NULL)
- return -EINVAL;
- sscanf(buf, "%d", &enable);
- if (hdcp->enable != enable) {
- /* Post event to workqueue */
- if (enable) {
- if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
- return -EFAULT;
- } else {
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- hdcp->enable = enable;
- }
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
- hdcp_enable_read, hdcp_enable_write);
-
-static ssize_t hdcp_trytimes_read(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- int trytimes = 0;
-
- if (hdcp)
- trytimes = hdcp->retry_times;
- return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
-}
-
-static ssize_t hdcp_trytimes_wrtie(struct device *device,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int trytimes;
-
- if (hdcp == NULL)
- return -EINVAL;
- sscanf(buf, "%d", &trytimes);
- if (hdcp->retry_times != trytimes)
- hdcp->retry_times = trytimes;
- return count;
-}
-
-
-static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
- hdcp_trytimes_read, hdcp_trytimes_wrtie);
-static struct miscdevice mdev;
-
-static int __init rk3036_hdcp_init(void)
-{
- int ret;
-
- DBG("[%s] %u\n", __func__, jiffies_to_msecs(jiffies));
- hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
- if (!hdcp) {
- HDCP_WARN(">>HDCP: kmalloc fail!\n");
- ret = -ENOMEM;
- goto error0;
- }
- memset(hdcp, 0, sizeof(struct hdcp));
- mutex_init(&hdcp->lock);
- mdev.minor = MISC_DYNAMIC_MINOR;
- mdev.name = "hdcp";
- mdev.mode = 0666;
- if (misc_register(&mdev)) {
- HDCP_WARN("HDCP: Could not add character driver\n");
- ret = HDMI_ERROR_FALSE;
- goto error1;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_enable);
- if (ret) {
- HDCP_WARN("HDCP: Could not add sys file enable\n");
- ret = -EINVAL;
- goto error2;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
- if (ret) {
- HDCP_WARN("HDCP: Could not add sys file trytimes\n");
- ret = -EINVAL;
- goto error3;
- }
- hdcp->workqueue = create_singlethread_workqueue("hdcp");
- if (hdcp->workqueue == NULL) {
- HDCP_WARN("HDCP,: create workqueue failed.\n");
- goto error4;
- }
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "hdcp.keys", mdev.this_device,
- GFP_KERNEL, hdcp,
- hdcp_load_keys_cb);
- if (ret < 0) {
- HDCP_WARN("HDCP: request_firmware_nowait failed: %d\n", ret);
- goto error5;
- }
-
- rk3036_hdmi_register_hdcp_callbacks(hdcp_start_frame_cb,
- hdcp_irq_cb,
- hdcp_power_on_cb,
- hdcp_power_off_cb);
-
- init_timer(&auth_timer);
- auth_timer.data = 0;
- auth_timer.function = auth_timer_func;
- DBG("%s success %u\n", __func__, jiffies_to_msecs(jiffies));
- return 0;
-error5:
- destroy_workqueue(hdcp->workqueue);
-error4:
- device_remove_file(mdev.this_device, &dev_attr_trytimes);
-error3:
- device_remove_file(mdev.this_device, &dev_attr_enable);
-error2:
- misc_deregister(&mdev);
-error1:
- kfree(hdcp->keys);
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-error0:
- return ret;
-}
-
-static void __exit rk3036_hdcp_exit(void)
-{
- device_remove_file(mdev.this_device, &dev_attr_enable);
- misc_deregister(&mdev);
- kfree(hdcp->keys);
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-}
-
-/* module_init(rk3036_hdcp_init); */
-late_initcall_sync(rk3036_hdcp_init);
-module_exit(rk3036_hdcp_exit);
+++ /dev/null
-#ifndef __RK3036_HDCP_H__
-#define __RK3036_HDCP_H__
-
-/***************************/
-/* Definitions */
-/***************************/
-
-/* Status / error codes */
-#define HDCP_OK 0
-#define HDCP_KEY_ERR 1
-#define HDCP_KSV_ERR 2
-#define HDCP_KEY_VALID 3
-#define HDCP_KEY_INVALID 4
-
-/* Delays */
-#define HDCP_ENABLE_DELAY 300
-#define HDCP_REAUTH_DELAY 100
-
-/* Event source */
-#define HDCP_SRC_SHIFT 8
-#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
-#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
-#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
-#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
-
-/* Event */
-#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
-#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
-#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
-#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
-#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 4)
-#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 5)
-#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 6)
-#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 7)
-
-/* Key size */
-#define HDCP_KEY_SIZE 308
-
-/* HDCP DDC Clock */
-#define HDCP_DDC_CLK 100000
-
-/* Authentication retry times */
-#define HDCP_INFINITE_REAUTH 0x100
-
-/* HDCP Regs */
-#define HDCP_CTRL1 0x52
- #define m_AUTH_START (1 << 7)
- #define m_BKSV_VALID (1 << 6)
- #define m_BKSV_INVALID (1 << 5)
- #define m_ENCRYPT_ENABLE (1 << 4)
- #define m_AUTH_STOP (1 << 3)
- #define m_ADVANED_ENABLE (1 << 2)
- #define m_HDMI_DVI (1 << 1)
- #define m_HDCP_RESET (1 << 0)
-
- #define v_AUTH_START(n) (n << 7)
- #define v_BKSV_VALID(n) (n << 6)
- #define v_BKSV_INVALID(n) (n << 5)
- #define v_ENCRYPT_ENABLE(n) (n << 4)
- #define v_AUTH_STOP(n) (n << 3)
- #define v_ADVANED_ENABLE(n) (n << 2)
- #define v_HDMI_DVI(n) (n << 1)
- #define v_HDCP_RESET(n) (n << 0)
-
-#define HDCP_CTRL2 0x53
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_ENABLE_PJ_CHECK (1 << 5)
- #define m_DISABLE_DEVICE_NUMBER_CHECK (1 << 4)
- #define m_DELAY_RI_1_CLK (1 << 3)
- #define m_USE_PRESET_AN (1 << 2)
- #define m_KEY_COMBINATION (3 << 0)
-
- #define v_DISABLE_127_CHECK(n) (n << 7)
- #define v_SKIP_BKSV_CHECK(n) (n << 6)
- #define v_ENABLE_PJ_CHECK(n) (n << 5)
- #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
- #define v_DELAY_RI_1_CLK(n) (n << 3)
- #define v_USE_PRESET_AN(n) (n << 2)
- #define v_KEY_COMBINATION(n) (n << 0)
-
-#define HDCP_KEY_STATUS 0x54
- #define m_KEY_READY (1 << 0)
-
-#define HDCP_CTRL_SOFT 0x57
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_NOT_AUTHENTICATED (1 << 5)
- #define m_ENCRYPTED (1 << 4)
- #define m_ADVANCED_CIPHER (1 << 3)
-
-#define HDCP_BCAPS_RX 0x58
-#define HDCP_TIMER_100MS 0x63
-#define HDCP_TIMER_5S 0x64
-#define HDCP_ERROR 0x65
- #define m_DDC_NO_ACK (1 << 3)
- #define m_PJ_MISMACH (1 << 2)
- #define m_RI_MISMACH (1 << 1)
- #define m_BKSV_WRONG (1 << 0)
-
-#define HDCP_KSV_BYTE0 0x66
-#define HDCP_KSV_BYTE1 0x67
-#define HDCP_KSV_BYTE2 0x68
-#define HDCP_KSV_BYTE3 0x69
-#define HDCP_KSV_BYTE4 0x6a
-
-#define HDCP_AN_SEED 0x6c
-
-#define HDCP_BCAPS_TX 0x80
-#define HDCP_BSTATE_0 0x81
-#define HDCP_BSTATE_1 0x82
-
-#define HDCP_KEY_FIFO 0x98
-
-#define HDCP_INT_MASK1 0xc2
-#define HDCP_INT_STATUS1 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_READY (1 << 6)
- #define m_INT_BKSV_UPDATE (1 << 5)
- #define m_INT_AUTH_SUCCESS (1 << 4)
- #define m_INT_AUTH_READY (1 << 3)
-
-#define HDCP_INT_MASK2 0xc4
-#define HDCP_INT_STATUS2 0xc5
- #define m_INT_SOFT_MODE_READY (1 << 7)
- #define m_INT_AUTH_M0_REDAY (1 << 6)
- #define m_INT_1st_FRAME_ARRIVE (1 << 5)
- #define m_INT_AN_READY (1 << 4)
- #define m_INT_ENCRYPTED (1 << 2)
- #define m_INT_NOT_ENCRYPTED_AVMUTE (1 << 1)
- #define m_INT_NOT_ENCRYPTED_AVUNMUTE (1 << 0)
-
-enum hdcp_states {
- HDCP_DISABLED,
- HDCP_ENABLE_PENDING,
- HDCP_AUTHENTICATION_START,
- HDCP_WAIT_KSV_LIST,
- HDCP_LINK_INTEGRITY_CHECK,
-};
-
-enum hdmi_states {
- HDMI_STOPPED,
- HDMI_STARTED
-};
-
-#define HDCP_PRIVATE_KEY_SIZE 280
-#define HDCP_KEY_SHA_SIZE 20
-
-struct hdcp_keys {
- u8 ksv[8];
- u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
- u8 sha1[HDCP_KEY_SHA_SIZE];
-};
-
-struct hdcp_delayed_work {
- struct delayed_work work;
- int event;
-};
-
-struct hdcp {
- int enable;
- int retry_times;
- struct hdcp_keys *keys;
- int invalidkey;
- char *invalidkeys;
- struct mutex lock;
- struct completion complete;
- struct workqueue_struct *workqueue;
-
- enum hdmi_states hdmi_state;
- enum hdcp_states hdcp_state;
-
- struct delayed_work *pending_start;
- struct delayed_work *pending_wq_event;
- int retry_cnt;
- int auth_state;
-};
-
-extern struct hdcp *hdcp;
-
-#ifdef HDCP_DEBUG
-#define DBG(format, ...) \
- printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-#if 1
-#define HDCP_WARN(x...) printk(KERN_INFO x)
-#else
-#define I2S_DBG(x...) do { } while (0)
-#endif
-
-extern void rk3036_hdcp_disable(void);
-extern int rk3036_hdcp_start_authentication(void);
-extern int rk3036_hdcp_check_bksv(void);
-extern int rk3036_hdcp_load_key2mem(struct hdcp_keys *key);
-extern void rk3036_hdcp_interrupt(char *status1, char *status2);
-extern void rk3036_set_colorbar(int enable);
-extern int rk3036_hdcp_stop_authentication(void);
-extern int is_1b_03_test(void);
-#endif /* __rk3036_HDCP_H__ */
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/uaccess.h>
-
-#include <linux/of_gpio.h>
-#include <linux/rk_fb.h>
-
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#endif
-
-#include "rk3036_hdmi.h"
-#include "rk3036_hdmi_hw.h"
-
-struct rk_hdmi_device *hdmi_dev;
-
-#if defined(CONFIG_DEBUG_FS)
-static int rk3036_hdmi_reg_show(struct seq_file *s, void *v)
-{
- int i = 0;
- u32 val = 0;
-
- seq_puts(s, "\n\n>>>rk3036_ctl reg");
- for (i = 0; i < 16; i++)
- seq_printf(s, " %2x", i);
-
- seq_puts(s,
- "\n-----------------------------------------------------------------");
-
- for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
- hdmi_readl(hdmi_dev, i, &val);
- if (i % 16 == 0)
- seq_printf(s, "\n>>>rk3036_ctl %2x:", i);
- seq_printf(s, " %02x", val);
-
- }
- seq_puts(s,
- "\n-----------------------------------------------------------------\n");
-
- return 0;
-}
-
-static ssize_t rk3036_hdmi_reg_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- u32 reg;
- u32 val;
- char kbuf[25];
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (copy_from_user(kbuf, buf, count))
- return -EFAULT;
- sscanf(kbuf, "%x%x", ®, &val);
- if ((reg < 0) || (reg > 0xed)) {
- dev_info(hdmi_drv->dev, "it is no hdmi reg\n");
- return count;
- }
- dev_info(hdmi_drv->dev, "/**********rk3036 reg config******/");
- dev_info(hdmi_drv->dev, "\n reg=%x val=%x\n", reg, val);
- hdmi_writel(hdmi_dev, reg, val);
-
- return count;
-}
-
-static int rk3036_hdmi_reg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, rk3036_hdmi_reg_show, NULL);
-}
-
-static const struct file_operations rk3036_hdmi_reg_fops = {
- .owner = THIS_MODULE,
- .open = rk3036_hdmi_reg_open,
- .read = seq_read,
- .write = rk3036_hdmi_reg_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-static int rk3036_hdmi_clk_enable(struct rk_hdmi_device *hdmi_dev)
-{
- struct hdmi *hdmi_drv;
- hdmi_drv = &hdmi_dev->driver;
-
- if (!hdmi_dev->clk_on) {
- if(hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
- clk_prepare_enable(hdmi_dev->pd);
- }
- clk_prepare_enable(hdmi_dev->hclk);
- spin_lock(&hdmi_dev->reg_lock);
- hdmi_dev->clk_on = 1;
- spin_unlock(&hdmi_dev->reg_lock);
- }
-
- return 0;
-}
-
-static int rk3036_hdmi_clk_disable(struct rk_hdmi_device *hdmi_dev)
-{
- struct hdmi *hdmi_drv;
- hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_dev->clk_on) {
- spin_lock(&hdmi_dev->reg_lock);
- hdmi_dev->clk_on = 0;
- spin_unlock(&hdmi_dev->reg_lock);
- if(hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
- clk_disable_unprepare(hdmi_dev->pd);
- }
- clk_disable_unprepare(hdmi_dev->hclk);
- }
-
- return 0;
-}
-
-int rk3036_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void))
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv == NULL)
- return HDMI_ERROR_FALSE;
-
- hdmi_drv->hdcp_cb = hdcp_cb;
- hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
- hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
- hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
-
- return HDMI_ERROR_SUCESS;
-}
-
-int rk3036_hdmi_register_cec_callbacks(void (*cec_irq)(void),
- void (*cec_set_device_pa)(int addr),
- int (*cec_enumerate)(void))
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv == NULL)
- return HDMI_ERROR_FALSE;
-
- hdmi_drv->cec_irq = cec_irq;
- hdmi_drv->cec_set_device_pa = cec_set_device_pa;
- hdmi_drv->cec_enumerate = cec_enumerate;
-
- return HDMI_ERROR_SUCESS;
-}
-
-static void rk3036_hdmi_early_suspend(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi enter early suspend pwr %d state %d\n",
- hdmi_drv->pwr_mode, hdmi_drv->state);
-
- flush_delayed_work(&hdmi_drv->delay_work);
- mutex_lock(&hdmi_drv->enable_mutex);
- if (!hdmi_drv->suspend) {
- hdmi_drv->suspend = 1;
- if (!hdmi_drv->enable) {
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
- }
-
- if (hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
-
- mutex_unlock(&hdmi_drv->enable_mutex);
- hdmi_drv->command = HDMI_CONFIG_ENABLE;
- init_completion(&hdmi_drv->complete);
- hdmi_drv->wait = 1;
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, 0);
- wait_for_completion_interruptible_timeout(&hdmi_drv->complete,
- msecs_to_jiffies(5000));
- flush_delayed_work(&hdmi_drv->delay_work);
- rk3036_hdmi_clk_disable(hdmi_dev);
- }
-}
-
-static void rk3036_hdmi_early_resume(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi exit early resume\n");
-
- mutex_lock(&hdmi_drv->enable_mutex);
- if (hdmi_drv->suspend) {
- hdmi_drv->suspend = 0;
- rk3036_hdmi_clk_enable(hdmi_dev);
- rk3036_hdmi_initial(hdmi_drv);
- if (hdmi_drv->enable && hdmi_drv->irq) {
- enable_irq(hdmi_drv->irq);
- rk3036_hdmi_irq(hdmi_drv);
- }
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(10));
- }
- mutex_unlock(&hdmi_drv->enable_mutex);
-}
-
-static int rk3036_hdmi_fb_event_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- struct fb_event *event = data;
- int blank_mode = *((int *)event->data);
-
- if (action == FB_EARLY_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- break;
- default:
- rk3036_hdmi_early_suspend();
- break;
- }
- } else if (action == FB_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- rk3036_hdmi_early_resume();
- break;
- default:
- break;
- }
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block rk3036_hdmi_fb_notifier = {
- .notifier_call = rk3036_hdmi_fb_event_notify,
-};
-
-
-static void rk3036_delay_work_func(struct work_struct *work)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv->suspend == 0) {
- if (hdmi_drv->enable == 1)
- rk3036_hdmi_irq(hdmi_drv);
- if (hdmi_drv->irq == 0)
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk3036_delay_work,
- msecs_to_jiffies(100));
- }
-}
-
-static irqreturn_t rk3036_hdmi_irq_func(int irq, void *dev_id)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
- if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1)) {
- hdmi_dbg(hdmi_drv->dev,
- "line = %d, rk3036_hdmi_irq_func irq triggered.\n",
- __LINE__);
- rk3036_hdmi_irq(hdmi_drv);
- }
-
- return IRQ_HANDLED;
-}
-
-static int rk3036_hdmi_drv_init(struct hdmi *hdmi_drv)
-{
- int ret = 0;
- int lcdc_id = 0;
- struct rk_screen screen;
-
- rk_fb_get_prmry_screen(&screen);
-
- /* hdmi is extend as default,TODO modify if hdmi is primary */
- /*lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;*/
- lcdc_id = screen.lcdc_id;//for box,hdmi is primary
-
- if (lcdc_id == 0)
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
- else
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
-
- if (IS_ERR(hdmi_drv->lcdc)) {
- dev_err(hdmi_drv->dev,
- "can not connect to video source lcdc\n");
- ret = -ENXIO;
- return ret;
- }
-
- hdmi_drv->xscale = 100;
- hdmi_drv->yscale = 100;
-
- /*spin_lock_init(&hdmi_drv->irq_lock);*/
- mutex_init(&hdmi_drv->enable_mutex);
- hdmi_sys_init(hdmi_drv);
- ret = rk3036_hdmi_initial(hdmi_drv);
-
- hdmi_drv_register(hdmi_drv);
- return ret;
-}
-
-static struct rk_hdmi_drvdata rk3036_hdmi_drvdata = {
- .soc_type = HDMI_SOC_RK3036,
-};
-
-static struct rk_hdmi_drvdata rk312x_hdmi_drvdata = {
- .soc_type = HDMI_SOC_RK312X,
-};
-
-#if defined(CONFIG_OF)
-static const struct of_device_id rk3036_hdmi_of_match[] = {
- {.compatible = "rockchip,rk3036-hdmi",
- .data = (void *)&rk3036_hdmi_drvdata, },
- {.compatible = "rockchip,rk312x-hdmi",
- .data = (void *)&rk312x_hdmi_drvdata,},
- {}
-};
-
-MODULE_DEVICE_TABLE(of, rk3036_hdmi_of_match);
-#endif
-
-static int rk3036_hdmi_probe(struct platform_device *pdev)
-{
- int ret;
- struct hdmi *hdmi_drv;
- struct resource *res;
- const struct of_device_id *match;
- struct device_node *node = pdev->dev.of_node;
-
- hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct rk_hdmi_device),
- GFP_KERNEL);
- if (!hdmi_dev) {
- dev_err(&pdev->dev, ">>rk3036_hdmi kmalloc fail!");
- return -ENOMEM;
- }
-
- hdmi_drv = &hdmi_dev->driver;
- hdmi_drv->dev = &pdev->dev;
- platform_set_drvdata(pdev, hdmi_dev);
- spin_lock_init(&hdmi_dev->reg_lock);
-
- match = of_match_node(rk3036_hdmi_of_match, node);
- hdmi_drv->data = (struct rk_hdmi_drvdata*)match->data;
- dev_info(hdmi_drv->dev, "%s,type=%d\n",
- __func__,hdmi_drv->data->soc_type);
-
-
-#ifdef CONFIG_SWITCH
- hdmi_drv->switch_hdmi.name = "hdmi";
- switch_dev_register(&(hdmi_drv->switch_hdmi));
-#endif
- hdmi_register_display_sysfs(hdmi_drv, NULL);
- fb_register_client(&rk3036_hdmi_fb_notifier);
-
- hdmi_drv->workqueue = create_singlethread_workqueue("hdmi");
- INIT_DELAYED_WORK(&(hdmi_drv->delay_work), hdmi_work);
- INIT_DELAYED_WORK(&hdmi_dev->rk3036_delay_work, rk3036_delay_work_func);
-
- /* enable clk */
- if(hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
- hdmi_dev->pd = devm_clk_get(hdmi_drv->dev, "pd_hdmi");
- if (IS_ERR(hdmi_dev->pd)) {
- dev_err(hdmi_drv->dev, "Unable to get hdmi pd\n");
- ret = -ENXIO;
- goto err1;
- }
- }
- hdmi_dev->hclk = devm_clk_get(hdmi_drv->dev, "pclk_hdmi");
- if (IS_ERR(hdmi_dev->hclk)) {
- dev_err(hdmi_drv->dev, "Unable to get hdmi hclk\n");
- ret = -ENXIO;
- goto err1;
- }
- rk3036_hdmi_clk_enable(hdmi_dev); /* enable clk may move to irq func */
- hdmi_dev->hclk_rate = clk_get_rate(hdmi_dev->hclk);
- /* request and remap iomem */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(hdmi_drv->dev, "Unable to get register resource\n");
- ret = -ENXIO;
- goto err2;
- }
- hdmi_dev->regbase_phy = res->start;
- hdmi_dev->regsize_phy = resource_size(res);
- hdmi_dev->regbase = devm_ioremap_resource(hdmi_drv->dev, res);
- if (IS_ERR(hdmi_dev->regbase)) {
- ret = PTR_ERR(hdmi_dev->regbase);
- dev_err(hdmi_drv->dev, "cannot ioremap registers,err=%d\n",
- ret);
- goto err2;
- }
- if (rk3036_hdmi_drv_init(hdmi_drv))
- goto err0;
-
- /* get the IRQ */
- hdmi_drv->irq = platform_get_irq(pdev, 0);
- if (hdmi_drv->irq <= 0) {
- dev_err(hdmi_drv->dev, "failed to get hdmi irq resource (%d).\n",
- hdmi_drv->irq);
- hdmi_drv->irq = 0;
- } else {
- /* request the IRQ */
- ret = devm_request_irq(hdmi_drv->dev, hdmi_drv->irq,
- rk3036_hdmi_irq_func, 0,
- dev_name(hdmi_drv->dev), hdmi_drv);
- if (ret) {
- dev_err(hdmi_drv->dev, "hdmi request_irq failed (%d)\n",
- ret);
- goto err2;
- }
- }
-
-#if defined(CONFIG_DEBUG_FS)
- hdmi_dev->debugfs_dir = debugfs_create_dir("rk3036", NULL);
- if (IS_ERR(hdmi_dev->debugfs_dir)) {
- dev_err(hdmi_drv->dev,
- "failed to create debugfs dir for rk3036!\n");
- } else {
- debugfs_create_file("hdmi", S_IRUSR,
- hdmi_dev->debugfs_dir, hdmi_drv,
- &rk3036_hdmi_reg_fops);
- }
-
-#endif
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk3036_delay_work,
- msecs_to_jiffies(0));
- dev_info(hdmi_drv->dev, "rk3036 hdmi probe success.\n");
-
- return 0;
-
-err2:
- rk3036_hdmi_clk_disable(hdmi_dev);
-err1:
- fb_unregister_client(&rk3036_hdmi_fb_notifier);
- hdmi_unregister_display_sysfs(hdmi_drv);
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi_drv->switch_hdmi));
-#endif
-
-err0:
- hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi probe error.\n");
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- return ret;
-}
-
-static int rk3036_hdmi_remove(struct platform_device *pdev)
-{
- struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev) {
- hdmi_drv = &hdmi_dev->driver;
- mutex_lock(&hdmi_drv->enable_mutex);
- if (!hdmi_drv->suspend && hdmi_drv->enable && hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- if (hdmi_drv->irq)
- free_irq(hdmi_drv->irq, NULL);
-
- flush_workqueue(hdmi_drv->workqueue);
- destroy_workqueue(hdmi_drv->workqueue);
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi_drv->switch_hdmi));
-#endif
- hdmi_unregister_display_sysfs(hdmi_drv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi_drv->early_suspend);
-#endif
- fb_destroy_modelist(&hdmi_drv->edid.modelist);
- if (hdmi_drv->edid.audio)
- kfree(hdmi_drv->edid.audio);
- if (hdmi_drv->edid.specs) {
- if (hdmi_drv->edid.specs->modedb)
- kfree(hdmi_drv->edid.specs->modedb);
- kfree(hdmi_drv->edid.specs);
- }
-
- hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi removed.\n");
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- }
-
- return 0;
-}
-
-static void rk3036_hdmi_shutdown(struct platform_device *pdev)
-{
- struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev) {
- hdmi_drv = &hdmi_dev->driver;
-#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi_drv->early_suspend);
-#endif
- flush_delayed_work(&hdmi_drv->delay_work);
- mutex_lock(&hdmi_drv->enable_mutex);
- hdmi_drv->suspend = 1;
- if (!hdmi_drv->enable) {
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
- }
- if (hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- if (hdmi_drv->hotplug == HDMI_HPD_ACTIVED)
- rk3036_hdmi_control_output(hdmi_drv, 0);
- rk3036_hdmi_clk_disable(hdmi_dev);
- }
- hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi shut down.\n");
-}
-
-
-static struct platform_driver rk3036_hdmi_driver = {
- .probe = rk3036_hdmi_probe,
- .remove = rk3036_hdmi_remove,
- .driver = {
- .name = "rk3036-hdmi",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(rk3036_hdmi_of_match),
- },
- .shutdown = rk3036_hdmi_shutdown,
-};
-
-static int __init rk3036_hdmi_init(void)
-{
- return platform_driver_register(&rk3036_hdmi_driver);
-}
-
-static void __exit rk3036_hdmi_exit(void)
-{
- platform_driver_unregister(&rk3036_hdmi_driver);
-}
-
-module_init(rk3036_hdmi_init);
-module_exit(rk3036_hdmi_exit);
+++ /dev/null
-#ifndef __RK3036_HDMI_H__
-#define __RK3036_HDMI_H__
-
-#include "../../rk_hdmi.h"
-
-enum {
- INPUT_IIS,
- INPUT_SPDIF
-};
-
-
-#if defined(CONFIG_SND_RK_SOC_HDMI_SPDIF)
-#define HDMI_CODEC_SOURCE_SELECT INPUT_SPDIF
-#else
-#define HDMI_CODEC_SOURCE_SELECT INPUT_IIS
-#endif
-
-extern void rk3036_hdmi_control_output(struct hdmi *hdmi, int enable);
-extern int rk3036_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-extern int rk3036_hdmi_register_cec_callbacks(void (*cec_irq)(void),
- void (*cec_set_device_pa)(int addr),
- int (*cec_enumerate)(void));
-
-
-extern struct rk_hdmi_device *hdmi_dev;
-
-struct rk_hdmi_device {
- int clk_on;
- spinlock_t reg_lock;
- struct hdmi driver;
- void __iomem *regbase;
- int regbase_phy;
- int regsize_phy;
- struct clk *pd;
- struct clk *hclk; /* HDMI AHP clk */
- struct delayed_work rk3036_delay_work;
- struct work_struct rk3036_irq_work_struct;
- struct dentry *debugfs_dir;
- unsigned int hclk_rate;
-};
-
-#endif /* __RK3036_HDMI_H__ */
+++ /dev/null
-#include "rk3036_hdmi.h"
-#include "rk3036_hdmi_hw.h"
-#include "rk3036_hdmi_cec.h"
-
-static cec_t cec;
-static char la_player[3] = {CEC_LOGADDR_PLAYBACK1,
- CEC_LOGADDR_PLAYBACK2,
- CEC_LOGADDR_PLAYBACK3};
-
-static int cec_read_frame(cec_framedata_t *frame)
-{
- int i, length,val;
- char *data = (char *)frame;//modify by hjc
- if(frame == NULL)
- return -1;
-
- hdmi_readl(hdmi_dev, CEC_RX_LENGTH, &length);
- hdmi_writel(hdmi_dev, CEC_RX_OFFSET, 0);
-
- printk("CEC: %s length is %d\n", __FUNCTION__, length);
- for(i = 0; i < length; i++) {
- hdmi_readl(hdmi_dev, CEC_DATA, &val);
- data[i] = val;
- printk("%02x\n", data[i]);
- }
- return 0;
-}
-
-static int cec_send_frame(cec_framedata_t *frame)
-{
- int i;
-
- CECDBG("CEC: TX srcdestaddr %02x opcode %02x ",
- frame->srcdestaddr, frame->opcode);
- if(frame->argcount) {
- CECDBG("args:");
- for(i = 0; i < frame->argcount; i++) {
- CECDBG("%02x ", frame->args[i]);
- }
- }
- CECDBG("\n");
-
- hdmi_writel(hdmi_dev, CEC_TX_OFFSET, 0);
- hdmi_writel(hdmi_dev, CEC_DATA, frame->srcdestaddr);
- hdmi_writel(hdmi_dev, CEC_DATA, frame->opcode);
-
- for(i = 0; i < frame->argcount; i++)
- hdmi_writel(hdmi_dev, CEC_DATA, frame->args[i]);
-
- hdmi_writel(hdmi_dev, CEC_TX_LENGTH, frame->argcount + 2);
-
- /*Wait for bus free*/
- cec.busfree = 1;
- hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE);
- CECDBG("start wait bus free\n");
- if(wait_event_interruptible_timeout(cec.wait, cec.busfree == 0, msecs_to_jiffies(17))) {
- return -1;
- }
- CECDBG("end wait bus free,start tx,busfree=%d\n",cec.busfree);
- /*Start TX*/
- cec.tx_done = 0;
- hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE|m_START_TX);
- if(wait_event_interruptible_timeout(cec.wait, cec.tx_done != 0, msecs_to_jiffies(100)))
- hdmi_writel(hdmi_dev, CEC_CTRL, 0);
- CECDBG("end tx,tx_done=%d\n",cec.tx_done);
- if (cec.tx_done == 1) {
- cec.tx_done = 0;//hjc add ,need?
- return 0;
- } else
- return -1;
-}
-
-static int cec_send_message(char opcode, char dest)
-{
- cec_framedata_t cecframe;
- CECDBG("CEC: cec_send_message\n");
-
- cecframe.opcode = opcode;
- cecframe.srcdestaddr = MAKE_SRCDEST(cec.address_logic, dest);
- cecframe.argcount = 0;
- return cec_send_frame(&cecframe);
-}
-
-static void cec_send_feature_abort ( cec_framedata_t *pcpi, char reason )
-{
- cec_framedata_t cecFrame;
- CECDBG("CEC: cec_send_feature_abort\n");
-
- if (( pcpi->srcdestaddr & 0x0F) != CEC_LOGADDR_UNREGORBC )
- {
- cecFrame.opcode = CECOP_FEATURE_ABORT;
- cecFrame.srcdestaddr = MAKE_SRCDEST( cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4 );
- cecFrame.args[0] = pcpi->opcode;
- cecFrame.args[1] = reason;
- cecFrame.argcount = 2;
- cec_send_frame( &cecFrame );
- }
-}
-
-static void cec_send_active_source(void)
-{
- cec_framedata_t cecframe;
-
- CECDBG("CEC: start_active_source\n");
- cecframe.opcode = CECOP_ACTIVE_SOURCE;
- cecframe.srcdestaddr = MAKE_SRCDEST( cec.address_logic, CEC_LOGADDR_UNREGORBC);
- cecframe.args[0] = (cec.address_phy & 0xFF00) >> 8; /* [Physical Address]*/
- cecframe.args[1] = (cec.address_phy & 0x00FF); /* [Physical Address]*/
- cecframe.argcount = 2;
- cec_send_frame( &cecframe );
-}
-
-static void start_active_source(void)
-{
- int i;
- CECDBG("CEC: start_active_source\n");
- /* GPIO simulate CEC timing may be not correct, so we try more times.*/
- /*send image view on first*/
- for(i = 0; i < 1; i++) {
- if(cec_send_message(CECOP_IMAGE_VIEW_ON,CEC_LOGADDR_TV) == 0) {
- cec_send_active_source();
- }
- }
-}
-
-static void cec_handle_inactive_source ( cec_framedata_t *pcpi )
-{
-
-}
-
-static void cec_handle_feature_abort( cec_framedata_t *pcpi )
-{
-
-}
-
-static bool validate_cec_message(cec_framedata_t *pcpi)
-{
- char parametercount = 0;
- bool countok = true;
- CECDBG("CEC: validate_cec_message,opcode=%d\n",pcpi->opcode);
-
- /* Determine required parameter count */
- switch (pcpi->opcode)
- {
- case CECOP_IMAGE_VIEW_ON:
- case CECOP_TEXT_VIEW_ON:
- case CECOP_STANDBY:
- case CECOP_GIVE_PHYSICAL_ADDRESS:
- case CECOP_GIVE_DEVICE_POWER_STATUS:
- case CECOP_GET_MENU_LANGUAGE:
- case CECOP_GET_CEC_VERSION:
- parametercount = 0;
- break;
- case CECOP_REPORT_POWER_STATUS: // power status*/
- case CECOP_CEC_VERSION: // cec version*/
- parametercount = 1;
- break;
- case CECOP_INACTIVE_SOURCE: // physical address*/
- case CECOP_FEATURE_ABORT: // feature opcode / abort reason*/
- case CECOP_ACTIVE_SOURCE: // physical address*/
- parametercount = 2;
- break;
- case CECOP_REPORT_PHYSICAL_ADDRESS: // physical address / device type*/
- case CECOP_DEVICE_VENDOR_ID: // vendor id*/
- parametercount = 3;
- break;
- case CECOP_SET_OSD_NAME: // osd name (1-14 bytes)*/
- case CECOP_SET_OSD_STRING: // 1 + x display control / osd string (1-13 bytes)*/
- parametercount = 1; // must have a minimum of 1 operands*/
- break;
- case CECOP_ABORT:
- break;
- case CECOP_ARC_INITIATE:
- break;
- case CECOP_ARC_REPORT_INITIATED:
- break;
- case CECOP_ARC_REPORT_TERMINATED:
- break;
-
- case CECOP_ARC_REQUEST_INITIATION:
- break;
- case CECOP_ARC_REQUEST_TERMINATION:
- break;
- case CECOP_ARC_TERMINATE:
- break;
- default:
- break;
- }
-
- /* Test for correct parameter count. */
-
- if (pcpi->argcount < parametercount) {
- CECDBG("CEC: pcpi->argcount[%d] < parametercount[%d]\n",
- pcpi->argcount,parametercount);
- countok = false;
- }
- return(countok );
-}
-
-static bool cec_rx_msg_handler_last(cec_framedata_t *pcpi)
-{
- bool isdirectaddressed;
- cec_framedata_t cecFrame;
-
- CECDBG("CEC: cec_rx_msg_handler_last,opcode=%d\n",pcpi->opcode);
- isdirectaddressed = !((pcpi->srcdestaddr & 0x0F) == CEC_LOGADDR_UNREGORBC);
-
- if (validate_cec_message(pcpi)) {/* If invalid message, ignore it, but treat it as handled*/
- if (isdirectaddressed) {
- switch (pcpi->opcode) {
- case CECOP_FEATURE_ABORT:
- cec_handle_feature_abort(pcpi);
- break;
- case CECOP_IMAGE_VIEW_ON: /*In our case, respond the same to both these messages*/
- case CECOP_TEXT_VIEW_ON:
- break;
- case CECOP_STANDBY: /* Direct and Broadcast*/
- /* Setting this here will let the main task know */
- /* (via SI_CecGetPowerState) and at the same time */
- /* prevent us from broadcasting a STANDBY message */
- /* of our own when the main task responds by */
- /* calling SI_CecSetPowerState( STANDBY ); */
- cec.powerstatus = CEC_POWERSTATUS_STANDBY;
- break;
- case CECOP_INACTIVE_SOURCE:
- cec_handle_inactive_source(pcpi);
- break;
- case CECOP_GIVE_PHYSICAL_ADDRESS:
- /* TV responds by broadcasting its Physical Address: 0.0.0.0 */
- cecFrame.opcode = CECOP_REPORT_PHYSICAL_ADDRESS;
- cecFrame.srcdestaddr = MAKE_SRCDEST(cec.address_logic,
- CEC_LOGADDR_UNREGORBC);
- cecFrame.args[0] = (cec.address_phy&0xFF00)>>8; /* [Physical Address]*/
- cecFrame.args[1] = (cec.address_phy&0x00FF); /*[Physical Address]*/
- cecFrame.args[2] = cec.address_logic;/*CEC_LOGADDR_PLAYBACK1;//2011.08.03 CEC_LOGADDR_TV; // [Device Type] = 0 = TV*/
- cecFrame.argcount = 3;
- cec_send_frame(&cecFrame);
- break;
- case CECOP_GIVE_DEVICE_POWER_STATUS:
- /* TV responds with power status. */
- cecFrame.opcode = CECOP_REPORT_POWER_STATUS;
- cecFrame.srcdestaddr = MAKE_SRCDEST(cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4);
- cecFrame.args[0] = cec.powerstatus;
- cecFrame.argcount = 1;
- cec_send_frame(&cecFrame);
- break;
- case CECOP_GET_MENU_LANGUAGE:
- /* TV Responds with a Set Menu language command. */
- cecFrame.opcode = CECOP_SET_MENU_LANGUAGE;
- cecFrame.srcdestaddr = CEC_LOGADDR_UNREGORBC;
- cecFrame.args[0] = 'e'; /* [language code see iso/fdis 639-2]*/
- cecFrame.args[1] = 'n'; /* [language code see iso/fdis 639-2]*/
- cecFrame.args[2] = 'g'; /* [language code see iso/fdis 639-2]*/
- cecFrame.argcount = 3;
- cec_send_frame(&cecFrame);
- break;
- case CECOP_GET_CEC_VERSION:
- /* TV responds to this request with it's CEC version support. */
- cecFrame.srcdestaddr = MAKE_SRCDEST(cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4);
- cecFrame.opcode = CECOP_CEC_VERSION;
- cecFrame.args[0] = 0x04; /* Report CEC1.3a*/
- cecFrame.argcount = 1;
- cec_send_frame(&cecFrame);
- break;
- case CECOP_REPORT_POWER_STATUS: /* Someone sent us their power state.*/
- /*l_sourcePowerStatus = pcpi->args[0];
- Let NEW SOURCE task know about it.
- if (l_cecTaskState.task == SI_CECTASK_NEWSOURCE) {
- l_cecTaskState.cpiState = CPI_RESPONSE;
- }*/
- break;
- /* Do not reply to directly addressed 'Broadcast' msgs. */
- case CECOP_ACTIVE_SOURCE:
- case CECOP_REPORT_PHYSICAL_ADDRESS: /*A physical address was broadcast -- ignore it.*/
- case CECOP_REQUEST_ACTIVE_SOURCE: /*We are not a source, so ignore this one.*/
- case CECOP_ROUTING_CHANGE: /*We are not a downstream switch, so ignore this one.*/
- case CECOP_ROUTING_INFORMATION: /*We are not a downstream switch, so ignore this one.*/
- case CECOP_SET_STREAM_PATH: /*We are not a source, so ignore this one.*/
- case CECOP_SET_MENU_LANGUAGE: /*As a TV, we can ignore this message*/
- case CECOP_DEVICE_VENDOR_ID:
- break;
- case CECOP_ABORT: /*Send Feature Abort for all unsupported features.*/
- default:
- cec_send_feature_abort(pcpi, CECAR_UNRECOG_OPCODE);
- break;
- }
- } else {
- /* Respond to broadcast messages. */
- switch (pcpi->opcode) {
- case CECOP_STANDBY:
-
- /* Setting this here will let the main task know */
- /* (via SI_CecGetPowerState) and at the same time */
- /* prevent us from broadcasting a STANDBY message */
- /* of our own when the main task responds by */
- /* calling SI_CecSetPowerState( STANDBY ); */
-
- cec.powerstatus = CEC_POWERSTATUS_STANDBY;
- break;
-
- case CECOP_ACTIVE_SOURCE:
- /*CecHandleActiveSource( pcpi );*/
- break;
- case CECOP_REPORT_PHYSICAL_ADDRESS:
- /*CecHandleReportPhysicalAddress( pcpi );*/
- break;
- /* Do not reply to 'Broadcast' msgs that we don't need. */
- case CECOP_REQUEST_ACTIVE_SOURCE: /*We are not a source, so ignore this one.*/
- /*SI_StartActiveSource(0,0);//2011.08.03*/
- break;
- case CECOP_ROUTING_CHANGE: /*We are not a downstream switch, so ignore this one.*/
- case CECOP_ROUTING_INFORMATION: /*We are not a downstream switch, so ignore this one.*/
- case CECOP_SET_STREAM_PATH: /*We are not a source, so ignore this one.*/
- case CECOP_SET_MENU_LANGUAGE: /*As a TV, we can ignore this message*/
- break;
- }
- }
- }
- return 0;
-}
-
-static void cec_work_func(struct work_struct *work)
-{
- struct cec_delayed_work *cec_w =
- container_of(work, struct cec_delayed_work, work.work);
- cec_framedata_t cecFrame;
- CECDBG(KERN_WARNING "CEC: cec_work_func,event=%d\n",cec_w->event);
- switch(cec_w->event)
- {
- case EVENT_ENUMERATE:
- break;
- case EVENT_RX_FRAME:
- memset(&cecFrame, 0, sizeof(cec_framedata_t));
- cec_read_frame(&cecFrame);
- cec_rx_msg_handler_last(&cecFrame);
- break;
- default:
- break;
- }
-
- if(cec_w->data)
- kfree(cec_w->data);
- kfree(cec_w);
-}
-
-static void cec_submit_work(int event, int delay, void *data)
-{
- struct cec_delayed_work *work;
-
- CECDBG("%s event %04x delay %d", __func__, event, delay);
- work = kmalloc(sizeof(struct cec_delayed_work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, cec_work_func);
- work->event = event;
- work->data = data;
- queue_delayed_work(cec.workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- CECDBG(KERN_WARNING "CEC: GPIO CEC: Cannot allocate memory to "
- "create work\n");;
- }
-}
-
-int cec_enumerate(void)
-{
- /*for(i = 0; i < 3; i++) {
- if(Cec_Ping(la_player[i]) == 1) {
- cec.address_logic = la_player[i];
- break;
- }
- }
- if(i == 3)
- return -1;
- //Broadcast our physical address.
- GPIO_CecSendMessage(CECOP_GET_MENU_LANGUAGE,CEC_LOGADDR_TV);
- msleep(100);*/
- CECDBG("CEC: %s\n", __func__);
- cec.address_logic = la_player[0];
- hdmi_writel(hdmi_dev, CEC_LOGICADDR, cec.address_logic);
- start_active_source();
- return 0;
-}
-
-void cec_set_device_pa(int addr)
-{
- CECDBG("CEC: Physical Address is %02x", addr);
- cec.address_phy = addr;
-}
-
-void rk3036_cec_isr(void)
-{
- int tx_isr = 0, rx_isr = 0;
- hdmi_readl(hdmi_dev, CEC_TX_INT, &tx_isr);
- hdmi_readl(hdmi_dev, CEC_RX_INT, &rx_isr);
-
- CECDBG("CEC: rk3036_cec_isr:tx_isr %02x rx_isr %02x\n\n", tx_isr, rx_isr);
-
- hdmi_writel(hdmi_dev, CEC_TX_INT, tx_isr);
- hdmi_writel(hdmi_dev, CEC_RX_INT, rx_isr);
-
- if (tx_isr & m_TX_BUSNOTFREE) {
- cec.busfree = 0;
- CECDBG("CEC: m_TX_BUSNOTFREE,busfree=%d\n",cec.busfree);
- } else if (tx_isr & m_TX_DONE) {
- cec.tx_done = 1;
- CECDBG("CEC: m_TX_DONE,busfree=%d\n",cec.tx_done);
- } else {
- cec.tx_done = -1;
- CECDBG("CEC: else:busfree=%d\n",cec.tx_done);
- }
-
- wake_up_interruptible_all(&cec.wait);
- if(rx_isr & m_RX_DONE)
- cec_submit_work(EVENT_RX_FRAME, 0, NULL);
-}
-
-
-static int __init rk3036_cec_init(void)
-{
- CECDBG(KERN_ERR "CEC: rk3036_cec_init start.\n");
- memset(&cec, 0, sizeof(cec_t));
- cec.workqueue = create_singlethread_workqueue("cec");
- if (cec.workqueue == NULL) {
- CECDBG(KERN_ERR "CEC: GPIO CEC: create workqueue failed.\n");
- return -1;
- }
- init_waitqueue_head(&cec.wait);
-
- /*Fref = Fsys / ((register 0xd4 + 1)*(register 0xd5 + 1))*/
- /*Fref = 0.5M, Fsys = 74.25M*/
- hdmi_writel(hdmi_dev, CEC_CLK_H, 11);
- hdmi_writel(hdmi_dev, CEC_CLK_L, 11);
-
- /*Set bus free time to 16.8ms*/
- hdmi_writel(hdmi_dev, CEC_BUSFREETIME_L, 0xd0);
- hdmi_writel(hdmi_dev, CEC_BUSFREETIME_H, 0x20);
-
- /*Enable TX/RX INT*/
- hdmi_writel(hdmi_dev, CEC_TX_INT, 0xFF);
- hdmi_writel(hdmi_dev, CEC_RX_INT, 0xFF);
-
- rk3036_hdmi_register_cec_callbacks(rk3036_cec_isr,
- cec_set_device_pa,
- cec_enumerate);
-
- CECDBG(KERN_ERR "CEC: rk3036_cec_init sucess\n");
-
- return 0;
-}
-
-static void __exit rk3036_cec_exit(void)
-{
- kfree(&cec);
-}
-
-late_initcall_sync(rk3036_cec_init);
-module_exit(rk3036_cec_exit);
+++ /dev/null
-#ifndef __RK3036_CEC_H__
-#define __RK3036_CEC_H__
-
-typedef enum
-{
- CEC_LOGADDR_TV = 0x00,
- CEC_LOGADDR_RECDEV1 = 0x01,
- CEC_LOGADDR_RECDEV2 = 0x02,
- CEC_LOGADDR_TUNER1 = 0x03, /* STB1 in Spev v1.3*/
- CEC_LOGADDR_PLAYBACK1 = 0x04, /* DVD1 in Spev v1.3*/
- CEC_LOGADDR_AUDSYS = 0x05,
- CEC_LOGADDR_TUNER2 = 0x06, /* STB2 in Spec v1.3*/
- CEC_LOGADDR_TUNER3 = 0x07, /* STB3 in Spec v1.3*/
- CEC_LOGADDR_PLAYBACK2 = 0x08, /* DVD2 in Spec v1.3*/
- CEC_LOGADDR_RECDEV3 = 0x09,
- CEC_LOGADDR_TUNER4 = 0x0A, /* RES1 in Spec v1.3*/
- CEC_LOGADDR_PLAYBACK3 = 0x0B, /* RES2 in Spec v1.3*/
- CEC_LOGADDR_RES3 = 0x0C,
- CEC_LOGADDR_RES4 = 0x0D,
- CEC_LOGADDR_FREEUSE = 0x0E,
- CEC_LOGADDR_UNREGORBC = 0x0F
-} cec_log_addr_t;
-
-typedef enum /* CEC Messages*/
-{
- CECOP_FEATURE_ABORT = 0x00,
- CECOP_IMAGE_VIEW_ON = 0x04,
- CECOP_TUNER_STEP_INCREMENT = 0x05, /* N/A*/
- CECOP_TUNER_STEP_DECREMENT = 0x06, /* N/A*/
- CECOP_TUNER_DEVICE_STATUS = 0x07, /* N/A*/
- CECOP_GIVE_TUNER_DEVICE_STATUS = 0x08, /* N/A*/
- CECOP_RECORD_ON = 0x09, /* N/A*/
- CECOP_RECORD_STATUS = 0x0A, /* N/A*/
- CECOP_RECORD_OFF = 0x0B, /* N/A*/
- CECOP_TEXT_VIEW_ON = 0x0D,
- CECOP_RECORD_TV_SCREEN = 0x0F, /* N/A*/
- CECOP_GIVE_DECK_STATUS = 0x1A,
- CECOP_DECK_STATUS = 0x1B,
- CECOP_SET_MENU_LANGUAGE = 0x32,
- CECOP_CLEAR_ANALOGUE_TIMER = 0x33, /* Spec 1.3A*/
- CECOP_SET_ANALOGUE_TIMER = 0x34, /* Spec 1.3A*/
- CECOP_TIMER_STATUS = 0x35, /* Spec 1.3A*/
- CECOP_STANDBY = 0x36,
- CECOP_PLAY = 0x41,
- CECOP_DECK_CONTROL = 0x42,
- CECOP_TIMER_CLEARED_STATUS = 0x43, /* Spec 1.3A*/
- CECOP_USER_CONTROL_PRESSED = 0x44,
- CECOP_USER_CONTROL_RELEASED = 0x45,
- CECOP_GIVE_OSD_NAME = 0x46,
- CECOP_SET_OSD_NAME = 0x47,
- CECOP_SET_OSD_STRING = 0x64,
- CECOP_SET_TIMER_PROGRAM_TITLE = 0x67, /* Spec 1.3A*/
- CECOP_SYSTEM_AUDIO_MODE_REQUEST = 0x70, /* Spec 1.3A*/
- CECOP_GIVE_AUDIO_STATUS = 0x71, /* Spec 1.3A*/
- CECOP_SET_SYSTEM_AUDIO_MODE = 0x72, /* Spec 1.3A*/
- CECOP_REPORT_AUDIO_STATUS = 0x7A, /* Spec 1.3A*/
- CECOP_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, /* Spec 1.3A*/
- CECOP_SYSTEM_AUDIO_MODE_STATUS = 0x7E, /* Spec 1.3A*/
- CECOP_ROUTING_CHANGE = 0x80,
- CECOP_ROUTING_INFORMATION = 0x81,
- CECOP_ACTIVE_SOURCE = 0x82,
- CECOP_GIVE_PHYSICAL_ADDRESS = 0x83,
- CECOP_REPORT_PHYSICAL_ADDRESS = 0x84,
- CECOP_REQUEST_ACTIVE_SOURCE = 0x85,
- CECOP_SET_STREAM_PATH = 0x86,
- CECOP_DEVICE_VENDOR_ID = 0x87,
- CECOP_VENDOR_COMMAND = 0x89,
- CECOP_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
- CECOP_VENDOR_REMOTE_BUTTON_UP = 0x8B,
- CECOP_GIVE_DEVICE_VENDOR_ID = 0x8C,
- CECOP_MENU_REQUEST = 0x8D,
- CECOP_MENU_STATUS = 0x8E,
- CECOP_GIVE_DEVICE_POWER_STATUS = 0x8F,
- CECOP_REPORT_POWER_STATUS = 0x90,
- CECOP_GET_MENU_LANGUAGE = 0x91,
- CECOP_SELECT_ANALOGUE_SERVICE = 0x92, /* Spec 1.3A N/A*/
- CECOP_SELECT_DIGITAL_SERVICE = 0x93, /* N/A*/
- CECOP_SET_DIGITAL_TIMER = 0x97, /* Spec 1.3A*/
- CECOP_CLEAR_DIGITAL_TIMER = 0x99, /* Spec 1.3A*/
- CECOP_SET_AUDIO_RATE = 0x9A, /* Spec 1.3A*/
- CECOP_INACTIVE_SOURCE = 0x9D, /* Spec 1.3A*/
- CECOP_CEC_VERSION = 0x9E, /* Spec 1.3A*/
- CECOP_GET_CEC_VERSION = 0x9F, /* Spec 1.3A*/
- CECOP_VENDOR_COMMAND_WITH_ID = 0xA0, /* Spec 1.3A*/
- CECOP_CLEAR_EXTERNAL_TIMER = 0xA1, /* Spec 1.3A*/
- CECOP_SET_EXTERNAL_TIMER = 0xA2, /* Spec 1.3A*/
- CDCOP_HEADER = 0xF8,
- CECOP_ABORT = 0xFF,
-
- CECOP_REPORT_SHORT_AUDIO = 0xA3, /* Spec 1.4*/
- CECOP_REQUEST_SHORT_AUDIO = 0xA4, /* Spec 1.4*/
-
- CECOP_ARC_INITIATE = 0xC0,
- CECOP_ARC_REPORT_INITIATED = 0xC1,
- CECOP_ARC_REPORT_TERMINATED = 0xC2,
-
- CECOP_ARC_REQUEST_INITIATION = 0xC3,
- CECOP_ARC_REQUEST_TERMINATION = 0xC4,
- CECOP_ARC_TERMINATE = 0xC5,
-} cec_opcode_t;
-
-typedef enum /* Operands for <Feature Abort> Opcode*/
-{
- CECAR_UNRECOG_OPCODE = 0x00,
- CECAR_NOT_CORRECT_MODE,
- CECAR_CANT_PROVIDE_SOURCE,
- CECAR_INVALID_OPERAND,
- CECAR_REFUSED
-} cec_abor_reason_t;
-
-enum /* Operands for <Power Status> Opcode*/
-{
- CEC_POWERSTATUS_ON = 0x00,
- CEC_POWERSTATUS_STANDBY = 0x01,
- CEC_POWERSTATUS_STANDBY_TO_ON = 0x02,
- CEC_POWERSTATUS_ON_TO_STANDBY = 0x03,
-};
-
-enum {
- EVENT_RX_FRAME,
- EVENT_ENUMERATE,
-};
-
-#define MAKE_SRCDEST( src, dest) (( src << 4) | dest )
-
-#define MAX_CMD_SIZE 16
-
-typedef struct
-{
- char srcdestaddr; /*Source in upper nybble, dest in lower nybble*/
- char opcode;
- char args[ MAX_CMD_SIZE ];
- char argcount;
- char nextframeargcount;
-} cec_framedata_t;
-
-struct cec_delayed_work {
- struct delayed_work work;
- int event;
- void *data;
-};
-
-typedef struct
-{
- struct workqueue_struct *workqueue;
- wait_queue_head_t wait;
- int busfree;
- int tx_done;
- int address_phy;
- int address_logic;
- int powerstatus;
-} cec_t;
-
-//#define DEBUG
-#ifdef DEBUG
-#define CECDBG(format, ...) \
- printk(KERN_INFO format, ## __VA_ARGS__)
-#else
-#define CECDBG(format, ...)
-#endif
-#endif
+++ /dev/null
-#include <linux/delay.h>
-#include "rk3036_hdmi.h"
-#include "rk3036_hdmi_hw.h"
-#include "rk3036_hdcp.h"
-int is_1b_03_test(void)
-{
- int reg_value;
- int reg_val_1;
-
- hdmi_readl(hdmi_dev, 0x58, ®_value);
- hdmi_readl(hdmi_dev, 0xc3, ®_val_1);
-
- if (reg_value != 0) {
- if ((reg_val_1 & 0x40) == 0)
- return 1;
- }
- return 0;
-}
-
-void rk3036_set_colorbar(int enable)
-{
- static int display_mask;
- int reg_value;
- int tmds_clk;
-
- tmds_clk = hdmi_dev->driver.tmdsclk;
- if (enable) {
- if (!display_mask) {
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
- hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE,
- v_REG_CLK_SOURCE_SYS);
- hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
- hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
- } else {
- hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
- }
- display_mask = 1;
- }
- } else {
- if (display_mask) {
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
- hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE,
- v_REG_CLK_SOURCE_SYS);
- hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
- hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
- } else {
- hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
- }
- display_mask = 0;
- }
- }
-}
-
-void rk3036_hdcp_disable(void)
-{
- int reg_value;
- int tmds_clk;
-
- tmds_clk = hdmi_dev->driver.tmdsclk;
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
- hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
- }
-
- /* Diable HDCP Interrupt*/
- hdmi_writel(hdmi_dev, HDCP_INT_MASK1, 0x00);
- /* Stop and Reset HDCP*/
- hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
- m_AUTH_START | m_AUTH_STOP | m_HDCP_RESET,
- v_AUTH_START(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1));
-
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
- hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
-}
-
-int rk3036_hdcp_key_check(struct hdcp_keys *key)
-{
- int i = 0;
-
- DBG("HDCP: check hdcp key\n");
- /*check 40 private key */
- for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++) {
- if (key->devicekey[i] != 0x00)
- return HDCP_KEY_VALID;
- }
- /*check aksv*/
- for (i = 0; i < 5; i++) {
- if (key->ksv[i] != 0x00)
- return HDCP_KEY_VALID;
- }
-
- return HDCP_KEY_INVALID;
-}
-int rk3036_hdcp_load_key2mem(struct hdcp_keys *key)
-{
- int i;
-
- DBG("HDCP: rk3036_hdcp_load_key2mem start\n");
- /* Write 40 private key*/
- for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
- hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->devicekey[i]);
- /* Write 1st aksv*/
- for (i = 0; i < 5; i++)
- hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
- /* Write 2nd aksv*/
- for (i = 0; i < 5; i++)
- hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
- DBG("HDCP: rk3036_hdcp_load_key2mem end\n");
- return HDCP_OK;
-}
-
-int rk3036_hdcp_start_authentication(void)
-{
- int temp;
- int retry = 0;
- int tmds_clk;
-
- tmds_clk = hdmi_dev->driver.tmdsclk;
- if (hdcp->keys == NULL) {
- HDCP_WARN("HDCP: key is not loaded\n");
- return HDCP_KEY_ERR;
- }
- if (rk3036_hdcp_key_check(hdcp->keys) == HDCP_KEY_INVALID) {
- HDCP_WARN("loaded HDCP key is incorrect\n");
- return HDCP_KEY_ERR;
- }
- if (tmds_clk > (HDMI_SYS_FREG_CLK << 2)) {
- /*Select TMDS CLK to configure regs*/
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);
- } else {
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
- }
- hdmi_writel(hdmi_dev, HDCP_TIMER_100MS, 0x28);
- hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
- while ((temp & m_KEY_READY) == 0) {
- if (retry > 1000) {
- HDCP_WARN("HDCP: loaded key error\n");
- return HDCP_KEY_ERR;
- }
- rk3036_hdcp_load_key2mem(hdcp->keys);
- msleep(1);
- hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
- retry++;
- }
- /*Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)*/
- retry = hdmi_dev->hclk_rate/(HDCP_DDC_CLK << 2);
- hdmi_writel(hdmi_dev, DDC_CLK_L, retry & 0xFF);
- hdmi_writel(hdmi_dev, DDC_CLK_H, (retry >> 8) & 0xFF);
- hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x67);
- /*Enable interrupt*/
- hdmi_writel(hdmi_dev, HDCP_INT_MASK1,
- m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE |
- m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);
- hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x00);
- /*Start authentication*/
- hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
- m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE |
- m_AUTH_STOP | m_HDCP_RESET,
- v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) |
- v_ADVANED_ENABLE(0) | v_AUTH_STOP(0) | v_HDCP_RESET(0));
-
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
- v_REG_CLK_SOURCE_TMDS);
- }
- return HDCP_OK;
-}
-
-int rk3036_hdcp_stop_authentication(void)
-{
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
- hdmi_writel(hdmi_dev, DDC_CLK_L, 0x1c);
- hdmi_writel(hdmi_dev, DDC_CLK_H, 0x00);
- hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x08);
- hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x06);
- hdmi_writel(hdmi_dev, HDCP_CTRL1, 0x02);
- return 0;
- /*hdmi_writel(HDCP_CTRL1, 0x0a);*/
-}
-#if 0
-int rk3036_hdcp_check_bksv(void)
-{
- int i, j;
- char temp = 0, bksv[5];
- char *invalidkey;
-
- for (i = 0; i < 5; i++) {
- hdmi_readl(HDCP_KSV_BYTE0 + (4 - i), &temp);
- bksv[i] = temp & 0xFF;
- }
- DBG("bksv is 0x%02x%02x%02x%02x%02x",
- bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
-
- temp = 0;
- for (i = 0; i < 5; i++) {
- for (j = 0; j < 8; j++) {
- if (bksv[i] & 0x01)
- temp++;
- bksv[i] >>= 1;
- }
- }
- if (temp != 20)
- return HDCP_KSV_ERR;
- for (i = 0; i < hdcp->invalidkey; i++) {
- invalidkey = hdcp->invalidkeys + i*5;
- if (memcmp(bksv, invalidkey, 5) == 0) {
- HDCP_WARN("HDCP:BKSV was revocated!\n");
- hdmi_msk_reg(HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE,
- v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));
- return HDCP_KSV_ERR;
- }
- }
- hdmi_msk_reg(HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE,
- v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));
- return HDCP_OK;
-}
-#endif
-
-int rk3036_hdcp_error(int value)
-{
- if (value & 0x80)
- HDCP_WARN("Timed out waiting for downstream repeater\n");
- else if (value & 0x40)
- HDCP_WARN("Too many devices connected to repeater tree\n");
- else if (value & 0x20)
- HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
- else if (value & 0x10)
- HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
- else if (value & 0x08)
- HDCP_WARN("DDC channels no acknowledge\n");
- else if (value & 0x04)
- HDCP_WARN("Pj mismatch\n");
- else if (value & 0x02)
- HDCP_WARN("Ri mismatch\n");
- else if (value & 0x01)
- HDCP_WARN("Bksv is wrong\n");
- else
- return 0;
- return 1;
-}
-void rk3036_hdcp_interrupt(char *status1, char *status2)
-{
- int interrupt1 = 0;
- int interrupt2 = 0;
- int temp = 0;
- int tmds_clk;
-
- tmds_clk = hdmi_dev->driver.tmdsclk;
- hdmi_readl(hdmi_dev, HDCP_INT_STATUS1, &interrupt1);
- hdmi_readl(hdmi_dev, HDCP_INT_STATUS2, &interrupt2);
-
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
- hdmi_msk_reg(hdmi_dev, SYS_CTRL,
- m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
-
- if (interrupt1) {
- hdmi_writel(hdmi_dev, HDCP_INT_STATUS1, interrupt1);
- if (interrupt1 & m_INT_HDCP_ERR) {
- hdmi_readl(hdmi_dev, HDCP_ERROR, &temp);
- HDCP_WARN("HDCP: Error reg 0x65 = 0x%02x\n", temp);
- rk3036_hdcp_error(temp);
- hdmi_writel(hdmi_dev, HDCP_ERROR, temp);
- }
- }
- if (interrupt2)
- hdmi_writel(hdmi_dev, HDCP_INT_STATUS2, interrupt2);
-
- *status1 = interrupt1;
- *status2 = interrupt2;
-
- if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
- v_REG_CLK_SOURCE_TMDS);
-/*
- hdmi_readl(HDCP_ERROR, &temp);
- DBG("HDCP: Error reg 0x65 = 0x%02x\n", temp);
-*/
-}
+++ /dev/null
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/of_irq.h>
-#include "rk3036_hdmi.h"
-#include "rk3036_hdmi_hw.h"
-static unsigned int rk3036_hdmi_support_vic[] = {
- HDMI_720X480P_60HZ_VIC,
- HDMI_720X480I_60HZ_VIC,
- HDMI_720X576P_50HZ_VIC,
- HDMI_720X576I_50HZ_VIC,
- HDMI_1280X720P_50HZ_VIC,
- HDMI_1280X720P_60HZ_VIC,
- HDMI_1920X1080P_50HZ_VIC,
- HDMI_1920X1080I_50HZ_VIC,
- HDMI_1920X1080P_60HZ_VIC,
- HDMI_1920X1080I_60HZ_VIC
-};
-static int __maybe_unused rk3036_hdmi_show_reg(struct hdmi *hdmi_drv)
-{
- int i = 0;
- u32 val = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- printk("\n>>>rk3036_ctl reg");
- for (i = 0; i < 16; i++)
- printk(" %2x", i);
-
- printk("\n-----------------------------------------------------------------");
-
- for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
- hdmi_readl(hdmi_dev, i, &val);
- if (i % 16 == 0)
- printk("\n>>>rk3036_ctl %2x:", i);
- printk(" %02x", val);
- }
- printk("\n-----------------------------------------------------------------\n");
-
- return 0;
-}
-
-static inline void delay100us(void)
-{
- msleep(1);
-}
-
-static void rk3036_hdmi_av_mute(struct hdmi *hdmi_drv, bool enable)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- if (enable) {
- hdmi_msk_reg(hdmi_dev, AV_MUTE,
- m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
- v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
- } else {
- hdmi_msk_reg(hdmi_dev, AV_MUTE,
- m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
- v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
- }
- hdmi_writel(hdmi_dev, PACKET_SEND_AUTO, m_PACKET_GCP_EN);
-}
-
-static void rk3036_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (enable)
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
- else
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
-}
-
-static void rk3036_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (hdmi_drv->pwr_mode == mode)
- return;
-
- hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
- hdmi_drv->pwr_mode, mode);
-
- switch (mode) {
- case NORMAL:
- hdmi_dbg(hdmi_drv->dev,
- "%s change pwr_mode NORMAL pwr_mode = %d, mode = %d\n",
- __func__, hdmi_drv->pwr_mode, mode);
- rk3036_hdmi_sys_power(hdmi_drv, false);
- if (hdmi_drv->data->soc_type == HDMI_SOC_RK3036) {
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0xbb);
- }
- else if (hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x5f);
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
- }
- hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
- hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
- hdmi_writel(hdmi_dev, 0xce, 0x00);
- hdmi_writel(hdmi_dev, 0xce, 0x01);
- rk3036_hdmi_sys_power(hdmi_drv, true);
- break;
- case LOWER_PWR:
- hdmi_dbg(hdmi_drv->dev,
- "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
- __func__, hdmi_drv->pwr_mode, mode);
- rk3036_hdmi_sys_power(hdmi_drv, false);
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
- hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
- break;
- default:
- hdmi_dbg(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
- mode);
- }
-
- hdmi_drv->pwr_mode = mode;
-}
-
-int rk3036_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
-{
- int value = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_dbg(hdmi_drv->dev, "[%s] value %02x\n", __func__, value);
- hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
- value &= m_HOTPLUG;
- if (value == m_HOTPLUG)
- return HDMI_HPD_ACTIVED;
- else if (value)
- return HDMI_HPD_INSERT;
- else
- return HDMI_HPD_REMOVED;
-}
-int rk3036_hdmi_insert(struct hdmi *hdmi_drv)
-{
- rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
- return 0;
-}
-
-
-int rk3036_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
-{
- u32 c = 0;
- u8 segment = 0;
- u8 offset = 0;
- int ret = -1;
- int i, j;
- int ddc_bus_freq;
- int trytime;
- int checksum = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- if (block % 2)
- offset = HDMI_EDID_BLOCK_SIZE;
-
- if (block / 2)
- segment = 1;
- ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
- hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
- hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-
- hdmi_dbg(hdmi_drv->dev,
- "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
- (int)segment, (int)block, (int)offset);
- disable_irq(hdmi_drv->irq);
-
- /* Enable edid interrupt */
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
-
- for (trytime = 0; trytime < 10; trytime++) {
- checksum = 0;
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
-
- /* Set edid fifo first addr */
- hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
-
- /* Set edid word address 0x00/0x80 */
- hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
-
- /* Set edid segment pointer */
- hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
-
- for (i = 0; i < 10; i++) {
- /* Wait edid interrupt */
- msleep(10);
- c = 0x00;
- hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
-
- if (c & m_INT_EDID_READY)
- break;
- }
-
- if (c & m_INT_EDID_READY) {
- for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
- c = 0;
- hdmi_readl(hdmi_dev, 0x50, &c);
- buf[j] = c;
- checksum += c;
-#ifdef HDMI_DEBUG
- if (j % 16 == 0)
- printk("\n>>>0x%02x: ",j);
-
- printk("0x%02x ", c);
-#endif
- }
-
- if ((checksum & 0xff) == 0) {
- ret = 0;
- hdmi_dbg(hdmi_drv->dev,
- "[%s] edid read sucess\n", __func__);
- break;
- }
- }
- }
- /*close edid irq*/
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
- /* clear EDID interrupt reg */
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
- m_INT_EDID_READY);
-
- enable_irq(hdmi_drv->irq);
-
- return ret;
-}
-
-static const char coeff_csc[][24] = {
- /*YUV2RGB:601 SD mode(Y[16:235],UV[16:240],RGB[0:255]):
- R = 1.164*Y +1.596*V - 204
- G = 1.164*Y - 0.391*U - 0.813*V + 154
- B = 1.164*Y + 2.018*U - 258*/
- {
- 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
- 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
- 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02},
-
- /*YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
- R = Y + 1.402*V - 248
- G = Y - 0.344*U - 0.714*V + 135
- B = Y + 1.772*U - 227*/
- {
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
- 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
- 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3},
- /*YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
- R = 1.164*Y +1.793*V - 248
- G = 1.164*Y - 0.213*U - 0.534*V + 77
- B = 1.164*Y + 2.115*U - 289*/
- {
- 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
- 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
- 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21},
- /*RGB2YUV:601 SD mode:
- Cb = -0.291G - 0.148R + 0.439B + 128
- Y = 0.504G + 0.257R + 0.098B + 16
- Cr = -0.368G + 0.439R - 0.071B + 128*/
- {
- /*0x11, 0x78, 0x01, 0xc1, 0x10, 0x48, 0x00, 0x80,
- 0x02, 0x04, 0x01, 0x07, 0x00, 0x64, 0x00, 0x10,
- 0x11, 0x29, 0x10, 0x97, 0x01, 0xc1, 0x00, 0x80*/
-
- /*0x11,0x4b,0x01,0x8a,0x10,0x3f,0x00,0x80,
- 0x01,0xbb,0x00,0xe2,0x00,0x56,0x00,0x1d,
- 0x11,0x05,0x10,0x85,0x01,0x8a,0x00,0x80*/
-
- 0x11,0x5f,0x01,0x82,0x10,0x23,0x00,0x80,
- 0x02,0x1c,0x00,0xa1,0x00,0x36,0x00,0x1e,
- 0x11,0x29,0x10,0x59,0x01,0x82,0x00,0x80
- },
-
- /*RGB2YUV:709 HD mode:
- Cb = - 0.338G - 0.101R + 0.439B + 128
- Y = 0.614G + 0.183R + 0.062B + 16
- Cr = - 0.399G + 0.439R - 0.040B + 128*/
- {
- 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
- 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
- 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
- },
- /*RGB[0:255]2RGB[16:235]:
- R' = R x (235-16)/255 + 16;
- G' = G x (235-16)/255 + 16;
- B' = B x (235-16)/255 + 16;*/
- {
- 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
- 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10},
-};
-static int rk3036_hdmi_video_csc(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- int value,i,csc_mode,c0_c2_change,auto_csc,csc_enable;
- const char *coeff = NULL;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- /* Enable or disalbe color space convert */
- hdmi_dbg(hdmi_drv->dev, "[%s] input_color=%d,output_color=%d\n",
- __func__, vpara->input_color, vpara->output_color);
- if (vpara->input_color == vpara->output_color) {
- if ((vpara->input_color >= VIDEO_INPUT_COLOR_YCBCR444) ||
- ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) &&
- (vpara->color_limit_range == COLOR_LIMIT_RANGE_0_255))) {
- value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
- v_VIDEO_C0_C2_EXCHANGE(C0_C2_CHANGE_DISABLE));
- return 0;
- } else if ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) &&
- (vpara->color_limit_range == COLOR_LIMIT_RANGE_16_235)) {
- csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_ENABLE;
- }
- }
-
- switch (vpara->vic) {
- case HDMI_720x480i_60Hz_4_3:
- case HDMI_720x576i_50Hz_4_3:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x576p_50Hz_4_3:
- case HDMI_720x480i_60Hz_16_9:
- case HDMI_720x576i_50Hz_16_9:
- case HDMI_720x480p_60Hz_16_9:
- case HDMI_720x576p_50Hz_16_9:
- if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
- && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
- csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_ENABLE;
- } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
- && vpara->output_color == VIDEO_OUTPUT_RGB444) {
-#ifdef AUTO_DEFINE_CSC
- csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
- auto_csc = AUTO_CSC_ENABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_DISABLE;
-#else
- csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_ENABLE;
- csc_enable = v_CSC_ENABLE;
-#endif
- }
- break;
- default:
- if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
- && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
- csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_ENABLE;
- } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
- && vpara->output_color == VIDEO_OUTPUT_RGB444) {
-#ifdef AUTO_DEFINE_CSC
- csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
- auto_csc = AUTO_CSC_ENABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_DISABLE;
-#else
- csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;//CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_ENABLE;
- csc_enable = v_CSC_ENABLE;
-#endif
- }
- break;
- }
-
- coeff = coeff_csc[csc_mode];
- for (i = 0; i < 24; i++) {
- hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
- }
-
- value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(auto_csc) | v_VIDEO_C0_C2_EXCHANGE(c0_c2_change));
-
-#if 0
- if (vpara->input_color != vpara->output_color) {
- if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb2yuv*/
- coeff = coeff_csc[3];
- for (i = 0; i < 24; i++) {
- hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
- }
-
- value = v_SOF_DISABLE | v_CSC_ENABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
- } else {/*yuv2rgb*/
-#ifdef AUTO_DEFINE_CSC
- value = v_SOF_DISABLE | v_CSC_DISABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(1) | v_VIDEO_C0_C2_EXCHANGE(1));
-#else
- if(hdmi_drv->lcdc->cur_screen->mode.xres <= 576)/*x <= 576,REC-601*/ {
- coeff = coeff_csc[0];
- printk("xres<=576,xres=%d\n",hdmi_drv->lcdc->cur_screen->mode.xres);
- } else/*x > 576,REC-709*/{
- coeff = coeff_csc[2];
- printk("xres>576,xres=%d\n",hdmi_drv->lcdc->cur_screen->mode.xres);
- }
- for (i = 0; i < 24; i++) {
- hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
- }
-
- value = v_SOF_DISABLE | v_CSC_ENABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(0));
-#endif
- }
- } else {
- if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb[0:255]->rbg[16:235]*/
- coeff = coeff_csc[5];
- for (i = 0; i < 24; i++) {
- hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
- }
-
- value = v_SOF_DISABLE | v_CSC_ENABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
- } else {
- value = v_SOF_DISABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
- hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
- v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
- }
- }
-#endif
- return 0;
-}
-
-static void rk3036_hdmi_config_avi(struct hdmi *hdmi_drv,
- unsigned char vic, unsigned char output_color)
-{
- int i;
- int avi_color_mode;
- char info[SIZE_AVI_INFOFRAME];
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- memset(info, 0, SIZE_AVI_INFOFRAME);
- hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
- info[0] = 0x82;
- info[1] = 0x02;
- info[2] = 0x0D;
- info[3] = info[0] + info[1] + info[2];
-
- if (output_color == VIDEO_OUTPUT_RGB444)
- avi_color_mode = AVI_COLOR_MODE_RGB;
- else if(output_color == VIDEO_OUTPUT_YCBCR444)
- avi_color_mode = AVI_COLOR_MODE_YCBCR444;
- else if(output_color == VIDEO_OUTPUT_YCBCR422)
- avi_color_mode = AVI_COLOR_MODE_YCBCR422;
-
- info[4] = (avi_color_mode << 5);
- info[5] =
- (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) |
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
- info[6] = 0;
- info[7] = vic;
- if ((vic == HDMI_720X480I_60HZ_VIC) || (vic == HDMI_720X576I_50HZ_VIC))
- info[8] = 1;
- else
- info[8] = 0;
-
- /* Calculate AVI InfoFrame ChecKsum */
- for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
- hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk3036_hdmi_config_video(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- struct fb_videomode *mode;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- int val;
-
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __func__);
-
- if (vpara == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] input parameter error\n",
- __func__);
- return -1;
- }
-
- if (hdmi_drv->data->soc_type == HDMI_SOC_RK3036) {
- vpara->input_color = VIDEO_INPUT_COLOR_RGB;
- /*vpara->output_color = VIDEO_OUTPUT_RGB444;*//*rk3036 vop only can output rgb fmt*/
- } else if (hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
- /* rk3128 vop can output yuv444 fmt */
- /*if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
- vpara->output_color = VIDEO_OUTPUT_YCBCR444;
- else
- vpara->output_color = VIDEO_OUTPUT_RGB444;*/
- }
-
-/* if (hdmi_drv->pwr_mode == LOWER_PWR)
- rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-*/
- /* Disable video and audio output */
- hdmi_msk_reg(hdmi_dev, AV_MUTE,
- m_AUDIO_MUTE | m_VIDEO_BLACK,
- v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
-
- /* Input video mode is SDR RGB24bit, Data enable signal from external */
- hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
- v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
- v_DE_EXTERNAL);
- val = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
- v_VIDEO_OUTPUT_FORMAT(vpara->output_color & 0x3) |
- v_VIDEO_INPUT_CSP(vpara->input_color && 0x1);
- hdmi_writel(hdmi_dev, VIDEO_CONTRL2,val);
-
- /* Set HDMI Mode */
- hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
-
- /* Enable or disalbe color space convert */
- rk3036_hdmi_video_csc(hdmi_drv, vpara);
-
- /* Set ext video timing */
-#if 1
- hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if (mode == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
- vpara->vic);
- return -ENOENT;
- }
- hdmi_drv->tmdsclk = mode->pixclock;
-#else
- value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
- if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
- value |= v_HSYNC_POLARITY(1);
- if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
- value |= v_VSYNC_POLARITY(1);
- hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
-
- value = mode->left_margin + mode->xres + mode->right_margin +
- mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->right_margin + mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
-
- value = mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->yres + mode->lower_margin +
- mode->vsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
-
- if (vpara->vic == HDMI_720x480p_60Hz_4_3 ||
- vpara->vic == HDMI_720x480p_60Hz_16_9)
- value = 42;
- else
- value = mode->upper_margin + mode->vsync_len;
-
- hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
-
- value = mode->vsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
-#endif
- if (vpara->output_mode == OUTPUT_HDMI) {
- rk3036_hdmi_config_avi(hdmi_drv, vpara->vic,
- vpara->output_color);
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __func__);
- } else {
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __func__);
- }
-
- /* rk3028a */
- hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
- hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
- hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
-
- return 0;
-}
-
-static void rk3036_hdmi_config_aai(struct hdmi *hdmi_drv)
-{
- int i;
- char info[SIZE_AUDIO_INFOFRAME];
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- memset(info, 0, SIZE_AUDIO_INFOFRAME);
-
- info[0] = 0x84;
- info[1] = 0x01;
- info[2] = 0x0A;
-
- info[3] = info[0] + info[1] + info[2];
- for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
- for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
- hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk3036_hdmi_config_audio(struct hdmi *hdmi_drv,
- struct hdmi_audio *audio)
-{
- int rate, N, channel, mclk_fs;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (audio->channel < 3)
- channel = I2S_CHANNEL_1_2;
- else if (audio->channel < 5)
- channel = I2S_CHANNEL_3_4;
- else if (audio->channel < 7)
- channel = I2S_CHANNEL_5_6;
- else
- channel = I2S_CHANNEL_7_8;
-
- switch (audio->rate) {
- case HDMI_AUDIO_FS_32000:
- rate = AUDIO_32K;
- N = N_32K;
- mclk_fs = MCLK_384FS;
- break;
- case HDMI_AUDIO_FS_44100:
- rate = AUDIO_441K;
- N = N_441K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_48000:
- rate = AUDIO_48K;
- N = N_48K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_88200:
- rate = AUDIO_882K;
- N = N_882K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_96000:
- rate = AUDIO_96K;
- N = N_96K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_176400:
- rate = AUDIO_1764K;
- N = N_1764K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_192000:
- rate = AUDIO_192K;
- N = N_192K;
- mclk_fs = MCLK_128FS;
- break;
- default:
- dev_err(hdmi_drv->dev, "[%s] not support such sample rate %d\n",
- __func__, audio->rate);
- return -ENOENT;
- }
-
- /* set_audio source I2S */
- if (HDMI_CODEC_SOURCE_SELECT == INPUT_IIS) {
- hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
- hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
- hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
- v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel));
- hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
- /* no swap */
- hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
- } else {
- hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
- /* no swap */
- hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
- }
-
- /* Set N value */
- hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
- hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
- hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
- rk3036_hdmi_config_aai(hdmi_drv);
-
- return 0;
-}
-
-void rk3036_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
-{
- int mutestatus = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- if (hdmi_drv->uboot_logo) {
- hdmi_drv->uboot_logo = 0;
- return;
- }
-
- if (enable) {
- if (hdmi_drv->pwr_mode == LOWER_PWR)
- rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-
- rk3036_hdmi_sys_power(hdmi_drv, true);
- rk3036_hdmi_sys_power(hdmi_drv, false);
- delay100us();
- rk3036_hdmi_sys_power(hdmi_drv, true);
- hdmi_writel(hdmi_dev, 0xce, 0x00);
- delay100us();
- hdmi_writel(hdmi_dev, 0xce, 0x01);
-
- hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
- if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
- hdmi_msk_reg(hdmi_dev, AV_MUTE,
- m_AUDIO_MUTE | m_VIDEO_BLACK,
- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
- }
- rk3036_hdmi_av_mute(hdmi_drv, 0);
- } else {
- hdmi_msk_reg(hdmi_dev, AV_MUTE,
- m_AUDIO_MUTE | m_VIDEO_BLACK,
- v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
- rk3036_hdmi_av_mute(hdmi_drv, 1);
- msleep(100);
- rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
- }
-}
-
-int rk3036_hdmi_removed(struct hdmi *hdmi_drv)
-{
- dev_info(hdmi_drv->dev, "Removed.\n");
- if (hdmi_drv->hdcp_power_off_cb)
- hdmi_drv->hdcp_power_off_cb();
- rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
-
- return HDMI_ERROR_SUCESS;
-}
-
-void rk3036_hdmi_irq(struct hdmi *hdmi_drv)
-{
- u32 interrupt = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
- if(interrupt) {
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
- dev_info(hdmi_drv->dev, "Clear edid irq.\n");
- }
-
- hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
- if(interrupt) {
- hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
- }
- if (interrupt & m_INT_HOTPLUG) {
- if (hdmi_drv->state == HDMI_SLEEP)
- hdmi_drv->state = WAIT_HOTPLUG;
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(20));
-
- }/*plug out*/
-
- if (hdmi_drv->hdcp_irq_cb)
- hdmi_drv->hdcp_irq_cb(0);
- if (hdmi_drv->cec_irq)
- hdmi_drv->cec_irq();
-}
-
-static void rk3036_hdmi_reset(struct hdmi *hdmi_drv)
-{
- u32 val = 0;
- u32 msk = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
- delay100us();
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
- delay100us();
- msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
- val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
-
- rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
-}
-static int rk3036_hdmi_debug(struct hdmi *hdmi_drv,int cmd)
-{
- switch(cmd) {
- case 0:
- printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
- rk3036_hdmi_irq(hdmi_drv);
- break;
- case 1:
- printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
- break;
- default:
- printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
- break;
- }
- return 0;
-}
-
-static struct rk_hdmi_drv_ops hdmi_drv_ops = {
- .hdmi_debug = rk3036_hdmi_debug,
-};
-
-int rk3036_hdmi_initial(struct hdmi *hdmi_drv)
-{
- int rc = HDMI_ERROR_SUCESS;
-
- hdmi_drv->pwr_mode = NORMAL;
- hdmi_drv->remove = rk3036_hdmi_removed;
- hdmi_drv->control_output = rk3036_hdmi_control_output;
- hdmi_drv->config_video = rk3036_hdmi_config_video;
- hdmi_drv->config_audio = rk3036_hdmi_config_audio;
- hdmi_drv->detect_hotplug = rk3036_hdmi_detect_hotplug;
- hdmi_drv->read_edid = rk3036_hdmi_read_edid;
- hdmi_drv->insert = rk3036_hdmi_insert;
- hdmi_drv->ops = &hdmi_drv_ops;
- hdmi_drv->support_vic = rk3036_hdmi_support_vic;
- hdmi_drv->support_vic_num = ARRAY_SIZE(rk3036_hdmi_support_vic);
-
- if (!hdmi_drv->uboot_logo) {
- rk3036_hdmi_reset_pclk();
- rk3036_hdmi_reset(hdmi_drv);
- } else {
- hdmi_drv->hotplug = rk3036_hdmi_detect_hotplug(hdmi_drv);
- if (hdmi_drv->hotplug == HDMI_HPD_REMOVED) {
- rk3036_hdmi_removed(hdmi_drv);
- hdmi_drv->state = HDMI_SLEEP;
- hdmi_drv->lcdc->uboot_logo = 0;
- hdmi_drv->uboot_logo = 0;
- }
- }
- if (hdmi_drv->hdcp_power_on_cb)
- rc = hdmi_drv->hdcp_power_on_cb();
-
- return rc;
-}
+++ /dev/null
-#ifndef _RK3036_HDMI_HW_H
-#define _RK3036_HDMI_HW_H
-
-#include <linux/rockchip/iomap.h>
-#include <linux/delay.h>
-
-enum PWR_MODE {
- NORMAL,
- LOWER_PWR,
-};
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
-};
-
-/* C0 C2 Change */
-enum {
- C0_C2_CHANGE_ENABLE, /* enable c0 c2 change*/
- C0_C2_CHANGE_DISABLE /* disable c0 c2 change*/
-};
-
-/* Auto CSC mode enable */
-enum {
- AUTO_CSC_DISABLE, /* disable auto csc*/
- AUTO_CSC_ENABLE /* enable auto csc*/
-};
-
-
-/* Color Limit Range */
-enum {
- COLOR_LIMIT_RANGE_0_255, /* Color Limit Range 0 To 255*/
- COLOR_LIMIT_RANGE_16_235, /* Color Limit Range 16 To 235*/
-};
-/* Color Space Convertion Mode */
-enum {
- CSC_ITU601_16_235_TO_RGB_0_255_8BIT, /* YCbCr 16-235 input to RGB 0-255 output according BT601 that is 8bit clolor depth */
- CSC_ITU601_0_255_TO_RGB_0_255_8BIT, /* YCbCr 0-255 input to RGB 0-255 output according BT601 that is 8bit clolor depth */
- CSC_ITU709_16_235_TO_RGB_0_255_8BIT, /* YCbCr 16-235 input to RGB 0-255 output according BT709 that is 8bit clolor depth */
- CSC_RGB_0_255_TO_ITU601_16_235_8BIT, /* RGB 0-255 input to YCbCr 16-235 output according BT601 that is 8bit clolor depth */
- CSC_RGB_0_255_TO_ITU709_16_235_8BIT, /* RGB 0-255 input to YCbCr 16-235 output accroding BT709 that is 8bit clolor depth */
- CSC_RGB_0_255_TO_RGB_16_235_8BIT, /* RGB 0-255 input to RGB 16-235 output that is 8bit clolor depth */
-};
-
-
-#define AUTO_DEFINE_CSC
-#ifdef RK616_USE_MCLK_12M
-#define HDMI_SYS_FREG_CLK 12000000
-#else
-#define HDMI_SYS_FREG_CLK 11289600
-#endif
-
-#define HDMI_SCL_RATE (100*1000)
-#define DDC_BUS_FREQ_L 0x4b
-#define DDC_BUS_FREQ_H 0x4c
-
-#define SYS_CTRL 0x00
-#define m_RST_ANALOG (1 << 6)
-#define v_RST_ANALOG (0 << 6)
-#define v_NOT_RST_ANALOG (1 << 6)
-
-#define m_RST_DIGITAL (1 << 5)
-#define v_RST_DIGITAL (0 << 5)
-#define v_NOT_RST_DIGITAL (1 << 5)
-
-#define m_REG_CLK_INV (1 << 4)
-#define v_REG_CLK_NOT_INV (0 << 4)
-#define v_REG_CLK_INV (1 << 4)
-#define m_VCLK_INV (1 << 3)
-#define v_VCLK_NOT_INV (0 << 3)
-#define v_VCLK_INV (1 << 3)
-#define m_REG_CLK_SOURCE (1 << 2)
-#define v_REG_CLK_SOURCE_TMDS (0 << 2)
-#define v_REG_CLK_SOURCE_SYS (1 << 2)
-#define m_POWER (1 << 1)
-#define v_PWR_ON (0 << 1)
-#define v_PWR_OFF (1 << 1)
-#define m_INT_POL (1 << 0)
-#define v_INT_POL_HIGH 1
-#define v_INT_POL_LOW 0
-
-#define VIDEO_CONTRL1 0x01
-#define m_VIDEO_INPUT_FORMAT (7 << 1)
-#define m_DE_SOURCE (1 << 0)
-enum {
- VIDEO_INPUT_SDR_RGB444 = 0,
- VIDEO_INPUT_DDR_RGB444 = 5,
- VIDEO_INPUT_DDR_YCBCR422 = 6
-};
-#define v_VIDEO_INPUT_FORMAT(n) (n << 1)
-#define v_DE_EXTERNAL 1
-#define v_DE_INTERANL 0
-
-#define VIDEO_CONTRL2 0x02
-#define m_VIDEO_OUTPUT_FORMAT (3 << 6)
-#define m_VIDEO_INPUT_BITS (3 << 4)
-#define m_VIDEO_INPUT_CSP (1 << 0)
-#define v_VIDEO_OUTPUT_FORMAT(n) (((n)&0x3) << 6)
-#define v_VIDEO_INPUT_BITS(n) (n << 4)
-#define v_VIDEO_INPUT_CSP(n) (n << 0)
-
-enum {
- VIDEO_INPUT_12BITS = 0,
- VIDEO_INPUT_10BITS,
- VIDEO_INPUT_REVERT,
- VIDEO_INPUT_8BITS
-};
-#define VIDEO_CONTRL 0x03
-#define m_VIDEO_AUTO_CSC (1 << 7)
-#define v_VIDEO_AUTO_CSC(n) (n << 7)
-#define m_VIDEO_C0_C2_EXCHANGE (1 << 0)
-#define v_VIDEO_C0_C2_EXCHANGE(n) (n << 0)
-
-
-#define VIDEO_CONTRL3 0x04
-#define m_COLOR_DEPTH_NOT_INDICATED (1 << 4)
-#define m_SOF (1 << 3)
-#define m_COLOR_RANGE (1 << 2)
-#define m_CSC (1 << 0)
-#define v_COLOR_DEPTH_NOT_INDICATED(n) ((n) << 4) /*1: Force GCP CD[3:0] zero
- 0: GCP CD[3:0] according
- color depth*/
-#define v_SOF_ENABLE (0 << 3)
-#define v_SOF_DISABLE (1 << 3)
-#define v_COLOR_RANGE_FULL (1 << 2)
-#define v_COLOR_RANGE_LIMITED (0 << 2)
-#define v_CSC_ENABLE 1
-#define v_CSC_DISABLE 0
-
-#define AV_MUTE 0x05
-#define m_AVMUTE_CLEAR (1 << 7)
-#define m_AVMUTE_ENABLE (1 << 6)
-#define m_AUDIO_MUTE (1 << 1)
-#define m_VIDEO_BLACK (1 << 0)
-#define v_AVMUTE_CLEAR(n) (n << 7)
-#define v_AVMUTE_ENABLE(n) (n << 6)
-#define v_AUDIO_MUTE(n) (n << 1)
-#define v_VIDEO_MUTE(n) (n << 0)
-
-#define VIDEO_TIMING_CTL 0x08
-#define v_HSYNC_POLARITY(n) (n << 3)
-#define v_VSYNC_POLARITY(n) (n << 2)
-#define v_INETLACE(n) (n << 1)
-#define v_EXTERANL_VIDEO(n) (n << 0)
-
-#define VIDEO_EXT_HTOTAL_L 0x09
-#define VIDEO_EXT_HTOTAL_H 0x0a
-#define VIDEO_EXT_HBLANK_L 0x0b
-#define VIDEO_EXT_HBLANK_H 0x0c
-#define VIDEO_EXT_HDELAY_L 0x0d
-#define VIDEO_EXT_HDELAY_H 0x0e
-#define VIDEO_EXT_HDURATION_L 0x0f
-#define VIDEO_EXT_HDURATION_H 0x10
-#define VIDEO_EXT_VTOTAL_L 0x11
-#define VIDEO_EXT_VTOTAL_H 0x12
-#define VIDEO_EXT_VBLANK 0x13
-#define VIDEO_EXT_VDELAY 0x14
-#define VIDEO_EXT_VDURATION 0x15
-
-#define VIDEO_CSC_COEF 0x18
-
-
-#define AUDIO_CTRL1 0x35
-enum {
- CTS_SOURCE_INTERNAL = 0,
- CTS_SOURCE_EXTERNAL
-};
-#define v_CTS_SOURCE(n) (n << 7)
-enum {
- DOWNSAMPLE_DISABLE = 0,
- DOWNSAMPLE_1_2,
- DOWNSAMPLE_1_4
-};
-#define v_DOWN_SAMPLE(n) (n << 5)
-enum {
- AUDIO_SOURCE_IIS = 0,
- AUDIO_SOURCE_SPDIF
-};
-#define v_AUDIO_SOURCE(n) (n << 3)
-#define v_MCLK_ENABLE(n) (n << 2)
-enum {
- MCLK_128FS = 0,
- MCLK_256FS,
- MCLK_384FS,
- MCLK_512FS
-};
-#define v_MCLK_RATIO(n) (n)
-
-#define AUDIO_SAMPLE_RATE 0x37
-enum {
- AUDIO_32K = 0x3,
- AUDIO_441K = 0x0,
- AUDIO_48K = 0x2,
- AUDIO_882K = 0x8,
- AUDIO_96K = 0xa,
- AUDIO_1764K = 0xc,
- AUDIO_192K = 0xe,
-};
-
-#define AUDIO_I2S_MODE 0x38
-enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
-};
-#define v_I2S_CHANNEL(n) ((n) << 2)
-enum {
- I2S_STANDARD = 0,
- I2S_LEFT_JUSTIFIED,
- I2S_RIGHT_JUSTIFIED
-};
-#define v_I2S_MODE(n) (n)
-
-#define AUDIO_I2S_MAP 0x39
-#define AUDIO_I2S_SWAPS_SPDIF 0x3a
-#define v_SPIDF_FREQ(n) (n)
-
-#define N_32K 0x1000
-#define N_441K 0x1880
-#define N_882K 0x3100
-#define N_1764K 0x6200
-#define N_48K 0x1800
-#define N_96K 0x3000
-#define N_192K 0x6000
-
-#define AUDIO_N_H 0x3f
-#define AUDIO_N_M 0x40
-#define AUDIO_N_L 0x41
-
-#define AUDIO_CTS_H 0x45
-#define AUDIO_CTS_M 0x46
-#define AUDIO_CTS_L 0x47
-
-#define DDC_CLK_L 0x4b
-#define DDC_CLK_H 0x4c
-
-#define EDID_SEGMENT_POINTER 0x4d
-#define EDID_WORD_ADDR 0x4e
-#define EDID_FIFO_OFFSET 0x4f
-#define EDID_FIFO_ADDR 0x50
-
-
-#define PACKET_SEND_MANUAL 0x9c
-#define PACKET_SEND_AUTO 0x9d
- #define m_PACKET_GCP_EN (1 << 7)
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX 0x9f
-enum {
- INFOFRAME_AVI = 0x06,
- INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_ADDR 0xa0
-
-#define SIZE_AVI_INFOFRAME 0x11 /* 14 bytes */
-#define SIZE_AUDIO_INFOFRAME 0x0F /* 15 bytes */
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-
-#define HDCP_CTRL 0x52
-#define m_HDMI_DVI (1 << 1)
-#define v_HDMI_DVI(n) (n << 1)
-
-#define INTERRUPT_MASK1 0xc0
-#define INTERRUPT_STATUS1 0xc1
-#define m_INT_ACTIVE_VSYNC (1 << 5)
-#define m_INT_EDID_READY (1 << 2)
-
-#define INTERRUPT_MASK2 0xc2
-#define INTERRUPT_STATUS2 0xc3
-#define m_INT_HDCP_ERR (1 << 7)
-#define m_INT_BKSV_FLAG (1 << 6)
-#define m_INT_HDCP_OK (1 << 4)
-
-#define HDMI_STATUS 0xc8
- #define m_HOTPLUG (1 << 7)
- #define m_MASK_INT_HOTPLUG (1 << 5)
- #define m_INT_HOTPLUG (1 << 1)
-
-
-#define HDMI_COLORBAR 0xc9
-
-#define PHY_SYNC 0xce /* sync phy parameter */
-#define PHY_SYS_CTL 0xe0
-#define m_TMDS_CLK_SOURCE (1 << 5)
-#define v_TMDS_FROM_PLL (0 << 5)
-#define v_TMDS_FROM_GEN (1 << 5)
-#define m_PHASE_CLK (1 << 4)
-#define v_DEFAULT_PHASE (0 << 4)
-#define v_SYNC_PHASE (1 << 4)
-#define m_TMDS_CURRENT_PWR (1 << 3)
-#define v_TURN_ON_CURRENT (0 << 3)
-#define v_CAT_OFF_CURRENT (1 << 3)
-#define m_BANDGAP_PWR (1 << 2)
-#define v_BANDGAP_PWR_UP (0 << 2)
-#define v_BANDGAP_PWR_DOWN (1 << 2)
-#define m_PLL_PWR (1 << 1)
-#define v_PLL_PWR_UP (0 << 1)
-#define v_PLL_PWR_DOWN (1 << 1)
-#define m_TMDS_CHG_PWR (1 << 0)
-#define v_TMDS_CHG_PWR_UP (0 << 0)
-#define v_TMDS_CHG_PWR_DOWN (1 << 0)
-
-#define PHY_CHG_PWR 0xe1
-#define v_CLK_CHG_PWR(n) ((n & 1) << 3)
-#define v_DATA_CHG_PWR(n) ((n & 7) << 0)
-
-#define PHY_DRIVER 0xe2
-#define v_CLK_MAIN_DRIVER(n) (n << 4)
-#define v_DATA_MAIN_DRIVER(n) (n << 0)
-
-#define PHY_PRE_EMPHASIS 0xe3
-#define v_PRE_EMPHASIS(n) ((n & 7) << 4)
-#define v_CLK_PRE_DRIVER(n) ((n & 3) << 2)
-#define v_DATA_PRE_DRIVER(n) ((n & 3) << 0)
-
-#define PHY_FEEDBACK_DIV_RATIO_LOW 0xe7
-#define v_FEEDBACK_DIV_LOW(n) (n & 0xff)
-#define PHY_FEEDBACK_DIV_RATIO_HIGH 0xe8
-#define v_FEEDBACK_DIV_HIGH(n) (n & 1)
-
-#define PHY_PRE_DIV_RATIO 0xed
-#define v_PRE_DIV_RATIO(n) (n & 0x1f)
-
-
-/*-----START----- HDMI CEC CTRL------START------*/
-#define CEC_CTRL 0xd0
- #define m_ADJUST_FOR_HISENSE (1 << 6)
- #define m_REJECT_RX_BROADCAST (1 << 5)
- #define m_BUSFREETIME_ENABLE (1 << 2)
- #define m_REJECT_RX (1 << 1)
- #define m_START_TX (1 << 0)
-
-#define CEC_DATA 0xd1
-#define CEC_TX_OFFSET 0xd2
-#define CEC_RX_OFFSET 0xd3
-#define CEC_CLK_H 0xd4
-#define CEC_CLK_L 0xd5
-#define CEC_TX_LENGTH 0xd6
-#define CEC_RX_LENGTH 0xd7
-#define CEC_TX_INT_MASK 0xd8
- #define m_TX_DONE (1 << 3)
- #define m_TX_NOACK (1 << 2)
- #define m_TX_BROADCAST_REJ (1 << 1)
- #define m_TX_BUSNOTFREE (1 << 0)
-
-#define CEC_RX_INT_MASK 0xd9
- #define m_RX_LA_ERR (1 << 4)
- #define m_RX_GLITCH (1 << 3)
- #define m_RX_DONE (1 << 0)
-
-#define CEC_TX_INT 0xda
-#define CEC_RX_INT 0xdb
-#define CEC_BUSFREETIME_L 0xdc
-#define CEC_BUSFREETIME_H 0xdd
-#define CEC_LOGICADDR 0xde
-/*------END------ HDMI CEC CTRL------END-------*/
-
-
-static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 *val)
-{
- int ret = 0;
-
- *val = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-static inline int hdmi_writel(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 val)
-{
- int ret = 0;
-
- writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 msk, u32 val)
-{
- int ret = 0;
- u32 temp;
-
- temp = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
- writel_relaxed(temp | ((val) & (msk)), hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-static inline void rk3036_hdmi_reset_pclk(void)
-{
- writel_relaxed(0x00010001, RK_CRU_VIRT + 0x128);
- msleep(100);
- writel_relaxed(0x00010000, RK_CRU_VIRT + 0x128);
-}
-
-extern int rk3036_hdmi_initial(struct hdmi *hdmi);
-extern void rk3036_hdmi_irq(struct hdmi *hdmi);
-
-#endif
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-
-obj-$(CONFIG_HDMI_RK3288) += rk3288_hdmi_hw.o rk3288_hdmi.o
-#obj-$(CONFIG_HDCP_RK3288) += hdcp/
+++ /dev/null
-/*
- * drivers/video/rockchip/hdmi/chips/rk3288/rk3188_hdmi.c
- *
- * Copyright (C) 2014 ROCKCHIP, Inc.
- *Author:zwl<zwl@rock-chips.com>
- *This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/uaccess.h>
-#include <linux/rockchip/grf.h>
-#include <linux/rockchip/iomap.h>
-#if defined(CONFIG_OF)
-#include <linux/of.h>
-#include <linux/of_device.h>
-#endif
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#endif
-
-#include "rk3288_hdmi_hw.h"
-#include "rk3288_hdmi.h"
-
-#define grf_readl(offset) readl_relaxed(RK_GRF_VIRT + offset)
-#define grf_writel(v, offset) \
-do { \
- writel_relaxed(v, RK_GRF_VIRT + offset); \
- dsb(); \
-} while (0)
-#define HDMI_PD_ON (1 << 0)
-#define HDMI_PCLK_ON (1 << 1)
-#define HDMI_HDCPCLK_ON (1 << 2)
-
-
-static struct rk3288_hdmi_device *hdmi_dev;
-
-#if defined(CONFIG_DEBUG_FS)
-static const struct rk3288_hdmi_reg_table hdmi_reg_table[] = {
- {IDENTIFICATION_BASE, CONFIG3_ID},
- {INTERRUPT_BASE, IH_MUTE},
- {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
- {VIDEO_PACKETIZER_BASE, VP_MASK},
- {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
- {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
- {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
- {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
- {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
- {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
- {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
- {HDCP_BKSV_BASE, HDCPREG_BKSV4},
- {HDCP_AN_BASE, HDCPREG_AN7},
- {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
- {CEC_ENGINE_BASE, CEC_WKUPCTRL},
- {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
-};
-
-static int rk3288_hdmi_reg_show(struct seq_file *s, void *v)
-{
- int i = 0, j = 0;
- u32 val = 0;
-
- seq_puts(s, "\n>>>hdmi_ctl reg");
- for (i = 0; i < 16; i++)
- seq_printf(s, " %2x", i);
-
- seq_puts(s,
- "\n-----------------------------------------------------------------");
-
- for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
- for (j = hdmi_reg_table[i].reg_base;
- j <= hdmi_reg_table[i].reg_end; j++) {
- val = hdmi_readl(hdmi_dev, j);
- if ((j - hdmi_reg_table[i].reg_base) % 16 == 0)
- seq_printf(s, "\n>>>hdmi_ctl %2x:", j);
- seq_printf(s, " %02x", val);
-
- }
- }
- seq_puts(s,
- "\n-----------------------------------------------------------------\n");
-
- return 0;
-}
-
-static ssize_t rk3288_hdmi_reg_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- u32 reg;
- u32 val;
- char kbuf[25];
-
- if (copy_from_user(kbuf, buf, count))
- return -EFAULT;
- sscanf(kbuf, "%x%x", ®, &val);
- if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
- dev_info(hdmi_dev->dev, "it is no hdmi reg\n");
- return count;
- }
- dev_info(hdmi_dev->dev, "/**********rk3288 hdmi reg config******/");
- dev_info(hdmi_dev->dev, "\n reg=%x val=%x\n", reg, val);
- hdmi_writel(hdmi_dev, reg, val);
-
- return count;
-}
-
-static int rk3288_hdmi_reg_open(struct inode *inode, struct file *file)
-{
- struct rk3288_hdmi_device *hdmi_dev = inode->i_private;
-
- return single_open(file, rk3288_hdmi_reg_show, hdmi_dev);
-}
-
-static const struct file_operations rk3288_hdmi_reg_fops = {
- .owner = THIS_MODULE,
- .open = rk3288_hdmi_reg_open,
- .read = seq_read,
- .write = rk3288_hdmi_reg_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-struct hdmi *rk3288_hdmi_register_hdcp_callbacks(void (*hdcp_cb) (void),
- void (*hdcp_irq_cb) (int status),
- int (*hdcp_power_on_cb) (void),
- void (*hdcp_power_off_cb) (void))
-{
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev == NULL)
- return NULL;
-
- hdmi_drv = &hdmi_dev->driver;
- hdmi_drv->hdcp_cb = hdcp_cb;
- hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
- hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
- hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
-
- return hdmi_drv;
-}
-
-#ifdef HDMI_INT_USE_POLL
-#define HDMI_POLL_MDELAY 100
-static void rk3288_poll_delay_work(struct work_struct *work)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv->suspend == 0) {
- if (hdmi_drv->enable == 1)
- hdmi_irq(0, hdmi_drv);
-
- if (hdmi_dev->irq == 0)
- queue_delayed_work(hdmi_drv->workqueue,
- &hdmi_dev->delay_work,
- msecs_to_jiffies(HDMI_POLL_MDELAY));
- }
-}
-#endif
-
-static int rk3288_hdmi_clk_enable(struct rk3288_hdmi_device *hdmi_dev)
-{
- if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->clk_on & HDMI_PCLK_ON)
- && (hdmi_dev->clk_on & HDMI_HDCPCLK_ON))
- return 0;
-
- if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0) {
- if (hdmi_dev->pd == NULL) {
- hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
- if (IS_ERR(hdmi_dev->pd)) {
- dev_err(hdmi_dev->dev,
- "Unable to get hdmi pd\n");
- return -1;
- }
- }
- clk_prepare_enable(hdmi_dev->pd);
- hdmi_dev->clk_on |= HDMI_PD_ON;
- }
-
- if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
- if (hdmi_dev->pclk == NULL) {
- hdmi_dev->pclk =
- devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
- if (IS_ERR(hdmi_dev->pclk)) {
- dev_err(hdmi_dev->dev,
- "Unable to get hdmi pclk\n");
- return -1;
- }
- }
- clk_prepare_enable(hdmi_dev->pclk);
- hdmi_dev->clk_on |= HDMI_PCLK_ON;
- }
-
- if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
- if (hdmi_dev->hdcp_clk == NULL) {
- hdmi_dev->hdcp_clk =
- devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
- if (IS_ERR(hdmi_dev->hdcp_clk)) {
- dev_err(hdmi_dev->dev,
- "Unable to get hdmi hdcp_clk\n");
- return -1;
- }
- }
- clk_prepare_enable(hdmi_dev->hdcp_clk);
- hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
- }
-
- return 0;
-}
-
-static int rk3288_hdmi_clk_disable(struct rk3288_hdmi_device *hdmi_dev)
-{
- if (hdmi_dev->clk_on == 0)
- return 0;
-
- if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->pd != NULL)) {
- clk_disable_unprepare(hdmi_dev->pd);
- hdmi_dev->clk_on &= ~HDMI_PD_ON;
- }
-
- if ((hdmi_dev->clk_on & HDMI_PCLK_ON) && (hdmi_dev->pclk != NULL)) {
- clk_disable_unprepare(hdmi_dev->pclk);
- hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
- }
-
- if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON)
- && (hdmi_dev->hdcp_clk != NULL)) {
- clk_disable_unprepare(hdmi_dev->hdcp_clk);
- hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
- }
-
- return 0;
-}
-
-static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
-{
- int ret = 0;
- struct rk_screen screen;
-
- rk_fb_get_prmry_screen(&screen);
-
- /* hdmi is extend as default,TODO modify if hdmi is primary */
- hdmi_dev->lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;
- /* lcdc source select */
- grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id), RK3288_GRF_SOC_CON6);
- if (hdmi_dev->lcdc_id == 0)
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
- else
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
- if (IS_ERR(hdmi_drv->lcdc)) {
- dev_err(hdmi_drv->dev,
- "can not connect to video source lcdc\n");
- ret = -ENXIO;
- return ret;
- }
-
- hdmi_drv->xscale = 100;
- hdmi_drv->yscale = 100;
-
- spin_lock_init(&hdmi_drv->irq_lock);
- mutex_init(&hdmi_drv->enable_mutex);
-
- rk3288_hdmi_initial(hdmi_drv);
- hdmi_sys_init(hdmi_drv);
- hdmi_drv_register(hdmi_drv);
-
- return ret;
-}
-
-static void rk3288_hdmi_early_suspend(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv->suspend)
- return;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi enter early suspend pwr %d state %d\n",
- hdmi_drv->pwr_mode, hdmi_drv->state);
- flush_delayed_work(&hdmi_drv->delay_work);
- mutex_lock(&hdmi_drv->enable_mutex);
- hdmi_drv->suspend = 1;
- if (!hdmi_drv->enable) {
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
- }
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- hdmi_drv->command = HDMI_CONFIG_ENABLE;
- init_completion(&hdmi_drv->complete);
- hdmi_drv->wait = 1;
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, 0);
- wait_for_completion_interruptible_timeout(&hdmi_drv->complete,
- msecs_to_jiffies(5000));
- flush_delayed_work(&hdmi_drv->delay_work);
-
- /* iomux to gpio and pull down when suspend */
- pinctrl_select_state(hdmi_dev->dev->pins->p,
- hdmi_dev->dev->pins->sleep_state);
- rk3288_hdmi_clk_disable(hdmi_dev);
- return;
-}
-
-static void rk3288_hdmi_early_resume(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (!hdmi_drv->suspend)
- return;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi enter early resume\n");
- /* iomux to default state for hdmi use when resume */
- pinctrl_select_state(hdmi_dev->dev->pins->p,
- hdmi_dev->dev->pins->default_state);
- rk3288_hdmi_clk_enable(hdmi_dev);
- mutex_lock(&hdmi_drv->enable_mutex);
- hdmi_drv->suspend = 0;
- rk3288_hdmi_initial(hdmi_drv);
- if (hdmi_dev->irq == 0) {
-#ifdef HDMI_INT_USE_POLL
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->delay_work,
- msecs_to_jiffies(5));
-#endif
- } else if (hdmi_drv->enable) {
- enable_irq(hdmi_drv->irq);
- }
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(10));
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
-}
-
-static int rk3288_hdmi_fb_event_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- struct fb_event *event = data;
- int blank_mode = *((int *)event->data);
-
- if (action == FB_EARLY_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- break;
- default:
- rk3288_hdmi_early_suspend();
- break;
- }
- } else if (action == FB_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- rk3288_hdmi_early_resume();
- break;
- default:
- break;
- }
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block rk3288_hdmi_fb_notifier = {
- .notifier_call = rk3288_hdmi_fb_event_notify,
-};
-
-#if defined(CONFIG_OF)
-static int rk3288_hdmi_parse_dt(struct rk3288_hdmi_device *hdmi_dev)
-{
- int val = 0;
- struct device_node *np = hdmi_dev->dev->of_node;
-
- if (!of_property_read_u32(np, "rockchips,hdmi_audio_source", &val))
- hdmi_dev->driver.audio.type = val;
-
- return 0;
-}
-
-static const struct of_device_id rk3288_hdmi_dt_ids[] = {
- {.compatible = "rockchip,rk3288-hdmi",},
- {}
-};
-#endif
-
-static int rk3288_hdmi_probe(struct platform_device *pdev)
-{
- int ret;
- struct resource *res;
- struct hdmi *dev_drv = NULL;
-
- hdmi_dev = kzalloc(sizeof(struct rk3288_hdmi_device), GFP_KERNEL);
- if (!hdmi_dev) {
- dev_err(&pdev->dev, ">>rk3288_hdmi_device kzalloc fail!");
- return -ENOMEM;
- }
-
- hdmi_dev->dev = &pdev->dev;
- platform_set_drvdata(pdev, hdmi_dev);
- mutex_init(&hdmi_dev->int_mutex);
-
- rk3288_hdmi_parse_dt(hdmi_dev);
- /* TODO Daisen wait to add cec iomux */
-
- /* enable pd and pclk and hdcp_clk */
- if (rk3288_hdmi_clk_enable(hdmi_dev) < 0)
- goto err0;
-
- /* request and remap iomem */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(hdmi_dev->dev, "Unable to get register resource\n");
- ret = -ENXIO;
- goto err0;
- }
- hdmi_dev->regbase_phy = res->start;
- hdmi_dev->regsize_phy = resource_size(res);
- hdmi_dev->regbase = devm_ioremap_resource(hdmi_dev->dev, res);
- if (IS_ERR(hdmi_dev->regbase)) {
- ret = PTR_ERR(hdmi_dev->regbase);
- dev_err(hdmi_dev->dev, "cannot ioremap registers,err=%d\n",
- ret);
- goto err0;
- }
-
- /*init hdmi driver */
- dev_drv = &hdmi_dev->driver;
- dev_drv->dev = &pdev->dev;
- if (rk3288_hdmi_drv_init(dev_drv))
- goto err0;
-
- dev_drv->workqueue = create_singlethread_workqueue("hdmi");
- INIT_DELAYED_WORK(&(dev_drv->delay_work), hdmi_work);
-
- hdmi_register_display_sysfs(dev_drv, NULL);
-
-#ifdef CONFIG_SWITCH
- dev_drv->switch_hdmi.name = "hdmi";
- switch_dev_register(&(dev_drv->switch_hdmi));
-#endif
-
- fb_register_client(&rk3288_hdmi_fb_notifier);
-
-#ifndef HDMI_INT_USE_POLL
- /* get and request the IRQ */
- dev_drv->irq = platform_get_irq(pdev, 0);
- if (dev_drv->irq <= 0) {
- dev_err(hdmi_dev->dev,
- "failed to get hdmi irq resource (%d).\n",
- hdmi_dev->irq);
- ret = -ENXIO;
- goto err1;
- }
-
- ret =
- devm_request_irq(hdmi_dev->dev, dev_drv->irq, hdmi_irq, 0,
- dev_name(hdmi_dev->dev), dev_drv);
- if (ret) {
- dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
- goto err1;
- }
-#else
- hdmi_dev->irq = 0;
- INIT_DELAYED_WORK(&hdmi_dev->delay_work, rk3288_poll_delay_work);
- queue_delayed_work(dev_drv->workqueue, &hdmi_dev->delay_work,
- msecs_to_jiffies(1));
-#endif
-
-#if defined(CONFIG_DEBUG_FS)
- hdmi_dev->debugfs_dir = debugfs_create_dir("rk3288-hdmi", NULL);
- if (IS_ERR(hdmi_dev->debugfs_dir)) {
- dev_err(hdmi_dev->dev,
- "failed to create debugfs dir for rk3288 hdmi!\n");
- } else {
- debugfs_create_file("hdmi", S_IRUSR, hdmi_dev->debugfs_dir,
- hdmi_dev, &rk3288_hdmi_reg_fops);
- }
-#endif
-
- dev_info(hdmi_dev->dev, "rk3288 hdmi probe sucess.\n");
- return 0;
-
-#ifndef HDMI_INT_USE_POLL
-err1:
-#endif
- fb_unregister_client(&rk3288_hdmi_fb_notifier);
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(dev_drv->switch_hdmi));
-#endif
- hdmi_unregister_display_sysfs(dev_drv);
-
- /*
- iounmap((void*)hdmi_dev->regbase);
- release_mem_region(res->start, hdmi_dev->regsize_phy);
- */
-err0:
- rk3288_hdmi_clk_disable(hdmi_dev);
- dev_info(hdmi_dev->dev, "rk3288 hdmi probe error.\n");
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- return ret;
-}
-
-static int rk3288_hdmi_remove(struct platform_device *pdev)
-{
- struct rk3288_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev) {
- hdmi_drv = &hdmi_dev->driver;
- mutex_lock(&hdmi_drv->enable_mutex);
- if (!hdmi_drv->suspend && hdmi_drv->enable)
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- free_irq(hdmi_drv->irq, NULL);
-
- flush_workqueue(hdmi_drv->workqueue);
- destroy_workqueue(hdmi_drv->workqueue);
-
- fb_unregister_client(&rk3288_hdmi_fb_notifier);
-
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi_drv->switch_hdmi));
-#endif
- hdmi_unregister_display_sysfs(hdmi_drv);
-
- /*
- iounmap((void*)hdmi_drv->regbase);
- release_mem_region(hdmi_drv->regbase_phy,
- hdmi_drv->regsize_phy);
- */
- rk3288_hdmi_clk_disable(hdmi_dev);
- fb_destroy_modelist(&hdmi_drv->edid.modelist);
- kfree(hdmi_drv->edid.audio);
- if (hdmi_drv->edid.specs) {
- kfree(hdmi_drv->edid.specs->modedb);
- kfree(hdmi_drv->edid.specs);
- }
-
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- }
- dev_info(hdmi_dev->dev, "rk3288 hdmi removed.\n");
- return 0;
-}
-
-static void rk3288_hdmi_shutdown(struct platform_device *pdev)
-{
-
-}
-
-static struct platform_driver rk3288_hdmi_driver = {
- .probe = rk3288_hdmi_probe,
- .remove = rk3288_hdmi_remove,
- .driver = {
- .name = "rk3288-hdmi",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(rk3288_hdmi_dt_ids),
- },
- .shutdown = rk3288_hdmi_shutdown,
-};
-
-static int __init rk3288_hdmi_init(void)
-{
- return platform_driver_register(&rk3288_hdmi_driver);
-}
-
-static void __exit rk3288_hdmi_exit(void)
-{
- platform_driver_unregister(&rk3288_hdmi_driver);
-}
-
-device_initcall_sync(rk3288_hdmi_init);
-module_exit(rk3288_hdmi_exit);
+++ /dev/null
-#ifndef __RK3288_HDMI_H__
-#define __RK3288_HDMI_H__
-
-#include "../../rk_hdmi.h"
-
-
-#define ENABLE 16
-#define HDMI_SEL_LCDC(x) ((((x)&1)<<4)|(1<<(4+ENABLE)))
-
-extern irqreturn_t hdmi_irq(int irq, void *priv);
-extern struct hdmi *rk3288_hdmi_register_hdcp_callbacks(
- void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-
-
-#endif /* __RK3288_HDMI_H__ */
+++ /dev/null
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include "rk3288_hdmi_hw.h"
-
-static unsigned int rk3288_hdmi_support_vic[] = {
- HDMI_720X480P_60HZ_VIC,
- HDMI_720X576P_50HZ_VIC,
- HDMI_1280X720P_50HZ_VIC,
- HDMI_1280X720P_60HZ_VIC,
- HDMI_1920X1080P_50HZ_VIC,
- HDMI_1920X1080P_60HZ_VIC,
- HDMI_3840X2160P_24HZ_VIC,
- HDMI_3840X2160P_25HZ_VIC,
- HDMI_3840X2160P_30HZ_VIC,
- HDMI_3840X2160P_50HZ_VIC,
- HDMI_3840X2160P_60HZ_VIC
-};
-static const struct phy_mpll_config_tab PHY_MPLL_TABLE[] = { /* opmode: 0:HDMI1.4 1:HDMI2.0 */
-/* pixclock pixrepet colordepth prepdiv tmdsmhl opmode fbdiv2 fbdiv1 ref_cntrl nctrl propctrl intctrl gmpctrl */
- {27000000, 0, HDMI_COLOR_DEPTH_8BIT, 0, 0, 0, 2, 3, 0, 3, 7, 0, 3},
- {27000000, 0, HDMI_COLOR_DEPTH_10BIT, 1, 0, 0, 5, 1, 0, 3, 3, 0, 0},
- {27000000, 0, HDMI_COLOR_DEPTH_12BIT, 2, 0, 0, 3, 3, 0, 3, 3, 0, 0},
- {27000000, 0, HDMI_COLOR_DEPTH_16BIT, 3, 0, 0, 2, 3, 0, 2, 5, 0, 1},
- {74250000, 0, HDMI_COLOR_DEPTH_8BIT, 0, 0, 0, 4, 3, 3, 2, 7, 0, 3},
- {74250000, 0, HDMI_COLOR_DEPTH_10BIT, 1, 0, 0, 5, 3, 3, 2, 7, 0, 2},
- {74250000, 0, HDMI_COLOR_DEPTH_12BIT, 2, 0, 0, 1, 2, 0, 1, 7, 0, 2},
- {74250000, 0, HDMI_COLOR_DEPTH_16BIT, 3, 0, 0, 1, 3, 0, 1, 7, 0, 2},
- {148500000, 0, HDMI_COLOR_DEPTH_8BIT, 0, 0, 0, 1, 1, 0, 1, 0, 0, 3},
- {148500000, 0, HDMI_COLOR_DEPTH_10BIT, 1, 0, 0, 5, 1, 3, 1, 7, 0, 3},
- {148500000, 0, HDMI_COLOR_DEPTH_12BIT, 2, 0, 0, 1, 2, 1, 0, 7, 0, 3},
- {148500000, 0, HDMI_COLOR_DEPTH_16BIT, 3, 0, 0, 1, 1, 0, 0, 7, 0, 3},
- {297000000, 0, HDMI_COLOR_DEPTH_8BIT, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3},
- {297000000, 0, HDMI_COLOR_DEPTH_10BIT, 1, 3, 1, 5, 0, 3, 0, 7, 0, 3},
- {297000000, 0, HDMI_COLOR_DEPTH_12BIT, 2, 3, 1, 1, 2, 2, 0, 7, 0, 3},
- {297000000, 0, HDMI_COLOR_DEPTH_16BIT, 3, 3, 1, 1, 1, 0, 0, 5, 0, 3},
- {594000000, 0, HDMI_COLOR_DEPTH_8BIT, 0, 3, 1, 1, 0, 0, 0, 3, 0, 3},
-};
-
-const struct phy_mpll_config_tab *get_phy_mpll_tab(int pixClock, char pixRepet,
- char colorDepth)
-{
- int i;
-
- if (pixClock == 0)
- return NULL;
-
- for (i = 0; i < ARRAY_SIZE(PHY_MPLL_TABLE); i++) {
- if ((PHY_MPLL_TABLE[i].pix_clock == pixClock)
- && (PHY_MPLL_TABLE[i].pix_repet == pixRepet)
- && (PHY_MPLL_TABLE[i].color_depth == colorDepth))
- return &PHY_MPLL_TABLE[i];
- }
- return NULL;
-}
-
-static void rk3288_hdmi_av_mute(struct hdmi *hdmi_drv, int enable)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_msk_reg(hdmi_dev, FC_GCP, m_FC_SET_AVMUTE,
- v_FC_SET_AVMUTE(enable));
-#if 0
- /* audio mute priority: AVMUTE, sample flat, validity */
- /* AVMUTE also mutes video */
- value = enable ? 0xF : 0;
- hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_SAMPFIT,
- v_AUD_PACK_SAMPFIT(value));
-#endif
-}
-
-static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
- if (hdmi_drv->pwr_mode == mode)
- return;
-
- hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n",
- __func__, hdmi_drv->pwr_mode, mode);
-
- switch (mode) {
- case NORMAL:
- hdmi_writel(hdmi_dev, MC_CLKDIS, 0x00);
- break;
- case LOWER_PWR:
- hdmi_writel(hdmi_dev, MC_CLKDIS, 0xff);
- hdmi_msk_reg(hdmi_dev, PHY_CONF0,
- m_TMDS_EN | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
- v_TMDS_EN(0) | v_TXPWRON_SIG(0) |
- v_ENHPD_RXSENSE_SIG(1));
- break;
- default:
- hdmi_dbg(hdmi_drv->dev, "unkown hdmi pwr mode %d\n", mode);
- }
- hdmi_drv->pwr_mode = mode;
-}
-
-/* i2c master reset */
-void rk3288_hdmi_i2cm_reset(struct rk3288_hdmi_device *hdmi_dev)
-{
- hdmi_msk_reg(hdmi_dev, I2CM_SOFTRSTZ, m_I2CM_SOFTRST,
- v_I2CM_SOFTRST(0));
- udelay(100);
-}
-
-void rk3288_hdmi_reset(struct hdmi *hdmi_drv)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0x00);
- udelay(100);
- hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0xff);
- hdmi_writel(hdmi_dev, MC_SWRSTZREQ_2, 0x00);
- udelay(100);
- hdmi_writel(hdmi_dev, MC_SWRSTZREQ_2, 0x01);
-
- rk3288_hdmi_i2cm_reset(hdmi_dev);
-#if 1
- /* reset PHY */
- hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
- udelay(100);
- hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
-#endif
-
- rk3288_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
-}
-
-int rk3288_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
- u32 value = hdmi_readl(hdmi_dev, PHY_STAT0);
-
- hdmi_dbg(hdmi_drv->dev, "[%s] reg%x value %02x\n", __func__,
- PHY_STAT0, value);
-
- if ((value & m_PHY_HPD) || ((value & 0xf0) == 0xf0))
- return HDMI_HPD_ACTIVED;
- else
- return HDMI_HPD_REMOVED;
-}
-
-int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
-{
- int i = 0, n = 0, index = 0, ret = -1, trytime = 2;
- int offset = (block % 2) * 0x80;
- int interrupt = 0;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_dbg(hdmi_drv->dev, "[%s] block %d\n", __func__, block);
-
- /* Set DDC I2C CLK which devided from DDC_CLK to 100KHz */
- hdmi_writel(hdmi_dev, I2CM_SS_SCL_HCNT_0_ADDR, 0x7a);
- hdmi_writel(hdmi_dev, I2CM_SS_SCL_LCNT_0_ADDR, 0x8d);
- hdmi_msk_reg(hdmi_dev, I2CM_DIV, m_I2CM_FAST_STD_MODE,
- v_I2CM_FAST_STD_MODE(STANDARD_MODE)); /* Set Standard Mode */
-
- /* Enable I2C interrupt for reading edid */
- hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0,
- v_SCDC_READREQ_MUTE(0) | v_I2CM_DONE_MUTE(0) |
- v_I2CM_ERR_MUTE(0));
- hdmi_msk_reg(hdmi_dev, I2CM_INT, m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(0));
- hdmi_msk_reg(hdmi_dev, I2CM_CTLINT, m_I2CM_NACK_MASK | m_I2CM_ARB_MASK,
- v_I2CM_NACK_MASK(0) | v_I2CM_ARB_MASK(0));
-
- hdmi_writel(hdmi_dev, I2CM_SLAVE, DDC_I2C_EDID_ADDR);
- hdmi_writel(hdmi_dev, I2CM_SEGADDR, DDC_I2C_SEG_ADDR);
- hdmi_writel(hdmi_dev, I2CM_SEGPTR, block / 2);
- while (trytime--) {
- for (n = 0; n < HDMI_EDID_BLOCK_SIZE / 8; n++) {
- hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset + 8 * n);
- /* enable extend sequential read operation */
- if (block == 0)
- hdmi_msk_reg(hdmi_dev, I2CM_OPERATION,
- m_I2CM_RD8, v_I2CM_RD8(1));
- else
- hdmi_msk_reg(hdmi_dev, I2CM_OPERATION,
- m_I2CM_RD8_EXT, v_I2CM_RD8_EXT(1));
-
- i = 20;
- while (i--) {
- msleep(1);
- interrupt = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
- if (interrupt)
- hdmi_writel(hdmi_dev, IH_I2CM_STAT0,
- interrupt);
-
- if (interrupt &
- (m_SCDC_READREQ | m_I2CM_DONE |
- m_I2CM_ERROR))
- break;
- msleep(4);
- }
-
- if (interrupt & m_I2CM_DONE) {
- for (index = 0; index < 8; index++) {
- buff[8 * n + index] =
- hdmi_readl(hdmi_dev,
- I2CM_READ_BUFF0 + index);
- }
-
- if (n == HDMI_EDID_BLOCK_SIZE / 8 - 1) {
- ret = 0;
- hdmi_dbg(hdmi_drv->dev,
- "[%s] edid read sucess\n",
- __func__);
-
-#ifdef HDMI_DEBUG
- for (i = 0; i < 128; i++) {
- printk("%02x ,", buff[i]);
- if ((i + 1) % 16 == 0)
- printk("\n");
- }
-#endif
- goto exit;
- }
- continue;
- } else if ((interrupt & m_I2CM_ERROR) || (i == -1)) {
- hdmi_err(hdmi_drv->dev,
- "[%s] edid read error\n",
- __func__);
- rk3288_hdmi_i2cm_reset(hdmi_dev);
- break;
- }
- }
-
- hdmi_err(hdmi_drv->dev, "[%s] edid try times %d\n",
- __func__, trytime);
- msleep(100);
- }
-
-exit:
- /* Disable I2C interrupt */
- hdmi_msk_reg(hdmi_dev, IH_MUTE_I2CM_STAT0,
- m_I2CM_DONE_MUTE | m_I2CM_ERR_MUTE,
- v_I2CM_DONE_MUTE(1) | v_I2CM_ERR_MUTE(1));
- hdmi_msk_reg(hdmi_dev, I2CM_INT, m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(1));
- hdmi_msk_reg(hdmi_dev, I2CM_CTLINT, m_I2CM_NACK_MASK | m_I2CM_ARB_MASK,
- v_I2CM_NACK_MASK(1) | v_I2CM_ARB_MASK(1));
- return ret;
-}
-
-static int rk3288_hdmi_video_forceOutput(struct hdmi *hdmi_drv, char enable)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEAUDIO,
- v_FC_FORCEAUDIO(0));
-
- if (enable) { /* Force output Blue */
- hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x00); /*R*/
- hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x00); /*G*/
- hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0xff); /*B*/
- hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEVIDEO,
- v_FC_FORCEVIDEO(1));
- } else {
- hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEVIDEO,
- v_FC_FORCEVIDEO(0));
- hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x00); /*R*/
- hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x00); /*G*/
- hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0x00); /*B*/
- }
-
- return 0;
-}
-
-/* TODO Daisen wait to add support 3D */
-static int rk3288_hdmi_video_frameComposer(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- int h_act = 0, v_act = 0;
- int h_syncdelay = 0, v_syncdelay = 0;
- int h_sync = 0, v_sync = 0;
- int h_blank = 0, v_blank = 0;
- int vsync_pol = hdmi_drv->lcdc->cur_screen->pin_vsync;
- int hsync_pol = hdmi_drv->lcdc->cur_screen->pin_hsync;
- int de_pol = (hdmi_drv->lcdc->cur_screen->pin_den == 0) ? 1 : 0;
- struct fb_videomode *mode = NULL;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if (mode == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
- vpara->vic);
- return -ENOENT;
- }
-
- hdmi_drv->pixclock = mode->pixclock;
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- hdmi_drv->tmdsclk = mode->pixclock;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- hdmi_drv->tmdsclk = mode->pixclock * 10 / 8;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- hdmi_drv->tmdsclk = mode->pixclock * 12 / 8;
- break;
- case HDMI_COLOR_DEPTH_16BIT:
- hdmi_drv->tmdsclk = mode->pixclock * 2;
- break;
- default:
- hdmi_drv->tmdsclk = mode->pixclock;
- break;
- }
-
- /* cfg to bypass hdcp data encrypt */
- hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_ENCRYPT_BYPASS | m_HDMI_DVI,
- v_ENCRYPT_BYPASS(1) | v_HDMI_DVI(vpara->output_mode));
- hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
- m_FC_VSYNC_POL | m_FC_HSYNC_POL | m_FC_DE_POL |
- m_FC_HDMI_DVI | m_FC_INTERLACE_MODE,
- v_FC_VSYNC_POL(vsync_pol) | v_FC_HSYNC_POL(hsync_pol) |
- v_FC_DE_POL(de_pol) | v_FC_HDMI_DVI(vpara->
- output_mode) |
- v_FC_INTERLACE_MODE(mode->vmode));
- hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_VBLANK,
- v_FC_VBLANK(mode->vmode));
-
- h_act = mode->xres;
- hdmi_writel(hdmi_dev, FC_INHACTIV1, v_FC_HACTIVE1(h_act >> 8));
- hdmi_writel(hdmi_dev, FC_INHACTIV0, (h_act & 0xff));
-
- v_act = mode->yres;
- hdmi_writel(hdmi_dev, FC_INVACTIV1, v_FC_VACTIVE1(v_act >> 8));
- hdmi_writel(hdmi_dev, FC_INVACTIV0, (v_act & 0xff));
-
- h_blank = mode->hsync_len + mode->left_margin + mode->right_margin;
- hdmi_writel(hdmi_dev, FC_INHBLANK1, v_FC_HBLANK1(h_blank >> 8));
- hdmi_writel(hdmi_dev, FC_INHBLANK0, (h_blank & 0xff));
-
- v_blank = mode->vsync_len + mode->upper_margin + mode->lower_margin;
- hdmi_writel(hdmi_dev, FC_INVBLANK, (v_blank & 0xff));
-
- h_syncdelay = mode->right_margin;
- hdmi_writel(hdmi_dev, FC_HSYNCINDELAY1,
- v_FC_HSYNCINDEAY1(h_syncdelay >> 8));
- hdmi_writel(hdmi_dev, FC_HSYNCINDELAY0, (h_syncdelay & 0xff));
-
- v_syncdelay = mode->lower_margin;
- hdmi_writel(hdmi_dev, FC_VSYNCINDELAY, (v_syncdelay & 0xff));
-
- h_sync = mode->hsync_len;
- hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH1, v_FC_HSYNCWIDTH1(h_sync >> 8));
- hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH0, (h_sync & 0xff));
-
- v_sync = mode->vsync_len;
- hdmi_writel(hdmi_dev, FC_VSYNCINWIDTH, (v_sync & 0xff));
-
- /* Set the control period minimum duration
- * (min. of 12 pixel clock cycles, refer to HDMI 1.4b specification)
- */
- hdmi_writel(hdmi_dev, FC_CTRLDUR, 12);
- hdmi_writel(hdmi_dev, FC_EXCTRLDUR, 32);
-#if 0
- /* used for HDMI 2.0 TX TODO Daisen wait to modify HDCP KEEPOUT */
- if (hdmi_drv->tmdsclk > 340000000) {
- hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_HDCP_KEEPOUT,
- v_FC_HDCP_KEEPOUT(1));
- hdmi_msk_reg(hdmi_dev, FC_SCRAMBLER_CTRL, m_FC_SCRAMBLE_EN,
- v_FC_SCRAMBLE_EN(1));
- }
-
- /* spacing < 256^2 * config / tmdsClock, spacing <= 50ms
- * worst case: tmdsClock == 25MHz => config <= 19
- */
- hdmi_writel(hdmi_dev, FC_EXCTRLSPAC, 1);
-
- /* Set PreambleFilter */
- for (i = 0; i < 3; i++) {
- value = (i + 1) * 11;
- if (i == 0) /* channel 0 */
- hdmi_writel(hdmi_dev, FC_CH0PREAM, value);
- else if (i == 1) /* channel 1 */
- hdmi_writel(hdmi_dev, FC_CH1PREAM, value & 0x3f);
- else if (i == 2) /* channel 2 */
- hdmi_writel(hdmi_dev, FC_CH2PREAM, value & 0x3f);
- }
-#endif
- /* Set PixelRepetition:No pixel repetition */
- hdmi_writel(hdmi_dev, FC_PRCONF,
- v_FC_PR_FACTOR(vpara->pixel_repet + 1));
-
- return 0;
-}
-
-static int rk3288_hdmi_video_packetizer(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- unsigned char color_depth = 0;
- unsigned char output_select = 0;
- unsigned char remap_size = 0;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- if (vpara->output_color == VIDEO_OUTPUT_RGB444
- || vpara->output_color == VIDEO_OUTPUT_YCBCR444
- || vpara->output_color == VIDEO_OUTPUT_YCBCR420) {
-
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- color_depth = COLOR_DEPTH_24BIT;
- output_select = OUT_FROM_8BIT_BYPASS;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- color_depth = COLOR_DEPTH_30BIT;
- output_select = OUT_FROM_PIXEL_PACKING;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- color_depth = COLOR_DEPTH_36BIT;
- output_select = OUT_FROM_PIXEL_PACKING;
- break;
- case HDMI_COLOR_DEPTH_16BIT:
- color_depth = COLOR_DEPTH_48BIT;
- output_select = OUT_FROM_PIXEL_PACKING;
- break;
- default:
- color_depth = COLOR_DEPTH_24BIT;
- output_select = OUT_FROM_8BIT_BYPASS;
- break;
- }
-
- /* Config Color Depth */
- hdmi_msk_reg(hdmi_dev, VP_PR_CD, m_COLOR_DEPTH,
- v_COLOR_DEPTH(color_depth));
- } else if (vpara->output_color == VIDEO_OUTPUT_YCBCR422) {
-
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- remap_size = YCC422_16BIT;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- remap_size = YCC422_20BIT;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- remap_size = YCC422_24BIT;
- break;
- default:
- remap_size = YCC422_16BIT;
- break;
- }
-
- output_select = OUT_FROM_YCC422_REMAP;
- /* Config remap size for the different color Depth */
- hdmi_msk_reg(hdmi_dev, VP_REMAP, m_YCC422_SIZE,
- v_YCC422_SIZE(remap_size));
- } else {
- hdmi_err(hdmi_drv->dev, "invalid output color type: %d",
- vpara->output_color);
- return -1;
- }
-
- /* Config pixel repettion */
- hdmi_msk_reg(hdmi_dev, VP_PR_CD, m_DESIRED_PR_FACTOR,
- v_DESIRED_PR_FACTOR(vpara->pixel_repet));
- if (vpara->pixel_repet > 0)
- hdmi_msk_reg(hdmi_dev, VP_CONF, m_PIXEL_REPET_EN | m_BYPASS_SEL,
- v_PIXEL_REPET_EN(1) | v_BYPASS_SEL(0));
- else
- hdmi_msk_reg(hdmi_dev, VP_CONF, m_PIXEL_REPET_EN | m_BYPASS_SEL,
- v_PIXEL_REPET_EN(0) | v_BYPASS_SEL(1));
-
- /* config output select */
- if (output_select == OUT_FROM_PIXEL_PACKING) { /* pixel packing */
- hdmi_msk_reg(hdmi_dev, VP_CONF,
- m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN |
- m_OUTPUT_SEL,
- v_BYPASS_EN(0) | v_PIXEL_PACK_EN(1) |
- v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
- } else if (output_select == OUT_FROM_YCC422_REMAP) { /* YCC422 */
- hdmi_msk_reg(hdmi_dev, VP_CONF,
- m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN |
- m_OUTPUT_SEL,
- v_BYPASS_EN(0) | v_PIXEL_PACK_EN(0) |
- v_YCC422_EN(1) | v_OUTPUT_SEL(output_select));
- } else if (output_select == OUT_FROM_8BIT_BYPASS || output_select == 3) {
- /* bypass */
- hdmi_msk_reg(hdmi_dev, VP_CONF,
- m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN |
- m_OUTPUT_SEL,
- v_BYPASS_EN(1) | v_PIXEL_PACK_EN(0) |
- v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
- }
-#if defined(HDMI_VIDEO_STUFFING)
- /* YCC422 and pixel packing stuffing */
- hdmi_msk_reg(hdmi_dev, VP_STUFF, m_PR_STUFFING, v_PR_STUFFING(1));
- hdmi_msk_reg(hdmi_dev, VP_STUFF, m_YCC422_STUFFING | m_PP_STUFFING,
- v_YCC422_STUFFING(1) | v_PP_STUFFING(1));
-#endif
- return 0;
-}
-
-int rk3288_hdmi_video_sampler(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- int map_code = 0;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
- || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444
- || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR420) {
-
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- map_code = VIDEO_RGB444_8BIT;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- map_code = VIDEO_RGB444_10BIT;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- map_code = VIDEO_RGB444_12BIT;
- break;
- case HDMI_COLOR_DEPTH_16BIT:
- map_code = VIDEO_RGB444_16BIT;
- break;
- default:
- map_code = VIDEO_RGB444_8BIT;
- break;
- }
- map_code +=
- (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444) ? 8 : 0;
- } else if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR422) {
- /* YCC422 mapping is discontinued - only map 1 is supported */
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- map_code = VIDEO_YCBCR422_8BIT;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- map_code = VIDEO_YCBCR422_10BIT;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- map_code = VIDEO_YCBCR422_12BIT;
- break;
- default:
- map_code = VIDEO_YCBCR422_8BIT;
- break;
- }
- } else {
- hdmi_err(hdmi_drv->dev, "invalid input color type: %d",
- vpara->input_color);
- return -1;
- }
-
- /* Set Data enable signal from external
- * and set video sample input mapping
- */
- hdmi_msk_reg(hdmi_dev, TX_INVID0, m_INTERNAL_DE_GEN | m_VIDEO_MAPPING,
- v_INTERNAL_DE_GEN(0) | v_VIDEO_MAPPING(map_code));
-
-#if defined(HDMI_VIDEO_STUFFING)
- hdmi_writel(hdmi_dev, TX_GYDATA0, 0x00);
- hdmi_writel(hdmi_dev, TX_GYDATA1, 0x00);
- hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_GYDATA_STUFF,
- v_GYDATA_STUFF(1));
- hdmi_writel(hdmi_dev, TX_RCRDATA0, 0x00);
- hdmi_writel(hdmi_dev, TX_RCRDATA1, 0x00);
- hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_RCRDATA_STUFF,
- v_RCRDATA_STUFF(1));
- hdmi_writel(hdmi_dev, TX_BCBDATA0, 0x00);
- hdmi_writel(hdmi_dev, TX_BCBDATA1, 0x00);
- hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_BCBDATA_STUFF,
- v_BCBDATA_STUFF(1));
-#endif
- return 0;
-}
-
-#ifdef HDMI_DEBUG
-static int __maybe_unused rk3288_hdmi_read_phy(struct rk3288_hdmi_device *hdmi_dev,
- int reg_addr)
-{
- int trytime = 2, i = 0, op_status = 0;
- int val = 0;
-
- while (trytime--) {
- hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
- hdmi_writel(hdmi_dev, PHY_I2CM_DATAI_1, 0x00);
- hdmi_writel(hdmi_dev, PHY_I2CM_DATAI_0, 0x00);
- hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_READ);
-
- i = 20;
- while (i--) {
- msleep(1);
- op_status = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
- if (op_status)
- hdmi_writel(hdmi_dev, IH_I2CMPHY_STAT0,
- op_status);
-
- if (op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
- break;
- }
- msleep(4);
- }
-
- if (op_status & m_I2CMPHY_DONE) {
- val = hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_1);
- val = (val & 0xff) << 8;
- val += (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_0) & 0xff);
- hdmi_dbg(hdmi_dev->dev, "phy_reg0x%02x: 0x%04x",
- reg_addr, val);
- return val;
- } else {
- hdmi_err(hdmi_dev->dev,
- "[%s] operation error,trytime=%d\n",
- __func__, trytime);
- }
- msleep(100);
- }
-
- return -1;
-}
-#endif
-
-static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev,
- int reg_addr, int val)
-{
- int trytime = 2, i = 0, op_status = 0;
-
- while (trytime--) {
- hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
- hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_1, (val >> 8) & 0xff);
- hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_0, val & 0xff);
- hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_WRITE);
-
- i = 20;
- while (i--) {
- msleep(1);
- op_status = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
- if (op_status)
- hdmi_writel(hdmi_dev, IH_I2CMPHY_STAT0,
- op_status);
-
- if (op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
- break;
- }
- msleep(4);
- }
-
- if (op_status & m_I2CMPHY_DONE) {
- return 0;
- } else {
- hdmi_err(hdmi_dev->dev,
- "[%s] operation error,trytime=%d\n",
- __func__, trytime);
- }
- msleep(100);
- }
-
- return -1;
-}
-
-int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv, unsigned char pixel_repet,
- unsigned char color_depth)
-{
- int stat = 0, i = 0;
- const struct phy_mpll_config_tab *phy_mpll = NULL;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_msk_reg(hdmi_dev, PHY_I2CM_DIV, m_PHY_I2CM_FAST_STD,
- v_PHY_I2CM_FAST_STD(0));
-
- /* power on PHY */
- hdmi_writel(hdmi_dev, PHY_CONF0, 0x3a);
- /*
- hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG,
- v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
- */
-
- /* reset PHY */
- hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
- msleep(5);
- hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
-
- /* Set slave address as PHY GEN2 address */
- hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_GEN2_ADDR);
-
- /* config the required PHY I2C register */
- phy_mpll =
- get_phy_mpll_tab(hdmi_drv->pixclock, pixel_repet, color_depth);
- if (phy_mpll) {
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG,
- v_PREP_DIV(phy_mpll->prep_div) |
- v_TMDS_CNTRL(phy_mpll->tmdsmhl_cntrl) |
- v_OPMODE(phy_mpll->opmode) |
- v_FBDIV2_CNTRL(phy_mpll->fbdiv2_cntrl) |
- v_FBDIV1_CNTRL(phy_mpll->fbdiv1_cntrl) |
- v_REF_CNTRL(phy_mpll->ref_cntrl) |
- v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL,
- v_MPLL_PROP_CNTRL(phy_mpll->prop_cntrl) |
- v_MPLL_INT_CNTRL(phy_mpll->int_cntrl));
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL,
- v_MPLL_GMP_CNTRL(phy_mpll->gmp_cntrl));
- }
- if (hdmi_drv->pixclock <= 74250000) {
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
- v_OVERRIDE(1) | v_SLOPEBOOST(0)
- | v_TX_SYMON(1) | v_TX_TRAON(0) |
- v_TX_TRBON(0) | v_CLK_SYMON(1));
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
- v_TX_TERM(R100_Ohms));
- } else if (hdmi_drv->pixclock == 148500000) {
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
- v_OVERRIDE(1) | v_SLOPEBOOST(3)
- | v_TX_SYMON(1) | v_TX_TRAON(0) |
- v_TX_TRBON(0) | v_CLK_SYMON(1));
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
- v_TX_TERM(R100_Ohms));
- } else if (hdmi_drv->pixclock == 297000000) {
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
- v_OVERRIDE(1) | v_SLOPEBOOST(2)
- | v_TX_SYMON(1) | v_TX_TRAON(0) |
- v_TX_TRBON(0) | v_CLK_SYMON(1));
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
- v_TX_TERM(R100_Ohms));
- } else if (hdmi_drv->pixclock > 297000000) {
- /* TODO Daisen wait to add and modify */
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
- v_TX_TERM(R13333_Ohms));
- }
-
- if (hdmi_drv->pixclock < 297000000)
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_VLEVCTRL,
- v_SUP_TXLVL(20) | v_SUP_CLKLVL(19));
- else
- rk3288_hdmi_write_phy(hdmi_dev, PHYTX_VLEVCTRL,
- v_SUP_TXLVL(17) | v_SUP_CLKLVL(16));
-
- /* power on PHY */
- hdmi_writel(hdmi_dev, PHY_CONF0, 0x6e);
- /*
- hdmi_msk_reg(hdmi_dev, PHY_CONF0,
- m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
- v_PDDQ_SIG(0) | v_TXPWRON_SIG(1) | v_ENHPD_RXSENSE_SIG(1));
- */
-
- /* check if the PHY PLL is locked */
-#define PHY_TIMEOUT 10000
- while (i++ < PHY_TIMEOUT) {
- if ((i % 100) == 0) {
- stat = hdmi_readl(hdmi_dev, PHY_STAT0);
- if (stat & m_PHY_LOCK) {
- break;
- }
- }
- }
- if ((stat & m_PHY_LOCK) == 0) {
- stat = hdmi_readl(hdmi_dev, MC_LOCKONCLOCK);
- hdmi_err(hdmi_dev->dev,
- "PHY PLL not locked: PCLK_ON=%d,TMDSCLK_ON=%d\n",
- (stat & m_PCLK_ON) >> 6, (stat & m_TMDSCLK_ON) >> 5);
- return -1;
- }
-
- return 0;
-}
-
-int rk3288_hdmi_config_vsi(struct hdmi *hdmi_drv, unsigned char vic_3d,
- unsigned char format, int auto_send)
-{
- int i = 0;
- unsigned char data[3] = { 0 };
- int id = 0x000c03;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- hdmi_dbg(hdmi_drv->dev, "[%s] vic %d format %d.\n", __func__,
- vic_3d, format);
- hdmi_msk_reg(hdmi_dev, FC_DATAUTO0, m_VSD_AUTO, v_VSD_AUTO(0));
- hdmi_writel(hdmi_dev, FC_VSDIEEEID0, id & 0xff);
- hdmi_writel(hdmi_dev, FC_VSDIEEEID1, (id >> 8) & 0xff);
- hdmi_writel(hdmi_dev, FC_VSDIEEEID2, (id >> 16) & 0xff);
-
- data[0] = format << 5; /* PB4 --HDMI_Video_Format */
- switch (format) {
- case HDMI_VIDEO_FORMAT_4Kx2K:
- data[1] = vic_3d; /* PB5--HDMI_VIC */
- data[2] = 0;
- break;
- case HDMI_VIDEO_FORMAT_3D:
- data[1] = vic_3d << 4; /* PB5--3D_Structure field */
- data[2] = 0; /* PB6--3D_Ext_Data field */
- break;
- default:
- data[1] = 0;
- data[2] = 0;
- break;
- }
-
- for (i = 0; i < 3; i++)
- hdmi_writel(hdmi_dev, FC_VSDPAYLOAD0 + i, data[i]);
-
- if (auto_send) {
- hdmi_msk_reg(hdmi_dev, FC_DATAUTO0, m_VSD_AUTO,
- v_VSD_AUTO(auto_send));
- } else {
- hdmi_msk_reg(hdmi_dev, FC_DATMAN, m_VSD_MAN, v_VSD_MAN(1));
- }
-
- return 0;
-}
-
-static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic,
- struct hdmi_video_para *vpara)
-{
- unsigned char colorimetry, ext_colorimetry, aspect_ratio, y1y0;
- unsigned char rgb_quan_range = AVI_QUANTIZATION_RANGE_DEFAULT;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- /* Set AVI infoFrame Data byte1 */
- if (vpara->output_color == VIDEO_OUTPUT_YCBCR444)
- y1y0 = AVI_COLOR_MODE_YCBCR444;
- else if (vpara->output_color == VIDEO_OUTPUT_YCBCR422)
- y1y0 = AVI_COLOR_MODE_YCBCR422;
- else if (vpara->output_color == VIDEO_OUTPUT_YCBCR420)
- y1y0 = AVI_COLOR_MODE_YCBCR420;
- else
- y1y0 = AVI_COLOR_MODE_RGB;
-
- hdmi_msk_reg(hdmi_dev, FC_AVICONF0, m_FC_ACTIV_FORMAT | m_FC_RGC_YCC,
- v_FC_RGC_YCC(y1y0) | v_FC_ACTIV_FORMAT(1));
-
- /* Set AVI infoFrame Data byte2 */
- switch (vic) {
- case HDMI_720x480i_60Hz_4_3:
- case HDMI_720x576i_50Hz_4_3:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x576p_50Hz_4_3:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
- colorimetry = AVI_COLORIMETRY_SMPTE_170M;
- break;
- case HDMI_720x480i_60Hz_16_9:
- case HDMI_720x576i_50Hz_16_9:
- case HDMI_720x480p_60Hz_16_9:
- case HDMI_720x576p_50Hz_16_9:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
- colorimetry = AVI_COLORIMETRY_SMPTE_170M;
- break;
- default:
- aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
- colorimetry = AVI_COLORIMETRY_ITU709;
- }
-
- if (vpara->color_depth > HDMI_COLOR_DEPTH_8BIT) {
- colorimetry = AVI_COLORIMETRY_EXTENDED;
- ext_colorimetry = 6;
- } else if (vpara->output_color == VIDEO_OUTPUT_RGB444) {
- colorimetry = AVI_COLORIMETRY_NO_DATA;
- ext_colorimetry = 0;
- }
-
- hdmi_writel(hdmi_dev, FC_AVICONF1,
- v_FC_COLORIMETRY(colorimetry) |
- v_FC_PIC_ASPEC_RATIO(aspect_ratio) |
- v_FC_ACT_ASPEC_RATIO
- (ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME));
-
- /* Set AVI infoFrame Data byte3 */
- hdmi_msk_reg(hdmi_dev, FC_AVICONF2,
- m_FC_EXT_COLORIMETRY | m_FC_QUAN_RANGE,
- v_FC_EXT_COLORIMETRY(ext_colorimetry) |
- v_FC_QUAN_RANGE(rgb_quan_range));
-
- /* Set AVI infoFrame Data byte4 */
- hdmi_writel(hdmi_dev, FC_AVIVID, (vic & 0xff));
-
- /* Set AVI infoFrame Data byte5 */
- hdmi_msk_reg(hdmi_dev, FC_AVICONF3, m_FC_YQ | m_FC_CN,
- v_FC_YQ(YQ_LIMITED_RANGE) | v_FC_CN(CN_GRAPHICS));
-
-}
-
-static const char coeff_csc[][24] = {
- /* G R B Bias */
- /* A1 | A2 | A3 | A4 | */
- /* B1 | B2 | B3 | B4 | */
- /* C1 | C2 | C3 | C4 | */
- { /* CSC_RGB_0_255_TO_RGB_16_235_8BIT */
- 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* G */
- 0x00, 0x00, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x20, /* R */
- 0x00, 0x00, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x20, /* B */
- },
- { /* CSC_RGB_0_255_TO_RGB_16_235_10BIT */
- 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* G */
- 0x00, 0x00, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x80, /* R */
- 0x00, 0x00, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x80, /* B */
- },
-#if 0
- { /* CSC_RGB_0_255_TO_ITU601_16_235_8BIT */
- 0x25, 0x91, 0x13, 0x23, 0x07, 0x4c, 0x00, 0x00, /* Y */
- 0xe5, 0x34, 0x20, 0x00, 0xfa, 0xcc, 0x02, 0x00, /* Cr */
- 0xea, 0xcd, 0xf5, 0x33, 0x20, 0x00, 0x02, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU601_16_235_10BIT */
- 0x25, 0x91, 0x13, 0x23, 0x07, 0x4c, 0x00, 0x00, /* Y */
- 0xe5, 0x34, 0x20, 0x00, 0xfa, 0xcc, 0x08, 0x00, /* Cr */
- 0xea, 0xcd, 0xf5, 0x33, 0x20, 0x00, 0x08, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU709_16_235_8BIT */
- 0x2d, 0xc6, 0x0d, 0x9b, 0x04, 0x9f, 0x00, 0x00, /* Y */
- 0xe2, 0xef, 0x20, 0x00, 0xfd, 0x11, 0x02, 0x00, /* Cr */
- 0xe7, 0x55, 0xf8, 0xab, 0x20, 0x00, 0x02, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU709_16_235_10BIT */
- 0x2d, 0xc6, 0x0d, 0x9b, 0x04, 0x9f, 0x00, 0x00, /* Y */
- 0xe2, 0xef, 0x20, 0x00, 0xfd, 0x11, 0x08, 0x00, /* Cr */
- 0xe7, 0x55, 0xf8, 0xab, 0x20, 0x00, 0x08, 0x00, /* Cb */
- },
-#else
- { /* CSC_RGB_0_255_TO_ITU601_16_235_8BIT */
- 0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x00, 0x40, /* Y */
- 0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x02, 0x00, /* Cr */
- 0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x02, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU601_16_235_10BIT */
- 0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x01, 0x00, /* Y */
- 0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x08, 0x00, /* Cr */
- 0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x08, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU709_16_235_8BIT */
- 0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x00, 0x40, /* Y */
- 0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x02, 0x00, /* Cr */
- 0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x02, 0x00, /* Cb */
- },
- { /* CSC_RGB_0_255_TO_ITU709_16_235_10BIT */
- 0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x01, 0x00, /* Y */
- 0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x08, 0x00, /* Cr */
- 0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x08, 0x00, /* Cb */
- },
-#endif
- /* Y Cr Cb Bias */
- { /* CSC_ITU601_16_235_TO_RGB_0_255_8BIT */
- 0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e, /* G */
- 0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a, /* R */
- 0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b, /* B */
- },
- { /* CSC_ITU709_16_235_TO_RGB_0_255_8BIT */
- 0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7, /* G */
- 0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d, /* R */
- 0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25, /* B */
- },
-};
-
-static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- int i, mode, interpolation, decimation, csc_scale;
- const char *coeff = NULL;
- unsigned char color_depth = 0;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- if ((vpara->input_color == vpara->output_color)
- && (vpara->color_limit_range == 0)) {
- hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF,
- v_FEED_THROUGH_OFF(0));
- return 0;
- }
-
- if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR422 &&
- (vpara->output_color == VIDEO_OUTPUT_RGB444
- || vpara->output_color == VIDEO_OUTPUT_YCBCR444)) {
- interpolation = 1;
- hdmi_msk_reg(hdmi_dev, CSC_CFG, m_CSC_INTPMODE,
- v_CSC_INTPMODE(interpolation));
- }
-
- if ((vpara->input_color == VIDEO_INPUT_COLOR_RGB
- || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
- && vpara->output_color == VIDEO_OUTPUT_YCBCR422) {
- decimation = 1;
- hdmi_msk_reg(hdmi_dev, CSC_CFG, m_CSC_DECIMODE,
- v_CSC_DECIMODE(decimation));
- }
-
- switch (vpara->vic) {
- case HDMI_720x480i_60Hz_4_3:
- case HDMI_720x576i_50Hz_4_3:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x576p_50Hz_4_3:
- case HDMI_720x480i_60Hz_16_9:
- case HDMI_720x576i_50Hz_16_9:
- case HDMI_720x480p_60Hz_16_9:
- case HDMI_720x576p_50Hz_16_9:
- if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
- && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
- mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
- csc_scale = 0;
- } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
- && vpara->output_color == VIDEO_OUTPUT_RGB444) {
- mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
- csc_scale = 1;
- }
- break;
- default:
- if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
- && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
- mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
- csc_scale = 0;
- } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
- && vpara->output_color == VIDEO_OUTPUT_RGB444) {
- mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
- csc_scale = 1;
- }
- break;
- }
-
- if ((vpara->input_color == VIDEO_INPUT_COLOR_RGB)
- && (vpara->output_color == VIDEO_OUTPUT_RGB444)
- && (vpara->color_limit_range == 1)) {
- mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
- csc_scale = 1;
- }
-
- switch (vpara->color_depth) {
- case HDMI_COLOR_DEPTH_8BIT:
- color_depth = COLOR_DEPTH_24BIT;
- break;
- case HDMI_COLOR_DEPTH_10BIT:
- color_depth = COLOR_DEPTH_30BIT;
- mode += 1;
- break;
- case HDMI_COLOR_DEPTH_12BIT:
- color_depth = COLOR_DEPTH_36BIT;
- mode += 2;
- break;
- case HDMI_COLOR_DEPTH_16BIT:
- color_depth = COLOR_DEPTH_48BIT;
- mode += 3;
- break;
- default:
- color_depth = COLOR_DEPTH_24BIT;
- break;
- }
-
- coeff = coeff_csc[mode];
- for (i = 0; i < 24; i++) {
- hdmi_writel(hdmi_dev, CSC_COEF_A1_MSB + i, coeff[i]);
- }
- hdmi_msk_reg(hdmi_dev, CSC_SCALE, m_CSC_SCALE, v_CSC_SCALE(csc_scale));
- /* config CSC_COLOR_DEPTH */
- hdmi_msk_reg(hdmi_dev, CSC_SCALE, m_CSC_COLOR_DEPTH,
- v_CSC_COLOR_DEPTH(color_depth));
-
- /* enable CSC */
- hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF,
- v_FEED_THROUGH_OFF(1));
- return 0;
-}
-
-int rk3288_hdmi_config_video(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- if (rk3288_hdmi_video_forceOutput(hdmi_drv, 1) < 0)
- return -1;
- if (rk3288_hdmi_video_frameComposer(hdmi_drv, vpara) < 0)
- return -1;
- if (rk3288_hdmi_video_packetizer(hdmi_drv, vpara) < 0)
- return -1;
- if (rk3288_hdmi_video_csc(hdmi_drv, vpara) < 0)
- return -1;
- if (rk3288_hdmi_video_sampler(hdmi_drv, vpara) < 0)
- return -1;
-
- if (vpara->output_mode == OUTPUT_HDMI) {
- rk3288_hdmi_config_avi(hdmi_drv, vpara->vic, vpara);
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n",
- __func__);
-
- if (vpara->format_3d != 0)
- rk3288_hdmi_config_vsi(hdmi_drv, vpara->format_3d,
- HDMI_VIDEO_FORMAT_3D, 1);
-#ifndef HDMI_VERSION_2
- else if ((vpara->vic > 92 && vpara->vic < 96)
- || (vpara->vic == 98)) {
- vpara->vic = (vpara->vic == 98) ? 4 : (96 - vpara->vic);
- rk3288_hdmi_config_vsi(hdmi_drv, vpara->vic,
- HDMI_VIDEO_FORMAT_4Kx2K, 1);
- }
-#endif
- else
- rk3288_hdmi_config_vsi(hdmi_drv, vpara->vic,
- HDMI_VIDEO_FORMAT_NORMAL, 1);
- } else {
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n",
- __func__);
- }
-
- rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
- rk3288_hdmi_config_phy(hdmi_drv, vpara->pixel_repet,
- vpara->color_depth);
- return 0;
-}
-
-static void rk3288_hdmi_config_aai(struct hdmi *hdmi_drv,
- struct hdmi_audio *audio)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- /* Refer to CEA861-E Audio infoFrame */
- /* Set both Audio Channel Count and
- * Audio Coding Type Refer to Stream Head for HDMI
- */
- hdmi_msk_reg(hdmi_dev, FC_AUDICONF0, m_FC_CHN_CNT | m_FC_CODING_TYEP,
- v_FC_CHN_CNT(0) | v_FC_CODING_TYEP(0));
-
- /* Set both Audio Sample Size and
- * Sample Frequency Refer to Stream Head for HDMI
- */
- hdmi_msk_reg(hdmi_dev, FC_AUDICONF1,
- m_FC_SAMPLE_SIZE | m_FC_SAMPLE_FREQ,
- v_FC_SAMPLE_SIZE(0) | v_FC_SAMPLE_FREQ(0));
-
- /* Set Channel Allocation */
- hdmi_writel(hdmi_dev, FC_AUDICONF2, 0x00);
-
- /* Set LFEPBL¡¢DOWN-MIX INH and LSV */
- hdmi_writel(hdmi_dev, FC_AUDICONF3, 0x00);
-}
-
-int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
-{
- int word_length = 0, channel = 0, mclk_fs;
- unsigned int N = 0, CTS = 0;
- unsigned char layout_value = 0;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- if (audio->channel < 3)
- channel = I2S_CHANNEL_1_2;
- else if (audio->channel < 5)
- channel = I2S_CHANNEL_3_4;
- else if (audio->channel < 7)
- channel = I2S_CHANNEL_5_6;
- else
- channel = I2S_CHANNEL_7_8;
-
- switch (audio->rate) {
- case HDMI_AUDIO_FS_32000:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000)
- N = N_32K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_32K_MIDCLK;
- else
- N = N_32K_LOWCLK;
-
- /* div a num to avoid the value is exceed 2^32(int) */
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 1000, 32);
- break;
- case HDMI_AUDIO_FS_44100:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000)
- N = N_441K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_441K_MIDCLK;
- else
- N = N_441K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 100, 441);
- break;
- case HDMI_AUDIO_FS_48000:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000) /* FS_153.6 */
- N = N_48K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_48K_MIDCLK;
- else
- N = N_48K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 1000, 48);
- break;
- case HDMI_AUDIO_FS_88200:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000)
- N = N_882K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_882K_MIDCLK;
- else
- N = N_882K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 100, 882);
- break;
- case HDMI_AUDIO_FS_96000:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000) /* FS_153.6 */
- N = N_96K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_96K_MIDCLK;
- else
- N = N_96K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 1000, 96);
- break;
- case HDMI_AUDIO_FS_176400:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000)
- N = N_1764K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_1764K_MIDCLK;
- else
- N = N_1764K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 100, 1764);
- break;
- case HDMI_AUDIO_FS_192000:
- mclk_fs = FS_256;
- if (hdmi_drv->pixclock >= 594000000) /* FS_153.6 */
- N = N_192K_HIGHCLK;
- else if (hdmi_drv->pixclock == 297000000)
- N = N_192K_MIDCLK;
- else
- N = N_192K_LOWCLK;
-
- CTS = CALC_CTS(N, hdmi_drv->tmdsclk / 1000, 192);
- break;
- default:
- hdmi_err(hdmi_drv->dev,
- "[%s] not support such sample rate %d\n", __func__,
- audio->rate);
- return -ENOENT;
- }
-
- switch (audio->word_length) {
- case HDMI_AUDIO_WORD_LENGTH_16bit:
- word_length = I2S_16BIT_SAMPLE;
- break;
- case HDMI_AUDIO_WORD_LENGTH_20bit:
- word_length = I2S_20BIT_SAMPLE;
- break;
- case HDMI_AUDIO_WORD_LENGTH_24bit:
- word_length = I2S_24BIT_SAMPLE;
- break;
- default:
- word_length = I2S_16BIT_SAMPLE;
- }
-
- hdmi_dbg(hdmi_drv->dev, "rate = %d, tmdsclk = %d, N = %d, CTS = %d\n",
- audio->rate, hdmi_drv->tmdsclk, N, CTS);
- /* more than 2 channels => layout 1 else layout 0
- * TODO Daisen wait to modify
- */
- layout_value = (audio->channel > 2) ? 1 : 0;
- hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_LAYOUT,
- v_AUD_PACK_LAYOUT(layout_value));
-
- if (hdmi_drv->audio.type == INPUT_SPDIF) {
- hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_I2S_SEL,
- v_I2S_SEL(AUDIO_SPDIF_GPA));
- hdmi_msk_reg(hdmi_dev, AUD_SPDIF1, m_SET_NLPCM | m_SPDIF_WIDTH,
- v_SET_NLPCM(PCM_LINEAR) |
- v_SPDIF_WIDTH(word_length));
- /* Mask fifo empty and full int and reset fifo */
- hdmi_msk_reg(hdmi_dev, AUD_SPDIFINT,
- m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK,
- v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
- hdmi_msk_reg(hdmi_dev, AUD_SPDIF0, m_SW_SAUD_FIFO_RST,
- v_SW_SAUD_FIFO_RST(1));
- } else {
- hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_I2S_SEL | m_I2S_IN_EN,
- v_I2S_SEL(AUDIO_I2S) | v_I2S_IN_EN(channel));
- hdmi_writel(hdmi_dev, AUD_CONF1,
- v_I2S_MODE(I2S_STANDARD_MODE) |
- v_I2S_WIDTH(word_length));
- /* Mask fifo empty and full int and reset fifo */
- hdmi_msk_reg(hdmi_dev, AUD_INT,
- m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK,
- v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
- hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_SW_AUD_FIFO_RST,
- v_SW_AUD_FIFO_RST(1));
- }
-
- hdmi_msk_reg(hdmi_dev, AUD_INPUTCLKFS, m_LFS_FACTOR,
- v_LFS_FACTOR(mclk_fs));
-
- /* Set N value */
- hdmi_msk_reg(hdmi_dev, AUD_N3, m_AUD_N3, v_AUD_N3(N >> 16));
- hdmi_writel(hdmi_dev, AUD_N2, (N >> 8) & 0xff);
- hdmi_writel(hdmi_dev, AUD_N1, N & 0xff);
- /* Set CTS by manual */
- hdmi_msk_reg(hdmi_dev, AUD_CTS3, m_N_SHIFT | m_CTS_MANUAL | m_AUD_CTS3,
- v_N_SHIFT(N_SHIFT_1) | v_CTS_MANUAL(1) | v_AUD_CTS3(CTS >>
- 16));
- hdmi_writel(hdmi_dev, AUD_CTS2, (CTS >> 8) & 0xff);
- hdmi_writel(hdmi_dev, AUD_CTS1, CTS & 0xff);
-
- hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE,
- v_AUDCLK_DISABLE(0));
- rk3288_hdmi_config_aai(hdmi_drv, audio);
-
- return 0;
-}
-
-void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
-{
- hdmi_dbg(hdmi_drv->dev, "[%s] %d\n", __func__, enable);
- if (enable == 0) {
- rk3288_hdmi_av_mute(hdmi_drv, 1);
- rk3288_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
- } else {
- if (hdmi_drv->pwr_mode == LOWER_PWR)
- rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-
- /* disable blue screen transmission
- * after turning on all necessary blocks
- */
- rk3288_hdmi_video_forceOutput(hdmi_drv, 0);
- rk3288_hdmi_av_mute(hdmi_drv, 0);
- }
-}
-
-int rk3288_hdmi_insert(struct hdmi *hdmi_drv)
-{
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
-
- /* report HPD state to HDCP (after configuration) */
- hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
-
- return 0;
-}
-
-int rk3288_hdmi_removed(struct hdmi *hdmi_drv)
-{
- rk3288_hdmi_control_output(hdmi_drv, 0);
- dev_printk(KERN_INFO, hdmi_drv->dev, "Removed.\n");
- return 0;
-}
-
-int rk3288_hdmi_initial(struct hdmi *hdmi_drv)
-{
- int rc = HDMI_ERROR_SUCESS;
-
- hdmi_drv->pwr_mode = NORMAL;
- hdmi_drv->insert = rk3288_hdmi_insert;
- hdmi_drv->remove = rk3288_hdmi_removed;
- hdmi_drv->control_output = rk3288_hdmi_control_output;
- hdmi_drv->config_video = rk3288_hdmi_config_video;
- hdmi_drv->config_audio = rk3288_hdmi_config_audio;
- hdmi_drv->detect_hotplug = rk3288_hdmi_detect_hotplug;
- hdmi_drv->read_edid = rk3288_hdmi_read_edid;
- hdmi_drv->support_vic = rk3288_hdmi_support_vic;
- hdmi_drv->support_vic_num = ARRAY_SIZE(rk3288_hdmi_support_vic);
-
- rk3288_hdmi_reset(hdmi_drv);
-
- if (hdmi_drv->hdcp_power_on_cb)
- rc = hdmi_drv->hdcp_power_on_cb();
-
- return rc;
-}
-
-irqreturn_t hdmi_irq(int irq, void *priv)
-{
- struct hdmi *hdmi_drv = (struct hdmi *)priv;
- struct rk3288_hdmi_device *hdmi_dev =
- container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
- int phy_int = 0, i2cm_int = 0, phy_i2cm_int = 0, cec_int = 0;
- int aud_dma_int = 0;
-
- /* read interrupt */
- phy_int = hdmi_readl(hdmi_dev, IH_PHY_STAT0);
- i2cm_int = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
- phy_i2cm_int = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
- cec_int = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
- aud_dma_int = hdmi_readl(hdmi_dev, IH_AHBDMAAUD_STAT0);
- /*
- hdcp_int = hdmi_readl(hdmi_dev, A_APIINTSTAT);
- */
-
- /* clear interrupt */
- hdmi_writel(hdmi_dev, IH_PHY_STAT0, phy_int);
- hdmi_writel(hdmi_dev, IH_I2CM_STAT0, i2cm_int);
- hdmi_writel(hdmi_dev, IH_I2CMPHY_STAT0, phy_i2cm_int);
- hdmi_writel(hdmi_dev, IH_CEC_STAT0, cec_int);
- hdmi_writel(hdmi_dev, IH_AHBDMAAUD_STAT0, aud_dma_int);
- /*
- hdmi_writel(hdmi_dev, A_APIINTCLR, hdcp_int);
- */
-
- /* HPD or RX_SENSE */
- if ((phy_int & m_HPD) || ((phy_int & 0x3c) == 0x3c)) {
- if (hdmi_drv->state == HDMI_SLEEP)
- hdmi_drv->state = WAIT_HOTPLUG;
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(5));
- }
- /* I2CM write or read result */
- if (i2cm_int & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR)) {
- /* spin_lock(&hdmi_drv->irq_lock); */
- hdmi_dev->i2cm_int = i2cm_int;
- /* spin_unlock(&hdmi_drv->irq_lock); */
- }
- /* PHY I2CM write or read result */
- if (phy_i2cm_int & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
- /* mutex_lock(&hdmi_dev->int_mutex); */
- hdmi_dev->phy_i2cm_int = phy_i2cm_int;
- /* mutex_unlock(&hdmi_dev->int_mutex); */
- }
- /* CEC */
- if (cec_int) {
- }
- /* HDCP */
- if (hdmi_drv->hdcp_irq_cb)
- hdmi_drv->hdcp_irq_cb(i2cm_int);
-
- return IRQ_HANDLED;
-}
+++ /dev/null
-#ifndef _RK3288_HDMI_HW_H
-#define _RK3288_HDMI_HW_H
-#include "../../rk_hdmi.h"
-
-#define HDMI_INT_USE_POLL 1 /* TODO Daisen wait to modify */
-
-enum PWR_MODE {
- NORMAL,
- LOWER_PWR,
-};
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI,
-};
-enum {
- INPUT_IIS,
- INPUT_SPDIF
-};
-
-/* Color Space Convertion Mode */
-enum {
- CSC_RGB_0_255_TO_RGB_16_235_8BIT, /* RGB 0-255 input to RGB 16-235 output that is 8bit clolor depth */
- CSC_RGB_0_255_TO_RGB_16_235_10BIT, /* RGB 0-255 input to RGB 16-235 output that is 8bit clolor depth */
- CSC_RGB_0_255_TO_ITU601_16_235_8BIT, /* RGB 0-255 input to YCbCr 16-235 output according BT601 that is 8bit clolor depth */
- CSC_RGB_0_255_TO_ITU601_16_235_10BIT, /* RGB 0-255 input to YCbCr 16-235 output according BT601 that is 10bit clolor depth */
- CSC_RGB_0_255_TO_ITU709_16_235_8BIT, /* RGB 0-255 input to YCbCr 16-235 output accroding BT709 that is 8bit clolor depth */
- CSC_RGB_0_255_TO_ITU709_16_235_10BIT, /* RGB 0-255 input to YCbCr 16-235 output accroding BT709 that is 10bit clolor depth */
- CSC_ITU601_16_235_TO_RGB_16_235_8BIT, /* YCbCr 16-235 input to RGB 16-235 output according BT601 that is 8bit clolor depth */
- CSC_ITU709_16_235_TO_RGB_16_235_8BIT, /* YCbCr 16-235 input to RGB 16-235 output according BT709 that is 8bit clolor depth */
- CSC_ITU601_16_235_TO_RGB_0_255_8BIT, /* YCbCr 16-235 input to RGB 0-255 output according BT601 that is 8bit clolor depth */
- CSC_ITU709_16_235_TO_RGB_0_255_8BIT /* YCbCr 16-235 input to RGB 0-255 output according BT709 that is 8bit clolor depth */
-};
-
-/* VIC VIDEO FORMAT */
-enum {
- HDMI_VIDEO_FORMAT_NORMAL = 0,
- HDMI_VIDEO_FORMAT_4Kx2K,
- HDMI_VIDEO_FORMAT_3D
-};
-
-#define HDMI_SCL_RATE (100*1000)
-#define DDC_I2C_EDID_ADDR 0x50 /* 0xA0/2 = 0x50 */
-#define DDC_I2C_SEG_ADDR 0x30 /* 0x60/2 = 0x30 */
-
-/* Register and Field Descriptions */
-/* Identification Registers */
-#define IDENTIFICATION_BASE 0x0000
-
-#define DESIGN_ID 0x0000
-#define REVISION_ID 0x0001
-#define PRODUCT_ID0 0x0002
-#define PRODUCT_ID1 0x0003
-
-#define CONFIG0_ID 0x0004
-#define m_PREPEN (1 << 7)
-#define m_AUDSPDIF (1 << 5)
-#define m_AUDI2S (1 << 4)
-#define m_HDMI14 (1 << 3)
-#define m_CSC (1 << 2)
-#define m_CEC (1 << 1)
-#define m_HDCP (1 << 0)
-
-#define CONFIG1_ID 0x0005
-#define m_HDMI20 (1 << 5)
-#define m_CONFAPB (1 << 1)
-
-#define CONFIG2_ID 0x0006
-enum PHYTYPE {
- HDMI_TX_PHY = 0x00,
- HDMI_MHL_WITH_HEAC_PHY = 0xb2,
- HDMI_MHL_PHY = 0xc2,
- HDMI_3D_TX_WITH_HEAC_PHY = 0xe2,
- HDMI_3D_TX_PHY = 0xf2
-};
-
-#define CONFIG3_ID 0x0007
-#define m_AHB_AUD_DMA (1 << 1)
-#define m_GP_AUD (1 << 0)
-
-/* Interrupt Registers */
-#define INTERRUPT_BASE 0x0100
-
-#define IH_FC_STAT0 0x0100
-#define m_AUD_INFOFRAME (1 << 7)
-#define m_AUD_CONTENT_PROTECT (1 << 6)
-#define m_AUD_HBR (1 << 5)
-#define m_AUD_SAMPLE (1 << 2)
-#define m_AUD_CLK_REGEN (1 << 1)
-#define m_NULL_PACKET (1 << 0)
-
-#define IH_FC_STAT1 0x0101
-#define m_GMD (1 << 7)
-#define m_ISCR1 (1 << 6)
-#define m_ISCR2 (1 << 5)
-#define m_VSD (1 << 4)
-#define m_SPD (1 << 3)
-#define m_AVI_INFOFRAME (1 << 1)
-#define m_GCP (1 << 0)
-
-#define IH_FC_STAT2 0x0102
-#define m_LOWPRIO_OVERFLOW (1 << 1)
-#define m_HIGHPRIO_OVERFLOW (1 << 0)
-
-#define IH_AS_SATA0 0x0103
-#define m_FIFO_UNDERRUN (1 << 4)
-#define m_FIFO_OVERRUN (1 << 3)
-#define m_AUD_FIFO_UDFLOW_THR (1 << 2)
-#define m_AUD_FIFO_UDFLOW (1 << 1)
-#define m_AUD_FIFO_OVERFLOW (1 << 0)
-
-#define IH_PHY_STAT0 0x0104
-#define m_RX_SENSE3 (1 << 5)
-#define m_RX_SENSE2 (1 << 4)
-#define m_RX_SENSE1 (1 << 3)
-#define m_RX_SENSE0 (1 << 2)
-#define m_TX_PHY_LOCK (1 << 1)
-#define m_HPD (1 << 0)
-
-#define IH_I2CM_STAT0 0x0105
-#define m_SCDC_READREQ (1 << 2)
-#define m_I2CM_DONE (1 << 1)
-#define m_I2CM_ERROR (1 << 0)
-
-#define IH_CEC_STAT0 0x0106
-#define m_WAKEUP (1 << 6)
-#define m_ERR_FOLLOW (1 << 5)
-#define m_ERR_INITIATOR (1 << 4)
-#define m_ARB_LOST (1 << 3)
-#define m_NACK (1 << 2)
-#define m_EOM (1 << 1)
-#define m_DONE (1 << 0)
-
-#define IH_VP_STAT0 0x0107
-#define m_FIFOFULL_REPET (1 << 7)
-#define m_FIFOEMPTY_REPET (1 << 6)
-#define m_FIFOFULL_PACK (1 << 5)
-#define m_FIFOEMPTY_PACK (1 << 4)
-#define m_FIFOFULL_REMAP (1 << 3)
-#define m_FIFOEMPTY_REMAP (1 << 2)
-#define m_FIFOFULL_BYPASS (1 << 1)
-#define m_FIFOEMPTY_BYPASS (1 << 0)
-
-#define IH_I2CMPHY_STAT0 0x0108
-#define m_I2CMPHY_DONE (1 << 1)
-#define m_I2CMPHY_ERR (1 << 0)
-
-#define IH_AHBDMAAUD_STAT0 0x0109
-#define m_AUDDMA_INT_BUFOVERRUN (1 << 6)
-#define m_AUDDMA_INT_ERR (1 << 5)
-#define m_AUDDMA_INT_LOST (1 << 4)
-#define m_AUDDMA_INT_RETRYSPLIT (1 << 3)
-#define m_AUDDMA_INT_DONE (1 << 2)
-#define m_AUDDMA_INT_BUFFULL (1 << 1)
-#define m_AUDDMA_INT_BUFEMPTY (1 << 0)
-
-#define IH_DECODE 0x0170
-#define m_IH_FC_STAT0 (1 << 7)
-#define m_IH_FC_STAT1 (1 << 6)
-#define m_IH_FC_STAT2_VP (1 << 5)
-#define m_IH_AS_STAT0 (1 << 4)
-#define m_IH_PHY (1 << 3)
-#define m_IH_I2CM_STAT0 (1 << 2)
-#define m_IH_CEC_STAT0 (1 << 1)
-#define m_IH_AHBDMAAUD_STAT0 (1 << 0)
-
-#define IH_MUTE_FC_STAT0 0x0180
-#define m_AUDI_MUTE (1 << 7)
-#define m_ACP_MUTE (1 << 6)
-#define m_DST_MUTE (1 << 4)
-#define m_OBA_MUTE (1 << 3)
-#define m_AUDS_MUTE (1 << 2)
-#define m_ACR_MUTE (1 << 1)
-#define m_NULL_MUTE (1 << 0)
-
-#define IH_MUTE_FC_STAT1 0x0181
-#define m_GMD_MUTE (1 << 7)
-#define m_ISCR1_MUTE (1 << 6)
-#define m_ISCR2_MUTE (1 << 5)
-#define m_VSD_MUTE (1 << 4)
-#define m_SPD_MUTE (1 << 3)
-#define m_AVI_MUTE (1 << 1)
-#define m_GCP_MUTE (1 << 0)
-
-#define IH_MUTE_FC_STAT2 0x0182
-#define m_LPRIO_OVERFLOW_MUTE (1 << 1)
-#define m_HPRIO_OVERFLOW_MUTE (1 << 0)
-
-#define IH_MUTE_AS_STAT0 0x0183
-#define m_FIFO_UNDERRUN_MUTE (1 << 4)
-#define m_FIFO_OVERRUN_MUTE (1 << 3)
-#define m_AUD_FIFO_UDF_THR_MUTE (1 << 2)
-#define m_AUD_FIFO_UDF_MUTE (1 << 1)
-#define m_AUD_FIFO_OVF_MUTE (1 << 0)
-
-#define IH_MUTE_PHY_STAT0 0x0184
-#define m_RX_SENSE3_MUTE (1 << 5)
-#define m_RX_SENSE2_MUTE (1 << 4)
-#define m_RX_SENSE1_MUTE (1 << 3)
-#define m_RX_SENSE0_MUTE (1 << 2)
-#define m_TX_PHY_LOCK_MUTE (1 << 1)
-#define m_HPD_MUTE (1 << 0)
-
-#define IH_MUTE_I2CM_STAT0 0x0185
-#define m_SCDC_READREQ_MUTE (1 << 2)
-#define v_SCDC_READREQ_MUTE(n) (((n)&0x01) << 2)
-#define m_I2CM_DONE_MUTE (1 << 1)
-#define v_I2CM_DONE_MUTE(n) (((n)&0x01) << 1)
-#define m_I2CM_ERR_MUTE (1 << 0)
-#define v_I2CM_ERR_MUTE(n) (((n)&0x01) << 0)
-
-#define IH_MUTE_CEC_STAT0 0x0186
-#define m_WAKEUP_MUTE (1 << 6)
-#define m_ERR_FOLLOW_MUTE (1 << 5)
-#define m_ERR_INITIATOR_MUTE (1 << 4)
-#define m_ARB_LOST_MUTE (1 << 3)
-#define m_NACK_MUTE (1 << 2)
-#define m_EOM_MUTE (1 << 1)
-#define m_DONE_MUTE (1 << 0)
-
-#define IH_MUTE_VP_STAT0 0x0187
-#define m_FIFOFULL_REP_MUTE (1 << 7)
-#define m_FIFOEMPTY_REP_MUTE (1 << 6)
-#define m_FIFOFULL_PACK_MUTE (1 << 5)
-#define m_FIFOEMPTY_PACK_MUTE (1 << 4)
-#define m_FIFOFULL_REMAP_MUTE (1 << 3)
-#define m_FIFOEMPTY_REMAP_MUTE (1 << 2)
-#define m_FIFOFULL_BYP_MUTE (1 << 1)
-#define m_FIFOEMPTY_BYP_MUTE (1 << 0)
-
-#define IH_MUTE_I2CMPHY_STAT0 0x0188
-#define m_I2CMPHY_DONE_MUTE (1 << 1)
-#define m_I2CMPHY_ERR_MUTE (1 << 0)
-
-#define IH_MUTE_AHBDMAAUD_STAT0 0x0189
-#define IH_MUTE 0x01ff
-
-/* Video Sampler Registers */
-#define VIDEO_SAMPLER_BASE 0x0200
-
-#define TX_INVID0 0x0200
-#define m_INTERNAL_DE_GEN (1 << 7)
-#define v_INTERNAL_DE_GEN(n) (((n)&0x01) << 7)
-enum VIDEO_MODE {
- VIDEO_RGB444_8BIT = 0x01,
- VIDEO_RGB444_10BIT = 0x03,
- VIDEO_RGB444_12BIT = 0x05,
- VIDEO_RGB444_16BIT = 0x07,
- VIDEO_YCBCR444_8BIT = 0x09, /* or YCbCr420 */
- VIDEO_YCBCR444_10BIT = 0x0b, /* or YCbCr420 */
- VIDEO_YCBCR444_12BIT = 0x0d, /* or YCbCr420 */
- VIDEO_YCBCR444_16BIT = 0x0f, /* or YCbCr420 */
- VIDEO_YCBCR422_12BIT = 0x12,
- VIDEO_YCBCR422_10BIT = 0x14,
- VIDEO_YCBCR422_8BIT = 0x16
-};
-#define m_VIDEO_MAPPING (0x1f << 0)
-#define v_VIDEO_MAPPING(n) ((n)&0x1f)
-
-#define TX_INSTUFFING 0x0201
-#define m_BCBDATA_STUFF (1 << 2)
-#define v_BCBDATA_STUFF(n) (((n)&0x01) << 2)
-#define m_RCRDATA_STUFF (1 << 1)
-#define v_RCRDATA_STUFF(n) (((n)&0x01) << 1)
-#define m_GYDATA_STUFF (1 << 0)
-#define v_GYDATA_STUFF(n) (((n)&0x01) << 0)
-
-#define TX_GYDATA0 0x0202
-#define TX_GYDATA1 0x0203
-#define TX_RCRDATA0 0x0204
-#define TX_RCRDATA1 0x0205
-#define TX_BCBDATA0 0x0206
-#define TX_BCBDATA1 0x0207
-
-/* Video Packetizer Registers */
-#define VIDEO_PACKETIZER_BASE 0x0800
-
-#define VP_STATUS 0x0800
-#define m_PACKING_PHASE (0x0f << 0)
-
-#define VP_PR_CD 0x0801
-enum COLOR_DEPTH {
- COLOR_DEPTH_24BIT_DEFAULT = 0,
- COLOR_DEPTH_24BIT = 0x04,
- COLOR_DEPTH_30BIT,
- COLOR_DEPTH_36BIT,
- COLOR_DEPTH_48BIT
-};
-#define m_COLOR_DEPTH (0x0f << 4)
-#define v_COLOR_DEPTH(n) (((n)&0x0f) << 4)
-enum PIXEL_REPET {
- NO_PIXEL_REPET = 0,
- PIXEL_SENT_2TIMES,
- PIXEL_SENT_3TIMES,
- PIXEL_SENT_4TIMES,
- PIXEL_SENT_5TIMES,
- PIXEL_SENT_6TIMES,
- PIXEL_SENT_7TIMES,
- PIXEL_SENT_8TIMES,
- PIXEL_SENT_9TIMES,
- PIXEL_SENT_10TIMES
-};
-#define m_DESIRED_PR_FACTOR (0x0f << 0)
-#define v_DESIRED_PR_FACTOR(n) (((n)&0x0f) << 0)
-
-#define VP_STUFF 0x0802
-#define m_IDEFAULT_PHASE (1 << 5)
-#define v_IDEFAULT_PHASE(n) (((n)&0x01) << 5)
-#define m_IFIX_PP_TO_LAST (1 << 4)
-#define m_ICX_GOTO_P0_ST (1 << 3)
-enum {
- DIRECT_MODE = 0,
- STUFFING_MODE
-};
-#define m_YCC422_STUFFING (1 << 2)
-#define v_YCC422_STUFFING(n) (((n)&0x01) << 2)
-#define m_PP_STUFFING (1 << 1)
-#define v_PP_STUFFING(n) (((n)&0x01) << 1)
-#define m_PR_STUFFING (1 << 0)
-#define v_PR_STUFFING(n) (((n)&0x01) << 0)
-
-#define VP_REMAP 0x0803
-enum YCC422_SIZE {
- YCC422_16BIT = 0,
- YCC422_20BIT,
- YCC422_24BIT
-};
-#define m_YCC422_SIZE (0x03 << 0)
-#define v_YCC422_SIZE(n) (((n)&0x03) << 0)
-
-#define VP_CONF 0x0804
-#define m_BYPASS_EN (1 << 6)
-#define v_BYPASS_EN(n) (((n)&0x01) << 6)
-#define m_PIXEL_PACK_EN (1 << 5)
-#define v_PIXEL_PACK_EN(n) (((n)&0x01) << 5)
-#define m_PIXEL_REPET_EN (1 << 4)
-#define v_PIXEL_REPET_EN(n) (((n)&0x01) << 4)
-#define m_YCC422_EN (1 << 3)
-#define v_YCC422_EN(n) (((n)&0x01) << 3)
-#define m_BYPASS_SEL (1 << 2)
-#define v_BYPASS_SEL(n) (((n)&0x01) << 2)
-enum {
- OUT_FROM_PIXEL_PACKING = 0,
- OUT_FROM_YCC422_REMAP,
- OUT_FROM_8BIT_BYPASS
-};
-#define m_OUTPUT_SEL (0x03 << 0)
-#define v_OUTPUT_SEL(n) ((n&0x03) << 0)
-
-#define VP_MASK 0x0807
-#define m_OINTFULL_REPET (1 << 7)
-#define m_OINTEMPTY_REPET (1 << 6)
-#define m_OINTFULL_PACK (1 << 5)
-#define m_OINTEMPTY_PACK (1 << 4)
-#define m_OINTFULL_REMAP (1 << 3)
-#define m_OINTEMPTY_REMAP (1 << 2)
-#define m_OINTFULL_BYPASS (1 << 1)
-#define m_OINTEMPTY_BYPASS (1 << 0)
-
-/* Frame Composer Registers */
-#define FRAME_COMPOSER_BASE 0x1000
-
-#define FC_INVIDCONF 0x1000
-#define m_FC_HDCP_KEEPOUT (1 << 7)
-#define v_FC_HDCP_KEEPOUT(n) (((n)&0x01) << 7)
-#define m_FC_VSYNC_POL (1 << 6)
-#define v_FC_VSYNC_POL(n) (((n)&0x01) << 6)
-#define m_FC_HSYNC_POL (1 << 5)
-#define v_FC_HSYNC_POL(n) (((n)&0x01) << 5)
-#define m_FC_DE_POL (1 << 4)
-#define v_FC_DE_POL(n) (((n)&0x01) << 4)
-#define m_FC_HDMI_DVI (1 << 3)
-#define v_FC_HDMI_DVI(n) (((n)&0x01) << 3)
-#define m_FC_VBLANK (1 << 1)
-#define v_FC_VBLANK(n) (((n)&0x01) << 1)
-#define m_FC_INTERLACE_MODE (1 << 0)
-#define v_FC_INTERLACE_MODE(n) (((n)&0x01) << 0)
-
-#define FC_INHACTIV0 0x1001
-
-#define FC_INHACTIV1 0x1002
-#define v_FC_HACTIVE1(n) ((n) & 0x3f)
-#define m_FC_H_ACTIVE_13 (1 << 5)
-#define v_FC_H_ACTIVE_13(n) (((n)&0x01) << 5)
-#define m_FC_H_ACTIVE_12 (1 << 4)
-#define v_FC_H_ACTIVE_12(n) (((n)&0x01) << 4)
-#define m_FC_H_ACTIVE (0x0f << 0)
-#define v_FC_H_ACTIVE(n) (((n)&0x0f) << 0)
-
-#define FC_INHBLANK0 0x1003
-
-#define FC_INHBLANK1 0x1004
-#define v_FC_HBLANK1(n) ((n) & 0x1f)
-#define m_FC_H_BLANK_12_11 (0x07 << 2)
-#define v_FC_H_BLANK_12_11(n) (((n)&0x07) << 2)
-#define m_FC_H_BLANK (0x03 << 0)
-#define v_FC_H_BLANK(n) (((n)&0x03) << 0)
-
-#define FC_INVACTIV0 0x1005
-
-#define FC_INVACTIV1 0x1006
-#define v_FC_VACTIVE1(n) ((n) & 0x1f)
-#define m_FC_V_ACTIVE_12_11 (0x03 << 3)
-#define v_FC_V_ACTIVE_12_11(n) (((n)&0x03) << 3)
-#define m_FC_V_ACTIVE (0x07 << 0)
-#define v_FC_V_ACTIVE(n) (((n)&0x07) << 0)
-
-#define FC_INVBLANK 0x1007
-#define FC_HSYNCINDELAY0 0x1008
-
-#define FC_HSYNCINDELAY1 0x1009
-#define v_FC_HSYNCINDEAY1(n) ((n) & 0x1f)
-#define m_FC_H_SYNCFP_12_11 (0x03 << 3)
-#define v_FC_H_SYNCFP_12_11(n) (((n)&0x03) << 3)
-#define m_FC_H_SYNCFP (0x07 << 0)
-#define v_FC_H_SYNCFP(n) (((n)&0x07) << 0)
-
-#define FC_HSYNCINWIDTH0 0x100a
-
-#define FC_HSYNCINWIDTH1 0x100b
-#define v_FC_HSYNCWIDTH1(n) ((n) & 0x03)
-#define m_FC_HSYNC_9 (1 << 1)
-#define v_FC_HSYNC_9(n) (((n)&0x01) << 1)
-#define m_FC_HSYNC (1 << 0)
-#define v_FC_HSYNC(n) (((n)&0x01) << 0)
-
-#define FC_VSYNCINDELAY 0x100c
-#define FC_VSYNCINWIDTH 0x100d
-#define FC_INFREQ0 0x100e
-#define FC_INFREQ1 0x100f
-#define FC_INFREQ2 0x1010
-#define FC_CTRLDUR 0x1011
-#define FC_EXCTRLDUR 0x1012
-#define FC_EXCTRLSPAC 0x1013
-#define FC_CH0PREAM 0x1014
-#define FC_CH1PREAM 0x1015
-#define FC_CH2PREAM 0x1016
-
-#define FC_AVICONF3 0x1017
-enum YCC_QUAN_RANGE {
- YQ_LIMITED_RANGE = 0,
- YQ_FULL_RANGE,
- RESERVED,
-};
-#define m_FC_YQ (0x03 << 2)
-#define v_FC_YQ(n) (((n)&0x03) << 2)
-enum IT_CONTENT_TYPE {
- CN_GRAPHICS = 0,
- CN_PHOTO,
- CN_CINEMA,
- CN_GAME,
-};
-#define m_FC_CN (0x03 << 0)
-#define v_FC_CN(n) (((n)&0x03) << 0)
-
-#define FC_GCP 0x1018
-#define m_FC_DEFAULT_PHASE (1 << 2)
-#define v_FC_DEFAULT_PHASE(n) (((n)&0x01) << 2)
-#define m_FC_SET_AVMUTE (1 << 1)
-#define v_FC_SET_AVMUTE(n) (((n)&0x01) << 1)
-#define m_FC_CLR_AVMUTE (1 << 0)
-#define v_FC_CLR_AVMUTE(n) (((n)&0x01) << 0)
-
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444,
- AVI_COLOR_MODE_YCBCR420
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-enum {
- AVI_QUANTIZATION_RANGE_DEFAULT = 0,
- AVI_QUANTIZATION_RANGE_LIMITED,
- AVI_QUANTIZATION_RANGE_FULL
-};
-
-#define FC_AVICONF0 0x1019
-#define m_FC_RGC_YCC_2 (1 << 7) /* use for HDMI2.0 TX */
-#define v_FC_RGC_YCC_2(n) (((n)&0x01) << 7)
-#define m_FC_ACTIV_FORMAT (1 << 6)
-#define v_FC_ACTIV_FORMAT(n) (((n)&0x01) << 6)
-#define m_FC_SCAN_INFO (0x03 << 4)
-#define v_FC_SCAN_INFO(n) (((n)&0x03) << 4)
-#define m_FC_BAR_FORMAT (0x03 << 2)
-#define v_FC_BAR_FORMAT(n) (((n)&0x03) << 2)
-#define m_FC_RGC_YCC (0x03 << 0)
-#define v_FC_RGC_YCC(n) (((n)&0x03) << 0)
-
-#define FC_AVICONF1 0x101a
-#define m_FC_COLORIMETRY (0x03 << 6)
-#define v_FC_COLORIMETRY(n) (((n)&0x03) << 6)
-#define m_FC_PIC_ASPEC_RATIO (0x03 << 4)
-#define v_FC_PIC_ASPEC_RATIO(n) (((n)&0x03) << 4)
-#define m_FC_ACT_ASPEC_RATIO (0x0f << 0)
-#define v_FC_ACT_ASPEC_RATIO(n) (((n)&0x0f) << 0)
-
-#define FC_AVICONF2 0x101b
-#define m_FC_IT_CONTENT (1 << 7)
-#define v_FC_IT_CONTENT(n) (((n)&0x01) << 7)
-#define m_FC_EXT_COLORIMETRY (0x07 << 4)
-#define v_FC_EXT_COLORIMETRY(n) (((n)&0x07) << 4)
-#define m_FC_QUAN_RANGE (0x03 << 2)
-#define v_FC_QUAN_RANGE(n) (((n)&0x03) << 2)
-#define m_FC_NUN_PIC_SCALE (0x03 << 0)
-#define v_FC_NUN_PIC_SCALE(n) (((n)&0x03) << 0)
-
-#define FC_AVIVID 0x101c
-#define m_FC_AVIVID_H (1 << 7) /* use for HDMI2.0 TX */
-#define v_FC_AVIVID_H(n) (((n)&0x01) << 7)
-#define m_FC_AVIVID (0x7f << 0)
-#define v_FC_AVIVID(n) (((n)&0x7f) << 0)
-
-#define FC_AVIETB0 0x101d
-#define FC_AVIETB1 0x101e
-#define FC_AVISBB0 0x101f
-#define FC_AVISBB1 0x1020
-#define FC_AVIELB0 0x1021
-#define FC_AVIELB1 0x1022
-#define FC_AVISRB0 0x1023
-#define FC_AVISRB1 0x1024
-
-#define FC_AUDICONF0 0x1025
-#define m_FC_CHN_CNT (0x07 << 4)
-#define v_FC_CHN_CNT(n) (((n)&0x07) << 4)
-#define m_FC_CODING_TYEP (0x0f << 0)
-#define v_FC_CODING_TYEP(n) (((n)&0x0f) << 0)
-
-#define FC_AUDICONF1 0x1026
-#define m_FC_SAMPLE_SIZE (0x03 << 4)
-#define v_FC_SAMPLE_SIZE(n) (((n)&0x03) << 4)
-#define m_FC_SAMPLE_FREQ (0x07 << 0)
-#define v_FC_SAMPLE_FREQ(n) (((n)&0x07) << 0)
-
-#define FC_AUDICONF2 0x1027
-
-#define FC_AUDICONF3 0x1028
-#define m_FC_LFE_PBL (0x03 << 5) /* only use for HDMI1.4 TX */
-#define v_FC_LFE_PBL(n) (((n)&0x03) << 5)
-#define m_FC_DM_INH (1 << 4)
-#define v_FC_DM_INH(n) (((n)&0x01) << 4)
-#define m_FC_LSV (0x0f << 0)
-#define v_FC_LSV(n) (((n)&0x0f) << 0)
-
-#define FC_VSDIEEEID2 0x1029
-#define FC_VSDSIZE 0x102a
-#define FC_VSDIEEEID1 0x1030
-#define FC_VSDIEEEID0 0x1031
-#define FC_VSDPAYLOAD0 0x1032 /* 0~23 */
-#define FC_SPDVENDORNAME0 0x104a /* 0~7 */
-#define FC_SPDPRODUCTNAME0 0x1052 /* 0~15 */
-#define FC_SPDDEVICEINF 0x1062
-
-#define FC_AUDSCONF 0x1063
-#define m_AUD_PACK_SAMPFIT (0x0f << 4)
-#define v_AUD_PACK_SAMPFIT(n) (((n)&0x0f) << 4)
-#define m_AUD_PACK_LAYOUT (1 << 0)
-#define v_AUD_PACK_LAYOUT(n) (((n)&0x01) << 0)
-
-#define FC_AUDSSTAT 0x1064
-#define FC_AUDSV 0x1065
-#define FC_AUDSU 0x1066
-#define FC_AUDSCHNLS0 0x1067 /* 0~8 */
-#define FC_CTRLQHIGH 0x1073
-#define FC_CTRLQLOW 0x1074
-#define FC_ACP0 0x1075
-#define FC_ACP16 0x1082 /* 16~1 */
-#define FC_ISCR1_0 0x1092
-#define FC_ISCR1_16 0x1093 /* 16~1 */
-#define FC_ISCR2_15 0x10a3 /* 15~0 */
-
-#define FC_DATAUTO0 0x10b3
-#define m_SPD_AUTO (1 << 4)
-#define v_SPD_AUTO(n) (((n)&0x01) << 4)
-#define m_VSD_AUTO (1 << 3)
-#define v_VSD_AUTO(n) (((n)&0x01) << 3)
-#define m_ISCR2_AUTO (1 << 2)
-#define v_ISCR2_AUTO(n) (((n)&0x01) << 2)
-#define m_ISCR1_AUTO (1 << 1)
-#define v_ISCR1_AUTO(n) (((n)&0x01) << 1)
-#define m_ACP_AUTO (1 << 0)
-#define v_ACP_AUTO(n) (((n)&0x01) << 0)
-
-#define FC_DATAUTO1 0x10b4
-#define FC_DATAUTO2 0x10b5
-
-#define FC_DATMAN 0x10b6
-#define m_SPD_MAN (1 << 4)
-#define v_SPD_MAN(n) (((n)&0x01) << 4)
-#define m_VSD_MAN (1 << 3)
-#define v_VSD_MAN(n) (((n)&0x01) << 3)
-#define m_ISCR2_MAN (1 << 2)
-#define v_ISCR2_MAN(n) (((n)&0x01) << 2)
-#define m_ISCR1_MAN (1 << 1)
-#define v_ISCR1_MAN(n) (((n)&0x01) << 1)
-#define m_ACP_MAN (1 << 0)
-#define v_ACP_MAN(n) (((n)&0x01) << 0)
-
-#define FC_DATAUTO3 0x10b7
-#define FC_RDRB0 0x10b8
-#define FC_RDRB1 0x10b9
-#define FC_RDRB2 0x10ba
-#define FC_RDRB3 0x10bb
-#define FC_RDRB4 0x10bc
-#define FC_RDRB5 0x10bd
-#define FC_RDRB6 0x10be
-#define FC_RDRB7 0x10bf
-#define FC_MASK0 0x10d2
-#define FC_MASK1 0x10d6
-#define FC_MASK2 0x10da
-
-#define FC_PRCONF 0x10e0
-#define m_FC_PR_FACTOR (0x0f << 4)
-#define v_FC_PR_FACTOR(n) (((n)&0x0f) << 4)
-
-#define FC_SCRAMBLER_CTRL 0x10e1
-#define m_FC_SCRAMBLE_UCP (1 << 4)
-#define v_FC_SCRAMBLE_UCP(n) (((n)&0x01) << 4)
-#define m_FC_SCRAMBLE_EN (1 << 0)
-#define v_FC_SCRAMBLE_EN(n) (((n)&0x01) << 0)
-
-#define FC_GMD_STAT 0x1100
-#define FC_GMD_EN 0x1101
-#define FC_GMD_UP 0x1102
-#define FC_GMD_CONF 0x1103
-#define FC_GMD_HB 0x1104
-#define FC_GMD_PB0 0x1105 /* 0~27 */
-
-#define FC_DBGFORCE 0x1200
-#define m_FC_FORCEAUDIO (1 << 4)
-#define v_FC_FORCEAUDIO(n) (((n)&0x01) << 4)
-#define m_FC_FORCEVIDEO (1 << 0)
-#define v_FC_FORCEVIDEO(n) (((n)&0x01) << 0)
-
-#define FC_DBGAUD0CH0 0x1201 /* aud0~aud2 ch0 */
-#define FC_DBGAUD0CH1 0x1204 /* aud0~aud2 ch1 */
-#define FC_DBGAUD0CH2 0x1207 /* aud0~aud2 ch2 */
-#define FC_DBGAUD0CH3 0x120a /* aud0~aud2 ch3 */
-#define FC_DBGAUD0CH4 0x120d /* aud0~aud2 ch4 */
-#define FC_DBGAUD0CH5 0x1210 /* aud0~aud2 ch5 */
-#define FC_DBGAUD0CH6 0x1213 /* aud0~aud2 ch6 */
-#define FC_DBGAUD0CH7 0x1216 /* aud0~aud2 ch7 */
-#define FC_DBGTMDS0 0x1219
-#define FC_DBGTMDS1 0x121a
-#define FC_DBGTMDS2 0x121b
-
-/* HDMI Source PHY Registers */
-#define HDMI_SOURCE_PHY_BASE 0x3000
-
-#define PHY_CONF0 0x3000
-#define m_POWER_DOWN_EN (1 << 7) /* enable depend on PHY_GEN2=0 and PHY_EXTERNAL=0 */
-#define v_POWER_DOWN_EN(n) (((n)&0x01) << 7)
-#define m_TMDS_EN (1 << 6) /* enable depend on PHY_GEN2=0 and PHY_EXTERNAL=0 */
-#define v_TMDS_EN(n) (((n)&0x01) << 6)
-#define m_SVSRET_SIG (1 << 5) /* depend on PHY_MHL_COMB0=1 */
-#define v_SVSRET_SIG(n) (((n)&0x01) << 5)
-#define m_PDDQ_SIG (1 << 4) /* depend on PHY_GEN2=1 or PHY_EXTERNAL=1 */
-#define v_PDDQ_SIG(n) (((n)&0x01) << 4)
-#define m_TXPWRON_SIG (1 << 3) /* depend on PHY_GEN2=1 or PHY_EXTERNAL=1 */
-#define v_TXPWRON_SIG(n) (((n)&0x01) << 3)
-#define m_ENHPD_RXSENSE_SIG (1 << 2) /* depend on PHY_GEN2=1 or PHY_EXTERNAL=1 */
-#define v_ENHPD_RXSENSE_SIG(n) (((n)&0x01) << 2)
-#define m_SEL_DATAEN_POL (1 << 1)
-#define v_SEL_DATAEN_POL(n) (((n)&0x01) << 1)
-#define m_SEL_INTERFACE (1 << 0)
-#define v_SEL_INTERFACE(n) (((n)&0x01) << 0)
-
-#define PHY_TST0 0x3001
-#define m_TEST_CLR_SIG (1 << 5)
-#define m_TEST_EN_SIG (1 << 4)
-#define m_TEST_CLK_SIG (1 << 0)
-
-#define PHY_TST1 0x3002
-#define PHY_TST2 0x3003
-#define PHY_STAT0 0x3004
-#define PHY_INI0 0x3005
-#define PHY_MASK 0x3006
-#define PHY_POL0 0x3007
-#define m_PHY_RX_SENSE3 (1 << 7)
-#define v_PHY_TX_SENSE3(n) (((n)&0x01) << 7)
-#define m_PHY_RX_SENSE2 (1 << 6)
-#define v_PHY_TX_SENSE2(n) (((n)&0x01) << 6)
-#define m_PHY_RX_SENSE1 (1 << 5)
-#define v_PHY_TX_SENSE1(n) (((n)&0x01) << 5)
-#define m_PHY_RX_SENSE0 (1 << 4)
-#define v_PHY_TX_SENSE0(n) (((n)&0x01) << 4)
-#define m_PHY_HPD (1 << 1)
-#define v_PHY_HPD (((n)&0x01) << 1)
-#define m_PHY_LOCK (1 << 0)
-#define v_PHY_LOCK(n) (((n)&0x01) << 0)
-
-#define PHY_PCLFREQ0 0x3008
-#define PHY_PCLFREQ1 0x3009
-#define PHY_PLLCFGFREQ0 0x300a
-#define PHY_PLLCFGFREQ1 0x300b
-#define PHY_PLLCFGFREQ2 0x300c
-
-/* I2C Master PHY Registers */
-#define I2C_MASTER_PHY_BASE 0x3020
-
-#define PHY_I2CM_SLAVE 0x3020
-#define PHY_GEN2_ADDR 0x69
-#define PHY_HEAC_ADDR 0x49
-#define PHY_I2C_SLAVE_ADDR 0x54
-
-#define PHY_I2CM_ADDRESS 0x3021
-#define PHY_I2CM_DATAO_1 0x3022
-#define PHY_I2CM_DATAO_0 0x3023
-#define PHY_I2CM_DATAI_1 0x3024
-#define PHY_I2CM_DATAI_0 0x3025
-
-#define PHY_I2CM_OPERATION 0x3026
-#define m_PHY_I2CM_WRITE (1 << 4)
-#define m_PHY_I2CM_READ (1 << 0)
-
-#define PHY_I2CM_INT 0x3027
-#define m_PHY_I2CM_DONE_INT_POL (1 << 3)
-#define v_PHY_I2CM_DONE_INT_POL(n) (((n)&0x01) << 3)
-#define m_PHY_I2CM_DONE_MASK (1 << 2)
-#define v_PHY_I2CM_DONE_MASK(n) (((n)&0x01) << 2)
-#define m_PHY_I2CM_DONE_INT (1 << 1)
-#define m_PHY_I2CM_DONE_STATUS (1 << 0)
-
-#define PHY_I2CM_CTLINT 0x3028
-#define m_PHY_I2CM_NACK_POL (1 << 7)
-#define v_PHY_I2CM_NACK_POL(n) (((n)&0x01) << 7)
-#define m_PHY_I2CM_NACK_MASK (1 << 6)
-#define v_PHY_I2CM_NACK_MASK(n) (((n)&0x01) << 6)
-#define m_PHY_I2CM_NACK_INT (1 << 5)
-#define m_PHY_I2CM_NACK_STATUS (1 << 4)
-#define m_PHY_I2CM_ARB_POL (1 << 3)
-#define v_PHY_I2CM_ARB_POL(n) (((n)&0x01) << 3)
-#define m_PHY_I2CM_ARB_MASK (1 << 2)
-#define v_PHY_I2CM_ARB_MASK(n) (((n)&0x01) << 2)
-#define m_PHY_I2CM_ARB_INT (1 << 1)
-#define m_PHY_I2CM_ARB_STATUS (1 << 0)
-
-#define PHY_I2CM_DIV 0x3029
-#define m_PHY_I2CM_FAST_STD (1 << 3)
-#define v_PHY_I2CM_FAST_STD(n) (((n)&0x01) << 3)
-
-#define PHY_I2CM_SOFTRSTZ 0x302a
-#define m_PHY_I2CM_SOFTRST (1 << 0)
-#define v_PHY_I2CM_SOFTRST(n) (((n)&0x01) << 0)
-
-#define PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
-#define PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
-#define PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
-#define PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
-#define PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
-#define PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
-#define PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
-#define PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
-#define PHY_I2CM_SDA_HOLD 0x3033
-
-/* Audio Sampler Registers */
-#define AUDIO_SAMPLER_BASE 0x3100
-
-#define AUD_CONF0 0x3100
-#define m_SW_AUD_FIFO_RST (1 << 7)
-#define v_SW_AUD_FIFO_RST(n) (((n)&0x01) << 7)
-enum {
- AUDIO_SPDIF_GPA = 0,
- AUDIO_I2S
-};
-#define m_I2S_SEL (1 << 5)
-#define v_I2S_SEL(n) (((n)&0x01) << 5)
-enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
-};
-#define m_I2S_IN_EN (0x0f << 0)
-#define v_I2S_IN_EN(n) (((n)&0x0f) << 0)
-
-#define AUD_CONF1 0x3101
-enum I2S_MODE {
- I2S_STANDARD_MODE = 0,
- I2S_RIGHT_JUSTIFIED_MODE,
- I2S_LEFT_JUSTIFIED_MODE,
- I2S_BURST_1_MODE,
- I2S_BURST_2_MODE
-};
-#define m_I2S_MODE (0x07 << 5)
-#define v_I2S_MODE(n) (((n)&0x07) << 5)
-enum I2S_WIDTH {
- I2S_16BIT_SAMPLE = 16,
- I2S_17BIT_SAMPLE,
- I2S_18BIT_SAMPLE,
- I2S_19BIT_SAMPLE,
- I2S_20BIT_SAMPLE,
- I2S_21BIT_SAMPLE,
- I2S_22BIT_SAMPLE,
- I2S_23BIT_SAMPLE,
- I2S_24BIT_SAMPLE,
-};
-#define m_I2S_WIDTH (0x1f << 0)
-#define v_I2S_WIDTH(n) (((n)&0x1f) << 0)
-
-#define AUD_INT 0x3102
-#define AUD_SPDIFINT 0x3302
-#define m_FIFO_EMPTY_MASK (1 << 3)
-#define v_FIFO_EMPTY_MASK(n) (((n)&0x01) << 3)
-#define m_FIFO_FULL_MASK (1 << 2)
-#define v_FIFO_FULL_MASK(n) (((n)&0x01) << 2)
-
-#define AUD_CONF2 0x3103
-#define m_NLPCM_EN (1 << 1)
-#define v_NLPCM_EN(n) (((n)&0x01) << 1)
-#define m_HBR_EN (1 << 0)
-#define v_HBR_EN(n) (((n)&0x01) << 0)
-
-#define AUD_INT1 0x3104
-#define AUD_SPDIFINT1 0x3303
-#define m_FIFO_OVERRUN_MASK (1 << 4)
-#define v_FIFO_OVERRUN_MASK(n) (((n)&0x01) << 4)
-
-/***************N-CTS Table**************/
-/* TMDS LOWCLK: <=148.5M */
-/* TMDS MIDCLK: 297M */
-/* TMDS HIGHCLK: 594M */
-#define N_32K_LOWCLK 0x1000
-#define N_32K_MIDCLK 0x0c00
-#define N_32K_HIGHCLK 0x0c00
-#define N_441K_LOWCLK 0x1880
-#define N_441K_MIDCLK 0x1260
-#define N_441K_HIGHCLK 0x24c0
-#define N_48K_LOWCLK 0x1800
-#define N_48K_MIDCLK 0x1400
-#define N_48K_HIGHCLK 0x1800
-#define N_882K_LOWCLK 0x3100
-#define N_882K_MIDCLK 0x24c0
-#define N_882K_HIGHCLK 0x4980
-#define N_96K_LOWCLK 0x3000
-#define N_96K_MIDCLK 0x2800
-#define N_96K_HIGHCLK 0x3000
-#define N_1764K_LOWCLK 0x6200
-#define N_1764K_MIDCLK 0x4980
-#define N_1764K_HIGHCLK 0x9300
-#define N_192K_LOWCLK 0x6000
-#define N_192K_MIDCLK 0x5000
-#define N_192K_HIGHCLK 0x6000
-
-#define CALC_CTS(N, TMDSCLK, FS) (((N) / 32) * (TMDSCLK) / ((FS) * 4))
-/****************************************/
-
-#define AUD_N1 0x3200
-#define AUD_N2 0x3201
-
-#define AUD_N3 0x3202
-#define m_NCTS_ATOMIC_WR (1 << 7)
-#define v_NCTS_ATOMIC_WR(n) (((n)&0x01) << 7)
-#define m_AUD_N3 (0x0f << 0)
-#define v_AUD_N3(n) (((n)&0x0f) << 0)
-
-#define AUD_CTS1 0x3203
-#define AUD_CTS2 0x3204
-
-#define AUD_CTS3 0x3205
-enum {
- N_SHIFT_1 = 0,
- N_SHIFT_16,
- N_SHIFT_32,
- N_SHIFT_64,
- N_SHIFT_128,
- N_SHIFT_256,
- N_SHIFT_OTHERS_128
-};
-#define m_N_SHIFT (0x07 << 5)
-#define v_N_SHIFT(n) (((n)&0x07) << 5)
-#define m_CTS_MANUAL (1 << 4)
-#define v_CTS_MANUAL(n) (((n)&0x01) << 4)
-#define m_AUD_CTS3 (0x0f << 0)
-#define v_AUD_CTS3(n) (((n)&0x0f) << 0)
-
-#define AUD_INPUTCLKFS 0x3206
-enum {
- FS_128 = 0,
- FS_256,
- FS_512,
- FS_64 = 4,
- FS_OTHERS_128
-};
-#define m_LFS_FACTOR (0x07 << 0)
-#define v_LFS_FACTOR(n) (((n)&0x07) << 0)
-
-#define AUD_SPDIF0 0x3300
-#define m_SW_SAUD_FIFO_RST (1 << 7)
-#define v_SW_SAUD_FIFO_RST(n) (((n)&0x01) << 7)
-
-#define AUD_SPDIF1 0x3301
-enum {
- PCM_LINEAR = 0,
- PCM_NONLINEAR
-};
-#define m_SET_NLPCM (1 << 7)
-#define v_SET_NLPCM(n) (((n)&0x01) << 7)
-#define m_SPDIF_HBR_MODE (1 << 6)
-#define v_SPDIF_HBR_MODE(n) (((n)&0x01) << 6)
-#define m_SPDIF_WIDTH (0x1f << 0)
-#define v_SPDIF_WIDTH(n) (((n)&0x1f) << 0)
-
-/* Generic Parallel Audio Interface Registers */
-#define GP_AUDIO_INTERFACE_BASE 0x3500
-
-#define GP_CONF0 0x3500
-#define GP_CONF1 0x3501
-#define GP_CONF2 0x3502
-#define GP_MASK 0x3506
-
-/* Audio DMA Registers */
-#define AUDIO_DMA_BASE 0x3600
-
-#define AHB_DMA_CONF0 0x3600
-#define AHB_DMA_START 0x3601
-#define AHB_DMA_STOP 0x3602
-#define AHB_DMA_THRSLD 0x3603
-#define AHB_DMA_STRADDR_SET0_0 0x3604 /* 0~3 */
-#define AHB_DMA_STPADDR_SET0_0 0x3608 /* 0~3 */
-#define AHB_DMA_BSTADDR0 0x360c /* 0~3 */
-#define AHB_DMA_MBLENGTH0 0x3610 /* 0~3 */
-#define AHB_DMA_MASK 0x3614
-#define AHB_DMA_CONF1 0x3616
-#define AHB_DMA_BUFFMASK 0x3619
-#define AHB_DMA_MASK1 0x361b
-#define AHB_DMA_STATUS 0x361c
-#define AHB_DMA_CONF2 0x361d
-#define AHB_DMA_STRADDR_SET1_0 0x3620 /* 0~3 */
-#define AHB_DMA_STPADDR_SET1_0 0x3624 /* 0~3 */
-
-/* Main Controller Registers */
-#define MAIN_CONTROLLER_BASE 0x4000
-
-#define MC_CLKDIS 0x4001
-#define m_HDCPCLK_DISABLE (1 << 6)
-#define v_HDCPCLK_DISABLE(n) (((n)&0x01) << 6)
-#define m_CECCLK_DISABLE (1 << 5)
-#define v_CECCLK_DISABLE(n) (((n)&0x01) << 5)
-#define m_CSCCLK_DISABLE (1 << 4)
-#define v_CSCCLK_DISABLE(n) (((n)&0x01) << 4)
-#define m_AUDCLK_DISABLE (1 << 3)
-#define v_AUDCLK_DISABLE(n) (((n)&0x01) << 3)
-#define m_PREPCLK_DISABLE (1 << 2)
-#define v_PREPCLK_DISABLE(n) (((n)&0x01) << 2)
-#define m_TMDSCLK_DISABLE (1 << 1)
-#define v_TMDSCLK_DISABLE(n) (((n)&0x01) << 1)
-#define m_PIXELCLK_DISABLE (1 << 0)
-#define v_PIXELCLK_DISABLE(n) (((n)&0x01) << 0)
-
-#define MC_SWRSTZREQ 0x4002
-#define m_IGPA_SWRST (1 << 7)
-#define v_IGPA_SWRST(n) (((n)&0x01) << 7)
-#define m_CEC_SWRST (1 << 6)
-#define v_CEC_SWRST(n) (((n)&0x01) << 6)
-#define m_ISPDIF_SWRST (1 << 4)
-#define v_ISPDIF_SWRST(n) (((n)&0x01) << 4)
-#define m_II2S_SWRST (1 << 3)
-#define v_II2S_SWRST(n) (((n)&0x01) << 3)
-#define m_PREP_SWRST (1 << 2)
-#define v_PREP_SWRST(n) (((n)&0x01) << 2)
-#define m_TMDS_SWRST (1 << 1)
-#define v_TMDS_SWRST(n) (((n)&0x01) << 1)
-#define m_PIXEL_SWRST (1 << 0)
-#define v_PIXEL_SWRST(n) (((n)&0x01) << 0)
-
-#define MC_OPCTRL 0x4003
-#define m_HDCP_BLOCK_BYP (1 << 0)
-#define v_HDCP_BLOCK_BYP(n) (((n)&0x01) << 0)
-
-#define MC_FLOWCTRL 0x4004
-#define m_FEED_THROUGH_OFF (1 << 0)
-#define v_FEED_THROUGH_OFF(n) (((n)&0x01) << 0)
-
-#define MC_PHYRSTZ 0x4005
-#define m_PHY_RSTZ (1 << 0)
-#define v_PHY_RSTZ(n) (((n)&0x01) << 0)
-
-#define MC_LOCKONCLOCK 0x4006
-#define m_IGPACLK_ON (1 << 7)
-#define v_IGPACLK_ON(n) (((n)&0x01) << 7)
-#define m_PCLK_ON (1 << 6)
-#define v_PCLK_ON(n) (((n)&0x01) << 6)
-#define m_TMDSCLK_ON (1 << 5)
-#define v_TMDSCLK_ON(n) (((n)&0x01) << 5)
-#define m_PREPCLK_ON (1 << 4)
-#define v_PREPCLK_ON(n) (((n)&0x01) << 4)
-#define m_I2SCLK_ON (1 << 3)
-#define v_I2SCLK_ON(n) (((n)&0x01) << 3)
-#define m_SPDIFCLK_ON (1 << 2)
-#define v_SPDIFCLK_ON(n) (((n)&0x01) << 2)
-#define m_CECCLK_ON (1 << 0)
-#define v_CECCLK_ON(n) (((n)&0x01) << 0)
-
-#define MC_HEACPHY_RST 0x4007
-#define m_HEAC_PHY_RST (1 << 0)
-#define v_HEAC_PHY_RST(n) (((n)&0x01) << 0)
-
-#define MC_LOCKONCLOCK_2 0x4009
-#define m_AHB_AUD_DMA_CLK (1 << 0)
-#define v_AHB_AUD_DMA_CLK(n) (((n)&0x01) << 0)
-
-#define MC_SWRSTZREQ_2 0x400a
-#define m_AHB_AUD_DMA_RST (1 << 7)
-#define v_AHB_AUD_DMA_RST(n) (((n)&0x01) << 7)
-
-/* Color Space Converter Registers */
-#define COLOR_SPACE_CONVERTER_BASE 0x4100
-
-#define CSC_CFG 0x4100
-#define m_CSC_INTPMODE (0x03 << 4)
-#define v_CSC_INTPMODE(n) (((n)&0x03) << 4)
-#define m_CSC_DECIMODE (0x03 << 0)
-#define v_CSC_DECIMODE(n) (((n)&0x03) << 0)
-
-#define CSC_SCALE 0x4101
-#define m_CSC_COLOR_DEPTH (0x0f << 4)
-#define v_CSC_COLOR_DEPTH(n) (((n)&0x0f) << 4)
-#define m_CSC_SCALE (0x03 << 0)
-#define v_CSC_SCALE(n) (((n)&0x03) << 0)
-
-#define CSC_COEF_A1_MSB 0x4102
-#define CSC_COEF_A1_LSB 0x4103
-#define CSC_COEF_A2_MSB 0x4104
-#define CSC_COEF_A2_LSB 0x4105
-#define CSC_COEF_A3_MSB 0x4106
-#define CSC_COEF_A3_LSB 0x4107
-#define CSC_COEF_A4_MSB 0x4108
-#define CSC_COEF_A4_LSB 0x4109
-#define CSC_COEF_B1_MSB 0x410a
-#define CSC_COEF_B1_LSB 0x410b
-#define CSC_COEF_B2_MSB 0x410c
-#define CSC_COEF_B2_LSB 0x410d
-#define CSC_COEF_B3_MSB 0x410e
-#define CSC_COEF_B3_LSB 0x410f
-#define CSC_COEF_B4_MSB 0x4110
-#define CSC_COEF_B4_LSB 0x4111
-#define CSC_COEF_C1_MSB 0x4112
-#define CSC_COEF_C1_LSB 0x4113
-#define CSC_COEF_C2_MSB 0x4114
-#define CSC_COEF_C2_LSB 0x4115
-#define CSC_COEF_C3_MSB 0x4116
-#define CSC_COEF_C3_LSB 0x4117
-#define CSC_COEF_C4_MSB 0x4118
-#define CSC_COEF_C4_LSB 0x4119
-#define CSC_SPARE_1 0x411a
-#define CSC_SPARE_2 0x411b
-
-/* HDCP Encryption Engine Registers */
-#define HDCP_ENCRYPTION_ENGINE_BASE 0x5000
-
-#define A_HDCPCFG0 0x5000
-#define m_HDCP_ENHANCE_LIKE (1 << 7)
-#define v_HDCP_ENHANCE_LIKE(n) (((n)&0x01) << 7)
-#define m_I2C_FAST_MODE (1 << 6)
-#define v_I2C_FAST_MODE(n) (((n)&0x01) << 6)
-#define m_ENCRYPT_BYPASS (1 << 5)
-#define v_ENCRYPT_BYPASS(n) (((n)&0x01) << 5)
-#define m_SYNC_RI_CHECK (1 << 4)
-#define v_SYNC_RI_CHECK(n) (((n)&0x01) << 4)
-#define m_AVMUTE (1 << 3)
-#define m_RX_DETECT (1 << 2)
-#define v_RX_DETECT(n) (((n)&0x01) << 2)
-#define m_FEATURE11_EN (1 << 1)
-#define v_FEATURE11_EN(n) (((n)&0x01) << 1)
-#define m_HDMI_DVI (1 << 0)
-#define v_HDMI_DVI(n) (((n)&0x01) << 0)
-
-#define A_HDCPCFG1 0x5001
-#define m_HDCP_LOCK (1 << 4)
-#define v_HDCP_LOCK(n) (((n)&0x01) << 4)
-#define m_SHA1_CHECK_DISABLE (1 << 3)
-#define v_SHA1_CHECK_DISBALE(n) (((n)&0x01) << 3)
-#define m_PH2UPSHFTENC (1 << 2)
-#define v_PH2UPSHFTENC(n) (((n)&0x01) << 2)
-#define m_ENCRYPT_DISBALE (1 << 1)
-#define v_ENCRYPT_DISBALE(n) (((n)&0x01) << 1)
-#define m_HDCP_SW_RST (1 << 0)
-#define v_HDCP_SW_RST(n) (((n)&0x01) << 0)
-
-#define A_HDCPOBS0 0x5002
-#define m_STATE_AUTH (0x0f << 4)
-#define m_SUB_STATE_AUTH (0x07 << 1)
-#define m_STATE_HDCP_ENGAGED (1 << 0)
-
-#define A_HDCPOBS1 0x5003
-#define m_STATE_OESS (0x07 << 3)
-#define m_STATE_REVO (0x07 << 0)
-
-#define A_HDCPOBS2 0x5004
-#define m_STATE_CIPHER (0x07 << 3)
-#define m_STATE_EESS (0x07 << 0)
-
-#define A_HDCPOBS3 0x5005
-#define m_BCAP_REPEATER (1 << 6)
-#define m_BCAP_KSVFIFO_READY (1 << 5)
-#define m_BCAP_FAST_I2C (1 << 4)
-#define m_BCAP_HDMI_MODE (1 << 2)
-#define m_BCAP_FEATURES11 (1 << 1)
-#define m_BCAP_FAST_REAUTH (1 << 0)
-
-#define A_APIINTCLR 0x5006
-#define A_APIINTSTAT 0x5007
-#define A_APIINTMSK 0x5008
-#define m_HDCP_ENGAGED (1 << 7)
-#define m_HDCP_FAILED (1 << 6)
-#define m_HDCP_I2C_NOACK (1 << 4)
-#define m_HDCP_LOST_ARBI (1 << 3)
-#define m_KEEP_ERR_INT (1 << 2)
-#define m_KSVSHA1_CALC_INT (1 << 1)
-#define m_KSV_ACCESS_INT (1 << 0)
-#define v_HDCP_ENGAGED(n) (((n)&0x01) << 7)
-#define v_HDCP_FAILED(n) (((n)&0x01) << 6)
-#define v_HDCP_I2C_NOACK(n) (((n)&0x01) << 4)
-#define v_HDCP_LOST_ARBI(n) (((n)&0x01) << 3)
-#define v_KEEP_ERR_INT(n) (((n)&0x01) << 1)
-#define v_KSVSHA1_CALC_INT(n) (((n)&0x01) << 1)
-#define v_KSV_ACCESS_INT(n) (((n)&0x01) << 0)
-
-#define A_VIDPOLCFG 0x5009
-#define m_UNENCRYT_CONF (0x03 << 5)
-#define v_UNENCRYT_CONF(n) (((n)&0x03) << 5)
-#define m_DATAEN_POL (1 << 4)
-#define v_DATAEN_POL(n) (((n)&0x01) << 4)
-#define m_VSYNC_POL (1 << 3)
-#define v_VSYNC_POL(n) (((n)&0x01) << 3)
-#define m_HSYNC_POL (1 << 1)
-#define v_HSYNC_POL(n) (((n)&0x01) << 1)
-
-#define A_OESSWCFG 0x500a
-#define A_COREVERLSB 0x5014
-#define A_COREVERMSB 0x5015
-
-#define A_KSVMEMCTRL 0x5016
-#define m_SHA1_FAIL (1 << 3)
-#define v_SHA1_FAIL(n) (((n)&0x01) << 3)
-#define m_KSV_UPDATE (1 << 2)
-#define v_KSV_UPDATE(n) (((n)&0x01) << 2)
-#define m_KSV_MEM_ACCESS (1 << 1)
-#define m_KSV_MEM_REQ (1 << 0)
-#define v_KSV_MEM_REQ(n) (((n)&0x01) << 0)
-
-#define HDCP_BSTATUS_0 0x5020
-#define m_MAX_DEVS_EXCEEDED (1 << 7)
-#define m_DEVICE_COUNT (0x7f << 0)
-
-#define HDCP_BSTATUS_1 0x5021
-#define HDCP_M0_0 0x5022
-#define HDCP_M0_1 0x5023
-#define HDCP_M0_2 0x5024
-#define HDCP_M0_3 0x5025
-#define HDCP_M0_4 0x5026
-#define HDCP_M0_5 0x5027
-#define HDCP_M0_6 0x5028
-#define HDCP_M0_7 0x5029
-#define HDCP_KSV 0x502a /* 0~634 */
-#define HDCP_VH 0x52a5 /* 0~19 */
-#define HDCP_REVOC_SIZE_0 0x52b9
-#define HDCP_REVOC_SIZE_1 0x52ba
-#define HDCP_REVOC_LIST 0x52bb /* 0~5059 */
-
-/* HDCP BKSV Registers */
-#define HDCP_BKSV_BASE 0x7800
-
-#define HDCPREG_BKSV0 0x7800
-#define HDCPREG_BKSV1 0x7801
-#define HDCPREG_BKSV2 0x7802
-#define HDCPREG_BKSV3 0x7803
-#define HDCPREG_BKSV4 0x7804
-
-/* HDCP AN Registers */
-#define HDCP_AN_BASE 0x7805
-
-#define HDCPREG_ANCONF 0x7805
-#define m_OAN_BYPASS (1 << 0)
-#define v_OAN_BYPASS(n) (((n)&0x01) << 0)
-
-#define HDCPREG_AN0 0x7806
-#define HDCPREG_AN1 0x7807
-#define HDCPREG_AN2 0x7808
-#define HDCPREG_AN3 0x7809
-#define HDCPREG_AN4 0x780a
-#define HDCPREG_AN5 0x780b
-#define HDCPREG_AN6 0x780c
-#define HDCPREG_AN7 0x780d
-
-/* Encrypted DPK Embedded Storage Registers */
-#define ENCRYPTED_DPK_EMBEDDED_BASE 0x780e
-
-#define HDCPREG_RMCTL 0x780e
-#define m_DPK_DECRYPT_EN (1 << 0)
-#define v_DPK_DECRYPT_EN(n) (((n)&0x01) << 0)
-
-#define HDCPREG_RMSTS 0x780f
-#define m_DPK_WR_OK_STS (1 << 6)
-#define m_DPK_DATA_INDEX (0x3f << 6)
-
-#define HDCPREG_SEED0 0x7810
-#define HDCPREG_SEED1 0x7811
-#define HDCPREG_DPK0 0x7812
-#define HDCPREG_DPK1 0x7813
-#define HDCPREG_DPK2 0x7814
-#define HDCPREG_DPK3 0x7815
-#define HDCPREG_DPK4 0x7816
-#define HDCPREG_DPK5 0x7817
-#define HDCPREG_DPK6 0x7818
-
-/* CEC Engine Registers */
-#define CEC_ENGINE_BASE 0x7d00
-
-#define CEC_CTRL 0x7d00
-#define CEC_MASK 0x7d02
-#define CEC_ADDR_L 0x7d05
-#define CEC_ADDR_H 0x7d06
-#define CEC_TX_CNT 0x7d07
-#define CEC_RX_CNT 0x7d08
-#define CEC_TX_DATA0 0x7d10 /* txdata0~txdata15 */
-#define CEC_RX_DATA0 0x7d20 /* rxdata0~rxdata15 */
-#define CEC_LOCK 0x7d30
-#define CEC_WKUPCTRL 0x7d31
-
-/* I2C Master Registers */
-#define I2C_MASTER_BASE 0x7e00
-
-#define I2CM_SLAVE 0x7e00
-#define I2CM_ADDRESS 0x7e01
-#define I2CM_DATAO 0x7e02
-#define I2CM_DATAI 0x7e03
-
-#define I2CM_OPERATION 0x7e04
-#define m_I2CM_WR (1 << 4)
-#define v_I2CM_WR(n) (((n)&0x01) << 4)
-#define m_I2CM_RD8_EXT (1 << 3)
-#define v_I2CM_RD8_EXT(n) (((n)&0x01) << 3)
-#define m_I2CM_RD8 (1 << 2)
-#define v_I2CM_RD8(n) (((n)&0x01) << 2)
-#define m_I2CM_RD_EXT (1 << 1)
-#define v_I2CM_RD_EXT(n) (((n)&0x01) << 1)
-#define m_I2CM_RD (1 << 0)
-#define v_I2CM_RD(n) (((n)&0x01) << 0)
-
-#define I2CM_INT 0x7e05
-#define m_I2CM_RD_REQ_MASK (1 << 6)
-#define v_I2CM_RD_REQ_MASK(n) (((n)&0x01) << 6)
-#define m_I2CM_DONE_MASK (1 << 2)
-#define v_I2CM_DONE_MASK(n) (((n)&0x01) << 2)
-
-#define I2CM_CTLINT 0x7e06
-#define m_I2CM_NACK_MASK (1 << 6)
-#define v_I2CM_NACK_MASK(n) (((n)&0x01) << 6)
-#define m_I2CM_ARB_MASK (1 << 2)
-#define v_I2CM_ARB_MASK(n) (((n)&0x01) << 2)
-
-#define I2CM_DIV 0x7e07
-enum {
- STANDARD_MODE = 0,
- FAST_MODE
-};
-#define m_I2CM_FAST_STD_MODE (1 << 3)
-#define v_I2CM_FAST_STD_MODE(n) (((n)&0x01) << 3)
-
-#define I2CM_SEGADDR 0x7e08
-#define m_I2CM_SEG_ADDR (0x7f << 0)
-#define v_I2CM_SEG_ADDR(n) (((n)&0x7f) << 0)
-
-#define I2CM_SOFTRSTZ 0x7e09
-#define m_I2CM_SOFTRST (1 << 0)
-#define v_I2CM_SOFTRST(n) (((n)&0x01) << 0)
-
-#define I2CM_SEGPTR 0x7e0a
-#define I2CM_SS_SCL_HCNT_1_ADDR 0x7e0b
-#define I2CM_SS_SCL_HCNT_0_ADDR 0x7e0c
-#define I2CM_SS_SCL_LCNT_1_ADDR 0x7e0d
-#define I2CM_SS_SCL_LCNT_0_ADDR 0x7e0e
-#define I2CM_FS_SCL_HCNT_1_ADDR 0x7e0f
-#define I2CM_FS_SCL_HCNT_0_ADDR 0x7e10
-#define I2CM_FS_SCL_LCNT_1_ADDR 0x7e11
-#define I2CM_FS_SCL_LCNT_0_ADDR 0x7e12
-#define I2CM_SDA_HOLD 0x7e13
-
-#define I2CM_SCDC_READ_UPDATE 0x7e14
-#define m_I2CM_UPRD_VSYNC_EN (1 << 5)
-#define v_I2CM_UPRD_VSYNC_EN(n) (((n)&0x01) << 5)
-#define m_I2CM_READ_REQ_EN (1 << 4)
-#define v_I2CM_READ_REQ_EN(n) (((n)&0x01) << 4)
-#define m_I2CM_READ_UPDATE (1 << 0)
-#define v_I2CM_READ_UPDATE(n) (((n)&0x01) << 0)
-
-#define I2CM_READ_BUFF0 0x7e20 /* buff0~buff7 */
-#define I2CM_SCDC_UPDATE0 0x7e30
-#define I2CM_SCDC_UPDATE1 0x7e31
-
-/*
-* HDMI TX PHY Define Start
-*/
-#define PHYTX_OPMODE_PLLCFG 0x06
-enum {
- PREP_DIV_BY_2 = 0, /* 16 bits */
- PREP_DIV_BY_15, /* 12 bits */
- PREP_DIV_BY_125, /* 10 bits */
- PREP_DIV_BY_1, /* 8 bits */
-};
-#define m_PREP_DIV (0x03 << 13)
-#define v_PREP_DIV(n) (((n)&0x03) << 13)
-enum {
- TMDS_DIV_BY_1 = 0,
- TMDS_DIV_NOT_USED,
- TMDS_DIV_BY_3,
- TMDS_DIV_BY_4,
-};
-#define m_TMDS_CNTRL (0x03 << 11)
-#define v_TMDS_CNTRL(n) (((n)&0x03) << 11)
-enum OPMODE {
- OP_HDMI_14 = 0,
- OP_HDMI_20,
-};
-#define m_OPMODE (0x03 << 9)
-#define v_OPMODE(n) (((n)&0x03) << 9)
-enum {
- FBDIV2_BY_1 = 1,
- FBDIV2_BY_2,
- FBDIV2_BY_3,
- FBDIV2_BY_4,
- FBDIV2_BY_5,
- FBDIV2_BY_6,
-};
-#define m_FBDIV2_CNTRL (0x07 << 6)
-#define v_FBDIV2_CNTRL(n) (((n)&0x07) << 6)
-enum {
- FBDIV1_BY_1 = 0,
- FBDIV1_BY_2,
- FBDIV1_BY_3,
- FBDIV1_BY_4,
-};
-#define m_FBDIV1_CNTRL (0x03 << 4)
-#define v_FBDIV1_CNTRL(n) (((n)&0x03) << 4)
-enum {
- REF_DIV_BY_1 = 0,
- REF_DIV_BY_2,
- REF_DIV_NOT_USED,
- REF_DIV_BY_4,
-};
-#define m_REF_CNTRL (0x03 << 2)
-#define v_REF_CNTRL(n) (((n)&0x03) << 2)
-#define m_MPLL_N_CNTRL (0x03 << 0)
-#define v_MPLL_N_CNTRL(n) (((n)&0x03) << 0)
-
-#define PHYTX_CLKSYMCTRL 0x09
-#define v_OVERRIDE(n) (0x01 << 15)
-#define m_SLOPEBOOST (0x03 << 4)
-#define v_SLOPEBOOST(n) (((n)&0x03) << 4)
-#define m_TX_SYMON (0x01 << 3)
-#define v_TX_SYMON(n) (((n)&0x01) << 3)
-#define m_TX_TRAON (0x01 << 2)
-#define v_TX_TRAON(n) (((n)&0x01) << 2)
-#define m_TX_TRBON (0x01 << 1)
-#define v_TX_TRBON(n) (((n)&0x01) << 1)
-#define m_CLK_SYMON (0x01 << 0)
-#define v_CLK_SYMON(n) (((n)&0x01) << 0)
-
-#define PHYTX_VLEVCTRL 0x0e
-#define m_SUP_TXLVL (0x1f << 5)
-#define v_SUP_TXLVL(n) (((n)&0x1f) << 5)
-#define m_SUP_CLKLVL (0x1f << 0)
-#define v_SUP_CLKLVL(n) (((n)&0x1f) << 0)
-
-#define PHYTX_PLLCURRCTRL 0x10
-#define m_MPLL_PROP_CNTRL (0x07 << 3)
-#define v_MPLL_PROP_CNTRL(n) (((n)&0x07) << 3)
-#define m_MPLL_INT_CNTRL (0x07 << 0)
-#define v_MPLL_INT_CNTRL(n) (((n)&0x07) << 0)
-
-#define PHYTX_PLLGMPCTRL 0x15
-#define m_MPLL_GMP_CNTRL (0x03 << 0)
-#define v_MPLL_GMP_CNTRL(n) (((n)&0x03) << 0)
-
-enum TERM_RESIS {
- R50_Ohms = 0,
- R5714_Ohms,
- R6667_Ohms,
- R80_Ohms,
- R100_Ohms,
- R13333_Ohms,
- R200_Ohms,
- ROPEN_CIRCUIT,
-};
-#define PHYTX_TERM_RESIS 0x19
-#define m_TX_TERM (0x07 << 0)
-#define v_TX_TERM(n) (((n)&0x07) << 0)
-
-struct phy_mpll_config_tab {
- u32 pix_clock;
- u8 pix_repet;
- u8 color_depth;
- u16 prep_div;
- u16 tmdsmhl_cntrl;
- u16 opmode;
- u32 fbdiv2_cntrl;
- u16 fbdiv1_cntrl;
- u16 ref_cntrl;
- u16 n_cntrl;
- u32 prop_cntrl;
- u32 int_cntrl;
- u16 gmp_cntrl;
-};
-
-/*
-* HDMI TX PHY Define End
-*/
-
-struct rk3288_hdmi_reg_table {
- int reg_base;
- int reg_end;
-};
-
-struct rk3288_hdmi_device {
- int irq;
- void __iomem *regbase;
- int regbase_phy;
- int regsize_phy;
- int lcdc_id;
- int i2cm_int;
- int phy_i2cm_int;
- unsigned char clk_on;
- struct mutex int_mutex;
- struct device *dev;
- struct clk *pd;
- struct clk *pclk; /* HDMI AHP clk */
- struct clk *hdcp_clk;
- struct hdmi driver;
- struct dentry *debugfs_dir;
-#ifdef HDMI_INT_USE_POLL
- struct delayed_work delay_work;
-#endif
-};
-
-static inline u32 hdmi_readl(struct rk3288_hdmi_device *hdmi_dev, u16 offset)
-{
- return readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
-}
-
-static inline int hdmi_writel(struct rk3288_hdmi_device *hdmi_dev, u16 offset,
- u32 val)
-{
- int ret = 0;
- writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-static inline int hdmi_msk_reg(struct rk3288_hdmi_device *hdmi_dev, u16 offset,
- u32 msk, u32 val)
-{
- int ret = 0;
- u32 temp;
- temp =
- readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
- writel_relaxed(temp | ((val) & (msk)),
- hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-int rk3288_hdmi_initial(struct hdmi *hdmi_drv);
-void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable);
-int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv, unsigned char pixel_repet,
- unsigned char color_depth);
-
-#endif
+++ /dev/null
-config HDCP_RK610
- bool "RK610 HDCP support"
- depends on HDMI_RK610
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-config HDCP_RK610_DEBUG
- bool "RK610 HDCP Debugging"
- depends on HDCP_RK610
- default n
- help
- Enableds verbose debugging the the HDCP drivers
+++ /dev/null
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-ccflags-$(CONFIG_HDCP_RK610_DEBUG) = -DHDCP_DEBUG
-
-obj-$(CONFIG_HDMI_RK610) += rk610_hdmi_hw.o rk610_hdmi.o
-obj-$(CONFIG_HDCP_RK610) += rk610_hdmi_hdcp.o rk610_hdcp.o
-
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/miscdevice.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include "rk610_hdmi.h"
-#include "rk610_hdcp.h"
-
-struct hdcp *hdcp = NULL;
-
-static void hdcp_work_queue(struct work_struct *work);
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_submit_work
- *-----------------------------------------------------------------------------
- */
-static struct delayed_work *hdcp_submit_work(int event, int delay)
-{
- struct hdcp_delayed_work *work;
-
- DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
-
- work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
- work->event = event;
- queue_delayed_work(hdcp->workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- printk(KERN_WARNING "HDCP: Cannot allocate memory to "
- "create work\n");
- return 0;
- }
-
- return &work->work;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_cancel_work
- *-----------------------------------------------------------------------------
- */
-static void hdcp_cancel_work(struct delayed_work **work)
-{
- int ret = 0;
-
- if (*work) {
- ret = cancel_delayed_work(*work);
- if (ret != 1) {
- ret = cancel_work_sync(&((*work)->work));
- printk(KERN_INFO "Canceling work failed - "
- "cancel_work_sync done %d\n", ret);
- }
- kfree(*work);
- *work = 0;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_failure
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_failure(void)
-{
- if (hdcp->hdmi_state == HDMI_STOPPED) {
- return;
- }
-
- rk610_hdcp_disable();
- rk610_hdmi_sys_enalbe_output(false);
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
- if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
- hdcp->retry_cnt--;
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying, attempts=%d\n",
- hdcp->retry_cnt);
- } else
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying\n");
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
- HDCP_REAUTH_DELAY);
- } else {
- printk(KERN_INFO "HDCP: authentication failed - "
- "HDCP disabled\n");
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
-
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_start_authentication
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_start_authentication(void)
-{
- int status = HDCP_OK;
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- DBG("HDCP: authentication start");
-
- status = rk610_hdcp_start_authentication();
-
- if (status != HDCP_OK) {
- DBG("HDCP: authentication failed");
- hdcp_wq_authentication_failure();
- } else {
- hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
-// hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_bksv
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_check_bksv(void)
-{
- int status = HDCP_OK;
-
- DBG("Check BKSV start");
-
- status = rk610_hdcp_check_bksv();
-
- if (status != HDCP_OK) {
- printk(KERN_INFO "HDCP: Check BKSV failed");
- hdcp->retry_cnt = 0;
- hdcp_wq_authentication_failure();
- }
- else {
- DBG("HDCP: Check BKSV successful");
-
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
-
- /* Restore retry counter */
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_sucess
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_sucess(void)
-{
- rk610_hdmi_sys_enalbe_output(true);
- printk(KERN_INFO "HDCP: authentication pass");
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_disable
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_disable(int event)
-{
- printk(KERN_INFO "HDCP: disabled");
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
- rk610_hdcp_disable();
- if(event == HDCP_DISABLE_CTL) {
- hdcp->hdcp_state = HDCP_DISABLED;
- if(hdcp->hdmi_state == HDMI_STARTED)
- rk610_hdmi_sys_enalbe_output(true);
- }
- else if(event == HDCP_STOP_FRAME_EVENT)
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_work_queue
- *-----------------------------------------------------------------------------
- */
-static void hdcp_work_queue(struct work_struct *work)
-{
- struct hdcp_delayed_work *hdcp_w =
- container_of(work, struct hdcp_delayed_work, work.work);
- int event = hdcp_w->event;
-
- mutex_lock(&hdcp->lock);
-
- DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
- jiffies_to_msecs(jiffies),
- hdcp->hdmi_state,
- hdcp->hdcp_state,
- (event & 0xFF00) >> 8,
- event & 0xFF);
-
- if(event == HDCP_STOP_FRAME_EVENT) {
- hdcp->hdmi_state = HDMI_STOPPED;
- }
-
- if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
- hdcp_wq_disable(event);
- }
-
- if (event & HDCP_WORKQUEUE_SRC)
- hdcp->pending_wq_event = 0;
-
- /* First handle HDMI state */
- if (event == HDCP_START_FRAME_EVENT) {
- hdcp->pending_start = 0;
- hdcp->hdmi_state = HDMI_STARTED;
- }
-
- /**********************/
- /* HDCP state machine */
- /**********************/
- switch (hdcp->hdcp_state) {
- case HDCP_DISABLED:
- /* HDCP enable control or re-authentication event */
- if (event == HDCP_ENABLE_CTL) {
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- if (hdcp->hdmi_state == HDMI_STARTED)
- hdcp_wq_start_authentication();
- else
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
- break;
-
- case HDCP_ENABLE_PENDING:
- /* HDMI start frame event */
- if (event == HDCP_START_FRAME_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_AUTHENTICATION_START:
- /* Re-authentication */
- if (event == HDCP_AUTH_REATT_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_WAIT_KSV_LIST:
- /* KSV failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: KSV switch failure\n");
-
- hdcp_wq_authentication_failure();
- }
- /* KSV list ready event */
- else if (event == HDCP_KSV_LIST_RDY_EVENT)
- hdcp_wq_check_bksv();
- break;
-
- case HDCP_LINK_INTEGRITY_CHECK:
- /* Ri failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: Ri check failure\n");
- hdcp_wq_authentication_failure();
- }
- else if(event == HDCP_AUTH_PASS_EVENT)
- hdcp_wq_authentication_sucess();
- break;
-
- default:
- printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
- break;
- }
-
- kfree(hdcp_w);
- if(event == HDCP_STOP_FRAME_EVENT)
- complete(&hdcp->complete);
-
- mutex_unlock(&hdcp->lock);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_start_frame_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_start_frame_cb(void)
-{
- DBG("hdcp_start_frame_cb()");
-
- /* Cancel any pending work */
- if (hdcp->pending_start)
- hdcp_cancel_work(&hdcp->pending_start);
- if (hdcp->pending_wq_event)
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_irq_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_irq_cb(int status)
-{
- char interrupt1;
- char interrupt2;
-
- rk610_hdcp_interrupt(&interrupt1, &interrupt2);
- DBG("%s 0x%02x 0x%02x", __FUNCTION__, interrupt1, interrupt2);
- if(interrupt1 & m_INT_HDCP_ERR)
- {
- if( (hdcp->hdcp_state != HDCP_DISABLED) &&
- (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
- {
- hdcp_submit_work(HDCP_FAIL_EVENT, 0);
- }
- }
- else if(interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
- hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
- else if(interrupt1 & m_INT_AUTH_SUCCESS)
- hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_on_cb
- *-----------------------------------------------------------------------------
- */
-static int hdcp_power_on_cb(void)
-{
- DBG("%s", __FUNCTION__);
-// return rk610_hdcp_load_key2mem(hdcp->keys);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_off_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_power_off_cb(void)
-{
- DBG("%s", __FUNCTION__);
- if(!hdcp->enable)
- return;
-
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- init_completion(&hdcp->complete);
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
- wait_for_completion_interruptible_timeout(&hdcp->complete,
- msecs_to_jiffies(5000));
-}
-
-// Load HDCP key to external HDCP memory
-static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
-{
- if (!fw) {
- pr_err("HDCP: failed to load keys\n");
- return;
- }
-
- if(fw->size < HDCP_KEY_SIZE) {
- pr_err("HDCP: firmware wrong size %d\n", fw->size);
- return;
- }
-
- hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->keys == NULL) {
- pr_err("HDCP: can't allocated space for keys\n");
- return;
- }
-
- memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
-
- printk(KERN_INFO "HDCP: load hdcp key success\n");
-
- if(fw->size > HDCP_KEY_SIZE) {
- DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
- if((fw->size - HDCP_KEY_SIZE) % 5) {
- pr_err("HDCP: failed to load invalid keys\n");
- return;
- }
- hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->invalidkeys == NULL) {
- pr_err("HDCP: can't allocated space for invalid keys\n");
- return;
- }
- memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
- hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
- printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
- }
-}
-
-static ssize_t hdcp_enable_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int enable = 0;
-
- if(hdcp)
- enable = hdcp->enable;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t hdcp_enable_write(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int enable;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &enable);
- if(hdcp->enable != enable)
- {
- /* Post event to workqueue */
- if(enable) {
- if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- else {
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- hdcp->enable = enable;
- }
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
-
-static ssize_t hdcp_trytimes_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int trytimes = 0;
-
- if(hdcp)
- trytimes = hdcp->retry_times;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
-}
-
-static ssize_t hdcp_trytimes_wrtie(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int trytimes;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &trytimes);
- if(hdcp->retry_times != trytimes)
- hdcp->retry_times = trytimes;
-
- return count;
-}
-
-
-static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
-
-
-static struct miscdevice mdev;
-
-static int __init rk610_hdcp_init(void)
-{
- int ret;
-
- DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
-
- hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
- if(!hdcp)
- {
- printk(KERN_ERR ">>HDCP: kmalloc fail!");
- ret = -ENOMEM;
- goto error0;
- }
- memset(hdcp, 0, sizeof(struct hdcp));
- mutex_init(&hdcp->lock);
-
- mdev.minor = MISC_DYNAMIC_MINOR;
- mdev.name = "hdcp";
- mdev.mode = 0666;
- if (misc_register(&mdev)) {
- printk(KERN_ERR "HDCP: Could not add character driver\n");
- ret = HDMI_ERROR_FALSE;
- goto error1;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_enable);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file enable\n");
- ret = -EINVAL;
- goto error2;
- }
-
- ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
- ret = -EINVAL;
- goto error3;
- }
-
- hdcp->workqueue = create_singlethread_workqueue("hdcp");
- if (hdcp->workqueue == NULL) {
- printk(KERN_ERR "HDCP,: create workqueue failed.\n");
- goto error4;
- }
-
-
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "hdcp.keys", mdev.this_device, GFP_KERNEL,
- hdcp, hdcp_load_keys_cb);
- if (ret < 0) {
- printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
- goto error5;
- }
-
- rk610_hdmi_register_hdcp_callbacks( hdcp_start_frame_cb,
- hdcp_irq_cb,
- hdcp_power_on_cb,
- hdcp_power_off_cb);
-
- DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
- return 0;
-
-error5:
- destroy_workqueue(hdcp->workqueue);
-error4:
- device_remove_file(mdev.this_device, &dev_attr_trytimes);
-error3:
- device_remove_file(mdev.this_device, &dev_attr_enable);
-error2:
- misc_deregister(&mdev);
-error1:
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-error0:
- return ret;
-}
-
-static void __exit rk610_hdcp_exit(void)
-{
- device_remove_file(mdev.this_device, &dev_attr_enable);
- misc_deregister(&mdev);
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-}
-
-module_init(rk610_hdcp_init);
-module_exit(rk610_hdcp_exit);
+++ /dev/null
-#ifndef __RK610_HDCP_H__
-#define __RK610_HDCP_H__
-
-/***************************/
-/* Definitions */
-/***************************/
-
-/* Status / error codes */
-#define HDCP_OK 0
-#define HDCP_KEY_ERR 1
-#define HDCP_KSV_ERR 2
-
-/* Delays */
-#define HDCP_ENABLE_DELAY 300
-#define HDCP_REAUTH_DELAY 100
-
-/* Event source */
-#define HDCP_SRC_SHIFT 8
-#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
-#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
-#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
-#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
-
-/* Event */
-#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
-#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
-#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
-#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
-#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 4)
-#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 5)
-#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 6)
-#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 7)
-
-/* Key size */
-#define HDCP_KEY_SIZE 308
-
-/* HDCP DDC Clock */
-#define HDCP_DDC_CLK 100000
-
-/* Authentication retry times */
-#define HDCP_INFINITE_REAUTH 0x100
-
-/* HDCP Regs */
-#define HDCP_CTRL1 0x52
- #define m_AUTH_START (1 << 7)
- #define m_BKSV_VALID (1 << 6)
- #define m_BKSV_INVALID (1 << 5)
- #define m_ENCRYPT_ENABLE (1 << 4)
- #define m_AUTH_STOP (1 << 3)
- #define m_ADVANED_ENABLE (1 << 2)
- #define m_HDMI_DVI (1 << 1)
- #define m_HDCP_RESET (1 << 0)
-
- #define v_AUTH_START(n) (n << 7)
- #define v_BKSV_VALID(n) (n << 6)
- #define v_BKSV_INVALID(n) (n << 5)
- #define v_ENCRYPT_ENABLE(n) (n << 4)
- #define v_AUTH_STOP(n) (n << 3)
- #define v_ADVANED_ENABLE(n) (n << 2)
- #define v_HDMI_DVI(n) (n << 1)
- #define v_HDCP_RESET(n) (n << 0)
-
-#define HDCP_CTRL2 0x53
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_ENABLE_PJ_CHECK (1 << 5)
- #define m_DISABLE_DEVICE_NUMBER_CHECK (1 << 4)
- #define m_DELAY_RI_1_CLK (1 << 3)
- #define m_USE_PRESET_AN (1 << 2)
- #define m_KEY_COMBINATION (3 << 0)
-
- #define v_DISABLE_127_CHECK(n) (n << 7)
- #define v_SKIP_BKSV_CHECK(n) (n << 6)
- #define v_ENABLE_PJ_CHECK(n) (n << 5)
- #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
- #define v_DELAY_RI_1_CLK(n) (n << 3)
- #define v_USE_PRESET_AN(n) (n << 2)
- #define v_KEY_COMBINATION(n) (n << 0)
-
-#define HDCP_KEY_STATUS 0x54
- #define m_KEY_READY (1 << 0)
-
-#define HDCP_CTRL_SOFT 0x57
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_NOT_AUTHENTICATED (1 << 5)
- #define m_ENCRYPTED (1 << 4)
- #define m_ADVANCED_CIPHER (1 << 3)
-
-#define HDCP_BCAPS_RX 0x58
-#define HDCP_TIMER_100MS 0x63
-#define HDCP_TIMER_5S 0x64
-#define HDCP_ERROR 0x65
- #define m_DDC_NO_ACK (1 << 3)
- #define m_PJ_MISMACH (1 << 2)
- #define m_RI_MISMACH (1 << 1)
- #define m_BKSV_WRONG (1 << 0)
-
-#define HDCP_KSV_BYTE0 0x66
-#define HDCP_KSV_BYTE1 0x67
-#define HDCP_KSV_BYTE2 0x68
-#define HDCP_KSV_BYTE3 0x69
-#define HDCP_KSV_BYTE4 0x6a
-
-#define HDCP_AN_SEED 0x6c
-
-#define HDCP_BCAPS_TX 0x80
-#define HDCP_BSTATE_0 0x81
-#define HDCP_BSTATE_1 0x82
-
-#define HDCP_KEY_FIFO 0x98
-
-#define HDCP_INT_MASK1 0xc2
-#define HDCP_INT_STATUS1 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_READY (1 << 6)
- #define m_INT_BKSV_UPDATE (1 << 5)
- #define m_INT_AUTH_SUCCESS (1 << 4)
- #define m_INT_AUTH_READY (1 << 3)
-
-#define HDCP_INT_MASK2 0xc4
-#define HDCP_INT_STATUS2 0xc5
- #define m_INT_SOFT_MODE_READY (1 << 7)
- #define m_INT_AUTH_M0_REDAY (1 << 6)
- #define m_INT_1st_FRAME_ARRIVE (1 << 5)
- #define m_INT_AN_READY (1 << 4)
- #define m_INT_ENCRYPTED (1 << 2)
- #define m_INT_NOT_ENCRYPTED_AVMUTE (1 << 1)
- #define m_INT_NOT_ENCRYPTED_AVUNMUTE (1 << 0)
-
-enum hdcp_states {
- HDCP_DISABLED,
- HDCP_ENABLE_PENDING,
- HDCP_AUTHENTICATION_START,
- HDCP_WAIT_KSV_LIST,
- HDCP_LINK_INTEGRITY_CHECK,
-};
-
-enum hdmi_states {
- HDMI_STOPPED,
- HDMI_STARTED
-};
-
-#define HDCP_PRIVATE_KEY_SIZE 280
-#define HDCP_KEY_SHA_SIZE 20
-
-struct hdcp_keys{
- u8 KSV[8];
- u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
- u8 sha1[HDCP_KEY_SHA_SIZE];
-};
-
-struct hdcp_delayed_work {
- struct delayed_work work;
- int event;
-};
-
-struct hdcp {
- int enable;
- int retry_times;
- struct hdcp_keys *keys;
- int invalidkey;
- char *invalidkeys;
- struct mutex lock;
- struct completion complete;
- struct workqueue_struct *workqueue;
-
- enum hdmi_states hdmi_state;
- enum hdcp_states hdcp_state;
-
- struct delayed_work *pending_start;
- struct delayed_work *pending_wq_event;
- int retry_cnt;
-};
-
-extern struct hdcp *hdcp;
-
-#ifdef DBG
-#undef DBG
-#endif
-
-#ifdef HDCP_DEBUG
-#define DBG(format, ...) \
- printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-extern void rk610_hdcp_disable(void);
-extern int rk610_hdcp_start_authentication(void);
-extern int rk610_hdcp_check_bksv(void);
-extern int rk610_hdcp_load_key2mem(struct hdcp_keys *key);
-extern void rk610_hdcp_interrupt(char *status1, char *status2);
-#endif /* __RK610_HDCP_H__ */
\ No newline at end of file
+++ /dev/null
-#include <linux/kernel.h>\r
-#include <linux/delay.h>\r
-#include <linux/module.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/interrupt.h>\r
-#include <mach/gpio.h>\r
-#include <mach/iomux.h>\r
-#include <linux/i2c.h>\r
-#include "rk610_hdmi.h"\r
-\r
-struct rk610_hdmi_pdata *rk610_hdmi = NULL;\r
-struct hdmi *hdmi=NULL;\r
-\r
-extern struct rk_lcdc_driver * rk_get_lcdc_drv(char *name);
-extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
-extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
-\r
-int rk610_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
- void (*hdcp_irq_cb)(int status),\r
- int (*hdcp_power_on_cb)(void),\r
- void (*hdcp_power_off_cb)(void))\r
-{\r
- hdmi->hdcp_cb = hdcp_cb;\r
- hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
- hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
- hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
- \r
- return HDMI_ERROR_SUCESS;\r
-}\r
-\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-static void hdmi_early_suspend(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
- flush_delayed_work(&hdmi->delay_work); \r
- mutex_lock(&hdmi->enable_mutex);\r
- hdmi->suspend = 1;\r
- if(!hdmi->enable) {\r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
- }\r
- \r
- #ifdef HDMI_USE_IRQ\r
- if(hdmi->irq)\r
- disable_irq(hdmi->irq);\r
- #endif\r
- \r
- mutex_unlock(&hdmi->enable_mutex);\r
- hdmi->command = HDMI_CONFIG_ENABLE;\r
- init_completion(&hdmi->complete);\r
- hdmi->wait = 1;\r
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
- wait_for_completion_interruptible_timeout(&hdmi->complete,\r
- msecs_to_jiffies(5000));\r
- flush_delayed_work(&hdmi->delay_work);\r
- return;\r
-}\r
-\r
-static void hdmi_early_resume(struct early_suspend *h)\r
-{\r
- hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
- mutex_lock(&hdmi->enable_mutex);\r
- \r
- hdmi->suspend = 0;\r
- #ifdef HDMI_USE_IRQ\r
- if(hdmi->enable && hdmi->irq) {\r
- enable_irq(hdmi->irq);\r
- }\r
- #else\r
- queue_delayed_work(rk610_hdmi->workqueue, &rk610_hdmi->delay_work, 100);\r
- #endif\r
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); \r
- mutex_unlock(&hdmi->enable_mutex);\r
- return;\r
-}\r
-#endif\r
-\r
-static void rk610_irq_work_func(struct work_struct *work)\r
-{\r
- if(hdmi->suspend == 0) {\r
- if(hdmi->enable == 1) {\r
- rk610_hdmi_interrupt();\r
- if(hdmi->hdcp_irq_cb)\r
- hdmi->hdcp_irq_cb(0);\r
- }\r
- #ifndef HDMI_USE_IRQ\r
- queue_delayed_work(rk610_hdmi->workqueue, &rk610_hdmi->delay_work, 50);\r
- #endif\r
- }\r
-}\r
-\r
-#ifdef HDMI_USE_IRQ\r
-static irqreturn_t rk610_irq(int irq, void *dev_id)\r
-{\r
- printk(KERN_INFO "rk610 irq triggered.\n");\r
- schedule_work(&rk610_hdmi->irq_work);\r
- return IRQ_HANDLED;\r
-}\r
-#endif\r
-\r
-static int rk610_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)\r
-{\r
- int rc = 0;\r
- \r
- rk610_hdmi = kzalloc(sizeof(struct rk610_hdmi_pdata), GFP_KERNEL);\r
- if(!rk610_hdmi)\r
- {\r
- dev_err(&client->dev, "no memory for state\n");\r
- return -ENOMEM;\r
- }\r
- rk610_hdmi->client = client;\r
- i2c_set_clientdata(client, rk610_hdmi);\r
- \r
- hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
- if(!hdmi)\r
- {\r
- dev_err(&client->dev, "rk610 hdmi kmalloc fail!");\r
- goto err_kzalloc_hdmi;\r
- }\r
- memset(hdmi, 0, sizeof(struct hdmi));\r
- hdmi->dev = &client->dev;\r
- \r
- if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
- else\r
- hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
- if(hdmi->lcdc == NULL)\r
- {\r
- dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
- rc = -ENXIO;\r
- goto err_request_lcdc;\r
- }\r
- hdmi->xscale = 100;\r
- hdmi->yscale = 100;\r
- hdmi->insert = rk610_hdmi_sys_insert;\r
- hdmi->remove = rk610_hdmi_sys_remove;\r
- hdmi->control_output = rk610_hdmi_sys_enalbe_output;\r
- hdmi->config_video = rk610_hdmi_sys_config_video;\r
- hdmi->config_audio = rk610_hdmi_sys_config_audio;\r
- hdmi->detect_hotplug = rk610_hdmi_sys_detect_hpd;\r
- hdmi->read_edid = rk610_hdmi_sys_read_edid;\r
- hdmi_sys_init();\r
- \r
- hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
- INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
- \r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- hdmi->early_suspend.suspend = hdmi_early_suspend;\r
- hdmi->early_suspend.resume = hdmi_early_resume;\r
- hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
- register_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- \r
- hdmi_register_display_sysfs(hdmi, NULL);\r
- #ifdef CONFIG_SWITCH\r
- hdmi->switch_hdmi.name="hdmi";\r
- switch_dev_register(&(hdmi->switch_hdmi));\r
- #endif\r
- \r
- spin_lock_init(&hdmi->irq_lock);\r
- mutex_init(&hdmi->enable_mutex);\r
- \r
- rk610_hdmi_sys_init();\r
- \r
-#ifdef HDMI_USE_IRQ\r
- if(client->irq != INVALID_GPIO) {\r
- INIT_WORK(&rk610_hdmi->irq_work, rk610_irq_work_func);\r
- schedule_work(&rk610_hdmi->irq_work);\r
- if((rc = gpio_request(client->irq, "hdmi gpio")) < 0)\r
- {\r
- dev_err(&client->dev, "fail to request gpio %d\n", client->irq);\r
- goto err_request_lcdc;\r
- }\r
- hdmi->irq = gpio_to_irq(client->irq);\r
- rk610_hdmi->gpio = client->irq;\r
- gpio_pull_updown(client->irq, GPIOPullUp);\r
- gpio_direction_input(client->irq);\r
- if((rc = request_irq(hdmi->irq, rk610_irq, IRQF_TRIGGER_RISING, NULL, hdmi)) < 0)\r
- {\r
- dev_err(&client->dev, "fail to request hdmi irq\n");\r
- goto err_request_irq;\r
- }\r
- }\r
- else\r
-#else\r
- {\r
- rk610_hdmi->workqueue = create_singlethread_workqueue("rk610 irq");\r
- INIT_DELAYED_WORK(&(rk610_hdmi->delay_work), rk610_irq_work_func);\r
- rk610_irq_work_func(NULL);\r
- }\r
-#endif\r
-\r
- dev_info(&client->dev, "rk610 hdmi i2c probe ok\n");\r
- \r
- return 0;\r
- \r
-err_request_irq:\r
- gpio_free(client->irq);\r
-err_request_lcdc:\r
- kfree(hdmi);\r
- hdmi = NULL;\r
-err_kzalloc_hdmi:\r
- kfree(rk610_hdmi);\r
- rk610_hdmi = NULL;\r
- dev_err(&client->dev, "rk610 hdmi probe error\n");\r
- return rc;\r
-\r
-}\r
-\r
-static int __devexit rk610_hdmi_i2c_remove(struct i2c_client *client)\r
-{ \r
- hdmi_dbg(hdmi->dev, "%s\n", __func__);\r
- if(hdmi) {\r
- mutex_lock(&hdmi->enable_mutex);\r
- if(!hdmi->suspend && hdmi->enable && hdmi->irq)\r
- disable_irq(hdmi->irq);\r
- mutex_unlock(&hdmi->enable_mutex);\r
- if(hdmi->irq)\r
- free_irq(hdmi->irq, NULL);\r
- flush_workqueue(hdmi->workqueue);\r
- destroy_workqueue(hdmi->workqueue);\r
- #ifdef CONFIG_SWITCH\r
- switch_dev_unregister(&(hdmi->switch_hdmi));\r
- #endif\r
- hdmi_unregister_display_sysfs(hdmi);\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- fb_destroy_modelist(&hdmi->edid.modelist);\r
- if(hdmi->edid.audio)\r
- kfree(hdmi->edid.audio);\r
- if(hdmi->edid.specs)\r
- {\r
- if(hdmi->edid.specs->modedb)\r
- kfree(hdmi->edid.specs->modedb);\r
- kfree(hdmi->edid.specs);\r
- }\r
- kfree(hdmi);\r
- hdmi = NULL;\r
- }\r
- return 0;\r
-}\r
-\r
-static void rk610_hdmi_i2c_shutdown(struct i2c_client *client)\r
-{\r
- if(hdmi) {\r
- #ifdef CONFIG_HAS_EARLYSUSPEND\r
- unregister_early_suspend(&hdmi->early_suspend);\r
- #endif\r
- }\r
- printk(KERN_INFO "rk610 hdmi shut down.\n");\r
-}\r
-\r
-static const struct i2c_device_id rk610_hdmi_id[] = {\r
- { "rk610_hdmi", 0 },\r
- { }\r
-};\r
-\r
-static struct i2c_driver rk610_hdmi_i2c_driver = {\r
- .driver = {\r
- .name = "rk610_hdmi",\r
- .owner = THIS_MODULE,\r
- },\r
- .probe = rk610_hdmi_i2c_probe,\r
- .remove = rk610_hdmi_i2c_remove,\r
- .shutdown = rk610_hdmi_i2c_shutdown,\r
- .id_table = rk610_hdmi_id,\r
-};\r
-\r
-static int __init rk610_hdmi_init(void)\r
-{\r
- return i2c_add_driver(&rk610_hdmi_i2c_driver);\r
-}\r
-\r
-static void __exit rk610_hdmi_exit(void)\r
-{\r
- i2c_del_driver(&rk610_hdmi_i2c_driver);\r
-}\r
-\r
-//module_init(rk610_hdmi_init);\r
-device_initcall_sync(rk610_hdmi_init);\r
-module_exit(rk610_hdmi_exit);\r
+++ /dev/null
-#ifndef __RK610_HDMI_H__\r
-#define __RK610_HDMI_H__\r
-#include "../../rk_hdmi.h"\r
-\r
-#if defined(CONFIG_HDMI_SOURCE_LCDC1)\r
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC1\r
-#else\r
-#define HDMI_SOURCE_DEFAULT HDMI_SOURCE_LCDC0\r
-#endif\r
-//#define HDMI_USE_IRQ\r
-\r
-struct rk610_hdmi_pdata {\r
- int gpio;\r
- struct i2c_client *client;\r
- struct delayed_work delay_work;\r
- #ifdef HDMI_USE_IRQ\r
- struct work_struct irq_work;\r
- #else\r
- struct workqueue_struct *workqueue;\r
- #endif\r
-};\r
-\r
-extern struct rk610_hdmi_pdata *rk610_hdmi;\r
-\r
-extern int rk610_hdmi_sys_init(void);\r
-extern void rk610_hdmi_interrupt(void);\r
-extern int rk610_hdmi_sys_detect_hpd(void);\r
-extern int rk610_hdmi_sys_insert(void);\r
-extern int rk610_hdmi_sys_remove(void);\r
-extern int rk610_hdmi_sys_read_edid(int block, unsigned char *buff);\r
-extern int rk610_hdmi_sys_config_video(struct hdmi_video_para *vpara);\r
-extern int rk610_hdmi_sys_config_audio(struct hdmi_audio *audio);\r
-extern void rk610_hdmi_sys_enalbe_output(int enable);\r
-extern int rk610_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
- void (*hdcp_irq_cb)(int status),\r
- int (*hdcp_power_on_cb)(void),\r
- void (*hdcp_power_off_cb)(void));\r
-#endif\r
+++ /dev/null
-#include <linux/delay.h>\r
-#include "rk610_hdmi.h"\r
-#include "rk610_hdmi_hw.h"\r
-#include "rk610_hdcp.h"\r
-\r
-static char rk610_hdmi_i2c_read_reg(char reg)\r
-{\r
- char val = 0;\r
- \r
- if(i2c_master_reg8_recv(rk610_hdmi->client, reg, &val, 1, 100*1000) > 0)\r
- return val;\r
- else {\r
- printk(KERN_ERR "[%s] read reg %02x error\n", __FUNCTION__, reg);\r
- return 0;\r
- }\r
-}\r
-static char rk610_hdmi_i2c_write_reg(char reg, char val)\r
-{\r
- if(i2c_master_reg8_send(rk610_hdmi->client, reg, &val, 1, 100*1000) > 0)\r
- return 0;\r
- else {\r
- printk(KERN_ERR "[%s] write reg %02x error\n", __FUNCTION__, reg);\r
- return -EINVAL;\r
- }\r
-}\r
-\r
-#define HDCPWrReg rk610_hdmi_i2c_write_reg\r
-#define HDCPRdReg rk610_hdmi_i2c_read_reg\r
-#define HDCPMskReg(temp, addr, msk, val) \\r
- temp = HDCPRdReg(addr) & (0xFF - (msk)) ; \\r
- HDCPWrReg(addr, temp | ( (val) & (msk) )); \r
- \r
-void rk610_hdcp_disable(void)\r
-{\r
- char temp;\r
- \r
- // Diable HDCP Interrupt\r
- HDCPWrReg(HDCP_INT_MASK1, 0x00);\r
- // Stop and Reset HDCP\r
- HDCPMskReg(temp, HDCP_CTRL1, m_ENCRYPT_ENABLE | m_AUTH_STOP | m_HDCP_RESET, \r
- v_ENCRYPT_ENABLE(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1) )\r
-}\r
-\r
-int rk610_hdcp_load_key2mem(struct hdcp_keys *key)\r
-{\r
- int i;\r
- DBG("HDCP: rk610_hdcp_load_key2mem start");\r
- // Write 40 private key\r
- for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->DeviceKey[i]);\r
- \r
- // Write 1st aksv\r
- for(i = 0; i < 5; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
- \r
- // Write 2nd aksv\r
- for(i = 0; i < 5; i++)\r
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
- DBG("HDCP: rk610_hdcp_load_key2mem end");\r
- return HDCP_OK;\r
-}\r
-\r
-int rk610_hdcp_start_authentication(void)\r
-{\r
- char temp;\r
- int retry = 0;\r
-\r
- if(hdcp->keys == NULL) {\r
- printk(KERN_ERR "HDCP: key is not loaded\n");\r
- return HDCP_KEY_ERR;\r
- }\r
- \r
- // Select TMDS CLK to configure regs\r
- HDCPMskReg(temp, SYS_CTRL, m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);\r
- \r
- temp = HDCPRdReg(HDCP_KEY_STATUS);\r
- while( ( temp & m_KEY_READY) == 0 ) {\r
- if(retry > 10) {\r
- printk(KERN_ERR "HDCP: loaded key error\n");\r
- return HDCP_KEY_ERR;\r
- }\r
- rk610_hdcp_load_key2mem(hdcp->keys);\r
- msleep(1);\r
- temp = HDCPRdReg(HDCP_KEY_STATUS);\r
- }\r
- \r
- // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)\r
- DBG("TMDS frequency %d", hdmi->tmdsclk);\r
- retry = hdmi->tmdsclk/(HDCP_DDC_CLK*4);\r
- HDCPWrReg(DDC_CLK_L, retry & 0xFF);\r
- HDCPWrReg(DDC_CLK_H, (retry >> 8) & 0xFF);\r
- \r
- HDCPWrReg(HDCP_CTRL2, 0x00);\r
- \r
- //Enable interrupt\r
- HDCPWrReg(HDCP_INT_MASK1, m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE | m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);\r
-// HDCPWrReg(HDCP_INT_MASK2, 0xFF);\r
- //Start authentication\r
- HDCPMskReg(temp, HDCP_CTRL1, m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE, v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) | v_ADVANED_ENABLE(0));\r
- \r
- return HDCP_OK;\r
-}\r
-\r
-int rk610_hdcp_check_bksv(void)\r
-{\r
- int i, j;\r
- char temp = 0, bksv[5];\r
- char *invalidkey;\r
- \r
- for(i = 0; i < 5; i++) {\r
- bksv[i] = HDCPRdReg(HDCP_KSV_BYTE0 + (4 - i)) & 0xFF;\r
- }\r
- DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);\r
- \r
- for (i = 0; i < 5; i++)\r
- {\r
- for (j = 0; j < 8; j++)\r
- {\r
- if (bksv[i] & 0x01)\r
- {\r
- temp++;\r
- }\r
- bksv[i] >>= 1;\r
- }\r
- }\r
- if (temp != 20)\r
- return HDCP_KSV_ERR;\r
- \r
- for(i = 0; i < hdcp->invalidkey; i++)\r
- {\r
- invalidkey = hdcp->invalidkeys + i *5;\r
- if(memcmp(bksv, invalidkey, 5) == 0) {\r
- printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");\r
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE, v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));\r
- return HDCP_KSV_ERR;\r
- }\r
- }\r
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE, v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));\r
- return HDCP_OK;\r
-}\r
-\r
-void rk610_hdcp_interrupt(char *status1, char *status2)\r
-{\r
- char interrupt1 = HDCPRdReg(HDCP_INT_STATUS1);\r
- char interrupt2 = HDCPRdReg(HDCP_INT_STATUS2);\r
- if(interrupt1) {\r
- HDCPWrReg(HDCP_INT_STATUS1, interrupt1);\r
- if(interrupt1 & m_INT_HDCP_ERR)\r
- printk(KERN_INFO "HDCP: Error 0x%02x\n", HDCPRdReg(HDCP_ERROR));\r
- }\r
- if(interrupt2)\r
- HDCPWrReg(HDCP_INT_STATUS2, interrupt2);\r
- \r
- *status1 = interrupt1;\r
- *status2 = interrupt2;\r
-}
\ No newline at end of file
+++ /dev/null
-#include <linux/delay.h>\r
-#include "rk610_hdmi.h"\r
-#include "rk610_hdmi_hw.h"\r
-#include <asm/atomic.h>\r
-\r
-static atomic_t edid_ready;\r
-\r
-static int rk610_hdmi_i2c_read_reg(char reg, char *val)\r
-{\r
- if(i2c_master_reg8_recv(rk610_hdmi->client, reg, val, 1, 100*1000) > 0)\r
- return 0;\r
- else {\r
- printk("[%s] reg %02x error\n", __FUNCTION__, reg);\r
- return -EINVAL;\r
- }\r
-}\r
-static int rk610_hdmi_i2c_write_reg(char reg, char val)\r
-{\r
- return i2c_master_reg8_send(rk610_hdmi->client, reg, &val, 1, 100*1000) > 0? 0: -EINVAL;\r
-}\r
-\r
-#define HDMIWrReg rk610_hdmi_i2c_write_reg\r
-\r
-int rk610_hdmi_sys_init(void)\r
-{\r
- // System power power off\r
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_OFF | v_INT_POL_HIGH);\r
- \r
- //Synchronize analog module.\r
-// HDMIWrReg(PHY_SYNC, 0x00);\r
-// HDMIWrReg(PHY_SYNC, 0x01);\r
- \r
- // set hdmi phy parameters\r
- // driver mode\r
- HDMIWrReg(PHY_DRIVER, v_MAIN_DRIVER(8)| v_PRE_DRIVER(0) | v_TX_ENABLE(0));\r
-// HDMIWrReg(PHY_PRE_EMPHASIS, 0x04);\r
- HDMIWrReg(PHY_PRE_EMPHASIS, v_PRE_EMPHASIS(0) | v_TMDS_PWRDOWN(1)); //Driver power down \r
- // pll mode\r
- HDMIWrReg(0xe8, 0x10);\r
- HDMIWrReg(0xe6, 0x2c);\r
-\r
- HDMIWrReg(PHY_PLL_CTRL, v_PLL_DISABLE(1) | v_PLL_RESET(1) | v_TMDS_RESET(1));\r
- HDMIWrReg(PHY_PLL_LDO_PWR, v_LDO_PWR_DOWN(1));\r
- HDMIWrReg(PHY_BANDGAP_PWR, v_BANDGAP_PWR_DOWN);\r
-\r
- // Enable Hotplug interrupt\r
- HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG);\r
- return HDMI_ERROR_SUCESS;\r
-}\r
-\r
-void rk610_hdmi_interrupt()\r
-{\r
- char interrupt = 0;\r
- \r
- if(rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &interrupt))\r
- return;\r
- \r
- HDMIWrReg(INTERRUPT_STATUS1, interrupt);\r
- \r
- if(interrupt)\r
- HDMIWrReg(INTERRUPT_STATUS1, interrupt);\r
- \r
- if(interrupt & m_INT_HOTPLUG) {\r
- hdmi_dbg(hdmi->dev, "%s interrupt %02x\n", __FUNCTION__, interrupt);\r
- if(hdmi->state == HDMI_SLEEP)\r
- hdmi->state = WAIT_HOTPLUG;\r
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); \r
- }\r
- else if(interrupt & m_INT_EDID_READY) {\r
- atomic_set(&edid_ready, 1);\r
- }\r
-}\r
-\r
-int rk610_hdmi_sys_detect_hpd(void)\r
-{\r
- char hdmi_status = 0;\r
-\r
- #ifdef HDMI_USE_IRQ\r
- rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &hdmi_status);\r
- HDMIWrReg(INTERRUPT_STATUS1, hdmi_status);\r
- #endif\r
- hdmi_status = 0;\r
- rk610_hdmi_i2c_read_reg(HDMI_STATUS, &hdmi_status);\r
-// printk("%s value is %02x\n", __FUNCTION__, hdmi_status); \r
- if(hdmi_status)\r
- return HDMI_HPD_ACTIVED;\r
- else\r
- return HDMI_HPD_REMOVED;\r
-}\r
-\r
-#define SYSCLK 11289600\r
-#define DDC_CLK 100000\r
-int rk610_hdmi_sys_read_edid(int block, unsigned char *buff)\r
-{\r
- char value;\r
- int count, rc = HDMI_ERROR_EDID;\r
- char hdmi_status = 0;\r
- \r
- // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)\r
- // when reg00 select reg_clk equal to sys_clk which is equal\r
- // to i2s clk, it gernerally is 11.2896MHz.\r
- \r
- count = SYSCLK/(DDC_CLK*4);\r
- HDMIWrReg(DDC_CLK_L, count & 0xFF);\r
- HDMIWrReg(DDC_CLK_H, (count >> 8) & 0xFF);\r
- \r
- // Enable EDID Interrupt\r
-// edid_ready = 0;\r
- atomic_set(&edid_ready, 0);\r
- value = 0;\r
- rk610_hdmi_i2c_read_reg(INTERRUPT_MASK1, &value);\r
- value |= m_INT_EDID_READY;\r
- HDMIWrReg(INTERRUPT_MASK1, value);\r
- \r
- // Reset FIFO offset\r
- HDMIWrReg(EDID_FIFO_OFFSET, 0);\r
- // Set EDID read addr.\r
- HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);\r
- HDMIWrReg(EDID_SEGMENT_POINTER, block/2);\r
-\r
- count = 0;\r
- while(count++ < 10)\r
- { \r
-#ifdef HDMI_USE_IRQ\r
- value = atomic_read(&edid_ready);\r
-#else \r
- msleep(10);\r
- rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &hdmi_status);\r
- value = (hdmi_status & m_INT_EDID_READY);\r
-#endif\r
- if(value)\r
- {\r
- for(value = 0; value < 128; value++)\r
- rk610_hdmi_i2c_read_reg(EDID_FIFO_ADDR, buff + value);\r
- rc = HDMI_ERROR_SUCESS;\r
- break;\r
- }\r
- msleep(100);\r
- }\r
- // Disable EDID interrupt.\r
- value = 0;\r
- rk610_hdmi_i2c_read_reg(INTERRUPT_MASK1, &value);\r
- value &= ~m_INT_EDID_READY;\r
- HDMIWrReg(INTERRUPT_MASK1, value);\r
- return rc;\r
-}\r
-\r
-static void rk610_hdmi_config_avi(unsigned char vic, unsigned char output_color)\r
-{\r
- int i;\r
- char info[SIZE_AVI_INFOFRAME];\r
- \r
- memset(info, 0, SIZE_AVI_INFOFRAME);\r
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);\r
- info[0] = 0x82;\r
- info[1] = 0x02;\r
- info[2] = 0x0D; \r
- info[3] = info[0] + info[1] + info[2];\r
- info[4] = (AVI_COLOR_MODE_RGB << 5);\r
- info[5] = (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;\r
- info[6] = 0;\r
- info[7] = vic;\r
- info[8] = 0;\r
-\r
- // Calculate AVI InfoFrame ChecKsum\r
- for (i = 4; i < SIZE_AVI_INFOFRAME; i++)\r
- {\r
- info[3] += info[i];\r
- }\r
- info[3] = 0x100 - info[3];\r
- \r
- for(i = 0; i < SIZE_AVI_INFOFRAME; i++)\r
- HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);\r
-}\r
-\r
-int rk610_hdmi_sys_config_video(struct hdmi_video_para *vpara)\r
-{\r
- char value;\r
- struct fb_videomode *mode;\r
- \r
- hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);\r
- if(vpara == NULL) {\r
- hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);\r
- return -1;\r
- }\r
- if(hdmi->hdcp_power_off_cb)\r
- hdmi->hdcp_power_off_cb();\r
- // Diable video and audio output\r
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));\r
- \r
- // Input video mode is SDR RGB24bit, Data enable signal from external\r
- HDMIWrReg(VIDEO_CONTRL1, v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) | v_DE_EXTERNAL);\r
- HDMIWrReg(VIDEO_CONTRL2, v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | (vpara->output_color & 0xFF));\r
-\r
- // Set HDMI Mode\r
- HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));\r
-\r
- // Enable or disalbe color space convert\r
- if(vpara->input_color != vpara->output_color) {\r
- value = v_SOF_DISABLE | v_CSC_ENABLE;\r
- }\r
- else\r
- value = v_SOF_DISABLE;\r
- HDMIWrReg(VIDEO_CONTRL3, value);\r
- \r
- #if 1\r
- HDMIWrReg(VIDEO_TIMING_CTL, 0);\r
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);\r
- if(mode == NULL)\r
- {\r
- hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);\r
- return -ENOENT;\r
- }\r
- hdmi->tmdsclk = mode->pixclock;\r
-#else\r
- value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);\r
- if(mode->sync & FB_SYNC_HOR_HIGH_ACT)\r
- value |= v_HSYNC_POLARITY(1);\r
- if(mode->sync & FB_SYNC_VERT_HIGH_ACT)\r
- value |= v_VSYNC_POLARITY(1);\r
- HDMIWrReg(VIDEO_TIMING_CTL, value);\r
- \r
- value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;\r
- HDMIWrReg(VIDEO_EXT_HTOTAL_L, value & 0xFF);\r
- HDMIWrReg(VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);\r
- \r
- value = mode->left_margin + mode->right_margin + mode->hsync_len;\r
- HDMIWrReg(VIDEO_EXT_HBLANK_L, value & 0xFF);\r
- HDMIWrReg(VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);\r
- \r
- value = mode->left_margin + mode->hsync_len;\r
- HDMIWrReg(VIDEO_EXT_HDELAY_L, value & 0xFF);\r
- HDMIWrReg(VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);\r
- \r
- value = mode->hsync_len;\r
- HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF);\r
- HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);\r
- \r
- value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;\r
- HDMIWrReg(VIDEO_EXT_VTOTAL_L, value & 0xFF);\r
- HDMIWrReg(VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);\r
- \r
- value = mode->upper_margin + mode->vsync_len + mode->lower_margin;\r
- HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF);\r
-\r
- if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)\r
- value = 42;\r
- else\r
- value = mode->upper_margin + mode->vsync_len;\r
-\r
- HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF);\r
- \r
- value = mode->vsync_len;\r
- HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF);\r
- #endif\r
- \r
- if(vpara->output_mode == OUTPUT_HDMI) {\r
- rk610_hdmi_config_avi(vpara->vic, vpara->output_color);\r
- hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);\r
- }\r
- else {\r
- hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); \r
- }\r
-\r
- // Power on TMDS\r
- HDMIWrReg(PHY_PRE_EMPHASIS, v_PRE_EMPHASIS(0) | v_TMDS_PWRDOWN(0)); // TMDS power on\r
- \r
- // Enable TMDS\r
- value = 0;\r
- rk610_hdmi_i2c_read_reg(PHY_DRIVER, &value);\r
- value |= v_TX_ENABLE(1);\r
- HDMIWrReg(PHY_DRIVER, value);\r
- \r
- return 0;\r
-}\r
-\r
-static void rk610_hdmi_config_aai(void)\r
-{\r
- int i;\r
- char info[SIZE_AUDIO_INFOFRAME];\r
- \r
- memset(info, 0, SIZE_AUDIO_INFOFRAME);\r
- \r
- info[0] = 0x84;\r
- info[1] = 0x01;\r
- info[2] = 0x0A;\r
- \r
- info[3] = info[0] + info[1] + info[2]; \r
- for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)\r
- info[3] += info[i];\r
- \r
- info[3] = 0x100 - info[3];\r
- \r
- HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);\r
- for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)\r
- HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);\r
-}\r
-\r
-int rk610_hdmi_sys_config_audio(struct hdmi_audio *audio)\r
-{\r
- int rate, N, channel, mclk_fs;\r
- \r
- if(audio->channel < 3)\r
- channel = I2S_CHANNEL_1_2;\r
- else if(audio->channel < 5)\r
- channel = I2S_CHANNEL_3_4;\r
- else if(audio->channel < 7)\r
- channel = I2S_CHANNEL_5_6;\r
- else\r
- channel = I2S_CHANNEL_7_8;\r
- \r
- switch(audio->rate)\r
- {\r
- case HDMI_AUDIO_FS_32000:\r
- rate = AUDIO_32K;\r
- N = N_32K;\r
- mclk_fs = MCLK_384FS;\r
- break;\r
- case HDMI_AUDIO_FS_44100:\r
- rate = AUDIO_441K;\r
- N = N_441K;\r
- mclk_fs = MCLK_256FS;\r
- break;\r
- case HDMI_AUDIO_FS_48000:\r
- rate = AUDIO_48K;\r
- N = N_48K;\r
- mclk_fs = MCLK_256FS;\r
- break;\r
- case HDMI_AUDIO_FS_88200:\r
- rate = AUDIO_882K;\r
- N = N_882K;\r
- mclk_fs = MCLK_128FS;\r
- break;\r
- case HDMI_AUDIO_FS_96000:\r
- rate = AUDIO_96K;\r
- N = N_96K;\r
- mclk_fs = MCLK_128FS;\r
- break;\r
- case HDMI_AUDIO_FS_176400:\r
- rate = AUDIO_1764K;\r
- N = N_1764K;\r
- mclk_fs = MCLK_128FS;\r
- break;\r
- case HDMI_AUDIO_FS_192000:\r
- rate = AUDIO_192K;\r
- N = N_192K;\r
- mclk_fs = MCLK_128FS;\r
- break;\r
- default:\r
- dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);\r
- return -ENOENT;\r
- }\r
-\r
- //set_audio source I2S\r
- HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK\r
- HDMIWrReg(AUDIO_SAMPLE_RATE, rate);\r
- HDMIWrReg(AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel) ); \r
- HDMIWrReg(AUDIO_I2S_MAP, 0x00); \r
- HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap \r
- \r
- //Set N value\r
- HDMIWrReg(AUDIO_N_H, (N >> 16) & 0x0F);\r
- HDMIWrReg(AUDIO_N_M, (N >> 8) & 0xFF); \r
- HDMIWrReg(AUDIO_N_L, N & 0xFF); \r
- rk610_hdmi_config_aai();\r
- \r
- return 0;\r
-}\r
-\r
-void rk610_hdmi_sys_enalbe_output(int enable)\r
-{\r
- char mutestatus = 0;\r
- \r
- if(enable) {\r
- rk610_hdmi_i2c_read_reg(AV_MUTE, &mutestatus);\r
- if(mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {\r
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));\r
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH);\r
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_OFF | v_INT_POL_HIGH);\r
- HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH);\r
- if(hdmi->hdcp_cb)\r
- hdmi->hdcp_cb();\r
- }\r
- }\r
- else {\r
- HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1)); \r
- }\r
-}\r
-\r
-int rk610_hdmi_sys_insert(void)\r
-{\r
- hdmi_dbg(hdmi->dev, "%s \n", __FUNCTION__);\r
- //Bring up analog module.\r
- HDMIWrReg(PHY_BANDGAP_PWR, v_BANDGAP_PWR_UP); //BG power on \r
- HDMIWrReg(PHY_PLL_LDO_PWR, 0x00); //PLL power on\r
- msleep(1);\r
- HDMIWrReg(PHY_PLL_CTRL, v_PLL_DISABLE(0)); //Analog reset\r
- return 0;\r
-}\r
-\r
-int rk610_hdmi_sys_remove(void)\r
-{\r
- hdmi_dbg(hdmi->dev, "%s \n", __FUNCTION__);\r
- if(hdmi->hdcp_power_off_cb)\r
- hdmi->hdcp_power_off_cb();\r
- HDMIWrReg(PHY_DRIVER, v_MAIN_DRIVER(8)| v_PRE_DRIVER(0) | v_TX_ENABLE(0));\r
- HDMIWrReg(PHY_PRE_EMPHASIS, v_PRE_EMPHASIS(0) | v_TMDS_PWRDOWN(1)); //Driver power down \r
- HDMIWrReg(PHY_PLL_CTRL, v_PLL_DISABLE(1) | v_PLL_RESET(1) | v_TMDS_RESET(1));\r
- HDMIWrReg(PHY_PLL_LDO_PWR, v_LDO_PWR_DOWN(1));\r
- HDMIWrReg(PHY_BANDGAP_PWR, v_BANDGAP_PWR_DOWN);\r
- return 0;\r
-}\r
+++ /dev/null
-#ifndef _RK610_HDMI_HW_H
-#define _RK610_HDMI_HW_H
-
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
- };
-
-#define SYS_CTRL 0x00
- #define m_INT_POL (1 << 0)
- #define m_POWER (1 << 1)
- #define m_REG_CLK_SOURCE (1 << 2)
- #define v_INT_POL_HIGH 1
- #define v_INT_POL_LOW 0
- #define v_PWR_ON (0 << 1)
- #define v_PWR_OFF (1 << 1)
- #define v_REG_CLK_SOURCE_TMDS (0 << 2)
- #define v_REG_CLK_SOURCE_IIS (1 << 2)
-#define VIDEO_CONTRL1 0x01
- #define m_VIDEO_INPUT_FORMAT (7 << 1)
- #define m_DE_SOURCE (1 << 0)
- enum {
- VIDEO_INPUT_SDR_RGB444 = 0,
- VIDEO_INPUT_DDR_RGB444 = 5,
- VIDEO_INPUT_DDR_YCBCR422 = 6
- };
- #define v_VIDEO_INPUT_FORMAT(n) (n << 1)
- #define v_DE_EXTERNAL 1
- #define v_DE_INTERANL 0
-
-#define VIDEO_CONTRL2 0x02
- #define m_VIDEO_OUTPUT_FORMAT (3 << 6)
- #define m_VIDEO_INPUT_BITS (3 << 4)
- #define v_VIDEO_OUTPUT_FORMAT(n)(n << 6)
- #define v_VIDEO_INPUT_BITS(n) (n << 4)
- enum{
- VIDEO_INPUT_12BITS = 0,
- VIDEO_INPUT_10BITS,
- VIDEO_INPUT_8BITS
- };
-#define VIDEO_CONTRL3 0x04
- #define m_SOF (1 << 3)
- #define m_CSC (1 << 0)
- #define v_SOF_ENABLE (0 << 3)
- #define v_SOF_DISABLE (1 << 3)
- #define v_CSC_ENABLE 1
- #define v_CSC_DISABLE 0
-
-#define AV_MUTE 0x05
- #define m_AVMUTE_CLEAR (1 << 7)
- #define m_AVMUTE_ENABLE (1 << 6)
- #define m_AUDIO_MUTE (1 << 1)
- #define m_VIDEO_BLACK (1 << 0)
- #define v_AUDIO_MUTE(n) (n << 1)
- #define v_VIDEO_MUTE(n) (n << 0)
-
-#define VIDEO_TIMING_CTL 0x08
- #define v_HSYNC_POLARITY(n) (n << 3)
- #define v_VSYNC_POLARITY(n) (n << 2)
- #define v_INETLACE(n) (n << 1)
- #define v_EXTERANL_VIDEO(n) (n << 0)
-
-#define VIDEO_EXT_HTOTAL_L 0x09
-#define VIDEO_EXT_HTOTAL_H 0x0a
-#define VIDEO_EXT_HBLANK_L 0x0b
-#define VIDEO_EXT_HBLANK_H 0x0c
-#define VIDEO_EXT_HDELAY_L 0x0d
-#define VIDEO_EXT_HDELAY_H 0x0e
-#define VIDEO_EXT_HDURATION_L 0x0f
-#define VIDEO_EXT_HDURATION_H 0x10
-#define VIDEO_EXT_VTOTAL_L 0x11
-#define VIDEO_EXT_VTOTAL_H 0x12
-#define VIDEO_EXT_VBLANK 0x13
-#define VIDEO_EXT_VDELAY 0x14
-#define VIDEO_EXT_VDURATION 0x15
-
-#define AUDIO_CTRL1 0x35
- enum {
- CTS_SOURCE_INTERNAL = 0,
- CTS_SOURCE_EXTERNAL
- };
- #define v_CTS_SOURCE(n) (n << 7)
- enum {
- DOWNSAMPLE_DISABLE = 0,
- DOWNSAMPLE_1_2,
- DOWNSAMPLE_1_4
- };
- #define v_DOWN_SAMPLE(n) (n << 5)
- enum {
- AUDIO_SOURCE_IIS = 0,
- AUDIO_SOURCE_SPDIF
- };
- #define v_AUDIO_SOURCE(n) (n << 3)
- #define v_MCLK_ENABLE(n) (n << 2)
- enum {
- MCLK_128FS = 0,
- MCLK_256FS,
- MCLK_384FS,
- MCLK_512FS
- };
- #define v_MCLK_RATIO(n) (n)
-
-#define AUDIO_SAMPLE_RATE 0x37
- enum {
- AUDIO_32K = 0x3,
- AUDIO_441K = 0x0,
- AUDIO_48K = 0x2,
- AUDIO_882K = 0x8,
- AUDIO_96K = 0xa,
- AUDIO_1764K = 0xc,
- AUDIO_192K = 0xe,
- };
-
-#define AUDIO_I2S_MODE 0x38
- enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
- };
- #define v_I2S_CHANNEL(n) ((n) << 2)
- enum {
- I2S_STANDARD = 0,
- I2S_LEFT_JUSTIFIED,
- I2S_RIGHT_JUSTIFIED
- };
- #define v_I2S_MODE(n) (n)
-
-#define AUDIO_I2S_MAP 0x39
-#define AUDIO_I2S_SWAPS_SPDIF 0x3a
- #define v_SPIDF_FREQ(n) (n)
-
-#define N_32K 0x1000
-#define N_441K 0x1880
-#define N_882K 0x3100
-#define N_1764K 0x6200
-#define N_48K 0x1800
-#define N_96K 0x3000
-#define N_192K 0x6000
-
-#define AUDIO_N_H 0x3f
-#define AUDIO_N_M 0x40
-#define AUDIO_N_L 0x41
-
-#define AUDIO_CTS_H 0x45
-#define AUDIO_CTS_M 0x46
-#define AUDIO_CTS_L 0x47
-
-
-#define DDC_CLK_L 0x4b
-#define DDC_CLK_H 0x4c
-
-#define EDID_SEGMENT_POINTER 0x4d
-#define EDID_WORD_ADDR 0x4e
-#define EDID_FIFO_OFFSET 0x4f
-#define EDID_FIFO_ADDR 0x50
-
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX 0x9f
-enum {
- INFOFRAME_AVI = 0x06,
- INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_ADDR 0xa0
-
-
-#define SIZE_AVI_INFOFRAME 0x11 // 14 bytes
-#define SIZE_AUDIO_INFOFRAME 0x0F // 15 bytes
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-
-#define HDCP_CTRL 0x52
- #define m_HDMI_DVI (1 << 1)
- #define v_HDMI_DVI(n) (n << 1)
-
-#define INTERRUPT_MASK1 0xc0
-#define INTERRUPT_STATUS1 0xc1
- #define m_INT_HOTPLUG (1 << 7)
- #define m_INT_ACTIVE_VSYNC (1 << 6)
- #define m_INT_EDID_READY (1 << 2)
-
-#define INTERRUPT_MASK2 0xc2
-#define INTERRUPT_STATUS2 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_FLAG (1 << 6)
- #define m_INT_HDCP_OK (1 << 4)
-
-#define HDMI_STATUS 0xc8
- #define m_HOTPLUG (1 << 7)
- #define m_DDC_SDA (1 << 5)
- #define m_DDC_SDC (1 << 4)
-
-#define PHY_SYNC 0xce //sync phy parameter
-
-#define PHY_DRIVER 0xe1
- #define v_MAIN_DRIVER(n) (n << 4)
- #define v_PRE_DRIVER(n) (n << 2)
- #define v_TX_ENABLE(n) (n << 1)
-
-#define PHY_PRE_EMPHASIS 0xe2
- #define v_PRE_EMPHASIS(n) (n << 4)
- #define v_TMDS_PWRDOWN(n) (n)
-
-#define PHY_PLL_TEST 0xe3
-#define PHY_BANDGAP_PWR 0xe4
- #define v_BANDGAP_PWR_DOWN 0x03
- #define v_BANDGAP_PWR_UP 0
-
-#define PHY_PLL_CTRL 0xe5
- #define v_PLL_DISABLE(n) (n << 4)
- #define v_PLL_RESET(n) (n << 3)
- #define v_TMDS_RESET(n) (n << 2)
-
-#define PHY_PLL_LDO_PWR 0xe7
- #define v_LDO_PWR_DOWN(n) (n << 2)
-
-#endif
\ No newline at end of file
+++ /dev/null
-config HDCP_RK616
- bool "RK616 HDCP support"
- depends on HDMI_RK616 || ARCH_RK3026
- default n
- help
- HDCP Interface. This adds the High Definition Content Protection Interface.
- See http://www.digital-cp.com/ for HDCP specification.
-
-config HDCP_RK616_DEBUG
- bool "RK616 HDCP Debugging"
- depends on HDCP_RK616
- default n
- help
- Enableds verbose debugging the the HDCP drivers
+++ /dev/null
-#
-# Makefile for HDMI linux kernel module.
-#
-
-ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
-ccflags-$(CONFIG_HDCP_RK616_DEBUG) = -DHDCP_DEBUG
-
-obj-$(CONFIG_HDMI_RK616) += rk616_hdmi_hw.o rk616_hdmi.o
-obj-$(CONFIG_HDCP_RK616) += rk616_hdmi_hdcp.o rk616_hdcp.o
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/miscdevice.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include "rk616_hdmi.h"
-#include "rk616_hdcp.h"
-
-struct hdcp *hdcp = NULL;
-
-static void hdcp_work_queue(struct work_struct *work);
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_submit_work
- *-----------------------------------------------------------------------------
- */
-static struct delayed_work *hdcp_submit_work(int event, int delay)
-{
- struct hdcp_delayed_work *work;
-
- DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
-
- work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
-
- if (work) {
- INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
- work->event = event;
- queue_delayed_work(hdcp->workqueue,
- &work->work,
- msecs_to_jiffies(delay));
- } else {
- printk(KERN_WARNING "HDCP: Cannot allocate memory to "
- "create work\n");
- return 0;
- }
-
- return &work->work;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_cancel_work
- *-----------------------------------------------------------------------------
- */
-static void hdcp_cancel_work(struct delayed_work **work)
-{
- int ret = 0;
-
- if (*work) {
- ret = cancel_delayed_work(*work);
- if (ret != 1) {
- ret = cancel_work_sync(&((*work)->work));
- printk(KERN_INFO "Canceling work failed - "
- "cancel_work_sync done %d\n", ret);
- }
- kfree(*work);
- *work = 0;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_failure
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_failure(void)
-{
- if (hdcp->hdmi_state == HDMI_STOPPED) {
- return;
- }
-
- rk616_hdcp_disable();
- rk616_hdmi_control_output(false);
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
- if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
- hdcp->retry_cnt--;
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying, attempts=%d\n",
- hdcp->retry_cnt);
- } else
- printk(KERN_INFO "HDCP: authentication failed - "
- "retrying\n");
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
- HDCP_REAUTH_DELAY);
- } else {
- printk(KERN_INFO "HDCP: authentication failed - "
- "HDCP disabled\n");
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
-
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_start_authentication
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_start_authentication(void)
-{
- int status = HDCP_OK;
-
- hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
-
- DBG("HDCP: authentication start");
-
- status = rk616_hdcp_start_authentication();
-
- if (status != HDCP_OK) {
- DBG("HDCP: authentication failed");
- hdcp_wq_authentication_failure();
- } else {
- hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
-// hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_check_bksv
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_check_bksv(void)
-{
- int status = HDCP_OK;
-
- DBG("Check BKSV start");
-
- status = rk616_hdcp_check_bksv();
-
- if (status != HDCP_OK) {
- printk(KERN_INFO "HDCP: Check BKSV failed");
- hdcp->retry_cnt = 0;
- hdcp_wq_authentication_failure();
- }
- else {
- DBG("HDCP: Check BKSV successful");
-
- hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
-
- /* Restore retry counter */
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_authentication_sucess
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_authentication_sucess(void)
-{
- rk616_hdmi_control_output(true);
- printk(KERN_INFO "HDCP: authentication pass");
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_wq_disable
- *-----------------------------------------------------------------------------
- */
-static void hdcp_wq_disable(int event)
-{
- printk(KERN_INFO "HDCP: disabled");
-
- hdcp_cancel_work(&hdcp->pending_wq_event);
- rk616_hdcp_disable();
- if(event == HDCP_DISABLE_CTL) {
- hdcp->hdcp_state = HDCP_DISABLED;
- if(hdcp->hdmi_state == HDMI_STARTED)
- rk616_hdmi_control_output(true);
- }
- else if(event == HDCP_STOP_FRAME_EVENT)
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_work_queue
- *-----------------------------------------------------------------------------
- */
-static void hdcp_work_queue(struct work_struct *work)
-{
- struct hdcp_delayed_work *hdcp_w =
- container_of(work, struct hdcp_delayed_work, work.work);
- int event = hdcp_w->event;
-
- mutex_lock(&hdcp->lock);
-
- DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
- jiffies_to_msecs(jiffies),
- hdcp->hdmi_state,
- hdcp->hdcp_state,
- (event & 0xFF00) >> 8,
- event & 0xFF);
-
- if(event == HDCP_STOP_FRAME_EVENT) {
- hdcp->hdmi_state = HDMI_STOPPED;
- }
-
- if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
- hdcp_wq_disable(event);
- }
-
- if (event & HDCP_WORKQUEUE_SRC)
- hdcp->pending_wq_event = 0;
-
- /* First handle HDMI state */
- if (event == HDCP_START_FRAME_EVENT) {
- hdcp->pending_start = 0;
- hdcp->hdmi_state = HDMI_STARTED;
- }
-
- /**********************/
- /* HDCP state machine */
- /**********************/
- switch (hdcp->hdcp_state) {
- case HDCP_DISABLED:
- /* HDCP enable control or re-authentication event */
- if (event == HDCP_ENABLE_CTL) {
- if(hdcp->retry_times == 0)
- hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
- else
- hdcp->retry_cnt = hdcp->retry_times;
- if (hdcp->hdmi_state == HDMI_STARTED)
- hdcp_wq_start_authentication();
- else
- hdcp->hdcp_state = HDCP_ENABLE_PENDING;
- }
- break;
-
- case HDCP_ENABLE_PENDING:
- /* HDMI start frame event */
- if (event == HDCP_START_FRAME_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_AUTHENTICATION_START:
- /* Re-authentication */
- if (event == HDCP_AUTH_REATT_EVENT)
- hdcp_wq_start_authentication();
-
- break;
-
- case HDCP_WAIT_KSV_LIST:
- /* KSV failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: KSV switch failure\n");
-
- hdcp_wq_authentication_failure();
- }
- /* KSV list ready event */
- else if (event == HDCP_KSV_LIST_RDY_EVENT)
- hdcp_wq_check_bksv();
- break;
-
- case HDCP_LINK_INTEGRITY_CHECK:
- /* Ri failure */
- if (event == HDCP_FAIL_EVENT) {
- printk(KERN_INFO "HDCP: Ri check failure\n");
- hdcp_wq_authentication_failure();
- }
- else if(event == HDCP_AUTH_PASS_EVENT)
- hdcp_wq_authentication_sucess();
- break;
-
- default:
- printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
- break;
- }
-
- kfree(hdcp_w);
- if(event == HDCP_STOP_FRAME_EVENT)
- complete(&hdcp->complete);
-
- mutex_unlock(&hdcp->lock);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_start_frame_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_start_frame_cb(void)
-{
- DBG("hdcp_start_frame_cb()");
-
- /* Cancel any pending work */
- if (hdcp->pending_start)
- hdcp_cancel_work(&hdcp->pending_start);
- if (hdcp->pending_wq_event)
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_irq_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_irq_cb(int status)
-{
- char interrupt1;
- char interrupt2;
-
- rk616_hdcp_interrupt(&interrupt1, &interrupt2);
- DBG("%s 0x%02x 0x%02x", __FUNCTION__, interrupt1, interrupt2);
- if(interrupt1 & m_INT_HDCP_ERR)
- {
- if( (hdcp->hdcp_state != HDCP_DISABLED) &&
- (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
- {
- hdcp_submit_work(HDCP_FAIL_EVENT, 0);
- }
- }
- else if(interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
- hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
- else if(interrupt1 & m_INT_AUTH_SUCCESS)
- hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_on_cb
- *-----------------------------------------------------------------------------
- */
-static int hdcp_power_on_cb(void)
-{
- DBG("%s", __FUNCTION__);
-// return rk616_hdcp_load_key2mem(hdcp->keys);
- return HDCP_OK;
-}
-
-/*-----------------------------------------------------------------------------
- * Function: hdcp_power_off_cb
- *-----------------------------------------------------------------------------
- */
-static void hdcp_power_off_cb(void)
-{
- DBG("%s", __FUNCTION__);
- if(!hdcp->enable)
- return;
-
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
- init_completion(&hdcp->complete);
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
- wait_for_completion_interruptible_timeout(&hdcp->complete,
- msecs_to_jiffies(5000));
-}
-
-// Load HDCP key to external HDCP memory
-static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
-{
- if (!fw) {
- pr_err("HDCP: failed to load keys\n");
- return;
- }
-
- if(fw->size < HDCP_KEY_SIZE) {
- pr_err("HDCP: firmware wrong size %d\n", fw->size);
- return;
- }
-
- hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->keys == NULL) {
- pr_err("HDCP: can't allocated space for keys\n");
- return;
- }
-
- memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
-
- printk(KERN_INFO "HDCP: load hdcp key success\n");
-
- if(fw->size > HDCP_KEY_SIZE) {
- DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
- if((fw->size - HDCP_KEY_SIZE) % 5) {
- pr_err("HDCP: failed to load invalid keys\n");
- return;
- }
- hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
- if(hdcp->invalidkeys == NULL) {
- pr_err("HDCP: can't allocated space for invalid keys\n");
- return;
- }
- memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
- hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
- printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
- }
-}
-
-static ssize_t hdcp_enable_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int enable = 0;
-
- if(hdcp)
- enable = hdcp->enable;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t hdcp_enable_write(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int enable;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &enable);
- if(hdcp->enable != enable)
- {
- /* Post event to workqueue */
- if(enable) {
- if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- else {
- hdcp_cancel_work(&hdcp->pending_start);
- hdcp_cancel_work(&hdcp->pending_wq_event);
-
- /* Post event to workqueue */
- if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
- return -EFAULT;
- }
- hdcp->enable = enable;
- }
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
-
-static ssize_t hdcp_trytimes_read(struct device *device,
- struct device_attribute *attr, char *buf)
-{
- int trytimes = 0;
-
- if(hdcp)
- trytimes = hdcp->retry_times;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
-}
-
-static ssize_t hdcp_trytimes_wrtie(struct device *device,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int trytimes;
-
- if(hdcp == NULL)
- return -EINVAL;
-
- sscanf(buf, "%d", &trytimes);
- if(hdcp->retry_times != trytimes)
- hdcp->retry_times = trytimes;
-
- return count;
-}
-
-
-static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
-
-
-static struct miscdevice mdev;
-
-static int __init rk616_hdcp_init(void)
-{
- int ret;
-
- DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
-
- hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
- if(!hdcp)
- {
- printk(KERN_ERR ">>HDCP: kmalloc fail!");
- ret = -ENOMEM;
- goto error0;
- }
- memset(hdcp, 0, sizeof(struct hdcp));
- mutex_init(&hdcp->lock);
-
- mdev.minor = MISC_DYNAMIC_MINOR;
- mdev.name = "hdcp";
- mdev.mode = 0666;
- if (misc_register(&mdev)) {
- printk(KERN_ERR "HDCP: Could not add character driver\n");
- ret = HDMI_ERROR_FALSE;
- goto error1;
- }
- ret = device_create_file(mdev.this_device, &dev_attr_enable);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file enable\n");
- ret = -EINVAL;
- goto error2;
- }
-
- ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
- if(ret)
- {
- printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
- ret = -EINVAL;
- goto error3;
- }
-
- hdcp->workqueue = create_singlethread_workqueue("hdcp");
- if (hdcp->workqueue == NULL) {
- printk(KERN_ERR "HDCP,: create workqueue failed.\n");
- goto error4;
- }
-
-
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "hdcp.keys", mdev.this_device, GFP_KERNEL,
- hdcp, hdcp_load_keys_cb);
- if (ret < 0) {
- printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
- goto error5;
- }
-
- rk616_hdmi_register_hdcp_callbacks(hdcp_start_frame_cb,
- hdcp_irq_cb,
- hdcp_power_on_cb,
- hdcp_power_off_cb);
-
- DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
- return 0;
-
-error5:
- destroy_workqueue(hdcp->workqueue);
-error4:
- device_remove_file(mdev.this_device, &dev_attr_trytimes);
-error3:
- device_remove_file(mdev.this_device, &dev_attr_enable);
-error2:
- misc_deregister(&mdev);
-error1:
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-error0:
- return ret;
-}
-
-static void __exit rk616_hdcp_exit(void)
-{
- device_remove_file(mdev.this_device, &dev_attr_enable);
- misc_deregister(&mdev);
- if(hdcp->keys)
- kfree(hdcp->keys);
- if(hdcp->invalidkeys)
- kfree(hdcp->invalidkeys);
- kfree(hdcp);
-}
-
-module_init(rk616_hdcp_init);
-module_exit(rk616_hdcp_exit);
+++ /dev/null
-#ifndef __rk616_HDCP_H__
-#define __rk616_HDCP_H__
-
-/***************************/
-/* Definitions */
-/***************************/
-
-/* Status / error codes */
-#define HDCP_OK 0
-#define HDCP_KEY_ERR 1
-#define HDCP_KSV_ERR 2
-
-/* Delays */
-#define HDCP_ENABLE_DELAY 300
-#define HDCP_REAUTH_DELAY 100
-
-/* Event source */
-#define HDCP_SRC_SHIFT 8
-#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
-#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
-#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
-#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
-
-/* Event */
-#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
-#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
-#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
-#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
-#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 4)
-#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 5)
-#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 6)
-#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 7)
-
-/* Key size */
-#define HDCP_KEY_SIZE 308
-
-/* HDCP DDC Clock */
-#define HDCP_DDC_CLK 100000
-
-/* Authentication retry times */
-#define HDCP_INFINITE_REAUTH 0x100
-
-/* HDCP Regs */
-#define HDCP_CTRL1 0x52
- #define m_AUTH_START (1 << 7)
- #define m_BKSV_VALID (1 << 6)
- #define m_BKSV_INVALID (1 << 5)
- #define m_ENCRYPT_ENABLE (1 << 4)
- #define m_AUTH_STOP (1 << 3)
- #define m_ADVANED_ENABLE (1 << 2)
- #define m_HDMI_DVI (1 << 1)
- #define m_HDCP_RESET (1 << 0)
-
- #define v_AUTH_START(n) (n << 7)
- #define v_BKSV_VALID(n) (n << 6)
- #define v_BKSV_INVALID(n) (n << 5)
- #define v_ENCRYPT_ENABLE(n) (n << 4)
- #define v_AUTH_STOP(n) (n << 3)
- #define v_ADVANED_ENABLE(n) (n << 2)
- #define v_HDMI_DVI(n) (n << 1)
- #define v_HDCP_RESET(n) (n << 0)
-
-#define HDCP_CTRL2 0x53
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_ENABLE_PJ_CHECK (1 << 5)
- #define m_DISABLE_DEVICE_NUMBER_CHECK (1 << 4)
- #define m_DELAY_RI_1_CLK (1 << 3)
- #define m_USE_PRESET_AN (1 << 2)
- #define m_KEY_COMBINATION (3 << 0)
-
- #define v_DISABLE_127_CHECK(n) (n << 7)
- #define v_SKIP_BKSV_CHECK(n) (n << 6)
- #define v_ENABLE_PJ_CHECK(n) (n << 5)
- #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
- #define v_DELAY_RI_1_CLK(n) (n << 3)
- #define v_USE_PRESET_AN(n) (n << 2)
- #define v_KEY_COMBINATION(n) (n << 0)
-
-#define HDCP_KEY_STATUS 0x54
- #define m_KEY_READY (1 << 0)
-
-#define HDCP_CTRL_SOFT 0x57
- #define m_DISABLE_127_CHECK (1 << 7)
- #define m_SKIP_BKSV_CHECK (1 << 6)
- #define m_NOT_AUTHENTICATED (1 << 5)
- #define m_ENCRYPTED (1 << 4)
- #define m_ADVANCED_CIPHER (1 << 3)
-
-#define HDCP_BCAPS_RX 0x58
-#define HDCP_TIMER_100MS 0x63
-#define HDCP_TIMER_5S 0x64
-#define HDCP_ERROR 0x65
- #define m_DDC_NO_ACK (1 << 3)
- #define m_PJ_MISMACH (1 << 2)
- #define m_RI_MISMACH (1 << 1)
- #define m_BKSV_WRONG (1 << 0)
-
-#define HDCP_KSV_BYTE0 0x66
-#define HDCP_KSV_BYTE1 0x67
-#define HDCP_KSV_BYTE2 0x68
-#define HDCP_KSV_BYTE3 0x69
-#define HDCP_KSV_BYTE4 0x6a
-
-#define HDCP_AN_SEED 0x6c
-
-#define HDCP_BCAPS_TX 0x80
-#define HDCP_BSTATE_0 0x81
-#define HDCP_BSTATE_1 0x82
-
-#define HDCP_KEY_FIFO 0x98
-
-#define HDCP_INT_MASK1 0xc2
-#define HDCP_INT_STATUS1 0xc3
- #define m_INT_HDCP_ERR (1 << 7)
- #define m_INT_BKSV_READY (1 << 6)
- #define m_INT_BKSV_UPDATE (1 << 5)
- #define m_INT_AUTH_SUCCESS (1 << 4)
- #define m_INT_AUTH_READY (1 << 3)
-
-#define HDCP_INT_MASK2 0xc4
-#define HDCP_INT_STATUS2 0xc5
- #define m_INT_SOFT_MODE_READY (1 << 7)
- #define m_INT_AUTH_M0_REDAY (1 << 6)
- #define m_INT_1st_FRAME_ARRIVE (1 << 5)
- #define m_INT_AN_READY (1 << 4)
- #define m_INT_ENCRYPTED (1 << 2)
- #define m_INT_NOT_ENCRYPTED_AVMUTE (1 << 1)
- #define m_INT_NOT_ENCRYPTED_AVUNMUTE (1 << 0)
-
-enum hdcp_states {
- HDCP_DISABLED,
- HDCP_ENABLE_PENDING,
- HDCP_AUTHENTICATION_START,
- HDCP_WAIT_KSV_LIST,
- HDCP_LINK_INTEGRITY_CHECK,
-};
-
-enum hdmi_states {
- HDMI_STOPPED,
- HDMI_STARTED
-};
-
-#define HDCP_PRIVATE_KEY_SIZE 280
-#define HDCP_KEY_SHA_SIZE 20
-
-struct hdcp_keys{
- u8 KSV[8];
- u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
- u8 sha1[HDCP_KEY_SHA_SIZE];
-};
-
-struct hdcp_delayed_work {
- struct delayed_work work;
- int event;
-};
-
-struct hdcp {
- int enable;
- int retry_times;
- struct hdcp_keys *keys;
- int invalidkey;
- char *invalidkeys;
- struct mutex lock;
- struct completion complete;
- struct workqueue_struct *workqueue;
-
- enum hdmi_states hdmi_state;
- enum hdcp_states hdcp_state;
-
- struct delayed_work *pending_start;
- struct delayed_work *pending_wq_event;
- int retry_cnt;
-};
-
-extern struct hdcp *hdcp;
-
-#ifdef HDCP_DEBUG
-#define DBG(format, ...) \
- printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-extern void rk616_hdcp_disable(void);
-extern int rk616_hdcp_start_authentication(void);
-extern int rk616_hdcp_check_bksv(void);
-extern int rk616_hdcp_load_key2mem(struct hdcp_keys *key);
-extern void rk616_hdcp_interrupt(char *status1, char *status2);
-#endif /* __rk616_HDCP_H__ */
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/uaccess.h>
-
-#include <linux/of_gpio.h>
-#include <linux/rk_fb.h>
-
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#endif
-
-#include "rk616_hdmi.h"
-#include "rk616_hdmi_hw.h"
-
-static struct rk_hdmi_device *hdmi_dev;
-
-#if defined(CONFIG_DEBUG_FS)
-static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
-{
- int i = 0;
- u32 val = 0;
-
- seq_puts(s, "\n>>>rk616_ctl reg");
- for (i = 0; i < 16; i++)
- seq_printf(s, " %2x", i);
-
- seq_puts(s,
- "\n-----------------------------------------------------------------");
-
- for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
- hdmi_readl(hdmi_dev, i, &val);
- if (i % 16 == 0)
- seq_printf(s, "\n>>>rk616_ctl %2x:", i);
- seq_printf(s, " %02x", val);
-
- }
- seq_puts(s,
- "\n-----------------------------------------------------------------\n");
-
- return 0;
-}
-
-static ssize_t rk616_hdmi_reg_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- u32 reg;
- u32 val;
- char kbuf[25];
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (copy_from_user(kbuf, buf, count))
- return -EFAULT;
- sscanf(kbuf, "%x%x", ®, &val);
- if ((reg < 0) || (reg > 0xed)) {
- dev_info(hdmi_drv->dev, "it is no hdmi reg\n");
- return count;
- }
- dev_info(hdmi_drv->dev, "/**********rk616 reg config******/");
- dev_info(hdmi_drv->dev, "\n reg=%x val=%x\n", reg, val);
- hdmi_writel(hdmi_dev, reg, val);
-
- return count;
-}
-
-static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
-{
- struct mfd_rk616 *rk616_drv = inode->i_private;
-
- return single_open(file, rk616_hdmi_reg_show, rk616_drv);
-}
-
-static const struct file_operations rk616_hdmi_reg_fops = {
- .owner = THIS_MODULE,
- .open = rk616_hdmi_reg_open,
- .read = seq_read,
- .write = rk616_hdmi_reg_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
-static int rk616_hdmi_clk_enable(struct rk_hdmi_device *hdmi_dev)
-{
- if (!hdmi_dev->clk_on) {
- clk_prepare_enable(hdmi_dev->hclk);
- spin_lock(&hdmi_dev->reg_lock);
- hdmi_dev->clk_on = 1;
- spin_unlock(&hdmi_dev->reg_lock);
- }
-
- return 0;
-}
-
-static int rk616_hdmi_clk_disable(struct rk_hdmi_device *hdmi_dev)
-{
- if (!hdmi_dev->clk_on) {
- spin_lock(&hdmi_dev->reg_lock);
- hdmi_dev->clk_on = 0;
- spin_unlock(&hdmi_dev->reg_lock);
- clk_disable_unprepare(hdmi_dev->hclk);
- }
-
- return 0;
-}
-
-#endif
-
-int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void))
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if (hdmi_drv == NULL)
- return HDMI_ERROR_FALSE;
-
- hdmi_drv->hdcp_cb = hdcp_cb;
- hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
- hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
- hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
-
- return HDMI_ERROR_SUCESS;
-}
-
-static void rk616_hdmi_early_suspend(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi enter early suspend pwr %d state %d\n",
- hdmi_drv->pwr_mode, hdmi_drv->state);
-
- flush_delayed_work(&hdmi_drv->delay_work);
- mutex_lock(&hdmi_drv->enable_mutex);
- hdmi_drv->suspend = 1;
- if (!hdmi_drv->enable) {
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
- }
-
- if (hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
-
- mutex_unlock(&hdmi_drv->enable_mutex);
- hdmi_drv->command = HDMI_CONFIG_ENABLE;
- init_completion(&hdmi_drv->complete);
- hdmi_drv->wait = 1;
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, 0);
- wait_for_completion_interruptible_timeout(&hdmi_drv->complete,
- msecs_to_jiffies(5000));
- flush_delayed_work(&hdmi_drv->delay_work);
-
-}
-
-static void rk616_hdmi_early_resume(void)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- hdmi_dbg(hdmi_drv->dev, "hdmi exit early resume\n");
-
- mutex_lock(&hdmi_drv->enable_mutex);
-
- hdmi_drv->suspend = 0;
- rk616_hdmi_initial(hdmi_drv);
- if (hdmi_drv->enable && hdmi_drv->irq) {
- enable_irq(hdmi_drv->irq);
- rk616_hdmi_work(hdmi_drv);
- }
- if (rk616_drv && !gpio_is_valid(rk616_drv->pdata->hdmi_irq))
- queue_delayed_work(hdmi_drv->workqueue,
- &hdmi_dev->rk616_delay_work,
- msecs_to_jiffies(100));
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(10));
- mutex_unlock(&hdmi_drv->enable_mutex);
-}
-
-static int rk616_hdmi_fb_event_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- struct fb_event *event = data;
- int blank_mode = *((int *)event->data);
-
- if (action == FB_EARLY_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- break;
- default:
- rk616_hdmi_early_suspend();
- break;
- }
- } else if (action == FB_EVENT_BLANK) {
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- rk616_hdmi_early_resume();
- break;
- default:
- break;
- }
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block rk616_hdmi_fb_notifier = {
- .notifier_call = rk616_hdmi_fb_event_notify,
-};
-
-
-static void rk616_delay_work_func(struct work_struct *work)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- if (hdmi_drv->suspend == 0) {
- if (hdmi_drv->enable == 1)
- rk616_hdmi_work(hdmi_drv);
-
- if (rk616_drv && !gpio_is_valid(rk616_drv->pdata->hdmi_irq))
- queue_delayed_work(hdmi_drv->workqueue,
- &hdmi_dev->rk616_delay_work,
- msecs_to_jiffies(100));
- }
-}
-
-static void __maybe_unused rk616_irq_work_func(struct work_struct *work)
-{
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
-
- if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1))
- rk616_hdmi_work(hdmi_drv);
-
- dev_info(hdmi_drv->dev, "func: %s, enable_irq\n", __func__);
- enable_irq(hdmi_drv->irq);
-}
-static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
-{
- struct work_struct *rk616_irq_work_struct;
- struct hdmi *hdmi_drv = &hdmi_dev->driver;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- if (rk616_drv) {
- rk616_irq_work_struct = dev_id;
- disable_irq_nosync(hdmi_drv->irq);
- queue_work(hdmi_drv->workqueue, rk616_irq_work_struct);
- } else {
- /* 3028a/3036 hdmi */
- if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1)) {
- hdmi_dbg(hdmi_drv->dev,
- "line = %d, rk616_hdmi_irq irq triggered.\n",
- __LINE__);
- rk616_hdmi_work(hdmi_drv);
- }
- }
- return IRQ_HANDLED;
-}
-
-static int rk616_hdmi_drv_init(struct hdmi *hdmi_drv)
-{
- int ret = 0;
- int lcdc_id = 0;
- struct rk_screen screen;
-
- rk_fb_get_prmry_screen(&screen);
-
- /* hdmi is extend as default,TODO modify if hdmi is primary */
- lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;
- /* lcdc source select */
- /* wait to modify!!
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
- grf_writel(HDMI_SEL_LCDC(lcdc_id), RK3036_GRF_SOC_CON6);
-#endif
- */
- lcdc_id = 0;
- if (lcdc_id == 0)
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
- else
- hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
-
- if (IS_ERR(hdmi_drv->lcdc)) {
- dev_err(hdmi_drv->dev,
- "can not connect to video source lcdc\n");
- ret = -ENXIO;
- return ret;
- }
-
- hdmi_drv->xscale = 100;
- hdmi_drv->yscale = 100;
-
- spin_lock_init(&hdmi_drv->irq_lock);
- mutex_init(&hdmi_drv->enable_mutex);
- hdmi_sys_init(hdmi_drv);
- ret = rk616_hdmi_initial(hdmi_drv);
-
- return ret;
-}
-
-#if defined(CONFIG_OF)
-static const struct of_device_id rk616_hdmi_of_match[] = {
- {.compatible = "rockchip,rk616-hdmi",},
- {.compatible = "rockchip,rk3036-hdmi",},
- {}
-};
-
-MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
-#endif
-
-static int rk616_hdmi_probe(struct platform_device *pdev)
-{
- int ret;
- //struct rk_hdmi_device *hdmi_dev;
- struct hdmi *hdmi_drv;
- struct resource __maybe_unused *mem;
- struct resource __maybe_unused *res;
-
- hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct rk_hdmi_device),
- GFP_KERNEL);
- if (!hdmi_dev) {
- dev_err(&pdev->dev, ">>rk616_hdmi kmalloc fail!");
- return -ENOMEM;
- }
-
- hdmi_drv = &hdmi_dev->driver;
- hdmi_drv->dev = &pdev->dev;
- platform_set_drvdata(pdev, hdmi_dev);
- spin_lock_init(&hdmi_dev->reg_lock);
-
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
- hdmi_dev->rk616_drv = NULL;
-#else
- hdmi_dev->rk616_drv = dev_get_drvdata(pdev->dev.parent);
- if (!(hdmi_dev->rk616_drv)) {
- dev_err(hdmi_drv->dev, "null mfd device rk616!\n");
- goto err0;
- }
-#endif
-
-#ifdef CONFIG_SWITCH
- hdmi_drv->switch_hdmi.name = "hdmi";
- switch_dev_register(&(hdmi_drv->switch_hdmi));
-#endif
- hdmi_register_display_sysfs(hdmi_drv, NULL);
- fb_register_client(&rk616_hdmi_fb_notifier);
-
- hdmi_drv->workqueue = create_singlethread_workqueue("hdmi");
- INIT_DELAYED_WORK(&(hdmi_drv->delay_work), hdmi_work);
- INIT_DELAYED_WORK(&hdmi_dev->rk616_delay_work, rk616_delay_work_func);
-
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
- /* enable clk */
- hdmi_dev->hclk = devm_clk_get(hdmi_drv->dev, "pclk_hdmi");
- if (IS_ERR(hdmi_dev->hclk)) {
- dev_err(hdmi_drv->dev, "Unable to get hdmi hclk\n");
- ret = -ENXIO;
- goto err1;
- }
- rk616_hdmi_clk_enable(hdmi_dev); /* enable clk may move to irq func */
- hdmi_dev->hclk_rate = clk_get_rate(hdmi_dev->hclk);
- /* request and remap iomem */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(hdmi_drv->dev, "Unable to get register resource\n");
- ret = -ENXIO;
- goto err2;
- }
- hdmi_dev->regbase_phy = res->start;
- hdmi_dev->regsize_phy = resource_size(res);
- hdmi_dev->regbase = devm_ioremap_resource(hdmi_drv->dev, res);
- if (IS_ERR(hdmi_dev->regbase)) {
- ret = PTR_ERR(hdmi_dev->regbase);
- dev_err(hdmi_drv->dev, "cannot ioremap registers,err=%d\n",
- ret);
- goto err2;
- }
- if (rk616_hdmi_drv_init(hdmi_drv))
- goto err0;
-
- /* get the IRQ */
- hdmi_drv->irq = platform_get_irq(pdev, 0);
- if (hdmi_drv->irq <= 0) {
- dev_err(hdmi_drv->dev, "failed to get hdmi irq resource (%d).\n",
- hdmi_drv->irq);
- hdmi_drv->irq = 0;
- } else {
- /* request the IRQ */
- ret = devm_request_irq(hdmi_drv->dev, hdmi_drv->irq,
- rk616_hdmi_irq, 0,
- dev_name(hdmi_drv->dev), hdmi_drv);
- if (ret) {
- dev_err(hdmi_drv->dev, "hdmi request_irq failed (%d)\n",
- ret);
- goto err2;
- }
- }
-#else
- if (gpio_is_valid(hdmi_dev->rk616_drv->pdata->hdmi_irq)) {
- INIT_WORK(&hdmi_dev->rk616_irq_work_struct,
- rk616_irq_work_func);
- ret = gpio_request(hdmi_dev->rk616_drv->pdata->hdmi_irq,
- "rk616_hdmi_irq");
- if (ret < 0) {
- dev_err(hdmi_drv->dev,
- "request gpio for rk616 hdmi irq fail\n");
- }
- gpio_direction_input(hdmi_dev->rk616_drv->pdata->hdmi_irq);
- hdmi_drv->irq =
- gpio_to_irq(hdmi_dev->rk616_drv->pdata->hdmi_irq);
- if (hdmi_drv->irq <= 0) {
- dev_err(hdmi_drv->dev,
- "failed to get hdmi irq resource (%d).\n",
- hdmi_drv->irq);
- ret = -ENXIO;
- goto err1;
- }
- if (rk616_hdmi_drv_init(hdmi_drv))
- goto err0;
-
- /* request the IRQ */
- ret = devm_request_irq(hdmi_drv->dev, hdmi_drv->irq,
- rk616_hdmi_irq, IRQF_TRIGGER_LOW,
- dev_name(&pdev->dev),
- &hdmi_dev->rk616_irq_work_struct);
- if (ret) {
- dev_err(hdmi_drv->dev, "hdmi request_irq failed (%d)\n",
- ret);
- goto err1;
- }
- } else {
- /* use roll polling method */
- hdmi_drv->irq = 0;
- }
-
-#endif
-
- //rk616_hdmi_work(hdmi_drv);
-
-#if defined(CONFIG_DEBUG_FS)
- if (hdmi_dev->rk616_drv && hdmi_dev->rk616_drv->debugfs_dir) {
- debugfs_create_file("hdmi", S_IRUSR,
- hdmi_dev->rk616_drv->debugfs_dir,
- hdmi_dev->rk616_drv, &rk616_hdmi_reg_fops);
- } else {
- hdmi_dev->debugfs_dir = debugfs_create_dir("rk616", NULL);
- if (IS_ERR(hdmi_dev->debugfs_dir)) {
- dev_err(hdmi_drv->dev,
- "failed to create debugfs dir for rk616!\n");
- } else {
- debugfs_create_file("hdmi", S_IRUSR,
- hdmi_dev->debugfs_dir, hdmi_drv,
- &rk616_hdmi_reg_fops);
- }
- }
-#endif
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk616_delay_work,
- msecs_to_jiffies(0));
- dev_info(hdmi_drv->dev, "rk616 hdmi probe success.\n");
-
- return 0;
-
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
-err2:
- rk616_hdmi_clk_disable(hdmi_dev);
-#endif
-
-err1:
- fb_unregister_client(&rk616_hdmi_fb_notifier);
- hdmi_unregister_display_sysfs(hdmi_drv);
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi_drv->switch_hdmi));
-#endif
-
-err0:
- hdmi_dbg(hdmi_drv->dev, "rk616 hdmi probe error.\n");
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- return ret;
-}
-
-static int rk616_hdmi_remove(struct platform_device *pdev)
-{
- struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev) {
- hdmi_drv = &hdmi_dev->driver;
- mutex_lock(&hdmi_drv->enable_mutex);
- if (!hdmi_drv->suspend && hdmi_drv->enable && hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- if (hdmi_drv->irq)
- free_irq(hdmi_drv->irq, NULL);
-
- flush_workqueue(hdmi_drv->workqueue);
- destroy_workqueue(hdmi_drv->workqueue);
-#ifdef CONFIG_SWITCH
- switch_dev_unregister(&(hdmi_drv->switch_hdmi));
-#endif
- hdmi_unregister_display_sysfs(hdmi_drv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi_drv->early_suspend);
-#endif
- fb_destroy_modelist(&hdmi_drv->edid.modelist);
- if (hdmi_drv->edid.audio)
- kfree(hdmi_drv->edid.audio);
- if (hdmi_drv->edid.specs) {
- if (hdmi_drv->edid.specs->modedb)
- kfree(hdmi_drv->edid.specs->modedb);
- kfree(hdmi_drv->edid.specs);
- }
-
- hdmi_dbg(hdmi_drv->dev, "rk616 hdmi removed.\n");
- kfree(hdmi_dev);
- hdmi_dev = NULL;
- }
-
- return 0;
-}
-
-static void rk616_hdmi_shutdown(struct platform_device *pdev)
-{
- struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
- struct hdmi *hdmi_drv = NULL;
-
- if (hdmi_dev) {
- hdmi_drv = &hdmi_dev->driver;
-#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&hdmi_drv->early_suspend);
-#endif
- flush_delayed_work(&hdmi_drv->delay_work);
- mutex_lock(&hdmi_drv->enable_mutex);
- hdmi_drv->suspend = 1;
- if (!hdmi_drv->enable) {
- mutex_unlock(&hdmi_drv->enable_mutex);
- return;
- }
- if (hdmi_drv->irq)
- disable_irq(hdmi_drv->irq);
- mutex_unlock(&hdmi_drv->enable_mutex);
- }
- hdmi_dbg(hdmi_drv->dev, "rk616 hdmi shut down.\n");
-}
-
-
-static struct platform_driver rk616_hdmi_driver = {
- .probe = rk616_hdmi_probe,
- .remove = rk616_hdmi_remove,
- .driver = {
- .name = "rk616-hdmi",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(rk616_hdmi_of_match),
- },
- .shutdown = rk616_hdmi_shutdown,
-};
-
-static int __init rk616_hdmi_init(void)
-{
- return platform_driver_register(&rk616_hdmi_driver);
-}
-
-static void __exit rk616_hdmi_exit(void)
-{
- platform_driver_unregister(&rk616_hdmi_driver);
-}
-
-late_initcall(rk616_hdmi_init);
-module_exit(rk616_hdmi_exit);
+++ /dev/null
-#ifndef __RK616_HDMI_H__
-#define __RK616_HDMI_H__
-
-#include "../../rk_hdmi.h"
-#include <linux/mfd/rk616.h>
-
-enum {
- INPUT_IIS,
- INPUT_SPDIF
-};
-
-#if defined(CONFIG_SND_RK_SOC_HDMI_SPDIF)
-#define HDMI_CODEC_SOURCE_SELECT INPUT_SPDIF
-#else
-#define HDMI_CODEC_SOURCE_SELECT INPUT_IIS
-#endif
-
-extern void rk616_hdmi_control_output(struct hdmi *hdmi, int enable);
-extern int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
- void (*hdcp_irq_cb)(int status),
- int (*hdcp_power_on_cb)(void),
- void (*hdcp_power_off_cb)(void));
-
-struct rk_hdmi_device {
- int clk_on;
- spinlock_t reg_lock;
- struct hdmi driver;
- void __iomem *regbase;
- int regbase_phy;
- int regsize_phy;
- struct clk *pd;
- struct clk *hclk; /* HDMI AHP clk */
- struct clk *pclk; /* HDMI APB clk */
- struct delayed_work rk616_delay_work;
- struct work_struct rk616_irq_work_struct;
- struct mfd_rk616 *rk616_drv;
- struct dentry *debugfs_dir;
- unsigned int hclk_rate;
-};
-
-#endif /* __RK616_HDMI_H__ */
+++ /dev/null
-#include <linux/delay.h>
-#include "rk616_hdmi.h"
-#include "rk616_hdmi_hw.h"
-#include "rk616_hdcp.h"
-
-#define HDCPWrReg HDMIWrReg
-#define HDCPRdReg HDMIRdReg
-#define HDCPMskReg(temp,addr,Msk,val) do{ \
- HDMIRdReg(addr,&temp); \
- HDMIWrReg(addr, ((val)&(Msk))|(temp&(~Msk))); \
- }while(0)
-
-void rk616_hdcp_disable(void)
-{
- char temp;
-
- // Diable HDCP Interrupt
- HDCPWrReg(HDCP_INT_MASK1, 0x00);
- // Stop and Reset HDCP
- HDCPMskReg(temp, HDCP_CTRL1, m_ENCRYPT_ENABLE | m_AUTH_STOP | m_HDCP_RESET,
- v_ENCRYPT_ENABLE(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1) );
-}
-
-int rk616_hdcp_load_key2mem(struct hdcp_keys *key)
-{
- int i;
- DBG("HDCP: rk616_hdcp_load_key2mem start");
- // Write 40 private key
- for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
- HDCPWrReg(HDCP_KEY_FIFO, key->DeviceKey[i]);
-
- // Write 1st aksv
- for(i = 0; i < 5; i++)
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);
-
- // Write 2nd aksv
- for(i = 0; i < 5; i++)
- HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);
- DBG("HDCP: rk616_hdcp_load_key2mem end");
- return HDCP_OK;
-}
-
-int rk616_hdcp_start_authentication(void)
-{
- char temp;
- int retry = 0;
-
- if(hdcp->keys == NULL) {
- printk(KERN_ERR "HDCP: key is not loaded\n");
- return HDCP_KEY_ERR;
- }
-
- // Select TMDS CLK to configure regs
- HDCPMskReg(temp, SYS_CTRL, m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);
-
- HDCPRdReg(HDCP_KEY_STATUS,&temp);
- while( ( temp & m_KEY_READY) == 0 ) {
- if(retry > 10) {
- printk(KERN_ERR "HDCP: loaded key error\n");
- return HDCP_KEY_ERR;
- }
- rk616_hdcp_load_key2mem(hdcp->keys);
- msleep(1);
- HDCPRdReg(HDCP_KEY_STATUS,&temp);
- }
-
- // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)
- DBG("TMDS frequency %d", hdmi->tmdsclk);
- retry = hdmi->tmdsclk/(HDCP_DDC_CLK*4);
- HDCPWrReg(DDC_CLK_L, retry & 0xFF);
- HDCPWrReg(DDC_CLK_H, (retry >> 8) & 0xFF);
-
- HDCPWrReg(HDCP_CTRL2, 0x00);
-
- //Enable interrupt
- HDCPWrReg(HDCP_INT_MASK1, m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE | m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);
-// HDCPWrReg(HDCP_INT_MASK2, 0xFF);
- //Start authentication
- HDCPMskReg(temp, HDCP_CTRL1, m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE, v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) | v_ADVANED_ENABLE(0));
-
- return HDCP_OK;
-}
-
-int rk616_hdcp_check_bksv(void)
-{
- int i, j;
- char temp = 0, bksv[5];
- char *invalidkey;
-
- for(i = 0; i < 5; i++) {
- HDCPRdReg(HDCP_KSV_BYTE0 + (4 - i),&temp);
- bksv[i] = temp & 0xFF;
- }
- DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
-
- temp = 0;
- for (i = 0; i < 5; i++)
- {
- for (j = 0; j < 8; j++)
- {
- if (bksv[i] & 0x01)
- {
- temp++;
- }
- bksv[i] >>= 1;
- }
- }
- if (temp != 20)
- return HDCP_KSV_ERR;
-
- for(i = 0; i < hdcp->invalidkey; i++)
- {
- invalidkey = hdcp->invalidkeys + i *5;
- if(memcmp(bksv, invalidkey, 5) == 0) {
- printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE, v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));
- return HDCP_KSV_ERR;
- }
- }
- HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE, v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));
- return HDCP_OK;
-}
-
-void rk616_hdcp_interrupt(char *status1, char *status2)
-{
- char interrupt1 = 0;
- char interrupt2 = 0;
- char temp =0;
- HDCPRdReg(HDCP_INT_STATUS1,&interrupt1);
- HDCPRdReg(HDCP_INT_STATUS2,&interrupt2);
- if(interrupt1) {
- HDCPWrReg(HDCP_INT_STATUS1, interrupt1);
- if(interrupt1 & m_INT_HDCP_ERR){
- HDCPRdReg(HDCP_ERROR,&temp);
- printk(KERN_INFO "HDCP: Error 0x%02x\n", temp);
- }
- }
- if(interrupt2)
- HDCPWrReg(HDCP_INT_STATUS2, interrupt2);
-
- *status1 = interrupt1;
- *status2 = interrupt2;
-}
+++ /dev/null
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/of_irq.h>
-#include "rk616_hdmi.h"
-#include "rk616_hdmi_hw.h"
-
-#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
-
-static int rk616_set_polarity(struct mfd_rk616 *rk616_drv, int vic)
-{
- u32 val;
- int ret;
- u32 hdmi_polarity_mask = (3 << 14);
-
- switch (vic) {
-
- case HDMI_1920x1080p_60Hz:
- case HDMI_1920x1080p_50Hz:
- case HDMI_1920x1080i_60Hz:
- case HDMI_1920x1080i_50Hz:
- case HDMI_1280x720p_60Hz:
- case HDMI_1280x720p_50Hz:
- val = 0xc000;
- ret = rk616_drv->write_dev_bits(rk616_drv, CRU_CFGMISC_CON,
- hdmi_polarity_mask, &val);
- break;
-
- case HDMI_720x576p_50Hz_4_3:
- case HDMI_720x576p_50Hz_16_9:
- case HDMI_720x480p_60Hz_4_3:
- case HDMI_720x480p_60Hz_16_9:
- val = 0x0;
- ret = rk616_drv->write_dev_bits(rk616_drv, CRU_CFGMISC_CON,
- hdmi_polarity_mask, &val);
- break;
- default:
- val = 0x0;
- ret = rk616_drv->write_dev_bits(rk616_drv, CRU_CFGMISC_CON,
- hdmi_polarity_mask, &val);
- break;
- }
- return ret;
-}
-
-static int rk616_hdmi_set_vif(struct hdmi *hdmi_drv, struct rk_screen *screen,
- bool connect)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- if (connect)
- rk616_set_polarity(rk616_drv, hdmi_drv->vic);
-
- rk616_set_vif(rk616_drv, screen, connect);
- return 0;
-}
-
-static int rk616_hdmi_init_pol_set(struct mfd_rk616 *rk616_drv, int pol)
-{
- u32 val;
- int ret;
- int int_pol_mask = (1 << 5);
-
- if (pol)
- val = 0x0;
- else
- val = 0x20;
- ret = rk616_drv->write_dev_bits(rk616_drv, CRU_CFGMISC_CON,
- int_pol_mask, &val);
-
- return 0;
-}
-#endif
-
-static int __maybe_unused rk616_hdmi_show_reg(struct hdmi *hdmi_drv)
-{
- int i = 0;
- u32 val = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- printk("\n>>>rk616_ctl reg");
- for (i = 0; i < 16; i++)
- printk(" %2x", i);
-
- printk("\n-----------------------------------------------------------------");
-
- for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
- hdmi_readl(hdmi_dev, i, &val);
- if (i % 16 == 0)
- printk("\n>>>rk616_ctl %2x:", i);
- printk(" %02x", val);
- }
- printk("\n-----------------------------------------------------------------\n");
-
- return 0;
-}
-
-static inline void delay100us(void)
-{
- msleep(1);
-}
-
-static void rk616_hdmi_av_mute(struct hdmi *hdmi_drv, bool enable)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
-}
-
-static void rk616_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (enable)
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
- else
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
-}
-
-static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
-{
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (hdmi_drv->pwr_mode == mode)
- return;
-
- hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
- hdmi_drv->pwr_mode, mode);
-
- switch (mode) {
- case NORMAL:
- hdmi_dbg(hdmi_drv->dev,
- "%s change pwr_mode NORMAL pwr_mode = %d, mode = %d\n",
- __func__, hdmi_drv->pwr_mode, mode);
- rk616_hdmi_sys_power(hdmi_drv, false);
- if (!(hdmi_drv->set_vif)
- && (hdmi_drv->vic == HDMI_1920x1080p_60Hz
- || hdmi_drv->vic == HDMI_1920x1080p_50Hz)) {
- /* 3026 and 1080p */
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0xcc);
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x4f);
- } else {
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0x99);
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x0f);
- }
-#ifdef SOC_CONFIG_RK3036
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x15);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x14);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x10);
-#else
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2d);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2c);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x28);
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x20);
-#endif
- hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
- hdmi_writel(hdmi_dev, 0xce, 0x00);
- hdmi_writel(hdmi_dev, 0xce, 0x01);
- rk616_hdmi_av_mute(hdmi_drv, 1);
- rk616_hdmi_sys_power(hdmi_drv, true);
- break;
- case LOWER_PWR:
- hdmi_dbg(hdmi_drv->dev,
- "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
- __func__, hdmi_drv->pwr_mode, mode);
- rk616_hdmi_av_mute(hdmi_drv, 0);
- rk616_hdmi_sys_power(hdmi_drv, false);
- hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
- hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
- hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
-#ifdef SOC_CONFIG_RK3036
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x17);
-#else
- hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2f);
-#endif
- break;
- default:
- hdmi_dbg(hdmi_drv->dev, "unkown rk616 hdmi pwr mode %d\n",
- mode);
- }
-
- hdmi_drv->pwr_mode = mode;
-}
-
-int rk616_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
-{
- int value = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_dbg(hdmi_drv->dev, "[%s] value %02x\n", __func__, value);
- hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
- value &= m_HOTPLUG;
- if (value == m_HOTPLUG)
- return HDMI_HPD_ACTIVED;
- else if (value)
- return HDMI_HPD_INSERT;
- else
- return HDMI_HPD_REMOVED;
-}
-int rk616_hdmi_insert(struct hdmi *hdmi_drv)
-{
- rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
- return 0;
-}
-
-
-int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
-{
- u32 c = 0;
- u8 segment = 0;
- u8 offset = 0;
- int ret = -1;
- int i, j;
- int ddc_bus_freq;
- int trytime;
- int checksum = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- if (block % 2)
- offset = HDMI_EDID_BLOCK_SIZE;
-
- if (block / 2)
- segment = 1;
-#ifdef SOC_CONFIG_RK3036
- ddc_bus_freq = (hdmi_dev->hclk_rate>> 2) / HDMI_SCL_RATE;
-#else
- ddc_bus_freq = (HDMI_SYS_FREG_CLK >> 2) / HDMI_SCL_RATE;
-#endif
- hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
- hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-
- hdmi_dbg(hdmi_drv->dev,
- "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
- (int)segment, (int)block, (int)offset);
- disable_irq(hdmi_drv->irq);
-
- /* Enable edid interrupt */
-#ifdef SOC_CONFIG_RK3036
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
-#else
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1,
- m_INT_HOTPLUG | m_INT_EDID_READY);
-#endif
-
- for (trytime = 0; trytime < 10; trytime++) {
- checksum = 0;
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
-
- /* Set edid fifo first addr */
- hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
-
- /* Set edid word address 0x00/0x80 */
- hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
-
- /* Set edid segment pointer */
- hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
-
- for (i = 0; i < 10; i++) {
- /* Wait edid interrupt */
- msleep(10);
- c = 0x00;
- hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
-
- if (c & m_INT_EDID_READY)
- break;
- }
-
- if (c & m_INT_EDID_READY) {
- for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
- c = 0;
- hdmi_readl(hdmi_dev, 0x50, &c);
- buf[j] = c;
- checksum += c;
-#ifdef HDMI_DEBUG
- if (j % 16 == 0)
- printk("\n>>>0x%02x: ",j);
-
- printk("0x%02x ", c);
-#endif
- }
-
- /* clear EDID interrupt reg */
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
- m_INT_EDID_READY);
-
- if ((checksum & 0xff) == 0) {
- ret = 0;
- hdmi_dbg(hdmi_drv->dev,
- "[%s] edid read sucess\n", __func__);
- break;
- }
- }
- }
- //close edid irq
-#ifdef SOC_CONFIG_RK3036
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
-#else
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
-#endif
- enable_irq(hdmi_drv->irq);
-
- return ret;
-}
-
-static void rk616_hdmi_config_avi(struct hdmi *hdmi_drv,
- unsigned char vic, unsigned char output_color)
-{
- int i;
- char info[SIZE_AVI_INFOFRAME];
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- memset(info, 0, SIZE_AVI_INFOFRAME);
- hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
- info[0] = 0x82;
- info[1] = 0x02;
- info[2] = 0x0D;
- info[3] = info[0] + info[1] + info[2];
- info[4] = (AVI_COLOR_MODE_RGB << 5);
- info[5] =
- (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA <<
- 4) |
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
- info[6] = 0;
- info[7] = vic;
- info[8] = 0;
-
- /* Calculate AVI InfoFrame ChecKsum */
- for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
- hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk616_hdmi_config_video(struct hdmi *hdmi_drv,
- struct hdmi_video_para *vpara)
-{
- int value;
- struct fb_videomode *mode;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_dbg(hdmi_drv->dev, "[%s]\n", __func__);
-
- if (vpara == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] input parameter error\n",
- __func__);
- return -1;
- }
-
- /* Output RGB as default */
- vpara->output_color = VIDEO_OUTPUT_RGB444;
- if (hdmi_drv->pwr_mode == LOWER_PWR)
- rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-
- /* Disable video and audio output */
- hdmi_writel(hdmi_dev, AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
-
- /* Input video mode is SDR RGB24bit, Data enable signal from external */
- hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
- v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
- v_DE_EXTERNAL);
- hdmi_writel(hdmi_dev, VIDEO_CONTRL2,
- v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
- v_VIDEO_OUTPUT_FORMAT(vpara->output_color & 0xFF));
-
- /* Set HDMI Mode */
- hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
-
- /* Enable or disalbe color space convert */
- if (vpara->input_color != vpara->output_color)
- value = v_SOF_DISABLE | v_CSC_ENABLE;
- else
- value = v_SOF_DISABLE;
- hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
-
- /* Set ext video timing */
-#if 1
- hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
- mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
- if (mode == NULL) {
- hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
- vpara->vic);
- return -ENOENT;
- }
- hdmi_drv->tmdsclk = mode->pixclock;
-#else
- value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
- if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
- value |= v_HSYNC_POLARITY(1);
- if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
- value |= v_VSYNC_POLARITY(1);
- hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
-
- value = mode->left_margin + mode->xres + mode->right_margin +
- mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->right_margin + mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
-
- value = mode->left_margin + mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
-
- value = mode->hsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->yres + mode->lower_margin +
- mode->vsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
- hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
-
- value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
-
- if (vpara->vic == HDMI_720x480p_60Hz_4_3
- || vpara->vic == HDMI_720x480p_60Hz_16_9)
- value = 42;
- else
- value = mode->upper_margin + mode->vsync_len;
-
- hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
-
- value = mode->vsync_len;
- hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
-#endif
-
- if (vpara->output_mode == OUTPUT_HDMI) {
- rk616_hdmi_config_avi(hdmi_drv, vpara->vic,
- vpara->output_color);
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __func__);
- } else {
- hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __func__);
- }
-
- if (hdmi_drv->set_vif) {
- hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x0f);
- hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x96);
- } else { /* rk3028a */
- hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
- hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
- hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
- }
- return 0;
-}
-
-static void rk616_hdmi_config_aai(struct hdmi *hdmi_drv)
-{
- int i;
- char info[SIZE_AUDIO_INFOFRAME];
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- memset(info, 0, SIZE_AUDIO_INFOFRAME);
-
- info[0] = 0x84;
- info[1] = 0x01;
- info[2] = 0x0A;
-
- info[3] = info[0] + info[1] + info[2];
- for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
- info[3] += info[i];
-
- info[3] = 0x100 - info[3];
-
- hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
- for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
- hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
-}
-
-static int rk616_hdmi_config_audio(struct hdmi *hdmi_drv,
- struct hdmi_audio *audio)
-{
- int rate, N, channel, mclk_fs;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (audio->channel < 3)
- channel = I2S_CHANNEL_1_2;
- else if (audio->channel < 5)
- channel = I2S_CHANNEL_3_4;
- else if (audio->channel < 7)
- channel = I2S_CHANNEL_5_6;
- else
- channel = I2S_CHANNEL_7_8;
-
- switch (audio->rate) {
- case HDMI_AUDIO_FS_32000:
- rate = AUDIO_32K;
- N = N_32K;
- mclk_fs = MCLK_384FS;
- break;
- case HDMI_AUDIO_FS_44100:
- rate = AUDIO_441K;
- N = N_441K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_48000:
- rate = AUDIO_48K;
- N = N_48K;
- mclk_fs = MCLK_256FS;
- break;
- case HDMI_AUDIO_FS_88200:
- rate = AUDIO_882K;
- N = N_882K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_96000:
- rate = AUDIO_96K;
- N = N_96K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_176400:
- rate = AUDIO_1764K;
- N = N_1764K;
- mclk_fs = MCLK_128FS;
- break;
- case HDMI_AUDIO_FS_192000:
- rate = AUDIO_192K;
- N = N_192K;
- mclk_fs = MCLK_128FS;
- break;
- default:
- dev_err(hdmi_drv->dev, "[%s] not support such sample rate %d\n",
- __func__, audio->rate);
- return -ENOENT;
- }
-
- /* set_audio source I2S */
- if (HDMI_CODEC_SOURCE_SELECT == INPUT_IIS) {
- hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
- hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
- hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
- v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel));
- hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
- /* no swap */
- hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
- } else {
- hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
- /* no swap */
- hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
- }
-
- /* Set N value */
- hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
- hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
- hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
- rk616_hdmi_config_aai(hdmi_drv);
-
- return 0;
-}
-
-void rk616_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
-{
- int mutestatus = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- if (enable) {
- if (hdmi_drv->pwr_mode == LOWER_PWR)
- rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
- hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
- if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
- }
- rk616_hdmi_sys_power(hdmi_drv, true);
- rk616_hdmi_sys_power(hdmi_drv, false);
- rk616_hdmi_sys_power(hdmi_drv, true);
- hdmi_writel(hdmi_dev, 0xce, 0x00);
- delay100us();
- hdmi_writel(hdmi_dev, 0xce, 0x01);
- } else {
- hdmi_writel(hdmi_dev, AV_MUTE,
- v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
- }
-}
-
-int rk616_hdmi_removed(struct hdmi *hdmi_drv)
-{
-
- dev_info(hdmi_drv->dev, "Removed.\n");
- if (hdmi_drv->hdcp_power_off_cb)
- hdmi_drv->hdcp_power_off_cb();
- rk616_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
-
- return HDMI_ERROR_SUCESS;
-}
-
-void rk616_hdmi_work(struct hdmi *hdmi_drv)
-{
- u32 interrupt = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-#ifdef SOC_CONFIG_RK3036
- hdmi_readl(hdmi_dev, HDMI_STATUS,&interrupt);
- if(interrupt){
- hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
- }
- if (interrupt & m_INT_HOTPLUG)
-#else
- hdmi_readl(hdmi_dev, INTERRUPT_STATUS1,&interrupt);
- if(interrupt){
- hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
- }
- if (interrupt & m_HOTPLUG)
-#endif
- {
- if (hdmi_drv->state == HDMI_SLEEP)
- hdmi_drv->state = WAIT_HOTPLUG;
-
- queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
- msecs_to_jiffies(40));
-
- }//plug out?
-
- if (hdmi_drv->hdcp_irq_cb)
- hdmi_drv->hdcp_irq_cb(0);
-}
-
-static void rk616_hdmi_reset(struct hdmi *hdmi_drv)
-{
- u32 val = 0;
- u32 msk = 0;
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
-
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
- delay100us();
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
- delay100us();
- msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
- val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
- hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
-#ifdef SOC_CONFIG_RK3036
- hdmi_readl(hdmi_dev, HDMI_STATUS,&val);//enable hpg
- val |= m_MASK_INT_HOTPLUG;
- //hdmi_writel(hdmi_dev, HDMI_STATUS,val);//do this will lead to clear hpd irq
-#else
- hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
-#endif
- rk616_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR); // hjc delete for audis
- //rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-}
-
-int rk616_hdmi_initial(struct hdmi *hdmi_drv)
-{
- int rc = HDMI_ERROR_SUCESS;
-#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
- struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
- struct rk_hdmi_device,
- driver);
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-#endif
-
- hdmi_drv->pwr_mode = NORMAL;
- hdmi_drv->remove = rk616_hdmi_removed;
- hdmi_drv->control_output = rk616_hdmi_control_output;
- hdmi_drv->config_video = rk616_hdmi_config_video;
- hdmi_drv->config_audio = rk616_hdmi_config_audio;
- hdmi_drv->detect_hotplug = rk616_hdmi_detect_hotplug;
- hdmi_drv->read_edid = rk616_hdmi_read_edid;
- hdmi_drv->insert = rk616_hdmi_insert;
-
-#if defined(CONFIG_ARCH_RK3026)
- rk3028_hdmi_reset_pclk();
- rk616_hdmi_reset(hdmi_drv);
-#elif defined(SOC_CONFIG_RK3036)
- rk3028_hdmi_reset_pclk();
- rk616_hdmi_reset(hdmi_drv);
-#else
- hdmi_drv->set_vif = rk616_hdmi_set_vif;
- rk616_hdmi_reset(hdmi_drv);
- rk616_hdmi_init_pol_set(rk616_drv, 0);
-#endif
-
- if (hdmi_drv->hdcp_power_on_cb)
- rc = hdmi_drv->hdcp_power_on_cb();
-
- return rc;
-}
+++ /dev/null
-#ifndef _RK616_HDMI_HW_H
-#define _RK616_HDMI_HW_H
-
-#define SOC_CONFIG_RK3036
-#include <linux/rockchip/iomap.h>
-#define RK616_HDMI_BASE 0x400
-enum PWR_MODE {
- NORMAL,
- LOWER_PWR,
-};
-enum {
- OUTPUT_DVI = 0,
- OUTPUT_HDMI
-};
-
-#ifdef RK616_USE_MCLK_12M
-#define HDMI_SYS_FREG_CLK 12000000
-#else
-#define HDMI_SYS_FREG_CLK 11289600
-#endif
-
-#define HDMI_SCL_RATE (100*1000)
-#define DDC_BUS_FREQ_L 0x4b
-#define DDC_BUS_FREQ_H 0x4c
-
-#define SYS_CTRL 0x00
-#define m_RST_ANALOG (1 << 6)
-#define v_RST_ANALOG (0 << 6)
-#define v_NOT_RST_ANALOG (1 << 6)
-
-#define m_RST_DIGITAL (1 << 5)
-#define v_RST_DIGITAL (0 << 5)
-#define v_NOT_RST_DIGITAL (1 << 5)
-
-#define m_REG_CLK_INV (1 << 4)
-#define v_REG_CLK_NOT_INV (0 << 4)
-#define v_REG_CLK_INV (1 << 4)
-#define m_VCLK_INV (1 << 3)
-#define v_VCLK_NOT_INV (0 << 3)
-#define v_VCLK_INV (1 << 3)
-#define m_REG_CLK_SOURCE (1 << 2)
-#define v_REG_CLK_SOURCE_TMDS (0 << 2)
-#define v_REG_CLK_SOURCE_SYS (1 << 2)
-#define m_POWER (1 << 1)
-#define v_PWR_ON (0 << 1)
-#define v_PWR_OFF (1 << 1)
-#define m_INT_POL (1 << 0)
-#define v_INT_POL_HIGH 1
-#define v_INT_POL_LOW 0
-
-#define VIDEO_CONTRL1 0x01
-#define m_VIDEO_INPUT_FORMAT (7 << 1)
-#define m_DE_SOURCE (1 << 0)
-enum {
- VIDEO_INPUT_SDR_RGB444 = 0,
- VIDEO_INPUT_DDR_RGB444 = 5,
- VIDEO_INPUT_DDR_YCBCR422 = 6
-};
-#define v_VIDEO_INPUT_FORMAT(n) (n << 1)
-#define v_DE_EXTERNAL 1
-#define v_DE_INTERANL 0
-
-#define VIDEO_CONTRL2 0x02
-#define m_VIDEO_OUTPUT_FORMAT (3 << 6)
-#define m_VIDEO_INPUT_BITS (3 << 4)
-#define v_VIDEO_OUTPUT_FORMAT(n)(n << 6)
-#define v_VIDEO_INPUT_BITS(n) (n << 4)
-enum {
- VIDEO_INPUT_12BITS = 0,
- VIDEO_INPUT_10BITS,
- VIDEO_INPUT_8BITS
-};
-#define VIDEO_CONTRL3 0x04
-#define m_SOF (1 << 3)
-#define m_CSC (1 << 0)
-#define v_SOF_ENABLE (0 << 3)
-#define v_SOF_DISABLE (1 << 3)
-#define v_CSC_ENABLE 1
-#define v_CSC_DISABLE 0
-
-#define AV_MUTE 0x05
-#define m_AVMUTE_CLEAR (1 << 7)
-#define m_AVMUTE_ENABLE (1 << 6)
-#define m_AUDIO_MUTE (1 << 1)
-#define m_VIDEO_BLACK (1 << 0)
-#define v_AUDIO_MUTE(n) (n << 1)
-#define v_VIDEO_MUTE(n) (n << 0)
-
-#define VIDEO_TIMING_CTL 0x08
-#define v_HSYNC_POLARITY(n) (n << 3)
-#define v_VSYNC_POLARITY(n) (n << 2)
-#define v_INETLACE(n) (n << 1)
-#define v_EXTERANL_VIDEO(n) (n << 0)
-
-#define VIDEO_EXT_HTOTAL_L 0x09
-#define VIDEO_EXT_HTOTAL_H 0x0a
-#define VIDEO_EXT_HBLANK_L 0x0b
-#define VIDEO_EXT_HBLANK_H 0x0c
-#define VIDEO_EXT_HDELAY_L 0x0d
-#define VIDEO_EXT_HDELAY_H 0x0e
-#define VIDEO_EXT_HDURATION_L 0x0f
-#define VIDEO_EXT_HDURATION_H 0x10
-#define VIDEO_EXT_VTOTAL_L 0x11
-#define VIDEO_EXT_VTOTAL_H 0x12
-#define VIDEO_EXT_VBLANK 0x13
-#define VIDEO_EXT_VDELAY 0x14
-#define VIDEO_EXT_VDURATION 0x15
-
-#define AUDIO_CTRL1 0x35
-enum {
- CTS_SOURCE_INTERNAL = 0,
- CTS_SOURCE_EXTERNAL
-};
-#define v_CTS_SOURCE(n) (n << 7)
-enum {
- DOWNSAMPLE_DISABLE = 0,
- DOWNSAMPLE_1_2,
- DOWNSAMPLE_1_4
-};
-#define v_DOWN_SAMPLE(n) (n << 5)
-enum {
- AUDIO_SOURCE_IIS = 0,
- AUDIO_SOURCE_SPDIF
-};
-#define v_AUDIO_SOURCE(n) (n << 3)
-#define v_MCLK_ENABLE(n) (n << 2)
-enum {
- MCLK_128FS = 0,
- MCLK_256FS,
- MCLK_384FS,
- MCLK_512FS
-};
-#define v_MCLK_RATIO(n) (n)
-
-#define AUDIO_SAMPLE_RATE 0x37
-enum {
- AUDIO_32K = 0x3,
- AUDIO_441K = 0x0,
- AUDIO_48K = 0x2,
- AUDIO_882K = 0x8,
- AUDIO_96K = 0xa,
- AUDIO_1764K = 0xc,
- AUDIO_192K = 0xe,
-};
-
-#define AUDIO_I2S_MODE 0x38
-enum {
- I2S_CHANNEL_1_2 = 1,
- I2S_CHANNEL_3_4 = 3,
- I2S_CHANNEL_5_6 = 7,
- I2S_CHANNEL_7_8 = 0xf
-};
-#define v_I2S_CHANNEL(n) ((n) << 2)
-enum {
- I2S_STANDARD = 0,
- I2S_LEFT_JUSTIFIED,
- I2S_RIGHT_JUSTIFIED
-};
-#define v_I2S_MODE(n) (n)
-
-#define AUDIO_I2S_MAP 0x39
-#define AUDIO_I2S_SWAPS_SPDIF 0x3a
-#define v_SPIDF_FREQ(n) (n)
-
-#define N_32K 0x1000
-#define N_441K 0x1880
-#define N_882K 0x3100
-#define N_1764K 0x6200
-#define N_48K 0x1800
-#define N_96K 0x3000
-#define N_192K 0x6000
-
-#define AUDIO_N_H 0x3f
-#define AUDIO_N_M 0x40
-#define AUDIO_N_L 0x41
-
-#define AUDIO_CTS_H 0x45
-#define AUDIO_CTS_M 0x46
-#define AUDIO_CTS_L 0x47
-
-#define DDC_CLK_L 0x4b
-#define DDC_CLK_H 0x4c
-
-#define EDID_SEGMENT_POINTER 0x4d
-#define EDID_WORD_ADDR 0x4e
-#define EDID_FIFO_OFFSET 0x4f
-#define EDID_FIFO_ADDR 0x50
-
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX 0x9f
-enum {
- INFOFRAME_AVI = 0x06,
- INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_ADDR 0xa0
-
-#define SIZE_AVI_INFOFRAME 0x11 /* 14 bytes */
-#define SIZE_AUDIO_INFOFRAME 0x0F /* 15 bytes */
-enum {
- AVI_COLOR_MODE_RGB = 0,
- AVI_COLOR_MODE_YCBCR422,
- AVI_COLOR_MODE_YCBCR444
-};
-enum {
- AVI_COLORIMETRY_NO_DATA = 0,
- AVI_COLORIMETRY_SMPTE_170M,
- AVI_COLORIMETRY_ITU709,
- AVI_COLORIMETRY_EXTENDED
-};
-enum {
- AVI_CODED_FRAME_ASPECT_NO_DATA,
- AVI_CODED_FRAME_ASPECT_4_3,
- AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
- ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
- ACTIVE_ASPECT_RATE_4_3,
- ACTIVE_ASPECT_RATE_16_9,
- ACTIVE_ASPECT_RATE_14_9
-};
-
-#define HDCP_CTRL 0x52
-#define m_HDMI_DVI (1 << 1)
-#define v_HDMI_DVI(n) (n << 1)
-
-#define INTERRUPT_MASK1 0xc0
-#define INTERRUPT_STATUS1 0xc1
-#ifndef SOC_CONFIG_RK3036
-#define m_INT_HOTPLUG (1 << 7)
-#endif
-#define m_INT_ACTIVE_VSYNC (1 << 5)
-#define m_INT_EDID_READY (1 << 2)
-
-#define INTERRUPT_MASK2 0xc2
-#define INTERRUPT_STATUS2 0xc3
-#define m_INT_HDCP_ERR (1 << 7)
-#define m_INT_BKSV_FLAG (1 << 6)
-#define m_INT_HDCP_OK (1 << 4)
-
-#define HDMI_STATUS 0xc8
- #define m_HOTPLUG (1 << 7)
- #ifdef SOC_CONFIG_RK3036
- #define m_MASK_INT_HOTPLUG (1 << 5)
- #define m_INT_HOTPLUG (1 << 1)
- #else
- #define m_DDC_SDA (1 << 5)
- #define m_DDC_SDC (1 << 4)
- #endif
-
-
-#define HDMI_COLORBAR 0xc9
-
-#define PHY_SYNC 0xce /* sync phy parameter */
-#define PHY_SYS_CTL 0xe0
-#define m_TMDS_CLK_SOURCE (1 << 5)
-#define v_TMDS_FROM_PLL (0 << 5)
-#define v_TMDS_FROM_GEN (1 << 5)
-#define m_PHASE_CLK (1 << 4)
-#define v_DEFAULT_PHASE (0 << 4)
-#define v_SYNC_PHASE (1 << 4)
-#define m_TMDS_CURRENT_PWR (1 << 3)
-#define v_TURN_ON_CURRENT (0 << 3)
-#define v_CAT_OFF_CURRENT (1 << 3)
-#define m_BANDGAP_PWR (1 << 2)
-#define v_BANDGAP_PWR_UP (0 << 2)
-#define v_BANDGAP_PWR_DOWN (1 << 2)
-#define m_PLL_PWR (1 << 1)
-#define v_PLL_PWR_UP (0 << 1)
-#define v_PLL_PWR_DOWN (1 << 1)
-#define m_TMDS_CHG_PWR (1 << 0)
-#define v_TMDS_CHG_PWR_UP (0 << 0)
-#define v_TMDS_CHG_PWR_DOWN (1 << 0)
-
-#define PHY_CHG_PWR 0xe1
-#define v_CLK_CHG_PWR(n) ((n & 1) << 3)
-#define v_DATA_CHG_PWR(n) ((n & 7) << 0)
-
-#define PHY_DRIVER 0xe2
-#define v_CLK_MAIN_DRIVER(n) (n << 4)
-#define v_DATA_MAIN_DRIVER(n) (n << 0)
-
-#define PHY_PRE_EMPHASIS 0xe3
-#define v_PRE_EMPHASIS(n) ((n & 7) << 4)
-#define v_CLK_PRE_DRIVER(n) ((n & 3) << 2)
-#define v_DATA_PRE_DRIVER(n) ((n & 3) << 0)
-
-#define PHY_FEEDBACK_DIV_RATIO_LOW 0xe7
-#define v_FEEDBACK_DIV_LOW(n) (n & 0xff)
-#define PHY_FEEDBACK_DIV_RATIO_HIGH 0xe8
-#define v_FEEDBACK_DIV_HIGH(n) (n & 1)
-
-#define PHY_PRE_DIV_RATIO 0xed
-#define v_PRE_DIV_RATIO(n) (n & 0x1f)
-
-#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
-static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev,
- u16 offset, u32 *val)
-{
- int ret;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- ret = rk616_drv->read_dev(rk616_drv,
- (RK616_HDMI_BASE + ((offset) << 2)), val);
- return ret;
-}
-
-static inline int hdmi_writel(struct rk_hdmi_device *hdmi_dev,
- u16 offset, u32 val)
-{
- int ret;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- ret = rk616_drv->write_dev(rk616_drv,
- (RK616_HDMI_BASE + ((offset) << 2)), &val);
- return ret;
-}
-
-static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 msk, u32 val)
-{
- int ret;
- struct mfd_rk616 *rk616_drv = hdmi_dev->rk616_drv;
-
- ret = rk616_drv->write_dev_bits(rk616_drv,
- (RK616_HDMI_BASE + ((offset) << 2)),
- msk, &val);
- return ret;
-}
-#else
-
-static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 *val)
-{
- int ret = 0;
-
- *val = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-static inline int hdmi_writel(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 val)
-{
- int ret = 0;
-
- writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-
-static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
- u32 msk, u32 val)
-{
- int ret = 0;
- u32 temp;
-
- temp = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
- writel_relaxed(temp | ((val) & (msk)), hdmi_dev->regbase + (offset) * 0x04);
- return ret;
-}
-#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
-static inline void rk3028_hdmi_reset_pclk(void)
-{
- writel_relaxed(0x00010001, RK_CRU_VIRT+ 0x128);
- msleep(100);
- writel_relaxed(0x00010000, RK_CRU_VIRT + 0x128);
-}
-#endif
-#endif
-
-extern int rk616_hdmi_initial(struct hdmi *hdmi);
-extern void rk616_hdmi_work(struct hdmi *hdmi);
-
-#endif
+++ /dev/null
-#ifndef __RK_HDMI_H__
-#define __RK_HDMI_H__
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/display-sys.h>
-#ifdef CONFIG_SWITCH
-#include <linux/switch.h>
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-#include <linux/atomic.h>
-#include<linux/rk_screen.h>
-#include <linux/rk_fb.h>
-
-/* default HDMI output video mode */
-#define HDMI_VIDEO_DEFAULT_MODE HDMI_1280x720p_60Hz
-
-#define HDMI_720X480P_60HZ_VIC 2
-#define HDMI_720X480I_60HZ_VIC 6
-#define HDMI_720X576P_50HZ_VIC 17
-#define HDMI_720X576I_50HZ_VIC 21
-#define HDMI_1280X720P_50HZ_VIC 19
-#define HDMI_1280X720P_60HZ_VIC 4
-#define HDMI_1920X1080P_50HZ_VIC 31
-#define HDMI_1920X1080I_50HZ_VIC 20
-#define HDMI_1920X1080P_60HZ_VIC 16
-#define HDMI_1920X1080I_60HZ_VIC 5
-#define HDMI_3840X2160P_24HZ_VIC 93
-#define HDMI_3840X2160P_25HZ_VIC 94
-#define HDMI_3840X2160P_30HZ_VIC 95
-#define HDMI_3840X2160P_50HZ_VIC 96
-#define HDMI_3840X2160P_60HZ_VIC 97
-#define HDMI_4096X2160P_24HZ_VIC 98
-#define HDMI_4096X2160P_25HZ_VIC 99
-#define HDMI_4096X2160P_30HZ_VIC 100
-#define HDMI_4096X2160P_50HZ_VIC 101
-#define HDMI_4096X2160P_60HZ_VIC 102
-
-/* HDMI video source */
-enum {
- HDMI_SOURCE_LCDC0 = 0,
- HDMI_SOURCE_LCDC1 = 1
-};
-
-enum {
- HDMI_SOC_RK3036,
- HDMI_SOC_RK312X,
- HDMI_SOC_RK3288
-};
-/*
- * If HDMI_ENABLE, system will auto configure output mode according to EDID
- * If HDMI_DISABLE, system will output mode according to
- * macro HDMI_VIDEO_DEFAULT_MODE
- */
-#define HDMI_AUTO_CONFIGURE HDMI_DISABLE
-
-/* default HDMI output audio mode */
-#define HDMI_AUDIO_DEFAULT_CHANNEL 2
-#define HDMI_AUDIO_DEFAULT_RATE HDMI_AUDIO_FS_44100
-#define HDMI_AUDIO_DEFAULT_WORD_LENGTH HDMI_AUDIO_WORD_LENGTH_16bit
-
-enum {
- VIDEO_INPUT_RGB_YCBCR_444 = 0,
- VIDEO_INPUT_YCBCR422,
- VIDEO_INPUT_YCBCR422_EMBEDDED_SYNC,
- VIDEO_INPUT_2X_CLOCK,
- VIDEO_INPUT_2X_CLOCK_EMBEDDED_SYNC,
- VIDEO_INPUT_RGB444_DDR,
- VIDEO_INPUT_YCBCR422_DDR
-};
-
-enum {
- VIDEO_OUTPUT_RGB444 = 0,
- VIDEO_OUTPUT_YCBCR444,
- VIDEO_OUTPUT_YCBCR422,
- VIDEO_OUTPUT_YCBCR420
-};
-
-enum {
- VIDEO_INPUT_COLOR_RGB = 0,
- VIDEO_INPUT_COLOR_YCBCR444,
- VIDEO_INPUT_COLOR_YCBCR422,
- VIDEO_INPUT_COLOR_YCBCR420
-};
-
-/* HDMI video mode code according CEA-861-E */
-enum hdmi_video_mode {
- HDMI_640x480p_60Hz = 1,
- HDMI_720x480p_60Hz_4_3,
- HDMI_720x480p_60Hz_16_9,
- HDMI_1280x720p_60Hz,
- HDMI_1920x1080i_60Hz, /* 5 */
- HDMI_720x480i_60Hz_4_3,
- HDMI_720x480i_60Hz_16_9,
- HDMI_720x240p_60Hz_4_3,
- HDMI_720x240p_60Hz_16_9,
- HDMI_2880x480i_60Hz_4_3, /* 10 */
- HDMI_2880x480i_60Hz_16_9,
- HDMI_2880x240p_60Hz_4_3,
- HDMI_2880x240p_60Hz_16_9,
- HDMI_1440x480p_60Hz_4_3,
- HDMI_1440x480p_60Hz_16_9, /* 15 */
- HDMI_1920x1080p_60Hz,
- HDMI_720x576p_50Hz_4_3,
- HDMI_720x576p_50Hz_16_9,
- HDMI_1280x720p_50Hz,
- HDMI_1920x1080i_50Hz, /* 20 */
- HDMI_720x576i_50Hz_4_3,
- HDMI_720x576i_50Hz_16_9,
- HDMI_720x288p_50Hz_4_3,
- HDMI_720x288p_50Hz_16_9,
- HDMI_2880x576i_50Hz_4_3, /* 25 */
- HDMI_2880x576i_50Hz_16_9,
- HDMI_2880x288p_50Hz_4_3,
- HDMI_2880x288p_50Hz_16_9,
- HDMI_1440x576p_50Hz_4_3,
- HDMI_1440x576p_50Hz_16_9, /* 30 */
- HDMI_1920x1080p_50Hz,
- HDMI_1920x1080p_24Hz,
- HDMI_1920x1080p_25Hz,
- HDMI_1920x1080p_30Hz,
- HDMI_2880x480p_60Hz_4_3, /* 35 */
- HDMI_2880x480p_60Hz_16_9,
- HDMI_2880x576p_50Hz_4_3,
- HDMI_2880x576p_50Hz_16_9,
- HDMI_1920x1080i_50Hz_2, /* V Line 1250 total */
- HDMI_1920x1080i_100Hz, /* 40 */
- HDMI_1280x720p_100Hz,
- HDMI_720x576p_100Hz_4_3,
- HDMI_720x576p_100Hz_16_9,
- HDMI_720x576i_100Hz_4_3,
- HDMI_720x576i_100Hz_16_9, /* 45 */
- HDMI_1920x1080i_120Hz,
- HDMI_1280x720p_120Hz,
- HDMI_720x480p_120Hz_4_3,
- HDMI_720x480p_120Hz_16_9,
- HDMI_720x480i_120Hz_4_3, /* 50 */
- HDMI_720x480i_120Hz_16_9,
- HDMI_720x576p_200Hz_4_3,
- HDMI_720x576p_200Hz_16_9,
- HDMI_720x576i_200Hz_4_3,
- HDMI_720x576i_200Hz_16_9, /* 55 */
- HDMI_720x480p_240Hz_4_3,
- HDMI_720x480p_240Hz_16_9,
- HDMI_720x480i_240Hz_4_3,
- HDMI_720x480i_240Hz_16_9,
- HDMI_1280x720p_24Hz, /* 60 */
- HDMI_1280x720p_25Hz,
- HDMI_1280x720p_30Hz,
- HDMI_1920x1080p_120Hz,
- HDMI_1920x1080p_100Hz,
-};
-
-/* HDMI Video Data Color Mode */
-enum {
- HDMI_COLOR_RGB = 0,
- HDMI_COLOR_YCbCr422,
- HDMI_COLOR_YCbCr444
-};
-
-/* HDMI Video Color Depth */
-enum {
- HDMI_COLOR_DEPTH_8BIT = 0x1,
- HDMI_COLOR_DEPTH_10BIT = 0x2,
- HDMI_COLOR_DEPTH_12BIT = 0x4,
- HDMI_COLOR_DEPTH_16BIT = 0x8
-};
-
-/* HDMI Audio type */
-enum hdmi_audio_type {
- HDMI_AUDIO_LPCM = 1,
- HDMI_AUDIO_AC3,
- HDMI_AUDIO_MPEG1,
- HDMI_AUDIO_MP3,
- HDMI_AUDIO_MPEG2,
- HDMI_AUDIO_AAC_LC, /* AAC */
- HDMI_AUDIO_DTS,
- HDMI_AUDIO_ATARC,
- HDMI_AUDIO_DSD, /* One bit Audio */
- HDMI_AUDIO_E_AC3,
- HDMI_AUDIO_DTS_HD,
- HDMI_AUDIO_MLP,
- HDMI_AUDIO_DST,
- HDMI_AUDIO_WMA_PRO
-};
-
-/* I2S Fs */
-enum hdmi_audio_fs {
- HDMI_AUDIO_FS_32000 = 0x1,
- HDMI_AUDIO_FS_44100 = 0x2,
- HDMI_AUDIO_FS_48000 = 0x4,
- HDMI_AUDIO_FS_88200 = 0x8,
- HDMI_AUDIO_FS_96000 = 0x10,
- HDMI_AUDIO_FS_176400 = 0x20,
- HDMI_AUDIO_FS_192000 = 0x40
-};
-
-/* Audio Word Length */
-enum hdmi_audio_word_length {
- HDMI_AUDIO_WORD_LENGTH_16bit = 0x1,
- HDMI_AUDIO_WORD_LENGTH_20bit = 0x2,
- HDMI_AUDIO_WORD_LENGTH_24bit = 0x4
-};
-
-/* EDID block size */
-#define HDMI_EDID_BLOCK_SIZE 128
-
-/* HDMI state machine */
-enum hdmi_state {
- HDMI_SLEEP = 0,
- HDMI_INITIAL,
- WAIT_HOTPLUG,
- READ_PARSE_EDID,
- WAIT_HDMI_ENABLE,
- SYSTEM_CONFIG,
- CONFIG_VIDEO,
- CONFIG_AUDIO,
- PLAY_BACK,
-};
-
-/* HDMI configuration command */
-enum hdmi_change {
- HDMI_CONFIG_NONE = 0,
- HDMI_CONFIG_VIDEO,
- HDMI_CONFIG_AUDIO,
- HDMI_CONFIG_COLOR,
- HDMI_CONFIG_HDCP,
- HDMI_CONFIG_ENABLE,
- HDMI_CONFIG_DISABLE,
- HDMI_CONFIG_DISPLAY
-};
-
-/* HDMI Hotplug status */
-enum {
- HDMI_HPD_REMOVED = 0,
- HDMI_HPD_INSERT,
- HDMI_HPD_ACTIVED
-};
-
-/* HDMI STATUS */
-#define HDMI_DISABLE 0
-#define HDMI_ENABLE 1
-#define HDMI_UNKOWN 0xFF
-
-/* HDMI Error Code */
-enum hdmi_errorcode {
- HDMI_ERROR_SUCESS = 0,
- HDMI_ERROR_FALSE,
- HDMI_ERROR_I2C,
- HDMI_ERROR_EDID,
-};
-
-/* HDMI audio parameters */
-struct hdmi_audio {
- u32 type; /* Audio type */
- u32 channel; /* Audio channel number */
- u32 rate; /* Audio sampling rate */
- u32 word_length; /* Audio data word length */
-};
-
-struct hdmi_edid {
- unsigned char sink_hdmi; /* HDMI display device flag */
- unsigned char ycbcr444; /* Display device support YCbCr444 */
- unsigned char ycbcr422; /* Display device support YCbCr422 */
- unsigned char deepcolor; /* bit3:DC_48bit; bit2:DC_36bit;
- * bit1:DC_30bit; bit0:DC_Y444;
- */
- unsigned char latency_fields_present;
- unsigned char i_latency_fields_present;
- unsigned char video_latency;
- unsigned char audio_latency;
- unsigned char interlaced_video_latency;
- unsigned char interlaced_audio_latency;
- unsigned char video_present; /* have additional video format
- * abount 4k and/or 3d
- */
- unsigned char support_3d; /* 3D format support */
- unsigned int maxtmdsclock; /* max tmds clock freq support */
- struct fb_monspecs *specs; /* Device spec */
- struct list_head modelist; /* Device supported display mode list */
- struct hdmi_audio *audio; /* Device supported audio info */
- int audio_num; /* Device supported audio type number */
- int base_audio_support; /* Device supported base audio */
- unsigned int cecaddress; /* CEC physical address */
-};
-
-/* RK HDMI Video Configure Parameters */
-struct hdmi_video_para {
- int vic;
- int input_mode; /* input video data interface */
- int input_color; /* input video color mode */
- int output_mode; /* output hdmi or dvi */
- int output_color; /* output video color mode */
- unsigned char format_3d; /* output 3d format */
- unsigned char color_depth; /* color depth: 8bit; 10bit;
- * 12bit; 16bit;
- */
- unsigned char pixel_repet; /* pixel repettion */
- unsigned char pixel_pack_phase; /* pixel packing default phase */
- unsigned char color_limit_range; /* quantization range
- * 0: full range(0~255)
- * 1:limit range(16~235)
- */
-};
-
-struct rk_hdmi_drvdata {
- u8 soc_type;
- u32 reversed;
-};
-struct hdmi;
-
-struct rk_hdmi_drv_ops {
- int (*hdmi_debug) (struct hdmi *hdmi, int cmd);
-};
-
-
-struct hdmi {
- struct device *dev;
- int id;
- int irq;
- struct rk_lcdc_driver *lcdc;
- struct rk_hdmi_drvdata *data;
- struct rk_display_device *ddev;
-#ifdef CONFIG_SWITCH
- struct switch_dev switch_hdmi;
-#endif
-
- struct mutex lock;
- struct workqueue_struct *workqueue;
- struct delayed_work delay_work;
-
- spinlock_t irq_lock;
- struct mutex enable_mutex;
-
- int wait;
- struct completion complete;
-
- int suspend;
-#ifdef CONFIG_HAS_EARLYSUSPEND
- struct early_suspend early_suspend;
-#endif
-
- struct hdmi_edid edid;
- int enable; /* Enable HDMI output or not */
- int vic; /* HDMI output video mode code */
- struct hdmi_audio audio; /* HDMI output audio type */
-
- int pwr_mode; /* power mode */
- int hotplug; /* hot plug status */
- int state; /* hdmi state machine status */
- int autoconfig; /* if true, auto config hdmi output mode
- * according to EDID
- */
- int command; /* HDMI configuration command */
- int display; /* HDMI display status */
- int xscale; /* x direction scale value */
- int yscale; /* y directoon scale value */
- int tmdsclk; /* TDMS Clock frequency */
- int pixclock; /* Pixel Clcok frequency */
- int uboot_logo;
-
- struct list_head pwrlist_head;
-
- int (*insert)(struct hdmi *hdmi);
- int (*remove)(struct hdmi *hdmi);
- void (*control_output)(struct hdmi *hdmi, int enable);
- int (*config_video)(struct hdmi *hdmi,
- struct hdmi_video_para *vpara);
- int (*config_audio)(struct hdmi *hdmi, struct hdmi_audio *audio);
- int (*detect_hotplug)(struct hdmi *hdmi);
- /* call back for edid */
- int (*read_edid)(struct hdmi *hdmi, int block, unsigned char *buff);
- int (*set_vif)(struct hdmi *hdmi, struct rk_screen *screen,
- bool connect);
-
- /* call back for hdcp operation */
- void (*hdcp_cb)(void);
- void (*hdcp_irq_cb)(int);
- int (*hdcp_power_on_cb)(void);
- void (*hdcp_power_off_cb)(void);
-
- /*call back for cec operation*/
- void (*cec_irq)(void);
- void (*cec_set_device_pa)(int);
- int (*cec_enumerate)(void);
- struct rk_hdmi_drv_ops *ops;
- unsigned int *support_vic;
- int support_vic_num;
-};
-
-#define hdmi_err(dev, format, arg...) \
- dev_err(dev , format , ## arg)
-
-#ifdef HDMI_DEBUG
-#define hdmi_dbg(dev, format, arg...) \
- dev_info(dev , format , ## arg)
-#else
-#define hdmi_dbg(dev, format, arg...)
-#endif
-
-int hdmi_drv_register(struct hdmi *hdmi_drv);
-int hdmi_get_hotplug(void);
-int hdmi_set_info(struct rk_screen *screen, unsigned int vic);
-void hdmi_init_lcdc(struct rk_screen *screen,
- struct rk29lcd_info *lcd_info);
-int hdmi_sys_init(struct hdmi *hdmi_drv);
-int hdmi_sys_parse_edid(struct hdmi *hdmi_drv);
-const char *hdmi_get_video_mode_name(unsigned char vic);
-int hdmi_videomode_to_vic(struct fb_videomode *vmode);
-const struct fb_videomode *hdmi_vic_to_videomode(int vic);
-int hdmi_add_videomode(const struct fb_videomode *mode,
- struct list_head *head);
-struct hdmi_video_timing *hdmi_find_mode(int vic);
-int hdmi_find_best_mode(struct hdmi *hdmi_drv, int vic);
-int hdmi_ouputmode_select(struct hdmi *hdmi_drv, int edid_ok);
-int hdmi_switch_fb(struct hdmi *hdmi_drv, int vic);
-int hdmi_init_video_para(struct hdmi *hdmi_drv,
- struct hdmi_video_para *video);
-void hdmi_work(struct work_struct *work);
-void hdmi_register_display_sysfs(struct hdmi *hdmi_drv,
- struct device *parent);
-void hdmi_unregister_display_sysfs(struct hdmi *hdmi_drv);
-
-int rk_hdmi_parse_dt(struct hdmi *hdmi_drv);
-int rk_hdmi_pwr_enable(struct hdmi *dev_drv);
-int rk_hdmi_pwr_disable(struct hdmi *dev_drv);
-
-#endif
+++ /dev/null
-#include "rk_hdmi.h"
-#include "../../edid.h"
-
-#define hdmi_edid_error(fmt, ...) \
- printk(pr_fmt(fmt), ##__VA_ARGS__)
-
-#if 0
-#define hdmi_edid_debug(fmt, ...) \
- printk(pr_fmt(fmt), ##__VA_ARGS__)
-#else
-#define hdmi_edid_debug(fmt, ...)
-#endif
-
-enum HDMI_EDID_ERRORCODE {
- E_HDMI_EDID_SUCCESS = 0,
- E_HDMI_EDID_PARAM,
- E_HDMI_EDID_HEAD,
- E_HDMI_EDID_CHECKSUM,
- E_HDMI_EDID_VERSION,
- E_HDMI_EDID_UNKOWNDATA,
- E_HDMI_EDID_NOMEMORY
-};
-
-static const unsigned int double_aspect_vic[] = {
- 3, 7, 9, 11, 13, 15, 18, 22, 24, 26, 28, 30,
- 36, 38, 43, 45, 49, 51, 53, 55, 57, 59
-};
-
-static int hdmi_edid_checksum(unsigned char *buf)
-{
- int i;
- int checksum = 0;
-
- for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)
- checksum += buf[i];
-
- checksum &= 0xff;
-
- if (checksum == 0)
- return E_HDMI_EDID_SUCCESS;
- else
- return E_HDMI_EDID_CHECKSUM;
-}
-
-/*
- * @Des Parse Detail Timing Descriptor.
- * @Param buf : pointer to DTD data.
- * @Param pvic: VIC of DTD descripted.
- */
-static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
-{
- mode->xres = H_ACTIVE;
- mode->yres = V_ACTIVE;
- mode->pixclock = PIXEL_CLOCK;
-/*
- mode->pixclock /= 1000;
- mode->pixclock = KHZ2PICOS(mode->pixclock);
-*/
- mode->right_margin = H_SYNC_OFFSET;
- mode->left_margin = (H_ACTIVE + H_BLANKING) -
- (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
- mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
- V_SYNC_WIDTH;
- mode->lower_margin = V_SYNC_OFFSET;
- mode->hsync_len = H_SYNC_WIDTH;
- mode->vsync_len = V_SYNC_WIDTH;
- if (HSYNC_POSITIVE)
- mode->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (VSYNC_POSITIVE)
- mode->sync |= FB_SYNC_VERT_HIGH_ACT;
- mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
- (V_ACTIVE + V_BLANKING));
- if (INTERLACED) {
- mode->yres *= 2;
- mode->upper_margin *= 2;
- mode->lower_margin *= 2;
- mode->vsync_len *= 2;
- mode->vmode |= FB_VMODE_INTERLACED;
- }
- mode->flag = FB_MODE_IS_DETAILED;
-
- hdmi_edid_debug("<<<<<<<<Detailed Time>>>>>>>>>\n");
- hdmi_edid_debug("%d KHz Refresh %d Hz", PIXEL_CLOCK/1000,
- mode->refresh);
- hdmi_edid_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
- H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
- hdmi_edid_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
- V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
- hdmi_edid_debug("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
- (VSYNC_POSITIVE) ? "+" : "-");
- return E_HDMI_EDID_SUCCESS;
-}
-
-static int hdmi_edid_parse_base(unsigned char *buf, int *extend_num,
- struct hdmi_edid *pedid)
-{
- int rc;
-#ifdef DEBUG
- int i = 0;
-#endif
-
- if (buf == NULL || extend_num == NULL)
- return E_HDMI_EDID_PARAM;
-
-#ifdef DEBUG
- for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++) {
- hdmi_edid_debug("%02x ", buf[i]&0xff);
- if ((i+1) % 16 == 0)
- hdmi_edid_debug("\n");
- }
-#endif
-
- /* Check first 8 byte to ensure it is an edid base block. */
- if (buf[0] != 0x00 ||
- buf[1] != 0xFF ||
- buf[2] != 0xFF ||
- buf[3] != 0xFF ||
- buf[4] != 0xFF ||
- buf[5] != 0xFF ||
- buf[6] != 0xFF ||
- buf[7] != 0x00) {
- hdmi_edid_error("[EDID] check header error\n");
- return E_HDMI_EDID_HEAD;
- }
-
- *extend_num = buf[0x7e];
-#ifdef DEBUG
- hdmi_edid_debug("[EDID] extend block num is %d\n", buf[0x7e]);
-#endif
-
- /* Checksum */
- rc = hdmi_edid_checksum(buf);
- if (rc != E_HDMI_EDID_SUCCESS) {
- hdmi_edid_error("[EDID] base block checksum error\n");
- return E_HDMI_EDID_CHECKSUM;
- }
-
- pedid->specs = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
- if (pedid->specs == NULL)
- return E_HDMI_EDID_NOMEMORY;
-
- fb_edid_to_monspecs(buf, pedid->specs);
-
- return E_HDMI_EDID_SUCCESS;
-}
-
-/* Parse CEA Short Video Descriptor */
-static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
-{
- const struct fb_videomode *mode;
- int count, i, j, vic;
-
- count = buf[0] & 0x1F;
- for (i = 0; i < count; i++) {
- hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
- buf[1 + i],
- buf[1 + i] & 0x7f,
- buf[1 + i] >> 7);
- #ifndef HDMI_VERSION_2
- vic = buf[1 + i] & 0x7f;
- #else
- vic = buf[1 + i] & 0xff;
- #endif
- for (j = 0; j < ARRAY_SIZE(double_aspect_vic); j++) {
- if (vic == double_aspect_vic[j]) {
- vic--;
- break;
- }
- }
- if (vic) {
- mode = hdmi_vic_to_videomode(vic);
- if (mode)
- hdmi_add_videomode(mode, &pedid->modelist);
- }
- }
- return 0;
-}
-
-/* Parse CEA Short Audio Descriptor */
-static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
-{
- int i, count;
-
- count = buf[0] & 0x1F;
- pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
- GFP_KERNEL);
- if (pedid->audio == NULL)
- return E_HDMI_EDID_NOMEMORY;
-
- pedid->audio_num = count / 3;
- for (i = 0; i < pedid->audio_num; i++) {
- pedid->audio[i].type = (buf[1 + i * 3] >> 3) & 0x0F;
- pedid->audio[i].channel = (buf[1 + i * 3] & 0x07) + 1;
- pedid->audio[i].rate = buf[1 + i * 3 + 1];
- if (pedid->audio[i].type == HDMI_AUDIO_LPCM) /* LPCM */
- pedid->audio[i].word_length = buf[1 + i * 3 + 2];
-/*
- printk("[EDID-CEA] type %d channel %d rate %d word length %d\n",
- pedid->audio[i].type, pedid->audio[i].channel,
- pedid->audio[i].rate, pedid->audio[i].word_length);
-*/
- }
- return E_HDMI_EDID_SUCCESS;
-}
-
-/* Parse CEA Vendor Specific Data Block */
-static int hdmi_edid_parse_cea_sdb(unsigned char *buf, struct hdmi_edid *pedid)
-{
- unsigned int count = 0, cur_offset = 0, i = 0;
- unsigned int IEEEOUI = 0;
- unsigned int supports_ai, dc_48bit, dc_36bit, dc_30bit, dc_y444;
- unsigned int len_3d, len_4k;
- unsigned char vic = 0;
- const struct fb_videomode *mode;
-
- count = buf[0] & 0x1F;
- IEEEOUI = buf[3];
- IEEEOUI <<= 8;
- IEEEOUI += buf[2];
- IEEEOUI <<= 8;
- IEEEOUI += buf[1];
- hdmi_edid_debug("[EDID-CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
- if (IEEEOUI == 0x0c03)
- pedid->sink_hdmi = 1;
-
- pedid->cecaddress = buf[cur_offset + 5];
- pedid->cecaddress |= buf[cur_offset + 4] << 8;
- hdmi_edid_debug("[EDID-CEA] CEC Physical addres is 0x%08x.\n", pedid->cecaddress);
-
- if (count > 5) {
- pedid->deepcolor = (buf[6] >> 3) & 0x0F;
- supports_ai = buf[6] >> 7;
- dc_48bit = (buf[6] >> 6) & 0x1;
- dc_36bit = (buf[6] >> 5) & 0x1;
- dc_30bit = (buf[6] >> 4) & 0x1;
- dc_y444 = (buf[6] >> 3) & 0x1;
- hdmi_edid_debug("[EDID-CEA] supports_ai %d\n"
- "dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d\n",
- supports_ai,
- dc_48bit, dc_36bit, dc_30bit, dc_y444);
- }
- if (count > 6)
- pedid->maxtmdsclock = buf[7] * 5000000;
-
- if (count > 7) {
- pedid->latency_fields_present = (buf[8] & 0x80) ? 1 : 0;
- pedid->i_latency_fields_present = (buf[8] & 0x40) ? 1 : 0;
- pedid->video_present = (buf[8] & 0x20) ? 1 : 0;
- }
-
- cur_offset = 9;
- if (count >= cur_offset) {
- if (pedid->latency_fields_present == 1) {
- pedid->video_latency = buf[cur_offset++];
- pedid->audio_latency = buf[cur_offset++];
- }
- if (count >= cur_offset && pedid->i_latency_fields_present) {
- pedid->interlaced_video_latency = buf[cur_offset++];
- pedid->interlaced_audio_latency = buf[cur_offset++];
- }
- }
-
- if (pedid->video_present == 0)
- return E_HDMI_EDID_SUCCESS;
-
- if (count >= cur_offset) {
- pedid->support_3d = (buf[cur_offset++] & 0x80) ? 1 : 0;
-
- len_4k = (buf[cur_offset] >> 5) & 0x07;
- len_3d = buf[cur_offset] & 0x1F;
- cur_offset++;
- }
- if (count >= cur_offset && len_4k > 0) {
- for (i = 0; i < len_4k; i++) {
- #ifndef HDMI_VERSION_2
- vic = buf[cur_offset + i] & 0x7f;
- if (vic > 0 && vic < 5)
- vic = (vic == 4) ? 98 : (96 - vic);
- hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
- buf[cur_offset + i],
- vic,
- buf[cur_offset + i] >> 7);
- #else
- vic = buf[cur_offset + i] & 0xff;
- hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
- buf[cur_offset + i], vic);
- #endif
- if (vic) {
- mode = hdmi_vic_to_videomode(vic);
- if (mode)
- hdmi_add_videomode(mode,
- &pedid->modelist);
- }
- }
- cur_offset += i;
- }
-
-/* TODO Daisen wait to add
- if (count >= cur_offset && pedid->support_3d && len_3d > 0) {
-
- }
-*/
- return E_HDMI_EDID_SUCCESS;
-}
-
-/* Parse CEA 861 Serial Extension. */
-static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
- struct hdmi_edid *pedid)
-{
- unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
- unsigned int underscan_support, baseaudio_support;
- unsigned int tag;
-
- if (buf == NULL)
- return E_HDMI_EDID_PARAM;
-
- /* Check ces extension version */
- if (buf[1] != 3) {
- hdmi_edid_error("[EDID-CEA] error version.\n");
- return E_HDMI_EDID_VERSION;
- }
-
- ddc_offset = buf[2];
- underscan_support = (buf[3] >> 7) & 0x01;
- baseaudio_support = (buf[3] >> 6) & 0x01;
- pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
- pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
- native_dtd_num = buf[3] & 0x0F;
- pedid->base_audio_support = baseaudio_support;
-
- /* Parse data block */
- while (cur_offset < ddc_offset) {
- tag = buf[cur_offset] >> 5;
- switch (tag) {
- case 0x02: /* Video Data Block */
- hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");
- hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
- break;
- case 0x01: /* Audio Data Block */
- hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");
- hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
- break;
- case 0x04: /* Speaker Allocation Data Block */
- hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocation Data Block.\n");
- break;
- case 0x03: /* Vendor Specific Data Block */
- hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");
- hdmi_edid_parse_cea_sdb(buf + cur_offset, pedid);
- break;
- case 0x05: /* VESA DTC Data Block */
- hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");
- break;
- case 0x07: /* Use Extended Tag */
- hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");
- break;
- default:
- hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");
- break;
- }
- cur_offset += (buf[cur_offset] & 0x1F) + 1;
- }
-#if 1
-{
- /* Parse DTD */
- struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode),
- GFP_KERNEL);
- if (vmode == NULL)
- return E_HDMI_EDID_SUCCESS;
- /* buf[126] = 0 and buf[127] = checksum */
- while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
- if (!buf[ddc_offset] && !buf[ddc_offset + 1])
- break;
- memset(vmode, 0, sizeof(struct fb_videomode));
- hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
- hdmi_add_videomode(vmode, &pedid->modelist);
- ddc_offset += 18;
- }
- kfree(vmode);
-}
-#endif
- return E_HDMI_EDID_SUCCESS;
-}
-
-static int hdmi_edid_parse_extensions(unsigned char *buf,
- struct hdmi_edid *pedid)
-{
- int rc;
-
- if (buf == NULL || pedid == NULL)
- return E_HDMI_EDID_PARAM;
-
- /* Checksum */
- rc = hdmi_edid_checksum(buf);
- if (rc != E_HDMI_EDID_SUCCESS) {
- hdmi_edid_error("[EDID] extensions block checksum error\n");
- return E_HDMI_EDID_CHECKSUM;
- }
-
- switch (buf[0]) {
- case 0xF0:
- hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");
- break;
- case 0x02:
- hdmi_edid_debug("[EDID-EXTEND] It is a CEA 861 Series Extension.\n");
- hdmi_edid_parse_extensions_cea(buf, pedid);
- break;
- case 0x10:
- hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");
- break;
- case 0x40:
- hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");
- break;
- case 0x50:
- hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");
- break;
- case 0x60:
- hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");
- break;
- default:
- hdmi_edid_error("[EDID-EXTEND] Unkowned extension.\n");
- return E_HDMI_EDID_UNKOWNDATA;
- }
-
- return E_HDMI_EDID_SUCCESS;
-}
-
-
-int hdmi_sys_parse_edid(struct hdmi *hdmi)
-{
- struct hdmi_edid *pedid;
- unsigned char *buff = NULL;
- int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;
-
- if (hdmi == NULL)
- return HDMI_ERROR_FALSE;
-
- pedid = &(hdmi->edid);
- memset(pedid, 0, sizeof(struct hdmi_edid));
- INIT_LIST_HEAD(&pedid->modelist);
-
- buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
- if (buff == NULL) {
- hdmi_dbg(hdmi->dev,
- "[%s] can not allocate memory for edid buff.\n",
- __func__);
- return -1;
- }
-
- /* Read base block edid. */
- memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
- rc = hdmi->read_edid(hdmi, 0, buff);
- if (rc) {
- dev_err(hdmi->dev, "[HDMI] read edid base block error\n");
- goto out;
- }
- rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
- if (rc) {
- dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");
- goto out;
- }
- for (i = 1; i < extendblock + 1; i++) {
- memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
- rc = hdmi->read_edid(hdmi, i, buff);
- if (rc) {
- printk("[HDMI] read edid block %d error\n", i);
- goto out;
- }
- rc = hdmi_edid_parse_extensions(buff, pedid);
- if (rc) {
- dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n",
- i);
- continue;
- }
- }
-out:
- kfree(buff);
- rc = hdmi_ouputmode_select(hdmi, rc);
- return rc;
-}
+++ /dev/null
-#include <linux/console.h>
-#include<linux/rk_fb.h>
-#include "rk_hdmi.h"
-
-#define OUT_TYPE SCREEN_HDMI
-#define OUT_FACE OUT_P888
-#define DCLK_POL 1
-#define SWAP_RB 0
-#define LCD_ACLK 800000000
-
-struct hdmi *m_hdmi_drv;
-
-static const struct fb_videomode hdmi_mode[] = {
- /* name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag(used for vic) */
-/*
- {"640x480p@60Hz", 60, 640, 480, 25175000, 48, 16, 33, 10, 96, 2, 0, 0, 1 },
-*/
- {"720x480i@60Hz", 60, 720, 480, 27000000, 57, 19, 15, 4, 62, 3, 0, 1, 6 },
- {"720x576i@50Hz", 50, 720, 576, 27000000, 69, 12, 19, 2, 63, 3, 0, 1, 21},
- {"720x480p@60Hz", 60, 720, 480, 27000000, 60, 16, 30, 9, 62, 6, 0, 0, 2 },
- {"720x576p@50Hz", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, 17},
-/*
- {"1280x720p@24Hz", 24, 1280, 720, 59400000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 60},
- {"1280x720p@25Hz", 25, 1280, 720, 74250000, 220, 2420, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 61},
- {"1280x720p@30Hz", 30, 1280, 720, 74250000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 62},
-*/
- {"1280x720p@50Hz", 50, 1280, 720, 74250000, 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 19},
- {"1280x720p@60Hz", 60, 1280, 720, 74250000, 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 4 },
-/*
- {"1920x1080p@24Hz", 24, 1920, 1080, 74250000, 148, 638, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 32},
- {"1920x1080p@25Hz", 25, 1920, 1080, 74250000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 33},
- {"1920x1080p@30Hz", 30, 1920, 1080, 74250000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 34},
- {"1920x1080i@50Hz_2", 50, 1920, 1080, 72000000, 184, 32, 57, 23, 168, 5, FB_SYNC_HOR_HIGH_ACT, 1, 39},
-*/
- {"1920x1080i@50Hz", 50, 1920, 1080, 74250000, 148, 528, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 20},
- {"1920x1080i@60Hz", 60, 1920, 1080, 74250000, 148, 88, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 5 },
- {"1920x1080p@50Hz", 50, 1920, 1080, 148500000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 31},
- {"1920x1080p@60Hz", 60, 1920, 1080, 148500000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 16},
-/*
- {"1440x288p@50Hz", 50, 720, 480, 27000000, 138, 24, 19, 2, 126, 3, 0, 0, 23},
- {"2880x576i@50Hz", 50, 1440, 240, 54000000, 276, 48, 19, 2, 252, 3, 0, 1, 25},
- {"2880x288p@50Hz", 50, 2880, 480, 54000000, 276, 48, 19, 3, 252, 3, 0, 0, 27},
- {"1440x576p@50Hz", 50, 2880, 480, 54000000, 136, 24, 39, 5, 128, 5, 0, 0, 29},
- {"2880x576p@50Hz", 50, 1920, 1080, 108000000, 272, 48, 39, 5, 256, 5, 0, 0, 37},
- {"1440x240p@60Hz", 60, 1440, 240, 27000000, 114, 38, 15, 4, 124, 3, 0, 0, 8 },
- {"2880x480i@60Hz", 60, 2880, 480, 54000000, 228, 76, 15, 4, 248, 3, 0, 1, 10},
- {"2880x480p@60Hz", 60, 2880, 480, 54000000, 228, 76, 15, 4, 248, 3, 0, 0, 12},
- {"1440x480p@60Hz", 60, 1440, 480, 54000000, 120, 32, 30, 9, 124, 6, 0, 0, 14},
- {"2880x480p@60Hz", 60, 2880, 480, 54000000, 240, 64, 30, 9, 248, 6, 0, 0, 35},
-
- {"1920x1080i@100Hz", 100, 1920, 1080, 148500000, 148, 528, 15, 2, 44, 5, 1, 1, 40},
- {"1280x720p@100Hz", 100, 1280, 720, 148500000, 220, 440, 20, 5, 40, 5, 1, 0, 41},
- {"720x576p@100Hz", 100, 720, 576, 54000000, 68, 12, 39, 5, 64, 5, 0, 0, 42},
- {"1440x576i@100Hz", 100, 1440, 576, 54000000, 138, 24, 19, 2, 12, 3, 0, 1, 44},
- {"1920x1080p@100Hz", 100, 1920, 1080, 297000000, 148, 528, 36, 4, 44, 5, 1, 0, 64},
-
- {"1920x1080i@120Hz", 120, 1920, 1080, 148500000, 148, 88, 15, 2, 44, 5, 1, 1, 46},
- {"1280x720p@120Hz", 120, 1280, 720, 148500000, 220, 110, 20, 5, 40, 5, 1, 0, 47},
- {"720x480p@120Hz", 120, 720, 480, 54000000, 60, 16, 30, 9, 62, 6, 0, 0, 48},
- {"1440x480i@120Hz", 120, 1440, 480, 54000000, 114, 38, 15, 4, 12, 3, 0, 1, 50},
- {"1920x1080p@120Hz", 120, 1920, 1080, 297000000, 148, 88, 36, 4, 44, 5, 1, 0, 63},
-
- {"720x576p@200Hz", 200, 720, 576, 108000000, 68, 12, 39, 5, 64, 5, 0, 0, 52},
- {"1440x576i@200Hz", 200, 1920, 1080, 108000000, 138, 24, 19, 2, 12, 3, 0, 1, 54},
-
- {"720x480p@240Hz", 240, 720, 480, 108000000, 60, 16, 30, 9, 62, 6, 0, 0, 56},
- {"1440x480i@240Hz", 240, 1440, 480, 108000000, 114, 38, 15, 4, 12, 3, 0, 1, 58},
-*/
- {"3840x2160p@24Hz", 24, 3840, 2160, 297000000, 296, 1276, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 93},
- {"3840x2160p@25Hz", 25, 3840, 2160, 297000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 94},
- {"3840x2160p@30Hz", 30, 3840, 2160, 297000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 95},
- {"3840x2160p@50Hz", 50, 3840, 2160, 594000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 96},
- {"3840x2160p@60Hz", 60, 3840, 2160, 594000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 97},
- {"4096x2160p@24Hz", 24, 4096, 2160, 297000000, 296, 1020, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 98},
- {"4096x2160p@25Hz", 25, 4096, 2160, 297000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 99},
- {"4096x2160p@30Hz", 30, 4096, 2160, 297000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 100},
- {"4096x2160p@50Hz", 50, 4096, 2160, 594000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 101},
- {"4096x2160p@60Hz", 60, 4096, 2160, 594000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 102},
-
-};
-
-void hdmi_init_lcdc(struct rk_screen *screen, struct rk29lcd_info *lcd_info)
-{
- hdmi_set_info(screen, HDMI_VIDEO_DEFAULT_MODE);
-}
-
-int hdmi_set_info(struct rk_screen *screen, unsigned int vic)
-{
- int i;
-
- if (screen == NULL)
- return -1;
-
- if (vic == 0)
- vic = HDMI_VIDEO_DEFAULT_MODE;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- if (hdmi_mode[i].flag == vic)
- break;
- }
- if (i == ARRAY_SIZE(hdmi_mode))
- return -1;
-
- memset(screen, 0, sizeof(struct rk_screen));
-
- /* screen type & face */
- screen->type = OUT_TYPE;
- screen->face = OUT_FACE;
- screen->color_mode = COLOR_YCBCR;
-
- /* Screen size */
- screen->mode.xres = hdmi_mode[i].xres;
- screen->mode.yres = hdmi_mode[i].yres;
-
- /* Timing */
- screen->mode.pixclock = hdmi_mode[i].pixclock;
- screen->mode.refresh = hdmi_mode[i].refresh;
- /* screen->lcdc_aclk = LCD_ACLK; */
- screen->mode.left_margin = hdmi_mode[i].left_margin;
- screen->mode.right_margin = hdmi_mode[i].right_margin;
- screen->mode.hsync_len = hdmi_mode[i].hsync_len;
- screen->mode.upper_margin = hdmi_mode[i].upper_margin;
- screen->mode.lower_margin = hdmi_mode[i].lower_margin;
- screen->mode.vsync_len = hdmi_mode[i].vsync_len;
- screen->mode.vmode = hdmi_mode[i].vmode;
- screen->hdmi_resolution = hdmi_mode[i].flag;
- if ((screen->hdmi_resolution == HDMI_720X480I_60HZ_VIC) ||
- (screen->hdmi_resolution == HDMI_720X576I_50HZ_VIC))
- screen->pixelrepeat = 1;
-
- /* Pin polarity */
-#if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026)
- screen->pin_hsync = 0;
- screen->pin_vsync = 0;
-#else
- screen->pin_hsync = 0;
- if (FB_SYNC_HOR_HIGH_ACT & hdmi_mode[i].sync)
- screen->pin_hsync = 1;
- else
- screen->pin_hsync = 0;
- if (FB_SYNC_VERT_HIGH_ACT & hdmi_mode[i].sync)
- screen->pin_vsync = 1;
- else
- screen->pin_vsync = 0;
-#endif
- 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;
-
- /* Init Default Overscan Value:
- * TODO modify the value according to your need adjust value
- */
- switch (vic) {
- case 16: /* 1080p-60Hz */
- screen->overscan.left = 97;
- screen->overscan.top = 97;
- screen->overscan.right = 97;
- screen->overscan.bottom = 97;
- break;
- default:
- screen->overscan.left = 96;
- screen->overscan.top = 96;
- screen->overscan.right = 96;
- screen->overscan.bottom = 96;
- break;
- }
-
- return 0;
-}
-
-#ifdef HDMI_DEBUG
-static void hdmi_show_sink_info(struct hdmi *hdmi)
-{
- struct list_head *pos, *head = &hdmi->edid.modelist;
- struct fb_modelist *modelist;
- struct fb_videomode *m;
- int i;
- struct hdmi_audio *audio;
-
- hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
- hdmi_dbg(hdmi->dev, "Support video mode:\n");
- list_for_each(pos, head) {
- modelist = list_entry(pos, struct fb_modelist, list);
- m = &modelist->mode;
- hdmi_dbg(hdmi->dev, " %s.\n", m->name);
- }
-
- for (i = 0; i < hdmi->edid.audio_num; i++) {
- audio = &(hdmi->edid.audio[i]);
- switch (audio->type) {
- case HDMI_AUDIO_LPCM:
- hdmi_dbg(hdmi->dev, "Support audio type: LPCM\n");
- break;
- case HDMI_AUDIO_AC3:
- hdmi_dbg(hdmi->dev, "Support audio type: AC3\n");
- break;
- case HDMI_AUDIO_MPEG1:
- hdmi_dbg(hdmi->dev, "Support audio type: MPEG1\n");
- break;
- case HDMI_AUDIO_MP3:
- hdmi_dbg(hdmi->dev, "Support audio type: MP3\n");
- break;
- case HDMI_AUDIO_MPEG2:
- hdmi_dbg(hdmi->dev, "Support audio type: MPEG2\n");
- break;
- case HDMI_AUDIO_AAC_LC:
- hdmi_dbg(hdmi->dev, "Support audio type: AAC\n");
- break;
- case HDMI_AUDIO_DTS:
- hdmi_dbg(hdmi->dev, "Support audio type: DTS\n");
- break;
- case HDMI_AUDIO_ATARC:
- hdmi_dbg(hdmi->dev, "Support audio type: ATARC\n");
- break;
- case HDMI_AUDIO_DSD:
- hdmi_dbg(hdmi->dev, "Support audio type: DSD\n");
- break;
- case HDMI_AUDIO_E_AC3:
- hdmi_dbg(hdmi->dev, "Support audio type: E-AC3\n");
- break;
- case HDMI_AUDIO_DTS_HD:
- hdmi_dbg(hdmi->dev, "Support audio type: DTS-HD\n");
- break;
- case HDMI_AUDIO_MLP:
- hdmi_dbg(hdmi->dev, "Support audio type: MLP\n");
- break;
- case HDMI_AUDIO_DST:
- hdmi_dbg(hdmi->dev, "Support audio type: DST\n");
- break;
- case HDMI_AUDIO_WMA_PRO:
- hdmi_dbg(hdmi->dev, "Support audio type: WMP-PRO\n");
- break;
- default:
- hdmi_dbg(hdmi->dev, "Support audio type: Unkown\n");
- break;
- }
-
- hdmi_dbg(hdmi->dev, "Support audio sample rate:\n");
- if (audio->rate & HDMI_AUDIO_FS_32000)
- hdmi_dbg(hdmi->dev, " 32000\n");
- if (audio->rate & HDMI_AUDIO_FS_44100)
- hdmi_dbg(hdmi->dev, " 44100\n");
- if (audio->rate & HDMI_AUDIO_FS_48000)
- hdmi_dbg(hdmi->dev, " 48000\n");
- if (audio->rate & HDMI_AUDIO_FS_88200)
- hdmi_dbg(hdmi->dev, " 88200\n");
- if (audio->rate & HDMI_AUDIO_FS_96000)
- hdmi_dbg(hdmi->dev, " 96000\n");
- if (audio->rate & HDMI_AUDIO_FS_176400)
- hdmi_dbg(hdmi->dev, " 176400\n");
- if (audio->rate & HDMI_AUDIO_FS_192000)
- hdmi_dbg(hdmi->dev, " 192000\n");
-
- hdmi_dbg(hdmi->dev, "Support audio word lenght:\n");
- if (audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
- hdmi_dbg(hdmi->dev, " 16bit\n");
- if (audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
- hdmi_dbg(hdmi->dev, " 20bit\n");
- if (audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
- hdmi_dbg(hdmi->dev, " 24bit\n");
- }
- hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
-}
-#endif
-
-/**
- * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
- * @hdmi: handle of hdmi
- * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
- */
-int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
-{
- struct list_head *head = &hdmi->edid.modelist;
- struct fb_monspecs *specs = hdmi->edid.specs;
- struct fb_videomode *modedb = NULL;
- int i, pixclock;
-
- if (edid_ok != HDMI_ERROR_SUCESS) {
- dev_err(hdmi->dev,
- "warning: EDID error, assume sink as HDMI and asume minitor support audio output!!!!");
- hdmi->edid.sink_hdmi = 1;
- /* if edid error,asume monitor support audio output */
- hdmi->edid.base_audio_support = 1;
- }
-
- if (edid_ok != HDMI_ERROR_SUCESS) {
- hdmi->edid.ycbcr444 = 0;
- hdmi->edid.ycbcr422 = 0;
- hdmi->autoconfig = HDMI_DISABLE;
- }
- if (head->next == head) {
- dev_info(hdmi->dev,
- "warning: no CEA video mode parsed from EDID !!!!");
- /* If EDID get error, list all system supported mode.
- * If output mode is set to DVI and EDID is ok, check
- * the output timing.
- */
-
- if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
- /* Get max resolution timing */
- modedb = &specs->modedb[0];
- for (i = 0; i < specs->modedb_len; i++) {
- if (specs->modedb[i].xres > modedb->xres)
- modedb = &specs->modedb[i];
- else if (specs->modedb[i].yres > modedb->yres)
- modedb = &specs->modedb[i];
- }
- /* For some monitor, the max pixclock read from EDID
- * is smaller than the clock of
- * max resolution mode supported.
- */
- pixclock = PICOS2KHZ(modedb->pixclock);
- pixclock /= 250;
- pixclock *= 250;
- pixclock *= 1000;
- if (pixclock == 148250000)
- pixclock = 148500000;
- if (pixclock > specs->dclkmax)
- specs->dclkmax = pixclock;
- }
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- if (modedb) {
- if ((hdmi_mode[i].pixclock < specs->dclkmin) ||
- (hdmi_mode[i].pixclock > specs->dclkmax) ||
- (hdmi_mode[i].refresh < specs->vfmin) ||
- (hdmi_mode[i].refresh > specs->vfmax) ||
- (hdmi_mode[i].xres > modedb->xres) ||
- (hdmi_mode[i].yres > modedb->yres))
- continue;
- }
- hdmi_add_videomode(&hdmi_mode[i], head);
- }
- }
-#ifdef HDMI_DEBUG
- hdmi_show_sink_info(hdmi);
-#endif
- return HDMI_ERROR_SUCESS;
-}
-
-/**
- * hdmi_videomode_compare - compare 2 videomodes
- * @mode1: first videomode
- * @mode2: second videomode
- *
- * RETURNS:
- * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
- */
-static int hdmi_videomode_compare(const struct fb_videomode *mode1,
- const struct fb_videomode *mode2)
-{
- if (mode1->xres > mode2->xres)
- return 1;
- else if (mode1->xres == mode2->xres) {
- if (mode1->yres > mode2->yres)
- return 1;
- else if (mode1->yres == mode2->yres) {
- if (mode1->pixclock > mode2->pixclock)
- return 1;
- else if (mode1->pixclock == mode2->pixclock) {
- if (mode1->refresh > mode2->refresh)
- return 1;
- else if (mode1->refresh == mode2->refresh)
- return 0;
- }
- }
- }
- return -1;
-}
-int hdmi_check_support_videomode(int vic)
-{
- int i, support = 0;
- if (m_hdmi_drv->support_vic_num == 0)
- return 1;
-
- for (i=0; i<m_hdmi_drv->support_vic_num; i++) {
- if (m_hdmi_drv->support_vic[i] == vic) {
- support = 1;
- break;
- }
- }
- if(i >= m_hdmi_drv->support_vic_num)
- support = 0;
- return support;
-}
-
-/**
- * hdmi_add_videomode: adds videomode entry to modelist
- * @mode: videomode to add
- * @head: struct list_head of modelist
- *
- * NOTES:
- * Will only add unmatched mode entries
- */
-int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
-{
- struct list_head *pos;
- struct fb_modelist *modelist, *modelist_new;
- struct fb_videomode *m;
- int i, found = 0;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- m = (struct fb_videomode *)&hdmi_mode[i];
- if (fb_mode_is_equal(m, mode)) {
- if(hdmi_check_support_videomode(m->flag))
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_for_each(pos, head) {
- modelist = list_entry(pos, struct fb_modelist, list);
- m = &modelist->mode;
- if (fb_mode_is_equal(m, mode)) {
- /* m == mode */
- return 0;
- } else {
- if (hdmi_videomode_compare(m, mode) == -1)
- break;
- }
- }
-
- modelist_new = kmalloc(sizeof(struct fb_modelist), GFP_KERNEL);
- if (!modelist_new)
- return -ENOMEM;
- modelist_new->mode = hdmi_mode[i];
- list_add_tail(&modelist_new->list, pos);
- }
-
- return 0;
-}
-
-/**
- * hdmi_videomode_to_vic: transverse video mode to vic
- * @vmode: videomode to transverse
- *
- */
-int hdmi_videomode_to_vic(struct fb_videomode *vmode)
-{
- unsigned char vic = 0;
- int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- if (vmode->vmode == hdmi_mode[i].vmode &&
- vmode->refresh == hdmi_mode[i].refresh &&
- vmode->xres == hdmi_mode[i].xres &&
- vmode->left_margin == hdmi_mode[i].left_margin &&
- vmode->right_margin == hdmi_mode[i].right_margin &&
- vmode->upper_margin == hdmi_mode[i].upper_margin &&
- vmode->lower_margin == hdmi_mode[i].lower_margin &&
- vmode->hsync_len == hdmi_mode[i].hsync_len &&
- vmode->vsync_len == hdmi_mode[i].vsync_len) {
- /*if ((vmode->vmode == FB_VMODE_NONINTERLACED
- && vmode->yres == hdmi_mode[i].yres)
- || (vmode->vmode == FB_VMODE_INTERLACED
- && vmode->yres == hdmi_mode[i].yres / 2))*/
- {
- vic = hdmi_mode[i].flag;
- break;
- }
- }
- }
- return vic;
-}
-
-/**
- * hdmi_vic_to_videomode: transverse vic mode to video mode
- * @vmode: vic to transverse
- *
- */
-const struct fb_videomode *hdmi_vic_to_videomode(int vic)
-{
- int i;
-
- if (vic == 0)
- return NULL;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- if (hdmi_mode[i].flag == vic)
- return &hdmi_mode[i];
- }
- return NULL;
-}
-
-/**
- * hdmi_find_best_mode: find the video mode nearest to input vic
- * @hdmi:
- * @vic: input vic
- *
- * NOTES:
- * If vic is zero, return the high resolution video mode vic.
- */
-int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
-{
- struct list_head *pos, *head = &hdmi->edid.modelist;
- struct fb_modelist *modelist;
- struct fb_videomode *m = NULL;
- int found = 0;
-
- if (vic) {
- list_for_each(pos, head) {
- modelist = list_entry(pos, struct fb_modelist, list);
- m = &modelist->mode;
- if (m->flag == vic) {
- found = 1;
- break;
- }
- }
- }
- if ((vic == 0 || found == 0) && head->next != head) {
- modelist = list_entry(head->next, struct fb_modelist, list);
- m = &modelist->mode;
- }
- if (m != NULL)
- return m->flag;
- else
- return 0;
-}
-
-const char *hdmi_get_video_mode_name(unsigned char vic)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
- if (vic == hdmi_mode[i].flag)
- break;
- }
- if (i == ARRAY_SIZE(hdmi_mode))
- return NULL;
- else
- return hdmi_mode[i].name;
-}
-
-/**
- * hdmi_switch_fb: switch lcdc mode to required video mode
- * @hdmi:
- * @type:
- *
- * NOTES:
- *
- */
-int hdmi_switch_fb(struct hdmi *hdmi, int vic)
-{
- int rc = 0;
- struct rk_screen *screen;
-
- screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
- if (screen == NULL)
- return -1;
-
- if (hdmi->vic == 0)
- hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
-
- rc = hdmi_set_info(screen, hdmi->vic);
-
- if (rc == 0) {
- if (hdmi->set_vif) /* turn off vif for jettab */
- hdmi->set_vif(hdmi, screen, 0);
- rk_fb_switch_screen(screen, 1, hdmi->lcdc->id);
- rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
- if (hdmi->set_vif)
- hdmi->set_vif(hdmi, screen, 1);
-
- }
-
- kfree(screen);
-
- return rc;
-}
-
-/**
- * hdmi_init_video_para: init video_para variable
- *
- * NOTES:
- *This parameters should be modified according to need by user
- */
-int hdmi_init_video_para(struct hdmi *hdmi_drv, struct hdmi_video_para *video)
-{
- struct rk_lcdc_driver *lcdc_drv = NULL;
-
- if (unlikely(hdmi_drv == NULL))
- return -1;
-
- lcdc_drv = hdmi_drv->lcdc;
- if (unlikely(lcdc_drv == NULL))
- return -1;
-
- memset(video, 0, sizeof(struct hdmi_video_para));
-
- video->vic = hdmi_drv->vic;
- video->input_mode = VIDEO_INPUT_RGB_YCBCR_444;
- if (lcdc_drv->output_color == COLOR_RGB)
- video->input_color = VIDEO_INPUT_COLOR_RGB;
- else
- video->input_color = VIDEO_INPUT_COLOR_YCBCR444;
-
- video->output_mode = hdmi_drv->edid.sink_hdmi;
- video->format_3d = 0; /* TODO modify according to EDID if need */
- video->pixel_repet = 0;
- /* 0:IT Video Format 1:CE Video Format
- * TODO modify according to EDID
- */
- video->color_limit_range = 1;
-
-#ifdef SOURCE_ABOVE_10BIT
- if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_16BIT)
- video->color_depth = HDMI_COLOR_DEPTH_16BIT;
- else if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_12BIT)
- video->color_depth = HDMI_COLOR_DEPTH_12BIT;
- else
-#endif
- if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_10BIT)
- video->color_depth = HDMI_COLOR_DEPTH_10BIT;
- else
- video->color_depth = HDMI_COLOR_DEPTH_8BIT;
-/*
- if (hdmi_drv->edid.ycbcr444)
- video->output_color = VIDEO_OUTPUT_YCBCR444;
- else if (hdmi_drv->edid.ycbcr422)
- video->output_color = VIDEO_OUTPUT_YCBCR422;
- else
-*/ video->output_color = VIDEO_OUTPUT_RGB444;
-
- /*For DVI, output RGB */
- if (hdmi_drv->edid.sink_hdmi == 0)
- video->output_color = VIDEO_OUTPUT_RGB444;
-
- return 0;
-}
-
-/**
- * hdmi_drv_register: init hdmi_drv variable
- *
- * NOTES:
- *
- */
-int hdmi_drv_register(struct hdmi *hdmi_drv)
-{
- m_hdmi_drv = hdmi_drv;
- return 0;
-}
-
-/**
- * hdmi_get_status: get hdmi hotplug status
- *
- * NOTES:
- *
- */
-int hdmi_get_hotplug(void)
-{
- if (m_hdmi_drv)
- return m_hdmi_drv->hotplug;
- else
- return HDMI_HPD_REMOVED;
-}
+++ /dev/null
-#include "rk_hdmi.h"
-#ifdef CONFIG_OF
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-
-/* rk hdmi power control parse from dts
- *
-*/
-int rk_hdmi_pwr_ctr_parse_dt(struct hdmi *dev_drv)
-{
- struct device_node *root = of_find_node_by_name(dev_drv->dev->of_node,
- "power_ctr_hdmi");
- struct device_node *child;
- struct rk_disp_pwr_ctr_list *pwr_ctr;
- struct list_head *pos;
- enum of_gpio_flags flags;
- u32 val = 0;
- u32 debug = 0;
- int ret;
-
- INIT_LIST_HEAD(&dev_drv->pwrlist_head);
- if (!root) {
- dev_err(dev_drv->dev, "can't find power_ctr node %d\n",
- dev_drv->id);
- return -ENODEV;
- }
-
- for_each_child_of_node(root, child) {
- pwr_ctr = kmalloc(sizeof(struct rk_disp_pwr_ctr_list),
- GFP_KERNEL);
- strcpy(pwr_ctr->pwr_ctr.name, child->name);
- if (!of_property_read_u32(child, "rockchip,power_type", &val)) {
- if (val == GPIO) {
- pwr_ctr->pwr_ctr.type = GPIO;
- pwr_ctr->pwr_ctr.gpio =
- of_get_gpio_flags(child, 0, &flags);
- if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
- dev_err(dev_drv->dev,
- "%s ivalid gpio\n",
- child->name);
- return -EINVAL;
- }
- pwr_ctr->pwr_ctr.atv_val =
- flags & OF_GPIO_ACTIVE_LOW;
- ret = gpio_request(pwr_ctr->pwr_ctr.gpio,
- child->name);
- if (ret) {
- dev_err(dev_drv->dev,
- "request %s gpio fail:%d\n",
- child->name, ret);
- return -1;
- }
-
- } else {
- pwr_ctr->pwr_ctr.type = REGULATOR;
-
- }
- };
- of_property_read_u32(child, "rockchip,delay", &val);
- pwr_ctr->pwr_ctr.delay = val;
- of_property_read_u32(child, "rockchip,is_rst", &val);
- pwr_ctr->pwr_ctr.is_rst = val;
- list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
- }
-
- of_property_read_u32(root, "rockchip,debug", &debug);
-
- if (debug) {
- list_for_each(pos, &dev_drv->pwrlist_head) {
- pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list,
- list);
- dev_info(dev_drv->dev, "pwr_ctr_name:%s\n"
- "pwr_type:%s\n" "gpio:%d\n"
- "atv_val:%d\n" "delay:%d\n\n",
- pwr_ctr->pwr_ctr.name,
- (pwr_ctr->pwr_ctr.type == GPIO) ?
- "gpio" : "regulator",
- pwr_ctr->pwr_ctr.gpio,
- pwr_ctr->pwr_ctr.atv_val,
- pwr_ctr->pwr_ctr.delay);
- }
- }
-
- return 0;
-
-}
-
-int rk_hdmi_pwr_enable(struct hdmi *dev_drv)
-{
- struct list_head *pos;
- struct rk_disp_pwr_ctr_list *pwr_ctr_list;
- struct pwr_ctr *pwr_ctr;
-
- if (list_empty(&dev_drv->pwrlist_head))
- return 0;
-
- list_for_each(pos, &dev_drv->pwrlist_head) {
- pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
- list);
- pwr_ctr = &pwr_ctr_list->pwr_ctr;
- if (pwr_ctr->type == GPIO) {
- gpio_direction_output(pwr_ctr->gpio, pwr_ctr->atv_val);
- mdelay(pwr_ctr->delay);
- if (pwr_ctr->is_rst == 1) {
- if (pwr_ctr->atv_val == 1)
- gpio_set_value(pwr_ctr->gpio, 0);
- else
- gpio_set_value(pwr_ctr->gpio, 1);
-
- mdelay(pwr_ctr->delay);
- }
- }
- }
-
- return 0;
-}
-
-int rk_hdmi_pwr_disable(struct hdmi *dev_drv)
-{
- struct list_head *pos;
- struct rk_disp_pwr_ctr_list *pwr_ctr_list;
- struct pwr_ctr *pwr_ctr;
-
- if (list_empty(&dev_drv->pwrlist_head))
- return 0;
-
- list_for_each(pos, &dev_drv->pwrlist_head) {
- pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
- list);
- pwr_ctr = &pwr_ctr_list->pwr_ctr;
- if (pwr_ctr->type == GPIO) {
- gpio_set_value(pwr_ctr->gpio, pwr_ctr->atv_val);
- if (pwr_ctr->is_rst == 1) {
- if (pwr_ctr->atv_val == 1)
- gpio_set_value(pwr_ctr->gpio, 0);
- else
- gpio_set_value(pwr_ctr->gpio, 1);
- }
- }
- }
-
- return 0;
-}
-
-int rk_hdmi_parse_dt(struct hdmi *hdmi_drv)
-{
- struct device_node *np = hdmi_drv->dev->of_node;
- int ret = 0, gpio = 0;
-
- if (!np) {
- dev_err(hdmi_drv->dev, "could not find hdmi node\n");
- return -1;
- }
-
- gpio = of_get_named_gpio(np, "rockchips,hdmi_irq_gpio", 0);
- if (!gpio_is_valid(gpio))
- dev_info(hdmi_drv->dev, "invalid hdmi_irq_gpio: %d\n", gpio);
- hdmi_drv->irq = gpio;
-
- ret = rk_hdmi_pwr_ctr_parse_dt(hdmi_drv);
-
- return ret;
-}
-
-#else
-int rk_hdmi_pwr_enable(struct hdmi *dev_drv)
-{
- return 0;
-}
-
-int rk_hdmi_pwr_disable(struct hdmi *dev_drv)
-{
- return 0;
-}
-
-int rk_hdmi_parse_dt(struct hdmi *hdmi_drv)
-{
- return 0;
-}
-#endif
+++ /dev/null
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#include <linux/interrupt.h>
-#include "rk_hdmi.h"
-
-static int hdmi_get_enable(struct rk_display_device *device)
-{
- struct hdmi *hdmi = device->priv_data;
- int enable;
-
- mutex_lock(&hdmi->enable_mutex);
- enable = hdmi->enable;
- mutex_unlock(&hdmi->enable_mutex);
-
- return enable;
-}
-
-static int hdmi_set_enable(struct rk_display_device *device, int enable)
-{
- struct hdmi *hdmi = device->priv_data;
-
- mutex_lock(&hdmi->enable_mutex);
- if (hdmi->enable == enable) {
- mutex_unlock(&hdmi->enable_mutex);
- return 0;
- }
- hdmi->enable = enable;
-
- if (hdmi->suspend) {
- mutex_unlock(&hdmi->enable_mutex);
- return 0;
- }
-
- if (enable == 0) {
- if (hdmi->irq)
- disable_irq(hdmi->irq);
- mutex_unlock(&hdmi->enable_mutex);
- hdmi->command = HDMI_CONFIG_ENABLE;
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
- } else {
- if (hdmi->irq)
- enable_irq(hdmi->irq);
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
- mutex_unlock(&hdmi->enable_mutex);
- }
- return 0;
-}
-
-static int hdmi_get_status(struct rk_display_device *device)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (hdmi->hotplug == HDMI_HPD_ACTIVED)
- return 1;
- else
- return 0;
-}
-
-static int hdmi_get_modelist(struct rk_display_device *device,
- struct list_head **modelist)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (!hdmi->hotplug)
- return -1;
- *modelist = &hdmi->edid.modelist;
- return 0;
-}
-
-static int hdmi_set_mode(struct rk_display_device *device,
- struct fb_videomode *mode)
-{
- struct hdmi *hdmi = device->priv_data;
- int vic = hdmi_videomode_to_vic(mode);
-
- hdmi->autoconfig = HDMI_DISABLE;
- if (vic && hdmi->vic != vic) {
- hdmi->vic = vic;
- if (!hdmi->hotplug)
- return 0;
- hdmi->command = HDMI_CONFIG_VIDEO;
- init_completion(&hdmi->complete);
- hdmi->wait = 1;
- queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
- wait_for_completion_interruptible_timeout(&hdmi->complete,
- msecs_to_jiffies
- (10000));
- }
- return 0;
-}
-
-static int hdmi_get_mode(struct rk_display_device *device,
- struct fb_videomode *mode)
-{
- struct hdmi *hdmi = device->priv_data;
- struct fb_videomode *vmode;
-
- if (!hdmi->hotplug)
- return -1;
-
- vmode = (struct fb_videomode *)hdmi_vic_to_videomode(hdmi->vic);
- if (unlikely(vmode == NULL))
- return -1;
- *mode = *vmode;
- return 0;
-}
-
-static int hdmi_set_scale(struct rk_display_device *device, int direction,
- int value)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (!hdmi || value < 0 || value > 100)
- return -1;
-
- if (!hdmi->hotplug)
- return 0;
-
- if (direction == DISPLAY_SCALE_X)
- hdmi->xscale = value;
- else if (direction == DISPLAY_SCALE_Y)
- hdmi->yscale = value;
- else
- return -1;
- rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
- return 0;
-}
-
-static int hdmi_get_scale(struct rk_display_device *device, int direction)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (!hdmi)
- return -1;
-
- if (direction == DISPLAY_SCALE_X)
- return hdmi->xscale;
- else if (direction == DISPLAY_SCALE_Y)
- return hdmi->yscale;
- else
- return -1;
-}
-static int hdmi_set_debug(struct rk_display_device *device, int cmd)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (!hdmi)
- return -1;
- if (hdmi->ops && hdmi->ops->hdmi_debug)
- hdmi->ops->hdmi_debug(hdmi,cmd);
-
- return 0;
-}
-//CEA 861-E: Audio Coding Type
-//sync width enum hdmi_audio_type
-static const char* const sAudioFormatStr[] = {
- "",
- "LPCM", //HDMI_AUDIO_LPCM = 1,
- "AC3", //HDMI_AUDIO_AC3,
- "MPEG1", //HDMI_AUDIO_MPEG1,
- "MP3", //HDMI_AUDIO_MP3,
- "MPEG2", //HDMI_AUDIO_MPEG2,
- "AAC-LC", //HDMI_AUDIO_AAC_LC, //AAC
- "DTS", //HDMI_AUDIO_DTS,
- "ATARC", //HDMI_AUDIO_ATARC,
- "DSD", //HDMI_AUDIO_DSD, //One bit Audio
- "E-AC3", //HDMI_AUDIO_E_AC3,
- "DTS-HD", //HDMI_AUDIO_DTS_HD,
- "MLP", //HDMI_AUDIO_MLP,
- "DST", //HDMI_AUDIO_DST,
- "WMA-PRO", //HDMI_AUDIO_WMA_PRO
-};
-
-static int hdmi_get_edidaudioinfo(struct rk_display_device *device, char *audioinfo, int len)
-{
- struct hdmi *hdmi = device->priv_data;
- int i=0;
- int size=0;
- struct hdmi_audio *audio;
- if(!hdmi)
- return -1;
-
- memset(audioinfo, 0x00, len);
- mutex_lock(&hdmi->lock);
- //printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);
- for(i = 0; i < hdmi->edid.audio_num; i++)
- {
- audio = &(hdmi->edid.audio[i]);
- if(audio->type<1 || audio->type>HDMI_AUDIO_WMA_PRO){
- printk("audio type: unsupported.");
- continue;
- }
- size = strlen(sAudioFormatStr[audio->type]);
- //printk("size: %d, type: %s\n", size, sAudioFormatStr[audio->type]);
- memcpy(audioinfo, sAudioFormatStr[audio->type], size);
- audioinfo[size]=',';
- audioinfo += (size+1);
- }
- mutex_unlock(&hdmi->lock);
- return 0;
-}
-
-
-static int hdmi_get_monspecs(struct rk_display_device *device, struct fb_monspecs *monspecs)
-{
- struct hdmi *hdmi = device->priv_data;
-
- if (!hdmi)
- return -1;
-
- mutex_lock(&hdmi->lock);
- if(hdmi->edid.specs)
- *monspecs = *(hdmi->edid.specs);
- mutex_unlock(&hdmi->lock);
- return 0;
-}
-
-struct rk_display_ops hdmi_display_ops = {
- .setenable = hdmi_set_enable,
- .getenable = hdmi_get_enable,
- .getstatus = hdmi_get_status,
- .getmodelist = hdmi_get_modelist,
- .setmode = hdmi_set_mode,
- .getmode = hdmi_get_mode,
- .setscale = hdmi_set_scale,
- .getscale = hdmi_get_scale,
- .setdebug = hdmi_set_debug,
- .getedidaudioinfo = hdmi_get_edidaudioinfo,
- .getmonspecs = hdmi_get_monspecs,
-};
-
-#if 1
-static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
-{
- device->owner = THIS_MODULE;
- strcpy(device->type, "HDMI");
- device->priority = DISPLAY_PRIORITY_HDMI;
-/*
- device->name = kmalloc(strlen(name), GFP_KERNEL);
- if(device->name)
- strcpy(device->name, name);
-*/
- device->priv_data = devdata;
- device->ops = &hdmi_display_ops;
- return 1;
-}
-
-static struct rk_display_driver display_hdmi = {
- .probe = hdmi_display_probe,
-};
-
-#ifdef CONFIG_DRM_ROCKCHIP
-extern void rk_drm_display_register(struct rk_display_ops *extend_ops,
- void *displaydata, int type);
-#endif
-
-void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
-{
- hdmi->ddev =
- rk_display_device_register(&display_hdmi, parent, hdmi);
-#ifdef CONFIG_DRM_ROCKCHIP
- rk_drm_display_register(&hdmi_display_ops, hdmi, SCREEN_HDMI);
-#endif
-}
-
-void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
-{
- if (hdmi->ddev)
- rk_display_device_unregister(hdmi->ddev);
-}
-#endif
+++ /dev/null
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/rockchip/common.h>
-#include <dt-bindings/clock/rk_system_status.h>
-#include "rk_hdmi.h"
-
-#define HDMI_MAX_TRY_TIMES 1
-#define HDMI_MAX_ID 1
-
-static char *envp[] = { "INTERFACE=HDMI", NULL };
-static int uboot_vic=-1;
-static void hdmi_sys_show_state(struct hdmi *hdmi)
-{
- switch (hdmi->state) {
- case HDMI_SLEEP:
- hdmi_dbg(hdmi->dev, "HDMI_SLEEP\n");
- break;
- case HDMI_INITIAL:
- hdmi_dbg(hdmi->dev, "HDMI_INITIAL\n");
- break;
- case WAIT_HOTPLUG:
- hdmi_dbg(hdmi->dev, "WAIT_HOTPLUG\n");
- break;
- case READ_PARSE_EDID:
- hdmi_dbg(hdmi->dev, "READ_PARSE_EDID\n");
- break;
- case WAIT_HDMI_ENABLE:
- hdmi_dbg(hdmi->dev, "WAIT_HDMI_ENABLE\n");
- break;
- case SYSTEM_CONFIG:
- hdmi_dbg(hdmi->dev, "SYSTEM_CONFIG\n");
- break;
- case CONFIG_VIDEO:
- hdmi_dbg(hdmi->dev, "CONFIG_VIDEO\n");
- break;
- case CONFIG_AUDIO:
- hdmi_dbg(hdmi->dev, "CONFIG_AUDIO\n");
- break;
- case PLAY_BACK:
- hdmi_dbg(hdmi->dev, "PLAY_BACK\n");
- break;
- default:
- hdmi_dbg(hdmi->dev, "Unkown State %d\n", hdmi->state);
- break;
- }
-}
-
-int hdmi_sys_init(struct hdmi *hdmi)
-{
- if (uboot_vic > 0) {
- hdmi->uboot_logo = support_uboot_display();
- hdmi->hotplug = HDMI_HPD_ACTIVED;
- hdmi->state = PLAY_BACK;
- hdmi->enable = HDMI_ENABLE;
- hdmi->display = HDMI_DISABLE;
- hdmi->vic = uboot_vic;
- } else {
- hdmi->hotplug = HDMI_HPD_REMOVED;
- hdmi->state = HDMI_SLEEP;
- hdmi->enable = HDMI_ENABLE;
- hdmi->display = HDMI_DISABLE;
- hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
- hdmi->uboot_logo = 0;
- }
- hdmi_dbg(hdmi->dev, "uboot-logo=%d,uboot_vic=%d\n",hdmi->uboot_logo,uboot_vic);
- hdmi->autoconfig = HDMI_AUTO_CONFIGURE;
- hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
- hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
- hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
-
- memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
- INIT_LIST_HEAD(&hdmi->edid.modelist);
- mutex_init(&hdmi->lock);
- return 0;
-}
-
-void hdmi_sys_remove(struct hdmi *hdmi)
-{
- int audio_need;
-
- audio_need = hdmi->edid.base_audio_support == 1 &&
- hdmi->edid.sink_hdmi == 1;
-
- fb_destroy_modelist(&hdmi->edid.modelist);
- kfree(hdmi->edid.audio);
- if (hdmi->edid.specs) {
- kfree(hdmi->edid.specs->modedb);
- kfree(hdmi->edid.specs);
- }
- memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
- INIT_LIST_HEAD(&hdmi->edid.modelist);
- hdmi->display = HDMI_DISABLE;
- if (hdmi->set_vif)
- hdmi->set_vif(hdmi, hdmi->lcdc->cur_screen, 0);
- rk_fb_switch_screen(hdmi->lcdc->cur_screen, 0, hdmi->lcdc->id);
- kobject_uevent_env(&hdmi->ddev->dev->kobj, KOBJ_REMOVE, envp);
-
-#ifdef CONFIG_SWITCH
- if (audio_need ||
- rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
- switch_set_state(&(hdmi->switch_hdmi), 0);
-#endif
- rockchip_clear_system_status(SYS_STATUS_HDMI);
-}
-
-static void hdmi_sys_sleep(struct hdmi *hdmi)
-{
- mutex_lock(&hdmi->enable_mutex);
- if (hdmi->enable && hdmi->irq)
- disable_irq(hdmi->irq);
- hdmi->state = HDMI_SLEEP;
- hdmi->remove(hdmi);
- if (hdmi->enable && hdmi->irq)
- enable_irq(hdmi->irq);
- mutex_unlock(&hdmi->enable_mutex);
-}
-
-static int hdmi_process_command(struct hdmi *hdmi)
-{
- int change, state = hdmi->state;
-
- change = hdmi->command;
- if (change != HDMI_CONFIG_NONE) {
- hdmi->command = HDMI_CONFIG_NONE;
- switch (change) {
- case HDMI_CONFIG_ENABLE:
- /* disable HDMI */
- mutex_lock(&hdmi->enable_mutex);
- if (!hdmi->enable || hdmi->suspend) {
- if (hdmi->hotplug != HDMI_HPD_REMOVED) {
- hdmi->hotplug = HDMI_HPD_REMOVED;
- hdmi->control_output(hdmi, HDMI_DISABLE);
- hdmi_sys_remove(hdmi);
- }
- hdmi->state = HDMI_SLEEP;
- hdmi->remove(hdmi);
- state = HDMI_SLEEP;
- }
- mutex_unlock(&hdmi->enable_mutex);
- if (hdmi->wait == 1) {
- complete(&hdmi->complete);
- hdmi->wait = 0;
- }
- break;
- case HDMI_CONFIG_COLOR:
- if (state > CONFIG_VIDEO)
- state = CONFIG_VIDEO;
- break;
- case HDMI_CONFIG_HDCP:
- break;
- case HDMI_CONFIG_DISPLAY:
- break;
- case HDMI_CONFIG_AUDIO:
- if (state > CONFIG_AUDIO)
- state = CONFIG_AUDIO;
- break;
- case HDMI_CONFIG_VIDEO:
- default:
- if (state > SYSTEM_CONFIG) {
- state = SYSTEM_CONFIG;
- hdmi->control_output(hdmi, HDMI_DISABLE);
- msleep(2000);
- } else {
- if (hdmi->wait == 1) {
- complete(&hdmi->complete);
- hdmi->wait = 0;
- }
- }
- break;
- }
- } else if (state == HDMI_SLEEP) {
- state = WAIT_HOTPLUG;
- }
- return state;
-}
-
-static DEFINE_MUTEX(work_mutex);
-
-void hdmi_work(struct work_struct *work)
-{
- int hotplug, state_last;
- int rc = HDMI_ERROR_SUCESS, trytimes = 0;
- struct hdmi_video_para video;
- struct delayed_work *delay_work =
- container_of(work, struct delayed_work, work);
- struct hdmi *hdmi = container_of(delay_work, struct hdmi, delay_work);
- int command = hdmi->command;
-
- mutex_lock(&work_mutex);
- /* Process hdmi command */
- hdmi->state = hdmi_process_command(hdmi);
-
- if (!hdmi->enable || hdmi->suspend) {
- mutex_unlock(&work_mutex);
- return;
- }
- hotplug = hdmi->detect_hotplug(hdmi);
- hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __func__,
- hotplug, hdmi->hotplug);
-
- if (hotplug != hdmi->hotplug) {
- if (hotplug == HDMI_HPD_ACTIVED) {
- if (hdmi->insert)
- hdmi->insert(hdmi);
- hdmi->state = READ_PARSE_EDID;
- } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
- hdmi->hotplug = hotplug;
- hdmi_sys_remove(hdmi);
- if (hotplug == HDMI_HPD_REMOVED) {
- hdmi_sys_sleep(hdmi);
- } else {
- hdmi->state = WAIT_HOTPLUG;
- hdmi->remove(hdmi);
- }
- if (hdmi->wait == 1) {
- complete(&hdmi->complete);
- hdmi->wait = 0;
- }
- mutex_unlock(&work_mutex);
- return;
- } else if (hotplug == HDMI_HPD_REMOVED) {
- hdmi->state = HDMI_SLEEP;
- hdmi->remove(hdmi);
- }
- hdmi->hotplug = hotplug;
- } else if (hotplug == HDMI_HPD_REMOVED) {
- hdmi_sys_sleep(hdmi);
- } else if (hotplug == HDMI_HPD_ACTIVED) {
- if (hdmi->uboot_logo) {
- if (hdmi->insert)
- hdmi->insert(hdmi);
- hdmi->state = READ_PARSE_EDID;
- }
- }
-
- do {
- hdmi_sys_show_state(hdmi);
- state_last = hdmi->state;
- switch (hdmi->state) {
- case READ_PARSE_EDID:
- rc = hdmi_sys_parse_edid(hdmi);
- if (rc == HDMI_ERROR_SUCESS) {
- if (hdmi->cec_set_device_pa)
- hdmi->cec_set_device_pa(hdmi->edid.cecaddress);
- if (hdmi->cec_enumerate)
- hdmi->cec_enumerate();
- hdmi->state = SYSTEM_CONFIG;
- kobject_uevent_env(&hdmi->ddev->dev->kobj,
- KOBJ_ADD, envp);
- hdmi_dbg(hdmi->dev,
- "[%s] base_audio_support =%d,sink_hdmi = %d\n",
- __func__,
- hdmi->edid.base_audio_support,
- hdmi->edid.sink_hdmi);
-#ifdef CONFIG_SWITCH
- if ((hdmi->edid.base_audio_support == 1 &&
- hdmi->edid.sink_hdmi == 1) ||
- (rk_fb_get_display_policy() ==
- DISPLAY_POLICY_BOX))
- switch_set_state(&(hdmi->switch_hdmi),
- 1);
-#endif
- rockchip_set_system_status(SYS_STATUS_HDMI);
- }
-
- break;
- case SYSTEM_CONFIG:
- if ((hdmi->remove) && !hdmi->uboot_logo)
- hdmi->remove(hdmi);
-
- if (hdmi->autoconfig)
- hdmi->vic = hdmi_find_best_mode(hdmi, 0);
- else
- hdmi->vic =
- hdmi_find_best_mode(hdmi, hdmi->vic);
- rc = hdmi_switch_fb(hdmi, hdmi->vic);
- if (rc == HDMI_ERROR_SUCESS)
- hdmi->state = CONFIG_VIDEO;
- if (hdmi->uboot_logo) {
- hdmi->state = CONFIG_AUDIO;
- }
-
- /* whether switch resolution */
- if (command == HDMI_CONFIG_VIDEO)
- kobject_uevent_env(&hdmi->ddev->dev->kobj,
- KOBJ_CHANGE, envp);
- break;
- case CONFIG_VIDEO:
- hdmi->display = HDMI_DISABLE;
- hdmi_init_video_para(hdmi, &video);
- rc = hdmi->config_video(hdmi, &video);
- if (rc == HDMI_ERROR_SUCESS) {
- if (hdmi->edid.sink_hdmi)
- hdmi->state = CONFIG_AUDIO;
- else
- hdmi->state = PLAY_BACK;
- }
- break;
- case CONFIG_AUDIO:
- rc = hdmi->config_audio(hdmi, &(hdmi->audio));
-
- if (rc == HDMI_ERROR_SUCESS)
- hdmi->state = PLAY_BACK;
- break;
- case PLAY_BACK:
- if (hdmi->display != HDMI_ENABLE) {
- hdmi->control_output(hdmi, HDMI_ENABLE);
- hdmi->display = HDMI_ENABLE;
- if (hdmi->hdcp_cb)
- hdmi->hdcp_cb();
- }
-
- if (hdmi->wait == 1) {
- complete(&hdmi->complete);
- hdmi->wait = 0;
- }
- break;
- default:
- break;
- }
- if (rc != HDMI_ERROR_SUCESS) {
- trytimes++;
- msleep(20);
- }
- if (hdmi->state != state_last)
- trytimes = 0;
-
- } while ((hdmi->state != state_last ||
- (rc != HDMI_ERROR_SUCESS)) &&
- trytimes < HDMI_MAX_TRY_TIMES);
- hdmi_dbg(hdmi->dev, "[%s] done\n", __func__);
- mutex_unlock(&work_mutex);
-}
-
-static int __init bootloader_setup(char *str)
-{
- if(str) {
- printk("hdmi init vic is %s\n", str);
- sscanf(str, "%d", &uboot_vic);
- }
- /*uboot_vic = 16;*/
- return 0;
-}
-early_param("hdmi.vic", bootloader_setup);
--- /dev/null
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include "rockchip-hdmi-cec.h"
+
+static struct cec_device *cec_dev;
+struct input_dev *devinput;
+static struct miscdevice mdev;
+
+int key_table[] = {
+ KEY_UP,
+ KEY_DOWN,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_REPLY,
+ KEY_BACK,
+ KEY_POWER,
+};
+
+static void cecmenucontrol(int uitemp);
+
+static int cecreadframe(struct cec_framedata *frame)
+{
+ if (frame == NULL || !cec_dev || cec_dev->readframe == NULL)
+ return -1;
+ else
+ return cec_dev->readframe(cec_dev->hdmi, frame);
+}
+
+static int cecsendframe(struct cec_framedata *frame)
+{
+ if (frame == NULL || !cec_dev || cec_dev->readframe == NULL)
+ return -1;
+ else
+ return cec_dev->sendframe(cec_dev->hdmi, frame);
+}
+
+static int cecsendping(char logicaddress)
+{
+ struct cec_framedata cecframe;
+
+ memset(&cecframe, 0, sizeof(struct cec_framedata));
+ cecframe.srcdestaddr = logicaddress << 4 | logicaddress;
+ return cec_dev->sendframe(cec_dev->hdmi, &cecframe);
+}
+
+/*static int CecSendMessage (char opCode, char dest)
+{
+ struct cec_framedata cecframe;
+
+ cecframe.opcode = opCode;
+ cecframe.srcdestaddr = MAKE_SRCDEST(cec_dev->address_logic, dest);
+ cecframe.argcount = 0;
+
+ return cecsendframe(&cecframe);
+}*/
+
+
+/*static void CecSendFeatureAbort (struct cec_framedata *pcpi, char reason)
+{
+ struct cec_framedata cecframe;
+
+ if ((pcpi->srcdestaddr & 0x0F) != CEC_LOGADDR_UNREGORBC) {
+ cecframe.opcode = CECOP_FEATURE_ABORT;
+ cecframe.srcdestaddr = MAKE_SRCDEST( cec_dev->address_logic,
+ ( pcpi->srcdestaddr & 0xF0) >> 4 );
+ cecframe.args[0] = pcpi->opcode;
+ cecframe.args[1] = reason;
+ cecframe.argcount = 2;
+ cecsendframe(&cecframe);
+ }
+}*/
+
+static void cecsendimageview(void)
+{
+ struct cec_framedata cecframe;
+
+ cecframe.opcode = CECOP_IMAGE_VIEW_ON;
+ cecframe.srcdestaddr = MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.argcount = 0;
+ cecsendframe(&cecframe);
+}
+
+static void cecsendactivesource(void)
+{
+ struct cec_framedata cecframe;
+
+ cecframe.opcode = CECOP_ACTIVE_SOURCE;
+ cecframe.srcdestaddr = MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.args[0] = (cec_dev->address_phy & 0xFF00) >> 8;
+ cecframe.args[1] = (cec_dev->address_phy & 0x00FF);
+ cecframe.argcount = 2;
+ cecsendframe(&cecframe);
+}
+
+static void cechandleinactivesource(struct cec_framedata *pcpi)
+{
+}
+
+static void cechandlefeatureabort(struct cec_framedata *pcpi)
+{
+}
+
+static bool validatececmessage(struct cec_framedata *pcpi)
+{
+ char parametercount = 0;
+ bool countok = true;
+
+ /* Determine required parameter count */
+
+ switch (pcpi->opcode) {
+ case CECOP_IMAGE_VIEW_ON:
+ case CECOP_TEXT_VIEW_ON:
+ case CECOP_STANDBY:
+ case CECOP_GIVE_PHYSICAL_ADDRESS:
+ case CECOP_GIVE_DEVICE_POWER_STATUS:
+ case CECOP_GET_MENU_LANGUAGE:
+ case CECOP_GET_CEC_VERSION:
+ parametercount = 0;
+ break;
+ case CECOP_REPORT_POWER_STATUS: /* power status*/
+ case CECOP_CEC_VERSION: /* cec version*/
+ parametercount = 1;
+ break;
+ case CECOP_INACTIVE_SOURCE: /* physical address*/
+ case CECOP_FEATURE_ABORT:
+ case CECOP_ACTIVE_SOURCE: /* physical address*/
+ parametercount = 2;
+ break;
+ case CECOP_REPORT_PHYSICAL_ADDRESS:
+ case CECOP_DEVICE_VENDOR_ID: /* vendor id*/
+ parametercount = 3;
+ break;
+ case CECOP_SET_OSD_NAME: /* osd name (1-14 bytes)*/
+ case CECOP_SET_OSD_STRING:
+ parametercount = 1; /* must have a minimum of 1 operands*/
+ break;
+ case CECOP_ABORT:
+ break;
+ case CECOP_ARC_INITIATE:
+ break;
+ case CECOP_ARC_REPORT_INITIATED:
+ break;
+ case CECOP_ARC_REPORT_TERMINATED:
+ break;
+ case CECOP_ARC_REQUEST_INITIATION:
+ break;
+ case CECOP_ARC_REQUEST_TERMINATION:
+ break;
+ case CECOP_ARC_TERMINATE:
+ break;
+ default:
+ break;
+ }
+
+ /* Test for correct parameter count. */
+
+ if (pcpi->argcount < parametercount)
+ countok = false;
+
+ return countok;
+}
+
+static bool cecrxmsghandlerlast(struct cec_framedata *pcpi)
+{
+ bool isdirectaddressed;
+ struct cec_framedata cecframe;
+
+ isdirectaddressed = !((pcpi->srcdestaddr & 0x0F) ==
+ CEC_LOGADDR_UNREGORBC);
+ pr_info("isDirectAddressed %d\n", (int)isdirectaddressed);
+ if (validatececmessage(pcpi)) {
+ /* If invalid message, ignore it, but treat it as handled */
+ if (isdirectaddressed) {
+ switch (pcpi->opcode) {
+ case CECOP_USER_CONTROL_PRESSED:
+ cecmenucontrol(pcpi->args[0]);
+ break;
+
+ case CECOP_VENDOR_REMOTE_BUTTON_DOWN:
+ cecmenucontrol(pcpi->args[0]);
+ break;
+ case CECOP_FEATURE_ABORT:
+ cechandlefeatureabort(pcpi);
+ break;
+
+ case CECOP_GIVE_OSD_NAME:
+ cecframe.opcode = CECOP_SET_OSD_NAME;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_TV);
+ cecframe.args[0] = 'r';
+ cecframe.args[1] = 'k';
+ cecframe.args[2] = '-';
+ cecframe.args[3] = 'b';
+ cecframe.args[4] = 'o';
+ cecframe.args[5] = 'x';
+ cecframe.argcount = 6;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_VENDOR_COMMAND_WITH_ID:
+
+ if (pcpi->args[2] == 00) {
+ cecframe.opcode = CECOP_SET_OSD_NAME;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_TV);
+ cecframe.args[0] = '1';
+ cecframe.args[1] = '1';
+ cecframe.args[2] = '1';
+ cecframe.args[3] = '1';
+ cecframe.args[4] = '1';
+ cecframe.args[5] = '1';
+ cecframe.argcount = 6;
+ cecsendframe(&cecframe);
+ }
+ break;
+ case CECOP_IMAGE_VIEW_ON:
+ case CECOP_TEXT_VIEW_ON:
+ /* In our case, respond the same to both these messages*/
+ break;
+
+ case CECOP_GIVE_DEVICE_VENDOR_ID:
+ cecframe.opcode = CECOP_DEVICE_VENDOR_ID;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.args[0] = 0x1;
+ cecframe.args[1] = 0x2;
+ cecframe.args[2] = 0x3;
+ cecframe.argcount = 3;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_STANDBY: /* Direct and Broadcast*/
+ /* Setting this here will let the main task know */
+ /* (via SI_CecGetPowerState) and at the same time */
+ /* prevent us from broadcasting a STANDBY message */
+ /* of our own when the main task responds by */
+ /* calling SI_CecSetPowerState( STANDBY ); */
+ cec_dev->powerstatus = CEC_POWERSTATUS_STANDBY;
+ break;
+
+ case CECOP_INACTIVE_SOURCE:
+ cechandleinactivesource(pcpi);
+ break;
+
+ case CECOP_GIVE_PHYSICAL_ADDRESS:
+
+ cecframe.opcode = CECOP_REPORT_PHYSICAL_ADDRESS;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.args[0] = (cec_dev->address_phy&0xFF00)>>8;
+ cecframe.args[1] = (cec_dev->address_phy&0x00FF);
+ cecframe.args[2] = cec_dev->address_logic;
+ cecframe.argcount = 3;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_GIVE_DEVICE_POWER_STATUS:
+ /* TV responds with power status. */
+
+ cecframe.opcode = CECOP_REPORT_POWER_STATUS;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ (pcpi->srcdestaddr & 0xF0) >> 4);
+ cec_dev->powerstatus = 0x00;
+ cecframe.args[0] = cec_dev->powerstatus;
+ cecframe.argcount = 1;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_GET_MENU_LANGUAGE:
+ /* TV Responds with a Set Menu language command. */
+
+ cecframe.opcode = CECOP_SET_MENU_LANGUAGE;
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.args[0] = 'e';
+ cecframe.args[1] = 'n';
+ cecframe.args[2] = 'g';
+ cecframe.argcount = 3;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_GET_CEC_VERSION:
+ /* TV responds to this request with it's CEC version support.*/
+
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_TV);
+ cecframe.opcode = CECOP_CEC_VERSION;
+ cecframe.args[0] = 0x05; /* Report CEC1.4b*/
+ cecframe.argcount = 1;
+ cecsendframe(&cecframe);
+ break;
+
+ case CECOP_REPORT_POWER_STATUS:
+ /*Someone sent us their power state.
+
+ l_sourcePowerStatus = pcpi->args[0];
+
+ let NEW SOURCE task know about it.
+
+ if ( l_cecTaskState.task == SI_CECTASK_NEWSOURCE )
+ {
+ l_cecTaskState.cpiState = CPI_RESPONSE;
+ }*/
+ break;
+
+ /* Do not reply to directly addressed 'Broadcast' msgs. */
+ case CECOP_REQUEST_ACTIVE_SOURCE:
+ cecsendactivesource();
+ break;
+
+ case CECOP_ACTIVE_SOURCE:
+ case CECOP_REPORT_PHYSICAL_ADDRESS:
+ case CECOP_ROUTING_CHANGE:
+ case CECOP_ROUTING_INFORMATION:
+ case CECOP_SET_STREAM_PATH:
+ case CECOP_SET_MENU_LANGUAGE:
+ case CECOP_DEVICE_VENDOR_ID:
+ break;
+
+ case CECOP_ABORT:
+ break;
+ default:
+ /*CecSendFeatureAbort(pcpi, CECAR_UNRECOG_OPCODE);*/
+ break;
+ }
+ } else {
+ /* Respond to broadcast messages. */
+ switch (pcpi->opcode) {
+ case CECOP_STANDBY:
+ /* Setting this here will let the main task know */
+ /* (via SI_CecGetPowerState) and at the same time */
+ /* prevent us from broadcasting a STANDBY message */
+ /* of our own when the main task responds by */
+ /* calling SI_CecSetPowerState( STANDBY ); */
+ cec_dev->powerstatus = CEC_POWERSTATUS_STANDBY;
+ input_event(devinput, EV_KEY, KEY_POWER, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_POWER, 0);
+ input_sync(devinput);
+ break;
+
+ case CECOP_ACTIVE_SOURCE:
+ /*CecHandleActiveSource( pcpi );*/
+ break;
+
+ case CECOP_REPORT_PHYSICAL_ADDRESS:
+ /*CecHandleReportPhysicalAddress( pcpi );*/
+ cecframe.srcdestaddr =
+ MAKE_SRCDEST(cec_dev->address_logic,
+ CEC_LOGADDR_UNREGORBC);
+ cecframe.opcode = CECOP_CEC_VERSION;
+ cecframe.args[0] = 0x05; /* CEC1.4b*/
+ cecframe.argcount = 1;
+ cecsendframe(&cecframe);
+ break;
+
+ /* Do not reply to 'Broadcast' msgs that we don't need.*/
+ case CECOP_REQUEST_ACTIVE_SOURCE:
+ cecsendactivesource();
+ break;
+ case CECOP_ROUTING_CHANGE:
+ case CECOP_ROUTING_INFORMATION:
+ case CECOP_SET_STREAM_PATH:
+ case CECOP_SET_MENU_LANGUAGE:
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void cecenumeration(void)
+{
+ char logicaddress[3] = {CEC_LOGADDR_PLAYBACK1,
+ CEC_LOGADDR_PLAYBACK2,
+ CEC_LOGADDR_PLAYBACK3};
+ int i;
+
+ if (!cec_dev)
+ return;
+
+ for (i = 0; i < 3; i++) {
+ if (cecsendping(logicaddress[i])) {
+ cec_dev->address_logic = logicaddress[i];
+ CECDBG("Logic Address is 0x%x\n",
+ cec_dev->address_logic);
+ break;
+ }
+ }
+ if (i == 3)
+ cec_dev->address_logic = CEC_LOGADDR_UNREGORBC;
+ cec_dev->setceclogicaddr(cec_dev->hdmi, cec_dev->address_logic);
+ cecsendimageview();
+ cecsendactivesource();
+}
+
+static void cecworkfunc(struct work_struct *work)
+{
+ struct cec_delayed_work *cec_w =
+ container_of(work, struct cec_delayed_work, work.work);
+ struct cec_framedata cecframe;
+
+ switch (cec_w->event) {
+ case EVENT_ENUMERATE:
+ cecenumeration();
+ break;
+ case EVENT_RX_FRAME:
+ memset(&cecframe, 0, sizeof(struct cec_framedata));
+ cecreadframe(&cecframe);
+ cecrxmsghandlerlast(&cecframe);
+ break;
+ default:
+ break;
+ }
+
+ kfree(cec_w->data);
+ kfree(cec_w);
+}
+
+void rockchip_hdmi_cec_submit_work(int event, int delay, void *data)
+{
+ struct cec_delayed_work *work;
+
+ CECDBG("%s event %04x delay %d\n", __func__, event, delay);
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+ if (work) {
+ INIT_DELAYED_WORK(&work->work, cecworkfunc);
+ work->event = event;
+ work->data = data;
+ queue_delayed_work(cec_dev->workqueue,
+ &work->work,
+ msecs_to_jiffies(delay));
+ } else {
+ CECDBG(KERN_WARNING "CEC: Cannot allocate memory\n");
+ }
+}
+
+void rockchip_hdmi_cec_set_pa(int devpa)
+{
+ if (cec_dev)
+ cec_dev->address_phy = devpa;
+ cecenumeration();
+}
+
+static int cec_input_device_init(void)
+{
+ int err, i;
+
+ devinput = input_allocate_device();
+ if (!devinput)
+ return -ENOMEM;
+ devinput->name = "hdmi_cec_key";
+ /*devinput->dev.parent = &client->dev;*/
+ devinput->phys = "hdmi_cec_key/input0";
+ devinput->id.bustype = BUS_HOST;
+ devinput->id.vendor = 0x0001;
+ devinput->id.product = 0x0001;
+ devinput->id.version = 0x0100;
+ err = input_register_device(devinput);
+ if (err < 0) {
+ input_free_device(devinput);
+ CECDBG("%s input device error", __func__);
+ return err;
+ }
+ for (i = 0; i < (sizeof(key_table)/sizeof(int)); i++)
+ input_set_capability(devinput, EV_KEY, key_table[i]);
+ return 0;
+}
+
+static void cecmenucontrol(int uitemp)
+{
+ switch (uitemp) {
+ case S_CEC_MAKESURE: /*make sure*/
+ CECDBG("CEC UIcommand makesure\n");
+ input_event(devinput, EV_KEY, KEY_REPLY, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_REPLY, 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_UP: /*up*/
+ CECDBG("CEC UIcommand up\n");
+ input_event(devinput, EV_KEY, KEY_UP, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_UP, 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_DOWN: /*down*/
+ CECDBG("CEC UIcommand down\n");
+ input_event(devinput, EV_KEY, KEY_DOWN, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_DOWN, 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_LEFT: /*left*/
+ CECDBG("CEC UIcommand left\n");
+ input_event(devinput, EV_KEY, KEY_LEFT , 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_LEFT , 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_RIGHT: /*right*/
+ CECDBG("CEC UIcommand right\n");
+ input_event(devinput, EV_KEY, KEY_RIGHT, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_RIGHT, 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_BACK: /*back*/
+ CECDBG("CEC UIcommand back\n");
+ input_event(devinput, EV_KEY, KEY_BACK, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_BACK, 0);
+ input_sync(devinput);
+ break;
+ case S_CEC_VENDORBACK:
+ CECDBG("CEC UIcommand vendor back\n");
+ input_event(devinput, EV_KEY, KEY_BACK, 1);
+ input_sync(devinput);
+ input_event(devinput, EV_KEY, KEY_BACK, 0);
+ input_sync(devinput);
+ break;
+ }
+}
+
+
+static ssize_t cec_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", cec_dev->cecval);
+}
+
+static ssize_t cec_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = sscanf(buf, "%s", cec_dev->cecval);
+ return strnlen(buf, PAGE_SIZE);
+}
+
+static struct device_attribute cec_control_attr = {
+ .attr = {.name = "cec", .mode = 0666},
+ .show = cec_show,
+ .store = cec_store,
+};
+
+int rockchip_hdmi_cec_init(struct hdmi *hdmi,
+ int (*sendframe)(struct hdmi *,
+ struct cec_framedata *),
+ int (*readframe)(struct hdmi *,
+ struct cec_framedata *),
+ void (*setceclogicaddr)(struct hdmi *, int))
+{
+ int ret;
+ static int cecmicsdevflag = 1;
+
+ mdev.minor = MISC_DYNAMIC_MINOR;
+ mdev.name = "cec";
+ mdev.mode = 0666;
+ cec_dev = kmalloc(sizeof(*cec_dev), GFP_KERNEL);
+ if (!cec_dev) {
+ pr_err("HDMI CEC: kmalloc fail!");
+ return -ENOMEM;
+ }
+ memset(cec_dev, 0, sizeof(struct cec_device));
+ cec_dev->hdmi = hdmi;
+ cec_dev->cecval[0] = '1';
+ cec_dev->cecval[1] = '\0';
+ cec_dev->sendframe = sendframe;
+ cec_dev->readframe = readframe;
+ cec_dev->setceclogicaddr = setceclogicaddr;
+ cec_dev->workqueue = create_singlethread_workqueue("hdmi-cec");
+ if (cec_dev->workqueue == NULL) {
+ pr_err("HDMI CEC: create workqueue failed.\n");
+ return -1;
+ }
+ if (cecmicsdevflag) {
+ cec_input_device_init();
+ if (misc_register(&mdev)) {
+ pr_err("CEC: Could not add cec misc driver\n");
+ goto error;
+ }
+
+ ret = device_create_file(mdev.this_device, &cec_control_attr);
+ if (ret) {
+ pr_err("CEC: Could not add sys file enable\n");
+ goto error1;
+ }
+ cecmicsdevflag = 0;
+ }
+ return 0;
+
+error1:
+ misc_deregister(&mdev);
+error:
+ ret = -EINVAL;
+ return ret;
+}
--- /dev/null
+#ifndef __ROCKCHIP_HDMI_CEC_H__
+#define __ROCKCHIP_HDMI_CEC_H__
+#include "rockchip-hdmi.h"
+
+#include <linux/input.h>
+
+enum {
+ CEC_LOGADDR_TV = 0x00,
+ CEC_LOGADDR_RECDEV1 = 0x01,
+ CEC_LOGADDR_RECDEV2 = 0x02,
+ CEC_LOGADDR_TUNER1 = 0x03, /* STB1 in Spev v1.3 */
+ CEC_LOGADDR_PLAYBACK1 = 0x04, /* DVD1 in Spev v1.3 */
+ CEC_LOGADDR_AUDSYS = 0x05,
+ CEC_LOGADDR_TUNER2 = 0x06, /* STB2 in Spec v1.3 */
+ CEC_LOGADDR_TUNER3 = 0x07, /* STB3 in Spec v1.3 */
+ CEC_LOGADDR_PLAYBACK2 = 0x08, /* DVD2 in Spec v1.3 */
+ CEC_LOGADDR_RECDEV3 = 0x09,
+ CEC_LOGADDR_TUNER4 = 0x0A, /* RES1 in Spec v1.3 */
+ CEC_LOGADDR_PLAYBACK3 = 0x0B, /* RES2 in Spec v1.3 */
+ CEC_LOGADDR_RES3 = 0x0C,
+ CEC_LOGADDR_RES4 = 0x0D,
+ CEC_LOGADDR_FREEUSE = 0x0E,
+ CEC_LOGADDR_UNREGORBC = 0x0F
+
+};
+
+enum { /* CEC Messages */
+ CECOP_FEATURE_ABORT = 0x00,
+ CECOP_IMAGE_VIEW_ON = 0x04,
+ CECOP_TUNER_STEP_INCREMENT = 0x05,
+ CECOP_TUNER_STEP_DECREMENT = 0x06,
+ CECOP_TUNER_DEVICE_STATUS = 0x07,
+ CECOP_GIVE_TUNER_DEVICE_STATUS = 0x08,
+ CECOP_RECORD_ON = 0x09,
+ CECOP_RECORD_STATUS = 0x0A,
+ CECOP_RECORD_OFF = 0x0B,
+ CECOP_TEXT_VIEW_ON = 0x0D,
+ CECOP_RECORD_TV_SCREEN = 0x0F,
+ CECOP_GIVE_DECK_STATUS = 0x1A,
+ CECOP_DECK_STATUS = 0x1B,
+ CECOP_SET_MENU_LANGUAGE = 0x32,
+ CECOP_CLEAR_ANALOGUE_TIMER = 0x33, /* Spec 1.3A */
+ CECOP_SET_ANALOGUE_TIMER = 0x34, /* Spec 1.3A */
+ CECOP_TIMER_STATUS = 0x35, /* Spec 1.3A */
+ CECOP_STANDBY = 0x36,
+ CECOP_PLAY = 0x41,
+ CECOP_DECK_CONTROL = 0x42,
+ CECOP_TIMER_CLEARED_STATUS = 0x43, /* Spec 1.3A */
+ CECOP_USER_CONTROL_PRESSED = 0x44,
+ CECOP_USER_CONTROL_RELEASED = 0x45,
+ CECOP_GIVE_OSD_NAME = 0x46,
+ CECOP_SET_OSD_NAME = 0x47,
+ CECOP_SET_OSD_STRING = 0x64,
+ CECOP_SET_TIMER_PROGRAM_TITLE = 0x67, /* Spec 1.3A */
+ CECOP_SYSTEM_AUDIO_MODE_REQUEST = 0x70, /* Spec 1.3A */
+ CECOP_GIVE_AUDIO_STATUS = 0x71, /* Spec 1.3A */
+ CECOP_SET_SYSTEM_AUDIO_MODE = 0x72, /* Spec 1.3A */
+ CECOP_REPORT_AUDIO_STATUS = 0x7A, /* Spec 1.3A */
+ CECOP_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, /* Spec 1.3A */
+ CECOP_SYSTEM_AUDIO_MODE_STATUS = 0x7E, /* Spec 1.3A */
+ CECOP_ROUTING_CHANGE = 0x80,
+ CECOP_ROUTING_INFORMATION = 0x81,
+ CECOP_ACTIVE_SOURCE = 0x82,
+ CECOP_GIVE_PHYSICAL_ADDRESS = 0x83,
+ CECOP_REPORT_PHYSICAL_ADDRESS = 0x84,
+ CECOP_REQUEST_ACTIVE_SOURCE = 0x85,
+ CECOP_SET_STREAM_PATH = 0x86,
+ CECOP_DEVICE_VENDOR_ID = 0x87,
+ CECOP_VENDOR_COMMAND = 0x89,
+ CECOP_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+ CECOP_VENDOR_REMOTE_BUTTON_UP = 0x8B,
+ CECOP_GIVE_DEVICE_VENDOR_ID = 0x8C,
+ CECOP_MENU_REQUEST = 0x8D,
+ CECOP_MENU_STATUS = 0x8E,
+ CECOP_GIVE_DEVICE_POWER_STATUS = 0x8F,
+ CECOP_REPORT_POWER_STATUS = 0x90,
+ CECOP_GET_MENU_LANGUAGE = 0x91,
+ CECOP_SELECT_ANALOGUE_SERVICE = 0x92, /* Spec 1.3A */
+ CECOP_SELECT_DIGITAL_SERVICE = 0x93,
+ CECOP_SET_DIGITAL_TIMER = 0x97, /* Spec 1.3A */
+ CECOP_CLEAR_DIGITAL_TIMER = 0x99, /* Spec 1.3A */
+ CECOP_SET_AUDIO_RATE = 0x9A, /* Spec 1.3A */
+ CECOP_INACTIVE_SOURCE = 0x9D, /* Spec 1.3A */
+ CECOP_CEC_VERSION = 0x9E, /* Spec 1.3A */
+ CECOP_GET_CEC_VERSION = 0x9F, /* Spec 1.3A */
+ CECOP_VENDOR_COMMAND_WITH_ID = 0xA0, /* Spec 1.3A */
+ CECOP_CLEAR_EXTERNAL_TIMER = 0xA1, /* Spec 1.3A */
+ CECOP_SET_EXTERNAL_TIMER = 0xA2, /* Spec 1.3A */
+ CDCOP_HEADER = 0xF8,
+ CECOP_ABORT = 0xFF,
+
+ CECOP_REPORT_SHORT_AUDIO = 0xA3, /* Spec 1.4 */
+ CECOP_REQUEST_SHORT_AUDIO = 0xA4, /* Spec 1.4 */
+
+ CECOP_ARC_INITIATE = 0xC0,
+ CECOP_ARC_REPORT_INITIATED = 0xC1,
+ CECOP_ARC_REPORT_TERMINATED = 0xC2,
+
+ CECOP_ARC_REQUEST_INITIATION = 0xC3,
+ CECOP_ARC_REQUEST_TERMINATION = 0xC4,
+ CECOP_ARC_TERMINATE = 0xC5,
+
+};
+
+/* Operands for <Feature Abort> Opcode */
+enum {
+ CECAR_UNRECOG_OPCODE = 0x00,
+ CECAR_NOT_CORRECT_MODE,
+ CECAR_CANT_PROVIDE_SOURCE,
+ CECAR_INVALID_OPERAND,
+ CECAR_REFUSED
+};
+
+/* Operands for <Power Status> Opcode */
+enum {
+ CEC_POWERSTATUS_ON = 0x00,
+ CEC_POWERSTATUS_STANDBY = 0x01,
+ CEC_POWERSTATUS_STANDBY_TO_ON = 0x02,
+ CEC_POWERSTATUS_ON_TO_STANDBY = 0x03,
+};
+
+enum {
+ EVENT_RX_FRAME,
+ EVENT_ENUMERATE,
+};
+
+#define MAKE_SRCDEST(src, dest) ((src << 4) | dest)
+
+#define MAX_CMD_SIZE 16
+
+struct cec_framedata {
+ char srcdestaddr; /* Source in upper nybble, dest in lower nybble */
+ char opcode;
+ char args[MAX_CMD_SIZE];
+ char argcount;
+ char nextframeargcount;
+};
+
+struct cec_delayed_work {
+ struct delayed_work work;
+ int event;
+ void *data;
+};
+
+struct cec_device {
+ struct workqueue_struct *workqueue;
+ struct hdmi *hdmi;
+ int address_phy;
+ int address_logic;
+ int powerstatus;
+ char cecval[32];
+
+ int (*sendframe)(struct hdmi *, struct cec_framedata *);
+ int (*readframe)(struct hdmi *, struct cec_framedata *);
+ void (*setceclogicaddr)(struct hdmi *, int);
+};
+
+#ifdef DEBUG
+#define CECDBG(format, ...) \
+ pr_info(format, ## __VA_ARGS__)
+#else
+#define CECDBG(format, ...)
+#endif
+
+/*====================================
+//used for cec key control direction OK and back
+====================================*/
+enum {
+ S_CEC_MAKESURE = 0x0,
+ S_CEC_UP = 0x1,
+ S_CEC_DOWN = 0x2,
+ S_CEC_LEFT = 0x3,
+ S_CEC_RIGHT = 0x4,
+ S_CEC_BACK = 0x0d,
+ S_CEC_VENDORBACK = 0x91,
+};
+
+int rockchip_hdmi_cec_init(struct hdmi *hdmi,
+ int (*sendframe)(struct hdmi *,
+ struct cec_framedata *),
+ int (*readframe)(struct hdmi *,
+ struct cec_framedata *),
+ void (*setceclogicaddr)(struct hdmi *, int));
+void rockchip_hdmi_cec_set_pa(int devpa);
+void rockchip_hdmi_cec_submit_work(int event, int delay, void *data);
+#endif /* __HDMI_CEC_H__ */
\ No newline at end of file
--- /dev/null
+#include <linux/delay.h>
+#include "rockchip-hdmi.h"
+#include "rockchip-hdmi-cec.h"
+
+struct hdmi_delayed_work {
+ struct delayed_work work;
+ struct hdmi *hdmi;
+ int event;
+ void *data;
+};
+
+struct hdmi_id_ref_info {
+ struct hdmi *hdmi;
+ int id;
+ int ref;
+} ref_info[HDMI_MAX_ID];
+
+static int uboot_vic;
+static void hdmi_work_queue(struct work_struct *work);
+
+struct delayed_work *hdmi_submit_work(struct hdmi *hdmi,
+ int event, int delay, void *data)
+{
+ struct hdmi_delayed_work *work;
+
+ DBG("%s event %04x delay %d", __func__, event, delay);
+
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+ if (work) {
+ INIT_DELAYED_WORK(&work->work, hdmi_work_queue);
+ work->hdmi = hdmi;
+ work->event = event;
+ work->data = data;
+ queue_delayed_work(hdmi->workqueue,
+ &work->work,
+ msecs_to_jiffies(delay));
+ } else {
+ pr_warn("HDMI: Cannot allocate memory to create work\n");
+ return 0;
+ }
+
+ return &work->work;
+}
+
+static void hdmi_send_uevent(struct hdmi *hdmi, int uevent)
+{
+ char *envp[3];
+
+ envp[0] = "INTERFACE=HDMI";
+ envp[1] = kmalloc(32, GFP_KERNEL);
+ if (envp[1] == NULL)
+ return;
+ sprintf(envp[1], "SCREEN=%d", hdmi->ddev->property);
+ envp[2] = NULL;
+ kobject_uevent_env(&hdmi->ddev->dev->kobj, uevent, envp);
+ kfree(envp[1]);
+}
+
+static inline void hdmi_wq_set_output(struct hdmi *hdmi, int mute)
+{
+ DBG("%s mute %d", __func__, mute);
+ if (hdmi->ops->setmute)
+ hdmi->ops->setmute(hdmi, mute);
+}
+
+static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
+{
+ DBG("%s", __func__);
+ if (hdmi->ops->setaudio)
+ hdmi->ops->setaudio(hdmi, &hdmi->audio);
+}
+
+static void hdmi_wq_set_video(struct hdmi *hdmi)
+{
+ struct hdmi_video video;
+
+ DBG("%s", __func__);
+
+ video.vic = hdmi->vic & HDMI_VIC_MASK;
+ if (hdmi->vic & HDMI_VIDEO_YUV420)
+ video.color_input = HDMI_COLOR_YCBCR420;
+ else
+ video.color_input = HDMI_COLOR_YCBCR444;
+ video.sink_hdmi = hdmi->edid.sink_hdmi;
+ video.format_3d = hdmi->mode_3d;
+ /* For DVI, output RGB */
+ if (hdmi->edid.sink_hdmi == 0) {
+ video.color_output = HDMI_COLOR_RGB_0_255;
+ } else {
+ if (hdmi->colormode == HDMI_COLOR_AUTO) {
+ if (hdmi->edid.ycbcr444)
+ video.color_output = HDMI_COLOR_YCBCR444;
+ else if (hdmi->edid.ycbcr422)
+ video.color_output = HDMI_COLOR_YCBCR422;
+ else
+ video.color_output = HDMI_COLOR_RGB_16_235;
+ } else {
+ video.color_output = hdmi->colormode;
+ }
+ }
+ if ((hdmi->property->feature & SUPPORT_DEEP_10BIT) &&
+ (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS)) {
+ if (hdmi->colordepth == HDMI_DEPP_COLOR_AUTO ||
+ hdmi->colordepth == 10)
+ video.color_output_depth = 10;
+ } else {
+ video.color_output_depth = 8;
+ }
+ if (hdmi->vic & HDMI_VIDEO_YUV420)
+ video.color_output = HDMI_COLOR_YCBCR420;
+ pr_info("hdmi output corlor mode is %d\n", video.color_output);
+ if (hdmi->ops->setvideo)
+ hdmi->ops->setvideo(hdmi, &video);
+}
+
+static void hdmi_wq_parse_edid(struct hdmi *hdmi)
+{
+ struct hdmi_edid *pedid;
+ unsigned char *buff = NULL;
+ int rc = HDMI_ERROR_SUCESS, extendblock = 0, i, trytimes;
+
+ if (hdmi == NULL)
+ return;
+
+ DBG("%s", __func__);
+
+ pedid = &(hdmi->edid);
+ fb_destroy_modelist(&pedid->modelist);
+ memset(pedid, 0, sizeof(struct hdmi_edid));
+ INIT_LIST_HEAD(&pedid->modelist);
+
+ buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
+ if (buff == NULL) {
+ dev_err(hdmi->dev,
+ "[%s] can not allocate memory for edid buff.\n",
+ __func__);
+ rc = HDMI_ERROR_FALSE;
+ goto out;
+ }
+
+ if (hdmi->ops->getedid == NULL) {
+ rc = HDMI_ERROR_FALSE;
+ goto out;
+ }
+
+ /* Read base block edid.*/
+ for (trytimes = 0; trytimes < 3; trytimes++) {
+ if (trytimes)
+ msleep(50);
+ memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
+ rc = hdmi->ops->getedid(hdmi, 0, buff);
+ if (rc) {
+ dev_err(hdmi->dev,
+ "[HDMI] read edid base block error\n");
+ continue;
+ }
+
+ rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
+ if (rc) {
+ dev_err(hdmi->dev,
+ "[HDMI] parse edid base block error\n");
+ continue;
+ }
+ if (!rc)
+ break;
+ }
+ if (rc)
+ goto out;
+
+ for (i = 1; i < extendblock + 1; i++) {
+ for (trytimes = 0; trytimes < 3; trytimes++) {
+ if (trytimes)
+ msleep(20);
+ memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
+ rc = hdmi->ops->getedid(hdmi, i, buff);
+ if (rc) {
+ dev_err(hdmi->dev,
+ "[HDMI] read edid block %d error\n",
+ i);
+ continue;
+ }
+
+ rc = hdmi_edid_parse_extensions(buff, pedid);
+ if (rc) {
+ dev_err(hdmi->dev,
+ "[HDMI] parse edid block %d error\n",
+ i);
+ continue;
+ }
+
+ if (!rc)
+ break;
+ }
+ }
+out:
+ kfree(buff);
+ rc = hdmi_ouputmode_select(hdmi, rc);
+}
+
+static void hdmi_wq_insert(struct hdmi *hdmi)
+{
+ DBG("%s", __func__);
+ if (hdmi->ops->insert)
+ hdmi->ops->insert(hdmi);
+ hdmi_wq_parse_edid(hdmi);
+ if (hdmi->property->feature & SUPPORT_CEC)
+ rockchip_hdmi_cec_set_pa(hdmi->edid.cecaddress);
+ hdmi_send_uevent(hdmi, KOBJ_ADD);
+ if (hdmi->enable) {
+ hdmi->autoset = 0;
+ hdmi_set_lcdc(hdmi);
+ hdmi_wq_set_video(hdmi);
+ #ifdef CONFIG_SWITCH
+ if ((hdmi->edid.baseaudio_support &&
+ hdmi->edid.sink_hdmi) ||
+ rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
+ switch_set_state(&(hdmi->switchdev), 1);
+ #endif
+ hdmi_wq_set_audio(hdmi);
+ hdmi_wq_set_output(hdmi, hdmi->mute);
+ if (hdmi->ops->hdcp_cb)
+ hdmi->ops->hdcp_cb(hdmi);
+ if (hdmi->ops->setcec)
+ hdmi->ops->setcec(hdmi);
+ }
+ if (hdmi->uboot)
+ hdmi->uboot = 0;
+}
+
+static void hdmi_wq_remove(struct hdmi *hdmi)
+{
+ struct list_head *pos, *n;
+ struct rk_screen screen;
+
+ DBG("%s", __func__);
+ if (hdmi->ops->remove)
+ hdmi->ops->remove(hdmi);
+
+ list_for_each_safe(pos, n, &hdmi->edid.modelist) {
+ list_del(pos);
+ kfree(pos);
+ }
+
+ kfree(hdmi->edid.audio);
+
+ if (hdmi->edid.specs) {
+ kfree(hdmi->edid.specs->modedb);
+ kfree(hdmi->edid.specs);
+ }
+ memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
+ hdmi_init_modelist(hdmi);
+ hdmi->mute = HDMI_AV_UNMUTE;
+ hdmi->mode_3d = HDMI_3D_NONE;
+ hdmi->uboot = 0;
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
+ screen.type = SCREEN_HDMI;
+ rk_fb_switch_screen(&screen, 0, hdmi->lcdc->id);
+ }
+ hdmi->hotplug = HDMI_HPD_REMOVED;
+ hdmi_send_uevent(hdmi, KOBJ_REMOVE);
+ #ifdef CONFIG_SWITCH
+ if ((hdmi->edid.baseaudio_support &&
+ hdmi->edid.sink_hdmi) ||
+ rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
+ switch_set_state(&(hdmi->switchdev), 0);
+ #endif
+}
+
+static void hdmi_work_queue(struct work_struct *work)
+{
+ struct hdmi_delayed_work *hdmi_w =
+ container_of(work, struct hdmi_delayed_work, work.work);
+ struct hdmi *hdmi = hdmi_w->hdmi;
+ int event = hdmi_w->event;
+ int hpd = HDMI_HPD_REMOVED;
+
+ mutex_lock(&hdmi->lock);
+
+ DBG("\nhdmi_work_queue() - evt= %x %d\n",
+ (event & 0xFF00) >> 8,
+ event & 0xFF);
+
+ switch (event) {
+ case HDMI_ENABLE_CTL:
+ if (!hdmi->enable) {
+ hdmi->enable = 1;
+ if (!hdmi->sleep) {
+ if (hdmi->ops->enable)
+ hdmi->ops->enable(hdmi);
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED)
+ hdmi_wq_insert(hdmi);
+ }
+ }
+ break;
+ case HDMI_RESUME_CTL:
+ if (hdmi->sleep) {
+ if (hdmi->ops->enable)
+ hdmi->ops->enable(hdmi);
+ hdmi->sleep = 0;
+ }
+ break;
+ case HDMI_DISABLE_CTL:
+ if (hdmi->enable) {
+ if (!hdmi->sleep) {
+ /*
+ if (hdmi->ops->disable)
+ hdmi->ops->disable(hdmi);
+ */
+ hdmi_wq_remove(hdmi);
+ }
+ hdmi->enable = 0;
+ }
+ break;
+ case HDMI_SUSPEND_CTL:
+ if (!hdmi->sleep) {
+ hdmi_wq_set_output(hdmi,
+ HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
+ if (hdmi->ops->disable)
+ hdmi->ops->disable(hdmi);
+ if (hdmi->enable)
+ hdmi_wq_remove(hdmi);
+ hdmi->sleep = 1;
+ }
+ break;
+ case HDMI_HPD_CHANGE:
+ if (hdmi->ops->getstatus)
+ hpd = hdmi->ops->getstatus(hdmi);
+ DBG("hdmi_work_queue() - hpd is %d hotplug is %d",
+ hpd, hdmi->hotplug);
+ if (hpd != hdmi->hotplug) {
+ if (hpd == HDMI_HPD_ACTIVED) {
+ hdmi->hotplug = hpd;
+ hdmi_wq_insert(hdmi);
+ } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
+ hdmi_wq_remove(hdmi);
+ }
+ hdmi->hotplug = hpd;
+ }
+ break;
+ case HDMI_SET_VIDEO:
+ if (hdmi->enable && !hdmi->sleep) {
+ hdmi_wq_set_output(hdmi,
+ HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
+ if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
+ msleep(2000);
+ else
+ msleep(1000);
+ hdmi_set_lcdc(hdmi);
+ hdmi_send_uevent(hdmi, KOBJ_CHANGE);
+ hdmi_wq_set_video(hdmi);
+ hdmi_wq_set_audio(hdmi);
+ hdmi_wq_set_output(hdmi, hdmi->mute);
+ if (hdmi->ops->hdcp_cb)
+ hdmi->ops->hdcp_cb(hdmi);
+ }
+ break;
+ case HDMI_SET_AUDIO:
+ if ((hdmi->mute & HDMI_AUDIO_MUTE) == 0 &&
+ hdmi->enable && !hdmi->sleep) {
+ hdmi_wq_set_output(hdmi, HDMI_AUDIO_MUTE);
+ hdmi_wq_set_audio(hdmi);
+ hdmi_wq_set_output(hdmi, hdmi->mute);
+ }
+ break;
+ case HDMI_MUTE_AUDIO:
+ case HDMI_UNMUTE_AUDIO:
+ if (hdmi->mute & HDMI_AUDIO_MUTE ||
+ !hdmi->enable || hdmi->sleep ||
+ hdmi->hotplug != HDMI_HPD_ACTIVED)
+ break;
+ if (event == HDMI_MUTE_AUDIO)
+ hdmi_wq_set_output(hdmi, hdmi->mute |
+ HDMI_AUDIO_MUTE);
+ else
+ hdmi_wq_set_output(hdmi,
+ hdmi->mute & (~HDMI_AUDIO_MUTE));
+ break;
+ case HDMI_SET_3D:
+ if (hdmi->ops->setvsi) {
+ if (hdmi->mode_3d != HDMI_3D_NONE)
+ hdmi->ops->setvsi(hdmi, hdmi->mode_3d,
+ HDMI_VIDEO_FORMAT_3D);
+ else if ((hdmi->vic & HDMI_TYPE_MASK) == 0)
+ hdmi->ops->setvsi(hdmi, hdmi->vic,
+ HDMI_VIDEO_FORMAT_NORMAL);
+ }
+ break;
+ case HDMI_SET_COLOR:
+ hdmi_wq_set_output(hdmi,
+ HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
+ msleep(100);
+ hdmi_wq_set_video(hdmi);
+ hdmi_wq_set_output(hdmi, hdmi->mute);
+ break;
+ case HDMI_ENABLE_HDCP:
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED && hdmi->ops->hdcp_cb)
+ hdmi->ops->hdcp_cb(hdmi);
+ break;
+ default:
+ pr_err("HDMI: hdmi_work_queue() unkown event\n");
+ break;
+ }
+
+ kfree(hdmi_w->data);
+ kfree(hdmi_w);
+
+ DBG("\nhdmi_work_queue() - exit evt= %x %d\n",
+ (event & 0xFF00) >> 8,
+ event & 0xFF);
+ mutex_unlock(&hdmi->lock);
+}
+
+struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
+ struct hdmi_ops *ops)
+{
+ struct hdmi *hdmi;
+ char name[32];
+ int i;
+
+ if (property == NULL || ops == NULL) {
+ pr_err("HDMI: %s invalid parameter\n", __func__);
+ return NULL;
+ }
+
+ for (i = 0; i < HDMI_MAX_ID; i++) {
+ if (ref_info[i].ref == 0)
+ break;
+ }
+ if (i == HDMI_MAX_ID)
+ return NULL;
+
+ DBG("hdmi_register() - video source %d display %d",
+ property->videosrc, property->display);
+
+ hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi) {
+ pr_err("HDMI: no memory to allocate hdmi device.\n");
+ return NULL;
+ }
+ memset(hdmi, 0, sizeof(struct hdmi));
+ mutex_init(&hdmi->lock);
+
+ hdmi->property = property;
+ hdmi->ops = ops;
+ hdmi->enable = false;
+ hdmi->mute = HDMI_AV_UNMUTE;
+ hdmi->hotplug = HDMI_HPD_REMOVED;
+ hdmi->autoset = HDMI_AUTO_CONFIG;
+ if (uboot_vic > 0) {
+ hdmi->vic = uboot_vic;
+ hdmi->uboot = 1;
+ hdmi->autoset = 0;
+ } else if (hdmi->autoset) {
+ hdmi->vic = 0;
+ } else {
+ hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
+ }
+ hdmi->colormode = HDMI_VIDEO_DEFAULT_COLORMODE;
+ hdmi->colordepth = HDMI_DEPP_COLOR_AUTO;
+ hdmi->mode_3d = HDMI_3D_NONE;
+ hdmi->audio.type = HDMI_AUDIO_DEFAULT_TYPE;
+ hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
+ hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
+ hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORDLENGTH;
+ hdmi->xscale = 100;
+ hdmi->yscale = 100;
+ hdmi_init_modelist(hdmi);
+
+#ifndef CONFIG_ARCH_RK29
+ if (hdmi->property->videosrc == DISPLAY_SOURCE_LCDC0)
+ hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
+ else
+ hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
+#endif
+ memset(name, 0, 32);
+ sprintf(name, "hdmi-%s", hdmi->property->name);
+ hdmi->workqueue = create_singlethread_workqueue(name);
+ if (hdmi->workqueue == NULL) {
+ pr_err("HDMI,: create workqueue failed.\n");
+ goto err_create_wq;
+ }
+ hdmi->ddev = hdmi_register_display_sysfs(hdmi, NULL);
+ if (hdmi->ddev == NULL) {
+ pr_err("HDMI : register display sysfs failed.\n");
+ goto err_register_display;
+ }
+ hdmi->id = i;
+ #ifdef CONFIG_SWITCH
+ if (hdmi->id == 0) {
+ hdmi->switchdev.name = "hdmi";
+ } else {
+ hdmi->switchdev.name = kzalloc(32, GFP_KERNEL);
+ memset((char *)hdmi->switchdev.name, 0, 32);
+ sprintf((char *)hdmi->switchdev.name, "hdmi%d", hdmi->id);
+ }
+ switch_dev_register(&(hdmi->switchdev));
+ #endif
+
+ ref_info[i].hdmi = hdmi;
+ ref_info[i].ref = 1;
+ return hdmi;
+
+err_register_display:
+ destroy_workqueue(hdmi->workqueue);
+err_create_wq:
+ kfree(hdmi);
+ return NULL;
+}
+
+void rockchip_hdmi_unregister(struct hdmi *hdmi)
+{
+ if (hdmi) {
+ flush_workqueue(hdmi->workqueue);
+ destroy_workqueue(hdmi->workqueue);
+ #ifdef CONFIG_SWITCH
+ switch_dev_unregister(&(hdmi->switchdev));
+ #endif
+ hdmi_unregister_display_sysfs(hdmi);
+ fb_destroy_modelist(&hdmi->edid.modelist);
+ kfree(hdmi->edid.audio);
+ if (hdmi->edid.specs) {
+ kfree(hdmi->edid.specs->modedb);
+ kfree(hdmi->edid.specs);
+ }
+ kfree(hdmi);
+
+ ref_info[hdmi->id].ref = 0;
+ ref_info[hdmi->id].hdmi = NULL;
+
+ hdmi = NULL;
+ }
+}
+
+int hdmi_get_hotplug(void)
+{
+ if (ref_info[0].hdmi)
+ return ref_info[0].hdmi->hotplug;
+ else
+ return HDMI_HPD_REMOVED;
+}
+
+int hdmi_config_audio(struct hdmi_audio *audio)
+{
+ int i;
+ struct hdmi *hdmi;
+
+ if (audio == NULL)
+ return HDMI_ERROR_FALSE;
+
+ for (i = 0; i < HDMI_MAX_ID; i++) {
+ if (ref_info[i].ref == 0)
+ continue;
+ hdmi = ref_info[i].hdmi;
+
+ /*
+ if (memcmp(audio, &hdmi->audio, sizeof(struct hdmi_audio)) == 0)
+ continue;
+ */
+ /*for (j = 0; j < hdmi->edid.audio_num; j++) {
+ if (audio->type == hdmi->edid.audio_num)
+ break;
+ }*/
+
+ /*if ( (j == hdmi->edid.audio_num) ||
+ (audio->channel > hdmi->edid.audio[j].channel) ||
+ ((audio->rate & hdmi->edid.audio[j].rate) == 0)||
+ ((audio->type == HDMI_AUDIO_LPCM) &&
+ ((audio->word_length &
+ hdmi->edid.audio[j].word_length) == 0)) ) {
+ pr_warn("[%s] warning : input audio type
+ not supported in hdmi sink\n", __func__);
+ continue;
+ }*/
+ memcpy(&hdmi->audio, audio, sizeof(struct hdmi_audio));
+ hdmi_submit_work(hdmi, HDMI_SET_AUDIO, 0, NULL);
+ }
+ return 0;
+}
+
+void hdmi_audio_mute(int mute)
+{
+ int i;
+ struct hdmi *hdmi;
+
+ for (i = 0; i < HDMI_MAX_ID; i++) {
+ if (ref_info[i].ref == 0)
+ continue;
+ hdmi = ref_info[i].hdmi;
+
+ if (mute)
+ hdmi_submit_work(hdmi, HDMI_MUTE_AUDIO, 0, NULL);
+ else
+ hdmi_submit_work(hdmi, HDMI_UNMUTE_AUDIO, 0, NULL);
+ }
+}
+
+static int __init bootloader_setup(char *str)
+{
+ if (str) {
+ pr_info("hdmi init vic is %s\n", str);
+ if (kstrtoint(str, 0, &uboot_vic) < 0)
+ uboot_vic = 0;
+ }
+ return 0;
+}
+
+early_param("hdmi.vic", bootloader_setup);
+
+static int __init hdmi_class_init(void)
+{
+ int i;
+
+ for (i = 0; i < HDMI_MAX_ID; i++) {
+ ref_info[i].id = i;
+ ref_info[i].ref = 0;
+ ref_info[i].hdmi = NULL;
+ }
+ pr_info("Rockchip hdmi driver version 2.0\n.");
+ return 0;
+}
+
+subsys_initcall(hdmi_class_init);
--- /dev/null
+#include "rockchip-hdmi.h"
+#include "../../edid.h"
+
+#ifdef EDIDDEBUG
+#define EDBG DBG
+#else
+#define EDBG(format, ...)
+#endif
+
+enum {
+ E_HDMI_EDID_SUCCESS = 0,
+ E_HDMI_EDID_PARAM,
+ E_HDMI_EDID_HEAD,
+ E_HDMI_EDID_CHECKSUM,
+ E_HDMI_EDID_VERSION,
+ E_HDMI_EDID_UNKOWNDATA,
+ E_HDMI_EDID_NOMEMORY
+};
+
+static int hdmi_edid_checksum(unsigned char *buf)
+{
+ int i;
+ int checksum = 0;
+
+ for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)
+ checksum += buf[i];
+
+ checksum &= 0xff;
+
+ if (checksum == 0)
+ return E_HDMI_EDID_SUCCESS;
+ else
+ return E_HDMI_EDID_CHECKSUM;
+}
+
+/*
+ @Des Parse Detail Timing Descriptor.
+ @Param buf : pointer to DTD data.
+ @Param pvic: VIC of DTD descripted.
+ */
+static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
+{
+ mode->xres = H_ACTIVE;
+ mode->yres = V_ACTIVE;
+ mode->pixclock = PIXEL_CLOCK;
+/* mode->pixclock /= 1000;
+ mode->pixclock = KHZ2PICOS(mode->pixclock);
+*/ mode->right_margin = H_SYNC_OFFSET;
+ mode->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ mode->lower_margin = V_SYNC_OFFSET;
+ mode->hsync_len = H_SYNC_WIDTH;
+ mode->vsync_len = V_SYNC_WIDTH;
+ if (HSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+ (V_ACTIVE + V_BLANKING));
+ if (INTERLACED) {
+ mode->yres *= 2;
+ mode->upper_margin *= 2;
+ mode->lower_margin *= 2;
+ mode->vsync_len *= 2;
+ mode->vmode |= FB_VMODE_INTERLACED;
+ }
+ mode->flag = FB_MODE_IS_DETAILED;
+
+ EDBG("<<<<<<<<Detailed Time>>>>>>>>>\n");
+ EDBG("%d KHz Refresh %d Hz",
+ PIXEL_CLOCK/1000, mode->refresh);
+ EDBG("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+ EDBG("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ EDBG("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
+ (VSYNC_POSITIVE) ? "+" : "-");
+ return E_HDMI_EDID_SUCCESS;
+}
+
+int hdmi_edid_parse_base(unsigned char *buf,
+ int *extend_num, struct hdmi_edid *pedid)
+{
+ int rc;
+
+ if (buf == NULL || extend_num == NULL)
+ return E_HDMI_EDID_PARAM;
+
+ /* Check first 8 byte to ensure it is an edid base block. */
+ if (buf[0] != 0x00 ||
+ buf[1] != 0xFF ||
+ buf[2] != 0xFF ||
+ buf[3] != 0xFF ||
+ buf[4] != 0xFF ||
+ buf[5] != 0xFF ||
+ buf[6] != 0xFF ||
+ buf[7] != 0x00) {
+ pr_err("[EDID] check header error\n");
+ return E_HDMI_EDID_HEAD;
+ }
+
+ *extend_num = buf[0x7e];
+ #ifdef DEBUG
+ EDBG("[EDID] extend block num is %d\n", buf[0x7e]);
+ #endif
+
+ /* Checksum */
+ rc = hdmi_edid_checksum(buf);
+ if (rc != E_HDMI_EDID_SUCCESS) {
+ pr_err("[EDID] base block checksum error\n");
+ return E_HDMI_EDID_CHECKSUM;
+ }
+
+ pedid->specs = kzalloc(sizeof(*pedid->specs), GFP_KERNEL);
+ if (pedid->specs == NULL)
+ return E_HDMI_EDID_NOMEMORY;
+
+ fb_edid_to_monspecs(buf, pedid->specs);
+
+ return E_HDMI_EDID_SUCCESS;
+}
+
+/* Parse CEA Short Video Descriptor */
+static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
+{
+ int count, i, vic;
+
+ count = buf[0] & 0x1F;
+ for (i = 0; i < count; i++) {
+ EDBG("[CEA] %02x VID %d native %d\n",
+ buf[1 + i], buf[1 + i] & 0x7f, buf[1 + i] >> 7);
+ vic = buf[1 + i] & 0x7f;
+ hdmi_add_vic(vic, &pedid->modelist);
+ }
+/*
+ struct list_head *pos;
+ struct display_modelist *modelist;
+
+ list_for_each(pos, &pedid->modelist) {
+ modelist = list_entry(pos, struct display_modelist, list);
+ pr_info("%s vic %d\n", __FUNCTION__, modelist->vic);
+ }
+*/ return 0;
+}
+
+/* Parse CEA Short Audio Descriptor */
+static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
+{
+ int i, count;
+
+ count = buf[0] & 0x1F;
+ pedid->audio = kmalloc((count/3)*sizeof(struct hdmi_audio), GFP_KERNEL);
+ if (pedid->audio == NULL)
+ return E_HDMI_EDID_NOMEMORY;
+
+ pedid->audio_num = count/3;
+ for (i = 0; i < pedid->audio_num; i++) {
+ pedid->audio[i].type = (buf[1 + i*3] >> 3) & 0x0F;
+ pedid->audio[i].channel = (buf[1 + i*3] & 0x07) + 1;
+ pedid->audio[i].rate = buf[1 + i*3 + 1];
+ if (pedid->audio[i].type == HDMI_AUDIO_LPCM)
+ pedid->audio[i].word_length = buf[1 + i*3 + 2];
+
+/* pr_info("type %d channel %d rate %d word length %d\n",
+ pedid->audio[i].type, pedid->audio[i].channel,
+ pedid->audio[i].rate, pedid->audio[i].word_length);
+*/ }
+ return E_HDMI_EDID_SUCCESS;
+}
+
+static int hdmi_edid_parse_3dinfo(unsigned char *buf, struct list_head *head)
+{
+ int i, j, len = 0, format_3d, vic_mask;
+ unsigned char offset = 2, vic_2d, structure_3d;
+ struct list_head *pos;
+ struct display_modelist *modelist;
+
+ if (buf[1] & 0xe0) {
+ len = (buf[1] & 0xe0) >> 5;
+ for (i = 0; i < len; i++) {
+ if (buf[offset])
+ hdmi_add_vic((96 - buf[offset++]), head);
+ }
+ }
+
+ if (buf[0] & 0x80) {
+ /* 3d supported */
+ len += (buf[1] & 0x1F) + 2;
+ if (((buf[0] & 0x60) == 0x40) || ((buf[0] & 0x60) == 0x20)) {
+ format_3d = buf[offset++] << 8;
+ format_3d |= buf[offset++];
+ if ((buf[0] & 0x60) == 0x20) {
+ vic_mask = 0xFFFF;
+ } else {
+ vic_mask = buf[offset++] << 8;
+ vic_mask |= buf[offset++];
+ }
+ } else {
+ format_3d = 0;
+ vic_mask = 0;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (vic_mask & (1 << i)) {
+ j = 0;
+ for (pos = (head)->next; pos != (head);
+ pos = pos->next) {
+ if (j++ == i) {
+ modelist =
+ list_entry(pos, struct display_modelist, list);
+ modelist->format_3d = format_3d;
+ break;
+ }
+ }
+ }
+ }
+ while (offset < len) {
+ vic_2d = (buf[offset] & 0xF0) >> 4;
+ structure_3d = (buf[offset++] & 0x0F);
+ j = 0;
+ for (pos = (head)->next; pos != (head);
+ pos = pos->next) {
+ j++;
+ if (j == vic_2d) {
+ modelist =
+ list_entry(pos, struct display_modelist, list);
+ modelist->format_3d |=
+ (1 << structure_3d);
+ if (structure_3d & 0x08)
+ modelist->detail_3d =
+ (buf[offset++] & 0xF0) >> 4;
+ break;
+ }
+ }
+ }
+ /* mandatory formats */
+ for (pos = (head)->next; pos != (head); pos = pos->next) {
+ modelist = list_entry(pos,
+ struct display_modelist,
+ list);
+ if (modelist->vic == HDMI_1920X1080P_24HZ ||
+ modelist->vic == HDMI_1280X720P_60HZ ||
+ modelist->vic == HDMI_1280X720P_50HZ) {
+ modelist->format_3d |=
+ (1 << HDMI_3D_FRAME_PACKING) |
+ (1 << HDMI_3D_TOP_BOOTOM);
+ } else if (modelist->vic == HDMI_1920X1080I_60HZ ||
+ modelist->vic == HDMI_1920X1080I_50HZ) {
+ modelist->format_3d |=
+ (1 << HDMI_3D_SIDE_BY_SIDE_HALF);
+ }
+ }
+ }
+
+ return 0;
+}
+static int hdmi_edmi_parse_vsdb(unsigned char *buf, struct hdmi_edid *pedid,
+ int cur_offset, int IEEEOUI)
+{
+ int count, buf_offset;
+
+ count = buf[cur_offset] & 0x1F;
+ switch (IEEEOUI) {
+ case 0x0c03:
+ pedid->sink_hdmi = 1;
+ pedid->cecaddress = buf[cur_offset + 5];
+ pedid->cecaddress |= buf[cur_offset + 4] << 8;
+ EDBG("[CEA] CEC Physical addres is 0x%08x.\n",
+ pedid->cecaddress);
+ if (count > 6)
+ pedid->deepcolor = (buf[cur_offset + 6] >> 3) & 0x0F;
+ if (count > 7) {
+ pedid->maxtmdsclock = buf[cur_offset + 7] * 5000000;
+ EDBG("[CEA] maxtmdsclock is %d.\n",
+ pedid->maxtmdsclock);
+ }
+ if (count > 8) {
+ pedid->fields_present = buf[cur_offset + 8];
+ EDBG("[CEA] fields_present is 0x%02x.\n",
+ pedid->fields_present);
+ }
+ buf_offset = cur_offset + 9;
+ if (pedid->fields_present & 0x80) {
+ pedid->video_latency = buf[buf_offset++];
+ pedid->audio_latency = buf[buf_offset++];
+ }
+ if (pedid->fields_present & 0x40) {
+ pedid->interlaced_video_latency = buf[buf_offset++];
+ pedid->interlaced_audio_latency = buf[buf_offset++];
+ }
+ if (pedid->fields_present & 0x20) {
+ hdmi_edid_parse_3dinfo(buf + buf_offset,
+ &pedid->modelist);
+ }
+ break;
+ case 0xc45dd8:
+ pedid->sink_hdmi = 1;
+ if (count > 4)
+ pedid->hf_vsdb_version = buf[cur_offset + 4];
+ switch (pedid->hf_vsdb_version) {
+ case 1:/*compliant with HDMI Specification 2.0*/
+ if (count > 5) {
+ pedid->maxtmdsclock =
+ buf[cur_offset + 5] * 5000000;
+ EDBG("[CEA] maxtmdsclock is %d.\n",
+ pedid->maxtmdsclock);
+ }
+ if (count > 6) {
+ pedid->scdc_present = buf[cur_offset+6] >> 7;
+ pedid->rr_capable =
+ (buf[cur_offset+6]&0x40) >> 6;
+ pedid->lte_340mcsc_scramble =
+ (buf[cur_offset+6]&0x08) >> 3;
+ pedid->independent_view =
+ (buf[cur_offset+6]&0x04) >> 2;
+ pedid->dual_view =
+ (buf[cur_offset+6]&0x02) >> 1;
+ pedid->osd_disparity_3d =
+ buf[cur_offset+6] & 0x01;
+ }
+ if (count > 7) {
+ pedid->deepcolor = buf[cur_offset+7]&0x7;
+ EDBG("[CEA] deepcolor is %d.\n",
+ pedid->deepcolor);
+ }
+ break;
+ default:
+ pr_info("hf_vsdb_version = %d\n",
+ pedid->hf_vsdb_version);
+ break;
+ }
+ break;
+ default:
+ pr_info("IEEOUT = 0x%x\n", IEEEOUI);
+ break;
+ }
+ return 0;
+}
+
+static void hdmi_edid_parse_yuv420cmdb(unsigned char *buf, int count,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct display_modelist *modelist;
+ int i, j, yuv420_mask, vic;
+
+ for (i = 0; i < count - 1; i++) {
+ EDBG("vic which support yuv420 mode is %x\n", buf[i]);
+ yuv420_mask |= buf[i] << (8 * i);
+ }
+ for (i = 0; i < 32; i++) {
+ if (yuv420_mask & (1 << i)) {
+ j = 0;
+ for (pos = head->next; pos != (head); pos = pos->next) {
+ if (j++ == i) {
+ modelist =
+ list_entry(pos, struct display_modelist, list);
+ vic = modelist->vic |
+ HDMI_VIDEO_YUV420;
+ hdmi_add_vic(vic, head);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* Parse CEA 861 Serial Extension. */
+static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
+ struct hdmi_edid *pedid)
+{
+ unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
+ unsigned int tag, IEEEOUI = 0, count, i;
+/* unsigned int underscan_support, baseaudio_support; */
+
+ if (buf == NULL)
+ return E_HDMI_EDID_PARAM;
+
+ /* Check ces extension version */
+ if (buf[1] != 3) {
+ pr_err("[CEA] error version.\n");
+ return E_HDMI_EDID_VERSION;
+ }
+
+ ddc_offset = buf[2];
+/* underscan_support = (buf[3] >> 7) & 0x01;
+*/ pedid->baseaudio_support = (buf[3] >> 6) & 0x01;
+ pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
+ pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
+ native_dtd_num = buf[3] & 0x0F;
+/* EDBG("[CEA] ddc_offset %d underscan_support %d
+ baseaudio_support %d yuv_support %d
+ native_dtd_num %d\n",
+ ddc_offset, underscan_support, baseaudio_support,
+ yuv_support, native_dtd_num);
+*/ /* Parse data block */
+ while (cur_offset < ddc_offset) {
+ tag = buf[cur_offset] >> 5;
+ count = buf[cur_offset] & 0x1F;
+ switch (tag) {
+ case 0x02: /* Video Data Block */
+ EDBG("[CEA] Video Data Block.\n");
+ hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
+ break;
+ case 0x01: /* Audio Data Block */
+ EDBG("[CEA] Audio Data Block.\n");
+ hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
+ break;
+ case 0x04: /* Speaker Allocation Data Block */
+ EDBG("[CEA] Speaker Allocatio Data Block.\n");
+ break;
+ case 0x03: /* Vendor Specific Data Block */
+ EDBG("[CEA] Vendor Specific Data Block.\n");
+
+ IEEEOUI = buf[cur_offset + 3];
+ IEEEOUI <<= 8;
+ IEEEOUI += buf[cur_offset + 2];
+ IEEEOUI <<= 8;
+ IEEEOUI += buf[cur_offset + 1];
+ EDBG("[CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
+
+ hdmi_edmi_parse_vsdb(buf, pedid,
+ cur_offset, IEEEOUI);
+ break;
+ case 0x05: /* VESA DTC Data Block */
+ EDBG("[CEA] VESA DTC Data Block.\n");
+ break;
+ case 0x07: /* Use Extended Tag */
+ EDBG("[CEA] Use Extended Tag Data Block %02x.\n",
+ buf[cur_offset + 1]);
+ switch (buf[cur_offset + 1]) {
+ case 0x00:
+ EDBG("[CEA] Video Capability Data Block\n");
+ EDBG("value is %02x\n", buf[cur_offset + 2]);
+ break;
+ case 0x05:
+ EDBG("[CEA] Colorimetry Data Block\n");
+ EDBG("value is %02x\n", buf[cur_offset + 2]);
+ break;
+ case 0x0e:
+ EDBG("[CEA] YCBCR 4:2:0 Video Data Block\n");
+ for (i = 0; i < count - 1; i++) {
+ EDBG("mode is %d\n",
+ buf[cur_offset + 2 + i]);
+ pedid->ycbcr420 = 1;
+ IEEEOUI = buf[cur_offset + 2 + i] |
+ HDMI_VIDEO_YUV420;
+ hdmi_add_vic(IEEEOUI,
+ &pedid->modelist);
+ }
+ break;
+ case 0x0f:
+ EDBG("[CEA] YCBCR 4:2:0 Capability Map Data\n");
+ hdmi_edid_parse_yuv420cmdb(&buf[cur_offset+2],
+ count,
+ &pedid->modelist);
+ pedid->ycbcr420 = 1;
+ break;
+ }
+ break;
+ default:
+ pr_err("[CEA] unkowned data block tag.\n");
+ break;
+ }
+ cur_offset += (buf[cur_offset] & 0x1F) + 1;
+ }
+#if 1
+{
+ /* Parse DTD */
+ struct fb_videomode *vmode =
+ kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+
+ if (vmode == NULL)
+ return E_HDMI_EDID_SUCCESS;
+ while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
+ if (!buf[ddc_offset] && !buf[ddc_offset + 1])
+ break;
+ memset(vmode, 0, sizeof(struct fb_videomode));
+ hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
+ hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);
+ ddc_offset += 18;
+ }
+ kfree(vmode);
+}
+#endif
+ return E_HDMI_EDID_SUCCESS;
+}
+
+int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)
+{
+ int rc;
+
+ if (buf == NULL || pedid == NULL)
+ return E_HDMI_EDID_PARAM;
+
+ /* Checksum */
+ rc = hdmi_edid_checksum(buf);
+ if (rc != E_HDMI_EDID_SUCCESS) {
+ pr_err("[EDID] extensions block checksum error\n");
+ return E_HDMI_EDID_CHECKSUM;
+ }
+
+ switch (buf[0]) {
+ case 0xF0:
+ EDBG("[EDID-EXTEND] Iextensions block map.\n");
+ break;
+ case 0x02:
+ EDBG("[EDID-EXTEND] CEA 861 Series Extension.\n");
+ hdmi_edid_parse_extensions_cea(buf, pedid);
+ break;
+ case 0x10:
+ EDBG("[EDID-EXTEND] Video Timing Block Extension.\n");
+ break;
+ case 0x40:
+ EDBG("[EDID-EXTEND] Display Information Extension.\n");
+ break;
+ case 0x50:
+ EDBG("[EDID-EXTEND] Localized String Extension.\n");
+ break;
+ case 0x60:
+ EDBG("[EDID-EXTEND] Digital Packet Video Link Extension.\n");
+ break;
+ default:
+ pr_err("[EDID-EXTEND] Unkowned Extension.\n");
+ return E_HDMI_EDID_UNKOWNDATA;
+ }
+
+ return E_HDMI_EDID_SUCCESS;
+}
--- /dev/null
+#include "rockchip-hdmi.h"
+
+static const struct hdmi_video_timing hdmi_mode[] = {
+/* name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag vic 2ndvic pixelrepeat interface */
+
+ { { "720x480i@60Hz", 60, 720, 480, 27000000, 57, 19, 15, 4, 62, 3, 0, 1, 0 }, 6, HDMI_720X480I_60HZ_16_9, 2, OUT_P888},
+ { { "720x576i@50Hz", 50, 720, 576, 27000000, 69, 12, 19, 2, 63, 3, 0, 1, 0 }, 21, HDMI_720X576I_50HZ_16_9, 2, OUT_P888},
+ { { "720x480p@60Hz", 60, 720, 480, 27000000, 60, 16, 30, 9, 62, 6, 0, 0, 0 }, 2, HDMI_720X480P_60HZ_16_9, 1, OUT_P888},
+ { { "720x576p@50Hz", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, 0 }, 17, HDMI_720X576P_50HZ_16_9, 1, OUT_P888},
+ { { "1280x720p@24Hz", 24, 1280, 720, 59400000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 60, HDMI_1280X720P_24HZ_4_3, 1, OUT_P888},
+ { { "1280x720p@25Hz", 25, 1280, 720, 74250000, 220, 2420, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 61, HDMI_1280X720P_25HZ_4_3, 1, OUT_P888},
+ { { "1280x720p@30Hz", 30, 1280, 720, 74250000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 62, HDMI_1280X720P_30HZ_4_3, 1, OUT_P888},
+ { { "1280x720p@50Hz", 50, 1280, 720, 74250000, 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 19, HDMI_1280X720P_50HZ_4_3, 1, OUT_P888},
+ { { "1280x720p@60Hz", 60, 1280, 720, 74250000, 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 4, HDMI_1280X720P_60HZ_4_3, 1, OUT_P888},
+ { { "1920x1080i@50Hz", 50, 1920, 1080, 74250000, 148, 528, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 0 }, 20, 0, 1, OUT_P888},
+ { { "1920x1080i@60Hz", 60, 1920, 1080, 74250000, 148, 88, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 0 }, 5, 0, 1, OUT_P888},
+ { { "1920x1080p@24Hz", 24, 1920, 1080, 74250000, 148, 638, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 32, HDMI_1920X1080P_24HZ_4_3, 1, OUT_P888},
+ { { "1920x1080p@25Hz", 25, 1920, 1080, 74250000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 33, HDMI_1920X1080P_25HZ_4_3, 1, OUT_P888},
+ { { "1920x1080p@30Hz", 30, 1920, 1080, 74250000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 34, HDMI_1920X1080P_30HZ_4_3, 1, OUT_P888},
+ { { "1920x1080p@50Hz", 50, 1920, 1080, 148500000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 31, HDMI_1920X1080P_50HZ_4_3, 1, OUT_P888},
+ { { "1920x1080p@60Hz", 60, 1920, 1080, 148500000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 16, HDMI_1920X1080P_60HZ_4_3, 1, OUT_P888},
+ { { "3840x2160p@24Hz", 24, 3840, 2160, 297000000, 296, 1276, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 93, HDMI_3840X2160P_24HZ_4_3, 1, OUT_P888},
+ { { "3840x2160p@25Hz", 25, 3840, 2160, 297000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 94, HDMI_3840X2160P_25HZ_4_3, 1, OUT_P888},
+ { { "3840x2160p@30Hz", 30, 3840, 2160, 297000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 95, HDMI_3840X2160P_30HZ_4_3, 1, OUT_P888},
+ { { "4096x2160p@24Hz", 24, 4096, 2160, 297000000, 296, 1020, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 98, 0, 1, OUT_P888},
+ { { "4096x2160p@25Hz", 25, 4096, 2160, 297000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 99, 0, 1, OUT_P888},
+ { { "4096x2160p@30Hz", 30, 4096, 2160, 297000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 100, 0, 1, OUT_P888},
+ { { "3840x2160p@50Hz", 50, 3840, 2160, 594000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 96, HDMI_3840X2160P_50HZ_4_3, 1, OUT_P888},
+ { { "3840x2160p@60Hz", 60, 3840, 2160, 594000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 97, HDMI_3840X2160P_60HZ_4_3, 1, OUT_P888},
+ { { "4096x2160p@50Hz", 50, 4096, 2160, 594000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 101, 0, 1, OUT_P888},
+ { { "4096x2160p@60Hz", 60, 4096, 2160, 594000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 102, 0, 1, OUT_P888},
+};
+
+static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
+{
+ int i;
+ struct fb_videomode *mode;
+
+ if (screen == NULL || hdmi == NULL)
+ return HDMI_ERROR_FALSE;
+
+ if (hdmi->vic == 0)
+ hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ if (hdmi_mode[i].vic == (hdmi->vic & HDMI_VIC_MASK) ||
+ hdmi_mode[i].vic_2nd == (hdmi->vic & HDMI_VIC_MASK))
+ break;
+ }
+ if (i == ARRAY_SIZE(hdmi_mode))
+ return HDMI_ERROR_FALSE;
+
+ memset(screen, 0, sizeof(struct rk_screen));
+
+ /* screen type & face */
+ screen->type = SCREEN_HDMI;
+ screen->color_mode = COLOR_YCBCR;
+ if (hdmi->vic & HDMI_VIDEO_YUV420)
+ screen->face = OUT_YUV_420;
+ else
+ screen->face = hdmi_mode[i].interface;
+ screen->pixelrepeat = hdmi_mode[i].pixelrepeat - 1;
+ mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
+
+ screen->mode = *mode;
+
+ /* Pin polarity */
+ #ifdef CONFIG_HDMI_RK616
+ screen->pin_hsync = 0;
+ screen->pin_vsync = 0;
+ #else
+ if (FB_SYNC_HOR_HIGH_ACT & mode->sync)
+ screen->pin_hsync = 1;
+ else
+ screen->pin_hsync = 0;
+ if (FB_SYNC_VERT_HIGH_ACT & mode->sync)
+ screen->pin_vsync = 1;
+ else
+ screen->pin_vsync = 0;
+ #endif
+ screen->pin_den = 0;
+ screen->pin_dclk = 1;
+
+ /* Swap rule */
+ if (hdmi->soctype == HDMI_SOC_RK3368 &&
+ screen->color_mode == COLOR_YCBCR &&
+ screen->face == OUT_P888)
+ screen->swap_rb = 1;
+ else
+ 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;
+
+ screen->overscan.left = hdmi->xscale;
+ screen->overscan.top = hdmi->yscale;
+ screen->overscan.right = hdmi->xscale;
+ screen->overscan.bottom = hdmi->yscale;
+ return 0;
+}
+
+/**
+ * hdmi_find_best_mode: find the video mode nearest to input vic
+ * @hdmi:
+ * @vic: input vic
+ *
+ * NOTES:
+ * If vic is zero, return the high resolution video mode vic.
+ */
+int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
+{
+ struct list_head *pos, *head = &hdmi->edid.modelist;
+ struct display_modelist *modelist;
+ int found = 0;
+/* pr_info("%s vic %d\n", __FUNCTION__, vic); */
+ if (vic) {
+ list_for_each(pos, head) {
+ modelist =
+ list_entry(pos,
+ struct display_modelist, list);
+ if (modelist->vic == vic) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if ((vic == 0 || found == 0) && head->next != head) {
+ /* If parse edid error, we select default mode; */
+ if (hdmi->edid.specs == NULL ||
+ hdmi->edid.specs->modedb_len == 0)
+ return HDMI_VIDEO_DEFAULT_MODE;
+ /*modelist = list_entry(head->prev,
+ struct display_modelist, list);*/
+ else
+ modelist = list_entry(head->next,
+ struct display_modelist, list);
+ }
+
+ if (modelist != NULL)
+ return modelist->vic;
+ else
+ return 0;
+}
+/**
+ * hdmi_set_lcdc: switch lcdc mode to required video mode
+ * @hdmi:
+ *
+ * NOTES:
+ *
+ */
+int hdmi_set_lcdc(struct hdmi *hdmi)
+{
+ int rc = 0;
+ struct rk_screen screen;
+
+ if (hdmi->autoset)
+ hdmi->vic = hdmi_find_best_mode(hdmi, 0);
+ else
+ hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
+
+ if (hdmi->vic == 0)
+ hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
+
+ rc = hdmi_set_info(&screen, hdmi);
+
+ if (rc == 0)
+ rk_fb_switch_screen(&screen, 1, hdmi->lcdc->id);
+
+ return rc;
+}
+
+/**
+ * hdmi_videomode_compare - compare 2 videomodes
+ * @mode1: first videomode
+ * @mode2: second videomode
+ *
+ * RETURNS:
+ * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
+ */
+static int hdmi_videomode_compare(const struct fb_videomode *mode1,
+ const struct fb_videomode *mode2)
+{
+ if (mode1->xres > mode2->xres)
+ return 1;
+
+ if (mode1->xres == mode2->xres) {
+ if (mode1->yres > mode2->yres)
+ return 1;
+ if (mode1->yres == mode2->yres) {
+ if (mode1->vmode < mode2->vmode)
+ return 1;
+ if (mode1->pixclock > mode2->pixclock)
+ return 1;
+ if (mode1->pixclock == mode2->pixclock) {
+ if (mode1->refresh > mode2->refresh)
+ return 1;
+ if (mode1->refresh == mode2->refresh) {
+ if (mode2->flag > mode1->flag)
+ return 1;
+ if (mode2->flag < mode1->flag)
+ return -1;
+ if (mode2->vmode > mode1->vmode)
+ return 1;
+ if (mode2->vmode == mode1->vmode)
+ return 0;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+/**
+ * hdmi_add_vic - add entry to modelist according vic
+ * @vic: vic to be added
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+int hdmi_add_vic(int vic, struct list_head *head)
+{
+ struct list_head *pos;
+ struct display_modelist *modelist;
+ int found = 0, v;
+
+/* DBG("%s vic %d", __FUNCTION__, vic); */
+ if (vic == 0)
+ return -1;
+
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct display_modelist, list);
+ v = modelist->vic;
+ if (v == vic) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ modelist = kmalloc(sizeof(*modelist),
+ GFP_KERNEL);
+
+ if (!modelist)
+ return -ENOMEM;
+ memset(modelist, 0, sizeof(struct display_modelist));
+ modelist->vic = vic;
+ list_add_tail(&modelist->list, head);
+ }
+ return 0;
+}
+
+/**
+ * hdmi_add_videomode: adds videomode entry to modelist
+ * @mode: videomode to be added
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+static int hdmi_add_videomode(const struct fb_videomode *mode,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct display_modelist *modelist, *modelist_new;
+ struct fb_videomode *m;
+ int i, found = 0;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ m = (struct fb_videomode *)&(hdmi_mode[i].mode);
+ if (fb_mode_is_equal(m, mode)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ list_for_each(pos, head) {
+ modelist = list_entry(pos,
+ struct display_modelist, list);
+ m = &modelist->mode;
+ if (fb_mode_is_equal(m, mode))
+ return 0;
+ else if (hdmi_videomode_compare(m, mode) == -1)
+ break;
+ }
+
+ modelist_new = kmalloc(sizeof(*modelist_new), GFP_KERNEL);
+ if (!modelist_new)
+ return -ENOMEM;
+ memset(modelist_new, 0, sizeof(struct display_modelist));
+ modelist_new->mode = hdmi_mode[i].mode;
+ modelist_new->vic = hdmi_mode[i].vic;
+ list_add_tail(&modelist_new->list, pos);
+ }
+
+ return 0;
+}
+
+/**
+ * hdmi_show_sink_info: show hdmi sink device infomation
+ * @hdmi: handle of hdmi
+ */
+static void hdmi_show_sink_info(struct hdmi *hdmi)
+{
+ struct list_head *pos, *head = &hdmi->edid.modelist;
+ struct display_modelist *modelist;
+ struct fb_videomode *m;
+ int i;
+ struct hdmi_audio *audio;
+
+ pr_info("******** Show Sink Info ********\n");
+ pr_info("Max tmds clk is %u\n", hdmi->edid.maxtmdsclock);
+ if (hdmi->edid.hf_vsdb_version)
+ pr_info("Support HFVSDB\n");
+ if (hdmi->edid.scdc_present)
+ pr_info("Support SCDC\n");
+ pr_info("Support video mode:\n");
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct display_modelist, list);
+ m = &modelist->mode;
+ if (m->flag)
+ pr_info(" %s(YCbCr420)\n", m->name);
+ else
+ pr_info(" %s\n", m->name);
+ }
+ pr_info("Support video color mode:\n");
+ pr_info(" RGB\n");
+ if (hdmi->edid.ycbcr420)
+ pr_info(" YCbCr420\n");
+ if (hdmi->edid.ycbcr422)
+ pr_info(" YCbCr422\n");
+ if (hdmi->edid.ycbcr444)
+ pr_info(" YCbCr444\n");
+ pr_info("Support video color depth:\n");
+ pr_info(" 24bit\n");
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS)
+ pr_info(" 30bit\n");
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS)
+ pr_info(" 36bit\n");
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS)
+ pr_info(" 48bit\n");
+
+ pr_info("Support audio type:\n");
+ for (i = 0; i < hdmi->edid.audio_num; i++) {
+ audio = &(hdmi->edid.audio[i]);
+ switch (audio->type) {
+ case HDMI_AUDIO_LPCM:
+ pr_info(" LPCM\n");
+ break;
+ case HDMI_AUDIO_AC3:
+ pr_info(" AC3\n");
+ break;
+ case HDMI_AUDIO_MPEG1:
+ pr_info(" MPEG1\n");
+ break;
+ case HDMI_AUDIO_MP3:
+ pr_info(" MP3\n");
+ break;
+ case HDMI_AUDIO_MPEG2:
+ pr_info(" MPEG2\n");
+ break;
+ case HDMI_AUDIO_AAC_LC:
+ pr_info("S AAC\n");
+ break;
+ case HDMI_AUDIO_DTS:
+ pr_info(" DTS\n");
+ break;
+ case HDMI_AUDIO_ATARC:
+ pr_info(" ATARC\n");
+ break;
+ case HDMI_AUDIO_DSD:
+ pr_info(" DSD\n");
+ break;
+ case HDMI_AUDIO_E_AC3:
+ pr_info(" E-AC3\n");
+ break;
+ case HDMI_AUDIO_DTS_HD:
+ pr_info(" DTS-HD\n");
+ break;
+ case HDMI_AUDIO_MLP:
+ pr_info(" MLP\n");
+ break;
+ case HDMI_AUDIO_DST:
+ pr_info(" DST\n");
+ break;
+ case HDMI_AUDIO_WMA_PRO:
+ pr_info(" WMP-PRO\n");
+ break;
+ default:
+ pr_info(" Unkown\n");
+ break;
+ }
+ pr_info("Support max audio channel is %d\n", audio->channel);
+ pr_info("Support audio sample rate:\n");
+ if (audio->rate & HDMI_AUDIO_FS_32000)
+ pr_info(" 32000\n");
+ if (audio->rate & HDMI_AUDIO_FS_44100)
+ pr_info(" 44100\n");
+ if (audio->rate & HDMI_AUDIO_FS_48000)
+ pr_info(" 48000\n");
+ if (audio->rate & HDMI_AUDIO_FS_88200)
+ pr_info(" 88200\n");
+ if (audio->rate & HDMI_AUDIO_FS_96000)
+ pr_info(" 96000\n");
+ if (audio->rate & HDMI_AUDIO_FS_176400)
+ pr_info(" 176400\n");
+ if (audio->rate & HDMI_AUDIO_FS_192000)
+ pr_info(" 192000\n");
+ pr_info("Support audio word lenght:\n");
+ if (audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
+ pr_info(" 16bit\n");
+ if (audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
+ pr_info(" 20bit\n");
+ if (audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
+ pr_info(" 24bit\n");
+ pr_info("\n");
+ }
+ pr_info("******** Show Sink Info ********\n");
+}
+
+/**
+ * hdmi_sort_modelist: sort modelist of edid
+ * @edid: edid to be sort
+ */
+static void hdmi_sort_modelist(struct hdmi_edid *edid, int feature)
+{
+ struct list_head *pos, *pos_new;
+ struct list_head head_new, *head = &edid->modelist;
+ struct display_modelist *modelist, *modelist_new, *modelist_n;
+ struct fb_videomode *m, *m_new;
+ int i, compare, vic;
+
+ INIT_LIST_HEAD(&head_new);
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct display_modelist, list);
+ /*pr_info("%s vic %d\n", __function__, modelist->vic);*/
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ vic = modelist->vic & HDMI_VIC_MASK;
+ if (vic == hdmi_mode[i].vic ||
+ vic == hdmi_mode[i].vic_2nd) {
+ if ((feature & SUPPORT_TMDS_600M) == 0 &&
+ !(modelist->vic & HDMI_VIDEO_YUV420) &&
+ hdmi_mode[i].mode.pixclock > 340000000 &&
+ edid->maxtmdsclock < 340000000)
+ continue;
+ if ((feature & SUPPORT_4K) == 0 &&
+ hdmi_mode[i].mode.xres >= 3840)
+ continue;
+ if ((feature & SUPPORT_4K_4096) == 0 &&
+ hdmi_mode[i].mode.xres == 4096)
+ continue;
+ if ((modelist->vic & HDMI_VIDEO_YUV420) &&
+ (feature & SUPPORT_YUV420) == 0)
+ continue;
+ if ((feature & SUPPORT_1080I) == 0 &&
+ hdmi_mode[i].mode.xres == 1920 &&
+ hdmi_mode[i].mode.vmode ==
+ FB_VMODE_INTERLACED)
+ continue;
+ if ((feature & SUPPORT_480I_576I) == 0 &&
+ hdmi_mode[i].mode.xres == 720 &&
+ hdmi_mode[i].mode.vmode ==
+ FB_VMODE_INTERLACED)
+ continue;
+ vic = modelist->vic;
+ modelist->vic = hdmi_mode[i].vic;
+ modelist->mode = hdmi_mode[i].mode;
+ if (vic & HDMI_VIDEO_YUV420) {
+ modelist->vic |= HDMI_VIDEO_YUV420;
+ modelist->mode.flag = 1;
+ }
+ compare = 1;
+ m = (struct fb_videomode *)&(modelist->mode);
+ list_for_each(pos_new, &head_new) {
+ modelist_new =
+ list_entry(pos_new,
+ struct display_modelist,
+ list);
+ m_new = &modelist_new->mode;
+ compare =
+ hdmi_videomode_compare(m, m_new);
+ if (compare != -1)
+ break;
+ }
+ if (compare != 0) {
+ modelist_n =
+ kmalloc(sizeof(*modelist_n),
+ GFP_KERNEL);
+ if (!modelist_n)
+ return;
+ *modelist_n = *modelist;
+ list_add_tail(&modelist_n->list,
+ pos_new);
+ }
+ break;
+ }
+ }
+ }
+ fb_destroy_modelist(head);
+
+ edid->modelist = head_new;
+ edid->modelist.prev->next = &edid->modelist;
+}
+
+/**
+ * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
+ * @hdmi: handle of hdmi
+ * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
+ */
+int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
+{
+ struct list_head *head = &hdmi->edid.modelist;
+ struct fb_monspecs *specs = hdmi->edid.specs;
+ struct fb_videomode *modedb = NULL, *mode = NULL;
+ int i, pixclock;
+
+ if (edid_ok != HDMI_ERROR_SUCESS) {
+ dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
+ hdmi->edid.sink_hdmi = 1;
+ hdmi->edid.baseaudio_support = 1;
+ hdmi->edid.ycbcr444 = 0;
+ hdmi->edid.ycbcr422 = 0;
+ }
+
+ if (head->next == head) {
+ dev_info(hdmi->dev,
+ "warning: no CEA video mode parsed from EDID !!!!\n");
+ /* If EDID get error, list all system supported mode.
+ If output mode is set to DVI and EDID is ok, check
+ the output timing.
+ */
+ if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
+ /* Get max resolution timing */
+ modedb = &specs->modedb[0];
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].xres > modedb->xres)
+ modedb = &specs->modedb[i];
+ else if (specs->modedb[i].xres ==
+ modedb->xres &&
+ specs->modedb[i].yres > modedb->yres)
+ modedb = &specs->modedb[i];
+ }
+ /* For some monitor, the max pixclock read from EDID
+ is smaller than the clock of max resolution mode
+ supported. We fix it. */
+ pixclock = PICOS2KHZ(modedb->pixclock);
+ pixclock /= 250;
+ pixclock *= 250;
+ pixclock *= 1000;
+ if (pixclock == 148250000)
+ pixclock = 148500000;
+ if (pixclock > specs->dclkmax)
+ specs->dclkmax = pixclock;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
+ if (modedb) {
+ if ((mode->pixclock < specs->dclkmin) ||
+ (mode->pixclock > specs->dclkmax) ||
+ (mode->refresh < specs->vfmin) ||
+ (mode->refresh > specs->vfmax) ||
+ (mode->xres > modedb->xres) ||
+ (mode->yres > modedb->yres))
+ continue;
+ } else {
+ if (!(hdmi->property->feature & SUPPORT_4K) &&
+ mode->xres >= 3840)
+ continue;
+ else if (mode->pixclock > 340000000)
+ continue;
+ }
+ hdmi_add_videomode(mode, head);
+ }
+ } else {
+ hdmi_sort_modelist(&hdmi->edid, hdmi->property->feature);
+ }
+ hdmi_show_sink_info(hdmi);
+
+ return HDMI_ERROR_SUCESS;
+}
+
+/**
+ * hdmi_videomode_to_vic: transverse video mode to vic
+ * @vmode: videomode to transverse
+ *
+ */
+int hdmi_videomode_to_vic(struct fb_videomode *vmode)
+{
+ struct fb_videomode *mode;
+ unsigned char vic = 0;
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
+ if (vmode->vmode == mode->vmode &&
+ vmode->refresh == mode->refresh &&
+ vmode->xres == mode->xres &&
+ vmode->yres == mode->yres &&
+ vmode->left_margin == mode->left_margin &&
+ vmode->right_margin == mode->right_margin &&
+ vmode->upper_margin == mode->upper_margin &&
+ vmode->lower_margin == mode->lower_margin &&
+ vmode->hsync_len == mode->hsync_len &&
+ vmode->vsync_len == mode->vsync_len) {
+ vic = hdmi_mode[i].vic;
+ break;
+ }
+ }
+ return vic;
+}
+
+/**
+ * hdmi_vic2timing: transverse vic mode to video timing
+ * @vmode: vic to transverse
+ *
+ */
+const struct hdmi_video_timing *hdmi_vic2timing(int vic)
+{
+ int i;
+
+ if (vic == 0)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ if (hdmi_mode[i].vic == vic || hdmi_mode[i].vic_2nd == vic)
+ return &(hdmi_mode[i]);
+ }
+ return NULL;
+}
+
+/**
+ * hdmi_vic_to_videomode: transverse vic mode to video mode
+ * @vmode: vic to transverse
+ *
+ */
+const struct fb_videomode *hdmi_vic_to_videomode(int vic)
+{
+ int i;
+
+ if (vic == 0)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ if (hdmi_mode[i].vic == (vic & HDMI_VIC_MASK) ||
+ hdmi_mode[i].vic_2nd == (vic & HDMI_VIC_MASK))
+ return &hdmi_mode[i].mode;
+ }
+ return NULL;
+}
+
+/**
+ * hdmi_init_modelist: initial hdmi mode list
+ * @hdmi:
+ *
+ * NOTES:
+ *
+ */
+void hdmi_init_modelist(struct hdmi *hdmi)
+{
+ int i, feature;
+ struct list_head *head = &hdmi->edid.modelist;
+
+ feature = hdmi->property->feature;
+ INIT_LIST_HEAD(&hdmi->edid.modelist);
+ for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+ if ((feature & SUPPORT_TMDS_600M) == 0 &&
+ hdmi_mode[i].mode.pixclock > 340000000)
+ continue;
+ if ((feature & SUPPORT_4K) == 0 &&
+ hdmi_mode[i].mode.xres >= 3840)
+ continue;
+ if ((feature & SUPPORT_4K_4096) == 0 &&
+ hdmi_mode[i].mode.xres == 4096)
+ continue;
+ if ((feature & SUPPORT_1080I) == 0 &&
+ hdmi_mode[i].mode.xres == 1920 &&
+ hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
+ continue;
+ if ((feature & SUPPORT_480I_576I) == 0 &&
+ hdmi_mode[i].mode.xres == 720 &&
+ hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
+ continue;
+ hdmi_add_videomode(&(hdmi_mode[i].mode), head);
+ }
+}
--- /dev/null
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#include <linux/interrupt.h>
+#include "rockchip-hdmi.h"
+
+static int hdmi_get_enable(struct rk_display_device *device)
+{
+ struct hdmi *hdmi = device->priv_data;
+ int enable;
+
+ enable = hdmi->enable;
+ return enable;
+}
+
+static int hdmi_set_enable(struct rk_display_device *device, int enable)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (enable == 0)
+ hdmi_submit_work(hdmi, HDMI_DISABLE_CTL, 0, NULL);
+ else
+ hdmi_submit_work(hdmi, HDMI_ENABLE_CTL, 0, NULL);
+ return 0;
+}
+
+static int hdmi_get_status(struct rk_display_device *device)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED)
+ return 1;
+ else
+ return 0;
+}
+
+static int hdmi_get_modelist(struct rk_display_device *device,
+ struct list_head **modelist)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ mutex_lock(&hdmi->lock);
+ *modelist = &hdmi->edid.modelist;
+ mutex_unlock(&hdmi->lock);
+ return 0;
+}
+
+static int hdmi_set_mode(struct rk_display_device *device,
+ struct fb_videomode *mode)
+{
+ struct hdmi *hdmi = device->priv_data;
+ struct display_modelist *display_modelist =
+ container_of(mode, struct display_modelist, mode);
+ int vic = 0;
+
+ if (mode == NULL) {
+ hdmi->autoset = 1;
+ vic = hdmi_find_best_mode(hdmi, 0);
+ } else {
+ hdmi->autoset = 0;
+ vic = display_modelist->vic;
+ }
+
+ if (vic && hdmi->vic != vic) {
+ hdmi->vic = vic;
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED)
+ hdmi_submit_work(hdmi, HDMI_SET_VIDEO, 0, NULL);
+ }
+ return 0;
+}
+
+static int hdmi_get_mode(struct rk_display_device *device,
+ struct fb_videomode *mode)
+{
+ struct hdmi *hdmi = device->priv_data;
+ struct fb_videomode *vmode;
+
+ if (mode == NULL)
+ return -1;
+
+ if (hdmi->vic) {
+ vmode = (struct fb_videomode *)
+ hdmi_vic_to_videomode(hdmi->vic);
+ if (unlikely(vmode == NULL))
+ return -1;
+ *mode = *vmode;
+ if (hdmi->vic & HDMI_VIDEO_YUV420)
+ mode->flag = 1;
+ } else {
+ memset(mode, 0, sizeof(struct fb_videomode));
+ }
+ return 0;
+}
+
+static int hdmi_set_3dmode(struct rk_display_device *device, int mode)
+{
+ struct hdmi *hdmi = device->priv_data;
+ struct list_head *modelist, *pos;
+ struct display_modelist *display_modelist = NULL;
+
+ if (!hdmi)
+ return -1;
+ mutex_lock(&hdmi->lock);
+ modelist = &hdmi->edid.modelist;
+ list_for_each(pos, modelist) {
+ display_modelist =
+ list_entry(pos, struct display_modelist, list);
+ if (hdmi->vic == display_modelist->vic)
+ break;
+ else
+ display_modelist = NULL;
+ }
+ mutex_unlock(&hdmi->lock);
+ if (!display_modelist)
+ return -1;
+
+ if ((mode != HDMI_3D_NONE) &&
+ ((display_modelist->format_3d & (1 << mode)) == 0))
+ return -1;
+
+ if (hdmi->mode_3d != mode) {
+ hdmi->mode_3d = mode;
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED)
+ hdmi_submit_work(hdmi, HDMI_SET_3D, 0, NULL);
+ }
+ return 0;
+}
+
+static int hdmi_get_3dmode(struct rk_display_device *device)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (!hdmi)
+ return -1;
+ else
+ return hdmi->mode_3d;
+}
+
+/*CEA 861-E: Audio Coding Type
+ sync width enum hdmi_audio_type
+*/
+static const char * const audioformatstr[] = {
+ "",
+ "LPCM", /*HDMI_AUDIO_LPCM = 1,*/
+ "AC3", /*HDMI_AUDIO_AC3,*/
+ "MPEG1", /*HDMI_AUDIO_MPEG1,*/
+ "MP3", /*HDMI_AUDIO_MP3,*/
+ "MPEG2", /*HDMI_AUDIO_MPEG2,*/
+ "AAC-LC", /*HDMI_AUDIO_AAC_LC, AAC*/
+ "DTS", /*HDMI_AUDIO_DTS,*/
+ "ATARC", /*HDMI_AUDIO_ATARC,*/
+ "DSD", /*HDMI_AUDIO_DSD, One bit Audio */
+ "E-AC3", /*HDMI_AUDIO_E_AC3,*/
+ "DTS-HD", /*HDMI_AUDIO_DTS_HD,*/
+ "MLP", /*HDMI_AUDIO_MLP,*/
+ "DST", /*HDMI_AUDIO_DST,*/
+ "WMA-PRO", /*HDMI_AUDIO_WMA_PRO*/
+};
+
+static int hdmi_get_edidaudioinfo(struct rk_display_device *device,
+ char *audioinfo, int len)
+{
+ struct hdmi *hdmi = device->priv_data;
+ int i = 0, size = 0;
+ struct hdmi_audio *audio;
+
+ if (!hdmi)
+ return -1;
+
+ memset(audioinfo, 0x00, len);
+ mutex_lock(&hdmi->lock);
+ /*printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);*/
+ for (i = 0; i < hdmi->edid.audio_num; i++) {
+ audio = &(hdmi->edid.audio[i]);
+ if (audio->type < 1 || audio->type > HDMI_AUDIO_WMA_PRO) {
+ pr_info("audio type: unsupported.");
+ continue;
+ }
+ size = strlen(audioformatstr[audio->type]);
+ memcpy(audioinfo, audioformatstr[audio->type], size);
+ audioinfo[size] = ',';
+ audioinfo += (size+1);
+ }
+ mutex_unlock(&hdmi->lock);
+ return 0;
+}
+
+static int hdmi_get_color(struct rk_display_device *device, char *buf)
+{
+ struct hdmi *hdmi = device->priv_data;
+ int i, mode;
+
+ mutex_lock(&hdmi->lock);
+ mode = (1 << HDMI_COLOR_RGB_0_255);
+ if (hdmi->edid.sink_hdmi) {
+ mode |= (1 << HDMI_COLOR_RGB_16_235);
+ if (hdmi->edid.ycbcr422)
+ mode |= (1 << HDMI_COLOR_YCBCR422);
+ if (hdmi->edid.ycbcr444)
+ mode |= (1 << HDMI_COLOR_YCBCR444);
+ }
+ i = snprintf(buf, PAGE_SIZE,
+ "Supported Color Mode: %d\n", mode);
+ i += snprintf(buf + i, PAGE_SIZE - i,
+ "Current Color Mode: %d\n", hdmi->colormode);
+
+ mode = (1 << 1); /* 24 bit*/
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS &&
+ hdmi->property->feature & SUPPORT_DEEP_10BIT)
+ mode |= (1 << HDMI_DEEP_COLOR_30BITS);
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS &&
+ hdmi->property->feature & SUPPORT_DEEP_12BIT)
+ mode |= (1 << HDMI_DEEP_COLOR_36BITS);
+ if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS &&
+ hdmi->property->feature & SUPPORT_DEEP_16BIT)
+ mode |= (1 << HDMI_DEEP_COLOR_48BITS);
+ i += snprintf(buf + i, PAGE_SIZE - i,
+ "Supported Color Depth: %d\n", mode);
+ i += snprintf(buf + i, PAGE_SIZE - i,
+ "Current Color Depth: %d\n", hdmi->colordepth);
+ mutex_unlock(&hdmi->lock);
+ return i;
+}
+
+static int hdmi_set_color(struct rk_display_device *device,
+ const char *buf, int len)
+{
+ struct hdmi *hdmi = device->priv_data;
+ int value;
+
+ if (!strncmp(buf, "mode", 4)) {
+ if (sscanf(buf, "mode=%d", &value) == -1)
+ return -1;
+ pr_debug("current mode is %d input mode is %d\n",
+ hdmi->colormode, value);
+ if (hdmi->colormode != value)
+ hdmi->colormode = value;
+ } else if (!strncmp(buf, "depth", 5)) {
+ if (sscanf(buf, "depth=%d", &value) == -1)
+ return -1;
+ pr_debug("current depth is %d input mode is %d\n",
+ hdmi->colordepth, value);
+ if (hdmi->colordepth != value)
+ hdmi->colordepth = value;
+ } else {
+ pr_err("%s unkown event\n", __func__);
+ return -1;
+ }
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED)
+ hdmi_submit_work(hdmi, HDMI_SET_COLOR, 0, NULL);
+ return 0;
+}
+
+static int hdmi_set_scale(struct rk_display_device *device, int direction,
+ int value)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (!hdmi || value < 0 || value > 100)
+ return -1;
+
+ if (!hdmi->hotplug)
+ return 0;
+
+ if (direction == DISPLAY_SCALE_X)
+ hdmi->xscale = value;
+ else if (direction == DISPLAY_SCALE_Y)
+ hdmi->yscale = value;
+ else
+ return -1;
+ rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
+ return 0;
+}
+
+static int hdmi_get_scale(struct rk_display_device *device, int direction)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (!hdmi)
+ return -1;
+
+ if (direction == DISPLAY_SCALE_X)
+ return hdmi->xscale;
+ else if (direction == DISPLAY_SCALE_Y)
+ return hdmi->yscale;
+ else
+ return -1;
+}
+
+static int hdmi_get_monspecs(struct rk_display_device *device,
+ struct fb_monspecs *monspecs)
+{
+ struct hdmi *hdmi = device->priv_data;
+
+ if (!hdmi)
+ return -1;
+
+ mutex_lock(&hdmi->lock);
+ if (hdmi->edid.specs)
+ *monspecs = *(hdmi->edid.specs);
+ mutex_unlock(&hdmi->lock);
+ return 0;
+}
+
+static struct rk_display_ops hdmi_display_ops = {
+ .setenable = hdmi_set_enable,
+ .getenable = hdmi_get_enable,
+ .getstatus = hdmi_get_status,
+ .getmodelist = hdmi_get_modelist,
+ .setmode = hdmi_set_mode,
+ .getmode = hdmi_get_mode,
+ .set3dmode = hdmi_set_3dmode,
+ .get3dmode = hdmi_get_3dmode,
+ .getedidaudioinfo = hdmi_get_edidaudioinfo,
+ .setcolor = hdmi_set_color,
+ .getcolor = hdmi_get_color,
+ .getmonspecs = hdmi_get_monspecs,
+ .setscale = hdmi_set_scale,
+ .getscale = hdmi_get_scale,
+};
+
+static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
+{
+ struct hdmi *hdmi = devdata;
+
+ device->owner = THIS_MODULE;
+ strcpy(device->type, "HDMI");
+ device->priority = DISPLAY_PRIORITY_HDMI;
+ device->name = hdmi->property->name;
+ device->property = hdmi->property->display;
+ device->priv_data = devdata;
+ device->ops = &hdmi_display_ops;
+ return 1;
+}
+
+static struct rk_display_driver display_hdmi = {
+ .probe = hdmi_display_probe,
+};
+
+struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
+ struct device *parent)
+{
+ return rk_display_device_register(&display_hdmi, parent, hdmi);
+}
+
+void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
+{
+ if (hdmi->ddev)
+ rk_display_device_unregister(hdmi->ddev);
+}
--- /dev/null
+#ifndef __ROCKCHIP_HDMI_H__
+#define __ROCKCHIP_HDMI_H__
+
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#include <linux/display-sys.h>
+#ifdef CONFIG_SWITCH
+#include <linux/switch.h>
+#endif
+
+#define HDMI_VIDEO_NORMAL (0 << 8)
+#define HDMI_VIDEO_EXT (1 << 8)
+#define HDMI_VIDEO_3D (2 << 8)
+#define HDMI_VIDEO_DVI (3 << 8)
+#define HDMI_VIDEO_YUV420 (4 << 8)
+#define HDMI_VIC_MASK (0xFF)
+#define HDMI_TYPE_MASK (0xFF << 8)
+#define HDMI_MAX_ID 4
+
+/* HDMI video information code according CEA-861-F */
+enum hdmi_video_infomation_code {
+ HDMI_640X480P_60HZ = 1,
+ HDMI_720X480P_60HZ_4_3,
+ HDMI_720X480P_60HZ_16_9,
+ HDMI_1280X720P_60HZ,
+ HDMI_1920X1080I_60HZ, /*5*/
+ HDMI_720X480I_60HZ_4_3,
+ HDMI_720X480I_60HZ_16_9,
+ HDMI_720X240P_60HZ_4_3,
+ HDMI_720X240P_60HZ_16_9,
+ HDMI_2880X480I_60HZ_4_3, /*10*/
+ HDMI_2880X480I_60HZ_16_9,
+ HDMI_2880X240P_60HZ_4_3,
+ HDMI_2880X240P_60HZ_16_9,
+ HDMI_1440X480P_60HZ_4_3,
+ HDMI_1440X480P_60HZ_16_9, /*15*/
+ HDMI_1920X1080P_60HZ,
+ HDMI_720X576P_50HZ_4_3,
+ HDMI_720X576P_50HZ_16_9,
+ HDMI_1280X720P_50HZ,
+ HDMI_1920X1080I_50HZ, /*20*/
+ HDMI_720X576I_50HZ_4_3,
+ HDMI_720X576I_50HZ_16_9,
+ HDMI_720X288P_50HZ_4_3,
+ HDMI_720X288P_50HZ_16_9,
+ HDMI_2880X576I_50HZ_4_3, /*25*/
+ HDMI_2880X576I_50HZ_16_9,
+ HDMI_2880X288P_50HZ_4_3,
+ HDMI_2880X288P_50HZ_16_9,
+ HDMI_1440X576P_50HZ_4_3,
+ HDMI_1440X576P_50HZ_16_9, /*30*/
+ HDMI_1920X1080P_50HZ,
+ HDMI_1920X1080P_24HZ,
+ HDMI_1920X1080P_25HZ,
+ HDMI_1920X1080P_30HZ,
+ HDMI_2880X480P_60HZ_4_3, /*35*/
+ HDMI_2880X480P_60HZ_16_9,
+ HDMI_2880X576P_50HZ_4_3,
+ HDMI_2880X576P_50HZ_16_9,
+ HDMI_1920X1080I_50HZ_1250, /* V Line 1250 total*/
+ HDMI_1920X1080I_100HZ, /*40*/
+ HDMI_1280X720P_100HZ,
+ HDMI_720X576P_100HZ_4_3,
+ HDMI_720X576P_100HZ_16_9,
+ HDMI_720X576I_100HZ_4_3,
+ HDMI_720X576I_100HZ_16_9, /*45*/
+ HDMI_1920X1080I_120HZ,
+ HDMI_1280X720P_120HZ,
+ HDMI_720X480P_120HZ_4_3,
+ HDMI_720X480P_120HZ_16_9,
+ HDMI_720X480I_120HZ_4_3, /*50*/
+ HDMI_720X480I_120HZ_16_9,
+ HDMI_720X576P_200HZ_4_3,
+ HDMI_720X576P_200HZ_16_9,
+ HDMI_720X576I_200HZ_4_3,
+ HDMI_720X576I_200HZ_16_9, /*55*/
+ HDMI_720X480P_240HZ_4_3,
+ HDMI_720X480P_240HZ_16_9,
+ HDMI_720X480I_240HZ_4_3,
+ HDMI_720X480I_240HZ_16_9,
+ HDMI_1280X720P_24HZ, /*60*/
+ HDMI_1280X720P_25HZ,
+ HDMI_1280X720P_30HZ,
+ HDMI_1920X1080P_120HZ,
+ HDMI_1920X1080P_100HZ,
+ HDMI_1280X720P_24HZ_4_3, /*65*/
+ HDMI_1280X720P_25HZ_4_3,
+ HDMI_1280X720P_30HZ_4_3,
+ HDMI_1280X720P_50HZ_4_3,
+ HDMI_1280X720P_60HZ_4_3,
+ HDMI_1280X720P_100HZ_4_3, /*70*/
+ HDMI_1280X720P_120HZ_4_3,
+ HDMI_1920X1080P_24HZ_4_3,
+ HDMI_1920X1080P_25HZ_4_3,
+ HDMI_1920X1080P_30HZ_4_3,
+ HDMI_1920X1080P_50HZ_4_3, /*75*/
+ HDMI_1920X1080P_60HZ_4_3,
+ HDMI_1920X1080P_100HZ_4_3,
+ HDMI_1920X1080P_120HZ_4_3,
+ HDMI_1680X720P_24HZ,
+ HDMI_1680X720P_25HZ, /*80*/
+ HDMI_1680X720P_30HZ,
+ HDMI_1680X720P_50HZ,
+ HDMI_1680X720P_60HZ,
+ HDMI_1680X720P_100HZ,
+ HDMI_1680X720P_120HZ, /*85*/
+ HDMI_2560X1080P_24HZ,
+ HDMI_2560X1080P_25HZ,
+ HDMI_2560X1080P_30HZ,
+ HDMI_2560X1080P_50HZ,
+ HDMI_2560X1080P_60HZ, /*90*/
+ HDMI_2560X1080P_100HZ,
+ HDMI_2560X1080P_120HZ,
+ HDMI_3840X2160P_24HZ,
+ HDMI_3840X2160P_25HZ,
+ HDMI_3840X2160P_30HZ, /*95*/
+ HDMI_3840X2160P_50HZ,
+ HDMI_3840X2160P_60HZ,
+ HDMI_4096X2160P_24HZ,
+ HDMI_4096X2160P_25HZ,
+ HDMI_4096X2160P_30HZ, /*100*/
+ HDMI_4096X2160P_50HZ,
+ HDMI_4096X2160P_60HZ,
+ HDMI_3840X2160P_24HZ_4_3,
+ HDMI_3840X2160P_25HZ_4_3,
+ HDMI_3840X2160P_30HZ_4_3, /*105*/
+ HDMI_3840X2160P_50HZ_4_3,
+ HDMI_3840X2160P_60HZ_4_3,
+};
+
+/* HDMI Extended Resolution */
+enum {
+ HDMI_VIC_4KX2K_30HZ = 1,
+ HDMI_VIC_4KX2K_25HZ,
+ HDMI_VIC_4KX2K_24HZ,
+ HDMI_VIC_4KX2K_24HZ_SMPTE
+};
+
+/* HDMI Video Format */
+enum {
+ HDMI_VIDEO_FORMAT_NORMAL = 0,
+ HDMI_VIDEO_FORMAT_4KX2K,
+ HDMI_VIDEO_FORMAT_3D,
+};
+
+/* HDMI 3D type */
+enum {
+ HDMI_3D_NONE = -1,
+ HDMI_3D_FRAME_PACKING = 0,
+ HDMI_3D_TOP_BOOTOM = 6,
+ HDMI_3D_SIDE_BY_SIDE_HALF = 8,
+};
+
+/* HDMI Video Data Color Mode */
+enum hdmi_video_color_mode {
+ HDMI_COLOR_AUTO = 0,
+ HDMI_COLOR_RGB_0_255,
+ HDMI_COLOR_RGB_16_235,
+ HDMI_COLOR_YCBCR444,
+ HDMI_COLOR_YCBCR422,
+ HDMI_COLOR_YCBCR420
+};
+
+/* HDMI Video Data Color Depth */
+enum hdmi_deep_color {
+ HDMI_DEPP_COLOR_AUTO = 0,
+ HDMI_DEEP_COLOR_Y444 = 0x1,
+ HDMI_DEEP_COLOR_30BITS = 0x2,
+ HDMI_DEEP_COLOR_36BITS = 0x4,
+ HDMI_DEEP_COLOR_48BITS = 0x8,
+};
+
+/* HDMI Audio source */
+enum {
+ HDMI_AUDIO_SRC_IIS = 0,
+ HDMI_AUDIO_SRC_SPDIF
+};
+
+/* HDMI Audio Type */
+enum hdmi_audio_type {
+ HDMI_AUDIO_NLPCM = 0,
+ HDMI_AUDIO_LPCM = 1,
+ HDMI_AUDIO_AC3,
+ HDMI_AUDIO_MPEG1,
+ HDMI_AUDIO_MP3,
+ HDMI_AUDIO_MPEG2,
+ HDMI_AUDIO_AAC_LC, /*AAC */
+ HDMI_AUDIO_DTS,
+ HDMI_AUDIO_ATARC,
+ HDMI_AUDIO_DSD, /* One bit Audio */
+ HDMI_AUDIO_E_AC3,
+ HDMI_AUDIO_DTS_HD,
+ HDMI_AUDIO_MLP,
+ HDMI_AUDIO_DST,
+ HDMI_AUDIO_WMA_PRO
+};
+
+/* HDMI Audio Sample Rate */
+enum hdmi_audio_samplerate {
+ HDMI_AUDIO_FS_32000 = 0x1,
+ HDMI_AUDIO_FS_44100 = 0x2,
+ HDMI_AUDIO_FS_48000 = 0x4,
+ HDMI_AUDIO_FS_88200 = 0x8,
+ HDMI_AUDIO_FS_96000 = 0x10,
+ HDMI_AUDIO_FS_176400 = 0x20,
+ HDMI_AUDIO_FS_192000 = 0x40
+};
+
+/* HDMI Audio Word Length */
+enum hdmi_audio_word_length {
+ HDMI_AUDIO_WORD_LENGTH_16bit = 0x1,
+ HDMI_AUDIO_WORD_LENGTH_20bit = 0x2,
+ HDMI_AUDIO_WORD_LENGTH_24bit = 0x4
+};
+
+/* HDMI Hotplug Status */
+enum hdmi_hotpulg_status {
+ HDMI_HPD_REMOVED = 0, /* HDMI is disconnected */
+ HDMI_HPD_INSERT, /* HDMI is connected, but HDP is low
+ or TMDS link is not pull up to 3.3V*/
+ HDMI_HPD_ACTIVED /* HDMI is connected, all singnal
+ is normal */
+};
+
+enum hdmi_mute_status {
+ HDMI_AV_UNMUTE = 0,
+ HDMI_VIDEO_MUTE = 0x1,
+ HDMI_AUDIO_MUTE = 0x2,
+};
+
+/* HDMI Error Code */
+enum hdmi_error_code {
+ HDMI_ERROR_SUCESS = 0,
+ HDMI_ERROR_FALSE,
+ HDMI_ERROR_I2C,
+ HDMI_ERROR_EDID,
+};
+
+/* HDMI Video Timing */
+struct hdmi_video_timing {
+ struct fb_videomode mode; /* Video timing*/
+ unsigned int vic; /* Video information code*/
+ unsigned int vic_2nd;
+ unsigned int pixelrepeat; /* Video pixel repeat rate*/
+ unsigned int interface; /* Video input interface*/
+};
+
+/* HDMI Video Parameters */
+struct hdmi_video {
+ unsigned int vic; /* Video information code*/
+ unsigned int color_input; /* Input video color mode*/
+ unsigned int color_output; /* Output video color mode*/
+ unsigned int color_output_depth;/* Output video Color Depth*/
+ unsigned int sink_hdmi; /* Output signal is DVI or HDMI*/
+ unsigned int format_3d; /* Output 3D mode*/
+};
+
+/* HDMI Audio Parameters */
+struct hdmi_audio {
+ u32 type; /*Audio type*/
+ u32 channel; /*Audio channel number*/
+ u32 rate; /*Audio sampling rate*/
+ u32 word_length; /*Audio data word length*/
+};
+
+/* HDMI EDID Information */
+struct hdmi_edid {
+ unsigned char sink_hdmi; /*HDMI display device flag*/
+ unsigned char ycbcr444; /*Display device support YCbCr444*/
+ unsigned char ycbcr422; /*Display device support YCbCr422*/
+ unsigned char ycbcr420; /*Display device support YCbCr420*/
+ unsigned char deepcolor; /*bit3:DC_48bit; bit2:DC_36bit;
+ bit1:DC_30bit; bit0:DC_Y444;*/
+ unsigned int cecaddress; /*CEC physical address*/
+ unsigned int maxtmdsclock; /*Max supported tmds clock*/
+ unsigned char fields_present; /*bit7: latency
+ bit6: i_lantency
+ bit5: hdmi_video*/
+ unsigned char video_latency;
+ unsigned char audio_latency;
+ unsigned char interlaced_video_latency;
+ unsigned char interlaced_audio_latency;
+ /* for hdmi 2.0 */
+ unsigned char hf_vsdb_version;
+ unsigned char scdc_present;
+ unsigned char rr_capable;
+ unsigned char lte_340mcsc_scramble;
+ unsigned char independent_view;
+ unsigned char dual_view;
+ unsigned char osd_disparity_3d;
+
+ struct fb_monspecs *specs; /*Device spec*/
+ struct list_head modelist; /*Device supported display mode list*/
+ unsigned char baseaudio_support;
+ struct hdmi_audio *audio; /*Device supported audio info*/
+ unsigned int audio_num; /*Device supported audio type number*/
+};
+
+struct hdmi;
+
+struct hdmi_ops {
+ int (*enable)(struct hdmi *);
+ int (*disable)(struct hdmi *);
+ int (*getstatus)(struct hdmi *);
+ int (*insert)(struct hdmi *);
+ int (*remove)(struct hdmi *);
+ int (*getedid)(struct hdmi *, int, unsigned char *);
+ int (*setvideo)(struct hdmi *, struct hdmi_video *);
+ int (*setaudio)(struct hdmi *, struct hdmi_audio *);
+ int (*setmute)(struct hdmi *, int);
+ int (*setvsi)(struct hdmi *, unsigned char, unsigned char);
+ int (*setcec)(struct hdmi *);
+ /* call back for hdcp operatoion */
+ void (*hdcp_cb)(struct hdmi *);
+ void (*hdcp_irq_cb)(int);
+ int (*hdcp_power_on_cb)(void);
+ void (*hdcp_power_off_cb)(void);
+};
+
+enum rk_hdmi_feature {
+ SUPPORT_480I_576I = (1 << 0),
+ SUPPORT_1080I = (1 << 1),
+ SUPPORT_DEEP_10BIT = (1 << 2),
+ SUPPORT_DEEP_12BIT = (1 << 3),
+ SUPPORT_DEEP_16BIT = (1 << 4),
+ SUPPORT_4K = (1 << 5),
+ SUPPORT_4K_4096 = (1 << 6),
+ SUPPORT_TMDS_600M = (1 << 7),
+ SUPPORT_YUV420 = (1 << 8),
+ SUPPORT_CEC = (1 << 9),
+ SUPPORT_HDCP = (1 << 10),
+ SUPPORT_HDCP2 = (1 << 11),
+};
+
+struct hdmi_property {
+ char *name;
+ int videosrc;
+ int display;
+ int feature;
+ void *priv;
+};
+
+enum {
+ HDMI_SOC_RK3036 = 0,
+ HDMI_SOC_RK312X,
+ HDMI_SOC_RK3288,
+ HDMI_SOC_RK3368
+};
+
+/* HDMI Information */
+struct hdmi {
+ int id; /*HDMI id*/
+ int soctype;
+ struct device *dev; /*HDMI device*/
+ struct rk_lcdc_driver *lcdc; /*HDMI linked lcdc*/
+ struct rk_display_device *ddev; /*Registered display device*/
+ #ifdef CONFIG_SWITCH
+ struct switch_dev switchdev; /*Registered switch device*/
+ #endif
+
+ struct hdmi_property *property;
+ struct hdmi_ops *ops;
+
+ struct mutex lock; /* mutex for hdmi operation*/
+ struct workqueue_struct *workqueue;
+
+ bool uboot; /* if true, HDMI is initialized in uboot*/
+
+ int hotplug; /* hot plug status*/
+ int autoset; /* if true, auto set hdmi output mode according EDID.*/
+ int mute; /* HDMI display status:
+ 2 means mute audio,
+ 1 means mute display;
+ 0 is unmute*/
+ int colordepth;
+ int colormode;
+
+ struct hdmi_edid edid; /* EDID information*/
+ int enable; /* Enable flag*/
+ int sleep; /* Sleep flag*/
+ int vic; /* HDMI output video information code*/
+ int mode_3d; /* HDMI output video 3d mode*/
+ struct hdmi_audio audio; /* HDMI output audio information.*/
+
+ int xscale;
+ int yscale;
+};
+
+/* HDMI EDID Block Size */
+#define HDMI_EDID_BLOCK_SIZE 128
+
+/* SCDC Registers */
+#define SCDC_SINK_VER 0x01 /* sink version */
+#define SCDC_SOURCE_VER 0x02 /* source version */
+#define SCDC_UPDATE_0 0x10 /* Update_0 */
+#define SCDC_UPDATE_1 0x11 /* Update_1 */
+#define SCDC_UPDATE_RESERVED 0x12 /* 0x12-0x1f - Reserved */
+#define SCDC_TMDS_CONFIG 0x20 /* TMDS_Config */
+#define SCDC_SCRAMBLER_STAT 0x21 /* Scrambler_Status */
+#define SCDC_CONFIG_0 0x30 /* Config_0 */
+#define SCDC_CONFIG_RESERVED 0x31 /* 0x31-0x3f - Reserved */
+#define SCDC_STATUS_FLAG_0 0x40 /* Status_Flag_0 */
+#define SCDC_STATUS_FLAG_1 0x41 /* Status_Flag_1 */
+#define SCDC_STATUS_RESERVED 0x42 /* 0x42-0x4f - Reserved */
+#define SCDC_ERR_DET_0_L 0x50 /* Err_Det_0_L */
+#define SCDC_ERR_DET_0_H 0x51 /* Err_Det_0_H */
+#define SCDC_ERR_DET_1_L 0x52 /* Err_Det_1_L */
+#define SCDC_ERR_DET_1_H 0x53 /* Err_Det_1_H */
+#define SCDC_ERR_DET_2_L 0x54 /* Err_Det_2_L */
+#define SCDC_ERR_DET_2_H 0x55 /* Err_Det_2_H */
+#define SCDC_ERR_DET_CHKSUM 0x56 /* Err_Det_Checksum */
+#define SCDC_TEST_CFG_0 0xc0 /* Test_config_0 */
+#define SCDC_TEST_RESERVED 0xc1 /* 0xc1-0xcf */
+#define SCDC_MAN_OUI_3RD 0xd0 /* Manufacturer IEEE OUI,
+ Third Octet */
+#define SCDC_MAN_OUI_2ND 0xd1 /* Manufacturer IEEE OUI,
+ Second Octet */
+#define SCDC_MAN_OUI_1ST 0xd2 /* Manufacturer IEEE OUI,
+ First Octet */
+#define SCDC_DEVICE_ID 0xd3 /* 0xd3-0xdd - Device ID */
+#define SCDC_MAN_SPECIFIC 0xde /* 0xde-0xff - ManufacturerSpecific */
+
+/* Event source */
+#define HDMI_SRC_SHIFT 8
+#define HDMI_SYSFS_SRC (0x1 << HDMI_SRC_SHIFT)
+#define HDMI_SUSPEND_SRC (0x2 << HDMI_SRC_SHIFT)
+#define HDMI_IRQ_SRC (0x4 << HDMI_SRC_SHIFT)
+#define HDMI_WORKQUEUE_SRC (0x8 << HDMI_SRC_SHIFT)
+
+/* Event */
+#define HDMI_ENABLE_CTL (HDMI_SYSFS_SRC | 0)
+#define HDMI_DISABLE_CTL (HDMI_SYSFS_SRC | 1)
+#define HDMI_SUSPEND_CTL (HDMI_SUSPEND_SRC | 2)
+#define HDMI_RESUME_CTL (HDMI_SUSPEND_SRC | 3)
+#define HDMI_HPD_CHANGE (HDMI_IRQ_SRC | 4)
+#define HDMI_SET_VIDEO (HDMI_SYSFS_SRC | 5)
+#define HDMI_SET_AUDIO (HDMI_SYSFS_SRC | 6)
+#define HDMI_SET_3D (HDMI_SYSFS_SRC | 7)
+#define HDMI_MUTE_AUDIO (HDMI_SYSFS_SRC | 8)
+#define HDMI_UNMUTE_AUDIO (HDMI_SYSFS_SRC | 9)
+#define HDMI_SET_COLOR (HDMI_SYSFS_SRC | 10)
+#define HDMI_ENABLE_HDCP (HDMI_SYSFS_SRC | 11)
+
+#define HDMI_DEFAULT_SCALE 95
+#define HDMI_AUTO_CONFIG false
+
+/* HDMI default vide mode */
+#define HDMI_VIDEO_DEFAULT_MODE HDMI_1280X720P_60HZ
+ /*HDMI_1920X1080P_60HZ*/
+#define HDMI_VIDEO_DEFAULT_COLORMODE HDMI_COLOR_AUTO
+#define HDMI_VIDEO_DEFAULT_COLORDEPTH HDMI_DEPP_COLOR_AUTO
+
+/* HDMI default audio parameter */
+#define HDMI_AUDIO_DEFAULT_TYPE HDMI_AUDIO_LPCM
+#define HDMI_AUDIO_DEFAULT_CHANNEL 2
+#define HDMI_AUDIO_DEFAULT_RATE HDMI_AUDIO_FS_44100
+#define HDMI_AUDIO_DEFAULT_WORDLENGTH HDMI_AUDIO_WORD_LENGTH_16bit
+
+#ifdef DEBUG
+#define DBG(format, ...) \
+ pr_info(format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
+ struct hdmi_ops *ops);
+void rockchip_hdmi_unregister(struct hdmi *hdmi);
+struct delayed_work *hdmi_submit_work(struct hdmi *hdmi,
+ int event, int delay, void *data);
+
+struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
+ struct device *parent);
+void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
+
+int hdmi_edid_parse_base(unsigned char *buf,
+ int *extend_num, struct hdmi_edid *pedid);
+int hdmi_edid_parse_extensions(unsigned char *buf,
+ struct hdmi_edid *pedid);
+
+void hdmi_init_modelist(struct hdmi *hdmi);
+int hdmi_set_lcdc(struct hdmi *hdmi);
+int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok);
+int hdmi_add_vic(int vic, struct list_head *head);
+int hdmi_find_best_mode(struct hdmi *hdmi, int vic);
+int hdmi_videomode_to_vic(struct fb_videomode *vmode);
+const struct fb_videomode *hdmi_vic_to_videomode(int vic);
+const struct hdmi_video_timing *hdmi_vic2timing(int vic);
+int hdmi_config_audio(struct hdmi_audio *audio);
+int hdmi_get_hotplug(void);
+#endif
--- /dev/null
+config RK_HDMI_V1
+ bool "RockChip HDMI V1 support"
+ depends on RK_HDMI
+ default y
+ help
+ Support rockchip hdmi version 1 if you say y here.
+
--- /dev/null
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
+
+obj-$(CONFIG_RK_HDMI_V1) += rockchip_hdmiv1_hw.o rockchip_hdmiv1.o rockchip_hdmiv1_cec.o rockchip_hdmiv1_hdcp.o
--- /dev/null
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+
+#include <linux/of_gpio.h>
+#include <linux/rk_fb.h>
+
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
+
+#include "rockchip_hdmiv1.h"
+#include "rockchip_hdmiv1_hw.h"
+
+static struct hdmi_dev *hdmi_dev;
+
+#if defined(CONFIG_DEBUG_FS)
+static int rockchip_hdmiv1_reg_show(struct seq_file *s, void *v)
+{
+ int i = 0;
+ u32 val = 0;
+
+ seq_puts(s, "\n\n>>>rk3036_ctl reg");
+ for (i = 0; i < 16; i++)
+ seq_printf(s, " %2x", i);
+
+ seq_puts(s,
+ "\n-----------------------------------------------------------------");
+
+ for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
+ hdmi_readl(hdmi_dev, i, &val);
+ if (i % 16 == 0)
+ seq_printf(s, "\n>>>rk3036_ctl %2x:", i);
+ seq_printf(s, " %02x", val);
+ }
+ seq_puts(s,
+ "\n-----------------------------------------------------------------\n");
+
+ return 0;
+}
+
+static ssize_t rockchip_hdmiv1_reg_write(struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ u32 reg;
+ u32 val;
+ char kbuf[25];
+ static int ret;
+ struct hdmi *hdmi_drv = hdmi_dev->hdmi;
+
+ if (copy_from_user(kbuf, buf, count))
+ return -EFAULT;
+ ret = sscanf(kbuf, "%x%x", ®, &val);
+ if ((reg < 0) || (reg > 0xed)) {
+ dev_info(hdmi_drv->dev, "it is no hdmi reg\n");
+ return count;
+ }
+ dev_info(hdmi_drv->dev, "/**********rk3036 reg config******/");
+ dev_info(hdmi_drv->dev, "\n reg=%x val=%x\n", reg, val);
+ hdmi_writel(hdmi_dev, reg, val);
+
+ return count;
+}
+
+static int rockchip_hdmiv1_reg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rockchip_hdmiv1_reg_show, NULL);
+}
+
+static const struct file_operations rockchip_hdmiv1_reg_fops = {
+ .owner = THIS_MODULE,
+ .open = rockchip_hdmiv1_reg_open,
+ .read = seq_read,
+ .write = rockchip_hdmiv1_reg_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+static int rockchip_hdmiv1_clk_enable(struct hdmi_dev *hdmi_dev)
+{
+ struct hdmi *hdmi_drv;
+
+ hdmi_drv = hdmi_dev->hdmi;
+ if (!hdmi_dev->clk_on) {
+ if (hdmi_dev->soctype == HDMI_SOC_RK312X)
+ clk_prepare_enable(hdmi_dev->pd);
+
+ clk_prepare_enable(hdmi_dev->hclk);
+ spin_lock(&hdmi_dev->reg_lock);
+ hdmi_dev->clk_on = 1;
+ spin_unlock(&hdmi_dev->reg_lock);
+ }
+
+ return 0;
+}
+
+static int rockchip_hdmiv1_clk_disable(struct hdmi_dev *hdmi_dev)
+{
+ struct hdmi *hdmi_drv;
+
+ hdmi_drv = hdmi_dev->hdmi;
+ if (hdmi_dev->clk_on) {
+ spin_lock(&hdmi_dev->reg_lock);
+ hdmi_dev->clk_on = 0;
+ spin_unlock(&hdmi_dev->reg_lock);
+ if (hdmi_dev->soctype == HDMI_SOC_RK312X)
+ clk_disable_unprepare(hdmi_dev->pd);
+ clk_disable_unprepare(hdmi_dev->hclk);
+ }
+
+ return 0;
+}
+
+static void rockchip_hdmiv1_early_suspend(void)
+{
+ struct hdmi *hdmi_drv = hdmi_dev->hdmi;
+ struct delayed_work *delay_work;
+
+ dev_info(hdmi_drv->dev, "hdmi suspend\n");
+ delay_work = hdmi_submit_work(hdmi_drv,
+ HDMI_SUSPEND_CTL, 0, NULL);
+ if (delay_work)
+ flush_delayed_work(delay_work);
+ mutex_lock(&hdmi_drv->lock);
+ if (hdmi_dev->irq)
+ disable_irq(hdmi_dev->irq);
+ mutex_unlock(&hdmi_drv->lock);
+ rockchip_hdmiv1_clk_disable(hdmi_dev);
+}
+
+static void rockchip_hdmiv1_early_resume(void)
+{
+ struct hdmi *hdmi_drv = hdmi_dev->hdmi;
+
+ dev_info(hdmi_drv->dev, "hdmi resume\n");
+ mutex_lock(&hdmi_drv->lock);
+ rockchip_hdmiv1_clk_enable(hdmi_dev);
+ rockchip_hdmiv1_initial(hdmi_drv);
+ if (hdmi_drv->enable && hdmi_dev->irq) {
+ rockchip_hdmiv1_irq(hdmi_drv);
+ enable_irq(hdmi_dev->irq);
+ }
+ mutex_unlock(&hdmi_drv->lock);
+ hdmi_submit_work(hdmi_drv, HDMI_RESUME_CTL, 0, NULL);
+}
+
+static int rockchip_hdmiv1_fb_event_notify(struct notifier_block *self,
+ unsigned long action,
+ void *data)
+{
+ struct fb_event *event = data;
+ int blank_mode = *((int *)event->data);
+
+ if (action == FB_EARLY_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ break;
+ default:
+ if (!hdmi_dev->hdmi->sleep)
+ rockchip_hdmiv1_early_suspend();
+ break;
+ }
+ } else if (action == FB_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ if (hdmi_dev->hdmi->sleep)
+ rockchip_hdmiv1_early_resume();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block rockchip_hdmiv1_fb_notifier = {
+ .notifier_call = rockchip_hdmiv1_fb_event_notify,
+};
+
+static irqreturn_t rockchip_hdmiv1_irq_func(int irq, void *dev_id)
+{
+ struct hdmi *hdmi_drv = hdmi_dev->hdmi;
+
+ if ((hdmi_drv->sleep == 0) && (hdmi_drv->enable == 1))
+ rockchip_hdmiv1_irq(hdmi_drv);
+
+ return IRQ_HANDLED;
+}
+
+static struct hdmi_property rockchip_hdmiv1_property = {
+ .videosrc = DISPLAY_SOURCE_LCDC0,
+ .display = DISPLAY_MAIN,
+};
+static struct hdmi_ops rockchip_hdmiv1_ops;
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rockchip_hdmiv1_dt_ids[] = {
+ {.compatible = "rockchip,rk3036-hdmi"},
+ {.compatible = "rockchip,rk312x-hdmi"},
+ {}
+};
+
+static int rockchip_hdmiv1_parse_dt(struct hdmi_dev *hdmi_dev)
+{
+ int val = 0;
+ struct device_node *np = hdmi_dev->dev->of_node;
+ const struct of_device_id *match;
+
+ match = of_match_node(rockchip_hdmiv1_dt_ids, np);
+ if (!match)
+ return PTR_ERR(match);
+
+ if (!strcmp(match->compatible, "rockchip,rk3036-hdmi")) {
+ hdmi_dev->soctype = HDMI_SOC_RK3036;
+ } else if (!strcmp(match->compatible, "rockchip,rk312x-hdmi")) {
+ hdmi_dev->soctype = HDMI_SOC_RK312X;
+ } else {
+ pr_err("It is not a valid rockchip soc!");
+ return -ENOMEM;
+ }
+
+ if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
+ rockchip_hdmiv1_property.videosrc = val;
+
+ if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
+ hdmi_dev->audiosrc = val;
+
+ if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
+ (val == 1)) {
+ pr_info("hdmi support cec\n");
+ rockchip_hdmiv1_property.feature |= SUPPORT_CEC;
+ }
+ if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
+ (val == 1)) {
+ pr_info("hdmi support hdcp\n");
+ rockchip_hdmiv1_property.feature |= SUPPORT_HDCP;
+ }
+ /*hdmi_dev->grf_base =
+ syscon_regmap_lookup_by_phandle(np, "rockchip,grf");*/
+ return 0;
+}
+MODULE_DEVICE_TABLE(of, rockchip_hdmiv1_dt_ids);
+#endif
+
+
+static int rockchip_hdmiv1_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+ struct delayed_work *delay_work;
+
+ hdmi_dev = devm_kzalloc(&pdev->dev,
+ sizeof(struct hdmi_dev),
+ GFP_KERNEL);
+ if (!hdmi_dev) {
+ dev_err(hdmi_dev->dev, ">>rk_hdmi kmalloc fail!");
+ return -ENOMEM;
+ }
+ hdmi_dev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, hdmi_dev);
+ spin_lock_init(&hdmi_dev->reg_lock);
+ rockchip_hdmiv1_parse_dt(hdmi_dev);
+ /* request and remap iomem */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(hdmi_dev->dev, "Unable to get register resource\n");
+ ret = -ENXIO;
+ goto failed;
+ }
+ hdmi_dev->regbase_phy = res->start;
+ hdmi_dev->regsize_phy = resource_size(res);
+ hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hdmi_dev->regbase)) {
+ ret = PTR_ERR(hdmi_dev->regbase);
+ dev_err(hdmi_dev->dev, "cannot ioremap registers,err=%d\n",
+ ret);
+ goto failed;
+ }
+ if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
+ hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
+ if (IS_ERR(hdmi_dev->pd)) {
+ dev_err(hdmi_dev->hdmi->dev, "Unable to get hdmi pd\n");
+ ret = -ENXIO;
+ goto failed;
+ }
+ }
+ hdmi_dev->hclk = devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
+ if (IS_ERR(hdmi_dev->hclk)) {
+ dev_err(hdmi_dev->hdmi->dev, "Unable to get hdmi hclk\n");
+ ret = -ENXIO;
+ goto failed;
+ }
+ /* enable clk */
+ rockchip_hdmiv1_clk_enable(hdmi_dev);
+ hdmi_dev->hclk_rate = clk_get_rate(hdmi_dev->hclk);
+
+ rockchip_hdmiv1_dev_init_ops(&rockchip_hdmiv1_ops);
+ rockchip_hdmiv1_property.name = (char *)pdev->name;
+ rockchip_hdmiv1_property.priv = hdmi_dev;
+ rockchip_hdmiv1_property.feature |= SUPPORT_1080I |
+ SUPPORT_480I_576I;
+ hdmi_dev->hdmi = rockchip_hdmi_register(&rockchip_hdmiv1_property,
+ &rockchip_hdmiv1_ops);
+ if (hdmi_dev->hdmi == NULL) {
+ dev_err(&pdev->dev, "register hdmi device failed\n");
+ ret = -ENOMEM;
+ goto failed;
+ }
+ hdmi_dev->hdmi->dev = &pdev->dev;
+
+ fb_register_client(&rockchip_hdmiv1_fb_notifier);
+ rockchip_hdmiv1_initial(hdmi_dev->hdmi);
+ rk_display_device_enable(hdmi_dev->hdmi->ddev);
+ if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX) {
+ delay_work = hdmi_submit_work(hdmi_dev->hdmi,
+ HDMI_HPD_CHANGE, 0, NULL);
+ if (delay_work)
+ flush_delayed_work(delay_work);
+ }
+#if defined(CONFIG_DEBUG_FS)
+ hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv1", NULL);
+ if (IS_ERR(hdmi_dev->debugfs_dir)) {
+ dev_err(hdmi_dev->hdmi->dev,
+ "failed to create debugfs dir for hdmi!\n");
+ } else {
+ debugfs_create_file("hdmi", S_IRUSR,
+ hdmi_dev->debugfs_dir, hdmi_dev->hdmi,
+ &rockchip_hdmiv1_reg_fops);
+ }
+#endif
+
+ /* get the IRQ */
+ hdmi_dev->irq = platform_get_irq(pdev, 0);
+ if (hdmi_dev->irq <= 0) {
+ dev_err(hdmi_dev->hdmi->dev, "failed to get hdmi irq resource (%d).\n",
+ hdmi_dev->irq);
+ hdmi_dev->irq = 0;
+ } else {
+ /* request the IRQ */
+ ret = devm_request_irq(hdmi_dev->hdmi->dev,
+ hdmi_dev->irq,
+ rockchip_hdmiv1_irq_func,
+ IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ dev_name(hdmi_dev->hdmi->dev),
+ hdmi_dev->hdmi);
+ if (ret) {
+ dev_err(hdmi_dev->hdmi->dev, "hdmi request_irq failed (%d)\n",
+ ret);
+ goto failed1;
+ }
+ }
+ dev_info(hdmi_dev->hdmi->dev, "hdmi probe success.\n");
+ return 0;
+
+failed1:
+ rockchip_hdmi_unregister(hdmi_dev->hdmi);
+failed:
+ kfree(hdmi_dev);
+ hdmi_dev = NULL;
+ dev_err(&pdev->dev, "rk3288 hdmi probe error.\n");
+ return ret;
+}
+
+static int rockchip_hdmiv1_remove(struct platform_device *pdev)
+{
+ struct hdmi *hdmi_drv = NULL;
+
+ hdmi_drv = hdmi_dev->hdmi;
+ rockchip_hdmi_unregister(hdmi_drv);
+ return 0;
+}
+
+static void rockchip_hdmiv1_shutdown(struct platform_device *pdev)
+{
+ struct hdmi_dev *hdmi_dev = platform_get_drvdata(pdev);
+ struct hdmi *hdmi_drv = NULL;
+
+ if (hdmi_dev) {
+ hdmi_drv = hdmi_dev->hdmi;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&hdmi_drv->early_suspend);
+#endif
+ mutex_lock(&hdmi_drv->lock);
+ hdmi_drv->sleep = 1;
+ if (!hdmi_drv->enable) {
+ mutex_unlock(&hdmi_drv->lock);
+ return;
+ }
+ if (hdmi_dev->irq)
+ disable_irq(hdmi_dev->irq);
+ mutex_unlock(&hdmi_drv->lock);
+ if (hdmi_drv->hotplug == HDMI_HPD_ACTIVED)
+ hdmi_drv->ops->setmute(hdmi_drv,
+ HDMI_VIDEO_MUTE |
+ HDMI_AUDIO_MUTE);
+ rockchip_hdmiv1_clk_disable(hdmi_dev);
+ }
+ dev_info(hdmi_drv->dev, "rk hdmi shut down.\n");
+}
+
+
+static struct platform_driver rockchip_hdmiv1_driver = {
+ .probe = rockchip_hdmiv1_probe,
+ .remove = rockchip_hdmiv1_remove,
+ .driver = {
+ .name = "rk-hdmi",
+ .owner = THIS_MODULE,
+ #if defined(CONFIG_OF)
+ .of_match_table = of_match_ptr(rockchip_hdmiv1_dt_ids),
+ #endif
+ },
+ .shutdown = rockchip_hdmiv1_shutdown,
+};
+
+static int __init rockchip_hdmiv1_init(void)
+{
+ return platform_driver_register(&rockchip_hdmiv1_driver);
+}
+
+static void __exit rockchip_hdmiv1_exit(void)
+{
+ platform_driver_unregister(&rockchip_hdmiv1_driver);
+}
+
+module_init(rockchip_hdmiv1_init);
+module_exit(rockchip_hdmiv1_exit);
--- /dev/null
+#ifndef __ROCKCHIP_HDMI_V1_H__
+#define __ROCKCHIP_HDMI_V1_H__
+
+#include "../rockchip-hdmi.h"
+
+struct hdmi_dev {
+ void __iomem *regbase;
+ int regbase_phy;
+ int regsize_phy;
+
+ struct clk *pd;
+ struct clk *hclk;
+ unsigned int hclk_rate;
+
+ struct hdmi *hdmi;
+ struct device *dev;
+ struct dentry *debugfs_dir;
+ int irq;
+
+ struct work_struct irq_work;
+ struct delayed_work delay_work;
+ struct workqueue_struct *workqueue;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int soctype;
+ int audiosrc;
+ int enable;
+ unsigned char clk_disable;
+ unsigned char clk_on;
+ spinlock_t reg_lock;
+
+ unsigned int tmdsclk;
+ unsigned int pixelrepeat;
+ int pwr_mode;
+};
+#endif /* __RK3036_HDMI_H__ */
--- /dev/null
+#include "rockchip_hdmiv1.h"
+#include "rockchip_hdmiv1_hw.h"
+#include "../rockchip-hdmi-cec.h"
+
+struct cec_t {
+ wait_queue_head_t wait;
+ int busfree;
+ int tx_done;
+};
+
+static int init = 1;
+static struct cec_t cec;
+
+static int rockchip_hdmiv1_cec_read_frame(struct hdmi *hdmi,
+ struct cec_framedata *frame)
+{
+ int i, length, val;
+ char *data = (char *)frame;
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ if (frame == NULL)
+ return -1;
+
+ hdmi_readl(hdmi_dev, CEC_RX_LENGTH, &length);
+ hdmi_writel(hdmi_dev, CEC_RX_OFFSET, 0);
+
+ CECDBG("CEC: %s length is %d\n", __func__, length);
+ for (i = 0; i < length; i++) {
+ hdmi_readl(hdmi_dev, CEC_DATA, &val);
+ data[i] = val;
+ pr_info("%02x\n", data[i]);
+ }
+ return 0;
+}
+
+static int rockchip_hdmiv1_cec_send_frame(struct hdmi *hdmi,
+ struct cec_framedata *frame)
+{
+ int i;
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ CECDBG("CEC: TX srcdestaddr %x opcode %x ",
+ frame->srcdestaddr, frame->opcode);
+ if (frame->argcount) {
+ DBG("args:");
+ for (i = 0; i < frame->argcount; i++)
+ DBG("%02x ", frame->args[i]);
+ }
+ CECDBG("\n");
+
+ hdmi_writel(hdmi_dev, CEC_TX_OFFSET, 0);
+ hdmi_writel(hdmi_dev, CEC_DATA, frame->srcdestaddr);
+ hdmi_writel(hdmi_dev, CEC_DATA, frame->opcode);
+
+ for (i = 0; i < frame->argcount; i++)
+ hdmi_writel(hdmi_dev, CEC_DATA, frame->args[i]);
+
+ hdmi_writel(hdmi_dev, CEC_TX_LENGTH, frame->argcount + 2);
+
+ /*Wait for bus free*/
+ cec.busfree = 1;
+ hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE);
+ CECDBG("start wait bus free\n");
+ if (wait_event_interruptible_timeout(cec.wait,
+ cec.busfree == 0,
+ msecs_to_jiffies(17)))
+ return -1;
+
+ CECDBG("end wait bus free,start tx,busfree=%d\n", cec.busfree);
+ /*Start TX*/
+ cec.tx_done = 0;
+ hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE|m_START_TX);
+ if (wait_event_interruptible_timeout(cec.wait,
+ cec.tx_done != 0,
+ msecs_to_jiffies(100)))
+ hdmi_writel(hdmi_dev, CEC_CTRL, 0);
+ CECDBG("end tx,tx_done=%d\n", cec.tx_done);
+
+ if (cec.tx_done == 1) {
+ cec.tx_done = 0;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+void rockchip_hdmiv1_cec_setcecla(struct hdmi *hdmi, int ceclgaddr)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ /*for(i = 0; i < 3; i++) {
+ if(Cec_Ping(la_player[i]) == 1) {
+ cec.address_logic = la_player[i];
+ break;
+ }
+ }
+ if(i == 3)
+ return -1;
+ //Broadcast our physical address.
+ GPIO_CecSendMessage(CECOP_GET_MENU_LANGUAGE,CEC_LOGADDR_TV);
+ msleep(100);*/
+ CECDBG("CEC: %s\n", __func__);
+ hdmi_writel(hdmi_dev, CEC_LOGICADDR, ceclgaddr);
+}
+
+void rockchip_hdmiv1_cec_isr(struct hdmi_dev *hdmi_dev)
+{
+ int tx_isr = 0, rx_isr = 0;
+
+ hdmi_readl(hdmi_dev, CEC_TX_INT, &tx_isr);
+ hdmi_readl(hdmi_dev, CEC_RX_INT, &rx_isr);
+
+ CECDBG("CEC: rockchip_hdmiv1_cec_isr:tx_isr %02x rx_isr %02x\n\n",
+ tx_isr, rx_isr);
+
+ hdmi_writel(hdmi_dev, CEC_TX_INT, tx_isr);
+ hdmi_writel(hdmi_dev, CEC_RX_INT, rx_isr);
+
+ if (tx_isr & m_TX_BUSNOTFREE) {
+ cec.busfree = 0;
+ CECDBG("CEC: m_TX_BUSNOTFREE,busfree=%d\n", cec.busfree);
+ } else if (tx_isr & m_TX_DONE) {
+ cec.tx_done = 1;
+ CECDBG("CEC: m_TX_DONE,busfree=%d\n", cec.tx_done);
+ } else {
+ cec.tx_done = -1;
+ CECDBG("CEC: else:busfree=%d\n", cec.tx_done);
+ }
+
+ wake_up_interruptible_all(&cec.wait);
+ if (rx_isr & m_RX_DONE)
+ rockchip_hdmi_cec_submit_work(EVENT_RX_FRAME, 0, NULL);
+}
+
+void rockchip_hdmiv1_cec_init(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ if (init) {
+ /*Fref = Fsys / ((register 0xd4 + 1)*(register 0xd5 + 1))*/
+ /*Fref = 0.5M, Fsys = 74.25M*/
+ hdmi_writel(hdmi_dev, CEC_CLK_H, 11);
+ hdmi_writel(hdmi_dev, CEC_CLK_L, 11);
+
+ /*Set bus free time to 16.8ms*/
+ hdmi_writel(hdmi_dev, CEC_BUSFREETIME_L, 0xd0);
+ hdmi_writel(hdmi_dev, CEC_BUSFREETIME_H, 0x20);
+
+ /*Enable TX/RX INT*/
+ hdmi_writel(hdmi_dev, CEC_TX_INT, 0xFF);
+ hdmi_writel(hdmi_dev, CEC_RX_INT, 0xFF);
+
+ CECDBG(KERN_ERR "CEC: rockchip_hdmiv1_cec_init sucess\n");
+ rockchip_hdmi_cec_init(hdmi,
+ rockchip_hdmiv1_cec_send_frame,
+ rockchip_hdmiv1_cec_read_frame,
+ rockchip_hdmiv1_cec_setcecla);
+ init = 0;
+ init_waitqueue_head(&cec.wait);
+ }
+ CECDBG("%s", __func__);
+}
+
--- /dev/null
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include "rockchip_hdmiv1.h"
+#include "rockchip_hdmiv1_hdcp.h"
+#include "rockchip_hdmiv1_hw.h"
+
+static struct hdcp *hdcp;
+
+static void hdcp_work_queue(struct work_struct *work);
+
+#define AUTH_TIMEOUT (2*HZ)
+static struct timer_list auth_timer;
+static int timer_state;
+
+static int is_1b_03_test(struct hdmi_dev *hdmi_dev)
+{
+ int reg_value;
+ int reg_val_1;
+
+ hdmi_readl(hdmi_dev, 0x58, ®_value);
+ hdmi_readl(hdmi_dev, 0xc3, ®_val_1);
+
+ if (reg_value != 0) {
+ if ((reg_val_1 & 0x40) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+static void rockchip_hdmiv1_set_colorbar(struct hdmi_dev *hdmi_dev,
+ int enable)
+{
+ static int display_mask;
+ int reg_value;
+ int tmds_clk;
+
+ tmds_clk = hdmi_dev->tmdsclk;
+ if (enable) {
+ if (!display_mask) {
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+ hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE,
+ v_REG_CLK_SOURCE_SYS);
+ hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
+ hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+ } else {
+ hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
+ }
+ display_mask = 1;
+ }
+ } else {
+ if (display_mask) {
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+ hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE,
+ v_REG_CLK_SOURCE_SYS);
+ hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
+ hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+ } else {
+ hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
+ }
+ display_mask = 0;
+ }
+ }
+}
+
+static void rockchip_hdmiv1_hdcp_disable(struct hdmi_dev *hdmi_dev)
+{
+ int reg_value;
+ int tmds_clk;
+
+ tmds_clk = hdmi_dev->tmdsclk;
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+ hdmi_readl(hdmi_dev, SYS_CTRL, ®_value);
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+ }
+
+ /* Diable HDCP Interrupt*/
+ hdmi_writel(hdmi_dev, HDCP_INT_MASK1, 0x00);
+ /* Stop and Reset HDCP*/
+ hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
+ m_AUTH_START | m_AUTH_STOP | m_HDCP_RESET,
+ v_AUTH_START(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1));
+
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+ hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+}
+
+static int rockchip_hdmiv1_hdcp_key_check(struct hdcp_keys *key)
+{
+ int i = 0;
+
+ DBG("HDCP: check hdcp key\n");
+ /*check 40 private key */
+ for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++) {
+ if (key->devicekey[i] != 0x00)
+ return HDCP_KEY_VALID;
+ }
+ /*check aksv*/
+ for (i = 0; i < 5; i++) {
+ if (key->ksv[i] != 0x00)
+ return HDCP_KEY_VALID;
+ }
+
+ return HDCP_KEY_INVALID;
+}
+
+static int rockchip_hdmiv1_hdcp_load_key2mem(void)
+{
+ int i;
+ struct hdmi_dev *hdmi_dev;
+ struct hdcp_keys *key;
+
+ if (!hdcp)
+ return -1;
+ hdmi_dev = hdcp->hdmi_dev;
+ key = hdcp->keys;
+ DBG("HDCP: rockchip_hdmiv1_hdcp_load_key2mem start\n");
+ /* Write 40 private key*/
+ for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
+ hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->devicekey[i]);
+ /* Write 1st aksv*/
+ for (i = 0; i < 5; i++)
+ hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
+ /* Write 2nd aksv*/
+ for (i = 0; i < 5; i++)
+ hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
+ DBG("HDCP: rockchip_hdmiv1_hdcp_load_key2mem end\n");
+ return HDCP_OK;
+}
+
+static int rockchip_hdmiv1_hdcp_start_authentication(struct hdmi_dev *hdmi_dev)
+{
+ int temp;
+ int retry = 0;
+ int tmds_clk;
+
+ tmds_clk = hdmi_dev->tmdsclk;
+ if (hdcp->keys == NULL) {
+ HDCP_WARN("HDCP: key is not loaded\n");
+ return HDCP_KEY_ERR;
+ }
+ if (rockchip_hdmiv1_hdcp_key_check(hdcp->keys) == HDCP_KEY_INVALID) {
+ HDCP_WARN("loaded HDCP key is incorrect\n");
+ return HDCP_KEY_ERR;
+ }
+ if (tmds_clk > (HDMI_SYS_FREG_CLK << 2)) {
+ /*Select TMDS CLK to configure regs*/
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);
+ } else {
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+ }
+ hdmi_writel(hdmi_dev, HDCP_TIMER_100MS, 0x28);
+ hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
+ while ((temp & m_KEY_READY) == 0) {
+ if (retry > 1000) {
+ HDCP_WARN("HDCP: loaded key error\n");
+ return HDCP_KEY_ERR;
+ }
+ rockchip_hdmiv1_hdcp_load_key2mem();
+ usleep_range(900, 1000);
+ hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
+ retry++;
+ }
+ /*Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)*/
+ retry = hdmi_dev->hclk_rate/(HDCP_DDC_CLK << 2);
+ hdmi_writel(hdmi_dev, DDC_CLK_L, retry & 0xFF);
+ hdmi_writel(hdmi_dev, DDC_CLK_H, (retry >> 8) & 0xFF);
+ hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x67);
+ /*Enable interrupt*/
+ hdmi_writel(hdmi_dev, HDCP_INT_MASK1,
+ m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE |
+ m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);
+ hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x00);
+ /*Start authentication*/
+ hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
+ m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE |
+ m_AUTH_STOP | m_HDCP_RESET,
+ v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) |
+ v_ADVANED_ENABLE(0) | v_AUTH_STOP(0) | v_HDCP_RESET(0));
+
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
+ v_REG_CLK_SOURCE_TMDS);
+ }
+ return HDCP_OK;
+}
+
+static int rockchip_hdmiv1_hdcp_stop_authentication(struct hdmi_dev *hdmi_dev)
+{
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+ hdmi_writel(hdmi_dev, DDC_CLK_L, 0x1c);
+ hdmi_writel(hdmi_dev, DDC_CLK_H, 0x00);
+ hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x08);
+ hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x06);
+ hdmi_writel(hdmi_dev, HDCP_CTRL1, 0x02);
+ return 0;
+ /*hdmi_writel(HDCP_CTRL1, 0x0a);*/
+}
+
+static int rockchip_hdmiv1_hdcp_error(int value)
+{
+ if (value & 0x80)
+ HDCP_WARN("Timed out waiting for downstream repeater\n");
+ else if (value & 0x40)
+ HDCP_WARN("Too many devices connected to repeater tree\n");
+ else if (value & 0x20)
+ HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
+ else if (value & 0x10)
+ HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
+ else if (value & 0x08)
+ HDCP_WARN("DDC channels no acknowledge\n");
+ else if (value & 0x04)
+ HDCP_WARN("Pj mismatch\n");
+ else if (value & 0x02)
+ HDCP_WARN("Ri mismatch\n");
+ else if (value & 0x01)
+ HDCP_WARN("Bksv is wrong\n");
+ else
+ return 0;
+ return 1;
+}
+
+static void rockchip_hdmiv1_hdcp_interrupt(struct hdmi_dev *hdmi_dev,
+ char *status1, char *status2)
+{
+ int interrupt1 = 0;
+ int interrupt2 = 0;
+ int temp = 0;
+ int tmds_clk;
+
+ tmds_clk = hdmi_dev->tmdsclk;
+ hdmi_readl(hdmi_dev, HDCP_INT_STATUS1, &interrupt1);
+ hdmi_readl(hdmi_dev, HDCP_INT_STATUS2, &interrupt2);
+
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+ m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+
+ if (interrupt1) {
+ hdmi_writel(hdmi_dev, HDCP_INT_STATUS1, interrupt1);
+ if (interrupt1 & m_INT_HDCP_ERR) {
+ hdmi_readl(hdmi_dev, HDCP_ERROR, &temp);
+ HDCP_WARN("HDCP: Error reg 0x65 = 0x%02x\n", temp);
+ rockchip_hdmiv1_hdcp_error(temp);
+ hdmi_writel(hdmi_dev, HDCP_ERROR, temp);
+ }
+ }
+ if (interrupt2)
+ hdmi_writel(hdmi_dev, HDCP_INT_STATUS2, interrupt2);
+
+ *status1 = interrupt1;
+ *status2 = interrupt2;
+
+ if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
+ v_REG_CLK_SOURCE_TMDS);
+/*
+ hdmi_readl(HDCP_ERROR, &temp);
+ DBG("HDCP: Error reg 0x65 = 0x%02x\n", temp);
+*/
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_submit_work
+ *-----------------------------------------------------------------------------
+ */
+static struct delayed_work *hdcp_submit_work(int event, int delay)
+{
+ struct hdcp_delayed_work *work;
+
+ DBG("%s event %04x delay %d\n", __func__, event, delay);
+ work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+ if (work) {
+ INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
+ work->event = event;
+ queue_delayed_work(hdcp->workqueue,
+ &work->work,
+ msecs_to_jiffies(delay));
+ } else {
+ HDCP_WARN("HDCP:Cannot allocate memory to create work\n");
+ return 0;
+ }
+
+ return &work->work;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_cancel_work
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_cancel_work(struct delayed_work **work)
+{
+ int ret = 0;
+
+ if (*work) {
+ ret = cancel_delayed_work(*work);
+ if (ret != 1) {
+ ret = cancel_work_sync(&((*work)->work));
+ HDCP_WARN("Canceling sync work failed %d\n", ret);
+ }
+ kfree(*work);
+ *work = 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: auth_timer_func
+ *-----------------------------------------------------------------------------
+ */
+static void auth_timer_func(unsigned long data)
+{
+ HDCP_WARN("hdcp auth 2 second timeout\n");
+ if (hdcp->auth_state == 0) {
+ mod_timer(&auth_timer, jiffies + AUTH_TIMEOUT);
+ if ((hdcp->hdcp_state != HDCP_DISABLED) &&
+ (hdcp->hdcp_state != HDCP_ENABLE_PENDING)) {
+ if (is_1b_03_test(hdcp->hdmi_dev))
+ return;
+ hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_failure
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_failure(void)
+{
+ if (hdcp->hdmi_state == HDMI_STOPPED)
+ return;
+
+ rockchip_hdmiv1_hdcp_disable(hdcp->hdmi_dev);
+/*
+ rockchip_hdmiv1_hdmi_control_output(false);
+ */
+ rockchip_hdmiv1_set_colorbar(hdcp->hdmi_dev, 1);
+ hdcp_cancel_work(&hdcp->pending_wq_event);
+ if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
+ if (hdcp->retry_cnt <= HDCP_INFINITE_REAUTH) {
+ hdcp->retry_cnt--;
+ HDCP_WARN("authentication failed attempts=%d\n",
+ hdcp->retry_cnt);
+ } else {
+ HDCP_WARN("authentication failed retrying\n");
+ }
+ hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+ if (hdcp->auth_state == 1 && timer_state == 0) {
+ DBG("add auth timer\n");
+ hdcp->auth_state = 0;
+ hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+ auth_timer.expires = jiffies + AUTH_TIMEOUT;
+ add_timer(&auth_timer);
+ timer_state = 1;
+ }
+
+ hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
+ HDCP_REAUTH_DELAY);
+ } else {
+ HDCP_WARN("authentication failed HDCP disabled\n");
+ hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+
+ if (timer_state == 1) {
+ DBG("delete auth timer\n");
+ del_timer_sync(&auth_timer);
+ timer_state = 0;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_start_authentication
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_start_authentication(void)
+{
+ int status = HDCP_OK;
+
+ hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+ DBG("HDCP: authentication start\n");
+ status = rockchip_hdmiv1_hdcp_start_authentication(hdcp->hdmi_dev);
+ if (status != HDCP_OK) {
+ DBG("HDCP: authentication failed\n");
+ hdcp_wq_authentication_failure();
+ } else {
+ /*hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;*/
+ hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+ }
+}
+#if 0
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_check_bksv
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_check_bksv(void)
+{
+ int status = HDCP_OK;
+
+ DBG("Check BKSV start");
+ status = rockchip_hdmiv1_hdcp_check_bksv();
+ if (status != HDCP_OK) {
+ HDCP_WARN("HDCP: Check BKSV failed");
+ hdcp->retry_cnt = 0;
+ hdcp_wq_authentication_failure();
+ } else {
+ DBG("HDCP: Check BKSV successful");
+ hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+ /* Restore retry counter */
+ if (hdcp->retry_times == 0)
+ hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+ else
+ hdcp->retry_cnt = hdcp->retry_times;
+ }
+}
+#endif
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_sucess
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_sucess(void)
+{
+ hdcp->auth_state = 1;
+ if (timer_state == 1) {
+ DBG("delete auth timer\n");
+ timer_state = 0;
+ del_timer_sync(&auth_timer);
+ }
+
+ rockchip_hdmiv1_set_colorbar(hdcp->hdmi_dev, 0);
+ HDCP_WARN("HDCP: authentication pass\n");
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_disable
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_disable(int event)
+{
+ HDCP_WARN("HDCP: disabled\n");
+
+ hdcp_cancel_work(&hdcp->pending_wq_event);
+ rockchip_hdmiv1_hdcp_disable(hdcp->hdmi_dev);
+ if (event == HDCP_DISABLE_CTL) {
+ hdcp->hdcp_state = HDCP_DISABLED;
+ if (hdcp->hdmi_state == HDMI_STARTED)
+ rockchip_hdmiv1_set_colorbar(hdcp->hdmi_dev, 0);
+ } else if (event == HDCP_STOP_FRAME_EVENT) {
+ hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_work_queue
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_work_queue(struct work_struct *work)
+{
+ struct hdcp_delayed_work *hdcp_w =
+ container_of(work, struct hdcp_delayed_work, work.work);
+ int event = hdcp_w->event;
+
+ mutex_lock(&hdcp->lock);
+ DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d\n",
+ jiffies_to_msecs(jiffies),
+ hdcp->hdmi_state,
+ hdcp->hdcp_state,
+ (event & 0xFF00) >> 8,
+ event & 0xFF);
+
+ if (event == HDCP_STOP_FRAME_EVENT)
+ hdcp->hdmi_state = HDMI_STOPPED;
+ if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT)
+ hdcp_wq_disable(event);
+ if (event & HDCP_WORKQUEUE_SRC)
+ hdcp->pending_wq_event = 0;
+ /* First handle HDMI state */
+ if (event == HDCP_START_FRAME_EVENT) {
+ hdcp->pending_start = 0;
+ hdcp->hdmi_state = HDMI_STARTED;
+ }
+
+ /**********************/
+ /* HDCP state machine */
+ /**********************/
+ switch (hdcp->hdcp_state) {
+ case HDCP_DISABLED:
+ /* HDCP enable control or re-authentication event */
+ if (event == HDCP_ENABLE_CTL) {
+ /*if (hdcp->retry_times == 0)
+ hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+ else
+ hdcp->retry_cnt = hdcp->retry_times;*/
+ hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+ if (hdcp->hdmi_state == HDMI_STARTED)
+ hdcp_wq_start_authentication();
+ else
+ hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+ }
+ break;
+ case HDCP_ENABLE_PENDING:
+ /* HDMI start frame event */
+ if (event == HDCP_START_FRAME_EVENT)
+ hdcp_wq_start_authentication();
+ break;
+ case HDCP_AUTHENTICATION_START:
+ /* Re-authentication */
+ if (event == HDCP_AUTH_REATT_EVENT)
+ hdcp_wq_start_authentication();
+ break;
+#if 0
+ case HDCP_WAIT_KSV_LIST:
+ /* KSV failure */
+ if (event == HDCP_FAIL_EVENT) {
+ HDCP_WARN("HDCP: KSV switch failure\n");
+ hdcp_wq_authentication_failure();
+ }
+ /* KSV list ready event */
+ else if (event == HDCP_KSV_LIST_RDY_EVENT)
+ hdcp_wq_check_bksv();
+ break;
+#endif
+ case HDCP_LINK_INTEGRITY_CHECK:
+ /* authentication failure */
+ if (event == HDCP_FAIL_EVENT) {
+ HDCP_WARN("HDCP: Ri check failure\n");
+ hdcp_wq_authentication_failure();
+ } else if (event == HDCP_AUTH_PASS_EVENT) {
+ hdcp_wq_authentication_sucess();
+ }
+ break;
+ default:
+ HDCP_WARN("HDCP: error - unknow HDCP state\n");
+ break;
+ }
+ kfree(hdcp_w);
+ if (event == HDCP_STOP_FRAME_EVENT)
+ complete(&hdcp->complete);
+ mutex_unlock(&hdcp->lock);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_start_frame_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_start_frame_cb(struct hdmi *hdmi)
+{
+ DBG("hdcp_start_frame_cb()\n");
+
+ /* Cancel any pending work */
+ if (hdcp->pending_start)
+ hdcp_cancel_work(&hdcp->pending_start);
+ if (hdcp->pending_wq_event)
+ hdcp_cancel_work(&hdcp->pending_wq_event);
+
+ if (timer_state == 0) {
+ DBG("add auth timer\n");
+ auth_timer.expires = jiffies + AUTH_TIMEOUT;
+ add_timer(&auth_timer);
+ timer_state = 1;
+ }
+
+ hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+ hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
+ HDCP_ENABLE_DELAY);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_irq_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_irq_cb(int status)
+{
+ char interrupt1;
+ char interrupt2;
+
+ rockchip_hdmiv1_hdcp_interrupt(hdcp->hdmi_dev,
+ &interrupt1,
+ &interrupt2);
+ DBG("%s 0x%02x 0x%02x\n", __func__, interrupt1, interrupt2);
+ if (interrupt1 & m_INT_HDCP_ERR) {
+ if ((hdcp->hdcp_state != HDCP_DISABLED) &&
+ (hdcp->hdcp_state != HDCP_ENABLE_PENDING))
+ hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+ }
+/*
+ else if (interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
+ hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
+ */
+ else if (interrupt1 & m_INT_AUTH_SUCCESS)
+ hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_on_cb
+ *-----------------------------------------------------------------------------
+ */
+static int hdcp_power_on_cb(void)
+{
+ DBG("%s", __func__);
+ return rockchip_hdmiv1_hdcp_load_key2mem();
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_off_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_power_off_cb(void)
+{
+ unsigned int time;
+
+ DBG("%s\n", __func__);
+ if (timer_state == 1) {
+ DBG("delete auth timer\n");
+ timer_state = 0;
+ del_timer_sync(&auth_timer);
+ }
+ hdcp->auth_state = 0;
+
+ if (!hdcp->enable)
+ return;
+ rockchip_hdmiv1_hdcp_stop_authentication(hdcp->hdmi_dev);
+ hdcp_cancel_work(&hdcp->pending_start);
+ hdcp_cancel_work(&hdcp->pending_wq_event);
+ init_completion(&hdcp->complete);
+ /* Post event to workqueue */
+ time = msecs_to_jiffies(5000);
+ if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
+ wait_for_completion_interruptible_timeout(&hdcp->complete,
+ time);
+}
+
+/*
+ * Load HDCP key to external HDCP memory
+ */
+static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
+{
+ if (!fw) {
+ pr_err("HDCP: failed to load keys\n");
+ return;
+ }
+ if (fw->size < HDCP_KEY_SIZE) {
+ pr_err("HDCP: firmware wrong size %d\n", (int)fw->size);
+ return;
+ }
+ hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
+ if (hdcp->keys == NULL) {
+ pr_err("HDCP: can't allocated space for keys\n");
+ return;
+ }
+ memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
+ HDCP_WARN("HDCP: load hdcp key success\n");
+
+ if (fw->size > HDCP_KEY_SIZE) {
+ DBG("%s invalid key size %d\n", __func__,
+ (int)fw->size - HDCP_KEY_SIZE);
+ if ((fw->size - HDCP_KEY_SIZE) % 5) {
+ pr_err("HDCP: failed to load invalid keys\n");
+ return;
+ }
+ hdcp->invalidkeys =
+ kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
+ if (hdcp->invalidkeys == NULL) {
+ pr_err("HDCP: can't allocated space for invalid keys\n");
+ return;
+ }
+ memcpy(hdcp->invalidkeys, fw->data +
+ HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
+ hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
+ HDCP_WARN("HDCP: loaded hdcp invalid key success\n");
+ }
+}
+
+static ssize_t hdcp_enable_read(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int enable = 0;
+
+ if (hdcp)
+ enable = hdcp->enable;
+ return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t hdcp_enable_write(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int enable;
+
+ if (hdcp == NULL)
+ return -EINVAL;
+ if (kstrtoint(buf, 0, &enable))
+ return -EINVAL;
+ if (hdcp->enable != enable) {
+ /* Post event to workqueue */
+ if (enable) {
+ if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
+ return -EFAULT;
+ } else {
+ hdcp_cancel_work(&hdcp->pending_start);
+ hdcp_cancel_work(&hdcp->pending_wq_event);
+
+ /* Post event to workqueue */
+ if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
+ return -EFAULT;
+ }
+ hdcp->enable = enable;
+ }
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
+ hdcp_enable_read, hdcp_enable_write);
+
+static ssize_t hdcp_trytimes_read(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int trytimes = 0;
+
+ if (hdcp)
+ trytimes = hdcp->retry_times;
+ return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
+}
+
+static ssize_t hdcp_trytimes_wrtie(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int trytimes;
+
+ if (hdcp == NULL)
+ return -EINVAL;
+ if (kstrtoint(buf, 0, &trytimes))
+ return -EINVAL;
+ if (hdcp->retry_times != trytimes)
+ hdcp->retry_times = trytimes;
+ return count;
+}
+
+
+static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
+ hdcp_trytimes_read, hdcp_trytimes_wrtie);
+static struct miscdevice mdev;
+
+int rockchip_hdmiv1_hdcp_init(struct hdmi *hdmi)
+{
+ int ret;
+
+ DBG("[%s]\n", __func__);
+ if (hdcp)
+ return 0;
+
+ hdcp = kmalloc(sizeof(*hdcp), GFP_KERNEL);
+ if (!hdcp) {
+ HDCP_WARN(">>HDCP: kmalloc fail!\n");
+ ret = -ENOMEM;
+ goto error0;
+ }
+ memset(hdcp, 0, sizeof(struct hdcp));
+ mutex_init(&hdcp->lock);
+ mdev.minor = MISC_DYNAMIC_MINOR;
+ mdev.name = "hdcp";
+ mdev.mode = 0666;
+ if (misc_register(&mdev)) {
+ HDCP_WARN("HDCP: Could not add character driver\n");
+ ret = HDMI_ERROR_FALSE;
+ goto error1;
+ }
+ ret = device_create_file(mdev.this_device, &dev_attr_enable);
+ if (ret) {
+ HDCP_WARN("HDCP: Could not add sys file enable\n");
+ ret = -EINVAL;
+ goto error2;
+ }
+ ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
+ if (ret) {
+ HDCP_WARN("HDCP: Could not add sys file trytimes\n");
+ ret = -EINVAL;
+ goto error3;
+ }
+ hdcp->workqueue = create_singlethread_workqueue("hdcp");
+ if (hdcp->workqueue == NULL) {
+ HDCP_WARN("HDCP,: create workqueue failed.\n");
+ goto error4;
+ }
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "hdcp", mdev.this_device,
+ GFP_KERNEL, hdcp,
+ hdcp_load_keys_cb);
+ if (ret < 0) {
+ HDCP_WARN("HDCP: request_firmware_nowait failed: %d\n", ret);
+ goto error5;
+ }
+ hdcp->hdmi_dev = hdmi->property->priv;
+ hdmi->ops->hdcp_cb = hdcp_start_frame_cb;
+ hdmi->ops->hdcp_irq_cb = hdcp_irq_cb;
+ hdmi->ops->hdcp_power_on_cb = hdcp_power_on_cb;
+ hdmi->ops->hdcp_power_off_cb = hdcp_power_off_cb;
+
+ init_timer(&auth_timer);
+ auth_timer.data = 0;
+ auth_timer.function = auth_timer_func;
+ DBG("%s success\n", __func__);
+ return 0;
+error5:
+ destroy_workqueue(hdcp->workqueue);
+error4:
+ device_remove_file(mdev.this_device, &dev_attr_trytimes);
+error3:
+ device_remove_file(mdev.this_device, &dev_attr_enable);
+error2:
+ misc_deregister(&mdev);
+error1:
+ kfree(hdcp->keys);
+ kfree(hdcp->invalidkeys);
+ kfree(hdcp);
+error0:
+ return ret;
+}
+
--- /dev/null
+#ifndef __ROCKCHIP_HDMIV1_HDCP_H__
+#define __ROCKCHIP_HDMIV1_HDCP_H__
+
+/***************************/
+/* Definitions */
+/***************************/
+
+/* Status / error codes */
+#define HDCP_OK 0
+#define HDCP_KEY_ERR 1
+#define HDCP_KSV_ERR 2
+#define HDCP_KEY_VALID 3
+#define HDCP_KEY_INVALID 4
+
+/* Delays */
+#define HDCP_ENABLE_DELAY 300
+#define HDCP_REAUTH_DELAY 100
+
+/* Event source */
+#define HDCP_SRC_SHIFT 8
+#define HDCP_IOCTL_SRC (0x1 << HDCP_SRC_SHIFT)
+#define HDCP_HDMI_SRC (0x2 << HDCP_SRC_SHIFT)
+#define HDCP_IRQ_SRC (0x4 << HDCP_SRC_SHIFT)
+#define HDCP_WORKQUEUE_SRC (0x8 << HDCP_SRC_SHIFT)
+
+/* Event */
+#define HDCP_ENABLE_CTL (HDCP_IOCTL_SRC | 0)
+#define HDCP_DISABLE_CTL (HDCP_IOCTL_SRC | 1)
+#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC | 2)
+#define HDCP_STOP_FRAME_EVENT (HDCP_HDMI_SRC | 3)
+#define HDCP_KSV_LIST_RDY_EVENT (HDCP_IRQ_SRC | 4)
+#define HDCP_FAIL_EVENT (HDCP_IRQ_SRC | 5)
+#define HDCP_AUTH_PASS_EVENT (HDCP_IRQ_SRC | 6)
+#define HDCP_AUTH_REATT_EVENT (HDCP_WORKQUEUE_SRC | 7)
+
+/* Key size */
+#define HDCP_KEY_SIZE 308
+
+/* HDCP DDC Clock */
+#define HDCP_DDC_CLK 100000
+
+/* Authentication retry times */
+#define HDCP_INFINITE_REAUTH 0x100
+
+/* HDCP Regs */
+#define HDCP_CTRL1 0x52
+ #define m_AUTH_START (1 << 7)
+ #define m_BKSV_VALID (1 << 6)
+ #define m_BKSV_INVALID (1 << 5)
+ #define m_ENCRYPT_ENABLE (1 << 4)
+ #define m_AUTH_STOP (1 << 3)
+ #define m_ADVANED_ENABLE (1 << 2)
+ #define m_HDMI_DVI (1 << 1)
+ #define m_HDCP_RESET (1 << 0)
+
+ #define v_AUTH_START(n) (n << 7)
+ #define v_BKSV_VALID(n) (n << 6)
+ #define v_BKSV_INVALID(n) (n << 5)
+ #define v_ENCRYPT_ENABLE(n) (n << 4)
+ #define v_AUTH_STOP(n) (n << 3)
+ #define v_ADVANED_ENABLE(n) (n << 2)
+ #define v_HDMI_DVI(n) (n << 1)
+ #define v_HDCP_RESET(n) (n << 0)
+
+#define HDCP_CTRL2 0x53
+ #define m_DISABLE_127_CHECK (1 << 7)
+ #define m_SKIP_BKSV_CHECK (1 << 6)
+ #define m_ENABLE_PJ_CHECK (1 << 5)
+ #define m_DISABLE_DEVICE_NUMBER_CHECK (1 << 4)
+ #define m_DELAY_RI_1_CLK (1 << 3)
+ #define m_USE_PRESET_AN (1 << 2)
+ #define m_KEY_COMBINATION (3 << 0)
+
+ #define v_DISABLE_127_CHECK(n) (n << 7)
+ #define v_SKIP_BKSV_CHECK(n) (n << 6)
+ #define v_ENABLE_PJ_CHECK(n) (n << 5)
+ #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
+ #define v_DELAY_RI_1_CLK(n) (n << 3)
+ #define v_USE_PRESET_AN(n) (n << 2)
+ #define v_KEY_COMBINATION(n) (n << 0)
+
+#define HDCP_KEY_STATUS 0x54
+ #define m_KEY_READY (1 << 0)
+
+#define HDCP_CTRL_SOFT 0x57
+ #define m_DISABLE_127_CHECK (1 << 7)
+ #define m_SKIP_BKSV_CHECK (1 << 6)
+ #define m_NOT_AUTHENTICATED (1 << 5)
+ #define m_ENCRYPTED (1 << 4)
+ #define m_ADVANCED_CIPHER (1 << 3)
+
+#define HDCP_BCAPS_RX 0x58
+#define HDCP_TIMER_100MS 0x63
+#define HDCP_TIMER_5S 0x64
+#define HDCP_ERROR 0x65
+ #define m_DDC_NO_ACK (1 << 3)
+ #define m_PJ_MISMACH (1 << 2)
+ #define m_RI_MISMACH (1 << 1)
+ #define m_BKSV_WRONG (1 << 0)
+
+#define HDCP_KSV_BYTE0 0x66
+#define HDCP_KSV_BYTE1 0x67
+#define HDCP_KSV_BYTE2 0x68
+#define HDCP_KSV_BYTE3 0x69
+#define HDCP_KSV_BYTE4 0x6a
+
+#define HDCP_AN_SEED 0x6c
+
+#define HDCP_BCAPS_TX 0x80
+#define HDCP_BSTATE_0 0x81
+#define HDCP_BSTATE_1 0x82
+
+#define HDCP_KEY_FIFO 0x98
+
+#define HDCP_INT_MASK1 0xc2
+#define HDCP_INT_STATUS1 0xc3
+ #define m_INT_HDCP_ERR (1 << 7)
+ #define m_INT_BKSV_READY (1 << 6)
+ #define m_INT_BKSV_UPDATE (1 << 5)
+ #define m_INT_AUTH_SUCCESS (1 << 4)
+ #define m_INT_AUTH_READY (1 << 3)
+
+#define HDCP_INT_MASK2 0xc4
+#define HDCP_INT_STATUS2 0xc5
+ #define m_INT_SOFT_MODE_READY (1 << 7)
+ #define m_INT_AUTH_M0_REDAY (1 << 6)
+ #define m_INT_1st_FRAME_ARRIVE (1 << 5)
+ #define m_INT_AN_READY (1 << 4)
+ #define m_INT_ENCRYPTED (1 << 2)
+ #define m_INT_NOT_ENCRYPTED_AVMUTE (1 << 1)
+ #define m_INT_NOT_ENCRYPTED_AVUNMUTE (1 << 0)
+
+enum hdcp_states {
+ HDCP_DISABLED,
+ HDCP_ENABLE_PENDING,
+ HDCP_AUTHENTICATION_START,
+ HDCP_WAIT_KSV_LIST,
+ HDCP_LINK_INTEGRITY_CHECK,
+};
+
+enum hdmi_states {
+ HDMI_STOPPED,
+ HDMI_STARTED
+};
+
+#define HDCP_PRIVATE_KEY_SIZE 280
+#define HDCP_KEY_SHA_SIZE 20
+
+struct hdcp_keys {
+ u8 ksv[8];
+ u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
+ u8 sha1[HDCP_KEY_SHA_SIZE];
+};
+
+struct hdcp_delayed_work {
+ struct delayed_work work;
+ int event;
+};
+
+struct hdcp {
+ int enable;
+ int retry_times;
+ struct hdcp_keys *keys;
+ int invalidkey;
+ char *invalidkeys;
+ struct mutex lock;
+ struct completion complete;
+ struct workqueue_struct *workqueue;
+
+ enum hdmi_states hdmi_state;
+ enum hdcp_states hdcp_state;
+
+ struct delayed_work *pending_start;
+ struct delayed_work *pending_wq_event;
+ int retry_cnt;
+ int auth_state;
+ struct hdmi_dev *hdmi_dev;
+};
+
+#if 1
+#define HDCP_WARN(x...) pr_warn(x)
+#else
+#define I2S_DBG(x...) do { } while (0)
+#endif
+int rockchip_hdmiv1_hdcp_init(struct hdmi *hdmi);
+#endif /* __ROCKCHIP_HDMIV1_HDCP_H__ */
--- /dev/null
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include "rockchip_hdmiv1.h"
+#include "rockchip_hdmiv1_hw.h"
+#include "rockchip_hdmiv1_hdcp.h"
+
+static inline void delay100us(void)
+{
+ usleep_range(99, 100);
+}
+
+static void rockchip_hdmiv1_av_mute(struct hdmi *hdmi_drv, bool enable)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (enable) {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+ v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
+ } else {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+ v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
+ }
+ hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
+ m_PACKET_GCP_EN, v_PACKET_GCP_EN(1));
+}
+
+static void rockchip_hdmiv1_sys_power(struct hdmi *hdmi_drv, bool enable)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (enable)
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
+ else
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
+}
+
+static void rockchip_hdmiv1_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (hdmi_dev->pwr_mode == mode)
+ return;
+
+ dev_info(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
+ hdmi_dev->pwr_mode, mode);
+
+ switch (mode) {
+ case NORMAL:
+ dev_info(hdmi_drv->dev,
+ "%s change pwr_mode NORMAL\n",
+ __func__);
+ rockchip_hdmiv1_sys_power(hdmi_drv, false);
+ if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
+ hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
+ hdmi_writel(hdmi_dev, PHY_DRIVER, 0xbb);
+ } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
+ hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x5f);
+ hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
+ }
+
+ hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
+ hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
+ hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
+ hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
+ hdmi_writel(hdmi_dev, 0xce, 0x00);
+ hdmi_writel(hdmi_dev, 0xce, 0x01);
+ rockchip_hdmiv1_sys_power(hdmi_drv, true);
+ break;
+ case LOWER_PWR:
+ dev_info(hdmi_drv->dev,
+ "%s change pwr_mode LOWER_PWR\n",
+ __func__);
+ rockchip_hdmiv1_sys_power(hdmi_drv, false);
+ hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
+ hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
+ hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
+ hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
+ break;
+ default:
+ dev_info(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
+ mode);
+ }
+
+ hdmi_dev->pwr_mode = mode;
+}
+
+int rockchip_hdmiv1_detect_hotplug(struct hdmi *hdmi_drv)
+{
+ int value = 0;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
+ value &= m_HOTPLUG;
+ if (value == m_HOTPLUG)
+ return HDMI_HPD_ACTIVED;
+ else if (value)
+ return HDMI_HPD_INSERT;
+ else
+ return HDMI_HPD_REMOVED;
+}
+
+int rockchip_hdmiv1_insert(struct hdmi *hdmi_drv)
+{
+ rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
+ return 0;
+}
+
+
+int rockchip_hdmiv1_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
+{
+ u32 c = 0;
+ u8 segment = 0;
+ u8 offset = 0;
+ int ret = -1;
+ int i, j;
+ int ddc_bus_freq;
+ int trytime;
+ int checksum = 0;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (block % 2)
+ offset = HDMI_EDID_BLOCK_SIZE;
+
+ if (block / 2)
+ segment = 1;
+ ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
+ hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
+ hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
+
+ dev_info(hdmi_drv->dev,
+ "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
+ (int)segment, (int)block, (int)offset);
+ disable_irq(hdmi_dev->irq);
+
+ /* Enable edid interrupt */
+ hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
+
+ for (trytime = 0; trytime < 10; trytime++) {
+ checksum = 0;
+ hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
+
+ /* Set edid fifo first addr */
+ hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
+
+ /* Set edid word address 0x00/0x80 */
+ hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
+
+ /* Set edid segment pointer */
+ hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
+
+ for (i = 0; i < 200; i++) {
+ /* Wait edid interrupt */
+ usleep_range(900, 1000);
+ c = 0x00;
+ hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
+
+ if (c & m_INT_EDID_READY)
+ break;
+ }
+
+ if (c & m_INT_EDID_READY) {
+ for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
+ c = 0;
+ hdmi_readl(hdmi_dev, 0x50, &c);
+ buf[j] = c;
+ checksum += c;
+#ifdef HDMI_DEBUG
+ if (j % 16 == 0)
+ printk("\n>>>0x%02x: ", j);
+ printk("0x%02x ", c);
+#endif
+ }
+
+ if ((checksum & 0xff) == 0) {
+ ret = 0;
+ dev_info(hdmi_drv->dev,
+ "[%s] edid read sucess\n", __func__);
+ break;
+ }
+ }
+ }
+ /*close edid irq*/
+ hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
+ /* clear EDID interrupt reg */
+ hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
+ m_INT_EDID_READY);
+
+ enable_irq(hdmi_dev->irq);
+
+ return ret;
+}
+
+static const char coeff_csc[][24] = {
+ /*YUV2RGB:601 SD mode(Y[16:235],UV[16:240],RGB[0:255]):
+ R = 1.164*Y +1.596*V - 204
+ G = 1.164*Y - 0.391*U - 0.813*V + 154
+ B = 1.164*Y + 2.018*U - 258*/
+ {
+ 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
+ 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
+ 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02},
+
+ /*YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
+ R = Y + 1.402*V - 248
+ G = Y - 0.344*U - 0.714*V + 135
+ B = Y + 1.772*U - 227*/
+ {
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
+ 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
+ 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3},
+ /*YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
+ R = 1.164*Y +1.793*V - 248
+ G = 1.164*Y - 0.213*U - 0.534*V + 77
+ B = 1.164*Y + 2.115*U - 289*/
+ {
+ 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
+ 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
+ 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21},
+ /*RGB2YUV:601 SD mode:
+ Cb = -0.291G - 0.148R + 0.439B + 128
+ Y = 0.504G + 0.257R + 0.098B + 16
+ Cr = -0.368G + 0.439R - 0.071B + 128*/
+ {
+ /*0x11, 0x78, 0x01, 0xc1, 0x10, 0x48, 0x00, 0x80,
+ 0x02, 0x04, 0x01, 0x07, 0x00, 0x64, 0x00, 0x10,
+ 0x11, 0x29, 0x10, 0x97, 0x01, 0xc1, 0x00, 0x80*/
+
+ /*0x11,0x4b,0x01,0x8a,0x10,0x3f,0x00,0x80,
+ 0x01,0xbb,0x00,0xe2,0x00,0x56,0x00,0x1d,
+ 0x11,0x05,0x10,0x85,0x01,0x8a,0x00,0x80*/
+
+ 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
+ 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
+ 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
+ },
+
+ /*RGB2YUV:709 HD mode:
+ Cb = - 0.338G - 0.101R + 0.439B + 128
+ Y = 0.614G + 0.183R + 0.062B + 16
+ Cr = - 0.399G + 0.439R - 0.040B + 128*/
+ {
+ 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
+ 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
+ 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
+ },
+ /*RGB[0:255]2RGB[16:235]:
+ R' = R x (235-16)/255 + 16;
+ G' = G x (235-16)/255 + 16;
+ B' = B x (235-16)/255 + 16;*/
+ {
+ 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
+ 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10},
+};
+
+static int rockchip_hdmiv1_video_csc(struct hdmi *hdmi_drv,
+ struct hdmi_video *vpara)
+{
+ int value, i, csc_mode, c0_c2_change, auto_csc, csc_enable;
+ const char *coeff = NULL;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ /* Enable or disalbe color space convert */
+ dev_info(hdmi_drv->dev, "[%s] input_color=%d,output_color=%d\n",
+ __func__, vpara->color_input, vpara->color_output);
+ if (vpara->color_input == vpara->color_output) {
+ if ((vpara->color_input >= HDMI_COLOR_YCBCR444) ||
+ (vpara->color_input == HDMI_COLOR_RGB_0_255)) {
+ value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
+ v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
+ v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
+ return 0;
+ } else if (vpara->color_input == HDMI_COLOR_RGB_16_235) {
+ csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_ENABLE;
+ }
+ }
+
+ switch (vpara->vic) {
+ case HDMI_720X480I_60HZ_4_3:
+ case HDMI_720X576I_50HZ_4_3:
+ case HDMI_720X480P_60HZ_4_3:
+ case HDMI_720X576P_50HZ_4_3:
+ case HDMI_720X480I_60HZ_16_9:
+ case HDMI_720X576I_50HZ_16_9:
+ case HDMI_720X480P_60HZ_16_9:
+ case HDMI_720X576P_50HZ_16_9:
+ if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
+ (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
+ vpara->color_output >= HDMI_COLOR_YCBCR444) {
+ csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_ENABLE;
+ } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
+ ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
+ (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
+#ifdef AUTO_DEFINE_CSC
+ csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
+ auto_csc = AUTO_CSC_ENABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_DISABLE;
+#else
+ csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_ENABLE;
+ csc_enable = v_CSC_ENABLE;
+#endif
+ }
+ break;
+ default:
+ if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
+ (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
+ vpara->color_output >= HDMI_COLOR_YCBCR444) {
+ csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_ENABLE;
+ } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
+ ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
+ (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
+#ifdef AUTO_DEFINE_CSC
+ csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
+ auto_csc = AUTO_CSC_ENABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_DISABLE;
+#else
+ /*CSC_ITU709_16_235_TO_RGB_0_255_8BIT;*/
+ csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_ENABLE;
+ csc_enable = v_CSC_ENABLE;
+#endif
+ }
+ break;
+ }
+
+ coeff = coeff_csc[csc_mode];
+ for (i = 0; i < 24; i++)
+ hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
+
+ value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC |
+ m_VIDEO_C0_C2_SWAP,
+ v_VIDEO_AUTO_CSC(auto_csc) |
+ v_VIDEO_C0_C2_SWAP(c0_c2_change));
+
+#if 0
+ if (vpara->input_color != vpara->output_color) {
+ if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb2yuv*/
+ coeff = coeff_csc[3];
+ for (i = 0; i < 24; i++)
+ hdmi_writel(hdmi_dev,
+ VIDEO_CSC_COEF+i, coeff[i]);
+
+ value = v_SOF_DISABLE | v_CSC_ENABLE;
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
+ v_VIDEO_AUTO_CSC(0) |
+ v_VIDEO_C0_C2_EXCHANGE(1));
+ } else {/*yuv2rgb*/
+#ifdef AUTO_DEFINE_CSC
+ value = v_SOF_DISABLE | v_CSC_DISABLE;
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
+ v_VIDEO_AUTO_CSC(1) |
+ v_VIDEO_C0_C2_EXCHANGE(1));
+#else
+ if (hdmi_drv->lcdc->cur_screen->mode.xres <= 576) {
+ /*x <= 576,REC-601*/
+ coeff = coeff_csc[0];
+ pr_info("xres<=576,xres=%d\n",
+ hdmi_drv->lcdc->cur_screen->mode.xres);
+ } else/*x > 576,REC-709*/{
+ coeff = coeff_csc[2];
+ pr_info("xres>576,xres=%d\n",
+ hdmi_drv->lcdc->cur_screen->mode.xres);
+ }
+ for (i = 0; i < 24; i++)
+ hdmi_writel(hdmi_dev,
+ VIDEO_CSC_COEF+i, coeff[i]);
+
+ value = v_SOF_DISABLE | v_CSC_ENABLE;
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC |
+ m_VIDEO_C0_C2_EXCHANGE,
+ v_VIDEO_AUTO_CSC(0) |
+ v_VIDEO_C0_C2_EXCHANGE(0));
+#endif
+ }
+ } else {
+ if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
+ /*rgb[0:255]->rbg[16:235]*/
+ coeff = coeff_csc[5];
+ for (i = 0; i < 24; i++)
+ hdmi_writel(hdmi_dev,
+ VIDEO_CSC_COEF+i, coeff[i]);
+
+ value = v_SOF_DISABLE | v_CSC_ENABLE;
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
+ v_VIDEO_AUTO_CSC(0) |
+ v_VIDEO_C0_C2_EXCHANGE(1));
+ } else {
+ value = v_SOF_DISABLE;
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+ hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC |
+ m_VIDEO_C0_C2_EXCHANGE,
+ v_VIDEO_AUTO_CSC(0) |
+ v_VIDEO_C0_C2_EXCHANGE(1));
+ }
+ }
+#endif
+ return 0;
+}
+
+static int rockchip_hdmiv1_config_vsi(struct hdmi *hdmi,
+ unsigned char vic_3d,
+ unsigned char format)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ char info[SIZE_VSI_INFOFRAME];
+ int i;
+
+ DBG("[%s] vic_3d %d format %d.\n", __func__, vic_3d, format);
+ memset(info, 0, SIZE_VSI_INFOFRAME);
+ hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
+ m_PACKET_VSI_EN, v_PACKET_VSI_EN(0));
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_VSI);
+ /* Header Bytes */
+ info[0] = 0x81;
+ info[1] = 0x01;
+ /* PB1 - PB3 contain the 24bit IEEE Registration Identifier */
+ info[4] = 0x03;
+ info[5] = 0x0c;
+ info[6] = 0x00;
+ /* PB4 - HDMI_Video_Format into bits 7:5 */
+ info[7] = format << 5;
+ /* PB5 - Depending on the video format, this byte will contain either
+ the HDMI_VIC code in buts 7:0, OR the 3D_Structure in bits 7:4. */
+ switch (format) {
+ case HDMI_VIDEO_FORMAT_4KX2K:
+ /* This is a 2x4K mode, set the HDMI_VIC in buts 7:0. Values
+ are from HDMI 1.4 Spec, 8.2.3.1 (Table 8-13). */
+ info[2] = 0x06 - 1;
+ info[8] = vic_3d;
+ info[9] = 0;
+ break;
+ case HDMI_VIDEO_FORMAT_3D:
+ /* This is a 3D mode, set the 3D_Structure in buts 7:4
+ Bits 3:0 are reseved so set to 0. Values are from HDMI 1.4
+ Spec, Appendix H (Table H-2). */
+ info[8] = vic_3d << 4;
+ /* Add the Extended data field when the 3D format is
+ Side-by-Side(Half). See Spec Table H-3 for details. */
+ if ((info[8] >> 4) == HDMI_3D_SIDE_BY_SIDE_HALF) {
+ info[2] = 0x06;
+ info[9] = 0x00;
+ } else {
+ info[2] = 0x06 - 1;
+ }
+ break;
+ default:
+ info[2] = 0x06 - 2;
+ info[8] = 0;
+ info[9] = 0;
+ break;
+ }
+ info[3] = info[0] + info[1] + info[2];
+ /* Calculate InfoFrame ChecKsum */
+ for (i = 4; i < SIZE_VSI_INFOFRAME; i++)
+ info[3] += info[i];
+ info[3] = 0x100 - info[3];
+
+ for (i = 0; i < SIZE_VSI_INFOFRAME; i++)
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
+ hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
+ m_PACKET_VSI_EN, v_PACKET_VSI_EN(1));
+ return 0;
+}
+
+static void rockchip_hdmiv1_config_avi(struct hdmi *hdmi_drv,
+ unsigned char vic,
+ unsigned char output_color)
+{
+ int i;
+ int avi_color_mode;
+ char info[SIZE_AVI_INFOFRAME];
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ memset(info, 0, SIZE_AVI_INFOFRAME);
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+ info[0] = 0x82;
+ info[1] = 0x02;
+ info[2] = 0x0D;
+ info[3] = info[0] + info[1] + info[2];
+
+ if ((output_color == HDMI_COLOR_RGB_0_255) ||
+ (output_color == HDMI_COLOR_RGB_16_235))
+ avi_color_mode = AVI_COLOR_MODE_RGB;
+ else if (output_color == HDMI_COLOR_YCBCR444)
+ avi_color_mode = AVI_COLOR_MODE_YCBCR444;
+ else if (output_color == HDMI_COLOR_YCBCR422)
+ avi_color_mode = AVI_COLOR_MODE_YCBCR422;
+
+ info[4] = (avi_color_mode << 5);
+ info[5] =
+ (AVI_COLORIMETRY_NO_DATA << 6) |
+ (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) |
+ ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
+ info[6] = 0;
+ info[7] = vic;
+ if ((vic == HDMI_720X480I_60HZ_4_3) ||
+ (vic == HDMI_720X576I_50HZ_4_3) ||
+ (vic == HDMI_720X480I_60HZ_16_9) ||
+ (vic == HDMI_720X480I_60HZ_16_9))
+ info[8] = 1;
+ else
+ info[8] = 0;
+
+ /* Calculate AVI InfoFrame ChecKsum */
+ for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
+ info[3] += info[i];
+
+ info[3] = 0x100 - info[3];
+
+ for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rockchip_hdmiv1_config_video(struct hdmi *hdmi_drv,
+ struct hdmi_video *vpara)
+{
+ struct fb_videomode *mode;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+ int value;
+
+ dev_dbg(hdmi_drv->dev, "[%s]\n", __func__);
+
+ if (vpara == NULL) {
+ dev_err(hdmi_drv->dev, "[%s] input parameter error\n",
+ __func__);
+ return -1;
+ }
+
+ if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
+ /*rk3036 vop only can output rgb fmt*/
+ vpara->color_input = HDMI_COLOR_RGB_0_255;
+ } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
+ /* rk3128 vop can output yuv444 fmt */
+ /*if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
+ vpara->output_color = VIDEO_OUTPUT_YCBCR444;
+ else
+ vpara->output_color = VIDEO_OUTPUT_RGB444;*/
+ }
+
+ mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
+ if (mode == NULL) {
+ dev_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
+ vpara->vic);
+ return -ENOENT;
+ }
+ hdmi_dev->tmdsclk = mode->pixclock;
+ if (hdmi_drv->uboot)
+ return 0;
+ /* Disable video and audio output */
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+
+ /* Input video mode is SDR RGB24bit,
+ Data enable signal from external */
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
+ v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
+ v_DE_EXTERNAL);
+
+ value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS);
+ if (vpara->color_output <= HDMI_COLOR_RGB_16_235)
+ value |= v_VIDEO_OUTPUT_COLOR(0);
+ else
+ value |= v_VIDEO_OUTPUT_COLOR((vpara->color_output - 2) & 0x3);
+ if (vpara->color_input <= HDMI_COLOR_RGB_16_235)
+ value |= v_VIDEO_INPUT_CSP(0);
+ else
+ value |= v_VIDEO_INPUT_CSP((vpara->color_input - 2) & 0x1);
+
+ hdmi_writel(hdmi_dev, VIDEO_CONTRL2, value);
+ /* Set HDMI Mode */
+ hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->sink_hdmi));
+
+ /* Enable or disalbe color space convert */
+ rockchip_hdmiv1_video_csc(hdmi_drv, vpara);
+
+ /* Set ext video timing */
+ if (mode->vmode || mode->pixclock <= 27000000) {
+ hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
+ } else {
+ value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+ value |= v_HSYNC_POLARITY(1);
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ value |= v_VSYNC_POLARITY(1);
+ hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
+
+ value = mode->left_margin +
+ mode->xres + mode->right_margin +
+ mode->hsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
+
+ value = mode->left_margin +
+ mode->right_margin +
+ mode->hsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
+
+ value = mode->left_margin + mode->hsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
+
+ value = mode->hsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L,
+ value & 0xFF);
+ hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H,
+ (value >> 8) & 0xFF);
+
+ value = mode->upper_margin + mode->yres + mode->lower_margin +
+ mode->vsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
+ hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
+
+ value = mode->upper_margin +
+ mode->vsync_len +
+ mode->lower_margin;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
+
+ if (vpara->vic == HDMI_720X480P_60HZ_4_3 ||
+ vpara->vic == HDMI_720X480P_60HZ_16_9)
+ value = 42;
+ else
+ value = mode->upper_margin + mode->vsync_len;
+
+ hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
+
+ value = mode->vsync_len;
+ hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
+ }
+ if (vpara->sink_hdmi == OUTPUT_HDMI) {
+ rockchip_hdmiv1_config_avi(hdmi_drv, vpara->vic,
+ vpara->color_output);
+ if (vpara->format_3d != HDMI_3D_NONE) {
+ rockchip_hdmiv1_config_vsi(hdmi_drv,
+ vpara->format_3d,
+ HDMI_VIDEO_FORMAT_3D);
+ } else if ((vpara->vic > 92 && vpara->vic < 96) ||
+ (vpara->vic == 98)) {
+ vpara->vic = (vpara->vic == 98) ?
+ 4 : (96 - vpara->vic);
+ rockchip_hdmiv1_config_vsi(hdmi_drv,
+ vpara->vic,
+ HDMI_VIDEO_FORMAT_4KX2K);
+ } else {
+ rockchip_hdmiv1_config_vsi(hdmi_drv,
+ vpara->vic,
+ HDMI_VIDEO_FORMAT_NORMAL);
+ }
+ dev_info(hdmi_drv->dev,
+ "[%s] sucess output HDMI.\n", __func__);
+ } else {
+ dev_info(hdmi_drv->dev,
+ "[%s] sucess output DVI.\n", __func__);
+ }
+
+ /* rk3028a */
+ hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
+ hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
+ hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
+
+ return 0;
+}
+
+static void rockchip_hdmiv1_config_aai(struct hdmi *hdmi_drv)
+{
+ int i;
+ char info[SIZE_AUDIO_INFOFRAME];
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ memset(info, 0, SIZE_AUDIO_INFOFRAME);
+
+ info[0] = 0x84;
+ info[1] = 0x01;
+ info[2] = 0x0A;
+
+ info[3] = info[0] + info[1] + info[2];
+ for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
+ info[3] += info[i];
+
+ info[3] = 0x100 - info[3];
+
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
+ for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
+ hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rockchip_hdmiv1_config_audio(struct hdmi *hdmi_drv,
+ struct hdmi_audio *audio)
+{
+ int rate, N, channel, mclk_fs;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (audio->channel < 3)
+ channel = I2S_CHANNEL_1_2;
+ else if (audio->channel < 5)
+ channel = I2S_CHANNEL_3_4;
+ else if (audio->channel < 7)
+ channel = I2S_CHANNEL_5_6;
+ else
+ channel = I2S_CHANNEL_7_8;
+
+ switch (audio->rate) {
+ case HDMI_AUDIO_FS_32000:
+ rate = AUDIO_32K;
+ N = N_32K;
+ mclk_fs = MCLK_384FS;
+ break;
+ case HDMI_AUDIO_FS_44100:
+ rate = AUDIO_441K;
+ N = N_441K;
+ mclk_fs = MCLK_256FS;
+ break;
+ case HDMI_AUDIO_FS_48000:
+ rate = AUDIO_48K;
+ N = N_48K;
+ mclk_fs = MCLK_256FS;
+ break;
+ case HDMI_AUDIO_FS_88200:
+ rate = AUDIO_882K;
+ N = N_882K;
+ mclk_fs = MCLK_128FS;
+ break;
+ case HDMI_AUDIO_FS_96000:
+ rate = AUDIO_96K;
+ N = N_96K;
+ mclk_fs = MCLK_128FS;
+ break;
+ case HDMI_AUDIO_FS_176400:
+ rate = AUDIO_1764K;
+ N = N_1764K;
+ mclk_fs = MCLK_128FS;
+ break;
+ case HDMI_AUDIO_FS_192000:
+ rate = AUDIO_192K;
+ N = N_192K;
+ mclk_fs = MCLK_128FS;
+ break;
+ default:
+ dev_err(hdmi_drv->dev,
+ "[%s] not support such sample rate %d\n",
+ __func__, audio->rate);
+ return -ENOENT;
+ }
+
+ /* set_audio source I2S */
+ if (hdmi_dev->audiosrc == HDMI_AUDIO_SRC_IIS) {
+ hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
+ hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
+ hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
+ v_I2S_MODE(I2S_STANDARD) |
+ v_I2S_CHANNEL(channel));
+ hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
+ /* no swap */
+ hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
+ } else {
+ hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
+ /* no swap */
+ hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
+ }
+
+ /* Set N value */
+ hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
+ hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
+ hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
+ rockchip_hdmiv1_config_aai(hdmi_drv);
+
+ return 0;
+}
+
+int rockchip_hdmiv1_control_output(struct hdmi *hdmi_drv, int enable)
+{
+ int mutestatus = 0;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (hdmi_drv->uboot) {
+ hdmi_drv->uboot = 0;
+ return 0;
+ }
+
+ if (enable == HDMI_AV_UNMUTE) {
+ if (hdmi_dev->pwr_mode == LOWER_PWR)
+ rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
+
+ rockchip_hdmiv1_sys_power(hdmi_drv, true);
+ rockchip_hdmiv1_sys_power(hdmi_drv, false);
+ delay100us();
+ rockchip_hdmiv1_sys_power(hdmi_drv, true);
+ hdmi_writel(hdmi_dev, 0xce, 0x00);
+ delay100us();
+ hdmi_writel(hdmi_dev, 0xce, 0x01);
+
+ hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
+ if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+ }
+ rockchip_hdmiv1_av_mute(hdmi_drv, 0);
+ } else {
+ hdmi_msk_reg(hdmi_dev, AV_MUTE,
+ m_AUDIO_MUTE | m_VIDEO_BLACK,
+ v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+ rockchip_hdmiv1_av_mute(hdmi_drv, 1);
+ msleep(100);
+ rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
+ }
+ return 0;
+}
+
+int rockchip_hdmiv1_removed(struct hdmi *hdmi_drv)
+{
+ dev_info(hdmi_drv->dev, "Removed.\n");
+ if (hdmi_drv->ops->hdcp_power_off_cb)
+ hdmi_drv->ops->hdcp_power_off_cb();
+
+ rockchip_hdmiv1_control_output(hdmi_drv, -1);
+ rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
+
+ return HDMI_ERROR_SUCESS;
+}
+
+static int rockchip_hdmiv1_enable(struct hdmi *hdmi_drv)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (!hdmi_dev->enable)
+ hdmi_dev->enable = 1;
+ hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 10, NULL);
+ return 0;
+}
+
+static int rockchip_hdmiv1_disable(struct hdmi *hdmi_drv)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ if (hdmi_dev->enable)
+ hdmi_dev->enable = 0;
+
+ return 0;
+}
+
+void rockchip_hdmiv1_irq(struct hdmi *hdmi_drv)
+{
+ u32 interrupt = 0;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
+ if (interrupt) {
+ hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
+ dev_info(hdmi_drv->dev, "Clear edid irq.\n");
+ }
+
+ hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
+ if (interrupt)
+ hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
+ if (interrupt & m_INT_HOTPLUG)
+ hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 20, NULL);
+
+ if (hdmi_drv->ops->hdcp_irq_cb)
+ hdmi_drv->ops->hdcp_irq_cb(0);
+ if (hdmi_drv->property->feature & SUPPORT_CEC)
+ rockchip_hdmiv1_cec_isr(hdmi_dev);
+}
+
+static void rockchip_hdmiv1_reset(struct hdmi *hdmi_drv)
+{
+ u32 val = 0;
+ u32 msk = 0;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
+ delay100us();
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
+ delay100us();
+ msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
+ val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
+ hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
+
+ rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
+}
+
+void rockchip_hdmiv1_dev_init_ops(struct hdmi_ops *ops)
+{
+ if (ops) {
+ ops->disable = rockchip_hdmiv1_disable;
+ ops->enable = rockchip_hdmiv1_enable;
+ ops->remove = rockchip_hdmiv1_removed;
+ ops->setmute = rockchip_hdmiv1_control_output;
+ ops->setvideo = rockchip_hdmiv1_config_video;
+ ops->setaudio = rockchip_hdmiv1_config_audio;
+ ops->getstatus = rockchip_hdmiv1_detect_hotplug;
+ ops->getedid = rockchip_hdmiv1_read_edid;
+ ops->insert = rockchip_hdmiv1_insert;
+ ops->setvsi = rockchip_hdmiv1_config_vsi;
+ }
+}
+
+int rockchip_hdmiv1_initial(struct hdmi *hdmi_drv)
+{
+ int rc = HDMI_ERROR_SUCESS;
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+
+ hdmi_dev->pwr_mode = NORMAL;
+
+ if (!hdmi_drv->uboot) {
+ rockchip_hdmiv1_reset_pclk();
+ rockchip_hdmiv1_reset(hdmi_drv);
+ } else if (hdmi_drv->ops->getstatus(hdmi_drv) == HDMI_HPD_REMOVED) {
+ rockchip_hdmiv1_removed(hdmi_drv);
+ hdmi_drv->lcdc->uboot_logo = 0;
+ hdmi_drv->uboot = 0;
+ }
+ if (hdmi_drv->property->feature & SUPPORT_CEC)
+ rockchip_hdmiv1_cec_init(hdmi_drv);
+ if (hdmi_drv->property->feature & SUPPORT_HDCP)
+ rockchip_hdmiv1_hdcp_init(hdmi_drv);
+ return rc;
+}
--- /dev/null
+#ifndef __ROCKCHIP_HDMI_V1_HW_H__
+#define __ROCKCHIP_HDMI_V1_HW_H__
+
+#include <linux/rockchip/iomap.h>
+#include <linux/delay.h>
+
+enum PWR_MODE {
+ NORMAL,
+ LOWER_PWR,
+};
+enum {
+ OUTPUT_DVI = 0,
+ OUTPUT_HDMI
+};
+
+/* C0 C2 Change */
+enum {
+ C0_C2_CHANGE_ENABLE, /* enable c0 c2 change*/
+ C0_C2_CHANGE_DISABLE /* disable c0 c2 change*/
+};
+
+/* Auto CSC mode enable */
+enum {
+ AUTO_CSC_DISABLE, /* disable auto csc*/
+ AUTO_CSC_ENABLE /* enable auto csc*/
+};
+
+
+/* Color Limit Range */
+enum {
+ COLOR_LIMIT_RANGE_0_255, /* Color Limit Range 0 To 255*/
+ COLOR_LIMIT_RANGE_16_235, /* Color Limit Range 16 To 235*/
+};
+/* Color Space Convertion Mode */
+enum {
+ CSC_ITU601_16_235_TO_RGB_0_255_8BIT,/* YCbCr 16-235 input to RGB
+ 0-255 output according BT601
+ that is 8bit clolor depth */
+ CSC_ITU601_0_255_TO_RGB_0_255_8BIT, /* YCbCr 0-255 input to RGB
+ 0-255 output according BT601
+ that is 8bit clolor depth */
+ CSC_ITU709_16_235_TO_RGB_0_255_8BIT,/* YCbCr 16-235 input to RGB
+ 0-255 output according BT709
+ that is 8bit clolor depth */
+ CSC_RGB_0_255_TO_ITU601_16_235_8BIT,/* RGB 0-255 input to YCbCr
+ 16-235 output according BT601
+ that is 8bit clolor depth */
+ CSC_RGB_0_255_TO_ITU709_16_235_8BIT,/* RGB 0-255 input to YCbCr 16-235
+ output accroding BT709 that is
+ 8bit clolor depth */
+ CSC_RGB_0_255_TO_RGB_16_235_8BIT, /* RGB 0-255 input to RGB 16-235
+ output that is 8bit clolor depth
+ */
+};
+
+
+#define AUTO_DEFINE_CSC
+#ifdef RK616_USE_MCLK_12M
+#define HDMI_SYS_FREG_CLK 12000000
+#else
+#define HDMI_SYS_FREG_CLK 11289600
+#endif
+
+#define HDMI_SCL_RATE (100*1000)
+#define DDC_BUS_FREQ_L 0x4b
+#define DDC_BUS_FREQ_H 0x4c
+
+#define SYS_CTRL 0x00
+#define m_RST_ANALOG (1 << 6)
+#define v_RST_ANALOG (0 << 6)
+#define v_NOT_RST_ANALOG (1 << 6)
+
+#define m_RST_DIGITAL (1 << 5)
+#define v_RST_DIGITAL (0 << 5)
+#define v_NOT_RST_DIGITAL (1 << 5)
+
+#define m_REG_CLK_INV (1 << 4)
+#define v_REG_CLK_NOT_INV (0 << 4)
+#define v_REG_CLK_INV (1 << 4)
+#define m_VCLK_INV (1 << 3)
+#define v_VCLK_NOT_INV (0 << 3)
+#define v_VCLK_INV (1 << 3)
+#define m_REG_CLK_SOURCE (1 << 2)
+#define v_REG_CLK_SOURCE_TMDS (0 << 2)
+#define v_REG_CLK_SOURCE_SYS (1 << 2)
+#define m_POWER (1 << 1)
+#define v_PWR_ON (0 << 1)
+#define v_PWR_OFF (1 << 1)
+#define m_INT_POL (1 << 0)
+#define v_INT_POL_HIGH 1
+#define v_INT_POL_LOW 0
+
+#define VIDEO_CONTRL1 0x01
+#define m_VIDEO_INPUT_FORMAT (7 << 1)
+#define m_DE_SOURCE (1 << 0)
+enum {
+ VIDEO_INPUT_SDR_RGB444 = 0,
+ VIDEO_INPUT_DDR_RGB444 = 5,
+ VIDEO_INPUT_DDR_YCBCR422 = 6
+};
+#define v_VIDEO_INPUT_FORMAT(n) (n << 1)
+#define v_DE_EXTERNAL 1
+#define v_DE_INTERANL 0
+
+#define VIDEO_CONTRL2 0x02
+#define m_VIDEO_OUTPUT_COLOR (3 << 6)
+#define m_VIDEO_INPUT_BITS (3 << 4)
+#define m_VIDEO_INPUT_CSP (1 << 0)
+#define v_VIDEO_OUTPUT_COLOR(n) (((n)&0x3) << 6)
+#define v_VIDEO_INPUT_BITS(n) (n << 4)
+#define v_VIDEO_INPUT_CSP(n) (n << 0)
+
+enum {
+ VIDEO_INPUT_12BITS = 0,
+ VIDEO_INPUT_10BITS,
+ VIDEO_INPUT_REVERT,
+ VIDEO_INPUT_8BITS
+};
+#define VIDEO_CONTRL 0x03
+#define m_VIDEO_AUTO_CSC (1 << 7)
+#define v_VIDEO_AUTO_CSC(n) (n << 7)
+#define m_VIDEO_C0_C2_SWAP (1 << 0)
+#define v_VIDEO_C0_C2_SWAP(n) (n << 0)
+
+
+#define VIDEO_CONTRL3 0x04
+#define m_COLOR_DEPTH_NOT_INDICATED (1 << 4)
+#define m_SOF (1 << 3)
+#define m_COLOR_RANGE (1 << 2)
+#define m_CSC (1 << 0)
+#define v_COLOR_DEPTH_NOT_INDICATED(n) ((n) << 4) /*1: Force GCP CD[3:0] zero
+ 0: GCP CD[3:0] according
+ color depth*/
+#define v_SOF_ENABLE (0 << 3)
+#define v_SOF_DISABLE (1 << 3)
+#define v_COLOR_RANGE_FULL (1 << 2)
+#define v_COLOR_RANGE_LIMITED (0 << 2)
+#define v_CSC_ENABLE 1
+#define v_CSC_DISABLE 0
+
+#define AV_MUTE 0x05
+#define m_AVMUTE_CLEAR (1 << 7)
+#define m_AVMUTE_ENABLE (1 << 6)
+#define m_AUDIO_MUTE (1 << 1)
+#define m_VIDEO_BLACK (1 << 0)
+#define v_AVMUTE_CLEAR(n) (n << 7)
+#define v_AVMUTE_ENABLE(n) (n << 6)
+#define v_AUDIO_MUTE(n) (n << 1)
+#define v_VIDEO_MUTE(n) (n << 0)
+
+#define VIDEO_TIMING_CTL 0x08
+#define v_HSYNC_POLARITY(n) (n << 3)
+#define v_VSYNC_POLARITY(n) (n << 2)
+#define v_INETLACE(n) (n << 1)
+#define v_EXTERANL_VIDEO(n) (n << 0)
+
+#define VIDEO_EXT_HTOTAL_L 0x09
+#define VIDEO_EXT_HTOTAL_H 0x0a
+#define VIDEO_EXT_HBLANK_L 0x0b
+#define VIDEO_EXT_HBLANK_H 0x0c
+#define VIDEO_EXT_HDELAY_L 0x0d
+#define VIDEO_EXT_HDELAY_H 0x0e
+#define VIDEO_EXT_HDURATION_L 0x0f
+#define VIDEO_EXT_HDURATION_H 0x10
+#define VIDEO_EXT_VTOTAL_L 0x11
+#define VIDEO_EXT_VTOTAL_H 0x12
+#define VIDEO_EXT_VBLANK 0x13
+#define VIDEO_EXT_VDELAY 0x14
+#define VIDEO_EXT_VDURATION 0x15
+
+#define VIDEO_CSC_COEF 0x18
+
+
+#define AUDIO_CTRL1 0x35
+enum {
+ CTS_SOURCE_INTERNAL = 0,
+ CTS_SOURCE_EXTERNAL
+};
+#define v_CTS_SOURCE(n) (n << 7)
+enum {
+ DOWNSAMPLE_DISABLE = 0,
+ DOWNSAMPLE_1_2,
+ DOWNSAMPLE_1_4
+};
+#define v_DOWN_SAMPLE(n) (n << 5)
+enum {
+ AUDIO_SOURCE_IIS = 0,
+ AUDIO_SOURCE_SPDIF
+};
+#define v_AUDIO_SOURCE(n) (n << 3)
+#define v_MCLK_ENABLE(n) (n << 2)
+enum {
+ MCLK_128FS = 0,
+ MCLK_256FS,
+ MCLK_384FS,
+ MCLK_512FS
+};
+#define v_MCLK_RATIO(n) (n)
+
+#define AUDIO_SAMPLE_RATE 0x37
+enum {
+ AUDIO_32K = 0x3,
+ AUDIO_441K = 0x0,
+ AUDIO_48K = 0x2,
+ AUDIO_882K = 0x8,
+ AUDIO_96K = 0xa,
+ AUDIO_1764K = 0xc,
+ AUDIO_192K = 0xe,
+};
+
+#define AUDIO_I2S_MODE 0x38
+enum {
+ I2S_CHANNEL_1_2 = 1,
+ I2S_CHANNEL_3_4 = 3,
+ I2S_CHANNEL_5_6 = 7,
+ I2S_CHANNEL_7_8 = 0xf
+};
+#define v_I2S_CHANNEL(n) ((n) << 2)
+enum {
+ I2S_STANDARD = 0,
+ I2S_LEFT_JUSTIFIED,
+ I2S_RIGHT_JUSTIFIED
+};
+#define v_I2S_MODE(n) (n)
+
+#define AUDIO_I2S_MAP 0x39
+#define AUDIO_I2S_SWAPS_SPDIF 0x3a
+#define v_SPIDF_FREQ(n) (n)
+
+#define N_32K 0x1000
+#define N_441K 0x1880
+#define N_882K 0x3100
+#define N_1764K 0x6200
+#define N_48K 0x1800
+#define N_96K 0x3000
+#define N_192K 0x6000
+
+#define AUDIO_N_H 0x3f
+#define AUDIO_N_M 0x40
+#define AUDIO_N_L 0x41
+
+#define AUDIO_CTS_H 0x45
+#define AUDIO_CTS_M 0x46
+#define AUDIO_CTS_L 0x47
+
+#define DDC_CLK_L 0x4b
+#define DDC_CLK_H 0x4c
+
+#define EDID_SEGMENT_POINTER 0x4d
+#define EDID_WORD_ADDR 0x4e
+#define EDID_FIFO_OFFSET 0x4f
+#define EDID_FIFO_ADDR 0x50
+
+
+#define PACKET_SEND_MANUAL 0x9c
+#define PACKET_SEND_AUTO 0x9d
+ #define m_PACKET_GCP_EN (1 << 7)
+ #define m_PACKET_MSI_EN (1 << 6) /*MPEG Source InfoFrame*/
+ #define m_PACKET_SDI_EN (1 << 5) /*Source product descriptor*/
+ #define m_PACKET_VSI_EN (1 << 4) /*HDMI Vendor Specific
+ InfoFrame*/
+ #define v_PACKET_GCP_EN(n) ((n & 1) << 7)
+ #define v_PACKET_MSI_EN(n) ((n & 1) << 6)
+ #define v_PACKET_SDI_EN(n) ((n & 1) << 5)
+ #define v_PACKET_VSI_EN(n) ((n & 1) << 4)
+
+/* CONTROL_PACKET_BUF_INDEX */
+#define CONTROL_PACKET_BUF_INDEX 0x9f
+enum {
+ INFOFRAME_VSI = 0x05,
+ INFOFRAME_AVI = 0x06,
+ INFOFRAME_AAI = 0x08,
+};
+#define CONTROL_PACKET_ADDR 0xa0
+#define SIZE_VSI_INFOFRAME 0x0A /* 10 bytes */
+#define SIZE_AVI_INFOFRAME 0x11 /* 14 bytes */
+#define SIZE_AUDIO_INFOFRAME 0x0F /* 15 bytes */
+enum {
+ AVI_COLOR_MODE_RGB = 0,
+ AVI_COLOR_MODE_YCBCR422,
+ AVI_COLOR_MODE_YCBCR444
+};
+enum {
+ AVI_COLORIMETRY_NO_DATA = 0,
+ AVI_COLORIMETRY_SMPTE_170M,
+ AVI_COLORIMETRY_ITU709,
+ AVI_COLORIMETRY_EXTENDED
+};
+enum {
+ AVI_CODED_FRAME_ASPECT_NO_DATA,
+ AVI_CODED_FRAME_ASPECT_4_3,
+ AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+ ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
+ ACTIVE_ASPECT_RATE_4_3,
+ ACTIVE_ASPECT_RATE_16_9,
+ ACTIVE_ASPECT_RATE_14_9
+};
+
+#define HDCP_CTRL 0x52
+#define m_HDMI_DVI (1 << 1)
+#define v_HDMI_DVI(n) (n << 1)
+
+#define INTERRUPT_MASK1 0xc0
+#define INTERRUPT_STATUS1 0xc1
+#define m_INT_ACTIVE_VSYNC (1 << 5)
+#define m_INT_EDID_READY (1 << 2)
+
+#define INTERRUPT_MASK2 0xc2
+#define INTERRUPT_STATUS2 0xc3
+#define m_INT_HDCP_ERR (1 << 7)
+#define m_INT_BKSV_FLAG (1 << 6)
+#define m_INT_HDCP_OK (1 << 4)
+
+#define HDMI_STATUS 0xc8
+ #define m_HOTPLUG (1 << 7)
+ #define m_MASK_INT_HOTPLUG (1 << 5)
+ #define m_INT_HOTPLUG (1 << 1)
+ #define v_MASK_INT_HOTPLUG(n) ((n & 0x1) << 5)
+
+#define HDMI_COLORBAR 0xc9
+
+#define PHY_SYNC 0xce /* sync phy parameter */
+#define PHY_SYS_CTL 0xe0
+#define m_TMDS_CLK_SOURCE (1 << 5)
+#define v_TMDS_FROM_PLL (0 << 5)
+#define v_TMDS_FROM_GEN (1 << 5)
+#define m_PHASE_CLK (1 << 4)
+#define v_DEFAULT_PHASE (0 << 4)
+#define v_SYNC_PHASE (1 << 4)
+#define m_TMDS_CURRENT_PWR (1 << 3)
+#define v_TURN_ON_CURRENT (0 << 3)
+#define v_CAT_OFF_CURRENT (1 << 3)
+#define m_BANDGAP_PWR (1 << 2)
+#define v_BANDGAP_PWR_UP (0 << 2)
+#define v_BANDGAP_PWR_DOWN (1 << 2)
+#define m_PLL_PWR (1 << 1)
+#define v_PLL_PWR_UP (0 << 1)
+#define v_PLL_PWR_DOWN (1 << 1)
+#define m_TMDS_CHG_PWR (1 << 0)
+#define v_TMDS_CHG_PWR_UP (0 << 0)
+#define v_TMDS_CHG_PWR_DOWN (1 << 0)
+
+#define PHY_CHG_PWR 0xe1
+#define v_CLK_CHG_PWR(n) ((n & 1) << 3)
+#define v_DATA_CHG_PWR(n) ((n & 7) << 0)
+
+#define PHY_DRIVER 0xe2
+#define v_CLK_MAIN_DRIVER(n) (n << 4)
+#define v_DATA_MAIN_DRIVER(n) (n << 0)
+
+#define PHY_PRE_EMPHASIS 0xe3
+#define v_PRE_EMPHASIS(n) ((n & 7) << 4)
+#define v_CLK_PRE_DRIVER(n) ((n & 3) << 2)
+#define v_DATA_PRE_DRIVER(n) ((n & 3) << 0)
+
+#define PHY_FEEDBACK_DIV_RATIO_LOW 0xe7
+#define v_FEEDBACK_DIV_LOW(n) (n & 0xff)
+#define PHY_FEEDBACK_DIV_RATIO_HIGH 0xe8
+#define v_FEEDBACK_DIV_HIGH(n) (n & 1)
+
+#define PHY_PRE_DIV_RATIO 0xed
+#define v_PRE_DIV_RATIO(n) (n & 0x1f)
+
+
+/*-----START----- HDMI CEC CTRL------START------*/
+#define CEC_CTRL 0xd0
+ #define m_ADJUST_FOR_HISENSE (1 << 6)
+ #define m_REJECT_RX_BROADCAST (1 << 5)
+ #define m_BUSFREETIME_ENABLE (1 << 2)
+ #define m_REJECT_RX (1 << 1)
+ #define m_START_TX (1 << 0)
+
+#define CEC_DATA 0xd1
+#define CEC_TX_OFFSET 0xd2
+#define CEC_RX_OFFSET 0xd3
+#define CEC_CLK_H 0xd4
+#define CEC_CLK_L 0xd5
+#define CEC_TX_LENGTH 0xd6
+#define CEC_RX_LENGTH 0xd7
+#define CEC_TX_INT_MASK 0xd8
+ #define m_TX_DONE (1 << 3)
+ #define m_TX_NOACK (1 << 2)
+ #define m_TX_BROADCAST_REJ (1 << 1)
+ #define m_TX_BUSNOTFREE (1 << 0)
+
+#define CEC_RX_INT_MASK 0xd9
+ #define m_RX_LA_ERR (1 << 4)
+ #define m_RX_GLITCH (1 << 3)
+ #define m_RX_DONE (1 << 0)
+
+#define CEC_TX_INT 0xda
+#define CEC_RX_INT 0xdb
+#define CEC_BUSFREETIME_L 0xdc
+#define CEC_BUSFREETIME_H 0xdd
+#define CEC_LOGICADDR 0xde
+/*------END------ HDMI CEC CTRL------END-------*/
+
+
+static inline int hdmi_readl(struct hdmi_dev *hdmi_dev,
+ u16 offset,
+ u32 *val)
+{
+ int ret = 0;
+
+ *val = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
+ return ret;
+}
+
+static inline int hdmi_writel(struct hdmi_dev *hdmi_dev,
+ u16 offset,
+ u32 val)
+{
+ int ret = 0;
+
+ writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
+ return ret;
+}
+
+static inline int hdmi_msk_reg(struct hdmi_dev *hdmi_dev,
+ u16 offset, u32 msk, u32 val)
+{
+ int ret = 0;
+ u32 temp;
+
+ temp = readl_relaxed(hdmi_dev->regbase +
+ (offset) * 0x04) & (0xFF - (msk));
+ writel_relaxed(temp | ((val) & (msk)),
+ hdmi_dev->regbase + (offset) * 0x04);
+ return ret;
+}
+static inline void rockchip_hdmiv1_reset_pclk(void)
+{
+ writel_relaxed(0x00010001, RK_CRU_VIRT + 0x128);
+ msleep(100);
+ writel_relaxed(0x00010000, RK_CRU_VIRT + 0x128);
+}
+
+
+
+void rockchip_hdmiv1_dev_init_ops(struct hdmi_ops *ops);
+int rockchip_hdmiv1_initial(struct hdmi *hdmi);
+void rockchip_hdmiv1_irq(struct hdmi *hdmi);
+void rockchip_hdmiv1_cec_init(struct hdmi *hdmi);
+void rockchip_hdmiv1_cec_isr(struct hdmi_dev *hdmi_dev);
+
+#endif
--- /dev/null
+config RK_HDMI_V2
+ bool "RockChip HDMI V2 support"
+ depends on RK_HDMI
+ default y
+ help
+ Rockchip hdmi version 2 which support hdmi 2.0.
+
--- /dev/null
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
+
+obj-$(CONFIG_RK_HDMI_V2) += rockchip_hdmiv2.o rockchip_hdmiv2_hw.o rockchip_hdmiv2_cec.o rockchip_hdmiv2_hdcp.o
--- /dev/null
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/mfd/syscon.h>
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
+
+#include "rockchip_hdmiv2.h"
+#include "rockchip_hdmiv2_hw.h"
+
+#define HDMI_SEL_LCDC(x) ((((x)&1)<<4)|(1<<20))
+#define grf_writel(v, offset) writel_relaxed(v, RK_GRF_VIRT + offset)
+
+static struct hdmi_dev *hdmi_dev;
+
+static struct hdmi_property rk_hdmi_property = {
+ .videosrc = DISPLAY_SOURCE_LCDC0,
+ .display = DISPLAY_MAIN,
+};
+
+#if defined(CONFIG_DEBUG_FS)
+static const struct rockchip_hdmiv2_reg_table hdmi_reg_table[] = {
+ {IDENTIFICATION_BASE, CONFIG3_ID},
+ {INTERRUPT_BASE, IH_MUTE},
+ {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
+ {VIDEO_PACKETIZER_BASE, VP_MASK},
+ {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
+ {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
+ {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
+ {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
+ {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
+ {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
+ {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
+ {HDCP_BKSV_BASE, HDCPREG_BKSV4},
+ {HDCP_AN_BASE, HDCPREG_AN7},
+ {HDCP2REG_BASE, HDCP2REG_MUTE},
+ {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
+ {CEC_ENGINE_BASE, CEC_WKUPCTRL},
+ {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
+};
+
+static int rockchip_hdmiv2_reg_show(struct seq_file *s, void *v)
+{
+ int i = 0, j = 0;
+ u32 val = 0;
+
+ seq_puts(s, "\n>>>hdmi_ctl reg ");
+ for (i = 0; i < 16; i++)
+ seq_printf(s, " %2x", i);
+ seq_puts(s, "\n-----------------------------------------------------------------");
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
+ for (j = hdmi_reg_table[i].reg_base;
+ j <= hdmi_reg_table[i].reg_end; j++) {
+ val = hdmi_readl(hdmi_dev, j);
+ if ((j - hdmi_reg_table[i].reg_base)%16 == 0)
+ seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
+ seq_printf(s, " %02x", val);
+ }
+ }
+ seq_puts(s, "\n-----------------------------------------------------------------\n");
+
+ /*rockchip_hdmiv2_dump_phy_regs(hdmi_dev);*/
+ return 0;
+}
+
+static ssize_t rockchip_hdmiv2_reg_write(struct file *file,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u32 reg;
+ u32 val;
+ char kbuf[25];
+
+ if (copy_from_user(kbuf, buf, count))
+ return -EFAULT;
+ if (sscanf(kbuf, "%x%x", ®, &val) == -1)
+ return -EFAULT;
+ if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
+ dev_info(hdmi_dev->hdmi->dev, "it is no hdmi reg\n");
+ return count;
+ }
+ dev_info(hdmi_dev->hdmi->dev,
+ "/**********hdmi reg config******/");
+ dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
+ hdmi_writel(hdmi_dev, reg, val);
+
+ return count;
+}
+
+static int rockchip_hdmiv2_reg_open(struct inode *inode, struct file *file)
+{
+ struct hdmi_dev *hdmi_dev = inode->i_private;
+
+ return single_open(file, rockchip_hdmiv2_reg_show, hdmi_dev);
+}
+
+static const struct file_operations rockchip_hdmiv2_reg_fops = {
+ .owner = THIS_MODULE,
+ .open = rockchip_hdmiv2_reg_open,
+ .read = seq_read,
+ .write = rockchip_hdmiv2_reg_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void rockchip_hdmiv2_early_suspend(struct early_suspend *h)
+{
+ struct hdmi *hdmi = hdmi_dev->hdmi;
+ struct delay_work *delay_work;
+ struct pinctrl_state *gpio_state;
+
+ HDMIDBG("hdmi enter early suspend\n");
+ delay_work = hdmi_submit_work(hdmi, HDMI_SUSPEND_CTL, 0, NULL);
+ if (delay_work)
+ flush_delayed_work_sync(delay_work);
+ /* iomux to gpio and pull down when suspend */
+ gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
+ pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
+ rockchip_hdmiv2_clk_disable(hdmi_dev);
+}
+
+static void rockchip_hdmiv2_early_resume(struct early_suspend *h)
+{
+ struct hdmi *hdmi = hdmi_dev->hdmi;
+
+ HDMIDBG("hdmi exit early resume\n");
+ /* iomux to default state for hdmi use when resume */
+ pinctrl_select_state(hdmi_dev->dev->pins->p,
+ hdmi_dev->dev->pins->default_state);
+ rockchip_hdmiv2_clk_enable(hdmi_dev);
+ hdmi_dev_initial(hdmi_dev);
+ if (hdmi->ops->hdcp_power_on_cb)
+ hdmi->ops->hdcp_power_on_cb();
+ hdmi_submit_work(hdmi, HDMI_RESUME_CTL, 0, NULL);
+}
+#endif
+
+#define HDMI_PD_ON (1 << 0)
+#define HDMI_PCLK_ON (1 << 1)
+#define HDMI_HDCPCLK_ON (1 << 2)
+#define HDMI_CECCLK_ON (1 << 3)
+
+static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
+{
+ if ((hdmi_dev->clk_on & HDMI_PD_ON) &&
+ (hdmi_dev->clk_on & HDMI_PCLK_ON) &&
+ (hdmi_dev->clk_on & HDMI_HDCPCLK_ON))
+ return 0;
+
+ if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0 &&
+ hdmi_dev->soctype == HDMI_SOC_RK3288) {
+ if (hdmi_dev->pd == NULL) {
+ hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
+ if (IS_ERR(hdmi_dev->pd)) {
+ dev_err(hdmi_dev->dev,
+ "Unable to get hdmi pd\n");
+ return -1;
+ }
+ }
+ clk_prepare_enable(hdmi_dev->pd);
+ hdmi_dev->clk_on |= HDMI_PD_ON;
+ }
+
+ if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
+ if (hdmi_dev->pclk == NULL) {
+ hdmi_dev->pclk =
+ devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
+ if (IS_ERR(hdmi_dev->pclk)) {
+ dev_err(hdmi_dev->dev,
+ "Unable to get hdmi pclk\n");
+ return -1;
+ }
+ }
+ clk_prepare_enable(hdmi_dev->pclk);
+ hdmi_dev->clk_on |= HDMI_PCLK_ON;
+ }
+
+ if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
+ if (hdmi_dev->hdcp_clk == NULL) {
+ hdmi_dev->hdcp_clk =
+ devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
+ if (IS_ERR(hdmi_dev->hdcp_clk)) {
+ dev_err(hdmi_dev->dev,
+ "Unable to get hdmi hdcp_clk\n");
+ return -1;
+ }
+ }
+ clk_prepare_enable(hdmi_dev->hdcp_clk);
+ hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
+ }
+
+ if ((rk_hdmi_property.feature & SUPPORT_CEC) &&
+ (hdmi_dev->clk_on & HDMI_CECCLK_ON) == 0) {
+ if (hdmi_dev->cec_clk == NULL) {
+ hdmi_dev->cec_clk =
+ devm_clk_get(hdmi_dev->dev, "cec_clk_hdmi");
+ if (IS_ERR(hdmi_dev->cec_clk)) {
+ dev_err(hdmi_dev->dev,
+ "Unable to get hdmi cec_clk\n");
+ return -1;
+ }
+ }
+ clk_prepare_enable(hdmi_dev->cec_clk);
+ hdmi_dev->clk_on |= HDMI_CECCLK_ON;
+ }
+ return 0;
+}
+
+static int rockchip_hdmiv2_clk_disable(struct hdmi_dev *hdmi_dev)
+{
+ if (hdmi_dev->clk_on == 0)
+ return 0;
+
+ if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->pd != NULL)) {
+ clk_disable_unprepare(hdmi_dev->pd);
+ hdmi_dev->clk_on &= ~HDMI_PD_ON;
+ }
+
+ if ((hdmi_dev->clk_on & HDMI_PCLK_ON) &&
+ (hdmi_dev->pclk != NULL)) {
+ clk_disable_unprepare(hdmi_dev->pclk);
+ hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
+ }
+
+ if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) &&
+ (hdmi_dev->hdcp_clk != NULL)) {
+ clk_disable_unprepare(hdmi_dev->hdcp_clk);
+ hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
+ }
+
+ return 0;
+}
+
+static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_event *event = data;
+ int blank_mode = *((int *)event->data);
+ struct hdmi *hdmi = hdmi_dev->hdmi;
+ struct delayed_work *delay_work;
+
+ if (action == FB_EARLY_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ break;
+ default:
+ HDMIDBG("suspend hdmi\n");
+ if (!hdmi->sleep) {
+ delay_work =
+ hdmi_submit_work(hdmi,
+ HDMI_SUSPEND_CTL,
+ 0, NULL);
+ if (delay_work)
+ flush_delayed_work(delay_work);
+ rockchip_hdmiv2_clk_disable(hdmi_dev);
+ }
+ break;
+ }
+ } else if (action == FB_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ HDMIDBG("resume hdmi\n");
+ if (hdmi->sleep) {
+ rockchip_hdmiv2_clk_enable(hdmi_dev);
+ rockchip_hdmiv2_dev_initial(hdmi_dev);
+ if (hdmi->ops->hdcp_power_on_cb)
+ hdmi->ops->hdcp_power_on_cb();
+ hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
+ 0, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block rockchip_hdmiv2_fb_notifier = {
+ .notifier_call = rockchip_hdmiv2_fb_event_notify,
+};
+#ifdef HDMI_INT_USE_POLL
+static void rockchip_hdmiv2_irq_work_func(struct work_struct *work)
+{
+ if (hdmi_dev->enable) {
+ rockchip_hdmiv2_dev_irq(0, hdmi_dev);
+ queue_delayed_work(hdmi_dev->workqueue,
+ &(hdmi_dev->delay_work),
+ msecs_to_jiffies(50));
+ }
+}
+#endif
+
+static struct hdmi_ops rk_hdmi_ops;
+
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk_hdmi_dt_ids[] = {
+ {.compatible = "rockchip,rk3288-hdmi",},
+ {.compatible = "rockchip,rk3368-hdmi",},
+ {}
+};
+
+static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
+{
+ int val = 0;
+ struct device_node *np = hdmi_dev->dev->of_node;
+ const struct of_device_id *match;
+
+ match = of_match_node(rk_hdmi_dt_ids, np);
+ if (!match)
+ return PTR_ERR(match);
+
+ if (!strcmp(match->compatible, "rockchip,rk3288-hdmi")) {
+ hdmi_dev->soctype = HDMI_SOC_RK3288;
+ } else if (!strcmp(match->compatible, "rockchip,rk3368-hdmi")) {
+ hdmi_dev->soctype = HDMI_SOC_RK3368;
+ } else {
+ pr_err("It is not a valid rockchip soc!");
+ return -ENOMEM;
+ }
+
+ if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
+ rk_hdmi_property.videosrc = val;
+
+ if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
+ hdmi_dev->audiosrc = val;
+
+ if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
+ (val == 1)) {
+ pr_info("hdmi support cec\n");
+ rk_hdmi_property.feature |= SUPPORT_CEC;
+ }
+ if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
+ (val == 1)) {
+ pr_info("hdmi support hdcp\n");
+ rk_hdmi_property.feature |= SUPPORT_HDCP;
+ }
+ #ifdef CONFIG_MFD_SYSCON
+ hdmi_dev->grf_base =
+ syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+ #endif
+ return 0;
+}
+#endif
+
+static int rockchip_hdmiv2_probe(struct platform_device *pdev)
+{
+ int ret = -1;
+ struct resource *res;
+
+ HDMIDBG("%s\n", __func__);
+ hdmi_dev = kmalloc(sizeof(*hdmi_dev), GFP_KERNEL);
+ if (!hdmi_dev) {
+ dev_err(&pdev->dev, ">>rockchip hdmiv2 kmalloc fail!");
+ return -ENOMEM;
+ }
+ memset(hdmi_dev, 0, sizeof(struct hdmi_dev));
+ platform_set_drvdata(pdev, hdmi_dev);
+ hdmi_dev->dev = &pdev->dev;
+
+ rockchip_hdmiv2_parse_dt(hdmi_dev);
+
+ /*request and remap iomem*/
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get register resource\n");
+ ret = -ENXIO;
+ goto failed;
+ }
+ hdmi_dev->regbase_phy = res->start;
+ hdmi_dev->regsize_phy = resource_size(res);
+ hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hdmi_dev->regbase)) {
+ ret = PTR_ERR(hdmi_dev->regbase);
+ dev_err(&pdev->dev,
+ "cannot ioremap registers,err=%d\n", ret);
+ goto failed;
+ }
+
+ /*enable pd and pclk and hdcp_clk*/
+ if (rockchip_hdmiv2_clk_enable(hdmi_dev) < 0) {
+ ret = -ENXIO;
+ goto failed1;
+ }
+ /*lcdc source select*/
+ if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
+ grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc),
+ RK3288_GRF_SOC_CON6);
+ /* select GPIO7_C0 as cec pin */
+ grf_writel(((1 << 12) | (1 << 28)), RK3288_GRF_SOC_CON8);
+ }
+ rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
+ /* Register HDMI device */
+ rk_hdmi_property.name = (char *)pdev->name;
+ rk_hdmi_property.priv = hdmi_dev;
+ if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
+ /*rk_hdmi_property.feature |= SUPPORT_DEEP_10BIT;*/
+ if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
+ rk_hdmi_property.feature |=
+ SUPPORT_4K |
+ SUPPORT_TMDS_600M;
+ } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
+ rk_hdmi_property.feature |=
+ SUPPORT_4K |
+ SUPPORT_4K_4096 |
+ SUPPORT_YUV420;
+ }
+ hdmi_dev->hdmi =
+ rockchip_hdmi_register(&rk_hdmi_property, &rk_hdmi_ops);
+ if (hdmi_dev->hdmi == NULL) {
+ dev_err(&pdev->dev, "register hdmi device failed\n");
+ ret = -ENOMEM;
+ goto failed1;
+ }
+ mutex_init(&hdmi_dev->ddc_lock);
+ hdmi_dev->hdmi->dev = &pdev->dev;
+ hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
+ fb_register_client(&rockchip_hdmiv2_fb_notifier);
+ rockchip_hdmiv2_dev_initial(hdmi_dev);
+ pinctrl_select_state(hdmi_dev->dev->pins->p,
+ hdmi_dev->dev->pins->default_state);
+#if defined(CONFIG_DEBUG_FS)
+ hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv2", NULL);
+ if (IS_ERR(hdmi_dev->debugfs_dir))
+ dev_err(hdmi_dev->hdmi->dev,
+ "failed to create debugfs dir for rockchip hdmiv2!\n");
+ else
+ debugfs_create_file("hdmi", S_IRUSR,
+ hdmi_dev->debugfs_dir,
+ hdmi_dev, &rockchip_hdmiv2_reg_fops);
+#endif
+ rk_display_device_enable(hdmi_dev->hdmi->ddev);
+
+#ifndef HDMI_INT_USE_POLL
+ /* get and request the IRQ */
+ hdmi_dev->irq = platform_get_irq(pdev, 0);
+ if (hdmi_dev->irq <= 0) {
+ dev_err(hdmi_dev->dev,
+ "failed to get hdmi irq resource (%d).\n",
+ hdmi_dev->irq);
+ ret = -ENXIO;
+ goto failed1;
+ }
+
+ ret =
+ devm_request_irq(hdmi_dev->dev, hdmi_dev->irq,
+ rockchip_hdmiv2_dev_irq,
+ IRQF_TRIGGER_HIGH,
+ dev_name(hdmi_dev->dev), hdmi_dev);
+ if (ret) {
+ dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
+ goto failed1;
+ }
+#else
+ hdmi_dev->workqueue =
+ create_singlethread_workqueue("rockchip hdmiv2 irq");
+ INIT_DELAYED_WORK(&(hdmi_dev->delay_work),
+ rockchip_hdmiv2_irq_work_func);
+ rockchip_hdmiv2_irq_work_func(NULL);
+
+#endif
+ dev_info(&pdev->dev, "rockchip hdmiv2 probe sucess.\n");
+ return 0;
+
+failed1:
+ rockchip_hdmi_unregister(hdmi_dev->hdmi);
+failed:
+ kfree(hdmi_dev);
+ hdmi_dev = NULL;
+ dev_err(&pdev->dev, "rk3288 hdmi probe error.\n");
+ return ret;
+}
+
+static int rockchip_hdmiv2_remove(struct platform_device *pdev)
+{
+ dev_info(&pdev->dev, "rk3288 hdmi driver removed.\n");
+ return 0;
+}
+
+static void rockchip_hdmiv2_shutdown(struct platform_device *pdev)
+{
+ struct hdmi *hdmi;
+
+ if (hdmi_dev) {
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&hdmi_dev->early_suspend);
+ #endif
+ hdmi = hdmi_dev->hdmi;
+ if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
+ hdmi->ops->setmute)
+ hdmi->ops->setmute(hdmi, HDMI_VIDEO_MUTE);
+ }
+}
+
+static struct platform_driver rockchip_hdmiv2_driver = {
+ .probe = rockchip_hdmiv2_probe,
+ .remove = rockchip_hdmiv2_remove,
+ .driver = {
+ .name = "rockchip-hdmiv2",
+ .owner = THIS_MODULE,
+ #if defined(CONFIG_OF)
+ .of_match_table = of_match_ptr(rk_hdmi_dt_ids),
+ #endif
+ },
+ .shutdown = rockchip_hdmiv2_shutdown,
+};
+
+static int __init rockchip_hdmiv2_init(void)
+{
+ return platform_driver_register(&rockchip_hdmiv2_driver);
+}
+
+static void __exit rockchip_hdmiv2_exit(void)
+{
+ platform_driver_unregister(&rockchip_hdmiv2_driver);
+}
+
+module_init(rockchip_hdmiv2_init);
+module_exit(rockchip_hdmiv2_exit);
--- /dev/null
+#ifndef __RK32_HDMI_H__
+#define __RK32_HDMI_H__
+#include <linux/regmap.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "../rockchip-hdmi.h"
+
+#ifdef DEBUG
+#define HDMIDBG(format, ...) \
+ pr_info(format, ## __VA_ARGS__)
+#else
+#define HDMIDBG(format, ...)
+#endif
+
+struct hdmi_dev {
+ void __iomem *regbase;
+ int regbase_phy;
+ int regsize_phy;
+ struct regmap *grf_base;
+
+ struct clk *pd;
+ struct clk *pclk;
+ struct clk *hdcp_clk;
+ struct clk *cec_clk;
+ struct hdmi *hdmi;
+ struct device *dev;
+ struct dentry *debugfs_dir;
+ int irq;
+
+ struct work_struct irq_work;
+ struct delayed_work delay_work;
+ struct workqueue_struct *workqueue;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int soctype;
+ int audiosrc;
+ int enable;
+ unsigned char clk_disable;
+ unsigned char clk_on;
+
+ unsigned long pixelclk;
+ unsigned int tmdsclk;
+ unsigned int pixelrepeat;
+ unsigned char colordepth;
+
+ bool tmdsclk_ratio_change;
+ struct mutex ddc_lock; /*mutex for ddc operation */
+};
+#endif /*__RK32_HDMI_H__*/
--- /dev/null
+#include <linux/delay.h>
+#include "../rockchip-hdmi-cec.h"
+#include "rockchip_hdmiv2.h"
+#include "rockchip_hdmiv2_hw.h"
+
+/* static wait_queue_head_t wait;*/
+static int init = 1;
+void rockchip_hdmiv2_cec_isr(struct hdmi_dev *hdmi_dev, char cec_int)
+{
+ CECDBG("%s cec 0x%x\n", __func__, cec_int);
+ if (cec_int & m_EOM)
+ rockchip_hdmi_cec_submit_work(EVENT_RX_FRAME, 0, NULL);
+ if (cec_int & m_DONE)
+ CECDBG("send frame success\n");
+}
+
+static int rockchip_hdmiv2_cec_readframe(struct hdmi *hdmi,
+ struct cec_framedata *frame)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ int i, count;
+ char *data = (char *)frame;
+
+ if (frame == NULL)
+ return -1;
+ count = hdmi_readl(hdmi_dev, CEC_RX_CNT);
+ CECDBG("%s count %d\n", __func__, count);
+ for (i = 0; i < count; i++) {
+ data[i] = hdmi_readl(hdmi_dev, CEC_RX_DATA0 + i);
+ CECDBG("%02x\n", data[i]);
+ }
+ hdmi_writel(hdmi_dev, CEC_LOCK, 0x0);
+ return 0;
+}
+
+
+void rockchip_hdmiv2_cec_setcecla(struct hdmi *hdmi, int ceclgaddr)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ short val;
+
+ if (ceclgaddr < 0 || ceclgaddr > 16)
+ return;
+ val = 1 << ceclgaddr;
+ hdmi_writel(hdmi_dev, CEC_ADDR_L, val & 0xff);
+ hdmi_writel(hdmi_dev, CEC_ADDR_H, val>>8);
+}
+
+static int rockchip_hdmiv2_cec_sendframe(struct hdmi *hdmi,
+ struct cec_framedata *frame)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ int i, interrupt;
+
+ CECDBG("TX srcdestaddr %02x opcode %02x ",
+ frame->srcdestaddr, frame->opcode);
+ if (frame->argcount) {
+ CECDBG("args:");
+ for (i = 0; i < frame->argcount; i++)
+ CECDBG("%02x ", frame->args[i]);
+ }
+ CECDBG("\n");
+ if ((frame->srcdestaddr & 0x0f) == ((frame->srcdestaddr >> 4) & 0x0f)) {
+ /*it is a ping command*/
+ hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
+ hdmi_writel(hdmi_dev, CEC_TX_CNT, 1);
+ } else {
+ hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
+ hdmi_writel(hdmi_dev, CEC_TX_DATA0 + 1, frame->opcode);
+ for (i = 0; i < frame->argcount; i++)
+ hdmi_writel(hdmi_dev,
+ CEC_TX_DATA0 + 2 + i, frame->args[i]);
+ hdmi_writel(hdmi_dev, CEC_TX_CNT, frame->argcount + 2);
+ }
+ /*Start TX*/
+ hdmi_msk_reg(hdmi_dev, CEC_CTRL, m_CEC_SEND, v_CEC_SEND(1));
+ i = 20;
+ while (i--) {
+ usleep_range(900, 1000);
+ interrupt = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
+ if (interrupt & (m_ERR_INITIATOR | m_ARB_LOST |
+ m_NACK | m_DONE)) {
+ hdmi_writel(hdmi_dev, IH_CEC_STAT0,
+ interrupt & (m_ERR_INITIATOR |
+ m_ARB_LOST | m_NACK | m_DONE));
+ break;
+ }
+ }
+ CECDBG("%s interrupt 0x%02x\n", __func__, interrupt);
+ if (interrupt & m_DONE)
+ return 0;
+ else if (interrupt & m_NACK)
+ return 1;
+ else
+ return -1;
+}
+
+void rockchip_hdmiv2_cec_init(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ if (init) {
+ rockchip_hdmi_cec_init(hdmi,
+ rockchip_hdmiv2_cec_sendframe,
+ rockchip_hdmiv2_cec_readframe,
+ rockchip_hdmiv2_cec_setcecla);
+ init = 0;
+ /* init_waitqueue_head(&wait); */
+ }
+ hdmi_writel(hdmi_dev, IH_MUTE_CEC_STAT0, m_ERR_INITIATOR |
+ m_ARB_LOST | m_NACK | m_DONE);
+ CECDBG("%s", __func__);
+}
--- /dev/null
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include "rockchip_hdmiv2.h"
+#include "rockchip_hdmiv2_hw.h"
+
+#define HDCP_KEY_SIZE 308
+#define HDCP_PRIVATE_KEY_SIZE 280
+#define HDCP_KEY_SHA_SIZE 20
+#define HDCP_KEY_SEED_SIZE 2
+
+struct hdcp_keys {
+ u8 KSV[8];
+ u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
+ u8 sha1[HDCP_KEY_SHA_SIZE];
+};
+
+struct hdcp {
+ struct hdmi *hdmi;
+ int enable;
+ int retry_times;
+ struct hdcp_keys *keys;
+ char *seeds;
+ int invalidkey;
+ char *invalidkeys;
+};
+
+static struct miscdevice mdev;
+static struct hdcp *hdcp = NULL;
+
+static void hdcp_load_key(struct hdmi *hdmi, struct hdcp_keys *key)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ int i, value;
+
+ /* Disable decryption logic */
+ hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
+ /* Poll untile DPK write is allowed */
+ do {
+ value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
+ } while ((value & m_DPK_WR_OK_STS) == 0);
+
+ /* write unencryped AKSV */
+ hdmi_writel(hdmi_dev, HDCPREG_DPK6, 0);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK5, 0);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK4, key->KSV[4]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK3, key->KSV[3]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK2, key->KSV[2]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK1, key->KSV[1]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK0, key->KSV[0]);
+ /* Poll untile DPK write is allowed */
+ do {
+ value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
+ } while ((value & m_DPK_WR_OK_STS) == 0);
+
+ if (hdcp->seeds != NULL) {
+ hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 1);
+ hdmi_writel(hdmi_dev, HDCPREG_SEED1, hdcp->seeds[0]);
+ hdmi_writel(hdmi_dev, HDCPREG_SEED0, hdcp->seeds[1]);
+ } else {
+ hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
+ }
+
+ /* write private key */
+ for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i += 7) {
+ hdmi_writel(hdmi_dev, HDCPREG_DPK6, key->devicekey[i + 6]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK5, key->devicekey[i + 5]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK4, key->devicekey[i + 4]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK3, key->devicekey[i + 3]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK2, key->devicekey[i + 2]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK1, key->devicekey[i + 1]);
+ hdmi_writel(hdmi_dev, HDCPREG_DPK0, key->devicekey[i]);
+
+ do {
+ value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
+ } while ((value & m_DPK_WR_OK_STS) == 0);
+ }
+
+ pr_info("%s success\n", __func__);
+}
+
+static void hdcp_load_keys_cb(const struct firmware *fw,
+ void *context)
+{
+ struct hdmi *hdmi = (struct hdmi *)context;
+
+ if (fw->size < HDCP_KEY_SIZE) {
+ pr_err("HDCP: firmware wrong size %d\n", (int)fw->size);
+ return;
+ }
+ hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
+ memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
+
+ if (fw->size > HDCP_KEY_SIZE) {
+ if ((fw->size - HDCP_KEY_SIZE) < HDCP_KEY_SEED_SIZE) {
+ pr_err("HDCP: invalid seed key size\n");
+ return;
+ }
+ hdcp->seeds = kmalloc(HDCP_KEY_SEED_SIZE, GFP_KERNEL);
+ if (hdcp->seeds == NULL) {
+ pr_err("HDCP: can't allocated space for seed keys\n");
+ return;
+ }
+ memcpy(hdcp->seeds, fw->data + HDCP_KEY_SIZE,
+ HDCP_KEY_SEED_SIZE);
+ }
+ hdcp_load_key(hdmi, hdcp->keys);
+}
+
+static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ if (!hdcp->enable)
+ return;
+ if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
+ hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
+ m_HDCP2_OVR_EN | m_HDCP2_FORCE,
+ v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
+ hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
+ hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
+ }
+
+ hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
+ m_FC_HDCP_KEEPOUT, v_FC_HDCP_KEEPOUT(1));
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG0,
+ m_HDMI_DVI, v_HDMI_DVI(hdmi->edid.sink_hdmi));
+ hdmi_writel(hdmi_dev, A_OESSWCFG, 0x40);
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG0,
+ m_ENCRYPT_BYPASS | m_FEATURE11_EN | m_SYNC_RI_CHECK,
+ v_ENCRYPT_BYPASS(0) | v_FEATURE11_EN(0) |
+ v_SYNC_RI_CHECK(1));
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG1,
+ m_ENCRYPT_DISBALE | m_PH2UPSHFTENC,
+ v_ENCRYPT_DISBALE(0) | v_PH2UPSHFTENC(1));
+ /* Reset HDCP Engine */
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG1,
+ m_HDCP_SW_RST, v_HDCP_SW_RST(0));
+
+ hdmi_writel(hdmi_dev, A_APIINTMSK, 0x00);
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
+
+ hdmi_msk_reg(hdmi_dev, MC_CLKDIS,
+ m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(0));
+ pr_info("%s success\n", __func__);
+}
+
+static void rockchip_hdmiv2_hdcp_stop(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ if (!hdcp->enable)
+ return;
+
+ hdmi_msk_reg(hdmi_dev, MC_CLKDIS,
+ m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(1));
+ hdmi_writel(hdmi_dev, A_APIINTMSK, 0xff);
+ hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(0));
+}
+
+static ssize_t hdcp_enable_read(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ int enable = 0;
+
+ if (hdcp)
+ enable = hdcp->enable;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t hdcp_enable_write(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int enable;
+
+ if (hdcp == NULL)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &enable))
+ return -EINVAL;
+
+ if (hdcp->enable != enable) {
+ if (!hdcp->enable)
+ hdmi_submit_work(hdcp->hdmi, HDMI_ENABLE_HDCP, 0, NULL);
+ else
+ rockchip_hdmiv2_hdcp_stop(hdcp->hdmi);
+ hdcp->enable = enable;
+ }
+
+ return count;
+}
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
+ hdcp_enable_read, hdcp_enable_write);
+
+static ssize_t hdcp_trytimes_read(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ int trytimes = 0;
+
+ if (hdcp)
+ trytimes = hdcp->retry_times;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
+}
+
+static ssize_t hdcp_trytimes_wrtie(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int trytimes;
+
+ if (hdcp == NULL)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &trytimes))
+ return -EINVAL;
+
+ if (hdcp->retry_times != trytimes)
+ hdcp->retry_times = trytimes;
+
+ return count;
+}
+static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
+ hdcp_trytimes_read, hdcp_trytimes_wrtie);
+
+static int hdcp_init(struct hdmi *hdmi)
+{
+ int ret;
+
+ mdev.minor = MISC_DYNAMIC_MINOR;
+ mdev.name = "hdcp";
+ mdev.mode = 0666;
+ hdcp = kmalloc(sizeof(*hdcp), GFP_KERNEL);
+ if (!hdcp) {
+ pr_err("HDCP: kmalloc fail!\n");
+ ret = -ENOMEM;
+ goto error0;
+ }
+ memset(hdcp, 0, sizeof(struct hdcp));
+ hdcp->hdmi = hdmi;
+ if (misc_register(&mdev)) {
+ pr_err("HDCP: Could not add character driver\n");
+ ret = HDMI_ERROR_FALSE;
+ goto error1;
+ }
+ ret = device_create_file(mdev.this_device, &dev_attr_enable);
+ if (ret) {
+ pr_err("HDCP: Could not add sys file enable\n");
+ ret = -EINVAL;
+ goto error2;
+ }
+ ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
+ if (ret) {
+ pr_err("HDCP: Could not add sys file enable\n");
+ ret = -EINVAL;
+ goto error3;
+ }
+
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "hdcp", mdev.this_device, GFP_KERNEL,
+ hdmi, hdcp_load_keys_cb);
+
+ if (ret < 0) {
+ pr_err("HDCP: request_firmware_nowait failed: %d\n", ret);
+ goto error4;
+ }
+
+ hdmi->ops->hdcp_cb = rockchip_hdmiv2_hdcp_start;
+ return 0;
+
+error4:
+ device_remove_file(mdev.this_device, &dev_attr_trytimes);
+error3:
+ device_remove_file(mdev.this_device, &dev_attr_enable);
+error2:
+ misc_deregister(&mdev);
+error1:
+ kfree(hdcp->keys);
+ kfree(hdcp->invalidkeys);
+ kfree(hdcp);
+error0:
+ return ret;
+}
+
+void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi)
+{
+ pr_info("%s", __func__);
+ if (hdcp == NULL)
+ hdcp_init(hdmi);
+ else
+ hdcp_load_key(hdmi, hdcp->keys);
+}
+
--- /dev/null
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include "rockchip_hdmiv2.h"
+#include "rockchip_hdmiv2_hw.h"
+
+static const struct phy_mpll_config_tab PHY_MPLL_TABLE[] = {
+ /*tmdsclk = (pixclk / ref_cntrl ) * (fbdiv2 * fbdiv1) / nctrl / tmdsmhl
+ opmode: 0:HDMI1.4 1:HDMI2.0
+ */
+/* |pixclock| tmdsclock|pixrepet|colordepth|prepdiv|tmdsmhl|opmode|
+ fbdiv2|fbdiv1|ref_cntrl|nctrl|propctrl|intctrl|gmpctrl| */
+ {27000000, 27000000, 0, 8, 0, 0, 0,
+ 2, 3, 0, 3, 3, 0, 0},
+ {27000000, 33750000, 0, 10, 1, 0, 0,
+ 5, 1, 0, 3, 3, 0, 0},
+ {27000000, 40500000, 0, 12, 2, 0, 0,
+ 3, 3, 0, 3, 3, 0, 0},
+ {27000000, 54000000, 0, 16, 3, 0, 0,
+ 2, 3, 0, 2, 5, 0, 1},
+/* {74250000, 74250000, 0, 8, 0, 0, 0,
+ 1, 3, 0, 2, 5, 0, 1}, */
+ {74250000, 74250000, 0, 8, 0, 0, 0,
+ 4, 3, 3, 2, 7, 0, 3},
+ {74250000, 92812500, 0, 10, 1, 0, 0,
+ 5, 0, 1, 1, 7, 0, 2},
+ {74250000, 111375000, 0, 12, 2, 0, 0,
+ 1, 2, 0, 1, 7, 0, 2},
+ {74250000, 148500000, 0, 16, 3, 0, 0,
+ 1, 3, 0, 1, 7, 0, 2},
+ {148500000, 74250000, 0, 8, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0, 3},
+ {148500000, 148500000, 0, 8, 0, 0, 0,
+ 1, 1, 0, 1, 0, 0, 3},
+ {148500000, 185625000, 0, 10, 1, 0, 0,
+ 5, 0, 3, 0, 7, 0, 3},
+ {148500000, 222750000, 0, 12, 2, 0, 0,
+ 1, 2, 1, 0, 7, 0, 3},
+ {148500000, 297000000, 0, 16, 3, 0, 0,
+ 1, 1, 0, 0, 7, 0, 3},
+ {297000000, 148500000, 0, 8, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0, 3},
+ {297000000, 297000000, 0, 8, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 3},
+ {297000000, 371250000, 0, 10, 1, 3, 1,
+ 5, 0, 3, 0, 7, 0, 3},
+ {297000000, 445500000, 0, 12, 2, 3, 1,
+ 1, 2, 2, 0, 7, 0, 3},
+ {297000000, 594000000, 0, 16, 1, 3, 1,
+ 1, 3, 1, 0, 0, 0, 3},
+/* {594000000, 297000000, 0, 8, 0, 0, 0,
+ 1, 3, 3, 1, 0, 0, 3},*/
+ {594000000, 297000000, 0, 8, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0, 3},
+ {594000000, 594000000, 0, 8, 0, 3, 1,
+ 1, 3, 3, 0, 0, 0, 3},
+};
+/* ddc i2c master reset */
+static void rockchip_hdmiv2_i2cm_reset(struct hdmi_dev *hdmi_dev)
+{
+ hdmi_msk_reg(hdmi_dev, I2CM_SOFTRSTZ,
+ m_I2CM_SOFTRST, v_I2CM_SOFTRST(0));
+ usleep_range(90, 100);
+}
+
+/*set read/write offset,set read/write mode*/
+static void rockchip_hdmiv2_i2cm_write_request(struct hdmi_dev *hdmi_dev,
+ u8 offset, u8 data)
+{
+ hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset);
+ hdmi_writel(hdmi_dev, I2CM_DATAO, data);
+ hdmi_msk_reg(hdmi_dev, I2CM_OPERATION, m_I2CM_WR, v_I2CM_WR(1));
+}
+
+static void rockchip_hdmiv2_i2cm_read_request(struct hdmi_dev *hdmi_dev,
+ u8 offset)
+{
+ hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset);
+ hdmi_msk_reg(hdmi_dev, I2CM_OPERATION, m_I2CM_RD, v_I2CM_RD(1));
+}
+
+static void rockchip_hdmiv2_i2cm_write_data(struct hdmi_dev *hdmi_dev,
+ u8 data, u8 offset)
+{
+ u8 interrupt;
+ int trytime = 2;
+ int i = 20;
+
+ while (trytime-- > 0) {
+ rockchip_hdmiv2_i2cm_write_request(hdmi_dev, offset, data);
+ while (i--) {
+ usleep_range(900, 1000);
+ interrupt = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
+ if (interrupt)
+ hdmi_writel(hdmi_dev,
+ IH_I2CM_STAT0, interrupt);
+
+ if (interrupt & (m_SCDC_READREQ |
+ m_I2CM_DONE | m_I2CM_ERROR))
+ break;
+ }
+
+ if (interrupt & m_I2CM_DONE) {
+ dev_dbg(hdmi_dev->hdmi->dev,
+ "[%s] write offset %02x data %02x success\n",
+ __func__, offset, data);
+ trytime = 0;
+ } else if ((interrupt & m_I2CM_ERROR) || (i == -1)) {
+ dev_err(hdmi_dev->hdmi->dev,
+ "[%s] write data error\n", __func__);
+ rockchip_hdmiv2_i2cm_reset(hdmi_dev);
+ }
+ }
+}
+
+static int rockchip_hdmiv2_i2cm_read_data(struct hdmi_dev *hdmi_dev, u8 offset)
+{
+ u8 interrupt, val;
+ int trytime = 2;
+ int i = 20;
+
+ while (trytime-- > 0) {
+ rockchip_hdmiv2_i2cm_read_request(hdmi_dev, offset);
+ while (i--) {
+ usleep_range(900, 1000);
+ interrupt = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
+ if (interrupt)
+ hdmi_writel(hdmi_dev, IH_I2CM_STAT0, interrupt);
+
+ if (interrupt & (m_SCDC_READREQ |
+ m_I2CM_DONE | m_I2CM_ERROR))
+ break;
+ }
+
+ if (interrupt & m_I2CM_DONE) {
+ val = hdmi_readl(hdmi_dev, I2CM_DATAI);
+ trytime = 0;
+ } else if ((interrupt & m_I2CM_ERROR) || (i == -1)) {
+ pr_err("[%s] read data error\n", __func__);
+ rockchip_hdmiv2_i2cm_reset(hdmi_dev);
+ }
+ }
+ return val;
+}
+
+static void rockchip_hdmiv2_i2cm_mask_int(struct hdmi_dev *hdmi_dev, int mask)
+{
+ if (0 == mask) {
+ hdmi_msk_reg(hdmi_dev, I2CM_INT,
+ m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(0));
+ hdmi_msk_reg(hdmi_dev, I2CM_CTLINT,
+ m_I2CM_NACK_MASK | m_I2CM_ARB_MASK,
+ v_I2CM_NACK_MASK(0) | v_I2CM_ARB_MASK(0));
+ } else {
+ hdmi_msk_reg(hdmi_dev, I2CM_INT,
+ m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(1));
+ hdmi_msk_reg(hdmi_dev, I2CM_CTLINT,
+ m_I2CM_NACK_MASK | m_I2CM_ARB_MASK,
+ v_I2CM_NACK_MASK(1) | v_I2CM_ARB_MASK(1));
+ }
+}
+
+#define I2C_DIV_FACTOR 100000
+static u16 i2c_count(u16 sfrclock, u16 sclmintime)
+{
+ unsigned long tmp_scl_period = 0;
+
+ if (((sfrclock * sclmintime) % I2C_DIV_FACTOR) != 0)
+ tmp_scl_period = (unsigned long)((sfrclock * sclmintime) +
+ (I2C_DIV_FACTOR - ((sfrclock * sclmintime) %
+ I2C_DIV_FACTOR))) / I2C_DIV_FACTOR;
+ else
+ tmp_scl_period = (unsigned long)(sfrclock * sclmintime) /
+ I2C_DIV_FACTOR;
+
+ return (u16)(tmp_scl_period);
+}
+
+#define EDID_I2C_MIN_SS_SCL_HIGH_TIME 50000
+#define EDID_I2C_MIN_SS_SCL_LOW_TIME 50000
+
+static void rockchip_hdmiv2_i2cm_clk_init(struct hdmi_dev *hdmi_dev)
+{
+ /* Set DDC I2C CLK which devided from DDC_CLK. */
+ hdmi_writel(hdmi_dev, I2CM_SS_SCL_HCNT_0_ADDR,
+ i2c_count(24000, EDID_I2C_MIN_SS_SCL_HIGH_TIME));
+ hdmi_writel(hdmi_dev, I2CM_SS_SCL_LCNT_0_ADDR,
+ i2c_count(24000, EDID_I2C_MIN_SS_SCL_LOW_TIME));
+ hdmi_msk_reg(hdmi_dev, I2CM_DIV, m_I2CM_FAST_STD_MODE,
+ v_I2CM_FAST_STD_MODE(STANDARD_MODE));
+}
+
+static int rockchip_hdmiv2_scdc_get_sink_version(struct hdmi_dev *hdmi_dev)
+{
+ return rockchip_hdmiv2_i2cm_read_data(hdmi_dev, SCDC_SINK_VER);
+}
+
+static void rockchip_hdmiv2_scdc_set_source_version(struct hdmi_dev *hdmi_dev,
+ u8 version)
+{
+ rockchip_hdmiv2_i2cm_write_data(hdmi_dev, version, SCDC_SOURCE_VER);
+}
+
+
+static void rockchip_hdmiv2_scdc_read_request(struct hdmi_dev *hdmi_dev,
+ int enable)
+{
+ hdmi_msk_reg(hdmi_dev, I2CM_SCDC_READ_UPDATE,
+ m_I2CM_READ_REQ_EN, v_I2CM_READ_REQ_EN(enable));
+ rockchip_hdmiv2_i2cm_write_data(hdmi_dev, enable, SCDC_CONFIG_0);
+}
+
+#ifdef HDMI_20_SCDC
+static void rockchip_hdmiv2_scdc_update_read(struct hdmi_dev *hdmi_dev)
+{
+ hdmi_msk_reg(hdmi_dev, I2CM_SCDC_READ_UPDATE,
+ m_I2CM_READ_UPDATE, v_I2CM_READ_UPDATE(1));
+}
+
+
+static int rockchip_hdmiv2_scdc_get_scambling_status(struct hdmi_dev *hdmi_dev)
+{
+ int val;
+
+ val = rockchip_hdmiv2_i2cm_read_data(hdmi_dev, SCDC_SCRAMBLER_STAT);
+ return val;
+}
+
+static void rockchip_hdmiv2_scdc_enable_polling(struct hdmi_dev *hdmi_dev,
+ int enable)
+{
+ rockchip_hdmiv2_scdc_read_request(hdmi_dev, enable);
+ hdmi_msk_reg(hdmi_dev, I2CM_SCDC_READ_UPDATE,
+ m_I2CM_UPRD_VSYNC_EN, v_I2CM_UPRD_VSYNC_EN(enable));
+}
+
+static int rockchip_hdmiv2_scdc_get_status_reg0(struct hdmi_dev *hdmi_dev)
+{
+ rockchip_hdmiv2_scdc_read_request(hdmi_dev, 1);
+ rockchip_hdmiv2_scdc_update_read(hdmi_dev);
+ return hdmi_readl(hdmi_dev, I2CM_SCDC_UPDATE0);
+}
+
+static int rockchip_hdmiv2_scdc_get_status_reg1(struct hdmi_dev *hdmi_dev)
+{
+ rockchip_hdmiv2_scdc_read_request(hdmi_dev, 1);
+ rockchip_hdmiv2_scdc_update_read(hdmi_dev);
+ return hdmi_readl(hdmi_dev, I2CM_SCDC_UPDATE1);
+}
+#endif
+
+static void rockchip_hdmiv2_scdc_init(struct hdmi_dev *hdmi_dev)
+{
+ rockchip_hdmiv2_i2cm_reset(hdmi_dev);
+ rockchip_hdmiv2_i2cm_mask_int(hdmi_dev, 1);
+ rockchip_hdmiv2_i2cm_clk_init(hdmi_dev);
+ /* set scdc i2c addr */
+ hdmi_writel(hdmi_dev, I2CM_SLAVE, DDC_I2C_SCDC_ADDR);
+ rockchip_hdmiv2_i2cm_mask_int(hdmi_dev, 0);/*enable interrupt*/
+}
+
+
+static int rockchip_hdmiv2_scrambling_enable(struct hdmi_dev *hdmi_dev,
+ int enable)
+{
+ HDMIDBG("%s enable %d\n", __func__, enable);
+ if (1 == enable) {
+ /* Write on Rx the bit Scrambling_Enable, register 0x20 */
+ rockchip_hdmiv2_i2cm_write_data(hdmi_dev, 1, SCDC_TMDS_CONFIG);
+ /* TMDS software reset request */
+ hdmi_msk_reg(hdmi_dev, MC_SWRSTZREQ,
+ m_TMDS_SWRST, v_TMDS_SWRST(0));
+ /* Enable/Disable Scrambling */
+ hdmi_msk_reg(hdmi_dev, FC_SCRAMBLER_CTRL,
+ m_FC_SCRAMBLE_EN, v_FC_SCRAMBLE_EN(1));
+ } else {
+ /* Enable/Disable Scrambling */
+ hdmi_msk_reg(hdmi_dev, FC_SCRAMBLER_CTRL,
+ m_FC_SCRAMBLE_EN, v_FC_SCRAMBLE_EN(0));
+ /* TMDS software reset request */
+ hdmi_msk_reg(hdmi_dev, MC_SWRSTZREQ,
+ m_TMDS_SWRST, v_TMDS_SWRST(0));
+ /* Write on Rx the bit Scrambling_Enable, register 0x20 */
+ rockchip_hdmiv2_i2cm_write_data(hdmi_dev, 0, SCDC_TMDS_CONFIG);
+ }
+ return 0;
+}
+
+
+
+static const struct phy_mpll_config_tab *get_phy_mpll_tab(
+ unsigned int pixclock, unsigned int tmdsclk,
+ char pixrepet, char colordepth)
+{
+ int i;
+
+ if (pixclock == 0)
+ return NULL;
+ HDMIDBG("%s pixClock %u pixRepet %d colorDepth %d\n",
+ __func__, pixclock, pixrepet, colordepth);
+ for (i = 0; i < ARRAY_SIZE(PHY_MPLL_TABLE); i++) {
+ if ((PHY_MPLL_TABLE[i].pix_clock == pixclock) &&
+ (PHY_MPLL_TABLE[i].tmdsclock == tmdsclk) &&
+ (PHY_MPLL_TABLE[i].pix_repet == pixrepet) &&
+ (PHY_MPLL_TABLE[i].color_depth == colordepth))
+ return &PHY_MPLL_TABLE[i];
+ }
+ return NULL;
+}
+
+static void rockchip_hdmiv2_powerdown(struct hdmi_dev *hdmi_dev)
+{
+ hdmi_msk_reg(hdmi_dev, PHY_CONF0,
+ m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
+ v_PDDQ_SIG(1) | v_TXPWRON_SIG(0) |
+ v_ENHPD_RXSENSE_SIG(1));
+ hdmi_writel(hdmi_dev, MC_CLKDIS, 0x7f);
+}
+
+static int rockchip_hdmiv2_write_phy(struct hdmi_dev *hdmi_dev,
+ int reg_addr, int val)
+{
+ int trytime = 2, i = 0, op_status = 0;
+
+ while (trytime--) {
+ hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
+ hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_1, (val >> 8) & 0xff);
+ hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_0, val & 0xff);
+ hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_WRITE);
+
+ i = 20;
+ while (i--) {
+ usleep_range(900, 1000);
+ op_status = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
+ if (op_status)
+ hdmi_writel(hdmi_dev,
+ IH_I2CMPHY_STAT0,
+ op_status);
+
+ if (op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR))
+ break;
+ }
+
+ if (op_status & m_I2CMPHY_DONE)
+ return 0;
+ else
+ dev_err(hdmi_dev->hdmi->dev,
+ "[%s] operation error,trytime=%d\n",
+ __func__, trytime);
+ msleep(100);
+ }
+
+ return -1;
+}
+
+static int __maybe_unused rockchip_hdmiv2_read_phy(struct hdmi_dev *hdmi_dev,
+ int reg_addr)
+{
+ int trytime = 2, i = 0, op_status = 0;
+ int val = 0;
+
+ while (trytime--) {
+ hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
+ hdmi_writel(hdmi_dev, PHY_I2CM_DATAI_1, 0x00);
+ hdmi_writel(hdmi_dev, PHY_I2CM_DATAI_0, 0x00);
+ hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_READ);
+
+ i = 20;
+ while (i--) {
+ usleep_range(900, 1000);
+ op_status = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
+ if (op_status)
+ hdmi_writel(hdmi_dev, IH_I2CMPHY_STAT0,
+ op_status);
+
+ if (op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR))
+ break;
+ }
+
+ if (op_status & m_I2CMPHY_DONE) {
+ val = hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_1);
+ val = (val & 0xff) << 8;
+ val += (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_0) & 0xff);
+ pr_debug("phy_reg0x%02x: 0x%04x",
+ reg_addr, val);
+ return val;
+ } else {
+ pr_err("[%s] operation error,trytime=%d\n",
+ __func__, trytime);
+ }
+ msleep(100);
+ }
+
+ return -1;
+}
+
+void rockchip_hdmiv2_dump_phy_regs(struct hdmi_dev *hdmi_dev)
+{
+ int i;
+
+ for (i = 0; i < 0x28; i++)
+ pr_info("phy reg %02x val %04x\n",
+ i, rockchip_hdmiv2_read_phy(hdmi_dev, i));
+}
+
+static int rockchip_hdmiv2_config_phy(struct hdmi_dev *hdmi_dev)
+{
+ int stat = 0, i = 0;
+ const struct phy_mpll_config_tab *phy_mpll = NULL;
+
+ hdmi_msk_reg(hdmi_dev, PHY_I2CM_DIV,
+ m_PHY_I2CM_FAST_STD, v_PHY_I2CM_FAST_STD(0));
+ /* power off PHY */
+ /* hdmi_writel(hdmi_dev, PHY_CONF0, 0x1e); */
+ hdmi_msk_reg(hdmi_dev, PHY_CONF0,
+ m_PDDQ_SIG | m_TXPWRON_SIG | m_SVSRET_SIG,
+ v_PDDQ_SIG(1) | v_TXPWRON_SIG(0) | v_SVSRET_SIG(1));
+
+ if (hdmi_dev->tmdsclk_ratio_change &&
+ hdmi_dev->hdmi->edid.scdc_present == 1) {
+ mutex_lock(&hdmi_dev->ddc_lock);
+ rockchip_hdmiv2_scdc_init(hdmi_dev);
+ stat = rockchip_hdmiv2_i2cm_read_data(hdmi_dev,
+ SCDC_TMDS_CONFIG);
+ if (hdmi_dev->tmdsclk > 340000000)
+ stat |= 2;
+ else
+ stat &= 0x1;
+ rockchip_hdmiv2_i2cm_write_data(hdmi_dev,
+ stat, SCDC_TMDS_CONFIG);
+ mutex_unlock(&hdmi_dev->ddc_lock);
+ }
+ /* reset PHY */
+ hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
+ usleep_range(1000, 2000);
+ hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
+
+ /* Set slave address as PHY GEN2 address */
+ hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_GEN2_ADDR);
+
+ /* config the required PHY I2C register */
+ phy_mpll = get_phy_mpll_tab(hdmi_dev->pixelclk,
+ hdmi_dev->tmdsclk,
+ hdmi_dev->pixelrepeat - 1,
+ hdmi_dev->colordepth);
+ if (phy_mpll) {
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG,
+ v_PREP_DIV(phy_mpll->prep_div) |
+ v_TMDS_CNTRL(
+ phy_mpll->tmdsmhl_cntrl) |
+ v_OPMODE(phy_mpll->opmode) |
+ v_FBDIV2_CNTRL(
+ phy_mpll->fbdiv2_cntrl) |
+ v_FBDIV1_CNTRL(
+ phy_mpll->fbdiv1_cntrl) |
+ v_REF_CNTRL(phy_mpll->ref_cntrl) |
+ v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL,
+ v_MPLL_PROP_CNTRL(
+ phy_mpll->prop_cntrl) |
+ v_MPLL_INT_CNTRL(
+ phy_mpll->int_cntrl));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL,
+ v_MPLL_GMP_CNTRL(
+ phy_mpll->gmp_cntrl));
+ }
+ if (hdmi_dev->tmdsclk <= 74250000) {
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
+ v_OVERRIDE(1) | v_SLOPEBOOST(0) |
+ v_TX_SYMON(1) | v_TX_TRAON(0) |
+ v_TX_TRBON(0) | v_CLK_SYMON(1));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
+ v_TX_TERM(R100_OHMS));
+ } else if (hdmi_dev->tmdsclk <= 148500000) {
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
+ v_OVERRIDE(1) | v_SLOPEBOOST(1) |
+ v_TX_SYMON(1) | v_TX_TRAON(0) |
+ v_TX_TRBON(0) | v_CLK_SYMON(1));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
+ v_TX_TERM(R100_OHMS));
+ } else if (hdmi_dev->tmdsclk <= 340000000) {
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
+ v_OVERRIDE(1) | v_SLOPEBOOST(1) |
+ v_TX_SYMON(1) | v_TX_TRAON(0) |
+ v_TX_TRBON(0) | v_CLK_SYMON(1));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
+ v_TX_TERM(R100_OHMS));
+ } else if (hdmi_dev->tmdsclk > 340000000) {
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_CLKSYMCTRL,
+ v_OVERRIDE(1) | v_SLOPEBOOST(0) |
+ v_TX_SYMON(1) | v_TX_TRAON(0) |
+ v_TX_TRBON(0) | v_CLK_SYMON(1));
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_TERM_RESIS,
+ v_TX_TERM(R100_OHMS));
+ }
+
+ if (hdmi_dev->tmdsclk < 297000000)
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_VLEVCTRL,
+ v_SUP_TXLVL(18) | v_SUP_CLKLVL(17));
+ else
+ rockchip_hdmiv2_write_phy(hdmi_dev, PHYTX_VLEVCTRL,
+ v_SUP_TXLVL(14) | v_SUP_CLKLVL(13));
+
+ rockchip_hdmiv2_write_phy(hdmi_dev, 0x05, 0x8000);
+ if (hdmi_dev->tmdsclk_ratio_change)
+ msleep(100);
+ /* power on PHY */
+ hdmi_writel(hdmi_dev, PHY_CONF0, 0x2e);
+ /*
+ hdmi_msk_reg(hdmi_dev, PHY_CONF0,
+ m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
+ v_PDDQ_SIG(0) | v_TXPWRON_SIG(1) |
+ v_ENHPD_RXSENSE_SIG(1));
+ */
+ /* check if the PHY PLL is locked */
+ #define PHY_TIMEOUT 10000
+ while (i++ < PHY_TIMEOUT) {
+ if ((i % 10) == 0) {
+ stat = hdmi_readl(hdmi_dev, PHY_STAT0);
+ if (stat & m_PHY_LOCK)
+ break;
+ usleep_range(1000, 2000);
+ }
+ }
+ if ((stat & m_PHY_LOCK) == 0) {
+ stat = hdmi_readl(hdmi_dev, MC_LOCKONCLOCK);
+ dev_err(hdmi_dev->hdmi->dev,
+ "PHY PLL not locked: PCLK_ON=%d,TMDSCLK_ON=%d\n",
+ (stat & m_PCLK_ON) >> 6, (stat & m_TMDSCLK_ON) >> 5);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int rockchip_hdmiv2_video_framecomposer(struct hdmi *hdmi_drv,
+ struct hdmi_video *vpara)
+{
+ struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
+ int value, vsync_pol, hsync_pol, de_pol;
+ struct hdmi_video_timing *timing = NULL;
+ struct fb_videomode *mode = NULL;
+ u32 sink_version, tmdsclk;
+
+ vsync_pol = hdmi_drv->lcdc->cur_screen->pin_vsync;
+ hsync_pol = hdmi_drv->lcdc->cur_screen->pin_hsync;
+ de_pol = (hdmi_drv->lcdc->cur_screen->pin_den == 0) ? 1 : 0;
+
+ hdmi_msk_reg(hdmi_dev, A_VIDPOLCFG,
+ m_DATAEN_POL | m_VSYNC_POL | m_HSYNC_POL,
+ v_DATAEN_POL(de_pol) |
+ v_VSYNC_POL(vsync_pol) |
+ v_HSYNC_POL(hsync_pol));
+
+ timing = (struct hdmi_video_timing *)hdmi_vic2timing(vpara->vic);
+ if (timing == NULL) {
+ dev_err(hdmi_drv->dev,
+ "[%s] not found vic %d\n", __func__, vpara->vic);
+ return -ENOENT;
+ }
+ mode = &(timing->mode);
+ if (vpara->color_input == HDMI_COLOR_YCBCR420)
+ tmdsclk = mode->pixclock / 2;
+ else
+ tmdsclk = mode->pixclock;
+ switch (vpara->color_output_depth) {
+ case 10:
+ tmdsclk += tmdsclk / 4;
+ break;
+ case 12:
+ tmdsclk += tmdsclk / 2;
+ break;
+ case 16:
+ tmdsclk += tmdsclk;
+ break;
+ case 8:
+ default:
+ break;
+ }
+
+ if (tmdsclk > 594000000) {
+ vpara->color_output_depth = 8;
+ tmdsclk = mode->pixclock;
+ }
+ pr_info("pixel clk is %u tmds clk is %u\n", mode->pixclock, tmdsclk);
+ if ((tmdsclk > 340000000 && hdmi_dev->tmdsclk < 340000000) ||
+ (tmdsclk < 340000000 && hdmi_dev->tmdsclk > 340000000))
+ hdmi_dev->tmdsclk_ratio_change = true;
+ else
+ hdmi_dev->tmdsclk_ratio_change = false;
+
+ hdmi_dev->tmdsclk = tmdsclk;
+ hdmi_dev->pixelclk = mode->pixclock;
+ hdmi_dev->pixelrepeat = timing->pixelrepeat;
+ hdmi_dev->colordepth = vpara->color_output_depth;
+
+ /* Video Register has already been set in uboot,
+ so we no need to set again */
+
+ if (hdmi_drv->uboot)
+ return -1;
+
+ /* Start/stop HDCP keepout window generation */
+ hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
+ m_FC_HDCP_KEEPOUT, v_FC_HDCP_KEEPOUT(1));
+ if (hdmi_drv->edid.scdc_present == 1) {
+ if (tmdsclk > 340000000) {/* used for HDMI 2.0 TX */
+ mutex_lock(&hdmi_dev->ddc_lock);
+ rockchip_hdmiv2_scdc_init(hdmi_dev);
+ sink_version =
+ rockchip_hdmiv2_scdc_get_sink_version(hdmi_dev);
+ pr_info("sink scdc version is %d\n", sink_version);
+ sink_version = hdmi_drv->edid.hf_vsdb_version;
+ rockchip_hdmiv2_scdc_set_source_version(hdmi_dev,
+ sink_version);
+ if (hdmi_drv->edid.rr_capable == 1)
+ rockchip_hdmiv2_scdc_read_request(hdmi_dev, 1);
+ rockchip_hdmiv2_scrambling_enable(hdmi_dev, 1);
+ mutex_unlock(&hdmi_dev->ddc_lock);
+ } else {
+ mutex_lock(&hdmi_dev->ddc_lock);
+ rockchip_hdmiv2_scdc_init(hdmi_dev);
+ rockchip_hdmiv2_scrambling_enable(hdmi_dev, 0);
+ mutex_unlock(&hdmi_dev->ddc_lock);
+ }
+ }
+
+ hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
+ m_FC_VSYNC_POL | m_FC_HSYNC_POL | m_FC_DE_POL |
+ m_FC_HDMI_DVI | m_FC_INTERLACE_MODE,
+ v_FC_VSYNC_POL(vsync_pol) | v_FC_HSYNC_POL(hsync_pol) |
+ v_FC_DE_POL(de_pol) | v_FC_HDMI_DVI(vpara->sink_hdmi) |
+ v_FC_INTERLACE_MODE(mode->vmode));
+ if (mode->vmode == FB_VMODE_INTERLACED)
+ hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
+ m_FC_VBLANK, v_FC_VBLANK(1));
+ else
+ hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
+ m_FC_VBLANK, v_FC_VBLANK(0));
+
+ value = mode->xres;
+ if (vpara->color_input == HDMI_COLOR_YCBCR420)
+ value = value / 2;
+ hdmi_writel(hdmi_dev, FC_INHACTIV1, v_FC_HACTIVE1(value >> 8));
+ hdmi_writel(hdmi_dev, FC_INHACTIV0, (value & 0xff));
+
+ value = mode->yres;
+ hdmi_writel(hdmi_dev, FC_INVACTIV1, v_FC_VACTIVE1(value >> 8));
+ hdmi_writel(hdmi_dev, FC_INVACTIV0, (value & 0xff));
+
+ value = mode->hsync_len + mode->left_margin + mode->right_margin;
+ if (vpara->color_input == HDMI_COLOR_YCBCR420)
+ value = value / 2;
+ hdmi_writel(hdmi_dev, FC_INHBLANK1, v_FC_HBLANK1(value >> 8));
+ hdmi_writel(hdmi_dev, FC_INHBLANK0, (value & 0xff));
+
+ value = mode->vsync_len + mode->upper_margin + mode->lower_margin;
+ hdmi_writel(hdmi_dev, FC_INVBLANK, (value & 0xff));
+
+ value = mode->right_margin;
+ if (vpara->color_input == HDMI_COLOR_YCBCR420)
+ value = value / 2;
+ hdmi_writel(hdmi_dev, FC_HSYNCINDELAY1, v_FC_HSYNCINDEAY1(value >> 8));
+ hdmi_writel(hdmi_dev, FC_HSYNCINDELAY0, (value & 0xff));
+
+ value = mode->lower_margin;
+ hdmi_writel(hdmi_dev, FC_VSYNCINDELAY, (value & 0xff));
+
+ value = mode->hsync_len;
+ if (vpara->color_input == HDMI_COLOR_YCBCR420)
+ value = value / 2;
+ hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH1, v_FC_HSYNCWIDTH1(value >> 8));
+ hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH0, (value & 0xff));
+
+ value = mode->vsync_len;
+ hdmi_writel(hdmi_dev, FC_VSYNCINWIDTH, (value & 0xff));
+
+ /*Set the control period minimum duration
+ (min. of 12 pixel clock cycles, refer to HDMI 1.4b specification)*/
+ hdmi_writel(hdmi_dev, FC_CTRLDUR, 12);
+ hdmi_writel(hdmi_dev, FC_EXCTRLDUR, 32);
+
+ hdmi_writel(hdmi_dev, FC_EXCTRLSPAC,
+ (hdmi_dev->tmdsclk/1000) * 50 / (256 * 512));
+
+#if 0
+ /* spacing < 256^2 * config / tmdsClock, spacing <= 50ms
+ * worst case: tmdsClock == 25MHz => config <= 19
+ */
+ hdmi_writel(hdmi_dev, FC_EXCTRLSPAC, 1);
+
+ /*Set PreambleFilter*/
+ for (i = 0; i < 3; i++) {
+ value = (i + 1) * 11;
+ if (i == 0) /*channel 0*/
+ hdmi_writel(hdmi_dev, FC_CH0PREAM, value);
+ else if (i == 1) /*channel 1*/
+ hdmi_writel(hdmi_dev, FC_CH1PREAM, value & 0x3f);
+ else if (i == 2) /*channel 2*/
+ hdmi_writel(hdmi_dev, FC_CH2PREAM, value & 0x3f);
+ }
+#endif
+
+ hdmi_writel(hdmi_dev, FC_PRCONF, v_FC_PR_FACTOR(timing->pixelrepeat));
+
+ return 0;
+}
+
+static int rockchip_hdmiv2_video_packetizer(struct hdmi_dev *hdmi_dev,
+ struct hdmi_video *vpara)
+{
+ unsigned char color_depth = 0;
+ unsigned char output_select = 0;
+ unsigned char remap_size = 0;
+
+ if (vpara->color_output == HDMI_COLOR_YCBCR422) {
+ switch (vpara->color_output_depth) {
+ case 8:
+ remap_size = YCC422_16BIT;
+ break;
+ case 10:
+ remap_size = YCC422_20BIT;
+ break;
+ case 12:
+ remap_size = YCC422_24BIT;
+ break;
+ default:
+ remap_size = YCC422_16BIT;
+ break;
+ }
+
+ output_select = OUT_FROM_YCC422_REMAP;
+ /*Config remap size for the different color Depth*/
+ hdmi_msk_reg(hdmi_dev, VP_REMAP,
+ m_YCC422_SIZE, v_YCC422_SIZE(remap_size));
+ } else {
+ switch (vpara->color_output_depth) {
+ case 10:
+ color_depth = COLOR_DEPTH_30BIT;
+ output_select = OUT_FROM_PIXEL_PACKING;
+ break;
+ case 12:
+ color_depth = COLOR_DEPTH_36BIT;
+ output_select = OUT_FROM_PIXEL_PACKING;
+ break;
+ case 16:
+ color_depth = COLOR_DEPTH_48BIT;
+ output_select = OUT_FROM_PIXEL_PACKING;
+ break;
+ case 8:
+ default:
+ color_depth = COLOR_DEPTH_24BIT_DEFAULT;
+ output_select = OUT_FROM_8BIT_BYPASS;
+ break;
+ }
+
+ /*Config Color Depth*/
+ hdmi_msk_reg(hdmi_dev, VP_PR_CD,
+ m_COLOR_DEPTH, v_COLOR_DEPTH(color_depth));
+ }
+
+ /*Config pixel repettion*/
+ hdmi_msk_reg(hdmi_dev, VP_PR_CD, m_DESIRED_PR_FACTOR,
+ v_DESIRED_PR_FACTOR(hdmi_dev->pixelrepeat - 1));
+ if (hdmi_dev->pixelrepeat > 1)
+ hdmi_msk_reg(hdmi_dev, VP_CONF,
+ m_PIXEL_REPET_EN | m_BYPASS_SEL,
+ v_PIXEL_REPET_EN(1) | v_BYPASS_SEL(0));
+ else
+ hdmi_msk_reg(hdmi_dev, VP_CONF,
+ m_PIXEL_REPET_EN | m_BYPASS_SEL,
+ v_PIXEL_REPET_EN(0) | v_BYPASS_SEL(1));
+
+ /*config output select*/
+ if (output_select == OUT_FROM_PIXEL_PACKING) { /* pixel packing */
+ hdmi_msk_reg(hdmi_dev, VP_CONF,
+ m_BYPASS_EN | m_PIXEL_PACK_EN |
+ m_YCC422_EN | m_OUTPUT_SEL,
+ v_BYPASS_EN(0) | v_PIXEL_PACK_EN(1) |
+ v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
+ } else if (output_select == OUT_FROM_YCC422_REMAP) { /* YCC422 */
+ hdmi_msk_reg(hdmi_dev, VP_CONF,
+ m_BYPASS_EN | m_PIXEL_PACK_EN |
+ m_YCC422_EN | m_OUTPUT_SEL,
+ v_BYPASS_EN(0) | v_PIXEL_PACK_EN(0) |
+ v_YCC422_EN(1) | v_OUTPUT_SEL(output_select));
+ } else if (output_select == OUT_FROM_8BIT_BYPASS ||
+ output_select == 3) { /* bypass */
+ hdmi_msk_reg(hdmi_dev, VP_CONF,
+ m_BYPASS_EN | m_PIXEL_PACK_EN |
+ m_YCC422_EN | m_OUTPUT_SEL,
+ v_BYPASS_EN(1) | v_PIXEL_PACK_EN(0) |
+ v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
+ }
+
+#if defined(HDMI_VIDEO_STUFFING)
+ /* YCC422 and pixel packing stuffing*/
+ hdmi_msk_reg(hdmi_dev, VP_STUFF, m_PR_STUFFING, v_PR_STUFFING(1));
+ hdmi_msk_reg(hdmi_dev, VP_STUFF,
+ m_YCC422_STUFFING | m_PP_STUFFING,
+ v_YCC422_STUFFING(1) | v_PP_STUFFING(1));
+#endif
+ return 0;
+}
+
+static int rockchip_hdmiv2_video_sampler(struct hdmi_dev *hdmi_dev,
+ struct hdmi_video *vpara)
+{
+ int map_code = 0;
+
+ if (vpara->color_input == HDMI_COLOR_YCBCR422) {
+ /* YCC422 mapping is discontinued - only map 1 is supported */
+ switch (vpara->color_output_depth) {
+ case 8:
+ map_code = VIDEO_YCBCR422_8BIT;
+ break;
+ case 10:
+ map_code = VIDEO_YCBCR422_10BIT;
+ break;
+ case 12:
+ map_code = VIDEO_YCBCR422_12BIT;
+ break;
+ default:
+ map_code = VIDEO_YCBCR422_8BIT;
+ break;
+ }
+ } else if (vpara->color_input == HDMI_COLOR_YCBCR420 ||
+ vpara->color_input == HDMI_COLOR_YCBCR444) {
+ switch (vpara->color_output_depth) {
+ case 10:
+ map_code = VIDEO_YCBCR444_10BIT;
+ break;
+ case 12:
+ map_code = VIDEO_YCBCR444_12BIT;
+ break;
+ case 16:
+ map_code = VIDEO_YCBCR444_16BIT;
+ break;
+ case 8:
+ default:
+ map_code = VIDEO_YCBCR444_8BIT;
+ break;
+ }
+ } else {
+ switch (vpara->color_output_depth) {
+ case 10:
+ map_code = VIDEO_RGB444_10BIT;
+ break;
+ case 12:
+ map_code = VIDEO_RGB444_12BIT;
+ break;
+ case 16:
+ map_code = VIDEO_RGB444_16BIT;
+ break;
+ case 8:
+ default:
+ map_code = VIDEO_RGB444_8BIT;
+ break;
+ }
+ map_code += (vpara->color_input == HDMI_COLOR_YCBCR444) ?
+ 8 : 0;
+ }
+
+ /* Set Data enable signal from external
+ and set video sample input mapping */
+ hdmi_msk_reg(hdmi_dev, TX_INVID0,
+ m_INTERNAL_DE_GEN | m_VIDEO_MAPPING,
+ v_INTERNAL_DE_GEN(0) | v_VIDEO_MAPPING(map_code));
+
+#if defined(HDMI_VIDEO_STUFFING)
+ hdmi_writel(hdmi_dev, TX_GYDATA0, 0x00);
+ hdmi_writel(hdmi_dev, TX_GYDATA1, 0x00);
+ hdmi_msk_reg(hdmi_dev, TX_INSTUFFING,
+ m_GYDATA_STUFF, v_GYDATA_STUFF(1));
+ hdmi_writel(hdmi_dev, TX_RCRDATA0, 0x00);
+ hdmi_writel(hdmi_dev, TX_RCRDATA1, 0x00);
+ hdmi_msk_reg(hdmi_dev, TX_INSTUFFING,
+ m_RCRDATA_STUFF, v_RCRDATA_STUFF(1));
+ hdmi_writel(hdmi_dev, TX_BCBDATA0, 0x00);
+ hdmi_writel(hdmi_dev, TX_BCBDATA1, 0x00);
+ hdmi_msk_reg(hdmi_dev, TX_INSTUFFING,
+ m_BCBDATA_STUFF, v_BCBDATA_STUFF(1));
+#endif
+ return 0;
+}
+
+static const char coeff_csc[][24] = {
+ /* G R B Bias
+ A1 | A2 | A3 | A4 |
+ B1 | B2 | B3 | B4 |
+ C1 | C2 | C3 | C4 | */
+ { /* CSC_RGB_0_255_TO_RGB_16_235_8BIT */
+ 0x36, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /*G*/
+ 0x00, 0x00, 0x36, 0xf7, 0x00, 0x00, 0x00, 0x40, /*R*/
+ 0x00, 0x00, 0x00, 0x00, 0x36, 0xf7, 0x00, 0x40, /*B*/
+ },
+ { /* CSC_RGB_0_255_TO_RGB_16_235_10BIT */
+ 0x36, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /*G*/
+ 0x00, 0x00, 0x36, 0xf7, 0x00, 0x00, 0x01, 0x00, /*R*/
+ 0x00, 0x00, 0x00, 0x00, 0x36, 0xf7, 0x01, 0x00, /*B*/
+ },
+ { /* CSC_RGB_0_255_TO_ITU601_16_235_8BIT */
+ 0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x00, 0x40, /*Y*/
+ 0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x02, 0x00, /*Cr*/
+ 0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x02, 0x00, /*Cb*/
+ },
+ { /* CSC_RGB_0_255_TO_ITU601_16_235_10BIT */
+ 0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x01, 0x00, /*Y*/
+ 0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x08, 0x00, /*Cr*/
+ 0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x08, 0x00, /*Cb*/
+ },
+ { /* CSC_RGB_0_255_TO_ITU709_16_235_8BIT */
+ 0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x00, 0x40, /*Y*/
+ 0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x02, 0x00, /*Cr*/
+ 0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x02, 0x00, /*Cb*/
+ },
+ { /* CSC_RGB_0_255_TO_ITU709_16_235_10BIT */
+ 0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x01, 0x00, /*Y*/
+ 0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x08, 0x00, /*Cr*/
+ 0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x08, 0x00, /*Cb*/
+ },
+ /* Y Cr Cb Bias */
+ { /* CSC_ITU601_16_235_TO_RGB_0_255_8BIT */
+ 0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e, /*G*/
+ 0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a, /*R*/
+ 0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b, /*B*/
+ },
+ { /* CSC_ITU709_16_235_TO_RGB_0_255_8BIT */
+ 0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7, /*G*/
+ 0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d, /*R*/
+ 0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25, /*B*/
+ },
+};
+
+static int rockchip_hdmiv2_video_csc(struct hdmi_dev *hdmi_dev,
+ struct hdmi_video *vpara)
+{
+ int i, mode, interpolation, decimation, csc_scale;
+ const char *coeff = NULL;
+ unsigned char color_depth = 0;
+
+ if (vpara->color_input == vpara->color_output) {
+ hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL,
+ m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(0));
+ return 0;
+ }
+
+ if (vpara->color_input == HDMI_COLOR_YCBCR422 &&
+ vpara->color_output != HDMI_COLOR_YCBCR422 &&
+ vpara->color_output != HDMI_COLOR_YCBCR420) {
+ interpolation = 1;
+ hdmi_msk_reg(hdmi_dev, CSC_CFG,
+ m_CSC_INTPMODE, v_CSC_INTPMODE(interpolation));
+ }
+
+ if ((vpara->color_input == HDMI_COLOR_RGB_0_255 ||
+ vpara->color_input == HDMI_COLOR_YCBCR444) &&
+ vpara->color_output == HDMI_COLOR_YCBCR422) {
+ decimation = 1;
+ hdmi_msk_reg(hdmi_dev, CSC_CFG,
+ m_CSC_DECIMODE, v_CSC_DECIMODE(decimation));
+ }
+
+ switch (vpara->vic) {
+ case HDMI_720X480I_60HZ_4_3:
+ case HDMI_720X576I_50HZ_4_3:
+ case HDMI_720X480P_60HZ_4_3:
+ case HDMI_720X576P_50HZ_4_3:
+ case HDMI_720X480I_60HZ_16_9:
+ case HDMI_720X576I_50HZ_16_9:
+ case HDMI_720X480P_60HZ_16_9:
+ case HDMI_720X576P_50HZ_16_9:
+ if (vpara->color_input == HDMI_COLOR_RGB_0_255 &&
+ vpara->color_output >= HDMI_COLOR_YCBCR444) {
+ mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
+ csc_scale = 0;
+ } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
+ vpara->color_output == HDMI_COLOR_RGB_0_255) {
+ mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
+ csc_scale = 1;
+ }
+ break;
+ default:
+ if (vpara->color_input == HDMI_COLOR_RGB_0_255 &&
+ vpara->color_output >= HDMI_COLOR_YCBCR444) {
+ mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
+ csc_scale = 0;
+ } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
+ vpara->color_output == HDMI_COLOR_RGB_0_255) {
+ mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
+ csc_scale = 1;
+ }
+ break;
+ }
+
+ if ((vpara->color_input == HDMI_COLOR_RGB_0_255) &&
+ (vpara->color_output == HDMI_COLOR_RGB_16_235)) {
+ mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
+ csc_scale = 0;
+ }
+
+ switch (vpara->color_output_depth) {
+ case 10:
+ color_depth = COLOR_DEPTH_30BIT;
+ mode += 1;
+ break;
+ case 12:
+ color_depth = COLOR_DEPTH_36BIT;
+ mode += 2;
+ break;
+ case 16:
+ color_depth = COLOR_DEPTH_48BIT;
+ mode += 3;
+ break;
+ case 8:
+ default:
+ color_depth = COLOR_DEPTH_24BIT;
+ break;
+ }
+
+ coeff = coeff_csc[mode];
+ for (i = 0; i < 24; i++)
+ hdmi_writel(hdmi_dev, CSC_COEF_A1_MSB + i, coeff[i]);
+
+ hdmi_msk_reg(hdmi_dev, CSC_SCALE,
+ m_CSC_SCALE, v_CSC_SCALE(csc_scale));
+ /*config CSC_COLOR_DEPTH*/
+ hdmi_msk_reg(hdmi_dev, CSC_SCALE,
+ m_CSC_COLOR_DEPTH, v_CSC_COLOR_DEPTH(color_depth));
+
+ /* enable CSC */
+ hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL,
+ m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(1));
+
+ return 0;
+}
+
+
+static int hdmi_dev_detect_hotplug(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ u32 value = hdmi_readl(hdmi_dev, PHY_STAT0);
+
+ HDMIDBG("[%s] reg%x value %02x\n", __func__, PHY_STAT0, value);
+
+ if (value & m_PHY_HPD)
+ return HDMI_HPD_ACTIVED;
+ else
+ return HDMI_HPD_REMOVED;
+}
+
+static int hdmi_dev_read_edid(struct hdmi *hdmi, int block, unsigned char *buff)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ int i = 0, n = 0, index = 0, ret = -1, trytime = 5;
+ int offset = (block % 2) * 0x80;
+ int interrupt = 0;
+
+ HDMIDBG("[%s] block %d\n", __func__, block);
+
+ rockchip_hdmiv2_i2cm_reset(hdmi_dev);
+
+ /* Set DDC I2C CLK which devided from DDC_CLK to 100KHz. */
+ rockchip_hdmiv2_i2cm_clk_init(hdmi_dev);
+
+ /* Enable I2C interrupt for reading edid */
+ rockchip_hdmiv2_i2cm_mask_int(hdmi_dev, 0);
+
+ hdmi_writel(hdmi_dev, I2CM_SLAVE, DDC_I2C_EDID_ADDR);
+ hdmi_writel(hdmi_dev, I2CM_SEGADDR, DDC_I2C_SEG_ADDR);
+ hdmi_writel(hdmi_dev, I2CM_SEGPTR, block / 2);
+ for (n = 0; n < HDMI_EDID_BLOCK_SIZE / 8; n++) {
+ for (trytime = 0; trytime < 5; trytime++) {
+ hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset + 8 * n);
+ /* enable extend sequential read operation */
+ if (block == 0)
+ hdmi_msk_reg(hdmi_dev, I2CM_OPERATION,
+ m_I2CM_RD8, v_I2CM_RD8(1));
+ else
+ hdmi_msk_reg(hdmi_dev, I2CM_OPERATION,
+ m_I2CM_RD8_EXT,
+ v_I2CM_RD8_EXT(1));
+
+ i = 20;
+ while (i--) {
+ usleep_range(900, 1000);
+ interrupt = hdmi_readl(hdmi_dev,
+ IH_I2CM_STAT0);
+ if (interrupt)
+ hdmi_writel(hdmi_dev,
+ IH_I2CM_STAT0, interrupt);
+
+ if (interrupt &
+ (m_SCDC_READREQ | m_I2CM_DONE |
+ m_I2CM_ERROR))
+ break;
+ }
+
+ if (interrupt & m_I2CM_DONE) {
+ for (index = 0; index < 8; index++)
+ buff[8 * n + index] =
+ hdmi_readl(hdmi_dev,
+ I2CM_READ_BUFF0 +
+ index);
+
+ if (n == HDMI_EDID_BLOCK_SIZE / 8 - 1) {
+ ret = 0;
+ goto exit;
+ }
+ break;
+ } else if ((interrupt & m_I2CM_ERROR) || (i == -1)) {
+ dev_err(hdmi->dev,
+ "[%s] edid read %d error\n",
+ __func__, offset + 8 * n);
+ }
+ }
+ if (trytime == 5) {
+ dev_err(hdmi->dev,
+ "[%s] edid read error\n", __func__);
+ break;
+ }
+ }
+
+exit:
+ /* Disable I2C interrupt */
+ rockchip_hdmiv2_i2cm_mask_int(hdmi_dev, 1);
+
+ #ifdef DEBUG
+ if (!ret) {
+ for (index = 0; index < 128; index++) {
+ printk("0x%02x ,", buff[index]);
+ if ((index + 1) % 16 == 0)
+ printk("\n");
+ }
+ }
+ #endif
+ return ret;
+}
+
+static void hdmi_dev_config_avi(struct hdmi_dev *hdmi_dev,
+ struct hdmi_video *vpara)
+{
+ unsigned char colorimetry, ext_colorimetry, aspect_ratio, y1y0;
+ unsigned char rgb_quan_range = AVI_QUANTIZATION_RANGE_DEFAULT;
+
+ /* Set AVI infoFrame Data byte1 */
+ if (vpara->color_output == HDMI_COLOR_YCBCR444)
+ y1y0 = AVI_COLOR_MODE_YCBCR444;
+ else if (vpara->color_output == HDMI_COLOR_YCBCR422)
+ y1y0 = AVI_COLOR_MODE_YCBCR422;
+ else if (vpara->color_output == HDMI_COLOR_YCBCR420)
+ y1y0 = AVI_COLOR_MODE_YCBCR420;
+ else
+ y1y0 = AVI_COLOR_MODE_RGB;
+
+ hdmi_msk_reg(hdmi_dev, FC_AVICONF0,
+ m_FC_ACTIV_FORMAT | m_FC_RGC_YCC,
+ v_FC_RGC_YCC(y1y0) | v_FC_ACTIV_FORMAT(1));
+
+ /* Set AVI infoFrame Data byte2 */
+ switch (vpara->vic) {
+ case HDMI_720X480I_60HZ_4_3:
+ case HDMI_720X576I_50HZ_4_3:
+ case HDMI_720X480P_60HZ_4_3:
+ case HDMI_720X576P_50HZ_4_3:
+ aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
+ colorimetry = AVI_COLORIMETRY_SMPTE_170M;
+ break;
+ case HDMI_720X480I_60HZ_16_9:
+ case HDMI_720X576I_50HZ_16_9:
+ case HDMI_720X480P_60HZ_16_9:
+ case HDMI_720X576P_50HZ_16_9:
+ aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
+ colorimetry = AVI_COLORIMETRY_SMPTE_170M;
+ break;
+ default:
+ aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
+ colorimetry = AVI_COLORIMETRY_ITU709;
+ }
+
+ if (vpara->color_output_depth > 8) {
+ colorimetry = AVI_COLORIMETRY_EXTENDED;
+ ext_colorimetry = 6;
+ } else if (vpara->color_output == HDMI_COLOR_RGB_16_235 ||
+ vpara->color_output == HDMI_COLOR_RGB_0_255) {
+ colorimetry = AVI_COLORIMETRY_NO_DATA;
+ ext_colorimetry = 0;
+ }
+
+ hdmi_writel(hdmi_dev, FC_AVICONF1,
+ v_FC_COLORIMETRY(colorimetry) |
+ v_FC_PIC_ASPEC_RATIO(aspect_ratio) |
+ v_FC_ACT_ASPEC_RATIO(ACTIVE_ASPECT_RATE_DEFAULT));
+
+ /* Set AVI infoFrame Data byte3 */
+ hdmi_msk_reg(hdmi_dev, FC_AVICONF2,
+ m_FC_EXT_COLORIMETRY | m_FC_QUAN_RANGE,
+ v_FC_EXT_COLORIMETRY(ext_colorimetry) |
+ v_FC_QUAN_RANGE(rgb_quan_range));
+
+ /* Set AVI infoFrame Data byte4 */
+ if ((vpara->vic > 92 && vpara->vic < 96) || (vpara->vic == 98))
+ hdmi_writel(hdmi_dev, FC_AVIVID, 0);
+ else
+ hdmi_writel(hdmi_dev, FC_AVIVID, vpara->vic & 0xff);
+ /* Set AVI infoFrame Data byte5 */
+ hdmi_msk_reg(hdmi_dev, FC_AVICONF3, m_FC_YQ | m_FC_CN,
+ v_FC_YQ(YQ_LIMITED_RANGE) | v_FC_CN(CN_GRAPHICS));
+}
+
+static int hdmi_dev_config_vsi(struct hdmi *hdmi,
+ unsigned char vic_3d, unsigned char format)
+{
+ int i = 0, id = 0x000c03;
+ unsigned char data[3] = {0};
+
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("[%s] vic %d format %d.\n", __func__, vic_3d, format);
+
+ hdmi_msk_reg(hdmi_dev, FC_DATAUTO0, m_VSD_AUTO, v_VSD_AUTO(0));
+ hdmi_writel(hdmi_dev, FC_VSDIEEEID2, id & 0xff);
+ hdmi_writel(hdmi_dev, FC_VSDIEEEID1, (id >> 8) & 0xff);
+ hdmi_writel(hdmi_dev, FC_VSDIEEEID0, (id >> 16) & 0xff);
+
+ data[0] = format << 5; /* PB4 --HDMI_Video_Format */
+ switch (format) {
+ case HDMI_VIDEO_FORMAT_4KX2K:
+ data[1] = vic_3d; /* PB5--HDMI_VIC */
+ data[2] = 0;
+ break;
+ case HDMI_VIDEO_FORMAT_3D:
+ data[1] = vic_3d << 4; /* PB5--3D_Structure field */
+ data[2] = 0; /* PB6--3D_Ext_Data field */
+ break;
+ default:
+ data[1] = 0;
+ data[2] = 0;
+ break;
+ }
+
+ for (i = 0; i < 3; i++)
+ hdmi_writel(hdmi_dev, FC_VSDPAYLOAD0 + i, data[i]);
+ hdmi_writel(hdmi_dev, FC_VSDSIZE, 0x6);
+/* if (auto_send) { */
+ hdmi_writel(hdmi_dev, FC_DATAUTO1, 0);
+ hdmi_writel(hdmi_dev, FC_DATAUTO2, 0x11);
+ hdmi_msk_reg(hdmi_dev, FC_DATAUTO0, m_VSD_AUTO, v_VSD_AUTO(1));
+/* }
+ else {
+ hdmi_msk_reg(hdmi_dev, FC_DATMAN, m_VSD_MAN, v_VSD_MAN(1));
+ }
+*/
+ return 0;
+}
+
+static int hdmi_dev_config_video(struct hdmi *hdmi, struct hdmi_video *vpara)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("%s vic %d 3dformat %d color mode %d color depth %d\n",
+ __func__, vpara->vic, vpara->format_3d,
+ vpara->color_output, vpara->color_output_depth);
+
+ if (hdmi_dev->soctype == HDMI_SOC_RK3288)
+ vpara->color_input = HDMI_COLOR_RGB_0_255;
+
+ if (!hdmi->uboot) {
+ /* befor configure video, we power off phy */
+ hdmi_msk_reg(hdmi_dev, PHY_CONF0,
+ m_PDDQ_SIG | m_TXPWRON_SIG,
+ v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
+
+ /* force output blue */
+ if (vpara->color_output == HDMI_COLOR_RGB_0_255) {
+ hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x00); /*R*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x00); /*G*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0x00); /*B*/
+ } else if (vpara->color_output == HDMI_COLOR_RGB_16_235) {
+ hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x10); /*R*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x10); /*G*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0x10); /*B*/
+ } else {
+ hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x80); /*R*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x10); /*G*/
+ hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0x80); /*B*/
+ }
+ hdmi_msk_reg(hdmi_dev, FC_DBGFORCE,
+ m_FC_FORCEVIDEO, v_FC_FORCEVIDEO(1));
+ }
+
+ hdmi_writel(hdmi_dev, MC_CLKDIS, m_HDCPCLK_DISABLE);
+ if (rockchip_hdmiv2_video_framecomposer(hdmi, vpara) < 0)
+ return -1;
+
+ if (rockchip_hdmiv2_video_packetizer(hdmi_dev, vpara) < 0)
+ return -1;
+ /* Color space convert */
+ if (rockchip_hdmiv2_video_csc(hdmi_dev, vpara) < 0)
+ return -1;
+ if (rockchip_hdmiv2_video_sampler(hdmi_dev, vpara) < 0)
+ return -1;
+
+ if (vpara->sink_hdmi == OUTPUT_HDMI) {
+ hdmi_dev_config_avi(hdmi_dev, vpara);
+ if (vpara->format_3d != HDMI_3D_NONE) {
+ hdmi_dev_config_vsi(hdmi,
+ vpara->format_3d,
+ HDMI_VIDEO_FORMAT_3D);
+ } else if ((vpara->vic > 92 && vpara->vic < 96) ||
+ (vpara->vic == 98)) {
+ vpara->vic = (vpara->vic == 98) ?
+ 4 : (96 - vpara->vic);
+ hdmi_dev_config_vsi(hdmi,
+ vpara->vic,
+ HDMI_VIDEO_FORMAT_4KX2K);
+ } else {
+ hdmi_dev_config_vsi(hdmi,
+ vpara->vic,
+ HDMI_VIDEO_FORMAT_NORMAL);
+ }
+ dev_info(hdmi->dev, "[%s] sucess output HDMI.\n", __func__);
+ } else {
+ dev_info(hdmi->dev, "[%s] sucess output DVI.\n", __func__);
+ }
+
+ rockchip_hdmiv2_config_phy(hdmi_dev);
+ return 0;
+}
+
+static void hdmi_dev_config_aai(struct hdmi_dev *hdmi_dev,
+ struct hdmi_audio *audio)
+{
+ /*Refer to CEA861-E Audio infoFrame*/
+ /*Set both Audio Channel Count and Audio Coding
+ Type Refer to Stream Head for HDMI*/
+ hdmi_msk_reg(hdmi_dev, FC_AUDICONF0,
+ m_FC_CHN_CNT | m_FC_CODING_TYEP,
+ v_FC_CHN_CNT(audio->channel-1) | v_FC_CODING_TYEP(0));
+
+ /*Set both Audio Sample Size and Sample Frequency
+ Refer to Stream Head for HDMI*/
+ hdmi_msk_reg(hdmi_dev, FC_AUDICONF1,
+ m_FC_SAMPLE_SIZE | m_FC_SAMPLE_FREQ,
+ v_FC_SAMPLE_SIZE(0) | v_FC_SAMPLE_FREQ(0));
+
+ /*Set Channel Allocation*/
+ hdmi_writel(hdmi_dev, FC_AUDICONF2, 0x00);
+
+ /*Set LFEPBL¡¢DOWN-MIX INH and LSV*/
+ hdmi_writel(hdmi_dev, FC_AUDICONF3, 0x00);
+}
+
+static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+ int word_length = 0, channel = 0, mclk_fs;
+ unsigned int N = 0, CTS = 0;
+ int rate = 0;
+
+ HDMIDBG("%s\n", __func__);
+
+ if (audio->channel < 3)
+ channel = I2S_CHANNEL_1_2;
+ else if (audio->channel < 5)
+ channel = I2S_CHANNEL_3_4;
+ else if (audio->channel < 7)
+ channel = I2S_CHANNEL_5_6;
+ else
+ channel = I2S_CHANNEL_7_8;
+
+ switch (audio->rate) {
+ case HDMI_AUDIO_FS_32000:
+ mclk_fs = FS_64;
+ rate = AUDIO_32K;
+ if (hdmi_dev->tmdsclk >= 594000000)
+ N = N_32K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_32K_MIDCLK;
+ else
+ N = N_32K_LOWCLK;
+ /*div a num to avoid the value is exceed 2^32(int)*/
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 32);
+ break;
+ case HDMI_AUDIO_FS_44100:
+ mclk_fs = FS_64;
+ rate = AUDIO_441K;
+ if (hdmi_dev->tmdsclk >= 594000000)
+ N = N_441K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_441K_MIDCLK;
+ else
+ N = N_441K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 441);
+ break;
+ case HDMI_AUDIO_FS_48000:
+ mclk_fs = FS_64;
+ rate = AUDIO_48K;
+ if (hdmi_dev->tmdsclk >= 594000000) /*FS_153.6*/
+ N = N_48K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_48K_MIDCLK;
+ else
+ N = N_48K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 48);
+ break;
+ case HDMI_AUDIO_FS_88200:
+ mclk_fs = FS_64;
+ rate = AUDIO_882K;
+ if (hdmi_dev->tmdsclk >= 594000000)
+ N = N_882K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_882K_MIDCLK;
+ else
+ N = N_882K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 882);
+ break;
+ case HDMI_AUDIO_FS_96000:
+ mclk_fs = FS_64;
+ rate = AUDIO_96K;
+ if (hdmi_dev->tmdsclk >= 594000000) /*FS_153.6*/
+ N = N_96K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_96K_MIDCLK;
+ else
+ N = N_96K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 96);
+ break;
+ case HDMI_AUDIO_FS_176400:
+ mclk_fs = FS_64;
+ rate = AUDIO_1764K;
+ if (hdmi_dev->tmdsclk >= 594000000)
+ N = N_1764K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_1764K_MIDCLK;
+ else
+ N = N_1764K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/100, 1764);
+ break;
+ case HDMI_AUDIO_FS_192000:
+ mclk_fs = FS_64;
+ rate = AUDIO_192K;
+ if (hdmi_dev->tmdsclk >= 594000000) /*FS_153.6*/
+ N = N_192K_HIGHCLK;
+ else if (hdmi_dev->tmdsclk >= 297000000)
+ N = N_192K_MIDCLK;
+ else
+ N = N_192K_LOWCLK;
+
+ CTS = CALC_CTS(N, hdmi_dev->tmdsclk/1000, 192);
+ break;
+ default:
+ dev_err(hdmi_dev->hdmi->dev,
+ "[%s] not support such sample rate %d\n",
+ __func__, audio->rate);
+ return -ENOENT;
+ }
+
+ switch (audio->word_length) {
+ case HDMI_AUDIO_WORD_LENGTH_16bit:
+ word_length = I2S_16BIT_SAMPLE;
+ break;
+ case HDMI_AUDIO_WORD_LENGTH_20bit:
+ word_length = I2S_20BIT_SAMPLE;
+ break;
+ case HDMI_AUDIO_WORD_LENGTH_24bit:
+ word_length = I2S_24BIT_SAMPLE;
+ break;
+ default:
+ word_length = I2S_16BIT_SAMPLE;
+ }
+
+ HDMIDBG("rate = %d, tmdsclk = %u, N = %d, CTS = %d\n",
+ audio->rate, hdmi_dev->tmdsclk, N, CTS);
+ /* more than 2 channels => layout 1 else layout 0 */
+ hdmi_msk_reg(hdmi_dev, FC_AUDSCONF,
+ m_AUD_PACK_LAYOUT,
+ v_AUD_PACK_LAYOUT((audio->channel > 2) ? 1 : 0));
+
+ if (hdmi_dev->audiosrc == HDMI_AUDIO_SRC_IIS) {
+ hdmi_msk_reg(hdmi_dev, AUD_CONF0,
+ m_I2S_SEL, v_I2S_SEL(AUDIO_SPDIF_GPA));
+ hdmi_msk_reg(hdmi_dev, AUD_SPDIF1,
+ m_SET_NLPCM | m_SPDIF_WIDTH,
+ v_SET_NLPCM(PCM_LINEAR) |
+ v_SPDIF_WIDTH(word_length));
+ /*Mask fifo empty and full int and reset fifo*/
+ hdmi_msk_reg(hdmi_dev, AUD_SPDIFINT,
+ m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK,
+ v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
+ hdmi_msk_reg(hdmi_dev, AUD_SPDIF0,
+ m_SW_SAUD_FIFO_RST, v_SW_SAUD_FIFO_RST(1));
+ } else {
+ /*Mask fifo empty and full int and reset fifo*/
+ hdmi_msk_reg(hdmi_dev, AUD_INT,
+ m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK,
+ v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
+ hdmi_msk_reg(hdmi_dev, AUD_CONF0,
+ m_SW_AUD_FIFO_RST, v_SW_AUD_FIFO_RST(1));
+ hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0xF7);
+ usleep_range(90, 100);
+ hdmi_msk_reg(hdmi_dev, AUD_CONF0,
+ m_I2S_SEL | m_I2S_IN_EN,
+ v_I2S_SEL(AUDIO_I2S) | v_I2S_IN_EN(channel));
+ hdmi_writel(hdmi_dev, AUD_CONF1,
+ v_I2S_MODE(I2S_STANDARD_MODE) |
+ v_I2S_WIDTH(word_length));
+ }
+
+ hdmi_msk_reg(hdmi_dev, AUD_INPUTCLKFS,
+ m_LFS_FACTOR, v_LFS_FACTOR(mclk_fs));
+
+ /*Set N value*/
+ hdmi_msk_reg(hdmi_dev, AUD_N3, m_NCTS_ATOMIC_WR, v_NCTS_ATOMIC_WR(1));
+ /*Set CTS by manual*/
+ hdmi_msk_reg(hdmi_dev, AUD_CTS3,
+ m_N_SHIFT | m_CTS_MANUAL | m_AUD_CTS3,
+ v_N_SHIFT(N_SHIFT_1) |
+ v_CTS_MANUAL(1) |
+ v_AUD_CTS3(CTS >> 16));
+ hdmi_writel(hdmi_dev, AUD_CTS2, (CTS >> 8) & 0xff);
+ hdmi_writel(hdmi_dev, AUD_CTS1, CTS & 0xff);
+
+ hdmi_msk_reg(hdmi_dev, AUD_N3, m_AUD_N3, v_AUD_N3(N >> 16));
+ hdmi_writel(hdmi_dev, AUD_N2, (N >> 8) & 0xff);
+ hdmi_writel(hdmi_dev, AUD_N1, N & 0xff);
+
+ /* set channel status register */
+ hdmi_msk_reg(hdmi_dev, FC_AUDSCHNLS7,
+ m_AUDIO_SAMPLE_RATE, v_AUDIO_SAMPLE_RATE(rate));
+ /* hdmi_writel(hdmi_dev, FC_AUDSCHNLS2, 0x1); */
+ /* hdmi_writel(hdmi_dev, FC_AUDSCHNLS8, ((~rate) << 4) | 0x2); */
+
+ hdmi_dev_config_aai(hdmi_dev, audio);
+
+ return 0;
+}
+
+static int hdmi_dev_control_output(struct hdmi *hdmi, int enable)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("[%s] %d\n", __func__, enable);
+
+ if (enable == HDMI_AV_UNMUTE) {
+ hdmi_writel(hdmi_dev, FC_DBGFORCE, 0x00);
+ hdmi_msk_reg(hdmi_dev, FC_GCP,
+ m_FC_SET_AVMUTE | m_FC_CLR_AVMUTE,
+ v_FC_SET_AVMUTE(0) | v_FC_CLR_AVMUTE(1));
+ } else {
+ if (enable & HDMI_VIDEO_MUTE) {
+ hdmi_msk_reg(hdmi_dev, FC_DBGFORCE,
+ m_FC_FORCEVIDEO, v_FC_FORCEVIDEO(1));
+ hdmi_msk_reg(hdmi_dev, FC_GCP,
+ m_FC_SET_AVMUTE | m_FC_CLR_AVMUTE,
+ v_FC_SET_AVMUTE(1) | v_FC_CLR_AVMUTE(0));
+ }
+/* if (enable & HDMI_AUDIO_MUTE) {
+ hdmi_msk_reg(hdmi_dev, FC_AUDSCONF,
+ m_AUD_PACK_SAMPFIT,
+ v_AUD_PACK_SAMPFIT(0x0F));
+ }
+*/ if (enable == (HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE)) {
+ msleep(100);
+ rockchip_hdmiv2_powerdown(hdmi_dev);
+ hdmi_dev->tmdsclk = 0;
+/*
+ hdmi_msk_reg(hdmi_dev, PHY_CONF0,
+ m_PDDQ_SIG | m_TXPWRON_SIG,
+ v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
+ hdmi_writel(hdmi_dev, MC_CLKDIS, 0x7f);
+*/ }
+ }
+ return 0;
+}
+
+static int hdmi_dev_insert(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("%s\n", __func__);
+ hdmi_writel(hdmi_dev, MC_CLKDIS, m_HDCPCLK_DISABLE);
+ return HDMI_ERROR_SUCESS;
+}
+
+static int hdmi_dev_remove(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("%s\n", __func__);
+ rockchip_hdmiv2_powerdown(hdmi_dev);
+ hdmi_dev->tmdsclk = 0;
+ return HDMI_ERROR_SUCESS;
+}
+
+static int hdmi_dev_enable(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("%s\n", __func__);
+ if (!hdmi_dev->enable) {
+ hdmi_writel(hdmi_dev, IH_MUTE, 0x00);
+ hdmi_dev->enable = 1;
+ }
+ hdmi_submit_work(hdmi, HDMI_HPD_CHANGE, 10, NULL);
+ return 0;
+}
+
+static int hdmi_dev_disable(struct hdmi *hdmi)
+{
+ struct hdmi_dev *hdmi_dev = hdmi->property->priv;
+
+ HDMIDBG("%s\n", __func__);
+ if (hdmi_dev->enable) {
+ hdmi_dev->enable = 0;
+ hdmi_writel(hdmi_dev, IH_MUTE, 0x1);
+ }
+ return 0;
+}
+
+void rockchip_hdmiv2_dev_init_ops(struct hdmi_ops *ops)
+{
+ if (ops) {
+ ops->enable = hdmi_dev_enable;
+ ops->disable = hdmi_dev_disable;
+ ops->getstatus = hdmi_dev_detect_hotplug;
+ ops->insert = hdmi_dev_insert;
+ ops->remove = hdmi_dev_remove;
+ ops->getedid = hdmi_dev_read_edid;
+ ops->setvideo = hdmi_dev_config_video;
+ ops->setaudio = hdmi_dev_config_audio;
+ ops->setmute = hdmi_dev_control_output;
+ ops->setvsi = hdmi_dev_config_vsi;
+ }
+}
+
+void rockchip_hdmiv2_dev_initial(struct hdmi_dev *hdmi_dev)
+{
+ struct hdmi *hdmi = hdmi_dev->hdmi;
+
+ if (!hdmi->uboot) {
+ /* reset hdmi */
+ if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
+ writel_relaxed((1 << 9) | (1 << 25),
+ RK_CRU_VIRT + 0x01d4);
+ udelay(1);
+ writel_relaxed((0 << 9) | (1 << 25),
+ RK_CRU_VIRT + 0x01d4);
+ } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
+ pr_info("reset hdmi\n");
+ regmap_write(hdmi_dev->grf_base, 0x031c,
+ (1 << 9) | (1 << 25));
+ udelay(5);
+ regmap_write(hdmi_dev->grf_base, 0x031c,
+ (0 << 9) | (1 << 25));
+ }
+ rockchip_hdmiv2_powerdown(hdmi_dev);
+ }
+ /*mute unnecessary interrrupt, only enable hpd*/
+ hdmi_writel(hdmi_dev, IH_MUTE_FC_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_FC_STAT1, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_FC_STAT2, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_AS_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_PHY_STAT0, 0xfe);
+ hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_CEC_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_VP_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_I2CMPHY_STAT0, 0xff);
+ hdmi_writel(hdmi_dev, IH_MUTE_AHBDMAAUD_STAT0, 0xff);
+
+ /* disable hdcp interrup */
+ hdmi_writel(hdmi_dev, A_APIINTMSK, 0xff);
+ hdmi_writel(hdmi_dev, PHY_MASK, 0xf1);
+
+ if (hdmi->property->feature & SUPPORT_CEC)
+ rockchip_hdmiv2_cec_init(hdmi);
+ if (hdmi->property->feature & SUPPORT_HDCP)
+ rockchip_hdmiv2_hdcp_init(hdmi);
+}
+
+irqreturn_t rockchip_hdmiv2_dev_irq(int irq, void *priv)
+{
+ struct hdmi_dev *hdmi_dev = priv;
+ struct hdmi *hdmi = hdmi_dev->hdmi;
+ char phy_pol = hdmi_readl(hdmi_dev, PHY_POL0);
+ char phy_status = hdmi_readl(hdmi_dev, PHY_STAT0);
+ char phy_int0 = hdmi_readl(hdmi_dev, PHY_INI0);
+ /*read interrupt*/
+ char fc_stat0 = hdmi_readl(hdmi_dev, IH_FC_STAT0);
+ char fc_stat1 = hdmi_readl(hdmi_dev, IH_FC_STAT1);
+ char fc_stat2 = hdmi_readl(hdmi_dev, IH_FC_STAT2);
+ char aud_int = hdmi_readl(hdmi_dev, IH_AS_SATA0);
+ char phy_int = hdmi_readl(hdmi_dev, IH_PHY_STAT0);
+ char vp_stat0 = hdmi_readl(hdmi_dev, IH_VP_STAT0);
+ char cec_int = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
+ char hdcp_int = hdmi_readl(hdmi_dev, A_APIINTSTAT);
+ char hdcp2_int = hdmi_readl(hdmi_dev, HDCP2REG_STAT);
+
+ /*clear interrupt*/
+ hdmi_writel(hdmi_dev, IH_FC_STAT0, fc_stat0);
+ hdmi_writel(hdmi_dev, IH_FC_STAT1, fc_stat1);
+ hdmi_writel(hdmi_dev, IH_FC_STAT2, fc_stat2);
+ hdmi_writel(hdmi_dev, IH_VP_STAT0, vp_stat0);
+
+ if (phy_int0 || phy_int) {
+ phy_pol = (phy_int0 & (~phy_status)) | ((~phy_int0) & phy_pol);
+ hdmi_writel(hdmi_dev, PHY_POL0, phy_pol);
+ hdmi_writel(hdmi_dev, IH_PHY_STAT0, phy_int);
+ if ((phy_int & m_HPD) || ((phy_int & 0x3c) == 0x3c))
+ hdmi_submit_work(hdmi, HDMI_HPD_CHANGE, 20, NULL);
+ }
+
+ /* Audio error */
+ if (aud_int) {
+ hdmi_writel(hdmi_dev, IH_AS_SATA0, aud_int);
+ hdmi_msk_reg(hdmi_dev, AUD_CONF0,
+ m_SW_AUD_FIFO_RST, v_SW_AUD_FIFO_RST(1));
+ hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0xF7);
+ }
+ /* CEC */
+ if (cec_int) {
+ hdmi_writel(hdmi_dev, IH_CEC_STAT0, cec_int);
+ rockchip_hdmiv2_cec_isr(hdmi_dev, cec_int);
+ }
+ /* HDCP */
+ if (hdcp_int) {
+ hdmi_writel(hdmi_dev, A_APIINTCLR, hdcp_int);
+ pr_info("hdcp_int is 0x%02x\n", hdcp_int);
+ }
+
+ /* HDCP2 */
+ if (hdcp2_int) {
+ hdmi_writel(hdmi_dev, HDCP2REG_STAT, hdcp2_int);
+ pr_info("hdcp2_int is 0x%02x\n", hdcp2_int);
+ }
+ return IRQ_HANDLED;
+}
--- /dev/null
+#ifndef _RK3288_HDMI_HW_H
+#define _RK3288_HDMI_HW_H
+#include <linux/interrupt.h>
+#include "../rockchip-hdmi.h"
+
+/*#define HDMI_INT_USE_POLL 1*/
+
+enum PWR_MODE {
+ NORMAL,
+ LOWER_PWR,
+};
+
+enum {
+ OUTPUT_DVI = 0,
+ OUTPUT_HDMI,
+};
+
+/* Color Space Convertion Mode */
+enum {
+ CSC_RGB_0_255_TO_RGB_16_235_8BIT, /* RGB 0-255 input to RGB
+ 16-235 output that is 8bit
+ clolor depth */
+ CSC_RGB_0_255_TO_RGB_16_235_10BIT, /* RGB 0-255 input to RGB
+ 16-235 output that is 8bit
+ clolor depth */
+ CSC_RGB_0_255_TO_ITU601_16_235_8BIT, /* RGB 0-255 input to YCbCr
+ 16-235 output according
+ BT601 that is 8bit clolor
+ depth */
+ CSC_RGB_0_255_TO_ITU601_16_235_10BIT, /* RGB 0-255 input to YCbCr
+ 16-235 output according
+ BT601 that is 10bit clolor
+ depth */
+ CSC_RGB_0_255_TO_ITU709_16_235_8BIT, /* RGB 0-255 input to YCbCr
+ 16-235 output accroding
+ BT709 that is 8bit clolor
+ depth */
+ CSC_RGB_0_255_TO_ITU709_16_235_10BIT, /* RGB 0-255 input to YCbCr
+ 16-235 output accroding
+ BT709 that is 10bit clolor
+ depth */
+ CSC_ITU601_16_235_TO_RGB_16_235_8BIT, /* YCbCr 16-235 input to RGB
+ 16-235 output according
+ BT601 that is 8bit clolor
+ depth */
+ CSC_ITU709_16_235_TO_RGB_16_235_8BIT, /* YCbCr 16-235 input to RGB
+ 16-235 output according
+ BT709 that is 8bit clolor
+ depth */
+ CSC_ITU601_16_235_TO_RGB_0_255_8BIT, /* YCbCr 16-235 input to RGB
+ 0-255 output according
+ BT601 that is 8bit clolor
+ depth */
+ CSC_ITU709_16_235_TO_RGB_0_255_8BIT /* YCbCr 16-235 input to RGB
+ 0-255 output according
+ BT709 that is 8bit clolor
+ depth */
+};
+
+#define HDMI_SCL_RATE (100*1000)
+#define DDC_I2C_EDID_ADDR 0x50 /* 0xA0/2 = 0x50 */
+#define DDC_I2C_SEG_ADDR 0x30 /* 0x60/2 = 0x30 */
+#define DDC_I2C_SCDC_ADDR 0x54 /* 0xa8/2 = 0x54 */
+
+/* Register and Field Descriptions */
+/* Identification Registers */
+#define IDENTIFICATION_BASE 0x0000
+
+#define DESIGN_ID 0x0000
+#define REVISION_ID 0x0001
+#define PRODUCT_ID0 0x0002
+#define PRODUCT_ID1 0x0003
+
+#define CONFIG0_ID 0x0004
+#define m_PREPEN (1 << 7)
+#define m_AUDSPDIF (1 << 5)
+#define m_AUDI2S (1 << 4)
+#define m_HDMI14 (1 << 3)
+#define m_CSC (1 << 2)
+#define m_CEC (1 << 1)
+#define m_HDCP (1 << 0)
+
+#define CONFIG1_ID 0x0005
+#define m_HDMI20 (1 << 5)
+#define m_CONFAPB (1 << 1)
+
+#define CONFIG2_ID 0x0006
+enum PHYTYPE {
+ HDMI_TX_PHY = 0x00,
+ HDMI_MHL_WITH_HEAC_PHY = 0xb2,
+ HDMI_MHL_PHY = 0xc2,
+ HDMI_3D_TX_WITH_HEAC_PHY = 0xe2,
+ HDMI_3D_TX_PHY = 0xf2,
+ HDMI2_TX_PHY = 0xf3
+};
+
+#define CONFIG3_ID 0x0007
+#define m_AHB_AUD_DMA (1 << 1)
+#define m_GP_AUD (1 << 0)
+
+/* Interrupt Registers */
+#define INTERRUPT_BASE 0x0100
+
+#define IH_FC_STAT0 0x0100
+#define m_AUD_INFOFRAME (1 << 7)
+#define m_AUD_CONTENT_PROTECT (1 << 6)
+#define m_AUD_HBR (1 << 5)
+#define m_AUD_SAMPLE (1 << 2)
+#define m_AUD_CLK_REGEN (1 << 1)
+#define m_NULL_PACKET (1 << 0)
+
+#define IH_FC_STAT1 0x0101
+#define m_GMD (1 << 7)
+#define m_ISCR1 (1 << 6)
+#define m_ISCR2 (1 << 5)
+#define m_VSD (1 << 4)
+#define m_SPD (1 << 3)
+#define m_AVI_INFOFRAME (1 << 1)
+#define m_GCP (1 << 0)
+
+#define IH_FC_STAT2 0x0102
+#define m_LOWPRIO_OVERFLOW (1 << 1)
+#define m_HIGHPRIO_OVERFLOW (1 << 0)
+
+#define IH_AS_SATA0 0x0103
+#define m_FIFO_UNDERRUN (1 << 4)
+#define m_FIFO_OVERRUN (1 << 3)
+#define m_AUD_FIFO_UDFLOW_THR (1 << 2)
+#define m_AUD_FIFO_UDFLOW (1 << 1)
+#define m_AUD_FIFO_OVERFLOW (1 << 0)
+
+#define IH_PHY_STAT0 0x0104
+#define m_RX_SENSE3 (1 << 5)
+#define m_RX_SENSE2 (1 << 4)
+#define m_RX_SENSE1 (1 << 3)
+#define m_RX_SENSE0 (1 << 2)
+#define m_TX_PHY_LOCK (1 << 1)
+#define m_HPD (1 << 0)
+
+#define IH_I2CM_STAT0 0x0105
+#define m_SCDC_READREQ (1 << 2)
+#define m_I2CM_DONE (1 << 1)
+#define m_I2CM_ERROR (1 << 0)
+
+#define IH_CEC_STAT0 0x0106
+#define m_WAKEUP (1 << 6)
+#define m_ERR_FOLLOW (1 << 5)
+#define m_ERR_INITIATOR (1 << 4)
+#define m_ARB_LOST (1 << 3)
+#define m_NACK (1 << 2)
+#define m_EOM (1 << 1)
+#define m_DONE (1 << 0)
+
+#define IH_VP_STAT0 0x0107
+#define m_FIFOFULL_REPET (1 << 7)
+#define m_FIFOEMPTY_REPET (1 << 6)
+#define m_FIFOFULL_PACK (1 << 5)
+#define m_FIFOEMPTY_PACK (1 << 4)
+#define m_FIFOFULL_REMAP (1 << 3)
+#define m_FIFOEMPTY_REMAP (1 << 2)
+#define m_FIFOFULL_BYPASS (1 << 1)
+#define m_FIFOEMPTY_BYPASS (1 << 0)
+
+#define IH_I2CMPHY_STAT0 0x0108
+#define m_I2CMPHY_DONE (1 << 1)
+#define m_I2CMPHY_ERR (1 << 0)
+
+#define IH_AHBDMAAUD_STAT0 0x0109
+#define m_AUDDMA_INT_BUFOVERRUN (1 << 6)
+#define m_AUDDMA_INT_ERR (1 << 5)
+#define m_AUDDMA_INT_LOST (1 << 4)
+#define m_AUDDMA_INT_RETRYSPLIT (1 << 3)
+#define m_AUDDMA_INT_DONE (1 << 2)
+#define m_AUDDMA_INT_BUFFULL (1 << 1)
+#define m_AUDDMA_INT_BUFEMPTY (1 << 0)
+
+#define IH_DECODE 0x0170
+#define m_IH_FC_STAT0 (1 << 7)
+#define m_IH_FC_STAT1 (1 << 6)
+#define m_IH_FC_STAT2_VP (1 << 5)
+#define m_IH_AS_STAT0 (1 << 4)
+#define m_IH_PHY (1 << 3)
+#define m_IH_I2CM_STAT0 (1 << 2)
+#define m_IH_CEC_STAT0 (1 << 1)
+#define m_IH_AHBDMAAUD_STAT0 (1 << 0)
+
+#define IH_MUTE_FC_STAT0 0x0180
+#define m_AUDI_MUTE (1 << 7)
+#define m_ACP_MUTE (1 << 6)
+#define m_DST_MUTE (1 << 4)
+#define m_OBA_MUTE (1 << 3)
+#define m_AUDS_MUTE (1 << 2)
+#define m_ACR_MUTE (1 << 1)
+#define m_NULL_MUTE (1 << 0)
+
+#define IH_MUTE_FC_STAT1 0x0181
+#define m_GMD_MUTE (1 << 7)
+#define m_ISCR1_MUTE (1 << 6)
+#define m_ISCR2_MUTE (1 << 5)
+#define m_VSD_MUTE (1 << 4)
+#define m_SPD_MUTE (1 << 3)
+#define m_AVI_MUTE (1 << 1)
+#define m_GCP_MUTE (1 << 0)
+
+#define IH_MUTE_FC_STAT2 0x0182
+#define m_LPRIO_OVERFLOW_MUTE (1 << 1)
+#define m_HPRIO_OVERFLOW_MUTE (1 << 0)
+
+#define IH_MUTE_AS_STAT0 0x0183
+#define m_FIFO_UNDERRUN_MUTE (1 << 4)
+#define m_FIFO_OVERRUN_MUTE (1 << 3)
+#define m_AUD_FIFO_UDF_THR_MUTE (1 << 2)
+#define m_AUD_FIFO_UDF_MUTE (1 << 1)
+#define m_AUD_FIFO_OVF_MUTE (1 << 0)
+
+#define IH_MUTE_PHY_STAT0 0x0184
+#define m_RX_SENSE3_MUTE (1 << 5)
+#define m_RX_SENSE2_MUTE (1 << 4)
+#define m_RX_SENSE1_MUTE (1 << 3)
+#define m_RX_SENSE0_MUTE (1 << 2)
+#define m_TX_PHY_LOCK_MUTE (1 << 1)
+#define m_HPD_MUTE (1 << 0)
+
+#define IH_MUTE_I2CM_STAT0 0x0185
+#define m_SCDC_READREQ_MUTE (1 << 2)
+#define v_SCDC_READREQ_MUTE(n) (((n)&0x01) << 2)
+#define m_I2CM_DONE_MUTE (1 << 1)
+#define v_I2CM_DONE_MUTE(n) (((n)&0x01) << 1)
+#define m_I2CM_ERR_MUTE (1 << 0)
+#define v_I2CM_ERR_MUTE(n) (((n)&0x01) << 0)
+
+#define IH_MUTE_CEC_STAT0 0x0186
+#define m_WAKEUP_MUTE (1 << 6)
+#define m_ERR_FOLLOW_MUTE (1 << 5)
+#define m_ERR_INITIATOR_MUTE (1 << 4)
+#define m_ARB_LOST_MUTE (1 << 3)
+#define m_NACK_MUTE (1 << 2)
+#define m_EOM_MUTE (1 << 1)
+#define m_DONE_MUTE (1 << 0)
+
+#define IH_MUTE_VP_STAT0 0x0187
+#define m_FIFOFULL_REP_MUTE (1 << 7)
+#define m_FIFOEMPTY_REP_MUTE (1 << 6)
+#define m_FIFOFULL_PACK_MUTE (1 << 5)
+#define m_FIFOEMPTY_PACK_MUTE (1 << 4)
+#define m_FIFOFULL_REMAP_MUTE (1 << 3)
+#define m_FIFOEMPTY_REMAP_MUTE (1 << 2)
+#define m_FIFOFULL_BYP_MUTE (1 << 1)
+#define m_FIFOEMPTY_BYP_MUTE (1 << 0)
+
+#define IH_MUTE_I2CMPHY_STAT0 0x0188
+#define m_I2CMPHY_DONE_MUTE (1 << 1)
+#define m_I2CMPHY_ERR_MUTE (1 << 0)
+
+#define IH_MUTE_AHBDMAAUD_STAT0 0x0189
+#define IH_MUTE 0x01ff
+
+/* Video Sampler Registers */
+#define VIDEO_SAMPLER_BASE 0x0200
+
+#define TX_INVID0 0x0200
+#define m_INTERNAL_DE_GEN (1 << 7)
+#define v_INTERNAL_DE_GEN(n) (((n)&0x01) << 7)
+enum VIDEO_MODE {
+ VIDEO_RGB444_8BIT = 0x01,
+ VIDEO_RGB444_10BIT = 0x03,
+ VIDEO_RGB444_12BIT = 0x05,
+ VIDEO_RGB444_16BIT = 0x07,
+ VIDEO_YCBCR444_8BIT = 0x09, /* or YCbCr420 */
+ VIDEO_YCBCR444_10BIT = 0x0b, /* or YCbCr420 */
+ VIDEO_YCBCR444_12BIT = 0x0d, /* or YCbCr420 */
+ VIDEO_YCBCR444_16BIT = 0x0f, /* or YCbCr420 */
+ VIDEO_YCBCR422_12BIT = 0x12,
+ VIDEO_YCBCR422_10BIT = 0x14,
+ VIDEO_YCBCR422_8BIT = 0x16
+};
+#define m_VIDEO_MAPPING (0x1f << 0)
+#define v_VIDEO_MAPPING(n) ((n)&0x1f)
+
+#define TX_INSTUFFING 0x0201
+#define m_BCBDATA_STUFF (1 << 2)
+#define v_BCBDATA_STUFF(n) (((n)&0x01) << 2)
+#define m_RCRDATA_STUFF (1 << 1)
+#define v_RCRDATA_STUFF(n) (((n)&0x01) << 1)
+#define m_GYDATA_STUFF (1 << 0)
+#define v_GYDATA_STUFF(n) (((n)&0x01) << 0)
+
+#define TX_GYDATA0 0x0202
+#define TX_GYDATA1 0x0203
+#define TX_RCRDATA0 0x0204
+#define TX_RCRDATA1 0x0205
+#define TX_BCBDATA0 0x0206
+#define TX_BCBDATA1 0x0207
+
+/* Video Packetizer Registers */
+#define VIDEO_PACKETIZER_BASE 0x0800
+
+#define VP_STATUS 0x0800
+#define m_PACKING_PHASE (0x0f << 0)
+
+#define VP_PR_CD 0x0801
+enum COLOR_DEPTH {
+ COLOR_DEPTH_24BIT_DEFAULT = 0,
+ COLOR_DEPTH_24BIT = 0x04,
+ COLOR_DEPTH_30BIT,
+ COLOR_DEPTH_36BIT,
+ COLOR_DEPTH_48BIT
+};
+#define m_COLOR_DEPTH (0x0f << 4)
+#define v_COLOR_DEPTH(n) (((n)&0x0f) << 4)
+enum PIXEL_REPET {
+ NO_PIXEL_REPET = 0,
+ PIXEL_SENT_2TIMES,
+ PIXEL_SENT_3TIMES,
+ PIXEL_SENT_4TIMES,
+ PIXEL_SENT_5TIMES,
+ PIXEL_SENT_6TIMES,
+ PIXEL_SENT_7TIMES,
+ PIXEL_SENT_8TIMES,
+ PIXEL_SENT_9TIMES,
+ PIXEL_SENT_10TIMES
+};
+#define m_DESIRED_PR_FACTOR (0x0f << 0)
+#define v_DESIRED_PR_FACTOR(n) (((n)&0x0f) << 0)
+
+#define VP_STUFF 0x0802
+#define m_IDEFAULT_PHASE (1 << 5)
+#define v_IDEFAULT_PHASE(n) (((n)&0x01) << 5)
+#define m_IFIX_PP_TO_LAST (1 << 4)
+#define m_ICX_GOTO_P0_ST (1 << 3)
+enum {
+ DIRECT_MODE = 0,
+ STUFFING_MODE
+};
+#define m_YCC422_STUFFING (1 << 2)
+#define v_YCC422_STUFFING(n) (((n)&0x01) << 2)
+#define m_PP_STUFFING (1 << 1)
+#define v_PP_STUFFING(n) (((n)&0x01) << 1)
+#define m_PR_STUFFING (1 << 0)
+#define v_PR_STUFFING(n) (((n)&0x01) << 0)
+
+#define VP_REMAP 0x0803
+enum YCC422_SIZE {
+ YCC422_16BIT = 0,
+ YCC422_20BIT,
+ YCC422_24BIT
+};
+#define m_YCC422_SIZE (0x03 << 0)
+#define v_YCC422_SIZE(n) (((n)&0x03) << 0)
+
+#define VP_CONF 0x0804
+#define m_BYPASS_EN (1 << 6)
+#define v_BYPASS_EN(n) (((n)&0x01) << 6)
+#define m_PIXEL_PACK_EN (1 << 5)
+#define v_PIXEL_PACK_EN(n) (((n)&0x01) << 5)
+#define m_PIXEL_REPET_EN (1 << 4)
+#define v_PIXEL_REPET_EN(n) (((n)&0x01) << 4)
+#define m_YCC422_EN (1 << 3)
+#define v_YCC422_EN(n) (((n)&0x01) << 3)
+#define m_BYPASS_SEL (1 << 2)
+#define v_BYPASS_SEL(n) (((n)&0x01) << 2)
+enum {
+ OUT_FROM_PIXEL_PACKING = 0,
+ OUT_FROM_YCC422_REMAP,
+ OUT_FROM_8BIT_BYPASS
+};
+#define m_OUTPUT_SEL (0x03 << 0)
+#define v_OUTPUT_SEL(n) ((n&0x03) << 0)
+
+#define VP_MASK 0x0807
+#define m_OINTFULL_REPET (1 << 7)
+#define m_OINTEMPTY_REPET (1 << 6)
+#define m_OINTFULL_PACK (1 << 5)
+#define m_OINTEMPTY_PACK (1 << 4)
+#define m_OINTFULL_REMAP (1 << 3)
+#define m_OINTEMPTY_REMAP (1 << 2)
+#define m_OINTFULL_BYPASS (1 << 1)
+#define m_OINTEMPTY_BYPASS (1 << 0)
+
+/* Frame Composer Registers */
+#define FRAME_COMPOSER_BASE 0x1000
+
+#define FC_INVIDCONF 0x1000
+#define m_FC_HDCP_KEEPOUT (1 << 7)
+#define v_FC_HDCP_KEEPOUT(n) (((n)&0x01) << 7)
+#define m_FC_VSYNC_POL (1 << 6)
+#define v_FC_VSYNC_POL(n) (((n)&0x01) << 6)
+#define m_FC_HSYNC_POL (1 << 5)
+#define v_FC_HSYNC_POL(n) (((n)&0x01) << 5)
+#define m_FC_DE_POL (1 << 4)
+#define v_FC_DE_POL(n) (((n)&0x01) << 4)
+#define m_FC_HDMI_DVI (1 << 3)
+#define v_FC_HDMI_DVI(n) (((n)&0x01) << 3)
+#define m_FC_VBLANK (1 << 1)
+#define v_FC_VBLANK(n) (((n)&0x01) << 1)
+#define m_FC_INTERLACE_MODE (1 << 0)
+#define v_FC_INTERLACE_MODE(n) (((n)&0x01) << 0)
+
+#define FC_INHACTIV0 0x1001
+
+#define FC_INHACTIV1 0x1002
+#define v_FC_HACTIVE1(n) ((n) & 0x3f)
+#define m_FC_H_ACTIVE_13 (1 << 5)
+#define v_FC_H_ACTIVE_13(n) (((n)&0x01) << 5)
+#define m_FC_H_ACTIVE_12 (1 << 4)
+#define v_FC_H_ACTIVE_12(n) (((n)&0x01) << 4)
+#define m_FC_H_ACTIVE (0x0f << 0)
+#define v_FC_H_ACTIVE(n) (((n)&0x0f) << 0)
+
+#define FC_INHBLANK0 0x1003
+
+#define FC_INHBLANK1 0x1004
+#define v_FC_HBLANK1(n) ((n) & 0x1f)
+#define m_FC_H_BLANK_12_11 (0x07 << 2)
+#define v_FC_H_BLANK_12_11(n) (((n)&0x07) << 2)
+#define m_FC_H_BLANK (0x03 << 0)
+#define v_FC_H_BLANK(n) (((n)&0x03) << 0)
+
+#define FC_INVACTIV0 0x1005
+
+#define FC_INVACTIV1 0x1006
+#define v_FC_VACTIVE1(n) ((n) & 0x1f)
+#define m_FC_V_ACTIVE_12_11 (0x03 << 3)
+#define v_FC_V_ACTIVE_12_11(n) (((n)&0x03) << 3)
+#define m_FC_V_ACTIVE (0x07 << 0)
+#define v_FC_V_ACTIVE(n) (((n)&0x07) << 0)
+
+#define FC_INVBLANK 0x1007
+#define FC_HSYNCINDELAY0 0x1008
+
+#define FC_HSYNCINDELAY1 0x1009
+#define v_FC_HSYNCINDEAY1(n) ((n) & 0x1f)
+#define m_FC_H_SYNCFP_12_11 (0x03 << 3)
+#define v_FC_H_SYNCFP_12_11(n) (((n)&0x03) << 3)
+#define m_FC_H_SYNCFP (0x07 << 0)
+#define v_FC_H_SYNCFP(n) (((n)&0x07) << 0)
+
+#define FC_HSYNCINWIDTH0 0x100a
+
+#define FC_HSYNCINWIDTH1 0x100b
+#define v_FC_HSYNCWIDTH1(n) ((n) & 0x03)
+#define m_FC_HSYNC_9 (1 << 1)
+#define v_FC_HSYNC_9(n) (((n)&0x01) << 1)
+#define m_FC_HSYNC (1 << 0)
+#define v_FC_HSYNC(n) (((n)&0x01) << 0)
+
+#define FC_VSYNCINDELAY 0x100c
+#define FC_VSYNCINWIDTH 0x100d
+#define FC_INFREQ0 0x100e
+#define FC_INFREQ1 0x100f
+#define FC_INFREQ2 0x1010
+#define FC_CTRLDUR 0x1011
+#define FC_EXCTRLDUR 0x1012
+#define FC_EXCTRLSPAC 0x1013
+#define FC_CH0PREAM 0x1014
+#define FC_CH1PREAM 0x1015
+#define FC_CH2PREAM 0x1016
+
+#define FC_AVICONF3 0x1017
+enum YCC_QUAN_RANGE {
+ YQ_LIMITED_RANGE = 0,
+ YQ_FULL_RANGE,
+ RESERVED,
+};
+#define m_FC_YQ (0x03 << 2)
+#define v_FC_YQ(n) (((n)&0x03) << 2)
+enum IT_CONTENT_TYPE {
+ CN_GRAPHICS = 0,
+ CN_PHOTO,
+ CN_CINEMA,
+ CN_GAME,
+};
+#define m_FC_CN (0x03 << 0)
+#define v_FC_CN(n) (((n)&0x03) << 0)
+
+#define FC_GCP 0x1018
+#define m_FC_DEFAULT_PHASE (1 << 2)
+#define v_FC_DEFAULT_PHASE(n) (((n)&0x01) << 2)
+#define m_FC_SET_AVMUTE (1 << 1)
+#define v_FC_SET_AVMUTE(n) (((n)&0x01) << 1)
+#define m_FC_CLR_AVMUTE (1 << 0)
+#define v_FC_CLR_AVMUTE(n) (((n)&0x01) << 0)
+
+enum {
+ AVI_COLOR_MODE_RGB = 0,
+ AVI_COLOR_MODE_YCBCR422,
+ AVI_COLOR_MODE_YCBCR444,
+ AVI_COLOR_MODE_YCBCR420
+};
+enum {
+ AVI_COLORIMETRY_NO_DATA = 0,
+ AVI_COLORIMETRY_SMPTE_170M,
+ AVI_COLORIMETRY_ITU709,
+ AVI_COLORIMETRY_EXTENDED
+};
+enum {
+ AVI_CODED_FRAME_ASPECT_NO_DATA,
+ AVI_CODED_FRAME_ASPECT_4_3,
+ AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+ ACTIVE_ASPECT_RATE_DEFAULT = 0x08,
+ ACTIVE_ASPECT_RATE_4_3,
+ ACTIVE_ASPECT_RATE_16_9,
+ ACTIVE_ASPECT_RATE_14_9
+};
+enum {
+ AVI_QUANTIZATION_RANGE_DEFAULT = 0,
+ AVI_QUANTIZATION_RANGE_LIMITED,
+ AVI_QUANTIZATION_RANGE_FULL
+};
+
+#define FC_AVICONF0 0x1019
+#define m_FC_RGC_YCC_2 (1 << 7) /* use for HDMI2.0 TX */
+#define v_FC_RGC_YCC_2(n) (((n)&0x01) << 7)
+#define m_FC_ACTIV_FORMAT (1 << 6)
+#define v_FC_ACTIV_FORMAT(n) (((n)&0x01) << 6)
+#define m_FC_SCAN_INFO (0x03 << 4)
+#define v_FC_SCAN_INFO(n) (((n)&0x03) << 4)
+#define m_FC_BAR_FORMAT (0x03 << 2)
+#define v_FC_BAR_FORMAT(n) (((n)&0x03) << 2)
+#define m_FC_RGC_YCC (0x03 << 0)
+#define v_FC_RGC_YCC(n) (((n)&0x03) << 0)
+
+#define FC_AVICONF1 0x101a
+#define m_FC_COLORIMETRY (0x03 << 6)
+#define v_FC_COLORIMETRY(n) (((n)&0x03) << 6)
+#define m_FC_PIC_ASPEC_RATIO (0x03 << 4)
+#define v_FC_PIC_ASPEC_RATIO(n) (((n)&0x03) << 4)
+#define m_FC_ACT_ASPEC_RATIO (0x0f << 0)
+#define v_FC_ACT_ASPEC_RATIO(n) (((n)&0x0f) << 0)
+
+#define FC_AVICONF2 0x101b
+#define m_FC_IT_CONTENT (1 << 7)
+#define v_FC_IT_CONTENT(n) (((n)&0x01) << 7)
+#define m_FC_EXT_COLORIMETRY (0x07 << 4)
+#define v_FC_EXT_COLORIMETRY(n) (((n)&0x07) << 4)
+#define m_FC_QUAN_RANGE (0x03 << 2)
+#define v_FC_QUAN_RANGE(n) (((n)&0x03) << 2)
+#define m_FC_NUN_PIC_SCALE (0x03 << 0)
+#define v_FC_NUN_PIC_SCALE(n) (((n)&0x03) << 0)
+
+#define FC_AVIVID 0x101c
+#define m_FC_AVIVID_H (1 << 7) /* use for HDMI2.0 TX */
+#define v_FC_AVIVID_H(n) (((n)&0x01) << 7)
+#define m_FC_AVIVID (0x7f << 0)
+#define v_FC_AVIVID(n) (((n)&0x7f) << 0)
+
+#define FC_AVIETB0 0x101d
+#define FC_AVIETB1 0x101e
+#define FC_AVISBB0 0x101f
+#define FC_AVISBB1 0x1020
+#define FC_AVIELB0 0x1021
+#define FC_AVIELB1 0x1022
+#define FC_AVISRB0 0x1023
+#define FC_AVISRB1 0x1024
+
+#define FC_AUDICONF0 0x1025
+#define m_FC_CHN_CNT (0x07 << 4)
+#define v_FC_CHN_CNT(n) (((n)&0x07) << 4)
+#define m_FC_CODING_TYEP (0x0f << 0)
+#define v_FC_CODING_TYEP(n) (((n)&0x0f) << 0)
+
+#define FC_AUDICONF1 0x1026
+#define m_FC_SAMPLE_SIZE (0x03 << 4)
+#define v_FC_SAMPLE_SIZE(n) (((n)&0x03) << 4)
+#define m_FC_SAMPLE_FREQ (0x07 << 0)
+#define v_FC_SAMPLE_FREQ(n) (((n)&0x07) << 0)
+
+#define FC_AUDICONF2 0x1027
+
+#define FC_AUDICONF3 0x1028
+#define m_FC_LFE_PBL (0x03 << 5) /*only use for HDMI1.4 TX*/
+#define v_FC_LFE_PBL(n) (((n)&0x03) << 5)
+#define m_FC_DM_INH (1 << 4)
+#define v_FC_DM_INH(n) (((n)&0x01) << 4)
+#define m_FC_LSV (0x0f << 0)
+#define v_FC_LSV(n) (((n)&0x0f) << 0)
+
+#define FC_VSDIEEEID2 0x1029
+#define FC_VSDSIZE 0x102a
+#define FC_VSDIEEEID1 0x1030
+#define FC_VSDIEEEID0 0x1031
+#define FC_VSDPAYLOAD0 0x1032 /* 0~23 */
+#define FC_SPDVENDORNAME0 0x104a /* 0~7 */
+#define FC_SPDPRODUCTNAME0 0x1052 /* 0~15 */
+#define FC_SPDDEVICEINF 0x1062
+
+#define FC_AUDSCONF 0x1063
+#define m_AUD_PACK_SAMPFIT (0x0f << 4)
+#define v_AUD_PACK_SAMPFIT(n) (((n)&0x0f) << 4)
+#define m_AUD_PACK_LAYOUT (1 << 0)
+#define v_AUD_PACK_LAYOUT(n) (((n)&0x01) << 0)
+
+#define FC_AUDSSTAT 0x1064
+#define FC_AUDSV 0x1065
+#define FC_AUDSU 0x1066
+#define FC_AUDSCHNLS0 0x1067 /*0~8*/
+#define FC_AUDSCHNLS1 0x1068
+#define FC_AUDSCHNLS2 0x1069
+#define FC_AUDSCHNLS3 0x106a
+#define FC_AUDSCHNLS4 0x106b
+#define FC_AUDSCHNLS5 0x106c
+#define FC_AUDSCHNLS6 0x106d
+#define FC_AUDSCHNLS7 0x106e
+#define FC_AUDSCHNLS8 0x106f
+
+enum {
+ AUDIO_32K = 0x3,
+ AUDIO_441K = 0x0,
+ AUDIO_48K = 0x2,
+ AUDIO_882K = 0x8,
+ AUDIO_96K = 0xa,
+ AUDIO_1764K = 0xc,
+ AUDIO_192K = 0xe,
+ AUDIO_768K = 0x9,
+};
+#define m_AUDIO_SAMPLE_RATE (0x0f << 0)
+#define v_AUDIO_SAMPLE_RATE(n) (((n)&0x0f) << 0)
+#define m_AUDIO_ORI_SAMPLE_RATE (0x0f << 4)
+#define v_AUDIO_ORI_SAMPLE_RATE(n) (((~n)&0x0f) << 4)
+#define m_AUDIO_WORD_LENGTH (0x0f << 0)
+#define v_AUDIO_WORD_LENGTH(n) (((n)&0x0f) << 0)
+
+#define FC_CTRLQHIGH 0x1073
+#define FC_CTRLQLOW 0x1074
+#define FC_ACP0 0x1075
+#define FC_ACP16 0x1082 /* 16~1 */
+#define FC_ISCR1_0 0x1092
+#define FC_ISCR1_16 0x1093 /* 16~1 */
+#define FC_ISCR2_15 0x10a3 /* 15~0 */
+
+#define FC_DATAUTO0 0x10b3
+#define m_SPD_AUTO (1 << 4)
+#define v_SPD_AUTO(n) (((n)&0x01) << 4)
+#define m_VSD_AUTO (1 << 3)
+#define v_VSD_AUTO(n) (((n)&0x01) << 3)
+#define m_ISCR2_AUTO (1 << 2)
+#define v_ISCR2_AUTO(n) (((n)&0x01) << 2)
+#define m_ISCR1_AUTO (1 << 1)
+#define v_ISCR1_AUTO(n) (((n)&0x01) << 1)
+#define m_ACP_AUTO (1 << 0)
+#define v_ACP_AUTO(n) (((n)&0x01) << 0)
+
+#define FC_DATAUTO1 0x10b4
+#define FC_DATAUTO2 0x10b5
+
+#define FC_DATMAN 0x10b6
+#define m_SPD_MAN (1 << 4)
+#define v_SPD_MAN(n) (((n)&0x01) << 4)
+#define m_VSD_MAN (1 << 3)
+#define v_VSD_MAN(n) (((n)&0x01) << 3)
+#define m_ISCR2_MAN (1 << 2)
+#define v_ISCR2_MAN(n) (((n)&0x01) << 2)
+#define m_ISCR1_MAN (1 << 1)
+#define v_ISCR1_MAN(n) (((n)&0x01) << 1)
+#define m_ACP_MAN (1 << 0)
+#define v_ACP_MAN(n) (((n)&0x01) << 0)
+
+#define FC_DATAUTO3 0x10b7
+ #define m_AVI_AUTO (1 << 3)
+ #define v_AVI_AUTO(n) (((n)&0x01) << 3)
+ #define m_GCP_AUTO (1 << 2)
+ #define v_GCP_AUTO(n) (((n)&0x01) << 2)
+ #define m_AAI_AUTO (1 << 1)
+ #define v_AAI_AUTO(n) (((n)&0x01) << 1)
+ #define m_ACR_AUTO (1 << 0)
+ #define v_ACR_AUTO(n) (((n)&0x01) << 0)
+#define FC_RDRB0 0x10b8
+#define FC_RDRB1 0x10b9
+#define FC_RDRB2 0x10ba
+#define FC_RDRB3 0x10bb
+#define FC_RDRB4 0x10bc
+#define FC_RDRB5 0x10bd
+#define FC_RDRB6 0x10be
+#define FC_RDRB7 0x10bf
+ #define m_AVI_PACKETS_PER_FRAME (0xf << 4)
+ #define m_AVI_PACKERS_LINE_SPACING (0xf)
+ #define v_AVI_PACKETS_PER_FRAME(n) (((n) & 0x0f) << 4)
+ #define v_AVI_PACKERS_LINE_SPACING(n) (((n) & 0x0f) << 0)
+#define FC_MASK0 0x10d2
+#define FC_MASK1 0x10d6
+#define FC_MASK2 0x10da
+
+#define FC_PRCONF 0x10e0
+#define m_FC_PR_FACTOR (0x0f << 4)
+#define v_FC_PR_FACTOR(n) (((n)&0x0f) << 4)
+
+#define FC_SCRAMBLER_CTRL 0x10e1
+#define m_FC_SCRAMBLE_UCP (1 << 4)
+#define v_FC_SCRAMBLE_UCP(n) (((n)&0x01) << 4)
+#define m_FC_SCRAMBLE_EN (1 << 0)
+#define v_FC_SCRAMBLE_EN(n) (((n)&0x01) << 0)
+
+#define FC_GMD_STAT 0x1100
+#define FC_GMD_EN 0x1101
+#define FC_GMD_UP 0x1102
+#define FC_GMD_CONF 0x1103
+#define FC_GMD_HB 0x1104
+#define FC_GMD_PB0 0x1105 /*0~27*/
+
+#define FC_DBGFORCE 0x1200
+#define m_FC_FORCEAUDIO (1 << 4)
+#define v_FC_FORCEAUDIO(n) (((n)&0x01) << 4)
+#define m_FC_FORCEVIDEO (1 << 0)
+#define v_FC_FORCEVIDEO(n) (((n)&0x01) << 0)
+
+#define FC_DBGAUD0CH0 0x1201 /* aud0~aud2 ch0 */
+#define FC_DBGAUD0CH1 0x1204 /* aud0~aud2 ch1 */
+#define FC_DBGAUD0CH2 0x1207 /* aud0~aud2 ch2 */
+#define FC_DBGAUD0CH3 0x120a /* aud0~aud2 ch3 */
+#define FC_DBGAUD0CH4 0x120d /* aud0~aud2 ch4 */
+#define FC_DBGAUD0CH5 0x1210 /* aud0~aud2 ch5 */
+#define FC_DBGAUD0CH6 0x1213 /* aud0~aud2 ch6 */
+#define FC_DBGAUD0CH7 0x1216 /* aud0~aud2 ch7 */
+#define FC_DBGTMDS0 0x1219
+#define FC_DBGTMDS1 0x121a
+#define FC_DBGTMDS2 0x121b
+
+/* HDMI Source PHY Registers */
+#define HDMI_SOURCE_PHY_BASE 0x3000
+
+#define PHY_CONF0 0x3000
+#define m_POWER_DOWN_EN (1 << 7)/* no use */
+#define v_POWER_DOWN_EN(n) (((n)&0x01) << 7)
+#define m_TMDS_EN (1 << 6)/* no use */
+#define v_TMDS_EN(n) (((n)&0x01) << 6)
+#define m_SVSRET_SIG (1 << 5)/* depend on PHY_MHL_COMB0=1 */
+#define v_SVSRET_SIG(n) (((n)&0x01) << 5)
+#define m_PDDQ_SIG (1 << 4)
+/*1: power down phy; 0: power on phy */
+#define v_PDDQ_SIG(n) (((n)&0x01) << 4)
+#define m_TXPWRON_SIG (1 << 3)
+/*1: power on transmitter; 0: power down transmitter */
+#define v_TXPWRON_SIG(n) (((n)&0x01) << 3)
+#define m_ENHPD_RXSENSE_SIG (1 << 2)
+/*1: enable detect hdp & rx sense */
+#define v_ENHPD_RXSENSE_SIG(n) (((n)&0x01) << 2)
+#define m_SEL_DATAEN_POL (1 << 1)
+#define v_SEL_DATAEN_POL(n) (((n)&0x01) << 1)
+#define m_SEL_INTERFACE (1 << 0)
+#define v_SEL_INTERFACE(n) (((n)&0x01) << 0)
+
+#define PHY_TST0 0x3001
+#define m_TEST_CLR_SIG (1 << 5)
+#define m_TEST_EN_SIG (1 << 4)
+#define m_TEST_CLK_SIG (1 << 0)
+
+#define PHY_TST1 0x3002
+#define PHY_TST2 0x3003
+#define PHY_STAT0 0x3004
+#define PHY_INI0 0x3005
+#define PHY_MASK 0x3006
+#define PHY_POL0 0x3007
+#define m_PHY_RX_SENSE3 (1 << 7)
+#define v_PHY_TX_SENSE3(n) (((n)&0x01) << 7)
+#define m_PHY_RX_SENSE2 (1 << 6)
+#define v_PHY_TX_SENSE2(n) (((n)&0x01) << 6)
+#define m_PHY_RX_SENSE1 (1 << 5)
+#define v_PHY_TX_SENSE1(n) (((n)&0x01) << 5)
+#define m_PHY_RX_SENSE0 (1 << 4)
+#define v_PHY_TX_SENSE0(n) (((n)&0x01) << 4)
+#define m_PHY_HPD (1 << 1)
+#define v_PHY_HPD (((n)&0x01) << 1)
+#define m_PHY_LOCK (1 << 0)
+#define v_PHY_LOCK(n) (((n)&0x01) << 0)
+
+#define PHY_PCLFREQ0 0x3008
+#define PHY_PCLFREQ1 0x3009
+#define PHY_PLLCFGFREQ0 0x300a
+#define PHY_PLLCFGFREQ1 0x300b
+#define PHY_PLLCFGFREQ2 0x300c
+
+/* I2C Master PHY Registers */
+#define I2C_MASTER_PHY_BASE 0x3020
+
+#define PHY_I2CM_SLAVE 0x3020
+#define PHY_GEN2_ADDR 0x69
+#define PHY_HEAC_ADDR 0x49
+#define PHY_I2C_SLAVE_ADDR 0x54
+
+#define PHY_I2CM_ADDRESS 0x3021
+#define PHY_I2CM_DATAO_1 0x3022
+#define PHY_I2CM_DATAO_0 0x3023
+#define PHY_I2CM_DATAI_1 0x3024
+#define PHY_I2CM_DATAI_0 0x3025
+
+#define PHY_I2CM_OPERATION 0x3026
+#define m_PHY_I2CM_WRITE (1 << 4)
+#define m_PHY_I2CM_READ (1 << 0)
+
+#define PHY_I2CM_INT 0x3027
+#define m_PHY_I2CM_DONE_INT_POL (1 << 3)
+#define v_PHY_I2CM_DONE_INT_POL(n) (((n)&0x01) << 3)
+#define m_PHY_I2CM_DONE_MASK (1 << 2)
+#define v_PHY_I2CM_DONE_MASK(n) (((n)&0x01) << 2)
+#define m_PHY_I2CM_DONE_INT (1 << 1)
+#define m_PHY_I2CM_DONE_STATUS (1 << 0)
+
+#define PHY_I2CM_CTLINT 0x3028
+#define m_PHY_I2CM_NACK_POL (1 << 7)
+#define v_PHY_I2CM_NACK_POL(n) (((n)&0x01) << 7)
+#define m_PHY_I2CM_NACK_MASK (1 << 6)
+#define v_PHY_I2CM_NACK_MASK(n) (((n)&0x01) << 6)
+#define m_PHY_I2CM_NACK_INT (1 << 5)
+#define m_PHY_I2CM_NACK_STATUS (1 << 4)
+#define m_PHY_I2CM_ARB_POL (1 << 3)
+#define v_PHY_I2CM_ARB_POL(n) (((n)&0x01) << 3)
+#define m_PHY_I2CM_ARB_MASK (1 << 2)
+#define v_PHY_I2CM_ARB_MASK(n) (((n)&0x01) << 2)
+#define m_PHY_I2CM_ARB_INT (1 << 1)
+#define m_PHY_I2CM_ARB_STATUS (1 << 0)
+
+#define PHY_I2CM_DIV 0x3029
+#define m_PHY_I2CM_FAST_STD (1 << 3)
+#define v_PHY_I2CM_FAST_STD(n) (((n)&0x01) << 3)
+
+#define PHY_I2CM_SOFTRSTZ 0x302a
+#define m_PHY_I2CM_SOFTRST (1 << 0)
+#define v_PHY_I2CM_SOFTRST(n) (((n)&0x01) << 0)
+
+#define PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
+#define PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
+#define PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
+#define PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
+#define PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
+#define PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
+#define PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
+#define PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
+#define PHY_I2CM_SDA_HOLD 0x3033
+
+/* Audio Sampler Registers */
+#define AUDIO_SAMPLER_BASE 0x3100
+
+#define AUD_CONF0 0x3100
+#define m_SW_AUD_FIFO_RST (1 << 7)
+#define v_SW_AUD_FIFO_RST(n) (((n)&0x01) << 7)
+enum {
+ AUDIO_SPDIF_GPA = 0,
+ AUDIO_I2S
+};
+#define m_I2S_SEL (1 << 5)
+#define v_I2S_SEL(n) (((n)&0x01) << 5)
+enum {
+ I2S_CHANNEL_1_2 = 1,
+ I2S_CHANNEL_3_4 = 3,
+ I2S_CHANNEL_5_6 = 7,
+ I2S_CHANNEL_7_8 = 0xf
+};
+#define m_I2S_IN_EN (0x0f << 0)
+#define v_I2S_IN_EN(n) (((n)&0x0f) << 0)
+
+#define AUD_CONF1 0x3101
+enum I2S_MODE {
+ I2S_STANDARD_MODE = 0,
+ I2S_RIGHT_JUSTIFIED_MODE,
+ I2S_LEFT_JUSTIFIED_MODE,
+ I2S_BURST_1_MODE,
+ I2S_BURST_2_MODE
+};
+#define m_I2S_MODE (0x07 << 5)
+#define v_I2S_MODE(n) (((n)&0x07) << 5)
+enum I2S_WIDTH {
+ I2S_16BIT_SAMPLE = 16,
+ I2S_17BIT_SAMPLE,
+ I2S_18BIT_SAMPLE,
+ I2S_19BIT_SAMPLE,
+ I2S_20BIT_SAMPLE,
+ I2S_21BIT_SAMPLE,
+ I2S_22BIT_SAMPLE,
+ I2S_23BIT_SAMPLE,
+ I2S_24BIT_SAMPLE,
+};
+#define m_I2S_WIDTH (0x1f << 0)
+#define v_I2S_WIDTH(n) (((n)&0x1f) << 0)
+
+#define AUD_INT 0x3102
+#define AUD_SPDIFINT 0x3302
+#define m_FIFO_EMPTY_MASK (1 << 3)
+#define v_FIFO_EMPTY_MASK(n) (((n)&0x01) << 3)
+#define m_FIFO_FULL_MASK (1 << 2)
+#define v_FIFO_FULL_MASK(n) (((n)&0x01) << 2)
+
+#define AUD_CONF2 0x3103
+#define m_NLPCM_EN (1 << 1)
+#define v_NLPCM_EN(n) (((n)&0x01) << 1)
+#define m_HBR_EN (1 << 0)
+#define v_HBR_EN(n) (((n)&0x01) << 0)
+
+#define AUD_INT1 0x3104
+#define AUD_SPDIFINT1 0x3303
+#define m_FIFO_OVERRUN_MASK (1 << 4)
+#define v_FIFO_OVERRUN_MASK(n) (((n)&0x01) << 4)
+
+/***************N-CTS Table**************/
+/* TMDS LOWCLK: <=148.5M */
+/* TMDS MIDCLK: 297M */
+/* TMDS HIGHCLK: 594M */
+#define N_32K_LOWCLK 0x1000
+#define N_32K_MIDCLK 0x0c00
+#define N_32K_HIGHCLK 0x0c00
+#define N_441K_LOWCLK 0x1880
+#define N_441K_MIDCLK 0x1260
+#define N_441K_HIGHCLK 0x24c0
+#define N_48K_LOWCLK 0x1800
+#define N_48K_MIDCLK 0x1400
+#define N_48K_HIGHCLK 0x1800
+#define N_882K_LOWCLK 0x3100
+#define N_882K_MIDCLK 0x24c0
+#define N_882K_HIGHCLK 0x4980
+#define N_96K_LOWCLK 0x3000
+#define N_96K_MIDCLK 0x2800
+#define N_96K_HIGHCLK 0x3000
+#define N_1764K_LOWCLK 0x6200
+#define N_1764K_MIDCLK 0x4980
+#define N_1764K_HIGHCLK 0x9300
+#define N_192K_LOWCLK 0x6000
+#define N_192K_MIDCLK 0x5000
+#define N_192K_HIGHCLK 0x6000
+
+#define CALC_CTS(N, TMDSCLK, FS) (((N) / 32) * (TMDSCLK) / ((FS) * 4))
+/****************************************/
+
+#define AUD_N1 0x3200
+#define AUD_N2 0x3201
+
+#define AUD_N3 0x3202
+#define m_NCTS_ATOMIC_WR (1 << 7)
+#define v_NCTS_ATOMIC_WR(n) (((n)&0x01) << 7)
+#define m_AUD_N3 (0x0f << 0)
+#define v_AUD_N3(n) (((n)&0x0f) << 0)
+
+#define AUD_CTS1 0x3203
+#define AUD_CTS2 0x3204
+
+#define AUD_CTS3 0x3205
+enum {
+ N_SHIFT_1 = 0,
+ N_SHIFT_16,
+ N_SHIFT_32,
+ N_SHIFT_64,
+ N_SHIFT_128,
+ N_SHIFT_256,
+ N_SHIFT_OTHERS_128
+};
+#define m_N_SHIFT (0x07 << 5)
+#define v_N_SHIFT(n) (((n)&0x07) << 5)
+#define m_CTS_MANUAL (1 << 4)
+#define v_CTS_MANUAL(n) (((n)&0x01) << 4)
+#define m_AUD_CTS3 (0x0f << 0)
+#define v_AUD_CTS3(n) (((n)&0x0f) << 0)
+
+#define AUD_INPUTCLKFS 0x3206
+enum {
+ FS_128 = 0,
+ FS_256,
+ FS_512,
+ FS_64 = 4,
+ FS_OTHERS_128
+};
+#define m_LFS_FACTOR (0x07 << 0)
+#define v_LFS_FACTOR(n) (((n)&0x07) << 0)
+
+#define AUD_SPDIF0 0x3300
+#define m_SW_SAUD_FIFO_RST (1 << 7)
+#define v_SW_SAUD_FIFO_RST(n) (((n)&0x01) << 7)
+
+#define AUD_SPDIF1 0x3301
+enum {
+ PCM_LINEAR = 0,
+ PCM_NONLINEAR
+};
+#define m_SET_NLPCM (1 << 7)
+#define v_SET_NLPCM(n) (((n)&0x01) << 7)
+#define m_SPDIF_HBR_MODE (1 << 6)
+#define v_SPDIF_HBR_MODE(n) (((n)&0x01) << 6)
+#define m_SPDIF_WIDTH (0x1f << 0)
+#define v_SPDIF_WIDTH(n) (((n)&0x1f) << 0)
+
+/* Generic Parallel Audio Interface Registers */
+#define GP_AUDIO_INTERFACE_BASE 0x3500
+
+#define GP_CONF0 0x3500
+#define GP_CONF1 0x3501
+#define GP_CONF2 0x3502
+#define GP_MASK 0x3506
+
+/* Audio DMA Registers */
+#define AUDIO_DMA_BASE 0x3600
+
+#define AHB_DMA_CONF0 0x3600
+#define AHB_DMA_START 0x3601
+#define AHB_DMA_STOP 0x3602
+#define AHB_DMA_THRSLD 0x3603
+#define AHB_DMA_STRADDR_SET0_0 0x3604 /* 0~3 */
+#define AHB_DMA_STPADDR_SET0_0 0x3608 /* 0~3 */
+#define AHB_DMA_BSTADDR0 0x360c /* 0~3 */
+#define AHB_DMA_MBLENGTH0 0x3610 /* 0~3 */
+#define AHB_DMA_MASK 0x3614
+#define AHB_DMA_CONF1 0x3616
+#define AHB_DMA_BUFFMASK 0x3619
+#define AHB_DMA_MASK1 0x361b
+#define AHB_DMA_STATUS 0x361c
+#define AHB_DMA_CONF2 0x361d
+#define AHB_DMA_STRADDR_SET1_0 0x3620 /* 0~3 */
+#define AHB_DMA_STPADDR_SET1_0 0x3624 /* 0~3 */
+
+/* Main Controller Registers */
+#define MAIN_CONTROLLER_BASE 0x4000
+
+#define MC_CLKDIS 0x4001
+#define m_HDCPCLK_DISABLE (1 << 6)
+#define v_HDCPCLK_DISABLE(n) (((n)&0x01) << 6)
+#define m_CECCLK_DISABLE (1 << 5)
+#define v_CECCLK_DISABLE(n) (((n)&0x01) << 5)
+#define m_CSCCLK_DISABLE (1 << 4)
+#define v_CSCCLK_DISABLE(n) (((n)&0x01) << 4)
+#define m_AUDCLK_DISABLE (1 << 3)
+#define v_AUDCLK_DISABLE(n) (((n)&0x01) << 3)
+#define m_PREPCLK_DISABLE (1 << 2)
+#define v_PREPCLK_DISABLE(n) (((n)&0x01) << 2)
+#define m_TMDSCLK_DISABLE (1 << 1)
+#define v_TMDSCLK_DISABLE(n) (((n)&0x01) << 1)
+#define m_PIXELCLK_DISABLE (1 << 0)
+#define v_PIXELCLK_DISABLE(n) (((n)&0x01) << 0)
+
+#define MC_SWRSTZREQ 0x4002
+#define m_IGPA_SWRST (1 << 7)
+#define v_IGPA_SWRST(n) (((n)&0x01) << 7)
+#define m_CEC_SWRST (1 << 6)
+#define v_CEC_SWRST(n) (((n)&0x01) << 6)
+#define m_ISPDIF_SWRST (1 << 4)
+#define v_ISPDIF_SWRST(n) (((n)&0x01) << 4)
+#define m_II2S_SWRST (1 << 3)
+#define v_II2S_SWRST(n) (((n)&0x01) << 3)
+#define m_PREP_SWRST (1 << 2)
+#define v_PREP_SWRST(n) (((n)&0x01) << 2)
+#define m_TMDS_SWRST (1 << 1)
+#define v_TMDS_SWRST(n) (((n)&0x01) << 1)
+#define m_PIXEL_SWRST (1 << 0)
+#define v_PIXEL_SWRST(n) (((n)&0x01) << 0)
+
+#define MC_OPCTRL 0x4003
+#define m_HDCP_BLOCK_BYP (1 << 0)
+#define v_HDCP_BLOCK_BYP(n) (((n)&0x01) << 0)
+
+#define MC_FLOWCTRL 0x4004
+#define m_FEED_THROUGH_OFF (1 << 0)
+#define v_FEED_THROUGH_OFF(n) (((n)&0x01) << 0)
+
+#define MC_PHYRSTZ 0x4005
+#define m_PHY_RSTZ (1 << 0)
+#define v_PHY_RSTZ(n) (((n)&0x01) << 0)
+
+#define MC_LOCKONCLOCK 0x4006
+#define m_IGPACLK_ON (1 << 7)
+#define v_IGPACLK_ON(n) (((n)&0x01) << 7)
+#define m_PCLK_ON (1 << 6)
+#define v_PCLK_ON(n) (((n)&0x01) << 6)
+#define m_TMDSCLK_ON (1 << 5)
+#define v_TMDSCLK_ON(n) (((n)&0x01) << 5)
+#define m_PREPCLK_ON (1 << 4)
+#define v_PREPCLK_ON(n) (((n)&0x01) << 4)
+#define m_I2SCLK_ON (1 << 3)
+#define v_I2SCLK_ON(n) (((n)&0x01) << 3)
+#define m_SPDIFCLK_ON (1 << 2)
+#define v_SPDIFCLK_ON(n) (((n)&0x01) << 2)
+#define m_CECCLK_ON (1 << 0)
+#define v_CECCLK_ON(n) (((n)&0x01) << 0)
+
+#define MC_HEACPHY_RST 0x4007
+#define m_HEAC_PHY_RST (1 << 0)
+#define v_HEAC_PHY_RST(n) (((n)&0x01) << 0)
+
+#define MC_LOCKONCLOCK_2 0x4009
+#define m_AHB_AUD_DMA_CLK (1 << 0)
+#define v_AHB_AUD_DMA_CLK(n) (((n)&0x01) << 0)
+
+#define MC_SWRSTZREQ_2 0x400a
+#define m_AHB_AUD_DMA_RST (1 << 7)
+#define v_AHB_AUD_DMA_RST(n) (((n)&0x01) << 7)
+
+/* Color Space Converter Registers */
+#define COLOR_SPACE_CONVERTER_BASE 0x4100
+
+#define CSC_CFG 0x4100
+#define m_CSC_INTPMODE (0x03 << 4)
+#define v_CSC_INTPMODE(n) (((n)&0x03) << 4)
+#define m_CSC_DECIMODE (0x03 << 0)
+#define v_CSC_DECIMODE(n) (((n)&0x03) << 0)
+
+#define CSC_SCALE 0x4101
+#define m_CSC_COLOR_DEPTH (0x0f << 4)
+#define v_CSC_COLOR_DEPTH(n) (((n)&0x0f) << 4)
+#define m_CSC_SCALE (0x03 << 0)
+#define v_CSC_SCALE(n) (((n)&0x03) << 0)
+
+#define CSC_COEF_A1_MSB 0x4102
+#define CSC_COEF_A1_LSB 0x4103
+#define CSC_COEF_A2_MSB 0x4104
+#define CSC_COEF_A2_LSB 0x4105
+#define CSC_COEF_A3_MSB 0x4106
+#define CSC_COEF_A3_LSB 0x4107
+#define CSC_COEF_A4_MSB 0x4108
+#define CSC_COEF_A4_LSB 0x4109
+#define CSC_COEF_B1_MSB 0x410a
+#define CSC_COEF_B1_LSB 0x410b
+#define CSC_COEF_B2_MSB 0x410c
+#define CSC_COEF_B2_LSB 0x410d
+#define CSC_COEF_B3_MSB 0x410e
+#define CSC_COEF_B3_LSB 0x410f
+#define CSC_COEF_B4_MSB 0x4110
+#define CSC_COEF_B4_LSB 0x4111
+#define CSC_COEF_C1_MSB 0x4112
+#define CSC_COEF_C1_LSB 0x4113
+#define CSC_COEF_C2_MSB 0x4114
+#define CSC_COEF_C2_LSB 0x4115
+#define CSC_COEF_C3_MSB 0x4116
+#define CSC_COEF_C3_LSB 0x4117
+#define CSC_COEF_C4_MSB 0x4118
+#define CSC_COEF_C4_LSB 0x4119
+#define CSC_SPARE_1 0x411a
+#define CSC_SPARE_2 0x411b
+
+/* HDCP Encryption Engine Registers */
+#define HDCP_ENCRYPTION_ENGINE_BASE 0x5000
+
+#define A_HDCPCFG0 0x5000
+#define m_HDCP_ENHANCE_LIKE (1 << 7)
+#define v_HDCP_ENHANCE_LIKE(n) (((n)&0x01) << 7)
+#define m_I2C_FAST_MODE (1 << 6)
+#define v_I2C_FAST_MODE(n) (((n)&0x01) << 6)
+#define m_ENCRYPT_BYPASS (1 << 5)
+#define v_ENCRYPT_BYPASS(n) (((n)&0x01) << 5)
+#define m_SYNC_RI_CHECK (1 << 4)
+#define v_SYNC_RI_CHECK(n) (((n)&0x01) << 4)
+#define m_AVMUTE (1 << 3)
+#define m_RX_DETECT (1 << 2)
+#define v_RX_DETECT(n) (((n)&0x01) << 2)
+#define m_FEATURE11_EN (1 << 1)
+#define v_FEATURE11_EN(n) (((n)&0x01) << 1)
+#define m_HDMI_DVI (1 << 0)
+#define v_HDMI_DVI(n) (((n)&0x01) << 0)
+
+#define A_HDCPCFG1 0x5001
+#define m_HDCP_LOCK (1 << 4)
+#define v_HDCP_LOCK(n) (((n)&0x01) << 4)
+#define m_SHA1_CHECK_DISABLE (1 << 3)
+#define v_SHA1_CHECK_DISBALE(n) (((n)&0x01) << 3)
+#define m_PH2UPSHFTENC (1 << 2)
+#define v_PH2UPSHFTENC(n) (((n)&0x01) << 2)
+#define m_ENCRYPT_DISBALE (1 << 1)
+#define v_ENCRYPT_DISBALE(n) (((n)&0x01) << 1)
+#define m_HDCP_SW_RST (1 << 0)
+#define v_HDCP_SW_RST(n) (((n)&0x01) << 0)
+
+#define A_HDCPOBS0 0x5002
+#define m_STATE_AUTH (0x0f << 4)
+#define m_SUB_STATE_AUTH (0x07 << 1)
+#define m_STATE_HDCP_ENGAGED (1 << 0)
+
+#define A_HDCPOBS1 0x5003
+#define m_STATE_OESS (0x07 << 3)
+#define m_STATE_REVO (0x07 << 0)
+
+#define A_HDCPOBS2 0x5004
+#define m_STATE_CIPHER (0x07 << 3)
+#define m_STATE_EESS (0x07 << 0)
+
+#define A_HDCPOBS3 0x5005
+#define m_BCAP_REPEATER (1 << 6)
+#define m_BCAP_KSVFIFO_READY (1 << 5)
+#define m_BCAP_FAST_I2C (1 << 4)
+#define m_BCAP_HDMI_MODE (1 << 2)
+#define m_BCAP_FEATURES11 (1 << 1)
+#define m_BCAP_FAST_REAUTH (1 << 0)
+
+#define A_APIINTCLR 0x5006
+#define A_APIINTSTAT 0x5007
+#define A_APIINTMSK 0x5008
+#define m_HDCP_ENGAGED (1 << 7)
+#define m_HDCP_FAILED (1 << 6)
+#define m_HDCP_I2C_NOACK (1 << 4)
+#define m_HDCP_LOST_ARBI (1 << 3)
+#define m_KEEP_ERR_INT (1 << 2)
+#define m_KSVSHA1_CALC_INT (1 << 1)
+#define m_KSV_ACCESS_INT (1 << 0)
+#define v_HDCP_ENGAGED(n) (((n)&0x01) << 7)
+#define v_HDCP_FAILED(n) (((n)&0x01) << 6)
+#define v_HDCP_I2C_NOACK(n) (((n)&0x01) << 4)
+#define v_HDCP_LOST_ARBI(n) (((n)&0x01) << 3)
+#define v_KEEP_ERR_INT(n) (((n)&0x01) << 1)
+#define v_KSVSHA1_CALC_INT(n) (((n)&0x01) << 1)
+#define v_KSV_ACCESS_INT(n) (((n)&0x01) << 0)
+
+#define A_VIDPOLCFG 0x5009
+#define m_UNENCRYT_CONF (0x03 << 5)
+#define v_UNENCRYT_CONF(n) (((n)&0x03) << 5)
+#define m_DATAEN_POL (1 << 4)
+#define v_DATAEN_POL(n) (((n)&0x01) << 4)
+#define m_VSYNC_POL (1 << 3)
+#define v_VSYNC_POL(n) (((n)&0x01) << 3)
+#define m_HSYNC_POL (1 << 1)
+#define v_HSYNC_POL(n) (((n)&0x01) << 1)
+
+#define A_OESSWCFG 0x500a
+#define A_COREVERLSB 0x5014
+#define A_COREVERMSB 0x5015
+
+#define A_KSVMEMCTRL 0x5016
+#define m_SHA1_FAIL (1 << 3)
+#define v_SHA1_FAIL(n) (((n)&0x01) << 3)
+#define m_KSV_UPDATE (1 << 2)
+#define v_KSV_UPDATE(n) (((n)&0x01) << 2)
+#define m_KSV_MEM_ACCESS (1 << 1)
+#define m_KSV_MEM_REQ (1 << 0)
+#define v_KSV_MEM_REQ(n) (((n)&0x01) << 0)
+
+#define HDCP_BSTATUS_0 0x5020
+#define m_MAX_DEVS_EXCEEDED (1 << 7)
+#define m_DEVICE_COUNT (0x7f << 0)
+
+#define HDCP_BSTATUS_1 0x5021
+#define HDCP_M0_0 0x5022
+#define HDCP_M0_1 0x5023
+#define HDCP_M0_2 0x5024
+#define HDCP_M0_3 0x5025
+#define HDCP_M0_4 0x5026
+#define HDCP_M0_5 0x5027
+#define HDCP_M0_6 0x5028
+#define HDCP_M0_7 0x5029
+#define HDCP_KSV 0x502a /* 0~634 */
+#define HDCP_VH 0x52a5 /* 0~19 */
+#define HDCP_REVOC_SIZE_0 0x52b9
+#define HDCP_REVOC_SIZE_1 0x52ba
+#define HDCP_REVOC_LIST 0x52bb /* 0~5059 */
+
+/* HDCP BKSV Registers */
+#define HDCP_BKSV_BASE 0x7800
+
+#define HDCPREG_BKSV0 0x7800
+#define HDCPREG_BKSV1 0x7801
+#define HDCPREG_BKSV2 0x7802
+#define HDCPREG_BKSV3 0x7803
+#define HDCPREG_BKSV4 0x7804
+
+/* HDCP AN Registers */
+#define HDCP_AN_BASE 0x7805
+
+#define HDCPREG_ANCONF 0x7805
+#define m_OAN_BYPASS (1 << 0)
+#define v_OAN_BYPASS(n) (((n)&0x01) << 0)
+
+#define HDCPREG_AN0 0x7806
+#define HDCPREG_AN1 0x7807
+#define HDCPREG_AN2 0x7808
+#define HDCPREG_AN3 0x7809
+#define HDCPREG_AN4 0x780a
+#define HDCPREG_AN5 0x780b
+#define HDCPREG_AN6 0x780c
+#define HDCPREG_AN7 0x780d
+
+/* Encrypted DPK Embedded Storage Registers */
+#define ENCRYPTED_DPK_EMBEDDED_BASE 0x780e
+
+#define HDCPREG_RMCTL 0x780e
+#define m_DPK_DECRYPT_EN (1 << 0)
+#define v_DPK_DECRYPT_EN(n) (((n)&0x01) << 0)
+
+#define HDCPREG_RMSTS 0x780f
+#define m_DPK_WR_OK_STS (1 << 6)
+#define m_DPK_DATA_INDEX (0x3f << 6)
+
+#define HDCPREG_SEED0 0x7810
+#define HDCPREG_SEED1 0x7811
+#define HDCPREG_DPK0 0x7812
+#define HDCPREG_DPK1 0x7813
+#define HDCPREG_DPK2 0x7814
+#define HDCPREG_DPK3 0x7815
+#define HDCPREG_DPK4 0x7816
+#define HDCPREG_DPK5 0x7817
+#define HDCPREG_DPK6 0x7818
+
+#define HDCP2REG_BASE 0x7900
+#define HDCP2REG_ID 0x7900
+#define HDCP2REG_CTRL 0x7904
+ #define m_HDCP2_HDP_OVR_VAL (1 << 5)
+ #define m_HDCP2_HDP_OVR_EN (1 << 4)
+ #define m_HDCP2_FORCE (1 << 2)
+ #define m_HDCP2_OVR_EN (1 << 1)
+ #define m_HDCP2_SWITCH_EN (1 << 0)
+
+ #define v_HDCP2_HDP_OVR_VAL(n) (((n)&0x01) << 5)
+ #define v_HDCP2_HDP_OVR_EN(n) (((n)&0x01) << 4)
+ #define v_HDCP2_FORCE(n) (((n)&0x01) << 2)
+ #define v_HDCP2_OVR_EN(n) (((n)&0x01) << 1)
+ #define v_HDCP2_SWITCH_EN(n) (((n)&0x01) << 0)
+#define HDCP2REG_CTRL1 0x7905
+ #define m_HDCP2_CD_VAL (0xf << 4)
+ #define m_HDCP2_CD_EN (1 << 3)
+ #define m_HDCP2_AVMUTE_OVR_VAL (1 << 1)
+ #define m_HDCP2_AVMUTE_OVR_EN (1 << 0)
+
+ #define v_HDCP2_CD_VAL(n) (((n)&0x0f) << 4)
+ #define v_HDCP2_CD_EN(n) (((n)&0x01) << 3)
+ #define v_HDCP2_AVMUTE_OVR_VAL(n) (((n)&0x01) << 1)
+ #define v_HDCP2_AVMUTE_OVR_EN(n) (((n)&0x01) << 0)
+#define HDCP2REG_STAS 0x7908
+#define HDCP2REG_MASK 0x790c
+#define HDCP2REG_STAT 0x790d
+#define HDCP2REG_MUTE 0x790e
+ #define m_HDCP2_CAPABLE (1 << 0)
+ #define m_HDCP2_NOTCAPABLE (1 << 1)
+ #define m_HDCP2_AUTH_LOST (1 << 2)
+ #define m_HDCP2_AUTH_OK (1 << 3)
+ #define m_HDCP2_AUTH_FAIL (1 << 4)
+
+/* CEC Engine Registers */
+#define CEC_ENGINE_BASE 0x7d00
+
+#define CEC_CTRL 0x7d00
+ #define m_CEC_STANBY (1 << 4)
+ #define m_CEC_BC_NCK (1 << 3)
+ #define m_CEC_FRAME_TYPE (3 << 1)
+ #define m_CEC_SEND (1 << 0)
+ #define v_CEC_STANBY(n) ((n & 0x1) << 4)
+ #define v_CEC_BC_NCK(n) ((n & 0x1) << 3)
+ #define v_CEC_FRAME_TYPE(n) ((n & 0x3) << 1)
+ #define v_CEC_SEND(n) (n & 0x1)
+#define CEC_MASK 0x7d02
+#define CEC_ADDR_L 0x7d05
+#define CEC_ADDR_H 0x7d06
+#define CEC_TX_CNT 0x7d07
+#define CEC_RX_CNT 0x7d08
+#define CEC_TX_DATA0 0x7d10 /* txdata0~txdata15 */
+#define CEC_RX_DATA0 0x7d20 /* rxdata0~rxdata15 */
+#define CEC_LOCK 0x7d30
+#define CEC_WKUPCTRL 0x7d31
+
+/* I2C Master Registers */
+#define I2C_MASTER_BASE 0x7e00
+
+#define I2CM_SLAVE 0x7e00
+#define I2CM_ADDRESS 0x7e01
+#define I2CM_DATAO 0x7e02
+#define I2CM_DATAI 0x7e03
+
+#define I2CM_OPERATION 0x7e04
+#define m_I2CM_WR (1 << 4)
+#define v_I2CM_WR(n) (((n)&0x01) << 4)
+#define m_I2CM_RD8_EXT (1 << 3)
+#define v_I2CM_RD8_EXT(n) (((n)&0x01) << 3)
+#define m_I2CM_RD8 (1 << 2)
+#define v_I2CM_RD8(n) (((n)&0x01) << 2)
+#define m_I2CM_RD_EXT (1 << 1)
+#define v_I2CM_RD_EXT(n) (((n)&0x01) << 1)
+#define m_I2CM_RD (1 << 0)
+#define v_I2CM_RD(n) (((n)&0x01) << 0)
+
+#define I2CM_INT 0x7e05
+#define m_I2CM_RD_REQ_MASK (1 << 6)
+#define v_I2CM_RD_REQ_MASK(n) (((n)&0x01) << 6)
+#define m_I2CM_DONE_MASK (1 << 2)
+#define v_I2CM_DONE_MASK(n) (((n)&0x01) << 2)
+
+#define I2CM_CTLINT 0x7e06
+#define m_I2CM_NACK_MASK (1 << 6)
+#define v_I2CM_NACK_MASK(n) (((n)&0x01) << 6)
+#define m_I2CM_ARB_MASK (1 << 2)
+#define v_I2CM_ARB_MASK(n) (((n)&0x01) << 2)
+
+#define I2CM_DIV 0x7e07
+enum {
+ STANDARD_MODE = 0,
+ FAST_MODE
+};
+#define m_I2CM_FAST_STD_MODE (1 << 3)
+#define v_I2CM_FAST_STD_MODE(n) (((n)&0x01) << 3)
+
+#define I2CM_SEGADDR 0x7e08
+#define m_I2CM_SEG_ADDR (0x7f << 0)
+#define v_I2CM_SEG_ADDR(n) (((n)&0x7f) << 0)
+
+#define I2CM_SOFTRSTZ 0x7e09
+#define m_I2CM_SOFTRST (1 << 0)
+#define v_I2CM_SOFTRST(n) (((n)&0x01) << 0)
+
+#define I2CM_SEGPTR 0x7e0a
+#define I2CM_SS_SCL_HCNT_1_ADDR 0x7e0b
+#define I2CM_SS_SCL_HCNT_0_ADDR 0x7e0c
+#define I2CM_SS_SCL_LCNT_1_ADDR 0x7e0d
+#define I2CM_SS_SCL_LCNT_0_ADDR 0x7e0e
+#define I2CM_FS_SCL_HCNT_1_ADDR 0x7e0f
+#define I2CM_FS_SCL_HCNT_0_ADDR 0x7e10
+#define I2CM_FS_SCL_LCNT_1_ADDR 0x7e11
+#define I2CM_FS_SCL_LCNT_0_ADDR 0x7e12
+#define I2CM_SDA_HOLD 0x7e13
+
+#define I2CM_SCDC_READ_UPDATE 0x7e14
+#define m_I2CM_UPRD_VSYNC_EN (1 << 5)
+#define v_I2CM_UPRD_VSYNC_EN(n) (((n)&0x01) << 5)
+#define m_I2CM_READ_REQ_EN (1 << 4)
+#define v_I2CM_READ_REQ_EN(n) (((n)&0x01) << 4)
+#define m_I2CM_READ_UPDATE (1 << 0)
+#define v_I2CM_READ_UPDATE(n) (((n)&0x01) << 0)
+
+#define I2CM_READ_BUFF0 0x7e20 /* buff0~buff7 */
+#define I2CM_SCDC_UPDATE0 0x7e30
+#define I2CM_SCDC_UPDATE1 0x7e31
+
+/*
+* HDMI TX PHY Define Start
+*/
+#define PHYTX_OPMODE_PLLCFG 0x06
+enum {
+ PREP_DIV_BY_2 = 0, /* 16 bits */
+ PREP_DIV_BY_15, /* 12 bits */
+ PREP_DIV_BY_125, /* 10 bits */
+ PREP_DIV_BY_1, /* 8 bits */
+};
+#define m_PREP_DIV (0x03 << 13)
+#define v_PREP_DIV(n) (((n)&0x03) << 13)
+enum {
+ TMDS_DIV_BY_1 = 0,
+ TMDS_DIV_NOT_USED,
+ TMDS_DIV_BY_3,
+ TMDS_DIV_BY_4,
+};
+#define m_TMDS_CNTRL (0x03 << 11)
+#define v_TMDS_CNTRL(n) (((n)&0x03) << 11)
+enum OPMODE {
+ OP_HDMI_14 = 0,
+ OP_HDMI_20,
+};
+#define m_OPMODE (0x03 << 9)
+#define v_OPMODE(n) (((n)&0x03) << 9)
+enum {
+ FBDIV2_BY_1 = 1,
+ FBDIV2_BY_2,
+ FBDIV2_BY_3,
+ FBDIV2_BY_4,
+ FBDIV2_BY_5,
+ FBDIV2_BY_6,
+};
+#define m_FBDIV2_CNTRL (0x07 << 6)
+#define v_FBDIV2_CNTRL(n) (((n)&0x07) << 6)
+enum {
+ FBDIV1_BY_1 = 0,
+ FBDIV1_BY_2,
+ FBDIV1_BY_3,
+ FBDIV1_BY_4,
+};
+#define m_FBDIV1_CNTRL (0x03 << 4)
+#define v_FBDIV1_CNTRL(n) (((n)&0x03) << 4)
+enum {
+ REF_DIV_BY_1 = 0,
+ REF_DIV_BY_2,
+ REF_DIV_NOT_USED,
+ REF_DIV_BY_4,
+};
+#define m_REF_CNTRL (0x03 << 2)
+#define v_REF_CNTRL(n) (((n)&0x03) << 2)
+#define m_MPLL_N_CNTRL (0x03 << 0)
+#define v_MPLL_N_CNTRL(n) (((n)&0x03) << 0)
+
+#define PHYTX_CLKSYMCTRL 0x09
+#define v_OVERRIDE(n) (0x01 << 15)
+#define m_SLOPEBOOST (0x03 << 4)
+#define v_SLOPEBOOST(n) (((n)&0x03) << 4)
+#define m_TX_SYMON (0x01 << 3)
+#define v_TX_SYMON(n) (((n)&0x01) << 3)
+#define m_TX_TRAON (0x01 << 2)
+#define v_TX_TRAON(n) (((n)&0x01) << 2)
+#define m_TX_TRBON (0x01 << 1)
+#define v_TX_TRBON(n) (((n)&0x01) << 1)
+#define m_CLK_SYMON (0x01 << 0)
+#define v_CLK_SYMON(n) (((n)&0x01) << 0)
+
+#define PHYTX_VLEVCTRL 0x0e
+#define m_SUP_TXLVL (0x1f << 5)
+#define v_SUP_TXLVL(n) (((n)&0x1f) << 5)
+#define m_SUP_CLKLVL (0x1f << 0)
+#define v_SUP_CLKLVL(n) (((n)&0x1f) << 0)
+
+#define PHYTX_PLLCURRCTRL 0x10
+#define m_MPLL_PROP_CNTRL (0x07 << 3)
+#define v_MPLL_PROP_CNTRL(n) (((n)&0x07) << 3)
+#define m_MPLL_INT_CNTRL (0x07 << 0)
+#define v_MPLL_INT_CNTRL(n) (((n)&0x07) << 0)
+
+#define PHYTX_PLLGMPCTRL 0x15
+#define m_MPLL_GMP_CNTRL (0x03 << 0)
+#define v_MPLL_GMP_CNTRL(n) (((n)&0x03) << 0)
+
+enum TERM_RESIS {
+ R50_OHMS = 0,
+ R5714_OHMS,
+ R6667_OHMS,
+ R80_OHMS,
+ R100_OHMS,
+ R13333_OHMS,
+ R200_OHMS,
+ ROPEN_CIRCUIT,
+};
+#define PHYTX_TERM_RESIS 0x19
+#define m_TX_TERM (0x07 << 0)
+#define v_TX_TERM(n) (((n)&0x07) << 0)
+
+
+struct phy_mpll_config_tab {
+ u32 pix_clock;
+ u32 tmdsclock;
+ u8 pix_repet;
+ u8 color_depth;
+ u16 prep_div;
+ u16 tmdsmhl_cntrl;
+ u16 opmode;
+ u32 fbdiv2_cntrl;
+ u16 fbdiv1_cntrl;
+ u16 ref_cntrl;
+ u16 n_cntrl;
+ u32 prop_cntrl;
+ u32 int_cntrl;
+ u16 gmp_cntrl;
+};
+
+/*
+* HDMI TX PHY Define End
+*/
+
+struct rockchip_hdmiv2_reg_table {
+ int reg_base;
+ int reg_end;
+};
+
+static inline u32 hdmi_readl(struct hdmi_dev *hdmi_dev, u16 offset)
+{
+ return readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
+}
+
+static inline int hdmi_writel(struct hdmi_dev *hdmi_dev, u16 offset, u32 val)
+{
+ int ret = 0;
+
+ writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
+ return ret;
+}
+
+static inline int hdmi_msk_reg(struct hdmi_dev *hdmi_dev,
+ u16 offset, u32 msk, u32 val)
+{
+ int ret = 0;
+ u32 temp;
+
+ temp = readl_relaxed(hdmi_dev->regbase +
+ (offset) * 0x04) & (0xFF - (msk));
+ writel_relaxed(temp | ((val) & (msk)),
+ hdmi_dev->regbase + (offset) * 0x04);
+ return ret;
+}
+irqreturn_t rockchip_hdmiv2_dev_irq(int irq, void *priv);
+void rockchip_hdmiv2_dev_init_ops(struct hdmi_ops *ops);
+void rockchip_hdmiv2_dev_initial(struct hdmi_dev *hdmi_dev);
+void rockchip_hdmiv2_cec_init(struct hdmi *hdmi);
+void rockchip_hdmiv2_cec_isr(struct hdmi_dev *hdmi_dev, char cec_int);
+void rockchip_hdmiv2_dump_phy_regs(struct hdmi_dev *hdmi_dev);
+void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi);
+#endif
#include "bmp_helper.h"
#if defined(CONFIG_RK_HDMI)
-#include "hdmi/rk_hdmi.h"
+#include "hdmi/rockchip-hdmi.h"
#endif
#if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
#include <linux/rk_fb.h>
#include <linux/device.h>
#include "lcd.h"
-#include "../hdmi/rk_hdmi.h"
+#include "../hdmi/rockchip-hdmi.h"
static struct rk_screen *rk_screen;
int rk_fb_get_prmry_screen(struct rk_screen *screen)
#define PRMRY 1 /*primary display device*/
#define EXTEND 2 /*extend display device*/
+#define DISPLAY_SOURCE_LCDC0 0
+#define DISPLAY_SOURCE_LCDC1 1
+
#define NO_DUAL 0
#define ONE_DUAL 1
#define DUAL 2
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/list.h>
+#include <dt-bindings/rkfb/rk_fb.h>
struct rk_display_device;
DISPLAY_SCALE_Y
};
+enum rk_display_property {
+ DISPLAY_MAIN = 0,
+ DISPLAY_AUX
+};
+
+
+/* HDMI mode list*/
+struct display_modelist {
+ struct list_head list;
+ struct fb_videomode mode;
+ unsigned int vic;
+ unsigned int format_3d;
+ unsigned int detail_3d;
+};
+
/* This structure defines all the properties of a Display. */
struct rk_display_driver {
void (*suspend)(struct rk_display_device *, pm_message_t state);
struct fb_videomode *mode);
int (*setscale)(struct rk_display_device *, int, int);
int (*getscale)(struct rk_display_device *, int);
+ int (*get3dmode)(struct rk_display_device *);
+ int (*set3dmode)(struct rk_display_device *, int);
+ int (*getcolor)(struct rk_display_device *, char *);
+ int (*setcolor)(struct rk_display_device *, const char *, int);
int (*setdebug)(struct rk_display_device *, int);
int (*getedidaudioinfo)(struct rk_display_device *,
char *audioinfo, int len);
int idx;
struct rk_display_ops *ops;
int priority;
+ int property;
struct list_head list;
};
void rk_display_device_enable(struct rk_display_device *ddev);
void rk_display_device_enable_other(struct rk_display_device *ddev);
void rk_display_device_disable_other(struct rk_display_device *ddev);
-void rk_display_device_select(int priority);
+void rk_display_device_select(int property, int priority);
+int display_add_videomode(const struct fb_videomode *mode,
+ struct list_head *head);
#endif