CONFIG_MISC_DEVICES=y
CONFIG_UID_STAT=y
CONFIG_APANIC=y
+CONFIG_SCALER_DEVICE=y
+CONFIG_SCALER_TEST=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_LCDC_RK3188=y
CONFIG_LCDC0_RK3188=y
CONFIG_LCDC1_RK3188=y
-CONFIG_LCD_DS1006H=y
+CONFIG_LCD_E242868_1024X600=y
CONFIG_RK_HDMI=y
CONFIG_HDMI_CAT66121=y
CONFIG_RK_HDMI_CTL_CODEC=y
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_SDMMC_RK29=y
-CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD=y
# CONFIG_SDMMC1_RK29 is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
#include "../mach-rk30/board-rk3168-ds1006h-camera.c"
#include <plat/key.h>
+#include <linux/scaler-core.h>
static struct rk29_keys_button key_button[] = {
{
return 0;
}
-#if defined(CONFIG_LCDC0_RK3188)
-struct rk29fb_info lcdc0_screen_info = {
+#if defined(CONFIG_LCDC1_RK3188)
+struct rk29fb_info lcdc1_screen_info = {
.prop = EXTEND, //extend display device
.lcd_info = NULL,
.set_screen_info = hdmi_init_lcdc,
};
#endif
-#if defined(CONFIG_LCDC1_RK3188)
-struct rk29fb_info lcdc1_screen_info = {
+#if defined(CONFIG_LCDC0_RK3188)
+struct rk29fb_info lcdc0_screen_info = {
.prop = PRMRY, //primary display device
.io_init = rk_fb_io_init,
.io_disable = rk_fb_io_disable,
#include "../mach-rk30/board-pmu-tps65910.c"
#endif
+#if defined(CONFIG_SCALER_TEST)
+//the fisrt port is default
+struct scaler_output_port tst_oports[] ={
+ {
+ .led_gpio = INVALID_GPIO,
+ .type = SCALER_OUT_VGA,
+ },
+};
+
+//the fisrt port is default
+struct scaler_input_port tst_iports[] = {
+ {
+ //RK
+ .led_gpio = RK30_PIN0_PD4,
+ .type = SCALER_IN_VGA,
+ },
+ {
+ //pc
+ .led_gpio = RK30_PIN0_PD5,
+ .type = SCALER_IN_VGA,
+ },
+};
+
+struct scaler_platform_data test_data = {
+ .func_type = SCALER_FUNC_SWITCH,
+
+ .iports = tst_iports,
+ .iport_size = ARRAY_SIZE(tst_iports),
+ .oports = tst_oports,
+ .oport_size = ARRAY_SIZE(tst_oports),
+
+ .power_gpio = RK30_PIN2_PD7,
+};
+#endif
+
static struct i2c_board_info __initdata i2c1_info[] = {
+#if defined(CONFIG_SCALER_TEST)
+ {
+ .type = "aswitch",
+ .addr = 0x57,
+ .flags = 0,
+ .platform_data = &test_data,
+ },
+#endif
#if defined (CONFIG_REGULATOR_ACT8846)
{
.type = "act8846",
#ifdef CONFIG_I2C2_RK30
static struct i2c_board_info __initdata i2c2_info[] = {
+#if defined(CONFIG_SCALER_DEVICE)
+ {
+ .type = "vga_i2c",
+ .addr = 0x50,
+ .flags = 0,
+ },
+#endif
#if defined (CONFIG_CT36X_TS)
{
.type = CT36X_NAME,
source "drivers/misc/bp/Kconfig"
source "drivers/misc/rk2928_callpad_misc/Kconfig"
source "drivers/misc/3g_module/Kconfig"
+source "drivers/misc/scaler/Kconfig"
endif # MISC_DEVICES
obj-y += rk2928_callpad_misc/
obj-$(CONFIG_MODEM_SOUND) += modem_sound.o
obj-$(CONFIG_TCC_BT_DEV) += tcc_bt_dev.o
+obj-$(CONFIG_SCALER_DEVICE) += scaler/
--- /dev/null
+#
+# all auto modem control drivers configuration\r
+#
+
+menuconfig SCALER_DEVICE
+ bool "Scaler Device Support"
+ default n
+
+if SCALER_DEVICE
+source "drivers/misc/scaler/chips/Kconfig"
+endif
--- /dev/null
+#
+# Makefile for the display core.
+#
+
+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
--- /dev/null
+#
+#config tv5735 support inport type and output type
+#
+
+config SCALER_TV5735
+ bool "Support tv5735 chip"
+ default n
+
+config SCALER_TEST
+ bool "test chip"
+ default n
--- /dev/null
+obj-$(CONFIG_SCALER_TV5735) += tv5735.o
+obj-$(CONFIG_SCALER_TEST) += test.o
--- /dev/null
+/*\r
+ Copyright (c) 2010 by Rockchip.\r
+*/\r
+#include <linux/module.h>\r
+#include <linux/input.h>\r
+#include <linux/i2c.h>\r
+#include <linux/delay.h>\r
+#include <linux/kthread.h>\r
+#include <linux/sched.h>\r
+#include <linux/slab.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/irq.h>\r
+#include <linux/cdev.h>\r
+#include <asm/uaccess.h>\r
+#include <linux/version.h>\r
+#include <linux/gpio.h>\r
+#include <linux/io.h>\r
+#include <linux/regulator/consumer.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#include <linux/wakelock.h>\r
+#endif\r
+#include <linux/scaler-core.h>\r
+\r
+struct scaler_chip_dev *chip = NULL;\r
+extern char *scaler_input_name[];\r
+\r
+\r
+//enbale chip to process image\r
+static void set_cur_inport(void) \r
+{\r
+ struct scaler_input_port *iport = NULL;\r
+ \r
+ list_for_each_entry(iport, &chip->iports, next) {\r
+ if (iport->id == chip->cur_inport_id) {\r
+ gpio_set_value(iport->led_gpio, GPIO_HIGH);\r
+ }else {\r
+ gpio_set_value(iport->led_gpio, GPIO_LOW);\r
+ }\r
+ }\r
+\r
+ //pc\r
+ if (chip->cur_inport_id == 2)\r
+ gpio_set_value(RK30_PIN0_PB4, GPIO_LOW);\r
+ else\r
+ //rk\r
+ gpio_set_value(RK30_PIN0_PB4, GPIO_HIGH);\r
+}\r
+\r
+static int parse_cmd(unsigned int cmd, unsigned long arg)\r
+{\r
+ printk("test: parse scaler cmd %u\n",cmd);\r
+\r
+ switch (cmd) {\r
+ case SCALER_IOCTL_SET_CUR_INPUT:\r
+ set_cur_inport();\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int test_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
+{\r
+ struct scaler_platform_data *pdata = client->dev.platform_data;\r
+\r
+ if (!pdata) {\r
+ printk("%s: client private data not define\n", __func__);\r
+ return -1;\r
+ }\r
+\r
+ chip = alloc_scaler_chip();\r
+ if (!chip) {\r
+ printk("%s: alloc scaler chip memory failed.\n", __func__);\r
+ return -1;\r
+ }\r
+ chip->client = client;\r
+ memcpy((void *)chip->name, (void *)client->name, (strlen(client->name) + 1));\r
+ //implement parse cmd function\r
+ init_scaler_chip(chip, pdata);\r
+ chip->parse_cmd = parse_cmd;\r
+\r
+ //vga 5v en\r
+ if (!gpio_request(RK30_PIN3_PD7, NULL))\r
+ gpio_direction_output(RK30_PIN3_PD7, GPIO_HIGH); \r
+ else\r
+ printk("%s: request vga5ven power gpio failed\n", __func__);\r
+ msleep(20);\r
+\r
+ //power\r
+ if (!gpio_request(RK30_PIN2_PD7, NULL))\r
+ gpio_direction_output(RK30_PIN2_PD7, GPIO_HIGH); \r
+ else\r
+ printk("%s: request vga power gpio failed\n", __func__);\r
+ msleep(20);\r
+\r
+ //vga sel\r
+ if (!gpio_request(RK30_PIN0_PB4, NULL))\r
+ gpio_direction_output(RK30_PIN0_PB4, GPIO_HIGH); //rk output\r
+ else\r
+ printk("%s: request vga switch gpio failed\n", __func__);\r
+ msleep(20);\r
+\r
+ //\r
+ if (!gpio_request(RK30_PIN1_PD6, NULL))\r
+ gpio_direction_output(RK30_PIN1_PD6, GPIO_HIGH); \r
+ else\r
+ printk("%s: request XNN223_PWN gpio failed\n", __func__);\r
+ msleep(20);\r
+\r
+ //register\r
+ register_scaler_chip(chip);\r
+\r
+ return 0;\r
+}\r
+\r
+static int test_i2c_remove(struct i2c_client *client)\r
+{\r
+\r
+ printk("%s: \n", __func__);\r
+ unregister_scaler_chip(chip);\r
+ free_scaler_chip(chip);\r
+ chip = NULL;\r
+ return 0;\r
+}\r
+\r
+\r
+static const struct i2c_device_id test_i2c_id[] ={\r
+ {"aswitch", 0}, \r
+ {}\r
+};\r
+MODULE_DEVICE_TABLE(i2c, test_i2c_id);\r
+\r
+static struct i2c_driver test_i2c_driver = {\r
+ .driver = {\r
+ .name = "aswitch"\r
+ },\r
+ .probe = test_i2c_probe,\r
+ .remove = test_i2c_remove,\r
+ .id_table = test_i2c_id,\r
+};\r
+\r
+static int __init test_init(void)\r
+{\r
+ int ret = 0;\r
+ printk("%s: \n", __func__);\r
+\r
+ ret = i2c_add_driver(&test_i2c_driver);\r
+ if(ret < 0){\r
+ printk("%s, register i2c device, error\n", __func__);\r
+ return ret;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static void __exit test_exit(void)\r
+{\r
+ printk("%s: \n", __func__);\r
+}\r
+\r
+module_init(test_init);\r
+module_exit(test_exit);\r
+\r
--- /dev/null
+/*
+ *
+ * Copyright (C) 2012 Rockchip
+ *
+ *---------------------------------
+ * version 1.0 2012-9-13
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/version.h>
+#include <linux/pm_runtime.h>
+#include <asm/uaccess.h>
+#include <linux/scaler-core.h>
+
+#define SCALER_CORE_VERSION "v1.0.0"
+#define SCALER_DEV_NAME "scaler-ctrl"
+
+static DEFINE_MUTEX(mutex_chips);
+static DEFINE_MUTEX(mutex_ports);
+
+static struct scaler_device *sdev = NULL;
+static unsigned short chip_ids = 0; //<id only grow>只增不减
+static unsigned int port_ids = 0;
+extern int scaler_sysfs_create(struct scaler_device *sdev);
+extern int scaler_sysfs_remove(struct scaler_device *sdev);
+
+static const char const *scaler_output_name[] = {
+ "output type",
+ "LVDS",
+ "VGA",
+ "RGB",
+ "HDMI",
+ "DP",
+};
+
+const char const *scaler_input_name[] = {
+ "input tpye",
+ "VGA",
+ "RGB",
+ "HDMI",
+ "DP",
+ "DVI",
+ "YPBPR",
+ "YCBCR",
+ "MYDP",
+ "IDP",
+};
+
+static const char const *scaler_func_name[] ={
+ "This Scaler Function Type Is:",
+ "convertor",
+ "switch",
+ "full function",
+};
+
+static void scaler_led_on(int gpio)
+{
+ gpio_set_value(gpio, GPIO_HIGH);
+}
+static void scaler_led_off(int gpio)
+{
+ gpio_set_value(gpio, GPIO_LOW);
+}
+
+static void default_start(void)
+{
+}
+
+static void default_stop(void)
+{
+}
+
+static int default_read(unsigned short reg, int bytes, void *desc)
+{
+ return 0;
+}
+
+static int default_write(unsigned short reg, int bytes, void *desc)
+{
+ return 0;
+}
+
+static int default_parse_cmd(unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+//alloc chip dev memory and init default value
+struct scaler_chip_dev *alloc_scaler_chip(void)
+{
+ struct scaler_chip_dev *p = kzalloc(sizeof(struct scaler_chip_dev), GFP_KERNEL);
+ if (p) {
+ strcpy(p->name, "unknown");
+ //init default operation function
+ p->start = default_start;
+ p->stop = default_stop;
+ p->read = default_read;
+ p->write = default_write;
+ p->parse_cmd = default_parse_cmd;
+ //init list head
+ INIT_LIST_HEAD(&p->next);
+ INIT_LIST_HEAD(&p->oports);
+ INIT_LIST_HEAD(&p->iports);
+ }
+ return p;
+}
+
+int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *pdata)
+{
+ int i;
+ struct scaler_output_port *oport = NULL;
+ struct scaler_input_port *iport = NULL;
+
+ if (!chip || !pdata) {
+ printk("%s: chip or pdata is null.\n", __func__);
+ return -1;
+ }
+
+ //set scaler function type
+ if (pdata->func_type > SCALER_FUNC_INVALID &&
+ pdata->func_type < SCALER_FUNC_NUMS) {
+ chip->func_type = pdata->func_type;
+ }else {
+ printk("%s: not defined scaer function type\n", __func__);
+ chip->func_type = SCALER_FUNC_FULL;
+ }
+ printk("%s: %s %s\n", chip->name, scaler_func_name[0], scaler_func_name[chip->func_type]);
+
+ //set scaler support input type
+ 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__);
+ return -1;
+ }else {
+ iport->max_hres = 1920;
+ iport->max_vres = 1080;
+ iport->freq = 60;
+ //input port id
+ mutex_lock(&mutex_ports);
+ iport->id = ++port_ids;
+ mutex_unlock(&mutex_ports);
+ //input port type
+ iport->type = pdata->iports[i].type;
+ //the first input port is default
+ if (!chip->cur_inport_id) {
+ chip->cur_in_type = iport->type;
+ chip->cur_inport_id = iport->id;
+ printk("%s: default %s %s\n", chip->name, scaler_input_name[0], scaler_input_name[iport->type]);
+ }
+
+ //init and request input gpio of indicator lamp
+ if (pdata->iports[i].led_gpio > 0) {
+ iport->led_gpio = pdata->iports[i].led_gpio;
+ if (!gpio_request(iport->led_gpio, NULL)) {
+ gpio_direction_output(iport->led_gpio, GPIO_HIGH);
+ }else {
+ printk("%s: request %s<id,%d> gpio failed\n", chip->name,
+ scaler_input_name[pdata->iports[i].type], iport->id);
+ }
+ }
+
+ //add input of chip
+ list_add_tail(&iport->next, &chip->iports);
+ printk("%s: support %s %s<id,%d> led_gpio %d\n", chip->name, scaler_input_name[0],
+ scaler_input_name[pdata->iports[i].type], iport->id, iport->led_gpio);
+ }//if (!iport)
+ }//for()
+
+ //set scaler output type
+ 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__);
+ return -1;
+ }else {
+ oport->max_hres = 1920;
+ oport->max_vres = 1080;
+ oport->freq = 60;
+ //output port id
+ mutex_lock(&mutex_ports);
+ oport->id = ++port_ids;
+ mutex_unlock(&mutex_ports);
+ //output port type
+ oport->type = pdata->oports[i].type;
+ //the first output port is default
+ if (!chip->cur_outport_id) {
+ chip->cur_out_type = oport->type;
+ chip->cur_outport_id = oport->id;
+ printk("%s: default %s %s\n", chip->name, scaler_output_name[0], scaler_output_name[oport->type]);
+ }
+
+ //init and request output gpio of indicator lamp
+ if (pdata->oports[i].led_gpio > 0) {
+ oport->led_gpio = pdata->oports[i].led_gpio;
+ if (!gpio_request(oport->led_gpio, NULL)) {
+ gpio_direction_output(oport->led_gpio, GPIO_HIGH);
+ }else {
+ printk("%s: request %s<id,%d> gpio failed\n", chip->name, scaler_output_name[pdata->oports[i].type], oport->id);
+ }
+ }
+
+ list_add_tail(&oport->next, &chip->oports);
+ printk("%s: support %s %s<id,%d> led_gpio %d\n", chip->name, scaler_output_name[0],
+ scaler_output_name[pdata->oports[i].type], oport->id, oport->led_gpio);
+ }// if (!oport)
+ }//for()
+
+ return 0;
+}
+
+//free scaler chip memory
+void free_scaler_chip(struct scaler_chip_dev *chip)
+{
+ struct scaler_output_port *out = NULL;
+ struct scaler_input_port *in = NULL;
+ if (chip) {
+
+ list_for_each_entry(out, &chip->oports, next) {
+ kfree(out);
+ }
+
+ list_for_each_entry(in, &chip->iports, next) {
+ if (in->led_gpio > 0)
+ gpio_free(in->led_gpio);
+ kfree(in);
+ }
+
+ kfree(chip);
+ }
+}
+
+//register chip to scaler core
+int register_scaler_chip(struct scaler_chip_dev *chip)
+{
+ int res = -1;
+ struct scaler_input_port *in;
+ struct scaler_output_port *out;
+
+ if (chip && sdev) {
+ res = 0;
+
+ //start chip to process
+ chip->start();
+
+ //power on input indicator lamp
+ list_for_each_entry(in, &chip->iports, next){
+ if (in->id == chip->cur_inport_id)
+ scaler_led_on(in->led_gpio);
+ else
+ scaler_led_off(in->led_gpio);
+ }
+
+ //power on output indicator lamp
+ list_for_each_entry(out, &chip->oports, next){
+ if (out->id == chip->cur_outport_id)
+ scaler_led_on(out->led_gpio);
+ else
+ scaler_led_off(out->led_gpio);
+ }
+ //add chip to scaler core
+ mutex_lock(&mutex_chips);
+ 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);
+ }
+
+ return res;
+}
+
+//unregister chip to scaler core
+int unregister_scaler_chip(struct scaler_chip_dev *chip)
+{
+ int res = -1;
+ struct scaler_input_port *in;
+ struct scaler_output_port *out;
+
+ if (chip && sdev) {
+ res = 0;
+
+ chip->stop();
+
+ //power off input indicator lamp
+ list_for_each_entry(in, &chip->iports, next){
+ if (in->id == chip->cur_inport_id)
+ scaler_led_off(in->led_gpio);
+ }
+
+ //power off output indicator lamp
+ list_for_each_entry(out, &chip->oports, next){
+ if (out->id == chip->cur_outport_id)
+ scaler_led_off(out->led_gpio);
+ }
+
+ //del chip from scaler core
+ mutex_lock(&mutex_chips);
+ list_del(&chip->next);
+ mutex_unlock(&mutex_chips);
+ printk("%s: unregister scaler chip %s success.\n", __func__, chip->name);
+ }
+
+ return res;
+}
+
+/*** cdev operate ***/
+static int scaler_file_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int scaler_file_close(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static ssize_t scaler_file_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+static ssize_t scaler_file_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static long scaler_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#else
+static int scaler_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+ int iport_id;
+ struct scaler_chip_dev *chip = NULL;
+ struct scaler_input_port *iport = NULL;
+
+
+ switch(cmd) {
+ case 0:
+ printk("get cur input cmd %#x\n", SCALER_IOCTL_GET_CUR_INPUT);
+ printk("set cur input cmd %#x\n", SCALER_IOCTL_SET_CUR_INPUT);
+ break;
+ case SCALER_IOCTL_SET_CUR_INPUT:
+ //choose input channel;
+ copy_from_user(&iport_id, 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->parse_cmd(cmd, arg);
+ break;
+ }
+ }//list iports
+ }
+ }//list chips
+
+ break;
+ case SCALER_IOCTL_GET_CUR_INPUT:
+ list_for_each_entry(chip, &sdev->chips, next) {
+ iport_id = chip->cur_inport_id;
+ }//list chips
+ copy_to_user(arg, &iport_id, sizeof(int));
+ printk("current input port id %d\n", iport_id);
+ break;
+ default:
+ //default_parse_cmd(cmd, arg);
+ break;
+ }
+
+
+ return 0;
+}
+
+struct file_operations scaler_fops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+ .unlocked_ioctl =scaler_file_ioctl,
+#else
+ .ioctl =scaler_file_ioctl, //定义所有对scaler操作的cmd
+#endif
+ .read =scaler_file_read,
+ .write = scaler_file_write,
+ .open = scaler_file_open,
+ .release = scaler_file_close,
+};
+
+//注册一个scaler的字符设备 供别的设备操作scaler
+static int scaler_register_chrdev(void)
+{
+ int ret = 0;
+
+ ret = alloc_chrdev_region(&sdev->devno, 0, 1, SCALER_DEV_NAME);
+ if(ret != 0){
+ printk("%s, can't allocate chrdev devno.\n", __func__);
+ return ret;
+ }else {
+ printk("%s: Scaler chrdev devno(%d,%d).\n", __func__, MAJOR(sdev->devno), MINOR(sdev->devno));
+ }
+
+ // initialize character device driver
+ sdev->cdev = cdev_alloc();
+ if (!sdev->cdev) {
+ printk("%s: cdev alloc failed.\n", __func__);
+ goto err1;
+ }
+
+ cdev_init(sdev->cdev, &scaler_fops);
+ sdev->cdev->owner = THIS_MODULE;
+ ret = cdev_add(sdev->cdev, sdev->devno, 1);
+ if(ret < 0){
+ printk("%s, add character device error, ret %d\n", __func__, ret);
+ goto err2;
+ }
+
+ sdev->class = class_create(THIS_MODULE, "scaler");
+ if(!sdev->class){
+ printk("%s, create class failed\n", __func__);
+ goto err3;
+ }
+
+ sdev->dev = device_create(sdev->class, NULL, sdev->devno, sdev, SCALER_DEV_NAME);
+ if (!sdev->dev) {
+ printk("%s: create device failed\n", __func__);
+ goto err4;
+ }
+
+
+ return 0;
+
+err4:
+ class_destroy(sdev->class);
+err3:
+ cdev_del(sdev->cdev);
+err2:
+ kfree(sdev->cdev);
+err1:
+ unregister_chrdev_region(sdev->devno, 1);
+
+ return -1;
+}
+
+static void scaler_unregister_chrdev(void)
+{
+ cdev_del(sdev->cdev);
+ unregister_chrdev_region(sdev->devno, 1);
+ kfree(sdev->cdev);
+ device_destroy(sdev->class, sdev->devno);
+ class_destroy(sdev->class);
+}
+
+static int __init rk_scaler_init(void)
+{
+ printk("%s: SCALER CORE VERSION: %s\n", __func__, SCALER_CORE_VERSION);
+
+ sdev = kzalloc(sizeof(struct scaler_device), GFP_KERNEL);
+ if (!sdev) {
+ printk("%s: malloc scaler devices failed.\n", __func__);
+ return -1;
+ }else {
+ INIT_LIST_HEAD(&sdev->chips);
+ }
+
+ if (scaler_register_chrdev() < 0) {
+ printk("%s: scaler register chrdev failed.\n", __func__);
+ goto err1;
+ }
+
+ if (scaler_sysfs_create(sdev) < 0) {
+ printk("%s: scaler sysfs create faild.\n", __func__);
+ goto err2;
+ }
+
+ return 0;
+err2:
+ scaler_unregister_chrdev();
+err1:
+ kfree(sdev);
+
+ return -1;
+}
+
+static void __exit rk_scaler_exit(void)
+{
+ printk("%s\n", __func__);
+ scaler_sysfs_remove(sdev);
+ scaler_unregister_chrdev();
+ kfree(sdev);
+}
+
+subsys_initcall(rk_scaler_init);
+module_exit(rk_scaler_exit);
+
+MODULE_AUTHOR("linjh <linjh@rock-chips.com>");
+MODULE_DESCRIPTION("RK Scaler Device Driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/scaler-core.h>
+#include <linux/slab.h>
+extern const char const *scaler_input_name[];
+static ssize_t scaler_iport_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int iports = 0;
+ struct scaler_chip_dev *chip = NULL;
+ struct scaler_input_port *in = NULL;
+ struct scaler_device *sdev = dev_get_drvdata(dev);
+
+ list_for_each_entry(chip, &sdev->chips, next) {
+
+ list_for_each_entry(in, &chip->iports, next) {
+ iports++;
+ printk("id = %d type = %s gpio = %d\n", in->id,
+ scaler_input_name[in->type], in->led_gpio);
+ }
+ }
+
+ 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_device *sdev = dev_get_drvdata(dev);
+
+ list_for_each_entry(chip, &sdev->chips, next) {
+
+ printk("id = %d type = %s\n", chip->cur_inport_id,
+ scaler_input_name[chip->cur_in_type]);
+ }
+ return 0;
+}
+static DEVICE_ATTR(cur_iport, 0664, scaler_cur_iport_show, NULL);
+
+static ssize_t scaler_oport_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ printk("%s: scaler sysfs test.\n", __func__);
+ 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 struct attribute *scaler_attributes[] = {
+ &dev_attr_iports.attr,
+ &dev_attr_cur_iport.attr,
+ &dev_attr_oports.attr,
+ NULL
+};
+
+static mode_t scaler_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ mode_t mode = attr->mode;
+
+ return mode;
+}
+
+static const struct attribute_group scaler_attr_group = {
+ .is_visible = scaler_attr_is_visible,
+ .attrs = scaler_attributes,
+};
+
+
+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;
+}
+
+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;
+}
--- /dev/null
+#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];
+ //display_add_videomode(mode, modelist);
+ 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) {
+#if 1
+ /* 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
+ /* get preferred timing */
+ if (specs->misc & FB_MISC_1ST_DETAIL) {
+
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+ modedb = &specs->modedb[i];
+ break;
+ }
+ }
+ } else {
+ /* otherwise, get first mode in database */
+ modedb = &specs->modedb[0];
+ }
+#endif
+ }
+ 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;
+}
+
+/*
+ * 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;
+ }
+}
+
+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_HDMI;
+ screen->face = OUT_P888;
+
+ /* Screen size */
+ screen->x_res = modedb->xres;
+ screen->y_res = modedb->yres;
+// screen->xpos = 0;
+// screen->ypos = 0;
+ /* 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;
+}
+
+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)
+{
+ printk("%s: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n", __func__);
+ 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,
+};
+
+static int vga_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
+{
+ int ret;
+ //struct rkdisplay_platform_data *vga_data;
+ printk("%s: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n", __func__);
+
+ memset(&rk29_monspec, 0, sizeof(struct rk29_monspecs));
+ rk29_monspec.i2c_client = client;
+ rk29_monspec.enable = 0;
+
+ /*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(1)
+ {
+ 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];
+printk("%s: xres,yres(%d, %d)\n=============================\n\n\n", __func__, mode->xres, mode->yres);
+ 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;
+ }
+ }
+ 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)
+{
+ printk("%s: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n", __func__);
+ 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);
--- /dev/null
+#ifndef __SCALER_CORE_H__
+#define __SCALER_CORE_H__
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/cdev.h>
+#include <linux/file.h>
+#include <linux/list.h>
+
+
+struct display_edid {
+ char *data;
+ char *ext_data;
+};
+
+enum scaler_output_type {
+ SCALER_OUT_INVALID = 0,
+ SCALER_OUT_LVDS,
+ SCALER_OUT_VGA,
+ SCALER_OUT_RGB,
+ SCALER_OUT_HDMI,
+ SCALER_OUT_DP,
+ SCALER_OUT_NUMS,
+};
+
+enum scaler_input_type {
+ SCALER_IN_INVALID = 0,
+ SCALER_IN_VGA,
+ SCALER_IN_RGB,
+ SCALER_IN_HDMI,
+ SCALER_IN_DP,
+ SCALER_IN_DVI,
+ SCALER_IN_YPBPR,
+ SCALER_IN_YCBCR,
+ SCALER_IN_MYDP,
+ SCALER_IN_IDP,
+ SCALER_IN_NUMS,
+};
+
+enum scaler_bus_type {
+ SCALER_BUS_TYPE_INVALID = 0,
+ SCALER_BUS_TYPE_UART,
+ SCALER_BUS_TYPE_I2C,
+ SCALER_BUS_TYPE_SPI,
+ SCALER_BUS_TYPE_NUMS,
+};
+
+/*
+ * the function of scaler, for example convertor or switch
+*/
+enum scaler_function_type {
+ SCALER_FUNC_INVALID = 0,
+ SCALER_FUNC_CONVERTOR, //转换器
+ SCALER_FUNC_SWITCH, //切换开关多选一输出
+ SCALER_FUNC_FULL, //全功能
+ SCALER_FUNC_NUMS,
+};
+
+struct scaler_output_port {
+ int id;
+ int max_hres;
+ int max_vres;
+ int freq;
+ int led_gpio; //working led
+ enum scaler_output_type type;
+ struct list_head next;
+};
+
+struct scaler_input_port {
+ int id;
+ int max_hres;
+ int max_vres;
+ int freq; //HZ
+ int led_gpio; //working led
+ enum scaler_input_type type;
+ struct list_head next;
+};
+
+struct scaler_chip_dev {
+ char id;
+ char name[I2C_NAME_SIZE];
+ struct i2c_client *client;
+
+ 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
+ enum scaler_input_type cur_in_type;
+ int cur_inport_id;
+ enum scaler_output_type cur_out_type;
+ 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
+ void (*stop)(void);
+ void (*reset)(char active);
+ void (*suspend)(void);
+ void (*resume)(void);
+
+ //
+ int (*read)(unsigned short reg, int bytes, void *dest);
+ int (*write)(unsigned short reg, int bytes, void *src);
+ int (*parse_cmd)(unsigned int cmd, unsigned long arg);
+ int (*update_firmware)(void *data);
+
+ //scaler chip dev list
+ struct list_head next;
+};
+
+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.
+
+ char *firmware;
+ //function type
+ enum scaler_function_type func_type;
+
+ //config in and out
+ struct scaler_input_port *iports;
+ struct scaler_output_port *oports;
+ int iport_size;
+ int oport_size;
+
+ int (*init_hw)(void);
+ int (*exit_hw)(void);
+};
+
+struct scaler_device {
+ struct class *class;
+ struct device *dev;
+ struct cdev *cdev;
+ dev_t devno;
+
+ struct display_edid edid;
+
+ struct list_head chips;
+};
+
+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);
+
+#define SCALER_IOCTL_MAGIC 's'
+#define SCALER_IOCTL_POWER _IOW(SCALER_IOCTL_MAGIC, 0x00, char)
+#define SCALER_IOCTL_GET_CUR_INPUT _IOR(SCALER_IOCTL_MAGIC, 0x01, int)
+#define SCALER_IOCTL_SET_CUR_INPUT _IOW(SCALER_IOCTL_MAGIC, 0x02, int)
+
+#endif