diff options
author | Srikant Patnaik | 2015-01-11 20:10:08 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 21:00:00 +0530 |
commit | 63058268f9ab1c96396d3d138aefc3f7b0f72869 (patch) | |
tree | 38b41e86beb0dd25e622e0ef15d62c7a6a2c64bc /drivers/video/wmt/devices/cs8556.c | |
parent | ddd6804ba90290b66ebff05b99752fcdd75fec45 (diff) | |
download | FOSSEE-netbook-kernel-source-63058268f9ab1c96396d3d138aefc3f7b0f72869.tar.gz FOSSEE-netbook-kernel-source-63058268f9ab1c96396d3d138aefc3f7b0f72869.tar.bz2 FOSSEE-netbook-kernel-source-63058268f9ab1c96396d3d138aefc3f7b0f72869.zip |
Fix white screen issue during bootup
Signed-off-by: Manish Patel <manish.patel@xzadium.com>
Diffstat (limited to 'drivers/video/wmt/devices/cs8556.c')
-rw-r--r--[-rwxr-xr-x] | drivers/video/wmt/devices/cs8556.c | 1244 |
1 files changed, 617 insertions, 627 deletions
diff --git a/drivers/video/wmt/devices/cs8556.c b/drivers/video/wmt/devices/cs8556.c index 72097685..c44fb336 100755..100644 --- a/drivers/video/wmt/devices/cs8556.c +++ b/drivers/video/wmt/devices/cs8556.c @@ -1,627 +1,617 @@ -/*++ - * linux/drivers/video/wmt/cs8556.c - * WonderMedia video post processor (VPP) driver - * - * Copyright c 2013 WonderMedia Technologies, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ -/********************************************************************* -* REVISON HISTORY -* -* VERSION | DATE | AUTHORS | DESCRIPTION -* 1.0 | 2013/08/24 | Howay Huo | First Release -**********************************************************************/ - -#define CS8556_C -/* #define DEBUG */ -/*----------------------- DEPENDENCE -----------------------------------------*/ -#include <linux/i2c.h> -#include <mach/hardware.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <mach/wmt_iomux.h> -#include "../vout.h" - -/*----------------------- PRIVATE MACRO --------------------------------------*/ -/* #define VT1632_XXXX xxxx *//*Example*/ - - -/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ -/* #define VT1632_XXXX 1 *//*Example*/ -#define CS8556_ADDR 0x3d -#define CS8556_NAME "CS8556" - -/*----------------------- PRIVATE TYPE --------------------------------------*/ -/* typedef xxxx vt1632_xxx_t; *//*Example*/ -struct avdetect_gpio_t { - unsigned int flag; - unsigned int gpiono; - unsigned int act; -}; - -/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h -------------*/ -/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ -/* int vt1632_xxx; *//*Example*/ -static int s_cs8556_ready; -static int s_cs8556_init; -static struct i2c_client *s_cs8556_client; -static enum vout_tvformat_t s_tvformat = TV_MAX; -static int s_irq_init; -static struct avdetect_gpio_t s_avdetect_gpio = {0, WMT_PIN_GP0_GPIO5, 1}; - -static unsigned char s_CS8556_Original_Offset0[] = { - 0xF0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, - 0x80, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static unsigned char s_RGB888_To_PAL_Offset0[] = { - 0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5F, 0x03, 0x3F, 0x00, 0x7D, 0x00, 0x53, 0x03, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x02, 0x04, 0x00, 0x2E, 0x00, 0x62, 0x02, - 0x00, 0x00, 0x84, 0x00, 0x2B, 0x00, 0x36, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBF, 0x06, 0x7F, 0x00, 0xFE, 0x00, 0xA4, 0x06, - 0x00, 0x00, 0x2D, 0x11, 0x3C, 0x01, 0x3A, 0x01, - 0x70, 0x02, 0x04, 0x00, 0x12, 0x00, 0x34, 0x01, - 0x00, 0x00, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x41, 0x18, 0x09, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x24, 0x1A, 0x00, 0x01, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x01, 0xA4, 0x06, 0x0B, 0x00, 0x07, 0x01, - 0xF0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x01 -}; - -static unsigned char s_RGB888_To_NTSC_Offset0[] = { - 0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x59, 0x03, 0x3D, 0x00, 0x7E, 0x00, 0x49, 0x03, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x02, 0x05, 0x00, 0x21, 0x00, 0x03, 0x02, - 0x00, 0x00, 0x7A, 0x00, 0x23, 0x00, 0x16, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xB3, 0x06, 0x7F, 0x00, 0x00, 0x01, 0xA4, 0x06, - 0x00, 0x00, 0x05, 0x50, 0x00, 0x01, 0x07, 0x01, - 0x0C, 0x02, 0x02, 0x00, 0x12, 0x00, 0x07, 0x01, - 0x00, 0x00, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x41, 0x18, 0x09, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x24, 0x1A, 0x00, 0x01, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x01, 0xA4, 0x06, 0x0B, 0x00, 0x07, 0x01, - 0xF0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 -}; - -/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ -/* void vt1632_xxx(void); *//*Example*/ -static int I2CMultiPageRead(unsigned char maddr, unsigned char page, - unsigned char saddr, int number, unsigned char *value) -{ - int ret; - unsigned char wbuf[2]; - struct i2c_msg rd[2]; - - wbuf[0] = page; - wbuf[1] = saddr; - - rd[0].addr = maddr; - rd[0].flags = 0; - rd[0].len = 2; - rd[0].buf = wbuf; - - rd[1].addr = maddr; - rd[1].flags = I2C_M_RD; - rd[1].len = number; - rd[1].buf = value; - - ret = i2c_transfer(s_cs8556_client->adapter, rd, ARRAY_SIZE(rd)); - - if (ret != ARRAY_SIZE(rd)) { - DBG_ERR("fail\n"); - return -1; - } - - return 0; -} - -static int I2CMultiPageWrite(unsigned char maddr, unsigned char page, - unsigned char saddr, int number, unsigned char *value) -{ - int ret; - unsigned char *pbuf; - struct i2c_msg wr[1]; - - pbuf = kmalloc(number + 2, GFP_KERNEL); - if (!pbuf) { - DBG_ERR("alloc memory fail\n"); - return -1; - } - - *pbuf = page; - *(pbuf + 1) = saddr; - - memcpy(pbuf + 2, value, number); - - wr[0].addr = maddr; - wr[0].flags = 0; - wr[0].len = number + 2; - wr[0].buf = pbuf; - - ret = i2c_transfer(s_cs8556_client->adapter, wr, ARRAY_SIZE(wr)); - - if (ret != ARRAY_SIZE(wr)) { - DBG_ERR("fail\n"); - kfree(pbuf); - return -1; - } - - kfree(pbuf); - return 0 ; -} - -/************************ i2c device struct definition ************************/ -static int __devinit cs8556_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - DBGMSG("cs8556_i2c_probe\n"); - - return 0; -} - -static int __devexit cs8556_i2c_remove(struct i2c_client *client) -{ - DBGMSG("cs8556_i2c_remove\n"); - - return 0; -} - - -static const struct i2c_device_id cs8556_i2c_id[] = { - {CS8556_NAME, 0}, - { }, -}; -MODULE_DEVICE_TABLE(i2c, cs8556_i2c_id); - -static struct i2c_board_info __initdata cs8556_i2c_board_info[] = { - { - I2C_BOARD_INFO(CS8556_NAME, CS8556_ADDR), - }, -}; - -static struct i2c_driver cs8556_i2c_driver = { - .driver = { - .name = CS8556_NAME, - .owner = THIS_MODULE, - }, - .probe = cs8556_i2c_probe, - .remove = __devexit_p(cs8556_i2c_remove), - .id_table = cs8556_i2c_id, -}; - -/*----------------------- Function Body --------------------------------------*/ -static void avdetect_irq_enable(void) -{ - wmt_gpio_unmask_irq(s_avdetect_gpio.gpiono); -} - -static void avdetect_irq_disable(void) -{ - wmt_gpio_mask_irq(s_avdetect_gpio.gpiono); -} - -int avdetect_irq_hw_init(int resume) -{ - int ret; - - if (!resume) { - ret = gpio_request(s_avdetect_gpio.gpiono, - "avdetect irq"); /* enable gpio */ - if (ret < 0) { - DBG_ERR("gpio(%d) request fail for avdetect irq\n", - s_avdetect_gpio.gpiono); - return ret; - } - } else - gpio_re_enabled(s_avdetect_gpio.gpiono); /* re-enable gpio */ - - gpio_direction_input(s_avdetect_gpio.gpiono); /* gpio input */ - - /* enable pull and pull-up */ - wmt_gpio_setpull(s_avdetect_gpio.gpiono, WMT_GPIO_PULL_UP); - - /* disable interrupt */ - wmt_gpio_mask_irq(s_avdetect_gpio.gpiono); - - /* rise edge and clear interrupt */ - wmt_gpio_set_irq_type(s_avdetect_gpio.gpiono, IRQ_TYPE_EDGE_BOTH); - - return 0; -} - -/* -static void avdetect_irq_hw_free(void) -{ - gpio_free(AVDETECT_IRQ_PIN); - -} -*/ - -static irqreturn_t avdetect_irq_handler(int irq, void *dev_id) -{ - /* DPRINT("avdetect_irq_handler\n"); */ - - if (!gpio_irqstatus(s_avdetect_gpio.gpiono)) - return IRQ_NONE; - - wmt_gpio_ack_irq(s_avdetect_gpio.gpiono); /* clear interrupt */ - - /* DPRINT("cvbs hotplug interrupt\n"); */ - if (!is_gpio_irqenable(s_avdetect_gpio.gpiono)) { - /* pr_err("avdetect irq is disabled\n"); */ - return IRQ_HANDLED; - } else - return IRQ_WAKE_THREAD; -} - -static irqreturn_t avdetect_irq_thread(int irq, void *dev) -{ - /* DPRINT(cvbs_hotplug_irq_thread\n"); */ - - if (s_avdetect_gpio.act == 1) { - if (gpio_get_value(s_avdetect_gpio.gpiono)) - DPRINT("av plug in\n"); - else - DPRINT("av plug out\n"); - } else { - if (gpio_get_value(s_avdetect_gpio.gpiono)) - DPRINT("av plug out\n"); - else - DPRINT("av plug in\n"); - } - - return IRQ_HANDLED; -} - -int cs8556_check_plugin(int hotplug) -{ - return 1; -} - -int cs8556_init(struct vout_t *vo) -{ - int ret; - char buf[40] = {0}; - int varlen = 40; - int no = 1; /* default i2c1 */ - int num; - unsigned char rbuf[256] = {0}; - struct i2c_adapter *adapter = NULL; - - DPRINT("cs8556_init\n"); - - if (s_tvformat == TV_MAX) { - if (wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) { - if (!strnicmp(buf, "PAL", 3)) - s_tvformat = TV_PAL; - else if (!strnicmp(buf, "NTSC", 4)) - s_tvformat = TV_NTSC; - else - s_tvformat = TV_UNDEFINED; - } else - s_tvformat = TV_UNDEFINED; - } - - if (s_tvformat == TV_UNDEFINED) - goto err0; - - if (!s_cs8556_init) { - if (wmt_getsyspara("wmt.cs8556.i2c", buf, &varlen) == 0) { - if (strlen(buf) > 0) - no = buf[0] - '0'; - } - - adapter = i2c_get_adapter(no); - if (adapter == NULL) { - DBG_ERR("Can't get i2c adapter,client address error\n"); - goto err0; - } - - s_cs8556_client = - i2c_new_device(adapter, cs8556_i2c_board_info); - if (s_cs8556_client == NULL) { - DBG_ERR("allocate i2c client failed\n"); - goto err0; - } - - i2c_put_adapter(adapter); - - ret = i2c_add_driver(&cs8556_i2c_driver); - if (ret != 0) { - DBG_ERR("Failed register CS8556 I2C driver: %d\n", ret); - goto err1; - } - - if (wmt_getsyspara("wmt.io.avdetect", buf, &varlen) == 0) { - num = sscanf(buf, "%d:%d:%d", &s_avdetect_gpio.flag, - &s_avdetect_gpio.gpiono, &s_avdetect_gpio.act); - - if (num != 3) - DBG_ERR("wmt.io.avdetect err. num = %d\n", num); - else { - if (s_avdetect_gpio.gpiono > 19) - DBG_ERR("invalid avdetect gpio : %d\n", - s_avdetect_gpio.gpiono); - else { - ret = avdetect_irq_hw_init(0); - if (!ret) { - ret = request_threaded_irq( - IRQ_GPIO, - avdetect_irq_handler, - avdetect_irq_thread, - IRQF_SHARED, - CS8556_NAME, - s_cs8556_client); - - if (ret) - DBG_ERR("irq req %d\n", - ret); - else { - s_irq_init = 1; - DPRINT("avdetect irq"); - DPRINT("req success\n"); - } - } - } - } - } - - s_cs8556_init = 1; - } else { - if (s_irq_init) - avdetect_irq_hw_init(1); - } - - ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf); - if (ret) { - DBG_ERR("I2C address 0x%02X is not found\n", CS8556_ADDR); - goto err0; - } - - switch (s_tvformat) { - case TV_PAL: - ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, - s_RGB888_To_PAL_Offset0); - if (ret) { - DBG_ERR("PAL init fail\n"); - goto err0; - } - break; - case TV_NTSC: - ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, - s_RGB888_To_NTSC_Offset0); - if (ret) { - DBG_ERR("NTSC init fail\n"); - goto err0; - } - break; - default: - goto err0; - break; - } - - if (s_irq_init) - avdetect_irq_enable(); - - s_cs8556_ready = 1; - - return 0; -#if 0 -err3: - cvbs_hotplug_irq_disable(); - free_irq(IRQ_GPIO, s_cs8556_client); - cvbs_hotplug_irq_hw_free(); -err2: - i2c_del_driver(&cs8556_i2c_driver); -#endif -err1: - i2c_unregister_device(s_cs8556_client); -err0: - s_cs8556_ready = 0; - return -1; -} - -static int cs8556_set_mode(unsigned int *option) -{ - if (!s_cs8556_ready) - return -1; - - return 0; -} - -static void cs8556_set_power_down(int enable) -{ - int ret; - unsigned char rbuf[256] = {0}; - - if (!s_cs8556_ready) - return; - - DBGMSG("cs8556_set_power_down(%d)\n", enable); - - if (enable) { - ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 5, - s_CS8556_Original_Offset0); - if (ret) - DBG_ERR("I2C write Original_Offset0 fail\n"); - else { - if (s_irq_init) - avdetect_irq_disable(); - } - } else { - ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf); - if (ret) { - DBG_ERR("I2C read Offset0 fail\n"); - return; - } - - switch (s_tvformat) { - case TV_PAL: - if (memcmp(rbuf, s_RGB888_To_PAL_Offset0, 0x50) != 0) { - ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, - 0x00, 256, s_RGB888_To_PAL_Offset0); - if (ret) - DBG_ERR("I2C write PAL_Offset0 fail\n"); - } - break; - case TV_NTSC: - if (memcmp(rbuf, s_RGB888_To_NTSC_Offset0, 0x50) != 0) { - ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, - 0x00, 256, s_RGB888_To_NTSC_Offset0); - if (ret) - DBG_ERR("I2C wr NTSC_Offset0 fail\n"); - } - break; - default: - break; - } - } -} - -static int cs8556_config(struct vout_info_t *info) -{ - return 0; -} - -static int cs8556_get_edid(char *buf) -{ - return -1; -} - -/* -static int cs8556_interrupt(void) -{ - return cs8556_check_plugin(1); -} -*/ - -void cs8556_read(void) -{ - int i, ret; - unsigned char rbuf[256] = {0}; - - ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf); - if (!ret) { - DPRINT("CS8556 Read offset0 data as follows:\n"); - for (i = 0; i < 256;) { - DPRINT("0x%02X,", rbuf[i]); - if ((++i) % 16 == 0) - DPRINT("\n"); - } - } -} - -int cvbs_is_ready(void) -{ - return s_cs8556_ready; -} - -/*----------------------- vout device plugin ---------------------------------*/ -struct vout_dev_t cs8556_vout_dev_ops = { - .name = CS8556_NAME, - .mode = VOUT_INF_DVI, - - .init = cs8556_init, - .set_power_down = cs8556_set_power_down, - .set_mode = cs8556_set_mode, - .config = cs8556_config, - .check_plugin = cs8556_check_plugin, - .get_edid = cs8556_get_edid, -/* .interrupt = cs8556_interrupt, */ -}; - -int cs8556_module_init(void) -{ - vout_device_register(&cs8556_vout_dev_ops); - return 0; -} /* End of cs8556_module_init */ -module_init(cs8556_module_init); -/*--------------------End of Function Body -----------------------------------*/ -#undef CS8556_C +/*++
+ * linux/drivers/video/wmt/cs8556.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013 WonderMedia Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+/********************************************************************************
+* REVISON HISTORY
+*
+* VERSION | DATE | AUTHORS | DESCRIPTION
+* 1.0 | 2013/08/24 | Howay Huo | First Release
+*******************************************************************************/
+
+#define CS8556_C
+// #define DEBUG
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include <linux/i2c.h>
+#include <mach/hardware.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include "../vout.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define VT1632_XXXX xxxx *//*Example*/
+//#define CONFIG_CS8556_INTERRUPT
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VT1632_XXXX 1 *//*Example*/
+#define CS8556_ADDR 0x3d
+#define CS8556_NAME "CS8556"
+
+/*----------------------- PRIVATE TYPE --------------------------------------*/
+/* typedef xxxx vt1632_xxx_t; *//*Example*/
+typedef struct {
+ unsigned int flag;
+ unsigned int gpiono;
+ unsigned int act;
+}avdetect_gpio_t;
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int vt1632_xxx; *//*Example*/
+static int s_cs8556_ready;
+static int s_cs8556_init;
+static struct i2c_client *s_cs8556_client;
+static int s_irq_init;
+static avdetect_gpio_t s_avdetect_gpio = {0, WMT_PIN_GP0_GPIO5, 1};
+
+static unsigned char s_CS8556_Original_Offset0[]={
+ 0xF0,0x7F,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x02,0x01,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static unsigned char s_RGB888_To_PAL_Offset0[]={
+ 0x01,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5F,0x03,0x3F,0x00,0x7D,0x00,0x53,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x70,0x02,0x04,0x00,0x2E,0x00,0x62,0x02,0x00,0x00,0x84,0x00,0x2B,0x00,0x36,0x00,
+ 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xBF,0x06,0x7F,0x00,0xFE,0x00,0xA4,0x06,0x00,0x00,0x2D,0x11,0x3C,0x01,0x3A,0x01,
+ 0x70,0x02,0x04,0x00,0x12,0x00,0x34,0x01,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,
+ 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x41,0x18,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,
+ 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+ 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x24,0x1A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x01,0xA4,0x06,0x0B,0x00,0x07,0x01,0xF0,0x00,0x00,0x00,0x00,0x04,0x40,0x01
+};
+
+static unsigned char s_RGB888_To_NTSC_Offset0[]={
+ 0x01,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x59,0x03,0x3D,0x00,0x7E,0x00,0x49,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x0C,0x02,0x05,0x00,0x21,0x00,0x03,0x02,0x00,0x00,0x7A,0x00,0x23,0x00,0x16,0x00,
+ 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xB3,0x06,0x7F,0x00,0x00,0x01,0xA4,0x06,0x00,0x00,0x05,0x50,0x00,0x01,0x07,0x01,
+ 0x0C,0x02,0x02,0x00,0x12,0x00,0x07,0x01,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,
+ 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x41,0x18,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,
+ 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+ 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x24,0x1A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x01,0xA4,0x06,0x0B,0x00,0x07,0x01,0xF0,0x00,0x00,0x00,0x00,0x04,0x00,0x00
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vt1632_xxx(void); *//*Example*/
+static int I2CMultiPageRead(unsigned char maddr, unsigned char page, unsigned char saddr, int number, unsigned char *value)
+{
+ int ret;
+ unsigned char wbuf[2];
+ struct i2c_msg rd[2];
+
+ wbuf[0] = page;
+ wbuf[1] = saddr;
+
+ rd[0].addr = maddr;
+ rd[0].flags = 0;
+ rd[0].len = 2;
+ rd[0].buf = wbuf;
+
+ rd[1].addr = maddr;
+ rd[1].flags = I2C_M_RD;
+ rd[1].len = number;
+ rd[1].buf = value;
+
+ ret = i2c_transfer(s_cs8556_client->adapter, rd, ARRAY_SIZE(rd));
+
+ if (ret != ARRAY_SIZE(rd)) {
+ DBG_ERR("fail\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int I2CMultiPageWrite(unsigned char maddr, unsigned char page, unsigned char saddr, int number, unsigned char *value)
+{
+ int ret;
+ unsigned char *pbuf;
+ struct i2c_msg wr[1];
+
+ pbuf = kmalloc(number + 2, GFP_KERNEL);
+ if(!pbuf) {
+ DBG_ERR("alloc memory fail\n");
+ return -1;
+ }
+
+ *pbuf = page;
+ *(pbuf + 1) = saddr;
+
+ memcpy(pbuf + 2, value, number);
+
+ wr[0].addr = maddr;
+ wr[0].flags = 0;
+ wr[0].len = number + 2;
+ wr[0].buf = pbuf;
+
+ ret = i2c_transfer(s_cs8556_client->adapter, wr, ARRAY_SIZE(wr));
+
+ if (ret != ARRAY_SIZE(wr)) {
+ DBG_ERR("fail\n");
+ kfree(pbuf);
+ return -1;
+ }
+
+ kfree(pbuf);
+ return 0 ;
+}
+
+/************************** i2c device struct definition **************************/
+static int __devinit cs8556_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ DBGMSG("cs8556_i2c_probe\n");
+
+ return 0;
+}
+
+static int __devexit cs8556_i2c_remove(struct i2c_client *client)
+{
+ DBGMSG("cs8556_i2c_remove\n");
+
+ return 0;
+}
+
+
+static const struct i2c_device_id cs8556_i2c_id[] = {
+ {CS8556_NAME, 0},
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, cs8556_i2c_id);
+
+static struct i2c_board_info __initdata cs8556_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO(CS8556_NAME, CS8556_ADDR),
+ },
+};
+
+static struct i2c_driver cs8556_i2c_driver = {
+ .driver = {
+ .name = CS8556_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = cs8556_i2c_probe,
+ .remove = __devexit_p(cs8556_i2c_remove),
+ .id_table = cs8556_i2c_id,
+};
+
+/*----------------------- Function Body --------------------------------------*/
+static void avdetect_irq_enable(void)
+{
+ wmt_gpio_unmask_irq(s_avdetect_gpio.gpiono);
+}
+
+static void avdetect_irq_disable(void)
+{
+ wmt_gpio_mask_irq(s_avdetect_gpio.gpiono);
+}
+
+int avdetect_irq_hw_init(int resume)
+{
+ int ret;
+
+ if(!resume) {
+ ret = gpio_request(s_avdetect_gpio.gpiono, "avdetect irq"); //enable gpio
+ if(ret < 0) {
+ DBG_ERR("gpio(%d) request fail for avdetect irq\n", s_avdetect_gpio.gpiono);
+ return ret;
+ }
+ }else
+ gpio_re_enabled(s_avdetect_gpio.gpiono); //re-enable gpio
+
+ gpio_direction_input(s_avdetect_gpio.gpiono); //gpio input
+
+ wmt_gpio_setpull(s_avdetect_gpio.gpiono, WMT_GPIO_PULL_UP); //enable pull and pull-up
+
+ wmt_gpio_mask_irq(s_avdetect_gpio.gpiono); //disable interrupt
+
+ wmt_gpio_set_irq_type(s_avdetect_gpio.gpiono, IRQ_TYPE_EDGE_BOTH); //rise edge and clear interrupt
+
+ return 0;
+}
+
+/*
+static void avdetect_irq_hw_free(void)
+{
+ gpio_free(AVDETECT_IRQ_PIN);
+
+}
+*/
+
+static irqreturn_t avdetect_irq_handler(int irq, void *dev_id)
+{
+ //printk("avdetect_irq_handler\n");
+
+ if(!gpio_irqstatus(s_avdetect_gpio.gpiono))
+ return IRQ_NONE;
+
+ wmt_gpio_ack_irq(s_avdetect_gpio.gpiono); //clear interrupt
+
+ //printk("cvbs hotplug interrupt\n");
+ if(!is_gpio_irqenable(s_avdetect_gpio.gpiono)) {
+ //pr_err("avdetect irq is disabled\n");
+ return IRQ_HANDLED;
+ }else
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t avdetect_irq_thread(int irq, void *dev)
+{
+ //printk(cvbs_hotplug_irq_thread\n");
+
+ if(s_avdetect_gpio.act == 1) {
+ if(gpio_get_value(s_avdetect_gpio.gpiono))
+ printk("av plug in\n");
+ else
+ printk("av plug out\n");
+ }
+ else {
+ if(gpio_get_value(s_avdetect_gpio.gpiono))
+ printk("av plug out\n");
+ else
+ printk("av plug in\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+void cs8556_set_tv_mode(int ntsc)
+{
+ int ret;
+ unsigned char rbuf[256] = {0};
+
+ if( !s_cs8556_ready )
+ return;
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+ if(ret) {
+ DBG_ERR("I2C read Offset0 fail\n");
+ return;
+ }
+
+ if(ntsc < 0) {
+ if(memcmp(rbuf, s_CS8556_Original_Offset0, 0x11) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_CS8556_Original_Offset0);
+ if(ret)
+ DBG_ERR("I2C write Original_Offset0 fail\n");
+ else {
+ if(s_irq_init)
+ avdetect_irq_disable();
+ }
+ }
+
+ return;
+ }
+
+ if(ntsc) {
+ if(memcmp(rbuf, s_RGB888_To_NTSC_Offset0, 0x50) !=0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_NTSC_Offset0);
+ if(ret)
+ DBG_ERR("I2C write NTSC_Offset0 fail\n");
+ }
+ } else {
+ if(memcmp(rbuf, s_RGB888_To_PAL_Offset0, 0x50) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_PAL_Offset0);
+ if(ret)
+ DBG_ERR("I2C write PAL_Offset0 fail\n");
+ }
+ }
+
+}
+
+int cs8556_check_plugin(int hotplug)
+{
+ return 1;
+}
+
+int cs8556_init(struct vout_s *vo)
+{
+ int ret;
+ char buf[40] = {0};
+ int varlen = 40;
+ int no = 1; //default i2c1
+ int num;
+ unsigned char rbuf[256] = {0};
+ struct i2c_adapter *adapter = NULL;
+ vout_tvformat_t tvformat = TV_MAX;
+
+ DPRINT("cs8556_init\n");
+
+ if(wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) {
+ if(!strnicmp(buf, "PAL", 3))
+ tvformat = TV_PAL;
+ else if(!strnicmp(buf, "NTSC", 4))
+ tvformat = TV_NTSC;
+ else
+ tvformat = TV_UNDEFINED;
+ } else
+ tvformat = TV_UNDEFINED;
+
+
+ if(tvformat == TV_UNDEFINED)
+ goto err0;
+
+ if(!s_cs8556_init) {
+ if(wmt_getsyspara("wmt.cs8556.i2c", buf, &varlen) == 0) {
+ if(strlen(buf) > 0)
+ no = buf[0] - '0';
+ }
+
+ adapter = i2c_get_adapter(no);
+ if (adapter == NULL) {
+ DBG_ERR("Can not get i2c adapter, client address error\n");
+ goto err0;
+ }
+
+ s_cs8556_client = i2c_new_device(adapter, cs8556_i2c_board_info);
+ if (s_cs8556_client == NULL) {
+ DBG_ERR("allocate i2c client failed\n");
+ goto err0;
+ }
+
+ i2c_put_adapter(adapter);
+
+ ret = i2c_add_driver(&cs8556_i2c_driver);
+ if (ret != 0) {
+ DBG_ERR("Failed to register CS8556 I2C driver: %d\n", ret);
+ goto err1;
+ }
+
+ if(wmt_getsyspara("wmt.io.avdetect", buf, &varlen) == 0) {
+ num = sscanf(buf, "%d:%d:%d", &s_avdetect_gpio.flag, &s_avdetect_gpio.gpiono,
+ &s_avdetect_gpio.act);
+
+ if(num != 3)
+ DBG_ERR("wmt.io.avdetect is error. param num = %d\n", num);
+ else {
+ if(s_avdetect_gpio.gpiono > 19)
+ DBG_ERR("invalid avdetect gpio no: %d\n", s_avdetect_gpio.gpiono);
+ else {
+ ret = avdetect_irq_hw_init(0);
+ if(!ret) {
+ ret = request_threaded_irq(IRQ_GPIO, avdetect_irq_handler,
+ avdetect_irq_thread, IRQF_SHARED, CS8556_NAME, s_cs8556_client);
+
+ if(ret)
+ DBG_ERR("%s: irq request failed: %d\n", __func__, ret);
+ else {
+ s_irq_init = 1;
+ DPRINT("avdetect irq request success\n");
+ }
+ }
+ }
+ }
+ }
+
+ s_cs8556_init = 1;
+ }
+ else {
+ if(s_irq_init)
+ avdetect_irq_hw_init(1);
+ }
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+ if(ret) {
+ DBG_ERR("I2C address 0x%02X is not found\n", CS8556_ADDR);
+ goto err0;
+ }
+
+ //if(s_cs8556_ready) {
+ // DPRINT("cs8556_reinit");
+ switch(tvformat) {
+ case TV_PAL:
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_PAL_Offset0);
+ if(ret) {
+ DBG_ERR("PAL init fail\n");
+ goto err0;
+ }
+ break;
+
+ case TV_NTSC:
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_NTSC_Offset0);
+ if(ret) {
+ DBG_ERR("NTSC init fail\n");
+ goto err0;
+ }
+ break;
+
+ default:
+ goto err0;
+ break;
+ }
+ //}
+
+ if(s_irq_init)
+ avdetect_irq_enable();
+
+ s_cs8556_ready = 1;
+
+ return 0;
+//err3:
+// cvbs_hotplug_irq_disable();
+// free_irq(IRQ_GPIO, s_cs8556_client);
+// cvbs_hotplug_irq_hw_free();
+//err2:
+// i2c_del_driver(&cs8556_i2c_driver);
+err1:
+ i2c_unregister_device(s_cs8556_client);
+err0:
+ s_cs8556_ready = 0;
+ return -1;
+}
+
+static int cs8556_set_mode(unsigned int *option)
+{
+ if(!s_cs8556_ready)
+ return -1;
+
+ return 0;
+}
+
+static void cs8556_set_power_down(int enable)
+{
+ int ret;
+ vout_t *vo;
+ unsigned char rbuf[256] = {0};
+
+ if( !s_cs8556_ready )
+ return;
+
+ vo = vout_get_entry(VPP_VOUT_NUM_DVI);
+ if (vo->status & (VPP_VOUT_STS_BLANK + VPP_VOUT_STS_POWERDN)) {
+ enable = 1;
+ }
+
+ DPRINT("cs8556_set_power_down(%d)\n",enable);
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 0x11, rbuf);
+ if(ret) {
+ DBG_ERR("I2C read Offset0 fail\n");
+ return;
+ }
+
+ if( enable ){
+ if(memcmp(rbuf, s_CS8556_Original_Offset0, 0x11) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 0x11, s_CS8556_Original_Offset0);
+ if(ret)
+ DBG_ERR("I2C write Offset0 to power down CS8556 fail\n");
+ else {
+ if(s_irq_init)
+ avdetect_irq_disable();
+ }
+ }
+ } else {
+ if(memcmp(rbuf, s_RGB888_To_PAL_Offset0, 0x11) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 0x11, s_RGB888_To_PAL_Offset0);
+ if(ret)
+ DBG_ERR("I2C write offset0 to power up CS8556 fail\n");
+ }
+ }
+}
+
+static int cs8556_config(vout_info_t *info)
+{
+ int ntsc;
+
+ if(!s_cs8556_ready)
+ return -1;
+
+ if(info->resx == 720 && (info->resy == 576 || info->resy == 480)) {
+ ntsc = (info->resy == 480) ? 1 : 0;
+
+ DPRINT("cs8556_config (%dx%d@%d) %s\n", info->resx, info->resy, info->fps, ntsc ? "NTSC" : "PAL");
+
+ cs8556_set_tv_mode(ntsc);
+ } else {
+
+ DPRINT("cs8556_config (%dx%d@%d)\n", info->resx, info->resy, info->fps);
+ cs8556_set_tv_mode(-1);
+ }
+
+ return 0;
+}
+
+static int cs8556_get_edid(char *buf)
+{
+ return -1;
+}
+
+#ifdef CONFIG_CS8556_INTERRUPT
+static int cs8556_interrupt(void)
+{
+ return cs8556_check_plugin(1);
+}
+#endif
+
+void cs8556_read(void)
+{
+ int i, ret;
+ unsigned char rbuf[256] = {0};
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+ if(!ret) {
+ printk("CS8556 Read offset0 data as follows:\n");
+ for(i = 0; i < 256;) {
+ printk("0x%02X,", rbuf[i]);
+ if((++i) % 16 == 0)
+ printk("\n");
+ }
+
+ }
+}
+
+/*----------------------- vout device plugin --------------------------------------*/
+vout_dev_t cs8556_vout_dev_ops = {
+ .name = CS8556_NAME,
+ .mode = VOUT_INF_DVI,
+
+ .init = cs8556_init,
+ .set_power_down = cs8556_set_power_down,
+ .set_mode = cs8556_set_mode,
+ .config = cs8556_config,
+ .check_plugin = cs8556_check_plugin,
+ .get_edid = cs8556_get_edid,
+#ifdef CONFIG_CS8556_INTERRUPT
+ .interrupt = cs8556_interrupt,
+#endif
+};
+
+int cs8556_module_init(void)
+{
+ vout_device_register(&cs8556_vout_dev_ops);
+ return 0;
+} /* End of cs8556_module_init */
+module_init(cs8556_module_init);
+/*--------------------End of Function Body -----------------------------------*/
+#undef CS8556_C
+
|