mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
androidcomputer: update dispaly scaler and commit tv5735 code
This commit is contained in:
parent
111efae5e7
commit
4af759ef57
|
|
@ -547,7 +547,7 @@ static int rk_fb_io_enable(void)
|
|||
|
||||
#if defined(CONFIG_LCDC1_RK3188)
|
||||
struct rk29fb_info lcdc1_screen_info = {
|
||||
.prop = EXTEND, //extend display device
|
||||
.prop = EXTEND, //extend display device
|
||||
.lcd_info = NULL,
|
||||
.set_screen_info = hdmi_init_lcdc,
|
||||
|
||||
|
|
@ -1544,7 +1544,7 @@ static struct i2c_board_info __initdata i2c0_info[] = {
|
|||
int __sramdata g_pmic_type = 0;
|
||||
#ifdef CONFIG_I2C1_RK30
|
||||
#ifdef CONFIG_REGULATOR_ACT8846
|
||||
#define PMU_POWER_SLEEP RK30_PIN0_PA1
|
||||
#define PMU_POWER_SLEEP RK30_PIN0_PD1
|
||||
#define PMU_VSEL RK30_PIN3_PD3
|
||||
#define ACT8846_HOST_IRQ RK30_PIN0_PB3
|
||||
|
||||
|
|
@ -1811,6 +1811,45 @@ static struct pmu_info tps65910_ldo_info[] = {
|
|||
#include "../mach-rk30/board-pmu-tps65910.c"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCALER_TV5735)
|
||||
struct scaler_output_port tv_oports[] ={
|
||||
{
|
||||
.led_gpio = INVALID_GPIO,
|
||||
.type = SCALER_OUT_VGA,
|
||||
},
|
||||
};
|
||||
|
||||
struct scaler_input_port tv_iports[] = {
|
||||
{//rk
|
||||
.led_gpio = RK30_PIN0_PD4,
|
||||
.type = SCALER_IN_RGB,
|
||||
},
|
||||
{//pc
|
||||
.led_gpio = RK30_PIN0_PD5,
|
||||
.type = SCALER_IN_VGA,
|
||||
}
|
||||
};
|
||||
|
||||
struct scaler_platform_data tv5735_data = {
|
||||
.func_type = SCALER_FUNC_FULL,
|
||||
|
||||
.iports = tv_iports,
|
||||
.iport_size = ARRAY_SIZE(tv_iports),
|
||||
|
||||
.oports = tv_oports,
|
||||
.oport_size = ARRAY_SIZE(tv_oports),
|
||||
|
||||
.power_gpio = RK30_PIN2_PD7,
|
||||
.power_level = GPIO_HIGH,
|
||||
.vga5v_gpio = RK30_PIN3_PD7,
|
||||
.vga5v_level = GPIO_HIGH,
|
||||
.ddc_sel_gpio = RK30_PIN0_PB4,
|
||||
.ddc_sel_level = GPIO_HIGH, //set default input port
|
||||
.vga_hsync_gpio= RK30_PIN0_PA1,
|
||||
.vga_vsync_gpio= RK30_PIN0_PA5,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCALER_TEST)
|
||||
//the fisrt port is default
|
||||
struct scaler_output_port tst_oports[] ={
|
||||
|
|
@ -1834,15 +1873,31 @@ struct scaler_input_port tst_iports[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void test_init_hw(void)
|
||||
{
|
||||
//xn223
|
||||
if (!gpio_request(RK30_PIN1_PD6, NULL))
|
||||
gpio_direction_output(RK30_PIN1_PD6, GPIO_HIGH);
|
||||
else
|
||||
printk("%s: request XNN223_PWN gpio failed\n", __func__);
|
||||
}
|
||||
|
||||
struct scaler_platform_data test_data = {
|
||||
.func_type = SCALER_FUNC_SWITCH,
|
||||
.func_type = SCALER_FUNC_SWITCH,
|
||||
|
||||
.iports = tst_iports,
|
||||
.iport_size = ARRAY_SIZE(tst_iports),
|
||||
.oports = tst_oports,
|
||||
.oport_size = ARRAY_SIZE(tst_oports),
|
||||
.iports = tst_iports,
|
||||
.iport_size = ARRAY_SIZE(tst_iports),
|
||||
.oports = tst_oports,
|
||||
.oport_size = ARRAY_SIZE(tst_oports),
|
||||
|
||||
.power_gpio = RK30_PIN2_PD7,
|
||||
.power_gpio = RK30_PIN2_PD7,
|
||||
.power_level = GPIO_HIGH,
|
||||
.vga5v_gpio = RK30_PIN3_PD7,
|
||||
.vga5v_level = GPIO_HIGH,
|
||||
.ddc_sel_gpio = RK30_PIN0_PB4,
|
||||
.ddc_sel_level = GPIO_HIGH,
|
||||
//func
|
||||
.init_hw = test_init_hw,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -1977,9 +2032,17 @@ void rk30_pwm_resume_voltage_set(void)
|
|||
|
||||
#ifdef CONFIG_I2C2_RK30
|
||||
static struct i2c_board_info __initdata i2c2_info[] = {
|
||||
#if defined(CONFIG_SCALER_DEVICE)
|
||||
#if defined(CONFIG_SCALER_TV5735)
|
||||
{
|
||||
.type = "vga_i2c",
|
||||
.type = "tv5735",
|
||||
.addr = 0x57,
|
||||
.flags = 0,
|
||||
.platform_data = &tv5735_data,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_SCALER_DEVICE_DDC)
|
||||
{
|
||||
.type = "scaler_ddc",
|
||||
.addr = 0x50,
|
||||
.flags = 0,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,5 +7,10 @@ menuconfig SCALER_DEVICE
|
|||
default n
|
||||
|
||||
if SCALER_DEVICE
|
||||
|
||||
config SCALER_DEVICE_DDC
|
||||
bool "Scaler Device Support DDC Read EDID"
|
||||
default n
|
||||
|
||||
source "drivers/misc/scaler/chips/Kconfig"
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
obj-$(CONFIG_SCALER_DEVICE) += chips/
|
||||
obj-$(CONFIG_SCALER_DEVICE) += scaler-core.o
|
||||
obj-$(CONFIG_SCALER_DEVICE) += scaler-sysfs.o
|
||||
obj-$(CONFIG_SCALER_DEVICE) += scaler-vga.o
|
||||
obj-$(CONFIG_SCALER_DEVICE_DDC) += scaler-edid.o
|
||||
|
|
|
|||
|
|
@ -2,54 +2,35 @@
|
|||
Copyright (c) 2010 by Rockchip.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#include <linux/wakelock.h>
|
||||
#endif
|
||||
#include <linux/scaler-core.h>
|
||||
|
||||
struct scaler_chip_dev *chip = NULL;
|
||||
extern char *scaler_input_name[];
|
||||
|
||||
|
||||
//enbale chip to process image
|
||||
static void set_cur_inport(void)
|
||||
{
|
||||
struct scaler_input_port *iport = NULL;
|
||||
int ddc_sel_level = -1;
|
||||
|
||||
list_for_each_entry(iport, &chip->iports, next) {
|
||||
|
||||
if (iport->id == chip->cur_inport_id) {
|
||||
if (iport->id == 1)
|
||||
ddc_sel_level = chip->pdata->ddc_sel_level;
|
||||
else
|
||||
ddc_sel_level = !chip->pdata->ddc_sel_level;
|
||||
if (chip->pdata->ddc_sel_gpio > 0)
|
||||
gpio_direction_output(chip->pdata->ddc_sel_gpio, ddc_sel_level);
|
||||
gpio_set_value(iport->led_gpio, GPIO_HIGH);
|
||||
}else {
|
||||
gpio_set_value(iport->led_gpio, GPIO_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
//pc
|
||||
if (chip->cur_inport_id == 2)
|
||||
gpio_set_value(RK30_PIN0_PB4, GPIO_LOW);
|
||||
else
|
||||
//rk
|
||||
gpio_set_value(RK30_PIN0_PB4, GPIO_HIGH);
|
||||
}
|
||||
|
||||
static int parse_cmd(unsigned int cmd, unsigned long arg)
|
||||
static int test_parse_cmd(unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
printk("test: parse scaler cmd %u\n",cmd);
|
||||
|
||||
|
|
@ -64,58 +45,51 @@ static int parse_cmd(unsigned int cmd, unsigned long arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void test_start(void)
|
||||
{
|
||||
scaler_switch_default_screen();
|
||||
}
|
||||
|
||||
static int test_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct scaler_platform_data *pdata = client->dev.platform_data;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&client->adapter->dev, "%s failed ENODEV\n\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
printk("%s: client private data not define\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scaler_init_platform(pdata);
|
||||
|
||||
chip = alloc_scaler_chip();
|
||||
if (!chip) {
|
||||
printk("%s: alloc scaler chip memory failed.\n", __func__);
|
||||
return -1;
|
||||
}else {
|
||||
chip->client = client;
|
||||
chip->pdata = pdata;
|
||||
memcpy((void *)chip->name, (void *)client->name, (strlen(client->name) + 1));
|
||||
}
|
||||
chip->client = client;
|
||||
memcpy((void *)chip->name, (void *)client->name, (strlen(client->name) + 1));
|
||||
|
||||
if (init_scaler_chip(chip, pdata) != 0)
|
||||
goto err;
|
||||
//implement parse cmd function
|
||||
init_scaler_chip(chip, pdata);
|
||||
chip->parse_cmd = parse_cmd;
|
||||
|
||||
//vga 5v en
|
||||
if (!gpio_request(RK30_PIN3_PD7, NULL))
|
||||
gpio_direction_output(RK30_PIN3_PD7, GPIO_HIGH);
|
||||
else
|
||||
printk("%s: request vga5ven power gpio failed\n", __func__);
|
||||
msleep(20);
|
||||
|
||||
//power
|
||||
if (!gpio_request(RK30_PIN2_PD7, NULL))
|
||||
gpio_direction_output(RK30_PIN2_PD7, GPIO_HIGH);
|
||||
else
|
||||
printk("%s: request vga power gpio failed\n", __func__);
|
||||
msleep(20);
|
||||
|
||||
//vga sel
|
||||
if (!gpio_request(RK30_PIN0_PB4, NULL))
|
||||
gpio_direction_output(RK30_PIN0_PB4, GPIO_HIGH); //rk output
|
||||
else
|
||||
printk("%s: request vga switch gpio failed\n", __func__);
|
||||
msleep(20);
|
||||
|
||||
//
|
||||
if (!gpio_request(RK30_PIN1_PD6, NULL))
|
||||
gpio_direction_output(RK30_PIN1_PD6, GPIO_HIGH);
|
||||
else
|
||||
printk("%s: request XNN223_PWN gpio failed\n", __func__);
|
||||
msleep(20);
|
||||
chip->parse_cmd = test_parse_cmd;
|
||||
chip->start = test_start;
|
||||
|
||||
//register
|
||||
register_scaler_chip(chip);
|
||||
if (register_scaler_chip(chip) != 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free_scaler_chip(chip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int test_i2c_remove(struct i2c_client *client)
|
||||
|
|
|
|||
325
drivers/misc/scaler/chips/tv5735.c
Normal file
325
drivers/misc/scaler/chips/tv5735.c
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
Copyright (c) 2010 by Rockchip.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/gpio.h>
|
||||
#include "tv_setting.h"
|
||||
|
||||
|
||||
#define TV_DEV_NAME "trueview"
|
||||
#define TV_I2C_RATE (400*1000)
|
||||
|
||||
static struct timer_list timer;
|
||||
static int vga_in_det = 0;
|
||||
static int vga_offset = 0;
|
||||
static struct scaler_chip_dev *chip = NULL;
|
||||
|
||||
/*** I2c operate ***/
|
||||
static int tv_select_bank(struct i2c_client *client, char bank)
|
||||
{
|
||||
u8 sel_bank = 0xf0;
|
||||
return i2c_master_reg8_send(client, sel_bank, &bank, 1, TV_I2C_RATE);
|
||||
}
|
||||
|
||||
static int tv_read_single_data(struct i2c_client *client, char reg)
|
||||
{
|
||||
int ret;
|
||||
unsigned char val;
|
||||
|
||||
ret = i2c_master_reg8_recv(client, reg, &val, 1, TV_I2C_RATE);
|
||||
if (ret != 1)
|
||||
printk("%s: read reg8 value error:%d\n", __func__, ret);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline int tv_write_single_data(struct i2c_client *client, char reg, char value)
|
||||
{
|
||||
return i2c_master_reg8_send(client, reg, &value, 1, TV_I2C_RATE);
|
||||
}
|
||||
|
||||
static void tv5735_init_reg(unsigned char *regs, int len)
|
||||
{
|
||||
int i, ret = -1;
|
||||
char reg, val;
|
||||
|
||||
if (chip == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < len; i += 2) {
|
||||
reg = regs[i + 0];
|
||||
val = regs[i + 1];
|
||||
|
||||
if (reg == 0xff && val == 0xff)
|
||||
break;
|
||||
|
||||
//ret = i2c_master_reg8_send(chip->client, reg, &val, 1, TV_I2C_RATE);
|
||||
ret = tv_write_single_data(chip->client, reg, val);
|
||||
if (ret != 1)
|
||||
printk("%s: write reg = %d failed.\n", __func__, reg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void set_cur_inport(void)
|
||||
{
|
||||
struct scaler_input_port *iport = NULL;
|
||||
int ddc_sel_level = -1;
|
||||
|
||||
list_for_each_entry(iport, &chip->iports, next) {
|
||||
if (iport->id == chip->cur_inport_id) {
|
||||
gpio_set_value(iport->led_gpio, GPIO_HIGH);
|
||||
|
||||
if (iport->id == 1)
|
||||
ddc_sel_level = chip->pdata->ddc_sel_level;
|
||||
else
|
||||
ddc_sel_level = !chip->pdata->ddc_sel_level;
|
||||
if (chip->pdata->ddc_sel_gpio > 0)
|
||||
gpio_direction_output(chip->pdata->ddc_sel_gpio, ddc_sel_level);
|
||||
|
||||
if (iport->type == SCALER_IN_RGB) {
|
||||
if (vga_in_det)
|
||||
del_timer_sync(&timer);
|
||||
tv5735_init_reg(regs[iport->type].regs, regs[iport->type].len);
|
||||
}
|
||||
if (iport->type == SCALER_IN_VGA) {
|
||||
tv5735_init_reg(vga2vga_regs[vga_offset].regs, vga2vga_regs[vga_offset].len);
|
||||
if (vga_in_det)
|
||||
add_timer(&timer);
|
||||
}
|
||||
}else {
|
||||
gpio_set_value(iport->led_gpio, GPIO_LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_cmd(unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
printk("tv5735: parse scaler cmd %u\n",cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case SCALER_IOCTL_SET_CUR_INPUT:
|
||||
set_cur_inport();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//enbale chip to process image
|
||||
static void tv5735_start(void)
|
||||
{
|
||||
scaler_switch_default_screen();
|
||||
set_cur_inport();
|
||||
//tv5735_init_reg(regs[chip->cur_in_type].regs, regs[chip->cur_in_type].len);
|
||||
}
|
||||
|
||||
static int tv_hardware_is_ok(struct i2c_client *client)
|
||||
{
|
||||
unsigned char reg_val= 0;
|
||||
unsigned chip_id = 0;
|
||||
|
||||
if (tv_select_bank(client, 0) == 1) {
|
||||
reg_val = tv_read_single_data(client, 0x0b);
|
||||
chip_id = reg_val;
|
||||
|
||||
msleep(10);
|
||||
reg_val = tv_read_single_data(client, 0x0c);
|
||||
chip_id = (chip_id << 8) | reg_val;
|
||||
|
||||
msleep(10);
|
||||
reg_val = tv_read_single_data(client, 0x0d);
|
||||
chip_id = (chip_id << 8) | reg_val;
|
||||
printk("%s: Chip Id %#x\n", client->name, chip_id);
|
||||
return 0;
|
||||
}else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/************pc v\hsync***************/
|
||||
static void timer_callbak_func(unsigned long arg)
|
||||
{
|
||||
int offset = -0, val1 = -1, val2 = -1;
|
||||
int hsync_cnt = 0, vsync_cnt = 0;
|
||||
unsigned long vtime, htime;
|
||||
struct scaler_platform_data *pdata = (struct scaler_platform_data*)arg;
|
||||
|
||||
vtime = jiffies + msecs_to_jiffies(200);
|
||||
val1 = gpio_get_value(pdata->vga_vsync_gpio);
|
||||
while (time_after(vtime, jiffies)) {
|
||||
val2 = gpio_get_value(pdata->vga_vsync_gpio);
|
||||
if (val1 != val2) {
|
||||
vsync_cnt++;
|
||||
val1 = val2;
|
||||
}
|
||||
}
|
||||
//printk("vsync cnt = %d\n", vsync_cnt);
|
||||
|
||||
htime = jiffies + msecs_to_jiffies(100);
|
||||
val1 = gpio_get_value(pdata->vga_hsync_gpio);
|
||||
while (time_after(htime, jiffies)) {
|
||||
val2 = gpio_get_value(pdata->vga_hsync_gpio);
|
||||
if (val1 != val2) {
|
||||
hsync_cnt++;
|
||||
val1 = val2;
|
||||
}
|
||||
}
|
||||
//printk("hsync cnt = %d\n", hsync_cnt);
|
||||
|
||||
//set reg
|
||||
offset = vga_offset;
|
||||
if (hsync_cnt > 10500 && hsync_cnt < 11500)
|
||||
offset = 0;
|
||||
if (hsync_cnt > 12000 && hsync_cnt < 12700)
|
||||
offset = 1;
|
||||
if (hsync_cnt > 9100 && hsync_cnt < 9600)
|
||||
offset = 2;
|
||||
|
||||
|
||||
if (offset != vga_offset) {
|
||||
vga_offset = offset;
|
||||
tv5735_init_reg(vga2vga_regs[offset].regs,
|
||||
vga2vga_regs[offset].len);
|
||||
}
|
||||
|
||||
mod_timer(&timer, (jiffies + msecs_to_jiffies(100)));
|
||||
}
|
||||
|
||||
static void setup_detect_pcsync_timer(const struct scaler_platform_data *pdata)
|
||||
{
|
||||
if (pdata->vga_hsync_gpio > 0) {
|
||||
if (gpio_request(pdata->vga_hsync_gpio, NULL) != 0) {
|
||||
printk("%s: request pc hsync detect pin failed\n", __func__);
|
||||
}else {
|
||||
if (pdata->vga_vsync_gpio > 0) {
|
||||
if (gpio_request(pdata->vga_vsync_gpio, NULL) != 0) {
|
||||
gpio_free(pdata->vga_hsync_gpio);
|
||||
printk("%s: request pc vsync detect pin failed\n", __func__);
|
||||
}else {
|
||||
gpio_direction_input(pdata->vga_hsync_gpio);
|
||||
gpio_direction_input(pdata->vga_vsync_gpio);
|
||||
init_timer(&timer);
|
||||
timer.function = timer_callbak_func;
|
||||
timer.data = (unsigned long)pdata;
|
||||
timer.expires = jiffies + msecs_to_jiffies(3000);
|
||||
vga_in_det = 1;
|
||||
}//request vsync
|
||||
}else {//defined vsync
|
||||
gpio_free(pdata->vga_hsync_gpio);
|
||||
}
|
||||
}//request hsync
|
||||
}//defined hsync
|
||||
|
||||
|
||||
}
|
||||
/********************pc v\hsync************************/
|
||||
|
||||
static int tv_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
int res;
|
||||
struct scaler_platform_data *pdata = client->dev.platform_data;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
res = -ENODEV;
|
||||
dev_err(&client->adapter->dev, "%s failed %d\n\n", __func__, res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
printk("%s: client private data not define\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scaler_init_platform(pdata);
|
||||
|
||||
if (tv_hardware_is_ok(client) != 0) {
|
||||
printk("%s chip hardware not ready\n", client->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//alloc chip memory
|
||||
chip = alloc_scaler_chip();
|
||||
if (!chip) {
|
||||
printk("%s: alloc scaler chip memory failed.\n", __func__);
|
||||
return -1;
|
||||
}else {
|
||||
chip->client = client;
|
||||
chip->pdata = pdata;
|
||||
memcpy((void *)chip->name, (void *)client->name, (strlen(client->name) + 1));
|
||||
}
|
||||
|
||||
//init chip
|
||||
if (init_scaler_chip(chip, pdata) != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
//implement parse cmd function
|
||||
chip->parse_cmd = parse_cmd;
|
||||
chip->start = tv5735_start;
|
||||
|
||||
//register chip
|
||||
if (register_scaler_chip(chip) != 0) {
|
||||
printk("%s: register scaler chip failed\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
setup_detect_pcsync_timer(pdata);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free_scaler_chip(chip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tv_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
|
||||
printk("%s: \n", __func__);
|
||||
unregister_scaler_chip(chip);
|
||||
free_scaler_chip(chip);
|
||||
chip = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct i2c_device_id tv_i2c_id[] ={
|
||||
{"tv5735", 0}, {}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tv_i2c_id);
|
||||
|
||||
static struct i2c_driver tv_i2c_driver = {
|
||||
.id_table = tv_i2c_id,
|
||||
.driver = {
|
||||
.name = "tv5735"
|
||||
},
|
||||
.probe = tv_i2c_probe,
|
||||
.remove = tv_i2c_remove,
|
||||
};
|
||||
|
||||
static int __init tv_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
printk("%s: \n", __func__);
|
||||
|
||||
ret = i2c_add_driver(&tv_i2c_driver);
|
||||
if(ret < 0){
|
||||
printk("%s, register i2c device, error\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit tv_exit(void)
|
||||
{
|
||||
printk("%s: \n", __func__);
|
||||
}
|
||||
|
||||
module_init(tv_init);
|
||||
module_exit(tv_exit);
|
||||
|
||||
2740
drivers/misc/scaler/chips/tv_setting.h
Normal file
2740
drivers/misc/scaler/chips/tv_setting.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/scaler-core.h>
|
||||
|
||||
#define SCALER_CORE_VERSION "v1.0.0"
|
||||
#define SCALER_CORE_NAME "scaler-core"
|
||||
#define SCALER_DEV_NAME "scaler-ctrl"
|
||||
|
||||
static DEFINE_MUTEX(mutex_chips);
|
||||
|
|
@ -113,6 +114,60 @@ struct scaler_chip_dev *alloc_scaler_chip(void)
|
|||
return p;
|
||||
}
|
||||
|
||||
int scaler_init_platform(struct scaler_platform_data *pdata)
|
||||
{
|
||||
printk("%s: init scaler platform\n", SCALER_CORE_NAME);
|
||||
|
||||
if (pdata->init_hw) {
|
||||
pdata->init_hw();
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
//power
|
||||
if (pdata->power_gpio > 0) {
|
||||
if (!gpio_request(pdata->power_gpio, NULL)) {
|
||||
if (pdata->power_level != GPIO_HIGH &&
|
||||
pdata->power_level != GPIO_LOW) {
|
||||
printk("%s: power pin level use default high\n", SCALER_CORE_NAME);
|
||||
pdata->power_level = GPIO_HIGH;
|
||||
}
|
||||
gpio_direction_output(pdata->power_gpio, pdata->power_level);
|
||||
}else
|
||||
printk("%s: request vga power gpio failed\n", SCALER_CORE_NAME);
|
||||
}else
|
||||
printk("%s: Don't defined power gpio pin\n", SCALER_CORE_NAME);
|
||||
|
||||
//vga 5v en
|
||||
if (pdata->vga5v_gpio > 0) {
|
||||
if (!gpio_request(pdata->vga5v_gpio, NULL)) {
|
||||
if (pdata->vga5v_level != GPIO_HIGH &&
|
||||
pdata->vga5v_level != GPIO_LOW) {
|
||||
printk("%s: vga5ven pin level use default high\n", SCALER_CORE_NAME);
|
||||
pdata->vga5v_level = GPIO_HIGH;
|
||||
}
|
||||
gpio_direction_output(pdata->vga5v_gpio, pdata->vga5v_level);
|
||||
}else
|
||||
printk("%s: request vga5ven gpio failed\n", SCALER_CORE_NAME);
|
||||
msleep(10);
|
||||
}else
|
||||
printk("%s: Don't defined vga5ven gpio pin\n", SCALER_CORE_NAME);
|
||||
|
||||
//ddc select
|
||||
if (pdata->ddc_sel_gpio > 0) {
|
||||
if (!gpio_request(pdata->ddc_sel_gpio, NULL)) {
|
||||
if (pdata->ddc_sel_level != GPIO_HIGH &&
|
||||
pdata->ddc_sel_level != GPIO_LOW) {
|
||||
printk("%s: ddc select pin level use default high\n", SCALER_CORE_NAME);
|
||||
pdata->ddc_sel_level = GPIO_HIGH;
|
||||
}
|
||||
gpio_direction_output(pdata->ddc_sel_gpio, pdata->ddc_sel_level);
|
||||
}else
|
||||
printk("%s: request ddc select gpio failed\n", SCALER_CORE_NAME);
|
||||
msleep(10);
|
||||
}else
|
||||
printk("%s: Don't defined ddc select gpio pin\n", SCALER_CORE_NAME);
|
||||
}
|
||||
|
||||
int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *pdata)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -120,7 +175,7 @@ int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *
|
|||
struct scaler_input_port *iport = NULL;
|
||||
|
||||
if (!chip || !pdata) {
|
||||
printk("%s: chip or pdata is null.\n", __func__);
|
||||
printk("%s: chip or pdata is null.\n", SCALER_CORE_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +184,7 @@ int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *
|
|||
pdata->func_type < SCALER_FUNC_NUMS) {
|
||||
chip->func_type = pdata->func_type;
|
||||
}else {
|
||||
printk("%s: not defined scaer function type\n", __func__);
|
||||
printk("%s: not defined scaer function type\n", SCALER_CORE_NAME);
|
||||
chip->func_type = SCALER_FUNC_FULL;
|
||||
}
|
||||
printk("%s: %s %s\n", chip->name, scaler_func_name[0], scaler_func_name[chip->func_type]);
|
||||
|
|
@ -138,7 +193,7 @@ int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *
|
|||
for (i = 0; i < pdata->iport_size; i++) {
|
||||
iport = kzalloc(sizeof(struct scaler_input_port), GFP_KERNEL);
|
||||
if (!iport) {
|
||||
printk("%s: kzalloc input port memeory failed.\n", __func__);
|
||||
printk("%s: kzalloc input port memeory failed.\n", SCALER_CORE_NAME);
|
||||
return -1;
|
||||
}else {
|
||||
iport->max_hres = 1920;
|
||||
|
|
@ -179,7 +234,7 @@ int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *
|
|||
for (i = 0; i < pdata->oport_size; i++) {
|
||||
oport = kzalloc(sizeof(struct scaler_output_port), GFP_KERNEL);
|
||||
if (!oport) {
|
||||
printk("%s: kzalloc output port memeory failed.\n", __func__);
|
||||
printk("%s: kzalloc output port memeory failed.\n", SCALER_CORE_NAME);
|
||||
return -1;
|
||||
}else {
|
||||
oport->max_hres = 1920;
|
||||
|
|
@ -214,6 +269,7 @@ int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *
|
|||
}// if (!oport)
|
||||
}//for()
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +279,8 @@ void free_scaler_chip(struct scaler_chip_dev *chip)
|
|||
struct scaler_output_port *out = NULL;
|
||||
struct scaler_input_port *in = NULL;
|
||||
if (chip) {
|
||||
|
||||
printk("%s: free %s chip<id:%d> memory resource\n",
|
||||
SCALER_CORE_NAME, chip->name, chip->id);
|
||||
list_for_each_entry(out, &chip->oports, next) {
|
||||
kfree(out);
|
||||
}
|
||||
|
|
@ -271,7 +328,11 @@ int register_scaler_chip(struct scaler_chip_dev *chip)
|
|||
chip->id = ++chip_ids; //chip id only grow
|
||||
list_add_tail(&chip->next, &sdev->chips);
|
||||
mutex_unlock(&mutex_chips);
|
||||
printk("%s: register scaler chip %s success.\n", __func__, chip->name);
|
||||
printk("%s: register scaler chip %s<id:%d> success.\n",
|
||||
SCALER_CORE_NAME, chip->name, chip->id);
|
||||
}else {
|
||||
printk("%s: register scaler chip %s<id:%d> failed.\n",
|
||||
SCALER_CORE_NAME, chip->name, chip->id);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
@ -305,7 +366,7 @@ int unregister_scaler_chip(struct scaler_chip_dev *chip)
|
|||
mutex_lock(&mutex_chips);
|
||||
list_del(&chip->next);
|
||||
mutex_unlock(&mutex_chips);
|
||||
printk("%s: unregister scaler chip %s success.\n", __func__, chip->name);
|
||||
printk("%s: unregister scaler chip %s<id:%d> success.\n", __func__, chip->name, chip->id);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
@ -350,13 +411,14 @@ static int scaler_file_ioctl(struct inode *inode, struct file *filp, unsigned i
|
|||
break;
|
||||
case SCALER_IOCTL_SET_CUR_INPUT:
|
||||
//choose input channel;
|
||||
copy_from_user(&iport_id, arg, sizeof(int));
|
||||
copy_from_user(&iport_id, (void *)arg, sizeof(int));
|
||||
|
||||
list_for_each_entry(chip, &sdev->chips, next) {
|
||||
if (chip->cur_inport_id != iport_id) {
|
||||
list_for_each_entry(iport, &chip->iports, next) {//if iport belong to this chip
|
||||
if (iport->id == iport_id) {
|
||||
chip->cur_inport_id = iport_id;
|
||||
chip->cur_in_type = iport->type;
|
||||
chip->parse_cmd(cmd, arg);
|
||||
break;
|
||||
}
|
||||
|
|
@ -369,7 +431,7 @@ static int scaler_file_ioctl(struct inode *inode, struct file *filp, unsigned i
|
|||
list_for_each_entry(chip, &sdev->chips, next) {
|
||||
iport_id = chip->cur_inport_id;
|
||||
}//list chips
|
||||
copy_to_user(arg, &iport_id, sizeof(int));
|
||||
copy_to_user((void *)arg, &iport_id, sizeof(int));
|
||||
printk("current input port id %d\n", iport_id);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
478
drivers/misc/scaler/scaler-edid.c
Normal file
478
drivers/misc/scaler/scaler-edid.c
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
//#include <linux/rk_screen.h>
|
||||
#include <linux/rk_fb.h>
|
||||
#include "../../video/edid.h"
|
||||
|
||||
#define DDC_ADDR 0x50 //read 0xa0 write 0xa1
|
||||
#define DDC_I2C_RATE 100*1000
|
||||
#define DEFAULT_MODE 3
|
||||
|
||||
#undef SDEBUG
|
||||
|
||||
#ifdef SDEBUG
|
||||
#define SPRINTK(fmt, args...) printk(fmt,## args)
|
||||
#else
|
||||
#define SPRINTK(fmt, args...)
|
||||
#endif
|
||||
|
||||
static struct scaler_ddc_dev
|
||||
{
|
||||
unsigned char *edid;
|
||||
struct i2c_client *client;
|
||||
struct fb_monspecs specs;
|
||||
struct list_head modelist;
|
||||
struct fb_videomode *mode;
|
||||
}*ddev = NULL;
|
||||
|
||||
static const struct fb_videomode default_modedb[] = {
|
||||
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag(used for vic)
|
||||
#if defined(CONFIG_CLK_RK30_BOX)
|
||||
{ "1024x768p@60Hz", 60, 1024, 768, KHZ2PICOS(65000), 160, 24, 29, 3, 136, 6, 0, 0, 0 },
|
||||
{ "1280x720p@60Hz", 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1280x1024p@60Hz", 60, 1280, 1024, KHZ2PICOS(108000), 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1366x768p@60Hz", 60, 1366, 768, KHZ2PICOS(85500), 213, 70, 24, 3, 143, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1440x900p@60Hz", 60, 1440, 900, KHZ2PICOS(106500), 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1680x1050p@60Hz", 60, 1680, 1050, KHZ2PICOS(146250), 280, 104, 30, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1920x1080p@60Hz", 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
#else
|
||||
//{ "640x480p@60Hz", 60, 640, 480, KHZ2PICOS(25175), 48, 16, 33, 10, 96, 2, 0, 0, 1 },
|
||||
{ "720x480p@60Hz", 60, 720, 480, KHZ2PICOS(27000), 60, 16, 30, 9, 62, 6, 0, 0, 2 },
|
||||
{ "720x576p@50Hz", 50, 720, 576, KHZ2PICOS(27000), 68, 12, 39, 5, 64, 5, 0, 0, 17 },
|
||||
{ "1280x720p@50Hz", 50, 1280, 720, KHZ2PICOS(74250), 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 19 },
|
||||
{ "1280x720p@60Hz", 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 4 },
|
||||
{ "1920x1080p@50Hz", 50, 1920, 1080, KHZ2PICOS(148500), 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 31 },
|
||||
{ "1920x1080p@60Hz", 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 16 },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int scaler_mode2screen(const struct fb_videomode *modedb, struct rk29fb_screen *screen)
|
||||
{
|
||||
if(modedb == NULL || screen == NULL)
|
||||
return -1;
|
||||
|
||||
memset(screen, 0, sizeof(struct rk29fb_screen));
|
||||
/* screen type & face */
|
||||
screen->type = SCREEN_RGB;
|
||||
screen->face = OUT_P888;
|
||||
//screen->lvds_format = LVDS_8BIT_1; //lvds data format
|
||||
|
||||
/* Screen size */
|
||||
screen->x_res = modedb->xres;
|
||||
screen->y_res = modedb->yres;
|
||||
|
||||
/* Timing */
|
||||
screen->pixclock = PICOS2KHZ(modedb->pixclock);
|
||||
screen->pixclock /= 250;
|
||||
screen->pixclock *= 250;
|
||||
screen->pixclock *= 1000;
|
||||
printk(" pixclock is %d\n", screen->pixclock);
|
||||
screen->lcdc_aclk = 300000000;
|
||||
|
||||
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 = 1;
|
||||
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_vga_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info)
|
||||
{
|
||||
scaler_mode2screen(&default_modedb[DEFAULT_MODE], screen);
|
||||
}
|
||||
|
||||
static int scaler_edid_read(char *buf, int len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ddev == NULL || ddev->client == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
// Check ddc i2c communication is available or not.
|
||||
rc = i2c_master_reg8_recv(ddev->client, 0, buf, 6, DDC_I2C_RATE);
|
||||
if(rc == 6) {
|
||||
/************DEBUG*************/
|
||||
SPRINTK("EDID HEAD: ");
|
||||
for (rc = 0; rc < 6; rc++)
|
||||
SPRINTK(" %#X", buf[rc]);
|
||||
SPRINTK("\n");
|
||||
/************DEBUG*************/
|
||||
|
||||
memset(buf, 0, len);
|
||||
// Read EDID.
|
||||
rc = i2c_master_reg8_recv(ddev->client, 0, buf, len, DDC_I2C_RATE);
|
||||
if(rc == len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("unable to read EDID block.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
*read edid of monitor and parse it
|
||||
*/
|
||||
static int scaler_parse_vga_edid(void)
|
||||
{
|
||||
int i ;
|
||||
struct fb_monspecs *specs = NULL;
|
||||
if (ddev == NULL) {
|
||||
return -ENODEV;
|
||||
}else {
|
||||
specs = &ddev->specs;
|
||||
//free old edid
|
||||
if (ddev->edid) {
|
||||
kfree(ddev->edid);
|
||||
ddev->edid = NULL;
|
||||
}
|
||||
ddev->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
if (!ddev->edid)
|
||||
return -ENOMEM;
|
||||
|
||||
//read edid
|
||||
if (!scaler_edid_read(ddev->edid, EDID_LENGTH)) {
|
||||
//free old fb_monspecs
|
||||
if(specs->modedb)
|
||||
kfree(specs->modedb);
|
||||
memset(specs, 0, sizeof(struct fb_monspecs));
|
||||
//parse edid to fb_monspecs
|
||||
fb_edid_to_monspecs(ddev->edid, specs);
|
||||
|
||||
/********** DEBUG ***********/
|
||||
SPRINTK("========================================\n");
|
||||
SPRINTK("Display Information (EDID)\n");
|
||||
SPRINTK("========================================\n");
|
||||
SPRINTK(" EDID Version %d.%d\n", (int) specs->version, (int) specs->revision);
|
||||
SPRINTK(" Serial Number: %s\n", specs->serial_no);
|
||||
SPRINTK(" ASCII Block: %s\n", specs->ascii);
|
||||
SPRINTK(" Monitor Name: %s\n", specs->monitor);
|
||||
SPRINTK(" Display Characteristics:\n");
|
||||
for (i = 0; i < specs->modedb_len; i++)
|
||||
SPRINTK(" %4d x %4d @%d [clk: %ldKHZ]\n", specs->modedb[i].xres, specs->modedb[i].yres,
|
||||
specs->modedb[i].refresh, PICOS2KHZ(specs->modedb[i].pixclock));
|
||||
SPRINTK("========================================\n");
|
||||
/********** DEBUG ***********/
|
||||
}else {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
printk("scaler-ddc: read and parse vga edid success.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scaler_set_default_modelist(void)
|
||||
{
|
||||
int i;
|
||||
struct fb_videomode *mode = NULL;
|
||||
struct list_head *modelist = &ddev->modelist;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(default_modedb); i++)
|
||||
{
|
||||
mode = (struct fb_videomode *)&default_modedb[i];
|
||||
fb_add_videomode(mode, modelist);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check mode 1920x1080p@60Hz is in modedb or not.
|
||||
* If exist, set it as output moe.
|
||||
* If not exist, try mode 1280x720p@60Hz.
|
||||
* If both mode not exist, try 720x480p@60Hz.
|
||||
*/
|
||||
static int scaler_check_mode(struct fb_videomode *mode)
|
||||
{
|
||||
struct fb_monspecs *specs = NULL;
|
||||
struct list_head *modelist = NULL;
|
||||
struct fb_videomode *tmp_mode = NULL;
|
||||
unsigned int pixclock;
|
||||
int i;
|
||||
|
||||
if (ddev == NULL)
|
||||
return -ENODEV;
|
||||
specs = &ddev->specs;
|
||||
modelist = &ddev->modelist;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
|
||||
if (mode) {
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(default_modedb); i++) {
|
||||
tmp_mode = (struct fb_videomode *)&default_modedb[i];
|
||||
pixclock = PICOS2KHZ(tmp_mode->pixclock);
|
||||
pixclock /= 250;
|
||||
pixclock *= 250;
|
||||
pixclock *= 1000;
|
||||
if( (pixclock <= specs->dclkmax) &&
|
||||
(tmp_mode->xres <= mode->xres) && (tmp_mode->yres <= mode->yres) &&
|
||||
(tmp_mode->refresh <= specs->vfmax) && (tmp_mode->refresh >= specs->vfmin)
|
||||
) {
|
||||
fb_add_videomode(tmp_mode, modelist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find monitor prefered video mode. If not find,
|
||||
* @specs init info of monitor
|
||||
*/
|
||||
struct fb_videomode *scaler_find_max_mode(void)
|
||||
{
|
||||
struct fb_videomode *mode = NULL/*, *nearest_mode = NULL*/;
|
||||
struct fb_monspecs *specs = NULL;
|
||||
int i, pixclock;
|
||||
|
||||
if (ddev == NULL)
|
||||
return NULL;
|
||||
specs = &ddev->specs;
|
||||
if(specs->modedb_len) {
|
||||
|
||||
|
||||
/* Get max resolution timing */
|
||||
mode = &specs->modedb[0];
|
||||
for (i = 0; i < specs->modedb_len; i++) {
|
||||
if(specs->modedb[i].xres > mode->xres)
|
||||
mode = &specs->modedb[i];
|
||||
else if( (specs->modedb[i].xres == mode->xres) && (specs->modedb[i].yres > mode->yres) )
|
||||
mode = &specs->modedb[i];
|
||||
}
|
||||
|
||||
// For some monitor, the max pixclock read from EDID is smaller
|
||||
// than the clock of max resolution mode supported. We fix it.
|
||||
pixclock = PICOS2KHZ(mode->pixclock);
|
||||
pixclock /= 250;
|
||||
pixclock *= 250;
|
||||
pixclock *= 1000;
|
||||
if(pixclock == 148250000)
|
||||
pixclock = 148500000;
|
||||
if(pixclock > specs->dclkmax)
|
||||
specs->dclkmax = pixclock;
|
||||
|
||||
printk("scaler-ddc: max mode %dx%d@%d[pixclock-%ld KHZ]\n", mode->xres, mode->yres,
|
||||
mode->refresh, PICOS2KHZ(mode->pixclock));
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static struct fb_videomode *scaler_find_best_mode(void)
|
||||
{
|
||||
int res = -1;
|
||||
struct fb_videomode *mode = NULL, *best = NULL;
|
||||
|
||||
res = scaler_parse_vga_edid();
|
||||
if (res == 0) {
|
||||
mode = scaler_find_max_mode();
|
||||
if (mode) {
|
||||
scaler_check_mode(mode);
|
||||
best = (struct fb_videomode *)fb_find_nearest_mode(mode, &ddev->modelist);
|
||||
}
|
||||
} else {
|
||||
printk("scaler-ddc: read and parse edid failed errno:%d.\n", res);
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
int scaler_switch_screen(struct fb_videomode *mode)
|
||||
{
|
||||
struct rk29fb_screen screen;
|
||||
|
||||
if (mode) {
|
||||
scaler_mode2screen(mode, &screen);
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
return FB_Switch_Screen(&screen, 1);
|
||||
#else
|
||||
return rk_fb_switch_screen(&screen, 1, 0);
|
||||
#endif
|
||||
}
|
||||
printk("scaler-ddc: fb_videomode is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int scaler_switch_default_screen(void)
|
||||
{
|
||||
int res;
|
||||
struct fb_videomode *mode = NULL;
|
||||
|
||||
if (ddev == NULL) {
|
||||
printk("scaler-ddc: No DDC Dev.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mode = scaler_find_best_mode();
|
||||
if (mode) {
|
||||
printk("scaler-ddc: best mode %dx%d@%d[pixclock-%ld KHZ]\n", mode->xres, mode->yres,
|
||||
mode->refresh, PICOS2KHZ(mode->pixclock));
|
||||
ddev->mode = mode;
|
||||
res = scaler_switch_screen(mode);
|
||||
}else {
|
||||
res = -1;
|
||||
printk("scaler-ddc: Don't find best mode\n");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scaler_switch_default_screen);
|
||||
|
||||
struct fb_videomode *scaler_get_cmode(void)
|
||||
{
|
||||
struct fb_videomode *mode = NULL;
|
||||
if (ddev != NULL)
|
||||
mode = ddev->mode;
|
||||
return mode;
|
||||
}
|
||||
EXPORT_SYMBOL(scaler_get_cmode);
|
||||
|
||||
|
||||
static int scaler_ddc_probe(struct i2c_client *client,const struct i2c_device_id *id)
|
||||
{
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -ENODEV;
|
||||
|
||||
ddev = kzalloc(sizeof(struct scaler_ddc_dev), GFP_KERNEL);
|
||||
if (ddev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&ddev->modelist);
|
||||
ddev->client = client;
|
||||
ddev->mode = &default_modedb[DEFAULT_MODE];
|
||||
scaler_set_default_modelist();
|
||||
|
||||
printk("%s: success.\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit scaler_ddc_remove(struct i2c_client *client)
|
||||
{
|
||||
if(ddev->edid)
|
||||
kfree(ddev->edid);
|
||||
if (ddev->specs.modedb)
|
||||
kfree(ddev->specs.modedb);
|
||||
kfree(ddev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id scaler_ddc_id[] = {
|
||||
{ "scaler_ddc", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct i2c_driver scaler_ddc_driver = {
|
||||
.driver = {
|
||||
.name = "scaler_ddc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = scaler_ddc_probe,
|
||||
.remove = scaler_ddc_remove,
|
||||
.id_table = scaler_ddc_id,
|
||||
};
|
||||
|
||||
static int __init scaler_ddc_init(void)
|
||||
{
|
||||
return i2c_add_driver(&scaler_ddc_driver);
|
||||
}
|
||||
|
||||
static void __exit scaler_ddc_exit(void)
|
||||
{
|
||||
i2c_del_driver(&scaler_ddc_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(scaler_ddc_init);
|
||||
module_exit(scaler_ddc_exit);
|
||||
|
||||
|
||||
/************SYSFS DEBUG ***********/
|
||||
void scaler_ddc_is_ok(void)
|
||||
{
|
||||
int rc = -1;
|
||||
char buf[8];
|
||||
if (ddev != NULL) {
|
||||
rc = i2c_master_reg8_recv(ddev->client, 0, buf, 8, DDC_I2C_RATE);
|
||||
if(rc == 8) {
|
||||
if (buf[0] == 0x00 && buf[1] == 0xff && buf[2] == 0xff && buf[3] == 0xff &&
|
||||
buf[4] == 0xff && buf[5] == 0xff && buf[6] == 0xff && buf[7] == 0x00)
|
||||
printk("scaler-ddc: is ok\n");
|
||||
else
|
||||
printk("scaler-ddc: io error");
|
||||
}else
|
||||
printk("scaler-ddc: i2c error\n");
|
||||
}else
|
||||
printk("scaler-ddc: unknown error\n");
|
||||
}
|
||||
|
||||
void scaler_current_mode(void)
|
||||
{
|
||||
if (ddev != NULL && ddev->mode != NULL)
|
||||
printk("scaler-ddc: cmode %dx%d@%d\n", ddev->mode->xres, ddev->mode->yres,
|
||||
ddev->mode->refresh);
|
||||
else
|
||||
printk("scaler-ddc: unknown mode\n");
|
||||
}
|
||||
|
||||
void scaler_test_read_vga_edid(void)
|
||||
{
|
||||
int i = 0, res;
|
||||
struct fb_monspecs *specs = NULL;
|
||||
|
||||
res = scaler_parse_vga_edid();
|
||||
if (res == 0) {
|
||||
specs = &ddev->specs;
|
||||
|
||||
printk("========================================\n");
|
||||
printk("Display Information (EDID)\n");
|
||||
printk("========================================\n");
|
||||
printk(" EDID Version %d.%d\n", (int) specs->version, (int) specs->revision);
|
||||
printk(" Serial Number: %s\n", specs->serial_no);
|
||||
printk(" ASCII Block: %s\n", specs->ascii);
|
||||
printk(" Monitor Name: %s\n", specs->monitor);
|
||||
printk(" Display Characteristics:\n");
|
||||
for (i = 0; i < specs->modedb_len; i++)
|
||||
printk(" %4d x %4d @%d [clk: %ldKHZ]\n", specs->modedb[i].xres, specs->modedb[i].yres,
|
||||
specs->modedb[i].refresh, PICOS2KHZ(specs->modedb[i].pixclock));
|
||||
printk("========================================\n");
|
||||
|
||||
}else{
|
||||
printk("scaler-ddc: read and parse failed errno %d\n", res);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,27 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/scaler-core.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
extern void scaler_test_read_vga_edid(void);
|
||||
extern void scaler_ddc_is_ok(void);
|
||||
extern void scaler_current_mode(void);
|
||||
extern const char const *scaler_input_name[];
|
||||
|
||||
static ssize_t scaler_chips_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct scaler_chip_dev *chip = NULL;
|
||||
struct scaler_device *sdev = dev_get_drvdata(dev);
|
||||
|
||||
list_for_each_entry(chip, &sdev->chips, next) {
|
||||
printk("name: %s<id: %d>\n", chip->name, chip->id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static DEVICE_ATTR(chips, 0664, scaler_chips_show, NULL);
|
||||
|
||||
static ssize_t scaler_iport_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -22,20 +42,13 @@ static ssize_t scaler_iport_show(struct device *dev,
|
|||
|
||||
return sprintf(buf, "%d\n", iports);
|
||||
}
|
||||
|
||||
static ssize_t scaler_iport_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static DEVICE_ATTR(iports, 0664, scaler_iport_show, NULL);
|
||||
|
||||
static ssize_t scaler_cur_iport_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct scaler_chip_dev *chip = NULL;
|
||||
struct scaler_input_port *in = NULL;
|
||||
//struct scaler_input_port *in = NULL;
|
||||
struct scaler_device *sdev = dev_get_drvdata(dev);
|
||||
|
||||
list_for_each_entry(chip, &sdev->chips, next) {
|
||||
|
|
@ -47,22 +60,15 @@ static ssize_t scaler_cur_iport_show(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR(cur_iport, 0664, scaler_cur_iport_show, NULL);
|
||||
|
||||
static ssize_t scaler_oport_show(struct device *dev,
|
||||
static ssize_t scaler_cmode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
printk("%s: scaler sysfs test.\n", __func__);
|
||||
scaler_current_mode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t scaler_oport_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static DEVICE_ATTR(oports, 0664, scaler_oport_show, NULL);
|
||||
static DEVICE_ATTR(current_mode, 0664, scaler_cmode_show, NULL);
|
||||
|
||||
extern void scaler_test_read_vga_edid(void);
|
||||
static ssize_t scaler_edid_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -71,11 +77,21 @@ static ssize_t scaler_edid_show(struct device *dev,
|
|||
}
|
||||
static DEVICE_ATTR(edid, 0664, scaler_edid_show, NULL);
|
||||
|
||||
static ssize_t scaler_ddc_status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
scaler_ddc_is_ok();
|
||||
return 0;
|
||||
}
|
||||
static DEVICE_ATTR(ddc_status, 0664, scaler_ddc_status_show, NULL);
|
||||
|
||||
static struct attribute *scaler_attributes[] = {
|
||||
&dev_attr_chips.attr,
|
||||
&dev_attr_iports.attr,
|
||||
&dev_attr_cur_iport.attr,
|
||||
&dev_attr_current_mode.attr,
|
||||
&dev_attr_edid.attr,
|
||||
&dev_attr_oports.attr,
|
||||
&dev_attr_ddc_status.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -97,8 +113,6 @@ int scaler_sysfs_create(struct scaler_device *sdev)
|
|||
{
|
||||
int err;
|
||||
|
||||
//sdev->kobj = kobject_create_and_add("attr", &sdev->dev->kobj);
|
||||
//err = sysfs_create_group(sdev->kobj, &scaler_attr_group);
|
||||
err = sysfs_create_group(&sdev->dev->kobj, &scaler_attr_group);
|
||||
|
||||
return err;
|
||||
|
|
@ -107,7 +121,5 @@ int scaler_sysfs_create(struct scaler_device *sdev)
|
|||
int scaler_sysfs_remove(struct scaler_device *sdev)
|
||||
{
|
||||
sysfs_remove_group(&sdev->dev->kobj, &scaler_attr_group);
|
||||
//dev_set_drvdata(sdev->dev, NULL);
|
||||
//kobject_put(sdev->kobj);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,577 +0,0 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/display-sys.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
#include <linux/rk_screen.h>
|
||||
#include <linux/rk_fb.h>
|
||||
#include "../../video/edid.h"
|
||||
|
||||
#define DDC_I2C_BUS 1
|
||||
#define DDC_ADDR 0x50
|
||||
#define DDC_I2C_RATE 100*1000
|
||||
|
||||
static const struct fb_videomode rk29_mode[] = {
|
||||
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag(used for vic)
|
||||
#if defined(CONFIG_CLK_RK30_BOX)
|
||||
{ "1024x768p@60Hz", 60, 1024, 768, KHZ2PICOS(65000), 160, 24, 29, 3, 136, 6, 0, 0, 0 },
|
||||
{ "1280x720p@60Hz", 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1280x1024p@60Hz", 60, 1280, 1024, KHZ2PICOS(108000), 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1366x768p@60Hz", 60, 1366, 768, KHZ2PICOS(85500), 213, 70, 24, 3, 143, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1440x900p@60Hz", 60, 1440, 900, KHZ2PICOS(106500), 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1680x1050p@60Hz", 60, 1680, 1050, KHZ2PICOS(146250), 280, 104, 30, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
{ "1920x1080p@60Hz", 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 },
|
||||
#else
|
||||
//{ "640x480p@60Hz", 60, 640, 480, KHZ2PICOS(25175), 48, 16, 33, 10, 96, 2, 0, 0, 1 },
|
||||
{ "720x480p@60Hz", 60, 720, 480, KHZ2PICOS(27000), 60, 16, 30, 9, 62, 6, 0, 0, 2 },
|
||||
{ "720x576p@50Hz", 50, 720, 576, KHZ2PICOS(27000), 68, 12, 39, 5, 64, 5, 0, 0, 17 },
|
||||
{ "1280x720p@50Hz", 50, 1280, 720, KHZ2PICOS(74250), 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 19 },
|
||||
{ "1280x720p@60Hz", 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 4 },
|
||||
{ "1920x1080p@50Hz", 50, 1920, 1080, KHZ2PICOS(148500), 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 31 },
|
||||
{ "1920x1080p@60Hz", 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 16 },
|
||||
#endif
|
||||
};
|
||||
|
||||
struct rk29_monspecs {
|
||||
struct i2c_client *i2c_client;
|
||||
struct rk_display_device *ddev;
|
||||
int io_enable_pin;
|
||||
int video_source;
|
||||
int property;
|
||||
struct fb_monspecs monspecs;
|
||||
struct list_head modelist;
|
||||
struct fb_videomode *mode;
|
||||
int enable;
|
||||
};
|
||||
|
||||
static struct rk29_monspecs rk29_monspec;
|
||||
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
extern int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable );
|
||||
#else
|
||||
static int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable )
|
||||
{
|
||||
return rk_fb_switch_screen(screen, enable , rk29_monspec.video_source);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned char *rk29fb_ddc_read(struct i2c_client *client)
|
||||
{
|
||||
unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
int rc;
|
||||
|
||||
if (!buf) {
|
||||
dev_warn(&client->dev, "unable to allocate memory for EDID "
|
||||
"block.\n");
|
||||
return NULL;
|
||||
}
|
||||
// Check ddc i2c communication is available or not.
|
||||
memset(buf, 0, EDID_LENGTH);
|
||||
rc = i2c_master_reg8_recv(client, 0, buf, 6, DDC_I2C_RATE);
|
||||
if(rc == 6)
|
||||
{
|
||||
// Read EDID.
|
||||
memset(buf, 0, EDID_LENGTH);
|
||||
rc = i2c_master_reg8_recv(client, 0, buf, EDID_LENGTH, DDC_I2C_RATE);
|
||||
if(rc == EDID_LENGTH)
|
||||
return buf;
|
||||
}
|
||||
|
||||
dev_warn(&client->dev, "unable to read EDID block.\n");
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fb_videomode *rk29fb_set_default_modelist(void)
|
||||
{
|
||||
int i;
|
||||
struct fb_videomode *mode = NULL;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
for(i = 0; i < ARRAY_SIZE(rk29_mode); i++)
|
||||
{
|
||||
mode = (struct fb_videomode *)&rk29_mode[i];
|
||||
fb_add_videomode(mode, modelist);
|
||||
}
|
||||
rk29_monspec.mode = (struct fb_videomode *)&rk29_mode[3];
|
||||
return rk29_monspec.mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find monitor prefered video mode. If not find,
|
||||
* set first mode as default mode.
|
||||
*/
|
||||
static struct fb_videomode *rk29fb_find_default_mode(void)
|
||||
{
|
||||
struct fb_monspecs *specs = &rk29_monspec.monspecs;
|
||||
struct fb_videomode *modedb = NULL;
|
||||
int i, pixclock;
|
||||
|
||||
if(specs->modedb_len) {
|
||||
/* Get max resolution timing */
|
||||
modedb = &specs->modedb[0];
|
||||
for (i = 0; i < specs->modedb_len; i++) {
|
||||
if(specs->modedb[i].xres > modedb->xres)
|
||||
modedb = &specs->modedb[i];
|
||||
else if( (specs->modedb[i].xres == modedb->xres) && (specs->modedb[i].yres > modedb->yres) )
|
||||
modedb = &specs->modedb[i];
|
||||
}
|
||||
// For some monitor, the max pixclock read from EDID is smaller
|
||||
// than the clock of max resolution mode supported. We fix it.
|
||||
|
||||
pixclock = PICOS2KHZ(modedb->pixclock);
|
||||
pixclock /= 250;
|
||||
pixclock *= 250;
|
||||
pixclock *= 1000;
|
||||
if(pixclock == 148250000)
|
||||
pixclock = 148500000;
|
||||
if(pixclock > specs->dclkmax)
|
||||
specs->dclkmax = pixclock;
|
||||
}
|
||||
else
|
||||
modedb = rk29fb_set_default_modelist();
|
||||
return modedb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check mode 1920x1080p@60Hz is in modedb or not.
|
||||
* If exist, set it as output moe.
|
||||
* If not exist, try mode 1280x720p@60Hz.
|
||||
* If both mode not exist, try 720x480p@60Hz.
|
||||
*/
|
||||
static int rk29fb_check_mode(void)
|
||||
{
|
||||
struct fb_monspecs *specs = &rk29_monspec.monspecs;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
struct fb_videomode *modedb = NULL, *mode = NULL;
|
||||
unsigned int pixclock;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
modedb = rk29fb_find_default_mode();
|
||||
|
||||
if(modedb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(rk29_mode); i++)
|
||||
{
|
||||
pixclock = PICOS2KHZ(rk29_mode[i].pixclock);
|
||||
pixclock /= 250;
|
||||
pixclock *= 250;
|
||||
pixclock *= 1000;
|
||||
if( (pixclock <= specs->dclkmax) &&
|
||||
(rk29_mode[i].xres <= modedb->xres) &&
|
||||
(rk29_mode[i].yres <= modedb->yres) &&
|
||||
(rk29_mode[i].refresh <= specs->vfmax) &&
|
||||
(rk29_mode[i].refresh >= specs->vfmin)
|
||||
)
|
||||
{
|
||||
mode = (struct fb_videomode *)&rk29_mode[i];
|
||||
//display_add_videomode(mode, modelist);
|
||||
fb_add_videomode(mode, modelist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* Probe monitor information using E-EDID.
|
||||
*/
|
||||
static int rk29fb_probe_screens(struct i2c_client *client)
|
||||
{
|
||||
struct fb_monspecs *spec = &rk29_monspec.monspecs;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
u8 *edid;
|
||||
struct fb_videomode *defaultmode, *mode;
|
||||
|
||||
if (client)
|
||||
edid = rk29fb_ddc_read(client);
|
||||
else
|
||||
edid = NULL;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
INIT_LIST_HEAD(modelist);
|
||||
if(spec->modedb)
|
||||
kfree(spec->modedb);
|
||||
memset(spec, 0, sizeof(struct fb_monspecs));
|
||||
if(edid)
|
||||
{
|
||||
fb_edid_to_monspecs(edid, spec);
|
||||
kfree(edid);
|
||||
rk29fb_check_mode();
|
||||
defaultmode = rk29fb_find_default_mode();
|
||||
if(defaultmode)
|
||||
mode = (struct fb_videomode *)fb_find_nearest_mode(defaultmode, &rk29_monspec.modelist);
|
||||
else
|
||||
mode = (struct fb_videomode *)&rk29_mode[3];
|
||||
rk29_monspec.mode = mode;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rk29fb_set_default_modelist();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
static int rk29_mode2screen(struct fb_videomode *modedb, struct rk29fb_screen *screen)
|
||||
{
|
||||
if(modedb == NULL || screen == NULL)
|
||||
return -1;
|
||||
|
||||
memset(screen, 0, sizeof(struct rk29fb_screen));
|
||||
/* screen type & face */
|
||||
screen->type = SCREEN_RGB;
|
||||
screen->face = OUT_P888;
|
||||
//screen->lvds_format = LVDS_8BIT_1; //lvds data format
|
||||
|
||||
/* Screen size */
|
||||
screen->x_res = modedb->xres;
|
||||
screen->y_res = modedb->yres;
|
||||
|
||||
/* Timing */
|
||||
screen->pixclock = PICOS2KHZ(modedb->pixclock);
|
||||
screen->pixclock /= 250;
|
||||
screen->pixclock *= 250;
|
||||
screen->pixclock *= 1000;
|
||||
printk("pixclock is %d\n", screen->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 = 1;
|
||||
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
static int rk29_set_enable(struct rk_display_device *device, int enable)
|
||||
{
|
||||
struct rk29_monspecs *rk29_monspec = device->priv_data;
|
||||
printk("[%s] set enable %d\n", __FUNCTION__, enable);
|
||||
if(enable != rk29_monspec->enable)
|
||||
{
|
||||
if(rk29_monspec->io_enable_pin != INVALID_GPIO) {
|
||||
gpio_set_value(rk29_monspec->io_enable_pin, enable?GPIO_HIGH:GPIO_LOW);
|
||||
}
|
||||
rk29_monspec->enable = enable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_get_enable(struct rk_display_device *device)
|
||||
{
|
||||
struct rk29_monspecs *rk29_monspec = device->priv_data;
|
||||
return rk29_monspec->enable;
|
||||
}
|
||||
|
||||
static int rk29_get_status(struct rk_display_device *device)
|
||||
{
|
||||
return (rk29fb_probe_screens(rk29_monspec.i2c_client))? 0:1;
|
||||
}
|
||||
|
||||
static int rk29_get_modelist(struct rk_display_device *device, struct list_head **modelist)
|
||||
{
|
||||
*modelist = &rk29_monspec.modelist;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
if(rk29_monspec.mode)
|
||||
{
|
||||
memcpy(mode, rk29_monspec.mode, sizeof(struct fb_videomode));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rk29_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < ARRAY_SIZE(rk29_mode); i++)
|
||||
{
|
||||
if(fb_mode_is_equal(&rk29_mode[i], mode))
|
||||
{
|
||||
struct rk29fb_screen screen;
|
||||
rk29_mode2screen(mode, &screen);
|
||||
FB_Switch_Screen(&screen, 1);
|
||||
rk29_monspec.mode = mode;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
struct rk_display_ops rk29_display_ops = {
|
||||
.setenable = rk29_set_enable,
|
||||
.getenable = rk29_get_enable,
|
||||
.getstatus = rk29_get_status,
|
||||
.getmodelist = rk29_get_modelist,
|
||||
.setmode = rk29_set_mode,
|
||||
.getmode = rk29_get_mode,
|
||||
};
|
||||
|
||||
static int rk29_display_probe(struct rk_display_device *device, void *devdata)
|
||||
{
|
||||
device->owner = THIS_MODULE;
|
||||
strcpy(device->type, "VGA");
|
||||
device->name = "vga";
|
||||
//device->property = rk29_monspec.property;
|
||||
device->priority = DISPLAY_PRIORITY_VGA;
|
||||
device->priv_data = devdata;
|
||||
device->ops = &rk29_display_ops;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct rk_display_driver display_rk29 = {
|
||||
.probe = rk29_display_probe,
|
||||
};
|
||||
/*
|
||||
* read edid of monitor and set screen atrrbute
|
||||
*/
|
||||
static int scaler_vga_set_screen(struct rk29fb_screen *screen)
|
||||
{
|
||||
|
||||
struct fb_monspecs *spec = &rk29_monspec.monspecs;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
u8 *edid;
|
||||
struct fb_videomode *defaultmode, *mode;
|
||||
|
||||
if (rk29_monspec.i2c_client)
|
||||
edid = rk29fb_ddc_read(rk29_monspec.i2c_client);
|
||||
else
|
||||
edid = NULL;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
INIT_LIST_HEAD(modelist);
|
||||
if(spec->modedb)
|
||||
kfree(spec->modedb);
|
||||
memset(spec, 0, sizeof(struct fb_monspecs));
|
||||
|
||||
if(edid)
|
||||
{
|
||||
fb_edid_to_monspecs(edid, spec);
|
||||
kfree(edid);
|
||||
rk29fb_check_mode();
|
||||
defaultmode = rk29fb_find_default_mode();
|
||||
if(defaultmode)
|
||||
mode = (struct fb_videomode *)fb_find_nearest_mode(defaultmode, &rk29_monspec.modelist);
|
||||
else
|
||||
mode = (struct fb_videomode *)&rk29_mode[3];
|
||||
rk29_monspec.mode = mode;
|
||||
|
||||
if(mode)
|
||||
{
|
||||
//struct rk29fb_screen screen;
|
||||
rk29_mode2screen(mode, screen);
|
||||
printk("%s: %dx%d@%d<%d>\n", __func__, mode->xres, mode->yres, mode->refresh, PICOS2KHZ(mode->pixclock * 1000));
|
||||
//printk("%s: lcdc id = %d video_source = %d\n", __func__, screen.lcdc_id, rk29_monspec.video_source);
|
||||
//FB_Switch_Screen(&screen, 1);
|
||||
//rk29_monspec.mode = mode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rk29fb_set_default_modelist();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int scaler_get_screens(struct i2c_client *client)
|
||||
{
|
||||
struct fb_monspecs *spec = &rk29_monspec.monspecs;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
u8 *edid;
|
||||
struct fb_videomode *defaultmode, *mode;
|
||||
|
||||
if (client)
|
||||
edid = rk29fb_ddc_read(client);
|
||||
else
|
||||
edid = NULL;
|
||||
|
||||
fb_destroy_modelist(modelist);
|
||||
INIT_LIST_HEAD(modelist);
|
||||
if(spec->modedb)
|
||||
kfree(spec->modedb);
|
||||
memset(spec, 0, sizeof(struct fb_monspecs));
|
||||
|
||||
if(edid)
|
||||
{
|
||||
fb_edid_to_monspecs(edid, spec);
|
||||
kfree(edid);
|
||||
rk29fb_check_mode();
|
||||
defaultmode = rk29fb_find_default_mode();
|
||||
if(defaultmode)
|
||||
mode = (struct fb_videomode *)fb_find_nearest_mode(defaultmode, &rk29_monspec.modelist);
|
||||
else
|
||||
mode = (struct fb_videomode *)&rk29_mode[3];
|
||||
rk29_monspec.mode = mode;
|
||||
|
||||
if(mode)
|
||||
{
|
||||
struct rk29fb_screen screen;
|
||||
rk29_mode2screen(mode, &screen);
|
||||
printk("%s: %dx%d@%d<%ld>\n", __func__, mode->xres, mode->yres, mode->refresh, PICOS2KHZ(mode->pixclock * 1000));
|
||||
FB_Switch_Screen(&screen, 1);
|
||||
rk29_monspec.mode = mode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rk29fb_set_default_modelist();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void set_vga_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info)
|
||||
{
|
||||
rk29_mode2screen(&rk29_mode[3], screen);
|
||||
}
|
||||
|
||||
static int vga_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
//struct rkdisplay_platform_data *vga_data;
|
||||
|
||||
memset(&rk29_monspec, 0, sizeof(struct rk29_monspecs));
|
||||
rk29_monspec.i2c_client = client;
|
||||
rk29_monspec.enable = 1;
|
||||
|
||||
/*if(client->dev.platform_data) {
|
||||
vga_data = client->dev.platform_data;
|
||||
rk29_monspec.io_enable_pin = vga_data->io_switch_pin;
|
||||
rk29_monspec.video_source = vga_data->video_source;
|
||||
rk29_monspec.property = vga_data->property;
|
||||
}
|
||||
else*/ {
|
||||
rk29_monspec.io_enable_pin = INVALID_GPIO;
|
||||
rk29_monspec.video_source = 0;
|
||||
rk29_monspec.property = 0;
|
||||
}
|
||||
if(rk29_monspec.io_enable_pin != INVALID_GPIO)
|
||||
{
|
||||
ret = gpio_request(rk29_monspec.io_enable_pin, NULL);
|
||||
if(ret != 0)
|
||||
{
|
||||
gpio_free(rk29_monspec.io_enable_pin);
|
||||
printk(">>>>>> vag enable gpio_request err \n ");
|
||||
return -1;
|
||||
}
|
||||
gpio_direction_output(rk29_monspec.io_enable_pin, GPIO_LOW);
|
||||
}
|
||||
INIT_LIST_HEAD(&rk29_monspec.modelist);
|
||||
//rk29_monspec.ddev = rk_display_device_register(&display_rk29, &client->dev, &rk29_monspec);
|
||||
//if(rk29_monspec.ddev == NULL)
|
||||
//{
|
||||
// printk("[%s] registor display error\n", __FUNCTION__);
|
||||
// return -1;
|
||||
//}
|
||||
//rk_display_device_enable(rk29_monspec.ddev);
|
||||
|
||||
if(rk29_monspec.enable)
|
||||
{
|
||||
#if 0
|
||||
struct fb_videomode *defaultmode, *mode;
|
||||
defaultmode = rk29fb_find_default_mode();
|
||||
if(defaultmode)
|
||||
mode = (struct fb_videomode *)fb_find_nearest_mode(defaultmode, &rk29_monspec.modelist);
|
||||
else
|
||||
mode = (struct fb_videomode *)&rk29_mode[0];
|
||||
|
||||
if(mode)
|
||||
{
|
||||
struct rk29fb_screen screen;
|
||||
rk29_mode2screen(mode, &screen);
|
||||
printk("%s: lcdc id = %d video_source = %d\n", __func__, screen.lcdc_id, rk29_monspec.video_source);
|
||||
FB_Switch_Screen(&screen, 1);
|
||||
rk29_monspec.mode = mode;
|
||||
}
|
||||
#else
|
||||
scaler_get_screens(rk29_monspec.i2c_client);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit vga_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct fb_monspecs *spec = &rk29_monspec.monspecs;
|
||||
struct list_head *modelist = &rk29_monspec.modelist;
|
||||
fb_destroy_modelist(modelist);
|
||||
if(spec->modedb)
|
||||
kfree(spec->modedb);
|
||||
rk_display_device_unregister(rk29_monspec.ddev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id vga_id[] = {
|
||||
{ "vga_i2c", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct i2c_driver vga_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "vga_i2c",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = &vga_i2c_probe,
|
||||
.remove = &vga_i2c_remove,
|
||||
.id_table = vga_id,
|
||||
};
|
||||
|
||||
static int __init rk29_vga_init(void)
|
||||
{
|
||||
return i2c_add_driver(&vga_i2c_driver);
|
||||
}
|
||||
|
||||
static void __exit rk29_vga_exit(void)
|
||||
{
|
||||
i2c_del_driver(&vga_i2c_driver);
|
||||
}
|
||||
module_init(rk29_vga_init);
|
||||
module_exit(rk29_vga_exit);
|
||||
|
||||
|
||||
/************ DEBUG ***********/
|
||||
void scaler_test_read_vga_edid(void)
|
||||
{
|
||||
scaler_get_screens(rk29_monspec.i2c_client);
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@
|
|||
#include <linux/cdev.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
struct scaler_platform_data;
|
||||
|
||||
struct display_edid {
|
||||
char *data;
|
||||
|
|
@ -80,25 +82,16 @@ struct scaler_chip_dev {
|
|||
char name[I2C_NAME_SIZE];
|
||||
struct i2c_client *client;
|
||||
|
||||
struct scaler_platform_data *pdata;
|
||||
|
||||
enum scaler_function_type func_type;
|
||||
|
||||
int int_gpio;
|
||||
int reset_gpio;
|
||||
int power_gpio;
|
||||
int status_gpio;
|
||||
char reg_size; //8bit = 1, 16bit = 2, 24bit = 3,32bit = 4.
|
||||
|
||||
struct list_head iports; //config all support input type by make menuconfig
|
||||
struct list_head oports; //config all support output type by make menuconfig
|
||||
struct list_head iports;
|
||||
struct list_head oports;
|
||||
enum scaler_input_type cur_in_type;
|
||||
int cur_inport_id;
|
||||
enum scaler_output_type cur_out_type;
|
||||
int cur_inport_id;
|
||||
int cur_outport_id;
|
||||
|
||||
//init hardware(gpio etc.)
|
||||
int (*init_hw)(void);
|
||||
int (*exit_hw)(void);
|
||||
|
||||
//enable chip to process image
|
||||
void (*start)(void);
|
||||
//disable chip to process image
|
||||
|
|
@ -120,9 +113,17 @@ struct scaler_chip_dev {
|
|||
struct scaler_platform_data {
|
||||
int int_gpio;
|
||||
int reset_gpio;
|
||||
int power_gpio;
|
||||
int status_gpio; //check chip if work on lower power mode or normal mode.
|
||||
|
||||
int power_gpio;
|
||||
int power_level;
|
||||
int vga5v_gpio;
|
||||
int vga5v_level;
|
||||
int ddc_sel_gpio;
|
||||
int ddc_sel_level; //ddc dev default select by defined the first input port in iports
|
||||
int vga_hsync_gpio; //detect vga-in v\hsync clk by gpio
|
||||
int vga_vsync_gpio;
|
||||
|
||||
char *firmware;
|
||||
//function type
|
||||
enum scaler_function_type func_type;
|
||||
|
|
@ -148,14 +149,20 @@ struct scaler_device {
|
|||
struct list_head chips;
|
||||
};
|
||||
|
||||
//scaler core
|
||||
int scaler_init_platform(struct scaler_platform_data *pdata);
|
||||
struct scaler_chip_dev *alloc_scaler_chip(void);
|
||||
//free chip memory and port memory
|
||||
void free_scaler_chip(struct scaler_chip_dev *chip);
|
||||
int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *pdata);
|
||||
//
|
||||
int register_scaler_chip(struct scaler_chip_dev *chip);
|
||||
int unregister_scaler_chip(struct scaler_chip_dev *chip);
|
||||
|
||||
//edid
|
||||
int scaler_switch_default_screen(void);
|
||||
struct fb_videmode *scaler_get_cmode(void);
|
||||
|
||||
//fs ioctl
|
||||
#define SCALER_IOCTL_MAGIC 'a'
|
||||
#define SCALER_IOCTL_POWER _IOW(SCALER_IOCTL_MAGIC, 0x00, char)
|
||||
#define SCALER_IOCTL_GET_CUR_INPUT _IOR(SCALER_IOCTL_MAGIC, 0x01, int)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user