mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
rk610 hdmi lcd lvds tvout codec support
This commit is contained in:
parent
ac1afdbe8f
commit
cbba37b0bb
|
|
@ -1705,6 +1705,35 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = {
|
|||
.platform_data = &bu92747guw_pdata,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_MFD_RK610
|
||||
{
|
||||
.type = "rk610_ctl",
|
||||
.addr = 0x40,
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_RK610_TVOUT
|
||||
{
|
||||
.type = "rk610_tvout",
|
||||
.addr = 0x42,
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_RK610_HDMI
|
||||
{
|
||||
.type = "rk610_hdmi",
|
||||
.addr = 0x46,
|
||||
.flags = 0,
|
||||
.irq = RK29_PIN1_PD7,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SND_SOC_RK610
|
||||
{
|
||||
.type = "rk610_i2c_codec",
|
||||
.addr = 0x60,
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -626,8 +626,8 @@ static const struct codec_pll_set codec_pll[] = {
|
|||
// rate parent band NR NF NO
|
||||
CODEC_PLL(108000, 24, LOW, 1, 18, 4), // for TV
|
||||
CODEC_PLL(648000, 24, HIGH, 1, 27, 1),
|
||||
CODEC_PLL(148500, 27, LOW, 1, 22, 4), // for HDMI
|
||||
CODEC_PLL(297000, 27, LOW, 1, 22, 2),
|
||||
CODEC_PLL(148500, 27, LOW, 2, 88, 8), //change for jetta hdmi dclk jitter 20120322// for HDMI
|
||||
CODEC_PLL(297000, 27, LOW, 2, 88, 4), //change for jetta hdmi dclk jitter 20120322// for HDMI
|
||||
CODEC_PLL(445500, 27, LOW, 2, 33, 1),
|
||||
CODEC_PLL(594000, 27, HIGH, 1, 22, 1),
|
||||
CODEC_PLL(891000, 27, HIGH, 1, 33, 1),
|
||||
|
|
|
|||
|
|
@ -742,6 +742,13 @@ config MFD_TPS65910
|
|||
config TPS65911_COMPARATOR
|
||||
tristate
|
||||
|
||||
config MFD_RK610
|
||||
bool "RK610(Jetta) Multimedia support"
|
||||
depends on I2C=y && GPIOLIB
|
||||
select MFD_CORE
|
||||
help
|
||||
if you say yes here you get support for the RK610, with func as
|
||||
HDMI LCD LVDS TVOUT CODEC.
|
||||
endif # MFD_SUPPORT
|
||||
|
||||
menu "Multimedia Capabilities Port drivers"
|
||||
|
|
|
|||
|
|
@ -96,3 +96,4 @@ obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
|
|||
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
|
||||
obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o
|
||||
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
|
||||
obj-$(CONFIG_MFD_RK610) += rk610-core.o
|
||||
272
drivers/mfd/rk610-core.c
Normal file
272
drivers/mfd/rk610-core.c
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <linux/mfd/rk610_core.h>
|
||||
#include <linux/clk.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define RK610_RESET_PIN RK29_PIN6_PC1
|
||||
|
||||
static struct i2c_client *rk610_control_client = NULL;
|
||||
#ifdef CONFIG_RK610_LCD
|
||||
extern int rk610_lcd_init(struct i2c_client *client);
|
||||
#else
|
||||
int rk610_lcd_init(struct i2c_client *client){}
|
||||
#endif
|
||||
int rk610_control_send_byte(const char reg, const char data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk("reg = 0x%02x, val=0x%02x\n", reg ,data);
|
||||
|
||||
if(rk610_control_client == NULL)
|
||||
return -1;
|
||||
//i2c_master_reg8_send
|
||||
ret = i2c_master_reg8_send(rk610_control_client, reg, &data, 1, 100*1000);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_SOC_RK610
|
||||
static unsigned int current_pll_value = 0;
|
||||
int rk610_codec_pll_set(unsigned int rate)
|
||||
{
|
||||
char N, M, NO, DIV;
|
||||
unsigned int F;
|
||||
char data;
|
||||
|
||||
if(current_pll_value == rate)
|
||||
return 0;
|
||||
|
||||
// Input clock is 12MHz.
|
||||
if(rate == 11289600) {
|
||||
// For 11.2896MHz, N = 2 M= 75 F = 0.264(0x43958) NO = 8
|
||||
N = 2;
|
||||
NO = 3;
|
||||
M = 75;
|
||||
F = 0x43958;
|
||||
DIV = 5;
|
||||
}
|
||||
else if(rate == 12288000) {
|
||||
// For 12.2888MHz, N = 2 M= 75 F = 0.92(0xEB851) NO = 8
|
||||
N = 2;
|
||||
NO = 3;
|
||||
M = 75;
|
||||
F = 0xEB851;
|
||||
DIV = 5;
|
||||
}
|
||||
else {
|
||||
printk(KERN_ERR "[%s] not support such frequency\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Enable codec pll fractional number and power down.
|
||||
data = 0x00;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
|
||||
msleep(10);
|
||||
|
||||
data = (N << 4) | NO;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON0, data);
|
||||
// M
|
||||
data = M;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON1, data);
|
||||
// F
|
||||
data = F & 0xFF;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON2, data);
|
||||
data = (F >> 8) & 0xFF;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON3, data);
|
||||
data = (F >> 16) & 0xFF;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON4, data);
|
||||
|
||||
// i2s mclk = codec_pll/5;
|
||||
i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
|
||||
data &= ~CLOCK_CON1_I2S_DVIDER_MASK;
|
||||
data |= (DIV - 1);
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
|
||||
|
||||
// Power up codec pll.
|
||||
data |= C_PLL_POWER_ON;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
|
||||
|
||||
current_pll_value = rate;
|
||||
printk(KERN_ERR "[%s] rate %u\n", __FUNCTION__, rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rk610_control_init_codec(void)
|
||||
{
|
||||
struct i2c_client *client = rk610_control_client;
|
||||
char data = 0;
|
||||
int ret;
|
||||
|
||||
if(rk610_control_client == NULL)
|
||||
return;
|
||||
printk(KERN_ERR "[%s] start\n", __FUNCTION__);
|
||||
|
||||
//gpio_set_value(RK610_RESET_PIN, GPIO_LOW); //reset rk601
|
||||
// mdelay(100);
|
||||
//gpio_set_value(RK610_RESET_PIN, GPIO_HIGH);
|
||||
//mdelay(100);
|
||||
|
||||
// Set i2c glitch timeout.
|
||||
data = 0x22;
|
||||
ret = i2c_master_reg8_send(client, RK610_CONTROL_REG_I2C_CON, &data, 1, 20*1000);
|
||||
|
||||
// rk610_codec_pll_set(11289600);
|
||||
|
||||
//use internal codec, enable DAC ADC LRCK output.
|
||||
// i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
|
||||
// data = CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE | CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
|
||||
// data = CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
|
||||
data = 0;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_CODEC_CON, data);
|
||||
|
||||
// Select internal i2s clock from codec_pll.
|
||||
i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
|
||||
// data |= CLOCK_CON1_I2S_CLK_CODEC_PLL;
|
||||
data = 0;
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
|
||||
|
||||
i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
|
||||
printk(KERN_ERR "[%s] RK610_CONTROL_REG_CODEC_CON is %x\n", __FUNCTION__, data);
|
||||
|
||||
i2c_master_reg8_recv(client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
|
||||
printk(KERN_ERR "[%s] RK610_CONTROL_REG_CLOCK_CON1 is %x\n", __FUNCTION__, data);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_RK610_DEBUG
|
||||
static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
{
|
||||
return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
}
|
||||
|
||||
static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
{
|
||||
return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
}
|
||||
static ssize_t rk610_show_reg_attrs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
|
||||
int i,size=0;
|
||||
char val;
|
||||
struct i2c_client *client=rk610_control_client;
|
||||
|
||||
for(i=0;i<256;i++)
|
||||
{
|
||||
rk610_read_p0_reg(client, i, &val);
|
||||
if(i%16==0)
|
||||
size += sprintf(buf+size,"\n>>>rk610_hdmi %x:",i);
|
||||
size += sprintf(buf+size," %2x",val);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
static ssize_t rk610_store_reg_attrs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct i2c_client *client=NULL;
|
||||
static char val=0,reg=0;
|
||||
client = rk610_control_client;
|
||||
printk("/**********rk610 reg config******/");
|
||||
|
||||
sscanf(buf, "%x%x", &val,®);
|
||||
printk("reg=%x val=%x\n",reg,val);
|
||||
rk610_write_p0_reg(client, reg, &val);
|
||||
printk("val=%x\n",val);
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct device_attribute rk610_attrs[] = {
|
||||
__ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs),
|
||||
};
|
||||
#endif
|
||||
static int rk610_control_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct clk *iis_clk;
|
||||
|
||||
iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
|
||||
if (IS_ERR(iis_clk)) {
|
||||
printk("failed to get i2s clk\n");
|
||||
ret = PTR_ERR(iis_clk);
|
||||
}else{
|
||||
printk("got i2s clk ok!\n");
|
||||
clk_enable(iis_clk);
|
||||
clk_set_rate(iis_clk, 11289600);
|
||||
rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
|
||||
clk_put(iis_clk);
|
||||
}
|
||||
|
||||
rk610_control_client = client;
|
||||
msleep(100);
|
||||
if(RK610_RESET_PIN != INVALID_GPIO) {
|
||||
ret = gpio_request(RK610_RESET_PIN, "rk610 reset");
|
||||
if (ret){
|
||||
printk(KERN_ERR "rk610_control_probe request gpio fail\n");
|
||||
}
|
||||
else {
|
||||
printk(KERN_ERR "rk610_control_probe request gpio ok\n");
|
||||
gpio_direction_output(RK610_RESET_PIN, GPIO_HIGH);
|
||||
msleep(100);
|
||||
gpio_direction_output(RK610_RESET_PIN, GPIO_LOW);
|
||||
msleep(100);
|
||||
gpio_set_value(RK610_RESET_PIN, GPIO_HIGH);
|
||||
}
|
||||
}
|
||||
rk610_lcd_init(client);
|
||||
#ifdef CONFIG_RK610_DEBUG
|
||||
device_create_file(&(client->dev), &rk610_attrs[0]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_control_remove(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rk610_control_id[] = {
|
||||
{ "rk610_ctl", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rk610_control_id);
|
||||
|
||||
static struct i2c_driver rk610_control_driver = {
|
||||
.driver = {
|
||||
.name = "rk610_ctl",
|
||||
},
|
||||
.probe = rk610_control_probe,
|
||||
.remove = rk610_control_remove,
|
||||
.id_table = rk610_control_id,
|
||||
};
|
||||
|
||||
static int __init rk610_control_init(void)
|
||||
{
|
||||
return i2c_add_driver(&rk610_control_driver);
|
||||
}
|
||||
|
||||
static void __exit rk610_control_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rk610_control_driver);
|
||||
}
|
||||
|
||||
fs_initcall(rk610_control_init);
|
||||
//module_init(rk610_control_init);
|
||||
module_exit(rk610_control_exit);
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("RK610 control driver");
|
||||
MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
@ -22,5 +22,8 @@ config DISPLAY_SUPPORT
|
|||
comment "Display hardware drivers"
|
||||
depends on DISPLAY_SUPPORT
|
||||
source "drivers/video/display/screen/Kconfig"
|
||||
source "drivers/video/display/lcd/Kconfig"
|
||||
source "drivers/video/display/tve/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# Display drivers
|
||||
|
||||
display-objs := display-sysfs.o
|
||||
display-objs := display-sys.o
|
||||
|
||||
obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
|
||||
obj-$(CONFIG_DISPLAY_SUPPORT) += screen/
|
||||
obj-y += lcd/
|
||||
obj-y += tve/
|
||||
404
drivers/video/display/display-sys.c
Normal file
404
drivers/video/display/display-sys.c
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/display-sys.h>
|
||||
|
||||
static struct list_head display_device_list;
|
||||
|
||||
static ssize_t display_show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
|
||||
}
|
||||
|
||||
static ssize_t display_show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
|
||||
}
|
||||
|
||||
static ssize_t display_show_enable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
int enable;
|
||||
if(dsp->ops && dsp->ops->getenable)
|
||||
enable = dsp->ops->getenable(dsp);
|
||||
else
|
||||
return 0;
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", enable);
|
||||
}
|
||||
|
||||
static ssize_t display_store_enable(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
int enable;
|
||||
|
||||
sscanf(buf, "%d", &enable);
|
||||
if(dsp->ops && dsp->ops->setenable)
|
||||
dsp->ops->setenable(dsp, enable);
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_show_connect(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
int connect;
|
||||
if(dsp->ops && dsp->ops->getstatus)
|
||||
connect = dsp->ops->getstatus(dsp);
|
||||
else
|
||||
return 0;
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", connect);
|
||||
}
|
||||
|
||||
static int mode_string(char *buf, unsigned int offset,
|
||||
const struct fb_videomode *mode)
|
||||
{
|
||||
// char m = 'U';
|
||||
char v = 'p';
|
||||
|
||||
// if (mode->flag & FB_MODE_IS_DETAILED)
|
||||
// m = 'D';
|
||||
// if (mode->flag & FB_MODE_IS_VESA)
|
||||
// m = 'V';
|
||||
// if (mode->flag & FB_MODE_IS_STANDARD)
|
||||
// m = 'S';
|
||||
|
||||
if (mode->vmode & FB_VMODE_INTERLACED)
|
||||
v = 'i';
|
||||
if (mode->vmode & FB_VMODE_DOUBLE)
|
||||
v = 'd';
|
||||
|
||||
return snprintf(&buf[offset], PAGE_SIZE - offset, "%dx%d%c-%d\n",
|
||||
mode->xres, mode->yres, v, mode->refresh);
|
||||
}
|
||||
static ssize_t display_show_modes(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
struct list_head *modelist, *pos;
|
||||
struct fb_modelist *fb_modelist;
|
||||
const struct fb_videomode *mode;
|
||||
int i;
|
||||
if(dsp->ops && dsp->ops->getmodelist)
|
||||
{
|
||||
if(dsp->ops->getmodelist(dsp, &modelist))
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
list_for_each(pos, modelist) {
|
||||
fb_modelist = list_entry(pos, struct fb_modelist, list);
|
||||
mode = &fb_modelist->mode;
|
||||
i += mode_string(buf, i, mode);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static ssize_t display_show_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
struct fb_videomode mode;
|
||||
|
||||
if(dsp->ops && dsp->ops->getmode)
|
||||
if(dsp->ops->getmode(dsp, &mode) == 0)
|
||||
return mode_string(buf, 0, &mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t display_store_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
char mstr[100];
|
||||
struct list_head *modelist, *pos;
|
||||
struct fb_modelist *fb_modelist;
|
||||
struct fb_videomode *mode;
|
||||
size_t i;
|
||||
|
||||
if(dsp->ops && dsp->ops->getmodelist)
|
||||
{
|
||||
if(dsp->ops && dsp->ops->getmodelist)
|
||||
{
|
||||
if(dsp->ops->getmodelist(dsp, &modelist))
|
||||
return -EINVAL;
|
||||
}
|
||||
list_for_each(pos, modelist) {
|
||||
fb_modelist = list_entry(pos, struct fb_modelist, list);
|
||||
mode = &fb_modelist->mode;
|
||||
i = mode_string(mstr, 0, mode);
|
||||
if (strncmp(mstr, buf, max(count, i)) == 0) {
|
||||
if(dsp->ops && dsp->ops->setmode)
|
||||
dsp->ops->setmode(dsp, mode);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct device_attribute display_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, display_show_name, NULL),
|
||||
__ATTR(type, S_IRUGO, display_show_type, NULL),
|
||||
__ATTR(enable, S_IRUGO | /*S_IWUGO*/S_IWUSR, display_show_enable, display_store_enable),
|
||||
__ATTR(connect, S_IRUGO, display_show_connect, NULL),
|
||||
__ATTR(modes, S_IRUGO, display_show_modes, NULL),
|
||||
__ATTR(mode, S_IRUGO | /*S_IWUGO*/S_IWUSR, display_show_mode, display_store_mode)
|
||||
};
|
||||
|
||||
static int display_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->suspend))
|
||||
dsp->driver->suspend(dsp, state);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int display_resume(struct device *dev)
|
||||
{
|
||||
struct rk_display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->resume))
|
||||
dsp->driver->resume(dsp);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
void rk_display_device_enable(struct rk_display_device *ddev)
|
||||
{
|
||||
#ifndef CONFIG_DISPLAY_AUTO_SWITCH
|
||||
return;
|
||||
#else
|
||||
struct list_head *pos, *head = &display_device_list;
|
||||
struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL;
|
||||
int enable = 0,connect, has_connect = 0;
|
||||
|
||||
list_for_each(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
enable = dev->ops->getenable(dev);
|
||||
connect = dev->ops->getstatus(dev);
|
||||
if(connect)
|
||||
dev_enable = dev;
|
||||
if(enable == 1)
|
||||
dev_enabled = dev;
|
||||
}
|
||||
// If no device is connected, enable highest priority device.
|
||||
if(dev_enable == NULL) {
|
||||
dev->ops->setenable(dev, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dev_enable == dev_enabled) {
|
||||
if(dev_enable != ddev)
|
||||
ddev->ops->setenable(ddev, 0);
|
||||
}
|
||||
else {
|
||||
if(dev_enabled)
|
||||
dev_enabled->ops->setenable(dev_enabled, 0);
|
||||
dev_enable->ops->setenable(dev_enable, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_enable);
|
||||
|
||||
void rk_display_device_enable_other(struct rk_display_device *ddev)
|
||||
{
|
||||
#ifndef CONFIG_DISPLAY_AUTO_SWITCH
|
||||
return;
|
||||
#else
|
||||
struct list_head *pos, *head = &display_device_list;
|
||||
struct rk_display_device *dev;
|
||||
int connect = 0;
|
||||
|
||||
list_for_each_prev(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
if(dev != ddev)
|
||||
{
|
||||
connect = dev->ops->getstatus(dev);
|
||||
if(connect)
|
||||
{
|
||||
dev->ops->setenable(dev, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_enable_other);
|
||||
|
||||
void rk_display_device_disable_other(struct rk_display_device *ddev)
|
||||
{
|
||||
#ifndef CONFIG_DISPLAY_AUTO_SWITCH
|
||||
return;
|
||||
#else
|
||||
struct list_head *pos, *head = &display_device_list;
|
||||
struct rk_display_device *dev;
|
||||
int enable = 0;
|
||||
|
||||
list_for_each(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
if(dev != ddev)
|
||||
{
|
||||
enable = dev->ops->getenable(dev);
|
||||
if(enable)
|
||||
dev->ops->setenable(dev, 0);
|
||||
}
|
||||
}
|
||||
ddev->ops->setenable(ddev, 1);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_disable_other);
|
||||
|
||||
void rk_display_device_select(int priority)
|
||||
{
|
||||
struct list_head *pos, *head = &display_device_list;
|
||||
struct rk_display_device *dev;
|
||||
int enable, found = 0;
|
||||
|
||||
list_for_each(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
if(dev->priority == priority)
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
printk("[%s] select display interface %d not exist\n", __FUNCTION__, priority);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
enable = dev->ops->getenable(dev);
|
||||
if(dev->priority == priority)
|
||||
{
|
||||
if(!enable)
|
||||
dev->ops->setenable(dev, 1);
|
||||
}
|
||||
else if(enable)
|
||||
dev->ops->setenable(dev, 0);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_select);
|
||||
static struct mutex allocated_dsp_lock;
|
||||
static DEFINE_IDR(allocated_dsp);
|
||||
static struct class *display_class;
|
||||
|
||||
struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver,
|
||||
struct device *parent, void *devdata)
|
||||
{
|
||||
struct rk_display_device *new_dev = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (unlikely(!driver))
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
if (!ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
new_dev = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
|
||||
if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
|
||||
// Reserve the index for this display
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
|
||||
if (!ret) {
|
||||
new_dev->dev = device_create(display_class, parent,
|
||||
MKDEV(0, 0), new_dev,
|
||||
"%s", new_dev->type);
|
||||
if (!IS_ERR(new_dev->dev)) {
|
||||
new_dev->parent = parent;
|
||||
new_dev->driver = driver;
|
||||
new_dev->dev->driver = parent->driver;
|
||||
mutex_init(&new_dev->lock);
|
||||
// Add new device to display device list.
|
||||
{
|
||||
struct list_head *pos, *head = &display_device_list;
|
||||
struct rk_display_device *dev;
|
||||
|
||||
list_for_each(pos, head) {
|
||||
dev = list_entry(pos, struct rk_display_device, list);
|
||||
if(dev->priority > new_dev->priority)
|
||||
break;
|
||||
}
|
||||
list_add_tail(&new_dev->list, pos);
|
||||
}
|
||||
return new_dev;
|
||||
}
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
kfree(new_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_register);
|
||||
|
||||
void rk_display_device_unregister(struct rk_display_device *ddev)
|
||||
{
|
||||
if (!ddev)
|
||||
return;
|
||||
// Free device
|
||||
mutex_lock(&ddev->lock);
|
||||
device_unregister(ddev->dev);
|
||||
mutex_unlock(&ddev->lock);
|
||||
// Mark device index as avaliable
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, ddev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
list_del(&ddev->list);
|
||||
kfree(ddev);
|
||||
}
|
||||
EXPORT_SYMBOL(rk_display_device_unregister);
|
||||
|
||||
static int __init rk_display_class_init(void)
|
||||
{
|
||||
display_class = class_create(THIS_MODULE, "display");
|
||||
if (IS_ERR(display_class)) {
|
||||
printk(KERN_ERR "Failed to create display class\n");
|
||||
display_class = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
display_class->dev_attrs = display_attrs;
|
||||
display_class->suspend = display_suspend;
|
||||
display_class->resume = display_resume;
|
||||
mutex_init(&allocated_dsp_lock);
|
||||
INIT_LIST_HEAD(&display_device_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit rk_display_class_exit(void)
|
||||
{
|
||||
class_destroy(display_class);
|
||||
}
|
||||
|
||||
subsys_initcall(rk_display_class_init);
|
||||
module_exit(rk_display_class_exit);
|
||||
|
||||
|
||||
MODULE_AUTHOR("zhengyang@rock-chips.com");
|
||||
MODULE_DESCRIPTION("Driver for rk display device");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* display-sysfs.c - Display output driver sysfs interface
|
||||
*
|
||||
* Copyright (C) 2007 James Simmons <jsimmons@infradead.org>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/display.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static ssize_t display_show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
|
||||
}
|
||||
|
||||
static ssize_t display_show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
|
||||
}
|
||||
|
||||
static ssize_t display_show_contrast(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t rc = -ENXIO;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver) && dsp->driver->get_contrast)
|
||||
rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
|
||||
mutex_unlock(&dsp->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t display_store_contrast(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t ret = -EINVAL, size;
|
||||
int contrast;
|
||||
char *endp;
|
||||
|
||||
contrast = simple_strtoul(buf, &endp, 0);
|
||||
size = endp - buf;
|
||||
|
||||
if (isspace(*endp))
|
||||
size++;
|
||||
|
||||
if (size != count)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver && dsp->driver->set_contrast)) {
|
||||
pr_debug("display: set contrast to %d\n", contrast);
|
||||
dsp->driver->set_contrast(dsp, contrast);
|
||||
ret = count;
|
||||
}
|
||||
mutex_unlock(&dsp->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t display_show_max_contrast(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t rc = -ENXIO;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver))
|
||||
rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct device_attribute display_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, display_show_name, NULL),
|
||||
__ATTR(type, S_IRUGO, display_show_type, NULL),
|
||||
__ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
|
||||
__ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
|
||||
};
|
||||
|
||||
static int display_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->suspend))
|
||||
dsp->driver->suspend(dsp, state);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int display_resume(struct device *dev)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->resume))
|
||||
dsp->driver->resume(dsp);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct mutex allocated_dsp_lock;
|
||||
static DEFINE_IDR(allocated_dsp);
|
||||
static struct class *display_class;
|
||||
|
||||
struct display_device *display_device_register(struct display_driver *driver,
|
||||
struct device *parent, void *devdata)
|
||||
{
|
||||
struct display_device *new_dev = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (unlikely(!driver))
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
if (!ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
|
||||
if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
|
||||
// Reserve the index for this display
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
|
||||
if (!ret) {
|
||||
new_dev->dev = device_create(display_class, parent,
|
||||
MKDEV(0, 0), new_dev,
|
||||
"display%d", new_dev->idx);
|
||||
if (!IS_ERR(new_dev->dev)) {
|
||||
new_dev->parent = parent;
|
||||
new_dev->driver = driver;
|
||||
mutex_init(&new_dev->lock);
|
||||
return new_dev;
|
||||
}
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
kfree(new_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(display_device_register);
|
||||
|
||||
void display_device_unregister(struct display_device *ddev)
|
||||
{
|
||||
if (!ddev)
|
||||
return;
|
||||
// Free device
|
||||
mutex_lock(&ddev->lock);
|
||||
device_unregister(ddev->dev);
|
||||
mutex_unlock(&ddev->lock);
|
||||
// Mark device index as available
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, ddev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
kfree(ddev);
|
||||
}
|
||||
EXPORT_SYMBOL(display_device_unregister);
|
||||
|
||||
static int __init display_class_init(void)
|
||||
{
|
||||
display_class = class_create(THIS_MODULE, "display");
|
||||
if (IS_ERR(display_class)) {
|
||||
printk(KERN_ERR "Failed to create display class\n");
|
||||
display_class = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
display_class->dev_attrs = display_attrs;
|
||||
display_class->suspend = display_suspend;
|
||||
display_class->resume = display_resume;
|
||||
mutex_init(&allocated_dsp_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit display_class_exit(void)
|
||||
{
|
||||
class_destroy(display_class);
|
||||
}
|
||||
|
||||
module_init(display_class_init);
|
||||
module_exit(display_class_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Display Hardware handling");
|
||||
MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
6
drivers/video/display/lcd/Kconfig
Normal file
6
drivers/video/display/lcd/Kconfig
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
config RK610_LCD
|
||||
bool "RK610(Jetta) lcd support"
|
||||
depends on MFD_RK610
|
||||
default y if MFD_RK610
|
||||
help
|
||||
Support Jetta(RK610) to output LCD1 and LVDS.
|
||||
4
drivers/video/display/lcd/Makefile
Normal file
4
drivers/video/display/lcd/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# Makefile for the jetta tv control.
|
||||
#
|
||||
obj-$(CONFIG_RK610_LCD) += rk610_lcd.o
|
||||
300
drivers/video/display/lcd/rk610_lcd.c
Normal file
300
drivers/video/display/lcd/rk610_lcd.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
#include <linux/fb.h>
|
||||
#include <linux/delay.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
#include <linux/hdmi.h>
|
||||
#include "rk610_lcd.h"
|
||||
#include <linux/mfd/rk610_core.h>
|
||||
#include "../../rk29_fb.h"
|
||||
static struct i2c_client *rk610_g_lcd_client=NULL;
|
||||
//static int rk610_scaler_read_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
//{
|
||||
//return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
//}
|
||||
|
||||
static int rk610_scaler_write_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
{
|
||||
return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
}
|
||||
static void rk610_scaler_pll_enable(struct i2c_client *client)
|
||||
{
|
||||
char c;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
c = S_PLL_PWR(0)|S_PLL_RESET(0)|S_PLL_BYPASS(0);
|
||||
rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
|
||||
}
|
||||
static void rk610_scaler_pll_disable(struct i2c_client *client)
|
||||
{
|
||||
char c;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);
|
||||
rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
|
||||
}
|
||||
static void rk610_scaler_enable(struct i2c_client *client)
|
||||
{
|
||||
char c;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
|
||||
c= SCL_BYPASS(0) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(ENABLE);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
|
||||
}
|
||||
static void rk610_scaler_disable(struct i2c_client *client)
|
||||
{
|
||||
char c;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
|
||||
c= SCL_BYPASS(1) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(DISABLE);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
|
||||
}
|
||||
static int rk610_output_config(struct i2c_client *client,struct rk29fb_screen *screen,bool enable)
|
||||
{
|
||||
char c=0;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
if(SCREEN_LVDS == screen->type){
|
||||
c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(1) |LVDS_PLL_PWR_PIN(0) \
|
||||
|LVDS_LANE_IN_FORMAT(DATA_D0_MSB) |LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL) \
|
||||
|LVDS_OUTPUT_FORMAT(screen->hw_format) ;
|
||||
rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);
|
||||
c = LVDS_OUT_ENABLE(0x0) |LVDS_TX_PWR_ENABLE(0x0);
|
||||
rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);
|
||||
}else if(SCREEN_RGB == screen->type){
|
||||
c = LCD1_OUT_ENABLE(LCD1_AS_OUT) | LCD1_OUT_SRC(enable?LCD1_FROM_SCL : LCD1_FROM_LCD0);
|
||||
rk610_scaler_write_p0_reg(client, LCD1_CON, &c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
static int rk610_scaler_pll_set(struct i2c_client *client,struct rk29fb_screen *screen,u32 clkin )
|
||||
{
|
||||
char c=0;
|
||||
char M=0,N=0,OD=0;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
/***************SET SCALER PLL FROM CLKIN ,DIV 0*/
|
||||
if(screen->s_pixclock != 0){
|
||||
OD = (screen->s_pixclock)&0x3;
|
||||
N = (screen->s_pixclock >>4)&0xf;
|
||||
M = (screen->s_pixclock >>8)&0xff;
|
||||
}else {
|
||||
RK610_ERR(&client->dev,"RK610 Scaler pll not support rate \n");
|
||||
}
|
||||
c = S_PLL_FROM_DIV<<3 | S_PLL_DIV(0);
|
||||
rk610_scaler_write_p0_reg(client, CLOCK_CON0, &c);
|
||||
|
||||
c = S_DIV_N(N)| S_DIV_OD(OD);
|
||||
rk610_scaler_write_p0_reg(client, S_PLL_CON0, &c);
|
||||
c = S_DIV_M(M);
|
||||
rk610_scaler_write_p0_reg(client, S_PLL_CON1, &c);
|
||||
rk610_scaler_pll_enable(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int scale_hv_factor(struct i2c_client *client ,u32 Hin_act, u32 Hout_act, u32 Vin_act, u32 Vout_act)
|
||||
{
|
||||
char c;
|
||||
u32 hfactor_f,vfactor_f,scl_factor_f;
|
||||
int hfactor;
|
||||
int vfactor;
|
||||
struct scl_hv_info HV2;
|
||||
hfactor_f = ((Hin_act-1)*4096)/(Hout_act-1);
|
||||
if(hfactor_f==4096)
|
||||
{hfactor = 0x1000;}
|
||||
else if(hfactor_f>(int)hfactor_f)
|
||||
{hfactor = (int)hfactor_f+1;}
|
||||
else
|
||||
{hfactor = (int)hfactor_f;}
|
||||
|
||||
scl_factor_f = Vin_act/Vout_act;
|
||||
if(scl_factor_f<2)
|
||||
{vfactor_f = ((Vin_act-1)*4096)/(Vout_act-1);}
|
||||
else
|
||||
{vfactor_f = ((Vin_act-2)*4096)/(Vout_act-1);}
|
||||
if(vfactor_f==4096)
|
||||
{vfactor = 0x1000;}
|
||||
else if(vfactor_f>(int)vfactor_f)
|
||||
{vfactor = (int)vfactor_f+1;}
|
||||
else
|
||||
{vfactor = (int)vfactor_f;}
|
||||
|
||||
HV2.scl_h= hfactor;
|
||||
HV2.scl_v= vfactor;
|
||||
/* SCL FACTOR */
|
||||
c = SCL_H_FACTOR_LSB(HV2.scl_h);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON1, &c);
|
||||
c = SCL_H_FACTOR_MSB(HV2.scl_h);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON2, &c);
|
||||
|
||||
c = SCL_V_FACTOR_LSB(HV2.scl_v);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON3, &c);
|
||||
c = SCL_V_FACTOR_MSB(HV2.scl_v);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON4, &c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_scaler_fator_config(struct i2c_client *client ,struct rk29fb_screen *screen)
|
||||
{
|
||||
switch(screen->hdmi_resolution){
|
||||
case HDMI_1920x1080p_60Hz:
|
||||
case HDMI_1920x1080p_50Hz:
|
||||
rk610_scaler_pll_set(client,screen,148500000);
|
||||
/***************set scaler factor********************/
|
||||
scale_hv_factor(client,1920,screen->x_res,1080,screen->y_res);
|
||||
break;
|
||||
case HDMI_1280x720p_60Hz:
|
||||
case HDMI_1280x720p_50Hz:
|
||||
rk610_scaler_pll_set(client,screen,74250000);
|
||||
/***************set scaler factor********************/
|
||||
scale_hv_factor(client,1280,screen->x_res,720,screen->y_res);
|
||||
break;
|
||||
case HDMI_720x576p_50Hz_16x9:
|
||||
case HDMI_720x576p_50Hz_4x3:
|
||||
rk610_scaler_pll_set(client,screen,27000000);
|
||||
/***************set scaler factor********************/
|
||||
scale_hv_factor(client,720,screen->x_res,576,screen->y_res);
|
||||
break;
|
||||
case HDMI_720x480p_60Hz_16x9:
|
||||
case HDMI_720x480p_60Hz_4x3:
|
||||
rk610_scaler_pll_set(client,screen,27000000);
|
||||
/***************set scaler factor********************/
|
||||
scale_hv_factor(client,720,screen->x_res,480,screen->y_res);
|
||||
break;
|
||||
default :
|
||||
RK610_ERR(&client->dev,"RK610 not support dual display at hdmi resolution=%d \n",screen->hdmi_resolution);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
static int rk610_scaler_output_timing_config(struct i2c_client *client,struct rk29fb_screen *screen)
|
||||
{
|
||||
char c;
|
||||
int h_st = screen->s_hsync_st;
|
||||
int hs_end = screen->s_hsync_len;
|
||||
int h_act_st = hs_end + screen->s_left_margin;
|
||||
int xres = screen->x_res;
|
||||
int h_act_end = h_act_st + xres;
|
||||
int h_total = h_act_end + screen->s_right_margin;
|
||||
int v_st = screen->s_vsync_st;
|
||||
int vs_end = screen->s_vsync_len;
|
||||
int v_act_st = vs_end + screen->s_upper_margin;
|
||||
int yres = screen->y_res;
|
||||
int v_act_end = v_act_st + yres;
|
||||
int v_total = v_act_end + screen->s_lower_margin;
|
||||
|
||||
/* SCL display Frame start point */
|
||||
c = SCL_DSP_HST_LSB(h_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON5, &c);
|
||||
c = SCL_DSP_HST_MSB(h_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON6, &c);
|
||||
|
||||
c = SCL_DSP_VST_LSB(v_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON7, &c);
|
||||
c = SCL_DSP_VST_MSB(v_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON8, &c);
|
||||
/* SCL output timing */
|
||||
|
||||
c = SCL_DSP_HTOTAL_LSB(h_total);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON9, &c);
|
||||
c = SCL_DSP_HTOTAL_MSB(h_total);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON10, &c);
|
||||
|
||||
c = SCL_DSP_HS_END(hs_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON11, &c);
|
||||
|
||||
c = SCL_DSP_HACT_ST_LSB(h_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON12, &c);
|
||||
c = SCL_DSP_HACT_ST_MSB(h_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON13, &c);
|
||||
|
||||
c = SCL_DSP_HACT_END_LSB(h_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON14, &c);
|
||||
c = SCL_DSP_HACT_END_MSB(h_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON15, &c);
|
||||
|
||||
c = SCL_DSP_VTOTAL_LSB(v_total);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON16, &c);
|
||||
c = SCL_DSP_VTOTAL_MSB(v_total);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON17, &c);
|
||||
|
||||
c = SCL_DSP_VS_END(vs_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON18, &c);
|
||||
|
||||
c = SCL_DSP_VACT_ST(v_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON19, &c);
|
||||
|
||||
c = SCL_DSP_VACT_END_LSB(v_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON20, &c);
|
||||
c = SCL_DSP_VACT_END_MSB(v_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON21, &c);
|
||||
|
||||
c = SCL_H_BORD_ST_LSB(h_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON22, &c);
|
||||
c = SCL_H_BORD_ST_MSB(h_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON23, &c);
|
||||
|
||||
c = SCL_H_BORD_END_LSB(h_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON24, &c);
|
||||
c = SCL_H_BORD_END_MSB(h_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON25, &c);
|
||||
|
||||
c = SCL_V_BORD_ST(v_act_st);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON26, &c);
|
||||
|
||||
c = SCL_V_BORD_END_LSB(v_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON27, &c);
|
||||
c = SCL_V_BORD_END_MSB(v_act_end);
|
||||
rk610_scaler_write_p0_reg(client, SCL_CON28, &c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int rk610_scaler_chg(struct i2c_client *client ,struct rk29fb_screen *screen)
|
||||
{
|
||||
|
||||
RK610_DBG(&client->dev,"%s screen->hdmi_resolution=%d\n",__FUNCTION__,screen->hdmi_resolution);
|
||||
rk610_scaler_fator_config(client,screen);
|
||||
rk610_scaler_enable(client);
|
||||
rk610_scaler_output_timing_config(client,screen);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
static int rk610_lcd_scaler_bypass(struct i2c_client *client,bool enable)//enable:0 bypass 1: scale
|
||||
{
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
|
||||
rk610_scaler_pll_disable(client);
|
||||
rk610_scaler_disable(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable )//enable:0 bypass 1: scale
|
||||
{
|
||||
int ret=0;
|
||||
struct i2c_client *client = rk610_g_lcd_client;
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
if(client == NULL){
|
||||
RK610_ERR(&client->dev,"%s client == NULL FAIL\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
if(enable == 1){
|
||||
rk610_output_config(client,screen,1);
|
||||
ret = rk610_scaler_chg(client,screen);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rk610_output_config(client,screen,0);
|
||||
ret = rk610_lcd_scaler_bypass(client,enable);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int rk610_lcd_init(struct i2c_client *client)
|
||||
{
|
||||
RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
|
||||
rk610_g_lcd_client = client;
|
||||
return 0;
|
||||
}
|
||||
165
drivers/video/display/lcd/rk610_lcd.h
Normal file
165
drivers/video/display/lcd/rk610_lcd.h
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#ifndef _RK610_LCD_H
|
||||
#define _RK610_LCD_H
|
||||
#include "../screen/screen.h"
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
/* LVDS config */
|
||||
/* LVDS ÍⲿÁ¬Ïß½Ó·¨ */
|
||||
#define LVDS_8BIT_1 0x00
|
||||
#define LVDS_8BIT_2 0x01
|
||||
#define LVDS_8BIT_3 0x10
|
||||
#define LVDS_6BIT 0x11
|
||||
//LVDS lane input format
|
||||
#define DATA_D0_MSB 0
|
||||
#define DATA_D7_MSB 1
|
||||
//LVDS input source
|
||||
#define FROM_LCD1 0
|
||||
#define FROM_LCD0_OR_SCL 1
|
||||
|
||||
/* LCD1 config */
|
||||
#define LCD1_AS_IN 0
|
||||
#define LCD1_AS_OUT 1
|
||||
|
||||
//LCD1 output source
|
||||
#define LCD1_FROM_LCD0 0
|
||||
#define LCD1_FROM_SCL 1
|
||||
|
||||
/* clock config */
|
||||
#define S_PLL_FROM_DIV 0
|
||||
#define S_PLL_FROM_CLKIN 1
|
||||
#define S_PLL_DIV(x) ((x)&0x7)
|
||||
/*********S_PLL_CON************/
|
||||
//S_PLL_CON0
|
||||
#define S_DIV_N(x) (((x)&0xf)<<4)
|
||||
#define S_DIV_OD(x) (((x)&3)<<0)
|
||||
//S_PLL_CON1
|
||||
#define S_DIV_M(x) ((x)&0xff)
|
||||
//S_PLL_CON2
|
||||
#define S_PLL_UNLOCK (0<<7) //0:unlock 1:pll_lock
|
||||
#define S_PLL_LOCK (1<<7) //0:unlock 1:pll_lock
|
||||
#define S_PLL_PWR(x) (((x)&1)<<2) //0:POWER UP 1:POWER DOWN
|
||||
#define S_PLL_RESET(x) (((x)&1)<<1) //0:normal 1:reset M/N dividers
|
||||
#define S_PLL_BYPASS(x) (((x)&1)<<0) //0:normal 1:bypass
|
||||
//LVDS_CON0
|
||||
#define LVDS_OUT_CLK_PIN(x) (((x)&1)<<7) //clk enable pin, 0: enable
|
||||
#define LVDS_OUT_CLK_PWR_PIN(x) (((x)&1)<<6) //clk pwr enable pin, 1: enable
|
||||
#define LVDS_PLL_PWR_PIN(x) (((x)&1)<<5) //pll pwr enable pin, 0:enable
|
||||
#define LVDS_LANE_IN_FORMAT(x) (((x)&1)<<3) //0: msb on D0 1:msb on D7
|
||||
#define LVDS_INPUT_SOURCE(x) (((x)&1)<<2) //0: from lcd1 1:from lcd0 or scaler
|
||||
#define LVDS_OUTPUT_FORMAT(x) (((x)&3)<<0) //00:8bit format-1 01:8bit format-2 10:8bit format-3 11:6bit format
|
||||
//LVDS_CON1
|
||||
#define LVDS_OUT_ENABLE(x) (((x)&0xf)<<4) //0:output enable 1:output disable
|
||||
#define LVDS_TX_PWR_ENABLE(x) (((x)&0xf)<<0) //0:working mode 1:power down
|
||||
//LCD1_CON
|
||||
#define LCD1_OUT_ENABLE(x) (((x)&1)<<1) //0:lcd1 as input 1:lcd1 as output
|
||||
#define LCD1_OUT_SRC(x) (((x)&1)<<0) //0:from lcd0 1:from scaler
|
||||
//SCL_CON0
|
||||
#define SCL_BYPASS(x) (((x)&1)<<4) //0:not bypass 1:bypass
|
||||
#define SCL_DEN_INV(x) (((x)&1)<<3) //scl_den_inv
|
||||
#define SCL_H_V_SYNC_INV(x) (((x)&1)<<2) //scl_sync_inv
|
||||
#define SCL_OUT_CLK_INV(x) (((x)&1)<<1) //scl_dclk_inv
|
||||
#define SCL_ENABLE(x) (((x)&1)<<0) //scaler enable
|
||||
//SCL_CON1
|
||||
#define SCL_H_FACTOR_LSB(x) ((x)&0xff) //scl_h_factor[7:0]
|
||||
//SCL_CON2
|
||||
#define SCL_H_FACTOR_MSB(x) (((x)>>8)&0x3f) //scl_h_factor[13:8]
|
||||
//SCL_CON3
|
||||
#define SCL_V_FACTOR_LSB(x) ((x)&0xff) //scl_v_factor[7:0]
|
||||
//SCL_CON4
|
||||
#define SCL_V_FACTOR_MSB(x) (((x)>>8)&0x3f) //scl_v_factor[13:8]
|
||||
//SCL_CON5
|
||||
#define SCL_DSP_HST_LSB(x) ((x)&0xff) //dsp_frame_hst[7:0]
|
||||
//SCL_CON6
|
||||
#define SCL_DSP_HST_MSB(x) (((x)>>8)&0xf) //dsp_frame_hst[11:8]
|
||||
//SCL_CON7
|
||||
#define SCL_DSP_VST_LSB(x) ((x)&0xff) //dsp_frame_vst[7:0]
|
||||
//SCL_CON8
|
||||
#define SCL_DSP_VST_MSB(x) (((x)>>8)&0xf) //dsp_frame_vst[11:8]
|
||||
//SCL_CON9
|
||||
#define SCL_DSP_HTOTAL_LSB(x) ((x)&0xff) //dsp_frame_htotal[7:0]
|
||||
//SCL_CON10
|
||||
#define SCL_DSP_HTOTAL_MSB(x) (((x)>>8)&0xf) //dsp_frame_htotal[11:8]
|
||||
//SCL_CON11
|
||||
#define SCL_DSP_HS_END(x) ((x)&0xff) //dsp_hs_end
|
||||
//SCL_CON12
|
||||
#define SCL_DSP_HACT_ST_LSB(x) ((x)&0xff) //dsp_hact_st[7:0]
|
||||
//SCL_CON13
|
||||
#define SCL_DSP_HACT_ST_MSB(x) (((x)>>8)&0x3) //dsp_hact_st[9:8]
|
||||
//SCL_CON14
|
||||
#define SCL_DSP_HACT_END_LSB(x) ((x)&0xff) //dsp_hact_end[7:0]
|
||||
//SCL_CON15
|
||||
#define SCL_DSP_HACT_END_MSB(x) (((x)>>8)&0xf) //dsp_frame_htotal[11:8]
|
||||
//SCL_CON16
|
||||
#define SCL_DSP_VTOTAL_LSB(x) ((x)&0xff) //dsp_frame_vtotal[7:0]
|
||||
//SCL_CON17
|
||||
#define SCL_DSP_VTOTAL_MSB(x) (((x)>>8)&0xf) //dsp_frame_vtotal[11:8]
|
||||
//SCL_CON18
|
||||
#define SCL_DSP_VS_END(x) ((x)&0xff) //dsp_vs_end
|
||||
//SCL_CON19
|
||||
#define SCL_DSP_VACT_ST(x) ((x)&0xff) //dsp_vact_st[7:0]
|
||||
//SCL_CON20
|
||||
#define SCL_DSP_VACT_END_LSB(x) ((x)&0xff) //dsp_vact_end[7:0]
|
||||
//SCL_CON21
|
||||
#define SCL_DSP_VACT_END_MSB(x) (((x)>>8)&0xf) //dsp_frame_vtotal[11:8]
|
||||
//SCL_CON22
|
||||
#define SCL_H_BORD_ST_LSB(x) ((x)&0xff) //dsp_hbord_st[7:0]
|
||||
//SCL_CON23
|
||||
#define SCL_H_BORD_ST_MSB(x) (((x)>>8)&0x3) //dsp_hbord_st[9:8]
|
||||
//SCL_CON24
|
||||
#define SCL_H_BORD_END_LSB(x) ((x)&0xff) //dsp_hbord_end[7:0]
|
||||
//SCL_CON25
|
||||
#define SCL_H_BORD_END_MSB(x) (((x)>>8)&0xf) //dsp_hbord_end[11:8]
|
||||
//SCL_CON26
|
||||
#define SCL_V_BORD_ST(x) ((x)&0xff) //dsp_vbord_st[7:0]
|
||||
//SCL_CON27
|
||||
#define SCL_V_BORD_END_LSB(x) ((x)&0xff) //dsp_vbord_end[7:0]
|
||||
//SCL_CON25
|
||||
#define SCL_V_BORD_END_MSB(x) (((x)>>8)&0xf) //dsp_vbord_end[11:8]
|
||||
#if 0
|
||||
/****************LCD STRUCT********/
|
||||
#define PLL_CLKOD(i) ((i) & 0x03)
|
||||
#define PLL_NO_1 PLL_CLKOD(0)
|
||||
#define PLL_NO_2 PLL_CLKOD(1)
|
||||
#define PLL_NO_4 PLL_CLKOD(2)
|
||||
#define PLL_NO_8 PLL_CLKOD(3)
|
||||
#define SCALE_PLL(_parent_rate , _rate, _m, _n, _od) \
|
||||
{ \
|
||||
.parent_rate = _parent_rate, \
|
||||
.rate = _rate, \
|
||||
.m = _m, \
|
||||
.n = _n, \
|
||||
.od = _od, \
|
||||
}
|
||||
#endif
|
||||
struct rk610_pll_info{
|
||||
u32 parent_rate;
|
||||
u32 rate;
|
||||
int m;
|
||||
int n;
|
||||
int od;
|
||||
};
|
||||
struct lcd_mode_inf{
|
||||
int h_pw;
|
||||
int h_bp;
|
||||
int h_vd;
|
||||
int h_fp;
|
||||
int v_pw;
|
||||
int v_bp;
|
||||
int v_vd;
|
||||
int v_fp;
|
||||
int f_hst;
|
||||
int f_vst;
|
||||
struct rk610_pll_info pllclk;
|
||||
};
|
||||
struct scl_hv_info{
|
||||
int scl_h ;
|
||||
int scl_v;
|
||||
};
|
||||
struct rk610_lcd_info{
|
||||
int enable;
|
||||
struct scl_hv_info scl;
|
||||
struct lcd_mode_inf *lcd_mode;
|
||||
};
|
||||
extern int rk610_lcd_init(struct i2c_client *client);
|
||||
extern int rk610_lcd_scaler_set_param(struct rk29fb_screen *screen,bool enable );
|
||||
#endif
|
||||
|
|
@ -68,6 +68,16 @@ config LCD_A050VL01
|
|||
bool "RGB A050VL01"
|
||||
config LCD_B101EW05
|
||||
bool "RGB lcd panel B101EW05"
|
||||
config LCD_HDMI_1024x768
|
||||
depends on MFD_RK610
|
||||
bool "RGB Hannstar LCD_HDMI_1024X768"
|
||||
---help---
|
||||
if support RK610, this setting can support dual screen output
|
||||
config LCD_HDMI_800x480
|
||||
depends on MFD_RK610
|
||||
bool "RGB Hannstar LCD_HDMI_800x480"
|
||||
---help---
|
||||
if support RK610, this setting can support dual screen output
|
||||
endchoice
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ obj-$(CONFIG_LCD_CPTCLAA038LA31XE) += lcd_CPTclaa038la31xe.o
|
|||
|
||||
obj-$(CONFIG_LCD_HX8357) += lcd_hx8357.o
|
||||
obj-$(CONFIG_LCD_HSD100PXN) += lcd_hsd100pxn.o
|
||||
obj-$(CONFIG_LCD_HDMI_1024x768) += lcd_hdmi_1024x768.o
|
||||
obj-$(CONFIG_LCD_HDMI_800x480) += lcd_hdmi_800x480.o
|
||||
obj-$(CONFIG_LCD_HSD07PFW1) += lcd_hsd07pfw1.o
|
||||
obj-$(CONFIG_LCD_B101AW06) += lcd_B101AW06.o
|
||||
obj-$(CONFIG_LCD_NT35510) += lcd_nt35510.o
|
||||
|
|
|
|||
153
drivers/video/display/screen/lcd_hdmi_1024x768.c
Normal file
153
drivers/video/display/screen/lcd_hdmi_1024x768.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#include <linux/fb.h>
|
||||
#include <linux/delay.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/board.h>
|
||||
#include "screen.h"
|
||||
#include <linux/hdmi.h>
|
||||
#include "../../rk29_fb.h"
|
||||
#include "../lcd/rk610_lcd.h"
|
||||
|
||||
/* Base */
|
||||
#define OUT_TYPE SCREEN_LVDS
|
||||
|
||||
#define OUT_FORMAT LVDS_8BIT_3
|
||||
#define OUT_FACE OUT_D888_P666
|
||||
#define OUT_CLK 65000000
|
||||
#define LCDC_ACLK 500000000//312000000 //29 lcdc axi DMA ƵÂÊ
|
||||
|
||||
/* Timing */
|
||||
#define H_PW 48 //10
|
||||
#define H_BP 88 //100
|
||||
#define H_VD 800 //1024
|
||||
#define H_FP 40 //210
|
||||
|
||||
#define V_PW 3 //10
|
||||
#define V_BP 32 //10
|
||||
#define V_VD 480 //768
|
||||
#define V_FP 13 //18
|
||||
|
||||
#define LCD_WIDTH 202
|
||||
#define LCD_HEIGHT 152
|
||||
|
||||
/* scaler Timing */
|
||||
//1920*1080*60
|
||||
#define S_OUT_CLK SCALE_RATE(148500000,66000000)
|
||||
#define S_H_PW 100
|
||||
#define S_H_BP 100
|
||||
#define S_H_VD 1024
|
||||
#define S_H_FP 151
|
||||
|
||||
#define S_V_PW 5
|
||||
#define S_V_BP 15
|
||||
#define S_V_VD 768
|
||||
#define S_V_FP 12
|
||||
|
||||
#define S_H_ST 1757
|
||||
#define S_V_ST 14
|
||||
|
||||
//1920*1080*50
|
||||
#define S1_OUT_CLK SCALE_RATE(148500000,54000000)
|
||||
#define S1_H_PW 100
|
||||
#define S1_H_BP 100
|
||||
#define S1_H_VD 1024
|
||||
#define S1_H_FP 126
|
||||
|
||||
#define S1_V_PW 5
|
||||
#define S1_V_BP 15
|
||||
#define S1_V_VD 768
|
||||
#define S1_V_FP 12
|
||||
|
||||
#define S1_H_ST 1757
|
||||
#define S1_V_ST 14
|
||||
/* Other */
|
||||
#define DCLK_POL 0
|
||||
#define SWAP_RB 0
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution)
|
||||
{
|
||||
switch(hdmi_resolution){
|
||||
case HDMI_1920x1080p_60Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S_OUT_CLK;
|
||||
screen->s_hsync_len = S_H_PW;
|
||||
screen->s_left_margin = S_H_BP;
|
||||
screen->s_right_margin = S_H_FP;
|
||||
screen->s_hsync_len = S_H_PW;
|
||||
screen->s_upper_margin = S_V_BP;
|
||||
screen->s_lower_margin = S_V_FP;
|
||||
screen->s_vsync_len = S_V_PW;
|
||||
screen->s_hsync_st = S_H_ST;
|
||||
screen->s_vsync_st = S_V_ST;
|
||||
break;
|
||||
case HDMI_1920x1080p_50Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S1_OUT_CLK;
|
||||
screen->s_hsync_len = S1_H_PW;
|
||||
screen->s_left_margin = S1_H_BP;
|
||||
screen->s_right_margin = S1_H_FP;
|
||||
screen->s_hsync_len = S1_H_PW;
|
||||
screen->s_upper_margin = S1_V_BP;
|
||||
screen->s_lower_margin = S1_V_FP;
|
||||
screen->s_vsync_len = S1_V_PW;
|
||||
screen->s_hsync_st = S1_H_ST;
|
||||
screen->s_vsync_st = S1_V_ST;
|
||||
break;
|
||||
default :
|
||||
printk("%s lcd not support dual display at this hdmi resolution %d \n",__func__,hdmi_resolution);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution){}
|
||||
#endif
|
||||
|
||||
void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info )
|
||||
{
|
||||
/* screen type & face */
|
||||
screen->type = OUT_TYPE;
|
||||
screen->face = OUT_FACE;
|
||||
|
||||
/* Screen size */
|
||||
screen->x_res = H_VD;
|
||||
screen->y_res = V_VD;
|
||||
|
||||
screen->width = LCD_WIDTH;
|
||||
screen->height = LCD_HEIGHT;
|
||||
|
||||
/* Timing */
|
||||
screen->lcdc_aclk = LCDC_ACLK;
|
||||
screen->pixclock = OUT_CLK;
|
||||
screen->left_margin = H_BP;
|
||||
screen->right_margin = H_FP;
|
||||
screen->hsync_len = H_PW;
|
||||
screen->upper_margin = V_BP;
|
||||
screen->lower_margin = V_FP;
|
||||
screen->vsync_len = V_PW;
|
||||
|
||||
/* Pin polarity */
|
||||
screen->pin_hsync = 0;
|
||||
screen->pin_vsync = 0;
|
||||
screen->pin_den = 0;
|
||||
screen->pin_dclk = DCLK_POL;
|
||||
|
||||
/* Swap rule */
|
||||
screen->swap_rb = SWAP_RB;
|
||||
screen->swap_rg = 0;
|
||||
screen->swap_gb = 0;
|
||||
screen->swap_delta = 0;
|
||||
screen->swap_dumy = 0;
|
||||
|
||||
/* Operation function*/
|
||||
screen->init = NULL;
|
||||
screen->standby = NULL;
|
||||
screen->sscreen_get = set_scaler_info;
|
||||
#ifdef CONFIG_RK610_LCD
|
||||
screen->sscreen_set = rk610_lcd_scaler_set_param;
|
||||
#endif
|
||||
}
|
||||
271
drivers/video/display/screen/lcd_hdmi_800x480.c
Normal file
271
drivers/video/display/screen/lcd_hdmi_800x480.c
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
#include <linux/fb.h>
|
||||
#include <linux/delay.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/board.h>
|
||||
#include "screen.h"
|
||||
#include <linux/hdmi.h>
|
||||
#include "../../rk29_fb.h"
|
||||
#include "../lcd/rk610_lcd.h"
|
||||
|
||||
/* Base */
|
||||
#define OUT_TYPE SCREEN_RGB
|
||||
|
||||
#define OUT_FACE OUT_P888
|
||||
#define OUT_CLK 33000000
|
||||
#define LCDC_ACLK 150000000//312000000 //29 lcdc axi DMA ƵÂÊ
|
||||
|
||||
/* Timing */
|
||||
#define H_PW 1
|
||||
#define H_BP 88
|
||||
#define H_VD 800
|
||||
#define H_FP 40
|
||||
|
||||
#define V_PW 3
|
||||
#define V_BP 29
|
||||
#define V_VD 480
|
||||
#define V_FP 13
|
||||
|
||||
#define LCD_WIDTH 154
|
||||
#define LCD_HEIGHT 85
|
||||
|
||||
/* scaler Timing */
|
||||
//1920*1080*60
|
||||
|
||||
#define S_OUT_CLK SCALE_RATE(148500000,33000000)
|
||||
#define S_H_PW 1
|
||||
#define S_H_BP 88
|
||||
#define S_H_VD 800
|
||||
#define S_H_FP 211
|
||||
|
||||
#define S_V_PW 3
|
||||
#define S_V_BP 10
|
||||
#define S_V_VD 480
|
||||
#define S_V_FP 7
|
||||
|
||||
#define S_H_ST 244
|
||||
#define S_V_ST 11
|
||||
|
||||
//1920*1080*50
|
||||
#define S1_OUT_CLK SCALE_RATE(148500000,30375000)
|
||||
#define S1_H_PW 1
|
||||
#define S1_H_BP 88
|
||||
#define S1_H_VD 800
|
||||
#define S1_H_FP 326
|
||||
|
||||
#define S1_V_PW 3
|
||||
#define S1_V_BP 9
|
||||
#define S1_V_VD 480
|
||||
#define S1_V_FP 8
|
||||
|
||||
#define S1_H_ST 270
|
||||
#define S1_V_ST 13
|
||||
//1280*720*60
|
||||
#define S2_OUT_CLK SCALE_RATE(74250000,33000000)
|
||||
#define S2_H_PW 1
|
||||
#define S2_H_BP 88
|
||||
#define S2_H_VD 800
|
||||
#define S2_H_FP 211
|
||||
|
||||
#define S2_V_PW 3
|
||||
#define S2_V_BP 9
|
||||
#define S2_V_VD 480
|
||||
#define S2_V_FP 8
|
||||
|
||||
#define S2_H_ST 0
|
||||
#define S2_V_ST 8
|
||||
//1280*720*50
|
||||
|
||||
#define S3_OUT_CLK SCALE_RATE(74250000,30375000)
|
||||
#define S3_H_PW 1
|
||||
#define S3_H_BP 88
|
||||
#define S3_H_VD 800
|
||||
#define S3_H_FP 326
|
||||
|
||||
#define S3_V_PW 3
|
||||
#define S3_V_BP 9
|
||||
#define S3_V_VD 480
|
||||
#define S3_V_FP 8
|
||||
|
||||
#define S3_H_ST 0
|
||||
#define S3_V_ST 8
|
||||
|
||||
//720*576*50
|
||||
#define S4_OUT_CLK SCALE_RATE(27000000,30000000)
|
||||
#define S4_H_PW 1
|
||||
#define S4_H_BP 88
|
||||
#define S4_H_VD 800
|
||||
#define S4_H_FP 263
|
||||
|
||||
#define S4_V_PW 3
|
||||
#define S4_V_BP 9
|
||||
#define S4_V_VD 480
|
||||
#define S4_V_FP 28
|
||||
|
||||
#define S4_H_ST 0
|
||||
#define S4_V_ST 33
|
||||
//720*480*60
|
||||
#define S5_OUT_CLK SCALE_RATE(27000000,31500000)
|
||||
#define S5_H_PW 1
|
||||
#define S5_H_BP 88
|
||||
#define S5_H_VD 800
|
||||
#define S5_H_FP 112
|
||||
|
||||
#define S5_V_PW 3
|
||||
#define S5_V_BP 9
|
||||
#define S5_V_VD 480
|
||||
#define S5_V_FP 28
|
||||
|
||||
#define S5_H_ST 0
|
||||
#define S5_V_ST 29
|
||||
/* Other */
|
||||
#define DCLK_POL 0
|
||||
#define SWAP_RB 0
|
||||
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution)
|
||||
{
|
||||
switch(hdmi_resolution){
|
||||
case HDMI_1920x1080p_60Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S_OUT_CLK;
|
||||
screen->s_hsync_len = S_H_PW;
|
||||
screen->s_left_margin = S_H_BP;
|
||||
screen->s_right_margin = S_H_FP;
|
||||
screen->s_hsync_len = S_H_PW;
|
||||
screen->s_upper_margin = S_V_BP;
|
||||
screen->s_lower_margin = S_V_FP;
|
||||
screen->s_vsync_len = S_V_PW;
|
||||
screen->s_hsync_st = S_H_ST;
|
||||
screen->s_vsync_st = S_V_ST;
|
||||
break;
|
||||
case HDMI_1920x1080p_50Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S1_OUT_CLK;
|
||||
screen->s_hsync_len = S1_H_PW;
|
||||
screen->s_left_margin = S1_H_BP;
|
||||
screen->s_right_margin = S1_H_FP;
|
||||
screen->s_hsync_len = S1_H_PW;
|
||||
screen->s_upper_margin = S1_V_BP;
|
||||
screen->s_lower_margin = S1_V_FP;
|
||||
screen->s_vsync_len = S1_V_PW;
|
||||
screen->s_hsync_st = S1_H_ST;
|
||||
screen->s_vsync_st = S1_V_ST;
|
||||
break;
|
||||
case HDMI_1280x720p_60Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S2_OUT_CLK;
|
||||
screen->s_hsync_len = S2_H_PW;
|
||||
screen->s_left_margin = S2_H_BP;
|
||||
screen->s_right_margin = S2_H_FP;
|
||||
screen->s_hsync_len = S2_H_PW;
|
||||
screen->s_upper_margin = S2_V_BP;
|
||||
screen->s_lower_margin = S2_V_FP;
|
||||
screen->s_vsync_len = S2_V_PW;
|
||||
screen->s_hsync_st = S2_H_ST;
|
||||
screen->s_vsync_st = S2_V_ST;
|
||||
break;
|
||||
case HDMI_1280x720p_50Hz:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S3_OUT_CLK;
|
||||
screen->s_hsync_len = S3_H_PW;
|
||||
screen->s_left_margin = S3_H_BP;
|
||||
screen->s_right_margin = S3_H_FP;
|
||||
screen->s_hsync_len = S3_H_PW;
|
||||
screen->s_upper_margin = S3_V_BP;
|
||||
screen->s_lower_margin = S3_V_FP;
|
||||
screen->s_vsync_len = S3_V_PW;
|
||||
screen->s_hsync_st = S3_H_ST;
|
||||
screen->s_vsync_st = S3_V_ST;
|
||||
break;
|
||||
case HDMI_720x576p_50Hz_4x3:
|
||||
case HDMI_720x576p_50Hz_16x9:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S4_OUT_CLK;
|
||||
screen->s_hsync_len = S4_H_PW;
|
||||
screen->s_left_margin = S4_H_BP;
|
||||
screen->s_right_margin = S4_H_FP;
|
||||
screen->s_hsync_len = S4_H_PW;
|
||||
screen->s_upper_margin = S4_V_BP;
|
||||
screen->s_lower_margin = S4_V_FP;
|
||||
screen->s_vsync_len = S4_V_PW;
|
||||
screen->s_hsync_st = S4_H_ST;
|
||||
screen->s_vsync_st = S4_V_ST;
|
||||
break;
|
||||
case HDMI_720x480p_60Hz_16x9:
|
||||
case HDMI_720x480p_60Hz_4x3:
|
||||
/* Scaler Timing */
|
||||
screen->hdmi_resolution = hdmi_resolution;
|
||||
screen->s_pixclock = S5_OUT_CLK;
|
||||
screen->s_hsync_len = S5_H_PW;
|
||||
screen->s_left_margin = S5_H_BP;
|
||||
screen->s_right_margin = S5_H_FP;
|
||||
screen->s_hsync_len = S5_H_PW;
|
||||
screen->s_upper_margin = S5_V_BP;
|
||||
screen->s_lower_margin = S5_V_FP;
|
||||
screen->s_vsync_len = S5_V_PW;
|
||||
screen->s_hsync_st = S5_H_ST;
|
||||
screen->s_vsync_st = S5_V_ST;
|
||||
break;
|
||||
default :
|
||||
printk("%s lcd not support dual display at this hdmi resolution %d \n",__func__,hdmi_resolution);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int set_scaler_info(struct rk29fb_screen *screen, u8 hdmi_resolution){}
|
||||
#endif
|
||||
|
||||
void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info )
|
||||
{
|
||||
/* screen type & face */
|
||||
screen->type = OUT_TYPE;
|
||||
screen->face = OUT_FACE;
|
||||
|
||||
/* Screen size */
|
||||
screen->x_res = H_VD;
|
||||
screen->y_res = V_VD;
|
||||
|
||||
screen->width = LCD_WIDTH;
|
||||
screen->height = LCD_HEIGHT;
|
||||
|
||||
/* Timing */
|
||||
screen->lcdc_aclk = LCDC_ACLK;
|
||||
screen->pixclock = OUT_CLK;
|
||||
screen->left_margin = H_BP;
|
||||
screen->right_margin = H_FP;
|
||||
screen->hsync_len = H_PW;
|
||||
screen->upper_margin = V_BP;
|
||||
screen->lower_margin = V_FP;
|
||||
screen->vsync_len = V_PW;
|
||||
|
||||
/* Pin polarity */
|
||||
screen->pin_hsync = 0;
|
||||
screen->pin_vsync = 0;
|
||||
screen->pin_den = 0;
|
||||
screen->pin_dclk = DCLK_POL;
|
||||
|
||||
/* Swap rule */
|
||||
screen->swap_rb = SWAP_RB;
|
||||
screen->swap_rg = 0;
|
||||
screen->swap_gb = 0;
|
||||
screen->swap_delta = 0;
|
||||
screen->swap_dumy = 0;
|
||||
|
||||
/* Operation function*/
|
||||
screen->init = NULL;
|
||||
screen->standby = NULL;
|
||||
screen->sscreen_get = set_scaler_info;
|
||||
#ifdef CONFIG_RK610_LCD
|
||||
screen->sscreen_set = rk610_lcd_scaler_set_param;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -11,26 +11,26 @@
|
|||
/* Base */
|
||||
#define OUT_TYPE SCREEN_RGB
|
||||
#define OUT_FACE OUT_P888
|
||||
#define OUT_CLK 28000000
|
||||
#define OUT_CLK 33000000
|
||||
#define LCDC_ACLK 150000000 //29 lcdc axi DMA ƵÂÊ
|
||||
|
||||
/* Timing */
|
||||
#define H_PW 1
|
||||
#define H_BP 88
|
||||
#define H_VD 800
|
||||
#define H_FP 40
|
||||
#define H_PW 8 //10
|
||||
#define H_BP 88 //100
|
||||
#define H_VD 800 //1024
|
||||
#define H_FP 40 //210
|
||||
|
||||
#define V_PW 3
|
||||
#define V_BP 29
|
||||
#define V_VD 480
|
||||
#define V_FP 13
|
||||
#define V_PW 3 //10
|
||||
#define V_BP 10 //10
|
||||
#define V_VD 480 //768
|
||||
#define V_FP 32 //18
|
||||
|
||||
/* Other */
|
||||
#define DCLK_POL 1
|
||||
#define DCLK_POL 0
|
||||
#define SWAP_RB 0
|
||||
|
||||
#define LCD_WIDTH 800 //need modify
|
||||
#define LCD_HEIGHT 480
|
||||
#define LCD_WIDTH 154 //need modify
|
||||
#define LCD_HEIGHT 85
|
||||
|
||||
#define TXD_PORT gLcd_info->txd_pin
|
||||
#define CLK_PORT gLcd_info->clk_pin
|
||||
|
|
|
|||
|
|
@ -1,8 +1,51 @@
|
|||
#ifndef _SCREEN_H
|
||||
#define _SCREEN_H
|
||||
#include <mach/board.h>
|
||||
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
/* Scaler PLL CONFIG */
|
||||
#define S_PLL_NO_1 0
|
||||
#define S_PLL_NO_2 1
|
||||
#define S_PLL_NO_4 2
|
||||
#define S_PLL_NO_8 3
|
||||
#define S_PLL_M(x) (((x)&0xff)<<8)
|
||||
#define S_PLL_N(x) (((x)&0xf)<<4)
|
||||
#define S_PLL_NO(x) ((S_PLL_NO_##x)&0x3)
|
||||
|
||||
enum{
|
||||
HDMI_RATE_148500000,
|
||||
HDMI_RATE_74250000,
|
||||
HDMI_RATE_27000000,
|
||||
};
|
||||
/* Scaler clk setting */
|
||||
#define SCALE_PLL(_parent_rate,_rate,_m,_n,_no) \
|
||||
HDMI_RATE_ ## _parent_rate ##_S_RATE_ ## _rate \
|
||||
= S_PLL_M(_m) | S_PLL_N(_n) | S_PLL_NO(_no)
|
||||
#define SCALE_RATE(_parent_rate , _rate) \
|
||||
(HDMI_RATE_ ## _parent_rate ## _S_RATE_ ## _rate)
|
||||
|
||||
enum{
|
||||
SCALE_PLL(148500000, 66000000, 16, 9, 4),
|
||||
SCALE_PLL(148500000, 54000000, 16, 11, 4),
|
||||
SCALE_PLL(148500000, 33000000, 16, 9, 8),
|
||||
SCALE_PLL(148500000, 30375000, 18, 11, 8),
|
||||
SCALE_PLL(148500000, 29700000, 16, 10, 8),
|
||||
SCALE_PLL(148500000, 25312500, 15, 11, 8),
|
||||
|
||||
SCALE_PLL(74250000, 66000000, 32, 9, 4),
|
||||
SCALE_PLL(74250000, 54000000, 32, 11, 4),
|
||||
SCALE_PLL(74250000, 33000000, 32, 9, 8),
|
||||
SCALE_PLL(74250000, 30375000, 36, 11, 8),
|
||||
SCALE_PLL(74250000, 25312500, 30, 11, 8),
|
||||
|
||||
SCALE_PLL(27000000, 31500000, 28, 3, 8),
|
||||
SCALE_PLL(27000000, 30000000, 80, 9, 8),
|
||||
};
|
||||
#endif
|
||||
typedef enum _SCREEN_TYPE {
|
||||
SCREEN_NULL = 0,
|
||||
SCREEN_RGB,
|
||||
SCREEN_LVDS,
|
||||
SCREEN_MCU,
|
||||
SCREEN_TVOUT,
|
||||
SCREEN_HDMI,
|
||||
|
|
@ -37,8 +80,9 @@ typedef enum _MCU_STATUS {
|
|||
|
||||
/* Screen description */
|
||||
typedef struct rk29fb_screen {
|
||||
/* screen type & out face */
|
||||
/* screen type & hardware connect format & out face */
|
||||
u16 type;
|
||||
u16 hw_format;
|
||||
u16 face;
|
||||
|
||||
/* Screen size */
|
||||
|
|
@ -47,6 +91,7 @@ typedef struct rk29fb_screen {
|
|||
u16 width;
|
||||
u16 height;
|
||||
|
||||
u32 mode;
|
||||
/* Timing */
|
||||
u32 pixclock;
|
||||
u16 left_margin;
|
||||
|
|
@ -55,7 +100,19 @@ typedef struct rk29fb_screen {
|
|||
u16 upper_margin;
|
||||
u16 lower_margin;
|
||||
u16 vsync_len;
|
||||
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
/* Scaler mode Timing */
|
||||
u32 s_pixclock;
|
||||
u16 s_left_margin;
|
||||
u16 s_right_margin;
|
||||
u16 s_hsync_len;
|
||||
u16 s_upper_margin;
|
||||
u16 s_lower_margin;
|
||||
u16 s_vsync_len;
|
||||
u16 s_hsync_st;
|
||||
u16 s_vsync_st;
|
||||
#endif
|
||||
u8 hdmi_resolution;
|
||||
/* mcu need */
|
||||
u8 mcu_wrperiod;
|
||||
u8 mcu_usefmk;
|
||||
|
|
@ -82,10 +139,12 @@ typedef struct rk29fb_screen {
|
|||
int (*refresh)(u8 arg);
|
||||
int (*scandir)(u16 dir);
|
||||
int (*disparea)(u8 area);
|
||||
|
||||
int (*sscreen_get)(struct rk29fb_screen *screen, u8 resolution);
|
||||
int (*sscreen_set)(struct rk29fb_screen *screen, bool type);// 1: use scaler 0:bypass
|
||||
} rk_screen;
|
||||
|
||||
extern void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info);
|
||||
extern void set_tv_info(struct rk29fb_screen *screen);
|
||||
extern void set_hdmi_info(struct rk29fb_screen *screen);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
13
drivers/video/display/tve/Kconfig
Normal file
13
drivers/video/display/tve/Kconfig
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
config RK610_TVOUT
|
||||
bool "RK610(Jetta) tvout support"
|
||||
depends on MFD_RK610
|
||||
default y if MFD_RK610
|
||||
help
|
||||
Support Jetta(RK610) to output YPbPr and CVBS.
|
||||
|
||||
config RK610_TVOUT_YPbPr
|
||||
bool "support YPbPr output"
|
||||
depends on RK610_TVOUT
|
||||
config RK610_TVOUT_CVBS
|
||||
bool "support CVBS output"
|
||||
depends on RK610_TVOUT
|
||||
6
drivers/video/display/tve/Makefile
Normal file
6
drivers/video/display/tve/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for the jetta tv control.
|
||||
#
|
||||
obj-$(CONFIG_RK610_TVOUT) += rk610_tv.o
|
||||
obj-$(CONFIG_RK610_TVOUT_YPbPr) += rk610_tv_ypbpr.o
|
||||
obj-$(CONFIG_RK610_TVOUT_CVBS) += rk610_tv_cvbs.o
|
||||
246
drivers/video/display/tve/rk610_tv.c
Normal file
246
drivers/video/display/tve/rk610_tv.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* rk610_tv.c
|
||||
*
|
||||
* Driver for rockchip rk610 tv control
|
||||
* Copyright (C) 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/console.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "rk610_tv.h"
|
||||
#include "../../rk29_fb.h"
|
||||
|
||||
#define DRV_NAME "rk610_tvout"
|
||||
#define RK610_I2C_RATE 100*1000
|
||||
|
||||
volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT;
|
||||
static struct i2c_client *rk610_tv_i2c_client = NULL;
|
||||
|
||||
int rk610_tv_wirte_reg(u8 reg, u8 data)
|
||||
{
|
||||
int ret;
|
||||
if(rk610_tv_i2c_client == NULL)
|
||||
return -1;
|
||||
ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode)
|
||||
{
|
||||
struct rk29fb_screen *screen;
|
||||
|
||||
if(modedb == NULL)
|
||||
return -1;
|
||||
screen = kzalloc(sizeof(struct rk29fb_screen), GFP_KERNEL);
|
||||
if(screen == NULL)
|
||||
return -1;
|
||||
|
||||
memset(screen, 0, sizeof(struct rk29fb_screen));
|
||||
/* screen type & face */
|
||||
screen->type = SCREEN_HDMI;
|
||||
screen->mode = modedb->vmode;
|
||||
screen->face = modedb->flag;
|
||||
/* Screen size */
|
||||
screen->x_res = modedb->xres;
|
||||
screen->y_res = modedb->yres;
|
||||
|
||||
/* Timing */
|
||||
screen->pixclock = modedb->pixclock;
|
||||
|
||||
screen->lcdc_aclk = 500000000;
|
||||
screen->left_margin = modedb->left_margin;
|
||||
screen->right_margin = modedb->right_margin;
|
||||
screen->hsync_len = modedb->hsync_len;
|
||||
screen->upper_margin = modedb->upper_margin;
|
||||
screen->lower_margin = modedb->lower_margin;
|
||||
screen->vsync_len = modedb->vsync_len;
|
||||
|
||||
/* Pin polarity */
|
||||
if(FB_SYNC_HOR_HIGH_ACT & modedb->sync)
|
||||
screen->pin_hsync = 1;
|
||||
else
|
||||
screen->pin_hsync = 0;
|
||||
if(FB_SYNC_VERT_HIGH_ACT & modedb->sync)
|
||||
screen->pin_vsync = 1;
|
||||
else
|
||||
screen->pin_vsync = 0;
|
||||
screen->pin_den = 0;
|
||||
screen->pin_dclk = 0;
|
||||
|
||||
/* Swap rule */
|
||||
screen->swap_rb = 0;
|
||||
screen->swap_rg = 0;
|
||||
screen->swap_gb = 0;
|
||||
screen->swap_delta = 0;
|
||||
screen->swap_dumy = 0;
|
||||
|
||||
/* Operation function*/
|
||||
screen->init = NULL;
|
||||
screen->standby = NULL;
|
||||
|
||||
switch(tv_mode)
|
||||
{
|
||||
#ifdef CONFIG_RK610_TVOUT_CVBS
|
||||
case TVOUT_CVBS_NTSC:
|
||||
case TVOUT_CVBS_PAL:
|
||||
screen->init = rk610_tv_cvbs_init;;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RK610_TVOUT_YPbPr
|
||||
case TVOUT_YPbPr_720x480p_60:
|
||||
case TVOUT_YPbPr_720x576p_50:
|
||||
case TVOUT_YPbPr_1280x720p_50:
|
||||
case TVOUT_YPbPr_1280x720p_60:
|
||||
//case TVOUT_YPbPr_1920x1080i_50:
|
||||
case TVOUT_YPbPr_1920x1080i_60:
|
||||
case TVOUT_YPbPr_1920x1080p_50:
|
||||
case TVOUT_YPbPr_1920x1080p_60:
|
||||
screen->init = rk610_tv_ypbpr_init;
|
||||
break;
|
||||
#endif
|
||||
default:{
|
||||
kfree(screen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rk610_tv_output_status = tv_mode;
|
||||
FB_Switch_Screen(screen, 1);
|
||||
kfree(screen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rk610_tv_standby(int type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
#ifdef CONFIG_RK610_TVOUT_CVBS
|
||||
case RK610_TVOUT_CVBS:
|
||||
if(rk610_cvbs_monspecs.enable == 0)
|
||||
return 0;
|
||||
#ifdef CONFIG_RK610_TVOUT_YPbPr
|
||||
if(rk610_ypbpr_monspecs.enable == 1)
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_RK610_TVOUT_YPbPr
|
||||
case RK610_TVOUT_YPBPR:
|
||||
if(rk610_ypbpr_monspecs.enable == 0)
|
||||
return 0;
|
||||
#ifdef CONFIG_RK610_TVOUT_CVBS
|
||||
if(rk610_cvbs_monspecs.enable == 1)
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = rk610_tv_wirte_reg(TVE_POWERCR, 0);
|
||||
if(ret < 0){
|
||||
printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0);
|
||||
if(ret < 0){
|
||||
printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
rc = -ENODEV;
|
||||
goto failout;
|
||||
}
|
||||
rk610_tv_i2c_client = client;
|
||||
|
||||
#ifdef CONFIG_RK610_TVOUT_YPbPr
|
||||
rk610_register_display_ypbpr(&client->dev);
|
||||
if(rk610_tv_output_status > TVOUT_CVBS_PAL)
|
||||
rk_display_device_enable(rk610_ypbpr_monspecs.ddev);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RK610_TVOUT_CVBS
|
||||
rk610_register_display_cvbs(&client->dev);
|
||||
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
|
||||
rk_display_device_enable(rk610_cvbs_monspecs.ddev);
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n");
|
||||
return 0;
|
||||
failout:
|
||||
kfree(client);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rk610_tv_remove(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct i2c_device_id rk610_tv_id[] = {
|
||||
{ DRV_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rk610_tv_id);
|
||||
|
||||
static struct i2c_driver rk610_tv_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.id_table = rk610_tv_id,
|
||||
.probe = rk610_tv_probe,
|
||||
.remove = rk610_tv_remove,
|
||||
};
|
||||
|
||||
static int __init rk610_tv_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = i2c_add_driver(&rk610_tv_driver);
|
||||
if(ret < 0){
|
||||
printk("i2c_add_driver err, ret = %d\n", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rk610_tv_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rk610_tv_driver);
|
||||
}
|
||||
|
||||
module_init(rk610_tv_init);
|
||||
//late_initcall(rk610_tv_init);
|
||||
module_exit(rk610_tv_exit);
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
129
drivers/video/display/tve/rk610_tv.h
Normal file
129
drivers/video/display/tve/rk610_tv.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#ifndef _RK610_TV_H
|
||||
#define _RK610_TV_H
|
||||
#include <linux/display-sys.h>
|
||||
#include <linux/fb.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include "../screen/screen.h"
|
||||
#include "../../rk29_fb.h"
|
||||
#include <linux/mfd/rk610_core.h>
|
||||
|
||||
#define TVE_VFCR 0x00
|
||||
#define TVE_VFCR_ENABLE_SUBCARRIER_RESET 0 << 6
|
||||
#define TVE_VFCR_DISABLE_SUBCARRIER_RESET 1 << 6
|
||||
#define TVE_VFCR_VIN_RANGE_16_235 0 << 3
|
||||
#define TVE_VFCR_VIN_RANGE_1_254 1 << 3
|
||||
#define TVE_VFCR_BLACK_7_5_IRE 0 << 2
|
||||
#define TVE_VFCR_BLACK_0_IRE 1 << 2
|
||||
#define TVE_VFCR_NTSC 0
|
||||
#define TVE_VFCR_PAL_M 1
|
||||
#define TVE_VFCR_PAL_B_N 2
|
||||
#define TVE_VFCR_PAL_NC 3
|
||||
|
||||
#define TVE_VINCR 0x01
|
||||
#define TVE_VINCR_PIX_DATA_DELAY(n) (n << 5)
|
||||
#define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE 0 << 4
|
||||
#define TVE_VINCR_H_SYNC_POLARITY_POSITIVE 1 << 4
|
||||
#define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE 0 << 3
|
||||
#define TVE_VINCR_V_SYNC_POLARITY_POSITIVE 1 << 3
|
||||
enum {
|
||||
INPUT_FORMAT_BT601_SLAVE = 0,
|
||||
INPUT_FORMAT_BT656,
|
||||
INPUT_FORMAT_BT601_MASTER,
|
||||
INPUT_FORMAT_INTERNAL_COLLOR_BAR
|
||||
};
|
||||
#define TVE_VINCR_INPUT_FORMAT(n) (n << 1)
|
||||
#define TVE_VINCR_VSYNC_FUNCTION_VSYNC 0
|
||||
#define TVE_VINCR_VSYNC_FUNCTION_FIELD 1
|
||||
|
||||
#define TVE_VOUTCR 0x02
|
||||
#define TVE_VOUTCR_OUTPUT_CVBS 0 << 6
|
||||
#define TVE_VOUTCR_OUTPUT_YPBPR 1 << 6
|
||||
#define TVE_VOUTCR_OUTPUT_ENABLE_BLUE 1 << 5
|
||||
#define TVE_VOUTCR_OUTPUT_ENABLE_BLACK 1 << 4
|
||||
#define TVE_VOUTCR_DISABLE_CVBS_COLOR 1 << 3
|
||||
#define TVE_VOUTCR_CVBS_Y2C_DELAY(n) (n << 0)
|
||||
|
||||
#define TVE_POWERCR 0x03
|
||||
#define TVE_PIX_CLK_INVERSE_ENABLE 1 << 4
|
||||
#define TVE_DAC_CLK_INVERSE_DISABLE 1 << 3
|
||||
#define TVE_DAC_Y_ENABLE 1 << 2
|
||||
#define TVE_DAC_U_ENABLE 1 << 1
|
||||
#define TVE_DAC_V_ENABLE 1 << 0
|
||||
|
||||
#define TVE_HDTVCR 0x05
|
||||
#define TVE_RESET 1 << 7
|
||||
#define TVE_FILTER(n) (n << 5)
|
||||
#define TVE_COLOR_CONVERT_REC601 0 << 4
|
||||
#define TVE_COLOR_CONVERT_REC709 1 << 4
|
||||
#define TVE_INPUT_DATA_RGB 0 << 3
|
||||
#define TVE_INPUT_DATA_YUV 1 << 3
|
||||
#define TVE_OUTPUT_50HZ 0 << 2
|
||||
#define TVE_OUTPUT_60HZ 1 << 2
|
||||
#define TVE_OUTPUT_MODE_PAL_NTSC 0
|
||||
#define TVE_OUTPUT_MODE_576P 1
|
||||
#define TVE_OUTPUT_MODE_480P 2
|
||||
#define TVE_OUTPUT_MODE_720P 3
|
||||
|
||||
#define TVE_YADJCR 0x06
|
||||
#define TVE_OUTPUT_MODE_1080P 1 << 6
|
||||
#define TVE_OUTPUT_MODE_1080I 1 << 5
|
||||
#define TVE_Y_ADJ_VALUE(n) n
|
||||
#define TVE_YCBADJCR 0x07
|
||||
#define TVE_YCRADJCR 0x08
|
||||
|
||||
/******************* TVOUT OUTPUT TYPE **********************/
|
||||
struct rk610_monspecs {
|
||||
struct rk_display_device *ddev;
|
||||
unsigned int enable;
|
||||
struct fb_videomode *mode;
|
||||
struct list_head modelist;
|
||||
unsigned int mode_set;
|
||||
};
|
||||
|
||||
enum {
|
||||
TVOUT_CVBS_NTSC = 1,
|
||||
TVOUT_CVBS_PAL,
|
||||
TVOUT_YPbPr_720x480p_60,
|
||||
TVOUT_YPbPr_720x576p_50,
|
||||
TVOUT_YPbPr_1280x720p_50,
|
||||
TVOUT_YPbPr_1280x720p_60,
|
||||
//TVOUT_YPbPr_1920x1080i_50,
|
||||
TVOUT_YPbPr_1920x1080i_60,
|
||||
TVOUT_YPbPr_1920x1080p_50,
|
||||
TVOUT_YPbPr_1920x1080p_60
|
||||
};
|
||||
|
||||
#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC
|
||||
|
||||
enum {
|
||||
RK610_TVOUT_CVBS = 0,
|
||||
RK610_TVOUT_YC,
|
||||
RK610_TVOUT_YPBPR,
|
||||
};
|
||||
|
||||
extern volatile int rk610_tv_output_status;
|
||||
extern struct rk_display_ops rk610_display_ops;
|
||||
|
||||
extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable );
|
||||
|
||||
extern int rk610_tv_wirte_reg(u8 reg, u8 data);
|
||||
extern int rk610_tv_standby(int type);
|
||||
extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode);
|
||||
extern int rk610_register_display(struct device *parent);
|
||||
|
||||
#ifdef CONFIG_RK610_TVOUT_YPbPr
|
||||
extern int rk610_tv_ypbpr_init(void);
|
||||
extern int rk610_register_display_ypbpr(struct device *parent);
|
||||
extern struct rk610_monspecs rk610_ypbpr_monspecs;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RK610_TVOUT_CVBS
|
||||
extern int rk610_tv_cvbs_init(void);
|
||||
extern int rk610_register_display_cvbs(struct device *parent);
|
||||
extern struct rk610_monspecs rk610_cvbs_monspecs;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
209
drivers/video/display/tve/rk610_tv_cvbs.c
Normal file
209
drivers/video/display/tve/rk610_tv_cvbs.c
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/display-sys.h>
|
||||
#include "rk610_tv.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
|
||||
#define RK610_LED_CVBS_PIN RK29_PIN4_PD3
|
||||
#else
|
||||
#define RK610_LED_CVBS_PIN INVALID_GPIO
|
||||
#endif
|
||||
|
||||
#ifdef USE_RGB2CCIR
|
||||
static const struct fb_videomode rk610_cvbs_mode [] = {
|
||||
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
|
||||
{ "NTSC", 60, 720, 480, 27000000, 116, 16, 25, 14, 6, 6, 0, 1, OUT_P888 },
|
||||
{ "PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, OUT_P888 },
|
||||
};
|
||||
#else
|
||||
static const struct fb_videomode rk610_cvbs_mode [] = {
|
||||
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
|
||||
{ "NTSC", 60, 720, 480, 27000000, 116, 16, 16, 3, 6, 3, 0, 1, OUT_CCIR656 },
|
||||
{ "PAL", 50, 720, 576, 27000000, 126, 12, 19, 2, 6, 3, 0, 1, OUT_CCIR656 },
|
||||
};
|
||||
#endif
|
||||
|
||||
struct rk610_monspecs rk610_cvbs_monspecs;
|
||||
|
||||
|
||||
int rk610_tv_cvbs_init(void)
|
||||
{
|
||||
unsigned char TVE_Regs[9];
|
||||
unsigned char TVE_CON_Reg;
|
||||
int ret, i;
|
||||
|
||||
rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
|
||||
|
||||
memset(TVE_Regs, 0, 9);
|
||||
TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE;
|
||||
TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
|
||||
TVE_Regs[TVE_POWERCR] = TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
|
||||
TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_CVBS;
|
||||
TVE_Regs[TVE_YADJCR] = 0x17;
|
||||
TVE_Regs[TVE_YCBADJCR] = 0x10;
|
||||
TVE_Regs[TVE_YCRADJCR] = 0x10;
|
||||
|
||||
switch(rk610_tv_output_status) {
|
||||
case TVOUT_CVBS_NTSC:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC;
|
||||
#ifdef USE_RGB2CCIR
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
|
||||
TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE;
|
||||
#else
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
|
||||
#endif
|
||||
break;
|
||||
case TVOUT_CVBS_PAL:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N;
|
||||
#ifdef USE_RGB2CCIR
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
|
||||
TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE;
|
||||
#else
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < sizeof(TVE_Regs); i++){
|
||||
// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
|
||||
ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
|
||||
if(ret < 0){
|
||||
printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
// printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg);
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
|
||||
#ifdef USE_RGB2CCIR
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable)
|
||||
{
|
||||
if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status)
|
||||
{
|
||||
if(enable == 0)
|
||||
{
|
||||
rk610_tv_standby(RK610_TVOUT_CVBS);
|
||||
rk610_cvbs_monspecs.enable = 0;
|
||||
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
|
||||
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
|
||||
}
|
||||
else if(enable == 1)
|
||||
{
|
||||
rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set);
|
||||
rk610_cvbs_monspecs.enable = 1;
|
||||
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
|
||||
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_get_enable(struct rk_display_device *device)
|
||||
{
|
||||
return rk610_cvbs_monspecs.enable;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_get_status(struct rk_display_device *device)
|
||||
{
|
||||
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
|
||||
{
|
||||
*modelist = &(rk610_cvbs_monspecs.modelist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
|
||||
{
|
||||
if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode))
|
||||
{
|
||||
if( ((i + 1) != rk610_tv_output_status) )
|
||||
{
|
||||
rk610_cvbs_monspecs.mode_set = i + 1;
|
||||
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
*mode = *(rk610_cvbs_monspecs.mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rk_display_ops rk610_cvbs_display_ops = {
|
||||
.setenable = rk610_cvbs_set_enable,
|
||||
.getenable = rk610_cvbs_get_enable,
|
||||
.getstatus = rk610_cvbs_get_status,
|
||||
.getmodelist = rk610_cvbs_get_modelist,
|
||||
.setmode = rk610_cvbs_set_mode,
|
||||
.getmode = rk610_cvbs_get_mode,
|
||||
};
|
||||
|
||||
static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata)
|
||||
{
|
||||
device->owner = THIS_MODULE;
|
||||
strcpy(device->type, "TV");
|
||||
device->priority = DISPLAY_PRIORITY_TV;
|
||||
device->priv_data = devdata;
|
||||
device->ops = &rk610_cvbs_display_ops;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct rk_display_driver display_rk610_cvbs = {
|
||||
.probe = rk610_display_cvbs_probe,
|
||||
};
|
||||
|
||||
int rk610_register_display_cvbs(struct device *parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs));
|
||||
INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist);
|
||||
for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
|
||||
fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist);
|
||||
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) {
|
||||
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]);
|
||||
rk610_cvbs_monspecs.mode_set = rk610_tv_output_status;
|
||||
}
|
||||
else {
|
||||
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]);
|
||||
rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
|
||||
}
|
||||
rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL);
|
||||
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
|
||||
{
|
||||
if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0)
|
||||
{
|
||||
gpio_free(RK610_LED_CVBS_PIN);
|
||||
dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n ");
|
||||
return -1;
|
||||
}
|
||||
gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp);
|
||||
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
229
drivers/video/display/tve/rk610_tv_ypbpr.c
Normal file
229
drivers/video/display/tve/rk610_tv_ypbpr.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/display-sys.h>
|
||||
#include "rk610_tv.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
|
||||
#define RK610_LED_YPbPr_PIN RK29_PIN4_PD5
|
||||
#else
|
||||
#define RK610_LED_YPbPr_PIN INVALID_GPIO
|
||||
#endif
|
||||
#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg)
|
||||
|
||||
static const struct fb_videomode rk610_YPbPr_mode [] = {
|
||||
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
|
||||
{ "YPbPr480p", 60, 720, 480, 27000000, 55, 19, 37, 5, 64, 5, 0, 0, OUT_P888 },
|
||||
{ "YPbPr576p", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, OUT_P888 },
|
||||
{ "YPbPr720p@50", 50, 1280, 720, 74250000, 600, 0, 20, 5, 100, 5, 0, 0, OUT_P888 },
|
||||
{ "YPbPr720p@60", 60, 1280, 720, 74250000, 270, 0, 20, 5, 100, 5, 0, 0, OUT_P888 },
|
||||
//{ "YPbPr1080i@50", 50, 1920, 1080, 148500000, 620, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 },
|
||||
{ "YPbPr1080i@60", 60, 1920, 1080, 148500000, 180, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 },
|
||||
{ "YPbPr1080p@50", 50, 1920, 1080, 148500000, 620, 0, 36, 4, 100, 5, 0, 0, OUT_P888 },
|
||||
{ "YPbPr1080p@60", 60, 1920, 1080, 148500000, 180, 0, 36, 4, 100, 5, 0, 0, OUT_P888 },
|
||||
};
|
||||
|
||||
struct rk610_monspecs rk610_ypbpr_monspecs;
|
||||
|
||||
int rk610_tv_ypbpr_init(void)
|
||||
{
|
||||
unsigned char TVE_Regs[9];
|
||||
unsigned char TVE_CON_Reg;
|
||||
int i, ret;
|
||||
|
||||
rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
|
||||
memset(TVE_Regs, 0, 9);
|
||||
|
||||
TVE_CON_Reg = 0x00;
|
||||
|
||||
TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
|
||||
TVE_Regs[TVE_POWERCR] = TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
|
||||
TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_YPBPR;
|
||||
TVE_Regs[TVE_YADJCR] = 0x17;
|
||||
TVE_Regs[TVE_YCBADJCR] = 0x10;
|
||||
TVE_Regs[TVE_YCRADJCR] = 0x10;
|
||||
|
||||
switch(rk610_tv_output_status)
|
||||
{
|
||||
case TVOUT_YPbPr_720x480p_60:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P;
|
||||
break;
|
||||
case TVOUT_YPbPr_720x576p_50:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P;
|
||||
break;
|
||||
case TVOUT_YPbPr_1280x720p_50:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P;
|
||||
break;
|
||||
case TVOUT_YPbPr_1280x720p_60:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P;
|
||||
break;
|
||||
/*case TVOUT_YPbPr_1920x1080i_50:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ;
|
||||
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I;
|
||||
break;
|
||||
*/
|
||||
case TVOUT_YPbPr_1920x1080i_60:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ;
|
||||
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I;
|
||||
break;
|
||||
case TVOUT_YPbPr_1920x1080p_50:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ;
|
||||
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P;
|
||||
break;
|
||||
case TVOUT_YPbPr_1920x1080p_60:
|
||||
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
|
||||
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
|
||||
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ;
|
||||
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
|
||||
|
||||
for(i = 0; i < sizeof(TVE_Regs); i++){
|
||||
// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
|
||||
ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
|
||||
if(ret < 0){
|
||||
E("rk610_tv_wirte_reg %d err!\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable)
|
||||
{
|
||||
if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status)
|
||||
{
|
||||
if(enable == 0)
|
||||
{
|
||||
rk610_tv_standby(RK610_TVOUT_YPBPR);
|
||||
rk610_ypbpr_monspecs.enable = 0;
|
||||
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
|
||||
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
|
||||
}
|
||||
else if(enable == 1)
|
||||
{
|
||||
rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set);
|
||||
rk610_ypbpr_monspecs.enable = 1;
|
||||
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
|
||||
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_get_enable(struct rk_display_device *device)
|
||||
{
|
||||
return rk610_ypbpr_monspecs.enable;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_get_status(struct rk_display_device *device)
|
||||
{
|
||||
if(rk610_tv_output_status > TVOUT_CVBS_PAL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist)
|
||||
{
|
||||
*modelist = &(rk610_ypbpr_monspecs.modelist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
|
||||
{
|
||||
if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode))
|
||||
{
|
||||
if( (i + 3) != rk610_tv_output_status )
|
||||
{
|
||||
rk610_ypbpr_monspecs.mode_set = i + 3;
|
||||
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
*mode = *(rk610_ypbpr_monspecs.mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rk_display_ops rk610_ypbpr_display_ops = {
|
||||
.setenable = rk610_ypbpr_set_enable,
|
||||
.getenable = rk610_ypbpr_get_enable,
|
||||
.getstatus = rk610_ypbpr_get_status,
|
||||
.getmodelist = rk610_ypbpr_get_modelist,
|
||||
.setmode = rk610_ypbpr_set_mode,
|
||||
.getmode = rk610_ypbpr_get_mode,
|
||||
};
|
||||
|
||||
static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata)
|
||||
{
|
||||
device->owner = THIS_MODULE;
|
||||
strcpy(device->type, "YPbPr");
|
||||
device->priority = DISPLAY_PRIORITY_YPbPr;
|
||||
device->priv_data = devdata;
|
||||
device->ops = &rk610_ypbpr_display_ops;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct rk_display_driver display_rk610_YPbPr = {
|
||||
.probe = rk610_display_YPbPr_probe,
|
||||
};
|
||||
|
||||
int rk610_register_display_ypbpr(struct device *parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs));
|
||||
INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist);
|
||||
for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
|
||||
fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist);
|
||||
if(rk610_tv_output_status > TVOUT_CVBS_PAL) {
|
||||
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]);
|
||||
rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status;
|
||||
}
|
||||
else {
|
||||
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]);
|
||||
rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60;
|
||||
}
|
||||
rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL);
|
||||
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
|
||||
{
|
||||
if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0)
|
||||
{
|
||||
gpio_free(RK610_LED_YPbPr_PIN);
|
||||
dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n ");
|
||||
return -1;
|
||||
}
|
||||
gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp);
|
||||
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -14,11 +14,13 @@ config HDMI_SAVE_DATA
|
|||
bool "enable hdmi save data"
|
||||
help
|
||||
Enable hdmi save data in rtc register
|
||||
|
||||
config HDMI_DUAL_DISP
|
||||
bool "dual display support"
|
||||
depends on RK610_HDMI
|
||||
help
|
||||
Support output lcd and hdmi at the same time.
|
||||
|
||||
#config HDMI_DUAL_DISP
|
||||
# bool "hdmi support dual display"
|
||||
# help
|
||||
# nothing
|
||||
#config HDMI_DEBUG
|
||||
# bool "hdmi debug"
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -4,4 +4,9 @@ config ANX7150
|
|||
bool "anx7150"
|
||||
config ANX9030
|
||||
bool "anx9030"
|
||||
config RK610_HDMI
|
||||
bool "RK610(Jetta) hdmi support"
|
||||
depends on MFD_RK610
|
||||
help
|
||||
Support Jetta(RK610) to hdmi.
|
||||
endchoice
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
obj-$(CONFIG_ANX7150) += anx7150_hw.o anx7150.o
|
||||
|
||||
obj-$(CONFIG_ANX7150) += anx7150/anx7150.o anx7150/anx7150_hw.o
|
||||
obj-$(CONFIG_RK610_HDMI) += rk610/rk610_hdmi.o rk610/rk610_hdmi_hw.o
|
||||
|
|
|
|||
0
drivers/video/hdmi/chips/anx7150.c → drivers/video/hdmi/chips/anx7150/anx7150.c
Executable file → Normal file
0
drivers/video/hdmi/chips/anx7150.c → drivers/video/hdmi/chips/anx7150/anx7150.c
Executable file → Normal file
0
drivers/video/hdmi/chips/anx7150.h → drivers/video/hdmi/chips/anx7150/anx7150.h
Executable file → Normal file
0
drivers/video/hdmi/chips/anx7150.h → drivers/video/hdmi/chips/anx7150/anx7150.h
Executable file → Normal file
0
drivers/video/hdmi/chips/anx7150_hw.h → drivers/video/hdmi/chips/anx7150/anx7150_hw.h
Executable file → Normal file
0
drivers/video/hdmi/chips/anx7150_hw.h → drivers/video/hdmi/chips/anx7150/anx7150_hw.h
Executable file → Normal file
299
drivers/video/hdmi/chips/rk610/rk610_hdmi.c
Normal file
299
drivers/video/hdmi/chips/rk610/rk610_hdmi.c
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
#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 <mach/board.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <linux/mfd/rk610_core.h>
|
||||
#include "rk610_hdmi.h"
|
||||
#include "rk610_hdmi_hw.h"
|
||||
|
||||
|
||||
struct i2c_client *rk610_g_hdmi_client=NULL;
|
||||
static bool hpd=0;
|
||||
|
||||
static void rk610_handler(struct work_struct *work)
|
||||
{
|
||||
struct i2c_client *client = rk610_g_hdmi_client;
|
||||
if(client==NULL){
|
||||
printk(">>> %s client==NULL\n",__func__);
|
||||
}
|
||||
Rk610_hdmi_event_work(client,&hpd);
|
||||
}
|
||||
|
||||
static DECLARE_DELAYED_WORK(rk610_irq_work, rk610_handler);
|
||||
static int rk610_hdmi_precent(struct hdmi *hdmi)
|
||||
{
|
||||
//struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi);
|
||||
schedule_delayed_work(&rk610_irq_work, msecs_to_jiffies(30));
|
||||
return hpd;
|
||||
}
|
||||
|
||||
static int rk610_hdmi_param_chg(struct rk610_hdmi_inf *rk610_hdmi)
|
||||
{
|
||||
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);
|
||||
hdmi_switch_fb(rk610_hdmi->hdmi, rk610_hdmi->hdmi->display_on);
|
||||
Rk610_hdmi_Set_Video(rk610_hdmi->hdmi->resolution);
|
||||
Rk610_hdmi_Set_Audio(rk610_hdmi->hdmi->audio_fs);
|
||||
Rk610_hdmi_Config_Done(rk610_hdmi->client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk610_hdmi_set_param(struct hdmi *hdmi)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi);
|
||||
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);
|
||||
if(rk610_hdmi->init == 1)
|
||||
return 0;
|
||||
|
||||
rk610_hdmi_param_chg(rk610_hdmi);
|
||||
return 0;
|
||||
}
|
||||
static int rk610_hdmi_insert(struct hdmi *hdmi)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi);
|
||||
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);
|
||||
if(rk610_hdmi->init == 1)
|
||||
return -1;
|
||||
rk610_hdmi_param_chg(rk610_hdmi);
|
||||
hdmi_set_spk(HDMI_DISABLE);
|
||||
printk("rk610_hdmi_insert hdmi->display_on=%d\n",hdmi->display_on);
|
||||
hdmi->scale = hdmi->scale_set;
|
||||
return 0;
|
||||
}
|
||||
static int rk610_hdmi_remove(struct hdmi *hdmi)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi);
|
||||
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);
|
||||
if(rk610_hdmi->init == 1)
|
||||
return -1;
|
||||
hdmi_set_spk(HDMI_ENABLE);
|
||||
hdmi_switch_fb(hdmi, HDMI_DISABLE);
|
||||
printk("rk610_hdmi_remove hdmi->display_on=%d\n",hdmi->display_on);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
static void rk610_hdmi_early_suspend(struct early_suspend *h)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = container_of(h,
|
||||
struct rk610_hdmi_inf,
|
||||
early_suspend);
|
||||
printk( "rk610_hdmi enter early suspend\n");
|
||||
hdmi_suspend(rk610_hdmi->hdmi);
|
||||
Rk610_hdmi_suspend(rk610_hdmi->client);
|
||||
return;
|
||||
}
|
||||
|
||||
static void rk610_hdmi_early_resume(struct early_suspend *h)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = container_of(h,
|
||||
struct rk610_hdmi_inf,
|
||||
early_suspend);
|
||||
printk("rk610_hdmi exit early suspend\n");
|
||||
hdmi_resume(rk610_hdmi->hdmi);
|
||||
Rk610_hdmi_resume(rk610_hdmi->client);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk610_hdmi_init(struct hdmi *hdmi)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = hdmi_priv(hdmi);
|
||||
#ifdef CONFIG_HDMI_SAVE_DATA
|
||||
int hdmi_data = hdmi_get_data();
|
||||
if(hdmi_data<0){
|
||||
hdmi_set_data((hdmi->resolution&0x7)|((hdmi->scale&0x1f)<<3));
|
||||
}
|
||||
else{
|
||||
hdmi->resolution = hdmi_data&0x7;
|
||||
hdmi->scale_set= ((hdmi_data>>3)&0x1f) + MIN_SCALE;
|
||||
hdmi->scale = hdmi->scale_set;
|
||||
}
|
||||
#endif
|
||||
RK610_DBG(&rk610_hdmi->client->dev,"%s \n",__FUNCTION__);
|
||||
rk610_hdmi->init =0;
|
||||
Rk610_hdmi_init(rk610_hdmi->client);
|
||||
hdmi_changed(hdmi,1);
|
||||
Rk610_hdmi_Set_Video(hdmi->resolution);
|
||||
Rk610_hdmi_Set_Audio(hdmi->audio_fs);
|
||||
Rk610_hdmi_Config_Done(rk610_hdmi->client);
|
||||
return 0;
|
||||
}
|
||||
static struct hdmi_ops rk610_hdmi_ops = {
|
||||
.set_param = rk610_hdmi_set_param,
|
||||
.hdmi_precent = rk610_hdmi_precent,
|
||||
.insert = rk610_hdmi_insert,
|
||||
.remove = rk610_hdmi_remove,
|
||||
.init = rk610_hdmi_init,
|
||||
};
|
||||
#ifdef CONFIG_RK610_DEBUG
|
||||
static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
{
|
||||
return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
}
|
||||
|
||||
static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val)
|
||||
{
|
||||
return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
|
||||
}
|
||||
static ssize_t rk610_show_reg_attrs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
|
||||
int i,size=0;
|
||||
char val;
|
||||
struct i2c_client *client=rk610_g_hdmi_client;
|
||||
|
||||
for(i=0;i<256;i++)
|
||||
{
|
||||
rk610_read_p0_reg(client, i, &val);
|
||||
if(i%16==0)
|
||||
size += sprintf(buf+size,"\n>>>rk610_hdmi %x:",i);
|
||||
size += sprintf(buf+size," %2x",val);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
static ssize_t rk610_store_reg_attrs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct i2c_client *client=NULL;
|
||||
char val,reg,addr;
|
||||
client = rk610_g_hdmi_client;
|
||||
printk("/**********rk610 reg config******/");
|
||||
|
||||
sscanf(buf, "%x%x%x", &val,®,&addr);
|
||||
printk("addr=%x ,reg=%x val=%x\n",addr,reg,val);
|
||||
rk610_write_p0_reg(client, reg, &val);
|
||||
printk("val=%x\n",val);
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct device_attribute rk610_attrs[] = {
|
||||
__ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs),
|
||||
};
|
||||
#endif
|
||||
#if 0
|
||||
static irqreturn_t rk610_hdmi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct hdmi *hdmi = (struct hdmi *)dev_id;
|
||||
unsigned long lock_flags = 0;
|
||||
printk("The rk610_hdmi interrupt handeler is working..\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk610_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct hdmi *hdmi = NULL;
|
||||
struct rk610_hdmi_inf *rk610_hdmi = NULL;
|
||||
|
||||
struct hdmi_platform_data *pdata = client->dev.platform_data;
|
||||
rk610_g_hdmi_client = client;
|
||||
if(pdata && pdata->io_init)
|
||||
{
|
||||
printk("rk610_hdmi_i2c_probe io_init \n");
|
||||
pdata->io_init();
|
||||
}
|
||||
hdmi = hdmi_register(sizeof(struct rk610_hdmi_inf), &client->dev);
|
||||
if (!hdmi)
|
||||
{
|
||||
dev_err(&client->dev, "fail to register hdmi\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdmi->ops = &rk610_hdmi_ops;
|
||||
hdmi->display_on = HDMI_DEFAULT_MODE;
|
||||
hdmi->hdcp_on = HDMI_DISABLE;
|
||||
hdmi->audio_fs = HDMI_I2S_DEFAULT_Fs;
|
||||
hdmi->resolution = HDMI_DEFAULT_RESOLUTION;
|
||||
hdmi->dual_disp = DUAL_DISP_CAP;
|
||||
hdmi->mode = DISP_ON_LCD;
|
||||
hdmi->scale = 100;
|
||||
hdmi->scale_set = 100;
|
||||
|
||||
rk610_hdmi = hdmi_priv(hdmi);
|
||||
rk610_hdmi->init = 1;
|
||||
rk610_hdmi->hdmi = hdmi;
|
||||
i2c_set_clientdata(client, rk610_hdmi);
|
||||
rk610_hdmi->client = client;
|
||||
if((gpio_request(client->irq, "hdmi gpio")) < 0)
|
||||
{
|
||||
dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
|
||||
goto err_gpio_free;
|
||||
}
|
||||
rk610_hdmi->irq = gpio_to_irq(client->irq);
|
||||
rk610_hdmi->gpio = client->irq;
|
||||
|
||||
gpio_direction_input(client->irq);
|
||||
#if 0
|
||||
if((ret = request_irq(rk610_hdmi->irq, rk610_hdmi_interrupt, IRQ_TYPE_EDGE_RISING,client->name, hdmi))<0){
|
||||
RK610_ERR(&client->dev, "fail to request gpio %d\n", client->irq);
|
||||
goto err_gpio_free;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
rk610_hdmi->early_suspend.suspend = rk610_hdmi_early_suspend;
|
||||
rk610_hdmi->early_suspend.resume = rk610_hdmi_early_resume;
|
||||
rk610_hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1;
|
||||
register_early_suspend(&rk610_hdmi->early_suspend);
|
||||
#endif
|
||||
#ifdef CONFIG_RK610_DEBUG
|
||||
device_create_file(&(client->dev), &rk610_attrs[0]);
|
||||
#endif
|
||||
rk610_hdmi_init(rk610_hdmi->hdmi);
|
||||
dev_info(&client->dev, "rk610_hdmi i2c probe ok\n");
|
||||
return 0;
|
||||
err_gpio_free:
|
||||
gpio_free(client->irq);
|
||||
err_hdmi_unregister:
|
||||
hdmi_unregister(hdmi);
|
||||
rk610_hdmi = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit rk610_hdmi_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rk610_hdmi_inf *rk610_hdmi = (struct rk610_hdmi_inf *)i2c_get_clientdata(client);
|
||||
struct hdmi *hdmi = rk610_hdmi->hdmi;
|
||||
|
||||
gpio_free(client->irq);
|
||||
hdmi_unregister(hdmi);
|
||||
rk610_hdmi = NULL;
|
||||
return 0;
|
||||
}
|
||||
static const struct i2c_device_id rk610_hdmi_id[] = {
|
||||
{ "rk610_hdmi", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct i2c_driver rk610_hdmi_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rk610_hdmi",
|
||||
},
|
||||
.probe = &rk610_hdmi_i2c_probe,
|
||||
.remove = &rk610_hdmi_i2c_remove,
|
||||
.id_table = rk610_hdmi_id,
|
||||
};
|
||||
|
||||
static int __init rk610_hdmi_module_init(void)
|
||||
{
|
||||
return i2c_add_driver(&rk610_hdmi_i2c_driver);
|
||||
}
|
||||
|
||||
static void __exit rk610_hdmi_module_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rk610_hdmi_i2c_driver);
|
||||
}
|
||||
|
||||
late_initcall(rk610_hdmi_module_init);
|
||||
//module_init(rk610_hdmi_module_init);
|
||||
module_exit(rk610_hdmi_module_exit);
|
||||
36
drivers/video/hdmi/chips/rk610/rk610_hdmi.h
Normal file
36
drivers/video/hdmi/chips/rk610/rk610_hdmi.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef _RK610_H
|
||||
#define _RK610_H
|
||||
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/earlysuspend.h>
|
||||
|
||||
/************RK610 device addr***********/
|
||||
#define RK610_CTRL_ADDR 0x40
|
||||
#define RK610_TVE_ADDR 0x42
|
||||
#define RK610_HDMI_ADDR 0x46
|
||||
#define RK610_CODEC_ADDR 0xc0 // 0x11xxxxxx
|
||||
|
||||
|
||||
/****************HDMI STRUCT********************************/
|
||||
|
||||
|
||||
struct rk610_hdmi_inf{
|
||||
int irq;
|
||||
int gpio;
|
||||
int init;
|
||||
struct i2c_client *client;
|
||||
struct hdmi *hdmi;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
};
|
||||
|
||||
/******************TVE STRUCT **************/
|
||||
|
||||
/*************RK610 STRUCT**********************************/
|
||||
//struct rk610_pdata {
|
||||
// struct rk610_hdmi_inf hdmi;
|
||||
// struct rk610_lcd_info lcd;
|
||||
//};
|
||||
/*****************END ***********************************/
|
||||
#endif
|
||||
1094
drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c
Normal file
1094
drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.c
Normal file
File diff suppressed because it is too large
Load Diff
208
drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h
Normal file
208
drivers/video/hdmi/chips/rk610/rk610_hdmi_hw.h
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
#ifndef _RK610_HDMI_HW_H
|
||||
#define _RK610_HDMI_HW_H
|
||||
#include <linux/earlysuspend.h>
|
||||
|
||||
#define MAX_V_DESCRIPTORS 20
|
||||
#define MAX_A_DESCRIPTORS 10
|
||||
#define MAX_SPEAKER_CONFIGURATIONS 4
|
||||
#define AUDIO_DESCR_SIZE 3
|
||||
|
||||
#define EDID_BLOCK_SIZE 128
|
||||
#define NUM_OF_EXTEN_ADDR 0x7e
|
||||
#define EDID_HDR_NO_OF_FF 0x06
|
||||
|
||||
// Data Block Tag Codes
|
||||
//====================================================
|
||||
#define AUDIO_D_BLOCK 0x01
|
||||
#define VIDEO_D_BLOCK 0x02
|
||||
#define VENDOR_SPEC_D_BLOCK 0x03
|
||||
#define SPKR_ALLOC_D_BLOCK 0x04
|
||||
#define USE_EXTENDED_TAG 0x07
|
||||
// Extended Data Block Tag Codes
|
||||
//====================================================
|
||||
#define COLORIMETRY_D_BLOCK 0x05
|
||||
|
||||
#define HDMI_SIGNATURE_LEN 0x03
|
||||
|
||||
#define CEC_PHYS_ADDR_LEN 0x02
|
||||
#define EDID_EXTENSION_TAG 0x02
|
||||
#define EDID_REV_THREE 0x03
|
||||
#define EDID_DATA_START 0x04
|
||||
|
||||
#define EDID_BLOCK_0 0x00
|
||||
#define EDID_BLOCK_2_3 0x01
|
||||
|
||||
#define VIDEO_CAPABILITY_D_BLOCK 0x00
|
||||
|
||||
//#define DEV_SUPPORT_CEC
|
||||
#if 1
|
||||
#define MSBIT 0x80
|
||||
#define LSBIT 0x01
|
||||
|
||||
#define TWO_LSBITS 0x03
|
||||
#define THREE_LSBITS 0x07
|
||||
#define FOUR_LSBITS 0x0F
|
||||
#define FIVE_LSBITS 0x1F
|
||||
#define SEVEN_LSBITS 0x7F
|
||||
#define TWO_MSBITS 0xC0
|
||||
#define EIGHT_BITS 0xFF
|
||||
#define BYTE_SIZE 0x08
|
||||
#define BITS_1_0 0x03
|
||||
#define BITS_2_1 0x06
|
||||
#define BITS_2_1_0 0x07
|
||||
#define BITS_3_2 0x0C
|
||||
#define BITS_4_3_2 0x1C
|
||||
#define BITS_5_4 0x30
|
||||
#define BITS_5_4_3 0x38
|
||||
#define BITS_6_5 0x60
|
||||
#define BITS_6_5_4 0x70
|
||||
#define BITS_7_6 0xC0
|
||||
|
||||
#define TPI_INTERNAL_PAGE_REG 0xBC
|
||||
#define TPI_INDEXED_OFFSET_REG 0xBD
|
||||
#define TPI_INDEXED_VALUE_REG 0xBE
|
||||
|
||||
#define EDID_TAG_ADDR 0x00
|
||||
#define EDID_REV_ADDR 0x01
|
||||
#define EDID_TAG_IDX 0x02
|
||||
#define LONG_DESCR_PTR_IDX 0x02
|
||||
#define MISC_SUPPORT_IDX 0x03
|
||||
|
||||
#define ESTABLISHED_TIMING_INDEX 35 // Offset of Established Timing in EDID block
|
||||
#define NUM_OF_STANDARD_TIMINGS 8
|
||||
#define STANDARD_TIMING_OFFSET 38
|
||||
#define LONG_DESCR_LEN 18
|
||||
#define NUM_OF_DETAILED_DESCRIPTORS 4
|
||||
|
||||
#define DETAILED_TIMING_OFFSET 0x36
|
||||
#endif
|
||||
enum{
|
||||
EDID_BLOCK0=0,
|
||||
EDID_BLOCK1,
|
||||
EDID_BLOCK2,
|
||||
EDID_BLOCK3,
|
||||
};
|
||||
#define RK610_SYS_FREG_CLK 11289600
|
||||
#define RK610_SCL_RATE (100*1000)
|
||||
#define RK610_DDC_CONFIG (RK610_SYS_FREG_CLK>>2)/RK610_SCL_RATE
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
//EVENT
|
||||
#define RK610_HPD_EVENT 1<<7
|
||||
#define RK610_HPD_PLUG 1<<7
|
||||
#define RK610_EDID_EVENT 1<<2
|
||||
|
||||
//output mode 0x52
|
||||
#define DISPLAY_DVI 0
|
||||
#define DISPLAY_HDMI 1
|
||||
|
||||
//0x00
|
||||
#define RK610_INT_POL 1
|
||||
#define RK610_SYS_PWR_ON 1
|
||||
#define RK610_SYS_PWR_OFF 0
|
||||
#define RK610_PHY_CLK 0
|
||||
#define RK610_SYS_CLK 1
|
||||
|
||||
#define RK610_MCLK_FS 0x01 //256fs
|
||||
//0x01
|
||||
// INPUT_VIDEO_FORMAT
|
||||
#define RGB_YUV444 0x00
|
||||
#define DDR_RGB444_YUV444 0x05
|
||||
#define DDR_YUV422 0x06
|
||||
|
||||
//0x02
|
||||
//video output format
|
||||
#define RGB444 0x00
|
||||
#define YUV444 0x01
|
||||
#define YUV422 0x02
|
||||
|
||||
//DATA WIDTH
|
||||
#define DATA_12BIT 0X00
|
||||
#define DATA_10BIT 0X01
|
||||
#define DATA_8BIT 0X03
|
||||
|
||||
//0X04
|
||||
//1:after 0:not After 1st sof for external DE sample
|
||||
#define DE_AFTER_SOF 0
|
||||
#define DE_NOAFTER_SOF 1
|
||||
|
||||
#define CSC_ENABLE 0
|
||||
#define CSC_DISABLE 1
|
||||
|
||||
//0X05
|
||||
#define CLEAR_AVMUTE(x) (x)<<7
|
||||
#define SET_AVMUTE(x) (x)<<6
|
||||
#define AUDIO_MUTE(x) (x)<<1
|
||||
#define VIDEO_BLACK(x) (x)<<0 //1:black 0:normal
|
||||
|
||||
//0x08
|
||||
#define VSYNC_POL(x) (x)<<3 //0:Negative 1:Positive
|
||||
#define HSYNC_POL(x) (x)<<2 //0:Negative 1:Positive
|
||||
#define INTER_PROGRESSIVE(x) (x)<<1 //0: progressive 1:interlace
|
||||
#define VIDEO_SET_ENABLE(x) (x)<<0 //0:disable 1: enable
|
||||
|
||||
/**********CONFIG CHANGE ************/
|
||||
#define VIDEO_CHANGE 1<<0
|
||||
#define AUDIO_CHANGE 1<<1
|
||||
|
||||
#define byte u8
|
||||
|
||||
typedef struct edid_info
|
||||
{ // for storing EDID parsed data
|
||||
byte edidDataValid;
|
||||
byte VideoDescriptor[MAX_V_DESCRIPTORS]; // maximum number of video descriptors
|
||||
byte AudioDescriptor[MAX_A_DESCRIPTORS][3]; // maximum number of audio descriptors
|
||||
byte SpkrAlloc[MAX_SPEAKER_CONFIGURATIONS]; // maximum number of speaker configurations
|
||||
byte UnderScan; // "1" if DTV monitor underscans IT video formats by default
|
||||
byte BasicAudio; // Sink supports Basic Audio
|
||||
byte YCbCr_4_4_4; // Sink supports YCbCr 4:4:4
|
||||
byte YCbCr_4_2_2; // Sink supports YCbCr 4:2:2
|
||||
byte HDMI_Sink; // "1" if HDMI signature found
|
||||
byte CEC_A_B; // CEC Physical address. See HDMI 1.3 Table 8-6
|
||||
byte CEC_C_D;
|
||||
byte ColorimetrySupportFlags; // IEC 61966-2-4 colorimetry support: 1 - xvYCC601; 2 - xvYCC709
|
||||
byte MetadataProfile;
|
||||
byte _3D_Supported;
|
||||
|
||||
} EDID_INF;
|
||||
enum EDID_ErrorCodes
|
||||
{
|
||||
EDID_OK,
|
||||
EDID_INCORRECT_HEADER,
|
||||
EDID_CHECKSUM_ERROR,
|
||||
EDID_NO_861_EXTENSIONS,
|
||||
EDID_SHORT_DESCRIPTORS_OK,
|
||||
EDID_LONG_DESCRIPTORS_OK,
|
||||
EDID_EXT_TAG_ERROR,
|
||||
EDID_REV_ADDR_ERROR,
|
||||
EDID_V_DESCR_OVERFLOW,
|
||||
EDID_UNKNOWN_TAG_CODE,
|
||||
EDID_NO_DETAILED_DESCRIPTORS,
|
||||
EDID_DDC_BUS_REQ_FAILURE,
|
||||
EDID_DDC_BUS_RELEASE_FAILURE
|
||||
};
|
||||
enum PWR_MODE{
|
||||
NORMAL,
|
||||
LOWER_PWR,
|
||||
SHUTDOWN,
|
||||
};
|
||||
struct rk610_hdmi_hw_inf{
|
||||
struct i2c_client *client;
|
||||
EDID_INF *edid_inf;
|
||||
u8 video_format;
|
||||
u8 audio_fs;
|
||||
u8 config_param;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
extern int Rk610_hdmi_suspend(struct i2c_client *client);
|
||||
extern int Rk610_hdmi_resume(struct i2c_client *client);
|
||||
#endif
|
||||
extern int Rk610_hdmi_Set_Video(u8 video_format);
|
||||
extern int Rk610_hdmi_Set_Audio(u8 audio_fs);
|
||||
extern int Rk610_hdmi_Config_Done(struct i2c_client *client);
|
||||
extern void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd);
|
||||
extern int Rk610_hdmi_init(struct i2c_client *client);
|
||||
#endif
|
||||
|
|
@ -31,18 +31,24 @@ static void __hdmi_changed(struct hdmi *hdmi)
|
|||
|
||||
mutex_lock(&hdmi->lock);
|
||||
precent = hdmi->ops->hdmi_precent(hdmi);
|
||||
|
||||
if(precent && hdmi->mode == DISP_ON_LCD && hdmi->display_on){
|
||||
if(precent && (hdmi->mode == DISP_ON_LCD) && hdmi->display_on){
|
||||
if(hdmi->ops->insert(hdmi) == 0){
|
||||
hdmi->mode = DISP_ON_HDMI;
|
||||
hdmi->mode = hdmi->display_on;
|
||||
kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
else
|
||||
hdmi_dbg(hdmi->dev, "insert error\n");
|
||||
hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE);
|
||||
|
||||
}
|
||||
else if((!precent || !hdmi->display_on) && hdmi->mode == DISP_ON_HDMI){
|
||||
else if(precent &&(hdmi->mode != hdmi->display_on)&& hdmi->display_on){
|
||||
hdmi->mode = hdmi->display_on;
|
||||
hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE);
|
||||
}
|
||||
else if((!precent || !hdmi->display_on) && hdmi->mode != DISP_ON_LCD){
|
||||
if(hdmi->ops->remove(hdmi) == 0){
|
||||
hdmi->mode = DISP_ON_LCD;
|
||||
hdmi_set_backlight(HDMI_ENABLE);
|
||||
kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
else
|
||||
|
|
@ -61,7 +67,7 @@ void hdmi_suspend(struct hdmi *hdmi)
|
|||
{
|
||||
del_timer(&hdmi->timer);
|
||||
flush_delayed_work(&hdmi->work);
|
||||
if(hdmi->mode == DISP_ON_HDMI){
|
||||
if(hdmi->mode != DISP_ON_LCD){
|
||||
hdmi->ops->remove(hdmi);
|
||||
hdmi->mode = DISP_ON_LCD;
|
||||
}
|
||||
|
|
@ -93,7 +99,7 @@ static void hdmi_detect_timer(unsigned long data)
|
|||
int precent = hdmi->ops->hdmi_precent(hdmi);
|
||||
|
||||
if((precent && hdmi->mode == DISP_ON_LCD) ||
|
||||
(!precent && hdmi->mode == DISP_ON_HDMI))
|
||||
(!precent && hdmi->mode != DISP_ON_LCD))
|
||||
hdmi_changed(hdmi, 100);
|
||||
mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));
|
||||
}
|
||||
|
|
@ -189,7 +195,7 @@ int hdmi_get_scale(void)
|
|||
struct hdmi* hdmi = get_hdmi_struct(0);
|
||||
if(!hdmi)
|
||||
return 100;
|
||||
else if(hdmi->mode == DISP_ON_HDMI)
|
||||
else if(hdmi->mode != DISP_ON_LCD)
|
||||
return hdmi->scale;
|
||||
else
|
||||
return 100;
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@
|
|||
#define H_BP3 60
|
||||
#define H_VD3 720
|
||||
#define H_FP3 16
|
||||
#define V_PW3 5
|
||||
#define V_BP3 35
|
||||
#define V_PW3 6
|
||||
#define V_BP3 30
|
||||
#define V_VD3 480
|
||||
#define V_FP3 5
|
||||
#define V_FP3 9
|
||||
|
||||
/* 1080p@50Hz Timing */
|
||||
#define OUT_CLK5 148500000
|
||||
|
|
@ -67,9 +67,9 @@
|
|||
#define H_VD4 1920
|
||||
#define H_FP4 528
|
||||
#define V_PW4 5
|
||||
#define V_BP4 35
|
||||
#define V_BP4 36
|
||||
#define V_VD4 1080
|
||||
#define V_FP4 5
|
||||
#define V_FP4 4
|
||||
|
||||
/* 1080p@60Hz Timing */
|
||||
#define OUT_CLK4 148500000
|
||||
|
|
@ -78,9 +78,9 @@
|
|||
#define H_VD5 1920
|
||||
#define H_FP5 88
|
||||
#define V_PW5 5
|
||||
#define V_BP5 35
|
||||
#define V_BP5 36
|
||||
#define V_VD5 1080
|
||||
#define V_FP5 5
|
||||
#define V_FP5 4
|
||||
|
||||
|
||||
extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable );
|
||||
|
|
@ -98,6 +98,7 @@ static int anx7150_standby(u8 enable)
|
|||
|
||||
struct rk29fb_screen hdmi_info[] = {
|
||||
{
|
||||
.hdmi_resolution = HDMI_1280x720p_50Hz,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD0,
|
||||
|
|
@ -123,6 +124,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_1280x720p_50Hz
|
||||
{
|
||||
.hdmi_resolution = HDMI_1280x720p_60Hz,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD1,
|
||||
|
|
@ -148,6 +150,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_1280x720p_60Hz
|
||||
{
|
||||
.hdmi_resolution = HDMI_720x576p_50Hz_4x3,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD2,
|
||||
|
|
@ -173,6 +176,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_720x576p_50Hz_4x3
|
||||
{
|
||||
.hdmi_resolution = HDMI_720x576p_50Hz_16x9,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD2,
|
||||
|
|
@ -198,6 +202,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_720x576p_50Hz_16x9
|
||||
{
|
||||
.hdmi_resolution = HDMI_720x480p_60Hz_4x3,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD3,
|
||||
|
|
@ -223,6 +228,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_720x480p_60Hz_4x3
|
||||
{
|
||||
.hdmi_resolution = HDMI_720x480p_60Hz_16x9,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD3,
|
||||
|
|
@ -248,6 +254,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_720x480p_60Hz_16x9
|
||||
{
|
||||
.hdmi_resolution = HDMI_1920x1080p_50Hz,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD4,
|
||||
|
|
@ -260,8 +267,8 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.upper_margin = V_BP4,
|
||||
.lower_margin = V_FP4,
|
||||
.vsync_len = V_PW4,
|
||||
.pin_hsync = 0,
|
||||
.pin_vsync = 0,
|
||||
.pin_hsync = 1,
|
||||
.pin_vsync = 1,
|
||||
.pin_den = 0,
|
||||
.pin_dclk = DCLK_POL,
|
||||
.swap_rb = SWAP_RB,
|
||||
|
|
@ -273,6 +280,7 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.standby = anx7150_standby,
|
||||
}, //HDMI_1920x1080p_50Hz
|
||||
{
|
||||
.hdmi_resolution = HDMI_1920x1080p_60Hz,
|
||||
.type = OUT_TYPE,
|
||||
.face = OUT_FACE,
|
||||
.x_res = H_VD5,
|
||||
|
|
@ -285,8 +293,8 @@ struct rk29fb_screen hdmi_info[] = {
|
|||
.upper_margin = V_BP5,
|
||||
.lower_margin = V_FP5,
|
||||
.vsync_len = V_PW5,
|
||||
.pin_hsync = 0,
|
||||
.pin_vsync = 0,
|
||||
.pin_hsync = 1,
|
||||
.pin_vsync = 1,
|
||||
.pin_den = 0,
|
||||
.pin_dclk = DCLK_POL,
|
||||
.swap_rb = SWAP_RB,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
#include <linux/hdmi.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/gpio.h>
|
||||
|
|
@ -61,6 +62,9 @@
|
|||
|
||||
#include "./display/screen/screen.h"
|
||||
|
||||
#ifdef CONFIG_MFD_RK610
|
||||
#include "./display/lcd/rk610_lcd.h"
|
||||
#endif
|
||||
#define ANDROID_USE_THREE_BUFS 0 //android use three buffers to accelerate UI display in rgb plane
|
||||
#define CURSOR_BUF_SIZE 256 //RK2818 cursor need 256B buf
|
||||
int rk29_cursor_buf[CURSOR_BUF_SIZE];
|
||||
|
|
@ -232,7 +236,18 @@ struct rk29fb_inf {
|
|||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_RK29_BL
|
||||
/* drivers/video/backlight/rk29_backlight.c */
|
||||
extern void rk29_backlight_set(bool on);
|
||||
#else
|
||||
void rk29_backlight_set(bool on)
|
||||
{
|
||||
/* please add backlight switching-related code here or on your backlight driver
|
||||
parameter: on=1 ==> open spk
|
||||
on=0 ==> close spk
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
typedef enum _TRSP_MODE
|
||||
{
|
||||
TRSP_CLOSE = 0,
|
||||
|
|
@ -2922,10 +2937,13 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
|
|||
|
||||
if(inf->cur_screen->standby) inf->cur_screen->standby(1);
|
||||
// operate the display_on pin to power down the lcd
|
||||
|
||||
#ifdef CONFIG_HDMI_DUAL_DISP
|
||||
inf->panel1_info.sscreen_get(&inf->panel1_info,inf->panel2_info.hdmi_resolution);
|
||||
inf->panel1_info.sscreen_set(&inf->panel1_info,enable);
|
||||
#else
|
||||
if(enable && mach_info->io_disable)mach_info->io_disable(); //close lcd out
|
||||
else if (mach_info->io_enable)mach_info->io_enable(); //open lcd out
|
||||
|
||||
#endif
|
||||
load_screen(inf->fb0, 0);
|
||||
mcu_refresh(inf);
|
||||
|
||||
|
|
@ -2933,6 +2951,7 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
|
|||
fb0_set_par(inf->fb0);
|
||||
LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(0));
|
||||
LcdWrReg(inf, REG_CFG_DONE, 0x01);
|
||||
|
||||
rk29fb_notify(inf, enable ? RK29FB_EVENT_HDMI_ON : RK29FB_EVENT_HDMI_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3204,6 +3223,7 @@ static int __devinit rk29fb_probe (struct platform_device *pdev)
|
|||
#else
|
||||
set_lcd_info(&inf->panel1_info, mach_info->lcd_info);
|
||||
#endif
|
||||
|
||||
inf->cur_screen = &inf->panel1_info;
|
||||
screen = inf->cur_screen;
|
||||
if(SCREEN_NULL==screen->type)
|
||||
|
|
@ -3486,7 +3506,9 @@ static int __devinit rk29fb_probe (struct platform_device *pdev)
|
|||
goto release_irq;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MFD_RK610
|
||||
rk610_lcd_scaler_set_param(&inf->panel1_info,0);
|
||||
#endif
|
||||
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
|
||||
fb0_set_par(inf->fb0);
|
||||
if (fb_prepare_logo(inf->fb0, FB_ROTATE_UR)) {
|
||||
|
|
|
|||
69
include/linux/display-sys.h
Normal file
69
include/linux/display-sys.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef _LINUX_DISPLAY_RK_H
|
||||
#define _LINUX_DISPLAY_RK_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct rk_display_device;
|
||||
|
||||
enum rk_display_priority {
|
||||
DISPLAY_PRIORITY_TV = 0,
|
||||
DISPLAY_PRIORITY_YPbPr,
|
||||
DISPLAY_PRIORITY_VGA,
|
||||
DISPLAY_PRIORITY_HDMI,
|
||||
DISPLAY_PRIORITY_LCD,
|
||||
};
|
||||
|
||||
/* This structure defines all the properties of a Display. */
|
||||
struct rk_display_driver {
|
||||
void (*suspend)(struct rk_display_device *, pm_message_t state);
|
||||
void (*resume)(struct rk_display_device *);
|
||||
int (*probe)(struct rk_display_device *, void *);
|
||||
int (*remove)(struct rk_display_device *);
|
||||
};
|
||||
|
||||
struct rk_display_ops {
|
||||
int (*setenable)(struct rk_display_device *, int enable);
|
||||
int (*getenable)(struct rk_display_device *);
|
||||
int (*getstatus)(struct rk_display_device *);
|
||||
int (*getmodelist)(struct rk_display_device *, struct list_head **modelist);
|
||||
int (*setmode)(struct rk_display_device *, struct fb_videomode *mode);
|
||||
int (*getmode)(struct rk_display_device *, struct fb_videomode *mode);
|
||||
};
|
||||
|
||||
struct rk_display_device {
|
||||
struct module *owner; /* Owner module */
|
||||
struct rk_display_driver *driver;
|
||||
struct device *parent; /* This is the parent */
|
||||
struct device *dev; /* This is this display device */
|
||||
struct mutex lock;
|
||||
void *priv_data;
|
||||
char type[16];
|
||||
char *name;
|
||||
int idx;
|
||||
struct rk_display_ops *ops;
|
||||
int priority;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct rk_display_devicelist {
|
||||
struct list_head list;
|
||||
struct rk_display_device *dev;
|
||||
};
|
||||
|
||||
extern struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver,
|
||||
struct device *dev, void *devdata);
|
||||
extern void rk_display_device_unregister(struct rk_display_device *dev);
|
||||
|
||||
extern void rk_display_device_enable(struct rk_display_device *ddev);
|
||||
|
||||
extern void rk_display_device_enable_other(struct rk_display_device *ddev);
|
||||
extern void rk_display_device_disable_other(struct rk_display_device *ddev);
|
||||
|
||||
|
||||
extern void rk_display_device_select(int priority);
|
||||
|
||||
#define to_rk_display_device(obj) container_of(obj, struct rk_display_device, class_dev)
|
||||
|
||||
#endif
|
||||
|
|
@ -62,7 +62,7 @@ typedef int BOOL;
|
|||
#define HDMI_720x480p_60Hz_16x9 7
|
||||
|
||||
/* HDMI default resolution */
|
||||
#define HDMI_DEFAULT_RESOLUTION HDMI_1920x1080p_50Hz
|
||||
#define HDMI_DEFAULT_RESOLUTION HDMI_1920x1080p_50Hz
|
||||
/* I2S Fs */
|
||||
#define HDMI_I2S_Fs_44100 0
|
||||
#define HDMI_I2S_Fs_48000 2
|
||||
|
|
|
|||
142
include/linux/mfd/rk610_core.h
Normal file
142
include/linux/mfd/rk610_core.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#ifndef __RK610_CONTROL_H_
|
||||
#define __RK610_CONTROL_H_
|
||||
|
||||
#define INVALID_GPIO -1
|
||||
#define RK610_DEBUG 1
|
||||
|
||||
#if RK610_DEBUG
|
||||
#define RK610_DBG(dev, format, arg...) \
|
||||
do{\
|
||||
dev_printk(KERN_INFO , dev , format , ## arg);\
|
||||
}while(0)
|
||||
#else
|
||||
#define RK610_DBG(dev, format, arg...)
|
||||
#endif
|
||||
#define RK610_ERR(dev, format, arg...) \
|
||||
do{\
|
||||
dev_printk(KERN_ERR , dev , format , ## arg);\
|
||||
}while(0)
|
||||
|
||||
#define RK610_CONTROL_REG_C_PLL_CON0 0x00
|
||||
#define RK610_CONTROL_REG_C_PLL_CON1 0x01
|
||||
#define RK610_CONTROL_REG_C_PLL_CON2 0x02
|
||||
#define RK610_CONTROL_REG_C_PLL_CON3 0x03
|
||||
#define RK610_CONTROL_REG_C_PLL_CON4 0x04
|
||||
#define RK610_CONTROL_REG_C_PLL_CON5 0x05
|
||||
#define C_PLL_DISABLE_FRAC 1 << 0
|
||||
#define C_PLL_BYPSS_ENABLE 1 << 1
|
||||
#define C_PLL_POWER_ON 1 << 2
|
||||
#define C_PLL_LOCLED 1 << 7
|
||||
|
||||
#define RK610_CONTROL_REG_TVE_CON 0x29
|
||||
#define TVE_CONTROL_VDAC_R_BYPASS_ENABLE 1 << 7
|
||||
#define TVE_CONTROL_VDAC_R_BYPASS_DISABLE 0 << 7
|
||||
#define TVE_CONTROL_CVBS_3_CHANNEL_ENALBE 1 << 6
|
||||
#define TVE_CONTROL_CVBS_3_CHANNEL_DISALBE 0 << 5
|
||||
enum {
|
||||
INPUT_DATA_FORMAT_RGB888 = 0,
|
||||
INPUT_DATA_FORMAT_RGB666,
|
||||
INPUT_DATA_FORMAT_RGB565,
|
||||
INPUT_DATA_FORMAT_YUV
|
||||
};
|
||||
#define RGB2CCIR_INPUT_DATA_FORMAT(n) n << 4
|
||||
|
||||
#define RGB2CCIR_RGB_SWAP_ENABLE 1 << 3
|
||||
#define RGB2CCIR_RGB_SWAP_DISABLE 0 << 3
|
||||
|
||||
#define RGB2CCIR_INPUT_INTERLACE 1 << 2
|
||||
#define RGB2CCIR_INPUT_PROGRESSIVE 0 << 2
|
||||
|
||||
#define RGB2CCIR_CVBS_PAL 0 << 1
|
||||
#define RGB2CCIR_CVBS_NTSC 1 << 1
|
||||
|
||||
#define RGB2CCIR_DISABLE 0
|
||||
#define RGB2CCIR_ENABLE 1
|
||||
|
||||
#define RK610_CONTROL_REG_CCIR_RESET 0x2a
|
||||
|
||||
#define RK610_CONTROL_REG_CLOCK_CON0 0x2b
|
||||
#define RK610_CONTROL_REG_CLOCK_CON1 0x2c
|
||||
#define CLOCK_CON1_I2S_CLK_CODEC_PLL 1 << 5
|
||||
#define CLOCK_CON1_I2S_DVIDER_MASK 0x1F
|
||||
#define RK610_CONTROL_REG_CODEC_CON 0x2d
|
||||
#define CODEC_CON_BIT_HDMI_BLCK_INTERANL 1<<4
|
||||
#define CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE 1<<3
|
||||
#define CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE 1<<2
|
||||
#define CODEC_CON_BIT_INTERAL_CODEC_DISABLE 1<<0
|
||||
|
||||
#define RK610_CONTROL_REG_I2C_CON 0x2e
|
||||
|
||||
/********************************************************************
|
||||
** ½á¹¹¶¨Òå *
|
||||
********************************************************************/
|
||||
/* RK610µÄ¼Ä´æÆ÷½á¹¹ */
|
||||
/* CODEC PLL REG */
|
||||
#define C_PLL_CON0 0x00
|
||||
#define C_PLL_CON1 0x01
|
||||
#define C_PLL_CON2 0x02
|
||||
#define C_PLL_CON3 0x03
|
||||
#define C_PLL_CON4 0x04
|
||||
#define C_PLL_CON5 0x05
|
||||
|
||||
/* SCALER PLL REG */
|
||||
#define S_PLL_CON0 0x06
|
||||
#define S_PLL_CON1 0x07
|
||||
#define S_PLL_CON2 0x08
|
||||
|
||||
/* LVDS REG */
|
||||
#define LVDS_CON0 0x09
|
||||
#define LVDS_CON1 0x0a
|
||||
|
||||
/* LCD1 REG */
|
||||
#define LCD1_CON 0x0b
|
||||
|
||||
/* SCALER REG */
|
||||
#define SCL_CON0 0x0c
|
||||
#define SCL_CON1 0x0d
|
||||
#define SCL_CON2 0x0e
|
||||
#define SCL_CON3 0x0f
|
||||
#define SCL_CON4 0x10
|
||||
#define SCL_CON5 0x11
|
||||
#define SCL_CON6 0x12
|
||||
#define SCL_CON7 0x13
|
||||
#define SCL_CON8 0x14
|
||||
#define SCL_CON9 0x15
|
||||
#define SCL_CON10 0x16
|
||||
#define SCL_CON11 0x17
|
||||
#define SCL_CON12 0x18
|
||||
#define SCL_CON13 0x19
|
||||
#define SCL_CON14 0x1a
|
||||
#define SCL_CON15 0x1b
|
||||
#define SCL_CON16 0x1c
|
||||
#define SCL_CON17 0x1d
|
||||
#define SCL_CON18 0x1e
|
||||
#define SCL_CON19 0x1f
|
||||
#define SCL_CON20 0x20
|
||||
#define SCL_CON21 0x21
|
||||
#define SCL_CON22 0x22
|
||||
#define SCL_CON23 0x23
|
||||
#define SCL_CON24 0x24
|
||||
#define SCL_CON25 0x25
|
||||
#define SCL_CON26 0x26
|
||||
#define SCL_CON27 0x27
|
||||
#define SCL_CON28 0x28
|
||||
|
||||
/* TVE REG */
|
||||
#define TVE_CON 0x29
|
||||
|
||||
/* CCIR REG */
|
||||
#define CCIR_RESET 0X2a
|
||||
|
||||
/* CLOCK REG */
|
||||
#define CLOCK_CON0 0X2b
|
||||
#define CLOCK_CON1 0X2c
|
||||
|
||||
/* CODEC REG */
|
||||
#define CODEC_CON 0x2e
|
||||
#define I2C_CON 0x2f
|
||||
|
||||
|
||||
extern int rk610_control_send_byte(const char reg, const char data);
|
||||
|
||||
#endif /*end of __RK610_CONTROL_H_*/
|
||||
|
|
@ -78,6 +78,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_RT5621 if I2C
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5625 if I2C
|
||||
select SND_SOC_RK610 if I2C
|
||||
select SND_SOC_WM8903 if I2C
|
||||
select SND_SOC_WM8904 if I2C
|
||||
select SND_SOC_WM8915 if I2C
|
||||
|
|
@ -395,6 +396,10 @@ config SND_SOC_RK1000
|
|||
tristate
|
||||
# depends on RK1000_CONTROL
|
||||
|
||||
config SND_SOC_RK610
|
||||
tristate
|
||||
depends on MFD_RK610
|
||||
|
||||
# Amp
|
||||
config SND_SOC_LM4857
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ snd-soc-wm9713-objs := wm9713.o
|
|||
snd-soc-wm-hubs-objs := wm_hubs.o
|
||||
snd-soc-rk1000-objs := rk1000_codec.o
|
||||
snd-soc-jz4740-codec-objs := jz4740.o
|
||||
snd-soc-rk610-objs := rk610_codec.o
|
||||
|
||||
# Amp
|
||||
snd-soc-lm4857-objs := lm4857.o
|
||||
|
|
@ -184,7 +185,7 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
|
|||
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
|
||||
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
|
||||
obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_RK610) += snd-soc-rk610.o
|
||||
# Amp
|
||||
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
|
||||
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
|
||||
|
|
|
|||
1137
sound/soc/codecs/rk610_codec.c
Normal file
1137
sound/soc/codecs/rk610_codec.c
Normal file
File diff suppressed because it is too large
Load Diff
267
sound/soc/codecs/rk610_codec.h
Normal file
267
sound/soc/codecs/rk610_codec.h
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2009 rockchip lhh
|
||||
*
|
||||
* Based on WM8750.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _RK610_CODEC_H
|
||||
#define _RK610_CODEC_H
|
||||
|
||||
/* RK610 register space */
|
||||
|
||||
#define ACCELCODEC_R00 0x00 //ADC High Pass Filter / DSM
|
||||
#define ACCELCODEC_R01 0x01 //DITHER power
|
||||
#define ACCELCODEC_R02 0x02 //DITHER power
|
||||
#define ACCELCODEC_R03 0x03 //DITHER power
|
||||
#define ACCELCODEC_R04 0x04 //Soft mute / sidetone gain control
|
||||
#define ACCELCODEC_R05 0x05 //Right interpolate filter volume control (MSB)
|
||||
#define ACCELCODEC_R06 0x06 //Right interpolate filter volume control (LSB)
|
||||
#define ACCELCODEC_R07 0x07 //Left interpolate filter volume control (MSB)
|
||||
#define ACCELCODEC_R08 0x08 //Left interpolate filter volume control (LSB)
|
||||
#define ACCELCODEC_R09 0x09 //Audio interface control
|
||||
#define ACCELCODEC_R0A 0x0A //Sample Rate / CLK control
|
||||
#define ACCELCODEC_R0B 0x0B //Decimation filter / Interpolate filter enable
|
||||
#define ACCELCODEC_R0C 0x0C //LIN volume
|
||||
#define ACCELCODEC_R0D 0x0D //LIP volume
|
||||
#define ACCELCODEC_R0E 0x0E //AL volume
|
||||
//#define ACCELCODEC_R0F 0x0F //RIN volume
|
||||
//#define ACCELCODEC_R10 0x10 //RIP volume
|
||||
//#define ACCELCODEC_R11 0x11 //AR volume
|
||||
#define ACCELCODEC_R12 0x12 //Input volume
|
||||
#define ACCELCODEC_R13 0x13 //Left out mix
|
||||
#define ACCELCODEC_R14 0x14 //Right out mix
|
||||
#define ACCELCODEC_R15 0x15 //LPF out mix / SCF
|
||||
#define ACCELCODEC_R16 0x16 //SCF control
|
||||
#define ACCELCODEC_R17 0x17 //LOUT (AOL) volume
|
||||
#define ACCELCODEC_R18 0x18 //ROUT (AOR) volume
|
||||
#define ACCELCODEC_R19 0x19 //MONOOUT (AOM) volume
|
||||
#define ACCELCODEC_R1A 0x1A //MONOOUT / Reference control
|
||||
#define ACCELCODEC_R1B 0x1B //Bias Current control
|
||||
#define ACCELCODEC_R1C 0x1C //ADC control
|
||||
#define ACCELCODEC_R1D 0x1D //Power Mrg 1
|
||||
#define ACCELCODEC_R1E 0x1E //Power Mrg 2
|
||||
#define ACCELCODEC_R1F 0x1F //Power Mrg 3
|
||||
|
||||
#define RK610_CACHE_REGNUM 0x1F
|
||||
|
||||
//ACCELCODEC_R00
|
||||
#define ASC_HPF_ENABLE (0x1) //high_pass filter
|
||||
#define ASC_HPF_DISABLE (0x0)
|
||||
|
||||
#define ASC_DSM_MODE_ENABLE (0x1 << 1)
|
||||
#define ASC_DSM_MODE_DISABLE (0x0 << 1)
|
||||
|
||||
#define ASC_SCRAMBLE_ENABLE (0x1 << 2)
|
||||
#define ASC_SCRAMBLE_DISABLE (0x0 << 2)
|
||||
|
||||
#define ASC_DITHER_ENABLE (0x1 << 3)
|
||||
#define ASC_DITHER_DISABLE (0x0 << 3)
|
||||
|
||||
#define ASC_BCLKDIV_4 (0x1 << 4)
|
||||
#define ASC_BCLKDIV_8 (0x2 << 4)
|
||||
#define ASC_BCLKDIV_16 (0x3 << 4)
|
||||
|
||||
//ACCECODEC_R04
|
||||
#define ASC_INT_MUTE_L (0x1)
|
||||
#define ASC_INT_ACTIVE_L (0x0)
|
||||
#define ASC_INT_MUTE_R (0x1 << 1)
|
||||
#define ASC_INT_ACTIVE_R (0x0 << 1)
|
||||
|
||||
#define ASC_SIDETONE_L_OFF (0x0 << 2)
|
||||
#define ASC_SIDETONE_L_GAIN_MAX (0x1 << 2)
|
||||
#define ASC_SIDETONE_R_OFF (0x0 << 5)
|
||||
#define ASC_SIDETONE_R_GAIN_MAX (0x1 << 5)
|
||||
|
||||
|
||||
//ACCELCODEC_R05
|
||||
#define ASC_INT_VOL_0DB (0x0)
|
||||
|
||||
|
||||
//ACCELCODEC_R09
|
||||
#define ASC_DSP_MODE (0x3)
|
||||
#define ASC_I2S_MODE (0x2)
|
||||
#define ASC_LEFT_MODE (0x1)
|
||||
//#define ASC_RIGHT_MODE (0x0)
|
||||
|
||||
#define ASC_32BIT_MODE (0x3 << 2)
|
||||
#define ASC_24BIT_MODE (0x2 << 2)
|
||||
#define ASC_20BIT_MODE (0x1 << 2)
|
||||
#define ASC_16BIT_MODE (0x0 << 2)
|
||||
|
||||
#define ASC_INVERT_LRCLK (0x1 << 4)
|
||||
#define ASC_NORMAL_LRCLK (0x0 << 4)
|
||||
|
||||
#define ASC_LRSWAP_ENABLE (0x1 << 5)
|
||||
#define ASC_LRSWAP_DISABLE (0x0 << 5)
|
||||
|
||||
#define ASC_MASTER_MODE (0x1 << 6)
|
||||
#define ASC_SLAVE_MODE (0x0 << 6)
|
||||
|
||||
#define ASC_INVERT_BCLK (0x1 << 7)
|
||||
#define ASC_NORMAL_BCLK (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R0A
|
||||
#define ASC_USB_MODE (0x1)
|
||||
#define ASC_NORMAL_MODE (0x0)
|
||||
|
||||
#define FREQ96kHz (0x0e << 1)
|
||||
#define FREQ48kHz (0x00 << 1)
|
||||
#define FREQ441kHz (0x11 << 1)
|
||||
#define FREQ32kHz (0x0c << 1)
|
||||
#define FREQ24kHz (0x1c << 1)
|
||||
#define FREQ2205kHz (0x1B << 1)
|
||||
#define FREQ16kHz (0x0a << 1)
|
||||
#define FREQ12kHz (0x08 << 1)
|
||||
#define FREQ11025kHz (0x19 << 1)
|
||||
//#define FREQ9k6Hz 0x09
|
||||
#define FREQ8kHz (0x06<<1)
|
||||
|
||||
#define ASC_CLKDIV2 (0x1 << 6)
|
||||
#define ASC_CLKNODIV (0x0 << 6)
|
||||
|
||||
#define ASC_CLK_ENABLE (0x1 << 7)
|
||||
#define ASC_CLK_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R0B
|
||||
#define ASC_DEC_ENABLE (0x1) //decimation filter enable
|
||||
#define ASC_DEC_DISABLE (0x0)
|
||||
#define ASC_INT_ENABLE (0x1 << 1) //interpolate filter enable
|
||||
#define ASC_INT_DISABLE (0x0 << 1)
|
||||
|
||||
//Input
|
||||
#define ASC_INPUT_MUTE (0x1 << 7)
|
||||
#define ASC_INPUT_ACTIVE (0x0 << 7)
|
||||
#define ASC_INPUT_VOL_0DB (0x0)
|
||||
|
||||
//ACCELCODEC_R12
|
||||
#define ASC_LINE_INPUT (0)
|
||||
#define ASC_MIC_INPUT (1 << 7)
|
||||
|
||||
#define ASC_MIC_BOOST_0DB (0)
|
||||
#define ASC_MIC_BOOST_20DB (1 << 5)
|
||||
|
||||
//ACCELCODEC_R13
|
||||
#define ASC_LPGAMXVOL_0DB (0x5)
|
||||
#define ASC_LPGAMX_ENABLE (0x1 << 3) //the left channel PGA output is directly fed into the left mixer
|
||||
#define ASC_LPGAMX_DISABLE (0x0 << 3)
|
||||
#define ASC_ALMXVOL_0DB (0x5 << 4)
|
||||
#define ASC_ALMX_ENABLE (0x1 << 7) //the left second line input is directly fed into the left mixer
|
||||
#define ASC_ALMX_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R14
|
||||
#define ASC_RPGAMXVOL_0DB (0x5)
|
||||
#define ASC_RPGAMX_ENABLE (0x1 << 3) //the right channel PGA output is directly fed into the right mixer
|
||||
#define ASC_RPGAMX_DISABLE (0x0 << 3)
|
||||
#define ASC_ARMXVOL_0DB (0x5 << 4)
|
||||
#define ASC_ARMX_ENABLE (0x1 << 7) //)the right second line input is directly fed into the right mixer
|
||||
#define ASC_ARMX_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R15
|
||||
#define ASC_LDAMX_ENABLE (0x1 << 2) //the left differential signal from DAC is directly fed into the left mixer
|
||||
#define ASC_LDAMX_DISABLE (0x0 << 2)
|
||||
#define ASC_RDAMX_ENABLE (0x1 << 3) //the right differential signal from DAC is directly fed into the right mixer
|
||||
#define ASC_RDAMX_DISABLE (0x0 << 3)
|
||||
#define ASC_LSCF_MUTE (0x1 << 4) //the left channel LPF is mute
|
||||
#define ASC_LSCF_ACTIVE (0x0 << 4)
|
||||
#define ASC_RSCF_MUTE (0x1 << 5) //the right channel LPF is mute
|
||||
#define ASC_RSCF_ACTIVE (0x0 << 5)
|
||||
#define ASC_LLPFMX_ENABLE (0x1 << 6) //the left channel LPF output is fed into the left into the mixer
|
||||
#define ASC_LLPFMX_DISABLE (0x0 << 6)
|
||||
#define ASC_RLPFMX_ENABLE (0x1 << 7) //the right channel LPF output is fed into the right into the mixer.
|
||||
#define ASC_RLPFMX_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R17/R18
|
||||
#define ASC_OUTPUT_MUTE (0x1 << 6)
|
||||
#define ASC_OUTPUT_ACTIVE (0x0 << 6)
|
||||
#define ASC_CROSSZERO_EN (0x1 << 7)
|
||||
#define ASC_OUTPUT_VOL_0DB (0x0F)
|
||||
//ACCELCODEC_R19
|
||||
#define ASC_MONO_OUTPUT_MUTE (0x1 << 7)
|
||||
#define ASC_MONO_OUTPUT_ACTIVE (0x0 << 7)
|
||||
#define ASC_MONO_CROSSZERO_EN (0x1 << 6)
|
||||
|
||||
//ACCELCODEC_R1A
|
||||
#define ASC_VMDSCL_SLOWEST (0x0 << 2)
|
||||
#define ASC_VMDSCL_SLOW (0x1 << 2)
|
||||
#define ASC_VMDSCL_FAST (0x2 << 2)
|
||||
#define ASC_VMDSCL_FASTEST (0x3 << 2)
|
||||
|
||||
#define ASC_MICBIAS_09 (0x1 << 4)
|
||||
#define ASC_MICBIAS_06 (0x0 << 4)
|
||||
|
||||
#define ASC_L2M_ENABLE (0x1 << 5) //the right channel LPF output is fed to mono PA
|
||||
#define ASC_L2M_DISABLE (0x0 << 5)
|
||||
#define ASC_R2M_ENABLE (0x1 << 6) //the left channel LPF output is fed to mono PA
|
||||
#define ASC_R2M_DISABLE (0x0 << 6)
|
||||
#define ASC_CAPLESS_ENABLE (0x1 << 7) //the capless connection is enable
|
||||
#define ASC_CAPLESS_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R1C
|
||||
#define ASC_DITH_0_DIV (0x0 << 3) //the amplitude setting of the ASDM dither(div=vdd/48)
|
||||
#define ASC_DITH_2_DIV (0x1 << 3)
|
||||
#define ASC_DITH_4_DIV (0x2 << 3)
|
||||
#define ASC_DITH_8_DIV (0x3 << 3)
|
||||
|
||||
#define ASC_DITH_ENABLE (0x1 << 5) //the ASDM dither is enabled
|
||||
#define ASC_DITH_DISABLE (0x0 << 5)
|
||||
|
||||
#define ASC_DEM_ENABLE (0x1 << 7) //the ASDM DEM is enabled
|
||||
#define ASC_DEM_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R1D
|
||||
#define ASC_PDVMID_ENABLE (0x1) //the VMID reference is powered down. VMID is connected to GND
|
||||
#define ASC_PDVMID_DISABLE (0x0)
|
||||
#define ASC_PDSDL_ENABLE (0x1 << 2) //the PGA S2D buffer is power down
|
||||
#define ASC_PDSDL_DISABLE (0x0 << 2)
|
||||
#define ASC_PDBSTL_ENABLE (0x1 << 4) //the micphone input Op-Amp is power down
|
||||
#define ASC_PDBSTL_DISABLE (0x0 << 4)
|
||||
#define ASC_PDPGAL_ENABLE (0x1 << 6) //the PGA is power down
|
||||
#define ASC_PDPGAL_DISABLE (0x0 << 6)
|
||||
#define ASC_PDREF_ENABLE (0x1 << 7) //reference generator is power down
|
||||
#define ASC_PDREF_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R1E
|
||||
#define ASC_PDPAR_ENABLE (0x1) //the right channel PA is power down
|
||||
#define ASC_PDPAR_DISABLE (0x0)
|
||||
#define ASC_PDPAL_ENABLE (0x1 << 1) //the left channel power amplifier is power down
|
||||
#define ASC_PDPAL_DISABLE (0x0 << 1)
|
||||
#define ASC_PDMIXR_ENABLE (0x1 << 2) //the right mixer is power down
|
||||
#define ASC_PDMIXR_DISABLE (0x0 << 2)
|
||||
#define ASC_PDMIXL_ENABLE (0x1 << 3) //the left mixer is power down
|
||||
#define ASC_PDMIXL_DISABLE (0x0 << 3)
|
||||
#define ASC_PDLPFR_ENABLE (0x1 << 4) //the right RC LPF is power down
|
||||
#define ASC_PDLPFR_DISABLE (0x0 << 4)
|
||||
#define ASC_PDLPFL_ENABLE (0x1 << 5) //the left channel RC LPF is power down
|
||||
#define ASC_PDLPFL_DISABLE (0x0 << 5)
|
||||
#define ASC_PDASDML_ENABLE (0x1 << 7) //the ASDM is power down
|
||||
#define ASC_PDASDML_DISABLE (0x0 << 7)
|
||||
|
||||
//ACCELCODEC_R1F
|
||||
#define ASC_PDSCFR_ENABLE (0x1 << 1) //the right channel DAC is power down
|
||||
#define ASC_PDSCFR_DISABLE (0x0 << 1)
|
||||
#define ASC_PDSCFL_ENABLE (0x1 << 2) //the left channel DAC is power down
|
||||
#define ASC_PDSCFL_DISABLE (0x0 << 2)
|
||||
#define ASC_PDMICB_ENABLE (0x1 << 4) //the micbias is power down
|
||||
#define ASC_PDMICB_DISABLE (0x0 << 4)
|
||||
#define ASC_PDIB_ENABLE (0x1 << 5) //the left channel LPF is power down
|
||||
#define ASC_PDIB_DISABLE (0x0 << 5)
|
||||
#define ASC_PDMIXM_ENABLE (0x1 << 6) //the mon mixer is power down
|
||||
#define ASC_PDMIXM_DISABLE (0x0 << 6)
|
||||
#define ASC_PDPAM_ENABLE (0x1 << 7) //the mono PA is power down.
|
||||
#define ASC_PDPAM_DISABLE (0x0 << 7)
|
||||
|
||||
#define LINE_2_MIXER_GAIN (0x5) //left and right PA gain
|
||||
#define RK610_CODEC_NUM_REG 0x20
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
|
||||
extern struct snd_soc_dai rk610_codec_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_rk610_codec;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -42,6 +42,12 @@ choice
|
|||
endchoice
|
||||
endif
|
||||
|
||||
config SND_RK29_SOC_SPDIF
|
||||
bool "Soc RK29 SPDIF support"
|
||||
depends on SND_RK29_SOC
|
||||
depends on SND_RK29_SOC_I2S
|
||||
help
|
||||
This supports the use of SPDIF interface on rk29 processors
|
||||
config SND_RK29_SOC_WM8988
|
||||
tristate "SoC I2S Audio support for rockchip - WM8988"
|
||||
depends on SND_RK29_SOC
|
||||
|
|
@ -136,8 +142,23 @@ config SND_RK29_SOC_RK1000
|
|||
help
|
||||
Say Y if you want to add support for SoC audio on rockchip
|
||||
with the RK1000.
|
||||
config SND_RK29_SOC_HDMI
|
||||
tristate "SoC I2S Audio support for rockchip - HDMI"
|
||||
depends on SND_RK29_SOC && HDMI_ITV
|
||||
select SND_RK29_SOC_I2S
|
||||
help
|
||||
Say Y if you want to add support for SoC audio on rockchip
|
||||
with the HDMI.
|
||||
config SND_RK29_SOC_RK610
|
||||
tristate "SoC I2S Audio support for rockchip - RK610"
|
||||
depends on SND_RK29_SOC && MFD_RK610 && I2C_RK29
|
||||
select SND_RK29_SOC_I2S
|
||||
select SND_SOC_RK610
|
||||
help
|
||||
Say Y if you want to add support for SoC audio on rockchip
|
||||
with the RK610(JETTA).
|
||||
|
||||
if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_RT5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 || SND_RK29_SOC_AIC3111
|
||||
if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_RT5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 || SND_RK29_SOC_AIC3111 || SND_RK29_SOC_HDMI || SND_RK29_SOC_RK610
|
||||
choice
|
||||
bool "Set i2s type"
|
||||
default SND_RK29_CODEC_SOC_SLAVE
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ endif
|
|||
ifdef CONFIG_ARCH_RK30
|
||||
snd-soc-rockchip-i2s-objs := rk30_i2s.o
|
||||
endif
|
||||
snd-soc-rockchip-spdif-objs := rk29_spdif.o
|
||||
|
||||
obj-$(CONFIG_SND_RK29_SOC) += snd-soc-rockchip.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_SPDIF) += snd-soc-rockchip-spdif.o
|
||||
|
||||
# ROCKCHIP Machine Support
|
||||
snd-soc-wm8900-objs := rk29_wm8900.o
|
||||
|
|
@ -20,6 +22,8 @@ snd-soc-aic3111-objs := rk29_aic3111.o
|
|||
snd-soc-wm8988-objs := rk29_wm8988.o
|
||||
snd-soc-rk1000-objs := rk29_rk1000codec.o
|
||||
snd-soc-wm8994-objs := rk29_wm8994.o
|
||||
snd-soc-hdmi-objs := rk29_hdmi.o
|
||||
snd-soc-rk610-objs := rk29_jetta_codec.o
|
||||
|
||||
obj-$(CONFIG_SND_RK29_SOC_WM8994) += snd-soc-wm8994.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o
|
||||
|
|
@ -30,3 +34,5 @@ obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o
|
|||
obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_CS42L52) += snd-soc-cs42l52.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_AIC3111) += snd-soc-aic3111.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_HDMI) += snd-soc-hdmi.o
|
||||
obj-$(CONFIG_SND_RK29_SOC_RK610) += snd-soc-rk610.o
|
||||
280
sound/soc/rk29/rk29_jetta_codec.c
Normal file
280
sound/soc/rk29/rk29_jetta_codec.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* rk29_wm8988.c -- SoC audio for rockchip
|
||||
*
|
||||
* Driver for rockchip wm8988 audio
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include "../codecs/rk610_codec.h"
|
||||
#include "rk29_pcm.h"
|
||||
#include "rk29_i2s.h"
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(KERN_ERR x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
static int rk29_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
#else
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
#endif
|
||||
int ret;
|
||||
unsigned int pll_out = 0;
|
||||
int div_bclk,div_mclk;
|
||||
// struct clk *general_pll;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
/*by Vincent Hsiung for EQ Vol Change*/
|
||||
#define HW_PARAMS_FLAG_EQVOL_ON 0x21
|
||||
#define HW_PARAMS_FLAG_EQVOL_OFF 0x22
|
||||
if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
|
||||
#else
|
||||
ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent
|
||||
#endif
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set codec DAI configuration */
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#else
|
||||
ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#endif
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
|
||||
#else
|
||||
ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
|
||||
#endif
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* set cpu DAI configuration */
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
|
||||
#else
|
||||
ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
|
||||
#endif
|
||||
#endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#else
|
||||
ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
|
||||
#endif
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch(params_rate(params)) {
|
||||
case 8000:
|
||||
case 16000:
|
||||
case 24000:
|
||||
case 32000:
|
||||
case 48000:
|
||||
case 96000:
|
||||
pll_out = 12288000;
|
||||
break;
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 88200:
|
||||
pll_out = 11289600;
|
||||
break;
|
||||
case 176400:
|
||||
pll_out = 11289600*2;
|
||||
break;
|
||||
case 192000:
|
||||
pll_out = 12288000*2;
|
||||
break;
|
||||
default:
|
||||
DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
|
||||
snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);
|
||||
|
||||
// #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
|
||||
// snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
|
||||
// #endif
|
||||
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
|
||||
div_bclk = 63;
|
||||
div_mclk = pll_out/(params_rate(params)*64) - 1;
|
||||
|
||||
DBG("func is%s,pll_out=%ld,div_mclk=%ld div_bclk=%ld\n",
|
||||
__FUNCTION__,pll_out,div_mclk, div_bclk);
|
||||
snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
|
||||
snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
|
||||
snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
|
||||
// DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_LINE("Audio Out", NULL),
|
||||
SND_SOC_DAPM_LINE("Line in", NULL),
|
||||
SND_SOC_DAPM_MIC("Micn", NULL),
|
||||
SND_SOC_DAPM_MIC("Micp", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route audio_map[]= {
|
||||
|
||||
{"Audio Out", NULL, "LOUT1"},
|
||||
{"Audio Out", NULL, "ROUT1"},
|
||||
{"Line in", NULL, "RINPUT1"},
|
||||
{"Line in", NULL, "LINPUT1"},
|
||||
// {"Micn", NULL, "RINPUT2"},
|
||||
// {"Micp", NULL, "LINPUT2"},
|
||||
};
|
||||
|
||||
/*
|
||||
* Logic for a RK610 codec as connected on a rockchip board.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
static int rk29_RK610_codec_init(struct snd_soc_pcm_runtime *rtd) {
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
/* Add specific widgets */
|
||||
snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets,
|
||||
ARRAY_SIZE(rk29_dapm_widgets));
|
||||
|
||||
/* Set up specific audio path audio_mapnects */
|
||||
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
|
||||
snd_soc_dapm_sync(dapm);
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int rk29_RK610_codec_init(struct snd_soc_codec *codec) {
|
||||
// struct snd_soc_dai *codec_dai = &codec->dai[0];
|
||||
int ret;
|
||||
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
// ret = snd_soc_dai_set_sysclk(codec_dai, 0,
|
||||
// 11289600, SND_SOC_CLOCK_IN);
|
||||
// if (ret < 0) {
|
||||
// printk(KERN_ERR "Failed to set WM8988 SYSCLK: %d\n", ret);
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
/* Add specific widgets */
|
||||
snd_soc_dapm_new_controls(codec, rk29_dapm_widgets,
|
||||
ARRAY_SIZE(rk29_dapm_widgets));
|
||||
|
||||
/* Set up specific audio path audio_mapnects */
|
||||
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
|
||||
|
||||
snd_soc_dapm_sync(codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static struct snd_soc_ops rk29_ops = {
|
||||
.hw_params = rk29_hw_params,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link rk29_dai = {
|
||||
.name = "RK610",
|
||||
.stream_name = "RK610 CODEC PCM",
|
||||
.codec_name = "RK610_CODEC.1-0060",
|
||||
.platform_name = "rockchip-audio",
|
||||
#if defined(CONFIG_SND_RK29_SOC_I2S_8CH)
|
||||
.cpu_dai_name = "rk29_i2s.0",
|
||||
#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
|
||||
.cpu_dai_name = "rk29_i2s.1",
|
||||
#endif
|
||||
.codec_dai_name = "rk610_codec_xx",
|
||||
.init = rk29_RK610_codec_init,
|
||||
.ops = &rk29_ops,
|
||||
};
|
||||
static struct snd_soc_card snd_soc_card_rk29 = {
|
||||
.name = "RK29_RK610",
|
||||
.dai_link = &rk29_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct platform_device *rk29_snd_device;
|
||||
|
||||
static int __init audio_card_init(void)
|
||||
{
|
||||
int ret =0;
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
printk(KERN_ERR "[%s] start\n", __FUNCTION__);
|
||||
rk29_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!rk29_snd_device) {
|
||||
printk("[%s] platform device allocation failed\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);
|
||||
#else
|
||||
platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata);
|
||||
rk29_snd_devdata.dev = &rk29_snd_device->dev;
|
||||
#endif
|
||||
ret = platform_device_add(rk29_snd_device);
|
||||
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
if (ret) {
|
||||
DBG("platform device add failed\n");
|
||||
platform_device_put(rk29_snd_device);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static void __exit audio_card_exit(void)
|
||||
{
|
||||
platform_device_unregister(rk29_snd_device);
|
||||
}
|
||||
|
||||
module_init(audio_card_init);
|
||||
module_exit(audio_card_exit);
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("rockchip");
|
||||
MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
Loading…
Reference in New Issue
Block a user