add hdmi driver

This commit is contained in:
kfx 2010-12-20 14:58:15 +08:00
parent 6d4d225869
commit 04f88ca2ad
19 changed files with 7796 additions and 595 deletions

9
arch/arm/mach-rk29/board-rk29sdk.c Normal file → Executable file
View File

@ -521,6 +521,15 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = {
.irq = RK29_PIN4_PA1,
},
#endif
#if defined (CONFIG_ANX7150)
{
.type = "anx7150",
.addr = 0x39, //0x39, 0x3d
.flags = 0,
.irq = RK29_PIN1_PD7,
},
#endif
};
#endif

View File

@ -2183,6 +2183,7 @@ source "drivers/video/omap/Kconfig"
source "drivers/video/backlight/Kconfig"
source "drivers/video/display/Kconfig"
source "drivers/video/hdmi/Kconfig"
if VT
source "drivers/video/console/Kconfig"

View File

@ -13,7 +13,7 @@ fb-objs := $(fb-y)
obj-$(CONFIG_VT) += console/
obj-$(CONFIG_LOGO) += logo/
obj-y += backlight/ display/
obj-y += backlight/ display/ hdmi/
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o

View File

@ -1,3 +1,5 @@
#include <mach/board.h>
typedef enum _SCREEN_TYPE {
SCREEN_NULL = 0,
SCREEN_RGB,

View File

@ -0,0 +1,19 @@
#
# Display drivers configuration
#
menu "HDMI support"
config HDMI
tristate "hdmi support"
help
nothing
if HDMI
source "drivers/video/hdmi/chips/Kconfig"
config HDMI_DEBUG
bool "hdmi debug"
help
nothing
endif
endmenu

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_HDMI) += hdmi-core.o hdmi-sysfs.o hdmi-fb.o hdmi-codec.o
obj-$(CONFIG_HDMI) += chips/

View File

@ -0,0 +1,7 @@
choice
prompt "HDMI chips select"
config ANX7150
bool "anx7150"
config ANX9030
bool "anx9030"
endchoice

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_ANX7150) += anx7150_hw.o anx7150.o

View File

@ -0,0 +1,461 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/hdmi.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include "anx7150.h"
#include "anx7150_hw.h"
int anx7150_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val)
{
client->addr = ANX7150_I2C_ADDR0;
return i2c_master_reg8_recv(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL;
}
int anx7150_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val)
{
client->addr = ANX7150_I2C_ADDR0;
return i2c_master_reg8_send(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL;
}
int anx7150_i2c_read_p1_reg(struct i2c_client *client, char reg, char *val)
{
client->addr = ANX7150_I2C_ADDR1;
return i2c_master_reg8_recv(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL;
}
int anx7150_i2c_write_p1_reg(struct i2c_client *client, char reg, char *val)
{
client->addr = ANX7150_I2C_ADDR1;
return i2c_master_reg8_send(client, reg, val, 1, ANX7150_SCL_RATE) > 0? 0: -EINVAL;
}
static int rk29_hdmi_enter(struct anx7150_dev_s *dev)
{
if(dev->rk29_output_status == RK29_OUTPUT_STATUS_LCD) {
printk("%s, resolution = %d\n", __func__, dev->resolution_real);
if(hdmi_switch_fb(dev->resolution_real, 1) < 0)
return -1;
dev->hdmi->resolution = dev->resolution_real;
dev->rk29_output_status = RK29_OUTPUT_STATUS_HDMI;
}
return 0;
}
static int rk29_hdmi_exit(struct anx7150_dev_s *dev)
{
if(dev->rk29_output_status == RK29_OUTPUT_STATUS_HDMI) {
printk("%s\n", __func__);
if(hdmi_switch_fb(dev->resolution_real, 0) < 0)
return -1;
dev->rk29_output_status = RK29_OUTPUT_STATUS_LCD;
}
return 0;
}
static int anx7150_display_on(struct hdmi* hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
rk29_hdmi_enter(&anx->dev);
hdmi->display_on = HDMI_ENABLE;
anx->dev.hdmi_enable = HDMI_ENABLE;
anx->dev.parameter_config = 1;
hdmi_dbg(hdmi->dev, "hdmi display on\n");
return 0;
}
static int anx7150_display_off(struct hdmi* hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
rk29_hdmi_exit(&anx->dev);
hdmi->display_on = HDMI_DISABLE;
anx->dev.hdmi_enable = HDMI_DISABLE;
anx->dev.parameter_config = 1;
hdmi_dbg(hdmi->dev, "hdmi display off\n");
return 0;
}
static int anx7150_set_param(struct hdmi *hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->dev.resolution_set = hdmi->resolution;
anx->dev.i2s_Fs = hdmi->audio_fs;
anx->dev.hdcp_enable = hdmi->hdcp_on;
anx->dev.hdmi_auto_switch = hdmi->auto_switch;
anx->dev.parameter_config = 1;
return 0;
}
static int anx7150_core_init(struct hdmi *hdmi)
{
//struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
return 0;
}
static irqreturn_t anx7150_detect_irq(int irq, void *dev_id)
{
//struct hdmi *hdmi = (struct hdmi *)dev_id;
return IRQ_HANDLED;
}
void anx7150_task(struct anx7150_pdata *anx)
{
int state;
int ret;
//anx->dev.anx7150_detect = anx7150_detect_device(anx);
if(anx->dev.anx7150_detect == 0)
goto out;
state = ANX7150_Get_System_State();
if(anx->dev.parameter_config){
if(state > WAIT_HDMI_ENABLE)
state = WAIT_HDMI_ENABLE;
anx->dev.parameter_config = 0;
anx->dev.fb_switch_state = 1;
}
if(anx->dev.hdmi_enable == HDMI_DISABLE && anx->dev.hdmi_auto_switch == HDMI_DISABLE){
//if(state > WAIT_HDMI_ENABLE)
state = HDMI_INITIAL;
}
state = ANX7150_Interrupt_Process(anx, state);
switch(state){
case HDMI_INITIAL:
if(anx->dev.hdmi_auto_switch)
rk29_hdmi_exit(&anx->dev);
ANX7150_API_Initial(anx->client);
state = WAIT_HOTPLUG;
if(anx->dev.hdmi_auto_switch)
anx->dev.rate = 1;
else
anx->dev.rate = 100;
break;
case WAIT_HOTPLUG:
if(anx->dev.hdmi_auto_switch)
rk29_hdmi_exit(&anx->dev);
if(anx->dev.HPD_status){
anx7150_plug(anx->client);
state = READ_PARSE_EDID;
}
if(anx->dev.hdmi_auto_switch)
anx->dev.rate = 50;
else
anx->dev.rate = 100;
break;
case READ_PARSE_EDID:
ret = ANX7150_Parse_EDID(anx->client,&anx->dev);
if(ret != 0){
dev_err(&anx->client->dev, "Parse_EDID err, ret=%d\n", ret);
}
state = WAIT_RX_SENSE;
if(anx->dev.hdmi_auto_switch)
anx->dev.rate = 50;
else
anx->dev.rate = 100;
break;
case WAIT_RX_SENSE:
if(ANX7150_GET_SENSE_STATE(anx->client) == 1){
hdmi_dbg(&anx->client->dev, "reciver active\n");
state = WAIT_HDMI_ENABLE;
anx->dev.reciver_status = HDMI_RECIVER_ACTIVE;
hdmi_changed(anx->dev.hdmi, 1);
}
if(anx->dev.hdmi_auto_switch)
anx->dev.rate = 50;
else
anx->dev.rate = 100;
break;
case WAIT_HDMI_ENABLE:
if(!anx->dev.hdmi_enable && anx->dev.hdmi_auto_switch)
rk29_hdmi_exit(&anx->dev);
if(anx->dev.hdmi_enable &&
(anx->dev.hdmi_auto_switch || anx->init ||anx->dev.parameter_config)) {
rk29_hdmi_enter(&anx->dev);
anx->init = 0;
}
/*
if(1 || anx->dev.rk29_output_status == RK29_OUTPUT_STATUS_HDMI){
state = SYSTEM_CONFIG;
anx->dev.rate = 1;
}
*/
state = SYSTEM_CONFIG;
if(anx->dev.hdmi_auto_switch)
anx->dev.rate = 50;
else
anx->dev.rate = 100;
break;
case SYSTEM_CONFIG:
anx->dev.resolution_real = ANX7150_Get_Optimal_resolution(anx->dev.resolution_set);
HDMI_Set_Video_Format(anx->dev.resolution_real);
HDMI_Set_Audio_Fs(anx->dev.i2s_Fs);
ANX7150_API_HDCP_ONorOFF(anx->dev.hdcp_enable);
ANX7150_API_System_Config();
state = CONFIG_VIDEO;
anx->dev.rate = 1;
if(anx->dev.fb_switch_state && anx->dev.rk29_output_status == RK29_OUTPUT_STATUS_HDMI) {
anx->dev.rk29_output_status = RK29_OUTPUT_STATUS_LCD;
rk29_hdmi_enter(&anx->dev);
anx->dev.fb_switch_state = 0;
}
break;
case CONFIG_VIDEO:
if(ANX7150_Config_Video(anx->client) == 0){
if(ANX7150_GET_RECIVER_TYPE() == 1)
state = CONFIG_AUDIO;
else
state = HDCP_AUTHENTICATION;
anx->dev.rate = 50;
}
anx->dev.rate = 10;
break;
case CONFIG_AUDIO:
ANX7150_Config_Audio(anx->client);
state = CONFIG_PACKETS;
anx->dev.rate = 1;
break;
case CONFIG_PACKETS:
ANX7150_Config_Packet(anx->client);
state = HDCP_AUTHENTICATION;
anx->dev.rate = 1;
break;
case HDCP_AUTHENTICATION:
ANX7150_HDCP_Process(anx->client);
state = PLAY_BACK;
anx->dev.rate = 100;
break;
case PLAY_BACK:
ret = ANX7150_PLAYBACK_Process();
if(ret == 1){
state = CONFIG_PACKETS;
anx->dev.rate = 1;
}
anx->dev.rate = 100;
break;
default:
state = HDMI_INITIAL;
anx->dev.rate = 100;
break;
}
if(state != ANX7150_Get_System_State()){
ANX7150_Set_System_State(anx->client, state);
}
out:
return;
}
static void anx7150_work_func(struct work_struct * work)
{
struct anx7150_dev_s *dev = container_of((void *)work, struct anx7150_dev_s, delay_work);
struct hdmi *hdmi = dev->hdmi;
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx7150_task(anx);
/*
if(dev->hdmi_auto_switch)
{
if(dev->HPD_status == HDMI_RECIVER_PLUG)
{
rk29_hdmi_enter(dev);
}
else
{
rk29_hdmi_exit(dev);
}
}
else
{
if(dev->hdmi_enable)
{
rk29_hdmi_enter(dev);
}
else
{
rk29_hdmi_exit(dev);
}
}
*/
if(dev->anx7150_detect)
{
queue_delayed_work(dev->workqueue, &dev->delay_work, dev->rate);
}
else
{
hdmi_dbg(hdmi->dev, "ANX7150 not exist!\n");
rk29_hdmi_exit(dev);
}
return;
}
static int anx7150_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int rc = 0;
struct hdmi *hdmi = NULL;
struct anx7150_pdata *anx = NULL;
hdmi = kzalloc(sizeof(struct hdmi), GFP_KERNEL);
if (!hdmi)
{
dev_err(&client->dev, "no memory for state\n");
return -ENOMEM;
}
anx = kzalloc(sizeof(struct anx7150_pdata), GFP_KERNEL);
if(!anx)
{
dev_err(&client->dev, "no memory for state\n");
goto err_kzalloc_anx;
}
anx->client = client;
anx->dev.anx7150_detect = 0;
anx->dev.resolution_set = HDMI_DEFAULT_RESOLUTION;
anx->dev.i2s_Fs = HDMI_I2S_DEFAULT_Fs;
anx->dev.hdmi_enable = HDMI_ENABLE;
anx->dev.hdmi_auto_switch = HDMI_AUTO_SWITCH;
anx->dev.reciver_status = HDMI_RECIVER_INACTIVE;
anx->dev.HPD_status = HDMI_RECIVER_UNPLUG;
anx->dev.HPD_change_cnt = 0;
anx->dev.rk29_output_status = RK29_OUTPUT_STATUS_LCD;
anx->dev.hdcp_enable = ANX7150_HDCP_EN;
anx->init = 1;
anx->dev.workqueue = create_singlethread_workqueue("ANX7150_WORKQUEUE");
INIT_DELAYED_WORK(&anx->dev.delay_work, anx7150_work_func);
hdmi->display_on = 0;
hdmi->auto_switch = anx->dev.hdmi_auto_switch;
hdmi->hdcp_on = anx->dev.hdcp_enable;
hdmi->audio_fs = anx->dev.i2s_Fs;
hdmi->resolution = anx->dev.resolution_set;
hdmi->dev = &client->dev;
hdmi->hdmi_display_on = anx7150_display_on;
hdmi->hdmi_display_off = anx7150_display_off;
hdmi->hdmi_set_param = anx7150_set_param;
hdmi->hdmi_core_init = anx7150_core_init;
if((rc = hdmi_register(&client->dev, hdmi)) < 0)
{
dev_err(&client->dev, "fail to register hdmi\n");
goto err_hdmi_register;
}
if((rc = gpio_request(client->irq, "hdmi gpio")) < 0)
{
dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
goto err_request_gpio;
}
anx->irq = gpio_to_irq(client->irq);
anx->gpio = client->irq;
anx->dev.hdmi = hdmi;
hdmi_set_privdata(hdmi, anx);
i2c_set_clientdata(client, anx);
gpio_pull_updown(client->irq,GPIOPullUp);
if((rc = request_irq(anx->irq, anx7150_detect_irq,IRQF_TRIGGER_FALLING,NULL,hdmi)) <0)
{
dev_err(&client->dev, "fail to request hdmi irq\n");
goto err_request_irq;
}
anx->dev.anx7150_detect = anx7150_detect_device(anx);
if(anx->dev.anx7150_detect) {
ANX7150_API_Initial(client);
queue_delayed_work(anx->dev.workqueue, &anx->dev.delay_work, 200);
}
hdmi_dbg(&client->dev, "anx7150 i2c probe ok\n");
return 0;
err_request_irq:
gpio_free(client->irq);
err_request_gpio:
hdmi_unregister(hdmi);
err_hdmi_register:
destroy_workqueue(anx->dev.workqueue);
kfree(anx);
anx = NULL;
err_kzalloc_anx:
kfree(hdmi);
hdmi = NULL;
return rc;
}
static int __devexit anx7150_i2c_remove(struct i2c_client *client)
{
struct anx7150_pdata *anx = (struct anx7150_pdata *)i2c_get_clientdata(client);
struct hdmi *hdmi = anx->dev.hdmi;
free_irq(anx->irq, NULL);
gpio_free(client->irq);
hdmi_unregister(hdmi);
destroy_workqueue(anx->dev.workqueue);
kfree(anx);
anx = NULL;
kfree(hdmi);
hdmi = NULL;
hdmi_dbg(hdmi->dev, "%s\n", __func__);
return 0;
}
static const struct i2c_device_id anx7150_id[] = {
{ "anx7150", 0 },
{ }
};
static struct i2c_driver anx7150_i2c_driver = {
.driver = {
.name = "anx7150",
.owner = THIS_MODULE,
},
.probe = &anx7150_i2c_probe,
.remove = &anx7150_i2c_remove,
.id_table = anx7150_id,
};
static int __init anx7150_init(void)
{
return i2c_add_driver(&anx7150_i2c_driver);
}
static void __exit anx7150_exit(void)
{
i2c_del_driver(&anx7150_i2c_driver);
}
//module_init(anx7150_init);
fs_initcall(anx7150_init);
module_exit(anx7150_exit);

View File

@ -0,0 +1,102 @@
#ifndef _ANX7150_H
#define _ANX7150_H
#include <linux/hdmi.h>
#define ANX7150_I2C_ADDR0 0X39
#define ANX7150_I2C_ADDR1 0X3d
#define ANX7150_SCL_RATE 100 * 1000
/* HDMI STATUS */
#define HDMI_DISABLE 0
#define HDMI_ENABLE 1
/* HDMI auto switch */
#define HDMI_AUTO_SWITCH HDMI_ENABLE
/* HDMI reciver status */
#define HDMI_RECIVER_INACTIVE 0
#define HDMI_RECIVER_ACTIVE 1
/* ANX7150 reciver HPD Status */
#define HDMI_RECIVER_UNPLUG 0
#define HDMI_RECIVER_PLUG 1
#define LCD 0
#define HDMI 1
#define RK29_OUTPUT_STATUS_LCD LCD
#define RK29_OUTPUT_STATUS_HDMI HDMI
/* HDMI HDCP ENABLE */
#define ANX7150_HDCP_EN HDMI_DISABLE
/* HDMI default resolution */
#define HDMI_DEFAULT_RESOLUTION HDMI_1280x720p_50Hz
/* I2S Fs */
#define HDMI_I2S_Fs_44100 0
#define HDMI_I2S_Fs_48000 2
/* I2S default sample rate */
#define HDMI_I2S_DEFAULT_Fs HDMI_I2S_Fs_48000
/* ANX7150 state machine */
enum{
HDMI_INITIAL = 1,
WAIT_HOTPLUG,
READ_PARSE_EDID,
WAIT_RX_SENSE,
WAIT_HDMI_ENABLE,
SYSTEM_CONFIG,
CONFIG_VIDEO,
CONFIG_AUDIO,
CONFIG_PACKETS,
HDCP_AUTHENTICATION,
PLAY_BACK,
RESET_LINK,
UNKNOWN,
};
struct anx7150_dev_s{
struct i2c_driver *i2c_driver;
struct fasync_struct *async_queue;
struct workqueue_struct *workqueue;
struct delayed_work delay_work;
struct miscdevice *mdev;
void (*notifier_callback)(struct anx7150_dev_s *);
int anx7150_detect;
int resolution_set;
int resolution_real;
int i2s_Fs;
int hdmi_enable;
int hdmi_auto_switch;
int reciver_status;
int HPD_change_cnt;
int HPD_status;
int rk29_output_status;
int hdcp_enable;
int parameter_config;
int rate;
int fb_switch_state;
struct hdmi *hdmi;
};
struct anx7150_pdata {
int irq;
int gpio;
int init;
struct i2c_client *client;
struct anx7150_dev_s dev;
};
int anx7150_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val);
int anx7150_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val);
int anx7150_i2c_read_p1_reg(struct i2c_client *client, char reg, char *val);
int anx7150_i2c_write_p1_reg(struct i2c_client *client, char reg, char *val);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,492 @@
// ANALOGIX Company
// ANX7150 Demo Firmware
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/hdmi.h>
#include "anx7150_sys.h"
/******** define uint8 and WORD, by kfx *******/
int anx7150_tmds_enable(struct hdmi *hdmi)
{
int rc = 0;
char c;
/* andio stream enable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0)
return rc;
c |= (ANX7150_HDMI_AUDCTRL1_IN_EN);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0)
return rc;
/* video stream enable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0)
return rc;
c |= (ANX7150_VID_CTRL_IN_EN);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0)
return rc;
/* TMDS enable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0)
return rc;
c |= (ANX7150_TMDS_CLKCH_MUTE);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0)
return rc;
return rc;
}
int anx7150_tmds_disable(struct hdmi *hdmi)
{
int rc = 0;
char c;
/* andio stream disable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0)
return rc;
c &= (~ANX7150_HDMI_AUDCTRL1_IN_EN);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDMI_AUDCTRL1_REG, &c)) < 0)
return rc;
/* video stream disable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0)
return rc;
c &= (~ANX7150_VID_CTRL_IN_EN);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_VID_CTRL_REG, &c)) < 0)
return rc;
/* TMDS disable */
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0)
return rc;
c &= (~ANX7150_TMDS_CLKCH_MUTE);
if((rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_TMDS_CLKCH_CONFIG_REG, &c)) < 0)
return rc;
return rc;
}
static void anx7150_set_video_format(struct hdmi *hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
switch(hdmi->resolution)
{
case HDMI_720x576p_50Hz:
anx->video_format = ANX7150_V720x576p_50Hz_4x3;
break;
case ANX7150_V1280x720p_50Hz:
anx->video_format = ANX7150_V1280x720p_50Hz;
break;
case HDMI_1280x720p_60Hz:
anx->video_format = ANX7150_V1280x720p_60Hz;
break;
default:
anx->video_format = ANX7150_V1280x720p_50Hz;
break;
}
anx->system_config_done = 0;
return;
}
static void anx7150_set_audio_fs(struct hdmi *hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->audio_format = hdmi->audio_fs;
anx->system_config_done = 0;
return;
}
static void anx7150_set_system_state(struct hdmi *hdmi, unsigned char ss)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->system_state = ss;
switch (ss)
{
case ANX7150_INITIAL:
dev_info(hdmi->dev, "system state: ANX7150_INITIAL\n");
break;
case ANX7150_WAIT_HOTPLUG:
dev_info(hdmi->dev, "system state: ANX7150_WAIT_HOTPLUG\n");
break;
case ANX7150_READ_PARSE_EDID:
dev_info(hdmi->dev, "system state: ANX7150_READ_PARSE_EDID\n");
break;
case ANX7150_WAIT_RX_SENSE:
dev_info(hdmi->dev, "system state: ANX7150_WAIT_RX_SENSE\n");
break;
case ANX7150_CONFIG_VIDEO:
dev_info(hdmi->dev, "system state: ANX7150_CONFIG_VIDEO\n");
break;
case ANX7150_CONFIG_AUDIO:
dev_info(hdmi->dev, "system state: ANX7150_CONFIG_AUDIO\n");
break;
case ANX7150_CONFIG_PACKETS:
dev_info(hdmi->dev, "system state: ANX7150_CONFIG_PACKETS\n");
break;
case ANX7150_HDCP_AUTHENTICATION:
dev_info(hdmi->dev, "system state: ANX7150_HDCP_AUTHENTICATION\n");
break;
case ANX7150_RESET_LINK:
dev_info(hdmi->dev, "system state: ANX7150_RESET_LINK\n");
break;
case ANX7150_PLAY_BACK:
dev_info(hdmi->dev, "system state: ANX7150_PLAY_BACK\n");
break;
default:
dev_info(hdmi->dev, "system state: ANX7150 unknown state\n");
break;
}
return;
}
static void anx7150_variable_initial(struct hdmi *hdmi)
{
int i;
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx7150_set_system_state(hdmi, ANX7150_INITIAL);
anx->anx7150_hdcp_auth_en = 0;
anx->anx7150_ksv_srm_pass =0;
anx->anx7150_srm_checked = 0;
anx->anx7150_hdcp_auth_pass = 0;
anx->anx7150_avmute_enable = 1;
anx->anx7150_hdcp_auth_fail_counter =0;
anx->anx7150_hdcp_encryption = 0;
anx->anx7150_send_blue_screen = 0;
anx->anx7150_hdcp_init_done = 0;
anx->anx7150_hdcp_wait_100ms_needed = 1;
anx->anx7150_auth_fully_pass = 0;
anx->timer_slot = 0;
/***************for video config***************/
anx->anx7150_video_timing_id = 0;
anx->anx7150_in_pix_rpt = 0;
anx->anx7150_tx_pix_rpt = 0;
anx->anx7150_new_csc = 0;
anx->anx7150_new_vid_id = 0;
anx->anx7150_new_hw_interface = 0;
/*****************end of video config**********/
/********************for edid parse************/
anx->edid.is_HDMI = 0;
anx->edid.ycbcr422_supported = 0;
anx->edid.ycbcr444_supported = 0;
anx->edid.supported_720p_60Hz = 0;
anx->edid.supported_720p_50Hz = 0;
anx->edid.supported_576p_50Hz = 0;
anx->edid.supported_576i_50Hz = 0;
anx->edid.supported_1080i_60Hz = 0;
anx->edid.supported_1080i_50Hz = 0;
anx->edid.supported_640x480p_60Hz = 0;
anx->edid.supported_720x480p_60Hz = 0;
anx->edid.supported_720x480i_60Hz = 0;
anx->edid.edid_errcode = 0;
anx->edid.SpeakerFormat = 0;
for (i = 0; i < 8; i ++)
{
anx->edid.AudioChannel[i] = 0;
anx->edid.AudioFormat[i] = 0;
anx->edid.AudioFs[i] = 0;
anx->edid.AudioLength[i] = 0;
}
/********************end of edid****************/
anx->packets_config.packets_need_config = 0x03; //new avi infoframe
anx->packets_config.avi_info.type = 0x82;
anx->packets_config.avi_info.version = 0x02;
anx->packets_config.avi_info.length = 0x0d;
anx->packets_config.avi_info.pb_uint8[1] = 0x21;//YCbCr422
anx->packets_config.avi_info.pb_uint8[2] = 0x08;
anx->packets_config.avi_info.pb_uint8[3] = 0x00;
anx->packets_config.avi_info.pb_uint8[4] = 0x00;
anx->packets_config.avi_info.pb_uint8[5] = 0x00;
anx->packets_config.avi_info.pb_uint8[6] = 0x00;
anx->packets_config.avi_info.pb_uint8[7] = 0x00;
anx->packets_config.avi_info.pb_uint8[8] = 0x00;
anx->packets_config.avi_info.pb_uint8[9] = 0x00;
anx->packets_config.avi_info.pb_uint8[10] = 0x00;
anx->packets_config.avi_info.pb_uint8[11] = 0x00;
anx->packets_config.avi_info.pb_uint8[12] = 0x00;
anx->packets_config.avi_info.pb_uint8[13] = 0x00;
// audio infoframe
anx->packets_config.audio_info.type = 0x84;
anx->packets_config.audio_info.version = 0x01;
anx->packets_config.audio_info.length = 0x0a;
anx->packets_config.audio_info.pb_uint8[1] = 0x00; //zy 061123 for ATC
anx->packets_config.audio_info.pb_uint8[2] = 0x00;
anx->packets_config.audio_info.pb_uint8[3] = 0x00;
anx->packets_config.audio_info.pb_uint8[4] = 0x00;
anx->packets_config.audio_info.pb_uint8[5] = 0x00;
anx->packets_config.audio_info.pb_uint8[6] = 0x00;
anx->packets_config.audio_info.pb_uint8[7] = 0x00;
anx->packets_config.audio_info.pb_uint8[8] = 0x00;
anx->packets_config.audio_info.pb_uint8[9] = 0x00;
anx->packets_config.audio_info.pb_uint8[10] = 0x00;
anx->anx7150_int_done = 0;
}
static void anx7150_hw_interface_variable_initial(struct hdmi *hdmi)
{
unsigned char c;
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->anx7150_video_format_config = 0x00;
anx->anx7150_rgborycbcr = 0x00;
anx->anx7150_ddr_edge = ANX7150_IDCK_EDGE_DDR;
c = 0;
c = (ANX7150_I2S_CH0_ENABLE << 2) | (ANX7150_I2S_CH1_ENABLE << 3) |
(ANX7150_I2S_CH2_ENABLE << 4) | (ANX7150_I2S_CH3_ENABLE << 5);
anx->audio_config.audio_type = ANX7150_AUD_HW_INTERFACE; // input I2S
anx->audio_config.down_sample = 0x00;
anx->audio_config.i2s_config.audio_channel = c;//0x04;
anx->audio_config.i2s_config.Channel_status1 =0x00;
anx->audio_config.i2s_config.Channel_status1 = 0x00;
anx->audio_config.i2s_config.Channel_status2 = 0x00;
anx->audio_config.i2s_config.Channel_status3 = 0x00;
anx->audio_config.i2s_config.Channel_status4 = 0x00;//0x02;//48k
anx->audio_config.i2s_config.Channel_status5 = ANX7150_I2S_WORD_LENGTH;//0x0b;
anx->audio_config.audio_layout = 0x00;
c = (ANX7150_I2S_SHIFT_CTRL << 3) | (ANX7150_I2S_DIR_CTRL << 2) |
(ANX7150_I2S_WS_POL << 1) | ANX7150_I2S_JUST_CTRL;
anx->audio_config.i2s_config.i2s_format = c;//0x00;
anx->freq_mclk= ANX7150_MCLK_Fs_RELATION;//set the relation of MCLK and WS
anx->anx7150_audio_clock_edge = ANX7150_AUD_CLK_EDGE;
return;
}
static int anx7150_hardware_initial(struct hdmi *hdmi)
{
int rc = 0;
char c = 0;
//clear HDCP_HPD_RST
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c);
c |= (0x01);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c);
mdelay(10);
c &= (~0x01);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c);
//Power on I2C
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);
c |= (ANX7150_SYS_CTRL3_I2C_PWON);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);
c = 0x00;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL2_REG, &c);
c= 0x00;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SRST_REG, &c);
//clear HDCP_HPD_RST
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c);
c &= (0xbf);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c);
//Power on Audio capture and Video capture module clock
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_PD_REG, &c);
c |= (0x06);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_PD_REG, &c);
//Enable auto set clock range for video PLL
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_CHIP_CTRL_REG, &c);
c &= (0x00);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_CHIP_CTRL_REG, &c);
//Set registers value of Blue Screen when HDCP authentication failed--RGB mode,green field
c = 0x10;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN0_REG, &c);
c = 0xeb;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN1_REG, &c);
c = 0x10;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_HDCP_BLUESCREEN2_REG, &c);
//ANX7150_i2c_read_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, &c);
//ANX7150_i2c_write_p0_reg(ANX7150_TMDS_CLKCH_CONFIG_REG, (c | 0x80));
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_PLL_CTRL0_REG, &c);
c = 0x00;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_CTRL0_REG, &c);
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c);
c |= (0x08);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_CHIP_DEBUG1_CTRL_REG, &c);
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_PLL_TX_AMP, &c);//jack wen
c |= (0x01);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_TX_AMP, &c); //TMDS swing
c = 0x00;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_PLL_CTRL1_REG, &c); //Added for PLL unlock issue in high temperature - Feiw
//if (ANX7150_AUD_HW_INTERFACE == 0x02) //jack wen, spdif
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_I2S_CTRL_REG, &c);//jack wen, for spdif input from SD0.
c &= (0xef);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_I2S_CTRL_REG, &c);
c = 0xc7;
rc = anx7150_i2c_write_p0_reg(hdmi->client, 0xE1, &c);
//ANX7150_i2c_read_p0_reg(ANX7150_SYS_CTRL1_REG, &c);
c = 0x00;
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL1_REG, &c);//power down HDCP, 090630
rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);//jack wen, for spdif input from SD0.
c &= (0xef);
rc = anx7150_i2c_write_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c);//power down all, 090630
//anx7150_set_system_state(hdmi, ANX7150_WAIT_HOTPLUG);
return rc;
}
static int anx7150_initial(struct hdmi *hdmi)
{
int rc = 0;
anx7150_variable_initial(hdmi);
anx7150_hw_interface_variable_initial(hdmi);
rc = anx7150_hardware_initial(hdmi);
return rc;
}
static void anx7150_set_hdcp_state(struct hdmi* hdmi)
{
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->hdcp_on = hdmi->hdcp_on;
return;
}
int anx7150_system_init(struct hdmi *hdmi)
{
int rc = 0;
if((rc = anx7150_detect_device(hdmi)) < 0)
{
dev_err(hdmi->dev, "anx7150 api detectdevice err!\n");
return rc;
}
anx7150_set_audio_fs(hdmi);
if((rc = anx7150_initial(hdmi)) < 0)
{
dev_err(hdmi->dev, "anx7150 initial err!\n");
return rc;
}
anx7150_set_hdcp_state(hdmi);
return 0;
}
static u8 anx7150_detect_device(struct hdmi *hdmi)
{
int i, rc = 0;
char d1, d2;
for (i=0; i<10; i++)
{
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_DEV_IDL_REG, &d1)) < 0)
continue;
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_DEV_IDH_REG, &d2)) < 0)
continue;
if (d1 == 0x50 && d2 == 0x71)
{
dev_info(hdmi->dev, "anx7150 detected!\n");
return 1;
}
}
dev_info(hdmi->dev, "anx7150 not detected");
return 0;
}
static u8 anx7150_get_system_state(struct anx7150_pdata *anx)
{
return anx->anx7150_system_state;
}
static u8 anx7150_get_hpd(struct i2c_client *client)
{
char c;
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_CTRL3_REG, &c)) < 0)
return rc;
if(c & ANX7150_SYS_CTRL3_PWON_ALL)
{
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_SYS_STATE_REG, &c)) < 0)
return rc;
return (c & ANX7150_SYS_STATE_HP)? 1:0;
}
else
{
if((rc = anx7150_i2c_read_p0_reg(hdmi->client, ANX7150_INTR_STATE_REG, &c)) < 0)
return rc;
return (c)? 1:0;
}
}
static u8 anx7150_interrupt_process(struct hdmi *hdmi, int state)
{
int hot_plug;
int rc;
hot_plug = anx7150_get_hpd(hdmi->client);
}
int anx7150_display_on_hw(struct hdmi *hdmi)
{
u8 state;
struct anx7150_pdata *anx = hdmi_get_privdata(hdmi);
anx->anx7150_detect = anx7150_detect_device(hdmi);
if(anx->anx7150_detect < 0)
{
return -EIO;
}
state = anx7150_get_system_state(anx);
if(hdmi->display_on == 0 && hdmi->auto_switch == 0)
{
if(state > WAIT_HDMI_ENABLE)
state = INITIAL;
}
if(hdmi->param_conf == 1)
{
if(state > WAIT_HDMI_ENABLE)
state = WAIT_HDMI_ENABLE;
hdmi->param_conf = 0;
}
state = anx7150_interrupt_process();
}

View File

@ -0,0 +1,6 @@
#include <linux/hdmi.h>
int hdmi_codec_set_audio_fs(unsigned char audio_fs)
{
return 0;
}

129
drivers/video/hdmi/hdmi-core.c Executable file
View File

@ -0,0 +1,129 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/hdmi.h>
struct class *hdmi_class;
struct hdmi_id_ref_info {
int id;
int ref;
}ref_info[HDMI_MAX_ID];
#ifdef CONFIG_SYSFS
extern int hdmi_create_attrs(struct hdmi *hdmi);
extern void hdmi_remove_attrs(struct hdmi *hdmi);
#else
static inline int hdmi_create_attrs(struct hdmi *hdmi)
{ return 0; }
static inline void hdmi_remove_attrs(struct hdmi *hdmi) {}
#endif /* CONFIG_SYSFS */
void *hdmi_get_privdata(struct hdmi *hdmi)
{
return hdmi->priv;
}
void hdmi_set_privdata(struct hdmi *hdmi, void *data)
{
hdmi->priv = data;
return;
}
void hdmi_changed(struct hdmi *hdmi, int plug)
{
hdmi_dbg(hdmi->dev, "%s\n", __FUNCTION__);
hdmi->plug = plug;
schedule_work(&hdmi->changed_work);
}
static void hdmi_changed_work(struct work_struct *work)
{
struct hdmi *hdmi = container_of(work, struct hdmi,
changed_work);
hdmi_dbg(hdmi->dev, "%s\n", __FUNCTION__);
kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
}
int hdmi_register(struct device *parent, struct hdmi *hdmi)
{
int rc = 0, i;
char name[8];
for(i = 0; i < HDMI_MAX_ID; i++)
{
if(ref_info[i].ref == 0)
{
ref_info[i].ref = 1;
hdmi->id = i;
break;
}
}
if(i == HDMI_MAX_ID)
return -EINVAL;
sprintf(name, "hdmi-%d", hdmi->id);
hdmi->dev = device_create(hdmi_class, parent, 0,
"%s", name);
if (IS_ERR(hdmi->dev)) {
rc = PTR_ERR(hdmi->dev);
goto dev_create_failed;
}
dev_set_drvdata(hdmi->dev, hdmi);
INIT_WORK(&hdmi->changed_work, hdmi_changed_work);
rc = hdmi_create_attrs(hdmi);
if (rc)
goto create_attrs_failed;
//hdmi_changed(hdmi, 0);
goto success;
create_attrs_failed:
device_unregister(hdmi->dev);
dev_create_failed:
success:
return rc;
}
void hdmi_unregister(struct hdmi *hdmi)
{
flush_scheduled_work();
hdmi_remove_attrs(hdmi);
device_unregister(hdmi->dev);
ref_info[hdmi->id].ref = 0;
}
static int __init hdmi_class_init(void)
{
int i;
hdmi_class = class_create(THIS_MODULE, "hdmi");
if (IS_ERR(hdmi_class))
return PTR_ERR(hdmi_class);
for(i = 0; i < HDMI_MAX_ID; i++) {
ref_info[i].id = i;
ref_info[i].ref = 0;
}
return 0;
}
static void __exit hdmi_class_exit(void)
{
class_destroy(hdmi_class);
}
EXPORT_SYMBOL(hdmi_changed);
EXPORT_SYMBOL(hdmi_register);
EXPORT_SYMBOL(hdmi_unregister);
subsys_initcall(hdmi_class_init);
module_exit(hdmi_class_exit);

196
drivers/video/hdmi/hdmi-fb.c Executable file
View File

@ -0,0 +1,196 @@
#include <linux/console.h>
#include <linux/fb.h>
#include <linux/hdmi.h>
#include "../display/screen/screen.h"
#include "../rk29_fb.h"
/* Base */
#define OUT_TYPE SCREEN_RGB
#define OUT_FACE OUT_P888
#define DCLK_POL 0
#define SWAP_RB 0
/* 720p@60Hz Timing */
#define OUT_CLK 74250000
#define H_PW 40
#define H_BP 220
#define H_VD 1280
#define H_FP 110
#define V_PW 5
#define V_BP 20
#define V_VD 720
#define V_FP 5
/* 720p@50Hz Timing */
#define OUT_CLK2 74250000
#define H_PW2 40
#define H_BP2 220
#define H_VD2 1280
#define H_FP2 440
#define V_PW2 5
#define V_BP2 20
#define V_VD2 720
#define V_FP2 5
/* 576p@50Hz Timing */
#define OUT_CLK3 27000000
#define H_PW3 64
#define H_BP3 68
#define H_VD3 720
#define H_FP3 12
#define V_PW3 5
#define V_BP3 39
#define V_VD3 576
#define V_FP3 5
extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable );
static int anx7150_init(void)
{
return 0;
}
static int anx7150_standby(u8 enable)
{
return 0;
}
static void hdmi_set_info(struct rk29fb_screen *screen)
{
struct rk29fb_screen *screen2 = screen + 1;
struct rk29fb_screen *screen3 = screen + 2;
/* ****************** 720p@60Hz ******************* */
/* screen type & face */
screen->type = OUT_TYPE;
screen->face = OUT_FACE;
/* Screen size */
screen->x_res = H_VD;
screen->y_res = V_VD;
/* Timing */
screen->pixclock = OUT_CLK;
screen->left_margin = H_BP;
screen->right_margin = H_FP;
screen->hsync_len = H_PW;
screen->upper_margin = V_BP;
screen->lower_margin = V_FP;
screen->vsync_len = V_PW;
/* Pin polarity */
screen->pin_hsync = 0;
screen->pin_vsync = 0;
screen->pin_den = 0;
screen->pin_dclk = DCLK_POL;
/* Swap rule */
screen->swap_rb = SWAP_RB;
screen->swap_rg = 0;
screen->swap_gb = 0;
screen->swap_delta = 0;
screen->swap_dumy = 0;
/* Operation function*/
screen->init = anx7150_init;
screen->standby = anx7150_standby;
/* ****************** 720p@50Hz ******************* */
/* screen type & face */
screen2->type = OUT_TYPE;
screen2->face = OUT_FACE;
/* Screen size */
screen2->x_res = H_VD2;
screen2->y_res = V_VD2;
/* Timing */
screen2->pixclock = OUT_CLK2;
screen2->left_margin = H_BP2;
screen2->right_margin = H_FP2;
screen2->hsync_len = H_PW2;
screen2->upper_margin = V_BP2;
screen2->lower_margin = V_FP2;
screen2->vsync_len = V_PW2;
/* Pin polarity */
screen2->pin_hsync = 0;
screen2->pin_vsync = 0;
screen2->pin_den = 0;
screen2->pin_dclk = DCLK_POL;
/* Swap rule */
screen2->swap_rb = SWAP_RB;
screen2->swap_rg = 0;
screen2->swap_gb = 0;
screen2->swap_delta = 0;
screen2->swap_dumy = 0;
/* Operation function*/
screen2->init = anx7150_init;
screen2->standby = anx7150_standby;
/* ****************** 576p@50Hz ******************* */
/* screen type & face */
screen3->type = OUT_TYPE;
screen3->face = OUT_FACE;
/* Screen size */
screen3->x_res = H_VD3;
screen3->y_res = V_VD3;
/* Timing */
screen3->pixclock = OUT_CLK3;
screen3->left_margin = H_BP3;
screen3->right_margin = H_FP3;
screen3->hsync_len = H_PW3;
screen3->upper_margin = V_BP3;
screen3->lower_margin = V_FP3;
screen3->vsync_len = V_PW3;
/* Pin polarity */
screen3->pin_hsync = 0;
screen3->pin_vsync = 0;
screen3->pin_den = 0;
screen3->pin_dclk = DCLK_POL;
/* Swap rule */
screen3->swap_rb = SWAP_RB;
screen3->swap_rg = 0;
screen3->swap_gb = 0;
screen3->swap_delta = 0;
screen3->swap_dumy = 0;
/* Operation function*/
screen3->init = anx7150_init;
screen3->standby = anx7150_standby;
}
int hdmi_switch_fb(int resolution, int type)
{
int rc = 0;
struct rk29fb_screen hdmi_info[3];
hdmi_set_info(&hdmi_info[0]);
switch(resolution)
{
case HDMI_1280x720p_50Hz:
rc = FB_Switch_Screen(&hdmi_info[1], type);
break;
case HDMI_1280x720p_60Hz:
rc = FB_Switch_Screen(&hdmi_info[0], type);
break;
case HDMI_720x576p_50Hz:
rc = FB_Switch_Screen(&hdmi_info[2], type);
break;
default:
rc = FB_Switch_Screen(&hdmi_info[1], type);
break;
}
return rc;
}

162
drivers/video/hdmi/hdmi-sysfs.c Executable file
View File

@ -0,0 +1,162 @@
#include <linux/ctype.h>
#include <linux/hdmi.h>
#include <linux/string.h>
static ssize_t hdmi_show_state_attrs(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hdmi *hdmi = dev_get_drvdata(dev);
return sprintf(buf, "display_on=%d\n"
"plug=%d\n"
"--------------------------\n"
"resolution support:\n"
"0 -- 1280x720p_50Hz\n"
"1 -- 1280x720p_60Hz\n"
"2 -- 720x576p_50Hz\n"
"--------------------------\n"
"auto_switch=%d\n"
"hdcp_on=%d\n"
"audio_fs=%d\n"
"resolution=%d\n",
hdmi->display_on,hdmi->plug,
hdmi->auto_switch, hdmi->hdcp_on,
hdmi->audio_fs, hdmi->resolution);
}
static ssize_t hdmi_restore_state_attrs(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct hdmi *hdmi = dev_get_drvdata(dev);
char *p;
const char *q;
int auto_switch = -1, hdcp_on = -1, audio_fs = -1, resolution = -1;
q = buf;
do
{
if((p = strstr(q, "auto_switch=")) != NULL)
{
q = p + 12;
if((sscanf(q, "%d", &auto_switch) == 1) &&
(auto_switch == 0 || auto_switch == 1))
hdmi->auto_switch = auto_switch;
else
{
dev_err(dev, "failed to set hdmi configuration\n");
return -EINVAL;
}
}
else if((p = strstr(q, "hdcp_on=")) != NULL)
{
q = p + 8;
if((sscanf(q, "%d", &hdcp_on) == 1) &&
(hdcp_on == 0 || hdcp_on == 1))
hdmi->hdcp_on = hdcp_on;
else
{
dev_err(dev, "failed to set hdmi configuration\n");
return -EINVAL;
}
}
else if((p = strstr(q, "audio_fs=")) != NULL)
{
q = p + 9;
if((sscanf(q, "%d", &audio_fs) == 1) &&
(audio_fs >= 0))
hdmi->audio_fs = audio_fs;
else
{
dev_err(dev, "failed to set hdmi configuration\n");
return -EINVAL;
}
}
else if((p = strstr(q, "resolution=")) != NULL)
{
q = p + 11;
if((sscanf(q, "%d", &resolution) == 1) &&
(resolution >= 0))
hdmi->resolution = resolution;
else
{
dev_err(dev, "failed to set hdmi configuration\n");
return -EINVAL;
}
}
else
break;
}while(*q != 0);
if(auto_switch == -1 &&
hdcp_on == -1 &&
audio_fs == -1 &&
resolution == -1)
{
dev_err(dev, "failed to set hdmi configuration\n");
return -EINVAL;
}
if(hdmi->hdmi_set_param)
hdmi->hdmi_set_param(hdmi);
return size;
}
static ssize_t hdmi_show_switch_attrs(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hdmi *hdmi = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", hdmi->display_on);
}
static ssize_t hdmi_restore_switch_attrs(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
int display_on = 0;
struct hdmi *hdmi = dev_get_drvdata(dev);
sscanf(buf, "%d", &display_on);
if(hdmi->hdmi_display_on && display_on == 1)
hdmi->hdmi_display_on(hdmi);
else if(hdmi->hdmi_display_off && display_on == 0)
hdmi->hdmi_display_off(hdmi);
return size;
}
static struct device_attribute hdmi_attrs[] = {
__ATTR(state, 0664, hdmi_show_state_attrs, hdmi_restore_state_attrs),
__ATTR(enable, 0664, hdmi_show_switch_attrs, hdmi_restore_switch_attrs),
};
int hdmi_create_attrs(struct hdmi *hdmi)
{
int rc = 0;
int i;
for (i = 0; i < ARRAY_SIZE(hdmi_attrs); i++) {
rc = device_create_file(hdmi->dev, &hdmi_attrs[i]);
if (rc)
goto create_failed;
}
goto succeed;
create_failed:
while (i--)
device_remove_file(hdmi->dev, &hdmi_attrs[i]);
succeed:
return rc;
}
void hdmi_remove_attrs(struct hdmi *hdmi)
{
int i;
for (i = 0; i < ARRAY_SIZE(hdmi_attrs); i++)
device_remove_file(hdmi->dev, &hdmi_attrs[i]);
}

File diff suppressed because it is too large Load Diff

70
include/linux/hdmi.h Executable file
View File

@ -0,0 +1,70 @@
/* include/linux/hdmi.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef __LINUX_HDMI_CORE_H
#define __LINUX_HDMI_CORE_H
#include <linux/device.h>
#include <linux/workqueue.h>
#include <linux/i2c.h>
#ifdef CONFIG_HDMI_DEBUG
#define hdmi_dbg(dev, format, arg...) \
dev_printk(KERN_INFO , dev , format , ## arg)
#else
#define hdmi_dbg(dev, format, arg...)
#endif
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define HDMI_1280x720p_50Hz 0
#define HDMI_1280x720p_60Hz 1
#define HDMI_720x576p_50Hz 2
#define HDMI_MAX_ID 32
struct hdmi {
struct device *dev;
struct work_struct changed_work;
int id;
BOOL display_on;
BOOL plug;
BOOL auto_switch;
BOOL hdcp_on;
BOOL param_conf;
u8 resolution;
u8 audio_fs;
void *priv;
int (*hdmi_display_on)(struct hdmi *);
int (*hdmi_display_off)(struct hdmi *);
int (*hdmi_set_param)(struct hdmi *);
int (*hdmi_core_init)(struct hdmi *);
};
extern void *hdmi_get_privdata(struct hdmi *hdmi);
extern void hdmi_set_privdata(struct hdmi *hdmi, void *data);
extern int hdmi_register(struct device *parent, struct hdmi *hdmi);
extern void hdmi_unregister(struct hdmi *hdmi);
extern void hdmi_changed(struct hdmi *hdmi, int plug);
extern int hdmi_codec_set_audio_fs(unsigned char audio_fs);
extern int hdmi_fb_set_resolution(unsigned char resolution);
extern int hdmi_switch_fb(int resolution, int type);
#endif