--- /dev/null
+/*
+ * gm7122_tve.c
+ *
+ * Driver for rockchip gm7122 tv encoder control
+ * Copyright (C) 2015
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#include <linux/display-sys.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include "gm7122_tve.h"
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/syscon.h>
+
+static const struct fb_videomode gm7122_cvbs_mode[] = {
+/*name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag */
+{"NTSC", 60, 720, 480, 27000000, 57, 19, 15, 4, 62, 3, 0, FB_VMODE_INTERLACED, 0},
+{"PAL", 50, 720, 576, 27000000, 62, 14, 17, 2, 68, 5, 0, FB_VMODE_INTERLACED, 0},
+};
+
+static struct gm7122_tve *gm7122_tve;
+
+static int cvbsformat;
+
+#define tve_writel(offset, v) gm7122_i2c_send(offset, v)
+/*#define tve_readl(offset, *v) gm7122_i2c_recv(offset, v)*/
+
+#ifdef DEBUG
+#define TVEDBG(format, ...) \
+ dev_info(gm7122_tve->dev,\
+ "GM7122 TVE: " format "\n", ## __VA_ARGS__)
+#else
+#define TVEDBG(format, ...)
+#endif
+
+int gm7122_i2c_send(const u8 reg, const u8 value)
+{
+ char buf[2];
+ int ret;
+
+ buf[0] = reg;
+ buf[1] = value;
+ ret = i2c_master_send(gm7122_tve->client, buf, 2);
+ if (ret != 2) {
+ TVEDBG("gm7122 control i2c write err,ret =%d\n", ret);
+ return -1;
+ }
+ return 0;
+}
+
+int gm7122_i2c_recv(const u8 reg, char *value)
+{
+ int ret;
+
+ ret = i2c_master_send(gm7122_tve->client, ®, 1);
+ i2c_master_recv(gm7122_tve->client, value, 1);
+ pr_info("%s reg = 0x%x , value = 0x%c\n", __func__, reg, *value);
+ return (ret == 2) ? 0 : -1;
+}
+
+
+static void tve_set_mode(int mode)
+{
+ TVEDBG("%s mode %d\n", __func__, mode);
+ if (cvbsformat >= 0)
+ return;
+
+ if (mode == TVOUT_CVBS_NTSC) {
+ tve_writel(BURST_START, V_D0_BS0(1) | V_D0_BS5(1));
+ tve_writel(BURST_END, V_D0_BE0(1) | V_D0_BE2(1) |
+ V_D0_BE3(1) | V_D0_BE4(1));
+ tve_writel(INPUT_PORT_CTL, V_SYMP(1) | V_UV2C(1) | V_Y2C(1));
+ tve_writel(COLOR_DIFF_CTL, 0x00);
+ tve_writel(U_GAIN_CTL, V_GAINU0(1) | V_GAINU2(1) |
+ V_GAINU3(3) | V_GAINU5(1) | V_GAINU6(1));
+ tve_writel(V_GAIN_CTL, V_GAINV0(1) | V_GAINV1(1) |
+ V_GAINV2(1) | V_GAINV3(1) | V_GAINV4(1) |
+ V_GAINV7(1));
+ tve_writel(UMSB_BLACK_GAIN, V_BLACK1(1) | V_BLACK2(1) |
+ V_BLACK3(1));
+ tve_writel(VMSB_BLNNL_GAIN, V_BLNNL2(1) | V_BLNNL3(1) |
+ V_BLNNL4(1));
+ tve_writel(STANDARD_CTL, V_PAL(0) | V_BIT0(1));
+ tve_writel(RTCEN_BURST_CTL, V_BSTA0(1) | V_BSTA1(1)|
+ V_BSTA3(1) | V_BSTA4(1) | V_BSTA5(1));
+ tve_writel(SUBCARRIER0, V_FSC00(1) | V_FSC01(1)|
+ V_FSC02(1) | V_FSC03(1) | V_FSC04(1));
+ tve_writel(SUBCARRIER1, V_FSC10(1) | V_FSC11(1)|
+ V_FSC12(1) | V_FSC13(1) | V_FSC14(1));
+ tve_writel(SUBCARRIER2, V_FSC20(1) | V_FSC21(1) |
+ V_FSC22(1) | V_FSC23(1));
+ tve_writel(SUBCARRIER3, V_FSC29(1) | V_FSC24(1));
+ tve_writel(RCV_PORT_CTL, 0x00);
+ tve_writel(TRIG0_CTL, V_HTRIG0(1) | V_HTRIG2(1) | V_HTRIG4(1) |
+ V_HTRIG5(1) | V_HTRIG6(1) | V_HTRIG7(1));
+ tve_writel(TRIG1_CTL, V_VTRIG0(1) | V_VTRIG4(1) | V_HTRIG8(1) |
+ V_HTRIG10(1));
+ } else if (mode == TVOUT_CVBS_PAL) {
+ tve_writel(BURST_START, V_D0_BS0(1) | V_D0_BS5(1));
+ tve_writel(BURST_END, V_D0_BE0(1) | V_D0_BE2(1) |
+ V_D0_BE3(1) | V_D0_BE4(1));
+ tve_writel(INPUT_PORT_CTL, V_SYMP(1) | V_UV2C(1) | V_Y2C(1));
+ /*tve_writel(INPUT_PORT_CTL, 0x93);*//*color bar for debug*/
+ tve_writel(COLOR_DIFF_CTL, V_CHPS0(1));
+ tve_writel(U_GAIN_CTL, V_GAINU1(1) | V_GAINU3(1) |
+ V_GAINU5(1) | V_GAINU6(1));
+ tve_writel(V_GAIN_CTL, V_GAINV0(1) | V_GAINV1(1) |
+ V_GAINV2(1) | V_GAINV3(1) | V_GAINV4(1) |
+ V_GAINV7(1));
+ tve_writel(UMSB_BLACK_GAIN, V_BLACK1(1) | V_BLACK4(1));
+ tve_writel(VMSB_BLNNL_GAIN, V_BLNNL0(1) | V_BLNNL1(1) |
+ V_BLNNL2(1) | V_BLNNL3(1) | V_BLNNL4(1));
+ tve_writel(STANDARD_CTL, V_PAL(1) | V_SCBW(1));
+ tve_writel(RTCEN_BURST_CTL, V_BSTA0(1) | V_BSTA1(1)|
+ V_BSTA3(1) | V_BSTA4(1) | V_BSTA5(1));
+ tve_writel(SUBCARRIER0, V_FSC00(1) | V_FSC01(1)|
+ V_FSC03(1) | V_FSC06(1) | V_FSC07(1));
+ tve_writel(SUBCARRIER1, V_FSC15(1) | V_FSC11(1)|
+ V_FSC09(1));
+ tve_writel(SUBCARRIER2, V_FSC19(1) | V_FSC16(1));
+ tve_writel(SUBCARRIER3, V_FSC29(1) | V_FSC27(1) | V_FSC25(1));
+ tve_writel(RCV_PORT_CTL, 0x00);
+ tve_writel(TRIG0_CTL, V_HTRIG0(1) | V_HTRIG2(1) | V_HTRIG4(1) |
+ V_HTRIG5(1) | V_HTRIG6(1) | V_HTRIG7(1));
+ tve_writel(TRIG1_CTL, V_VTRIG0(1) | V_VTRIG4(1) | V_HTRIG8(1) |
+ V_HTRIG10(1));
+ }
+}
+
+static int tve_switch_fb(const struct fb_videomode *modedb, int enable)
+{
+ struct rk_screen *screen = &gm7122_tve->screen;
+
+ if (modedb == NULL)
+ return -1;
+
+ memset(screen, 0, sizeof(struct rk_screen));
+ /* screen type & face */
+ /*screen->type = SCREEN_TVOUT;*/
+ screen->type = SCREEN_RGB;
+ screen->face = OUT_CCIR656;
+ screen->color_mode = COLOR_YCBCR;
+ screen->mode = *modedb;
+ /*screen->mode.vmode = 0;*/
+
+ /* 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;
+ /*screen->pixelrepeat = 1;*/
+
+ /* Swap rule */
+ screen->swap_rb = 0;
+ screen->swap_rg = 0;
+ screen->swap_gb = 0;
+ screen->swap_delta = 0;
+ screen->swap_dumy = 0;
+ screen->overscan.left = 100;
+ screen->overscan.top = 100;
+ screen->overscan.right = 100;
+ screen->overscan.bottom = 100;
+ /* Operation function*/
+ screen->init = NULL;
+ screen->standby = NULL;
+ rk_fb_switch_screen(screen, enable, gm7122_tve->lcdcid);
+ if (enable) {
+ if (screen->mode.yres == 480)
+ tve_set_mode(TVOUT_CVBS_NTSC);
+ else
+ tve_set_mode(TVOUT_CVBS_PAL);
+ }
+ return 0;
+}
+
+static int cvbs_set_enable(struct rk_display_device *device, int enable)
+{
+ if (gm7122_tve->enable != enable) {
+ gm7122_tve->enable = enable;
+ if (gm7122_tve->suspend)
+ return 0;
+
+ if (enable == 0) {
+ /*tve_enable(false);*/
+ cvbsformat = -1;
+ tve_switch_fb(gm7122_tve->mode, 0);
+ } else if (enable == 1) {
+ tve_switch_fb(gm7122_tve->mode, 1);
+ /*tve_enable(true);*/
+ }
+ }
+ return 0;
+}
+
+static int cvbs_get_enable(struct rk_display_device *device)
+{
+ TVEDBG("%s enable %d\n", __func__, gm7122_tve->enable);
+ return gm7122_tve->enable;
+}
+
+static int cvbs_get_status(struct rk_display_device *device)
+{
+ return 1;
+}
+
+static int
+cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
+{
+ *modelist = &(gm7122_tve->modelist);
+ return 0;
+}
+
+static int
+cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gm7122_cvbs_mode); i++) {
+ if (fb_mode_is_equal(&gm7122_cvbs_mode[i], mode)) {
+ if (gm7122_tve->mode != &gm7122_cvbs_mode[i]) {
+ gm7122_tve->mode =
+ (struct fb_videomode *)&gm7122_cvbs_mode[i];
+ if (gm7122_tve->enable &&
+ !gm7122_tve->suspend) {
+ /*tve_enable(false);*/
+ if (!fb_mode_is_equal(gm7122_tve->mode,
+ mode)) {
+ gpio_set_value(
+ gm7122_tve->io_sleep.gpio,
+ gm7122_tve->io_sleep.active);
+ msleep(20);
+ gpio_set_value(
+ gm7122_tve->io_sleep.gpio,
+ !(gm7122_tve->io_sleep.active));
+ }
+ tve_switch_fb(gm7122_tve->mode, 1);
+ }
+ /*tve_enable(true);*/
+ }
+ return 0;
+ }
+ }
+ TVEDBG("%s\n", __func__);
+ return -1;
+}
+
+static int
+cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+ *mode = *(gm7122_tve->mode);
+ return 0;
+}
+
+static int
+tve_fb_event_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_event *event = data;
+ int blank_mode = *((int *)event->data);
+
+ if (action == FB_EARLY_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ break;
+ default:
+ TVEDBG("suspend tve\n");
+ if (!gm7122_tve->suspend) {
+ gm7122_tve->suspend = 1;
+ if (gm7122_tve->enable) {
+ tve_switch_fb(gm7122_tve->mode, 0);
+ /*tve_enable(false);*/
+ }
+ }
+ break;
+ }
+ } else if (action == FB_EVENT_BLANK) {
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ TVEDBG("resume tve\n");
+ if (gm7122_tve->suspend) {
+ gm7122_tve->suspend = 0;
+ if (gm7122_tve->enable) {
+ tve_switch_fb(gm7122_tve->mode, 1);
+ /*tve_enable(true);*/
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block tve_fb_notifier = {
+ .notifier_call = tve_fb_event_notify,
+};
+
+static struct rk_display_ops cvbs_display_ops = {
+ .setenable = cvbs_set_enable,
+ .getenable = cvbs_get_enable,
+ .getstatus = cvbs_get_status,
+ .getmodelist = cvbs_get_modelist,
+ .setmode = cvbs_set_mode,
+ .getmode = cvbs_get_mode,
+};
+
+static int
+display_cvbs_probe(struct rk_display_device *device, void *devdata)
+{
+ device->owner = THIS_MODULE;
+ strcpy(device->type, "TV");
+ device->name = "cvbs";
+ device->priority = DISPLAY_PRIORITY_TV;
+ device->property = 0;/*just for test*/
+ device->priv_data = devdata;
+ device->ops = &cvbs_display_ops;
+ return 1;
+}
+
+static struct rk_display_driver display_cvbs = {
+ .probe = display_cvbs_probe,
+};
+
+#if defined(CONFIG_OF)
+static const struct i2c_device_id gm7122_tve_dt_ids[] = {
+ { "gm7122_tve", 0 },
+ {}
+};
+#endif
+
+static int __init bootloader_tve_setup(char *str)
+{
+ if (str) {
+ pr_info("cvbs init tve.format is %s\n", str);
+ if (kstrtoint(str, 0, &cvbsformat) < 0)
+ cvbsformat = -1;
+ }
+ return 0;
+}
+
+early_param("tve.format", bootloader_tve_setup);
+
+
+static int gm7122_tve_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int i;
+ struct device_node *gm7122_np;
+ enum of_gpio_flags flags;
+ int ret;
+
+ gm7122_tve = kmalloc(sizeof(*gm7122_tve), GFP_KERNEL);
+ if (!gm7122_tve) {
+ dev_err(&client->dev, "gm7122 tv encoder device kmalloc fail!\n");
+ return -ENOMEM;
+ }
+ memset(gm7122_tve, 0, sizeof(*gm7122_tve));
+ gm7122_tve->client = client;
+ gm7122_tve->dev = &client->dev;
+ gm7122_np = gm7122_tve->dev->of_node;
+ of_property_read_u32(gm7122_np, "rockchip,source", &(ret));
+ gm7122_tve->lcdcid = ret;
+ of_property_read_u32(gm7122_np, "rockchip,prop", &(ret));
+ gm7122_tve->property = ret;
+ /********Get reset pin***********/
+ gm7122_tve->io_reset.gpio = of_get_named_gpio_flags(gm7122_np, "gpio-reset",
+ 0, &flags);
+ if (!gpio_is_valid(gm7122_tve->io_reset.gpio)) {
+ TVEDBG("invalid gm7122_tve->io_reset.gpio: %d\n",
+ gm7122_tve->io_reset.gpio);
+ goto failout;
+ }
+ ret = gpio_request(gm7122_tve->io_reset.gpio, "gm7122-reset-io");
+ if (ret != 0) {
+ TVEDBG("gpio_request gm7122_tve->io_reset.gpio invalid: %d\n",
+ gm7122_tve->io_reset.gpio);
+ goto failout;
+ }
+ gm7122_tve->io_reset.active = (flags & OF_GPIO_ACTIVE_LOW);
+ gpio_direction_output(gm7122_tve->io_reset.gpio,
+ !(gm7122_tve->io_reset.active));
+ gpio_set_value(gm7122_tve->io_reset.gpio,
+ !(gm7122_tve->io_reset.active));
+ /********Reset pin end***********/
+ /********Get sleep pin***********/
+ gm7122_tve->io_sleep.gpio = of_get_named_gpio_flags(gm7122_np, "gpio-sleep", 0, &flags);
+ if (!gpio_is_valid(gm7122_tve->io_sleep.gpio)) {
+ TVEDBG("invalid gm7122_tve->io_reset.gpio: %d\n",
+ gm7122_tve->io_sleep.gpio);
+ }
+ ret = gpio_request(gm7122_tve->io_sleep.gpio, "gm7122-sleep-io");
+ if (ret != 0) {
+ TVEDBG("gpio_request gm7122_tve->io_reset.gpio invalid: %d\n",
+ gm7122_tve->io_sleep.gpio);
+ goto failout;
+ }
+ gm7122_tve->io_sleep.active = !(flags & OF_GPIO_ACTIVE_LOW);
+ gpio_direction_output(gm7122_tve->io_sleep.gpio,
+ !(gm7122_tve->io_sleep.active));
+ gpio_set_value(gm7122_tve->io_sleep.gpio,
+ !(gm7122_tve->io_sleep.active));
+ /********Sleep pin end***********/
+ INIT_LIST_HEAD(&(gm7122_tve->modelist));
+ for (i = 0; i < ARRAY_SIZE(gm7122_cvbs_mode); i++)
+ fb_add_videomode(&gm7122_cvbs_mode[i], &(gm7122_tve->modelist));
+ if (cvbsformat >= 0) {
+ gm7122_tve->mode =
+ (struct fb_videomode *)&gm7122_cvbs_mode[cvbsformat];
+ gm7122_tve->enable = 1;
+ tve_switch_fb(gm7122_tve->mode, 1);
+ } else {
+ gm7122_tve->mode = (struct fb_videomode *)&gm7122_cvbs_mode[1];
+ }
+ gm7122_tve->ddev =
+ rk_display_device_register(&display_cvbs,
+ gm7122_tve->dev, NULL);
+ rk_display_device_enable(gm7122_tve->ddev);
+ fb_register_client(&tve_fb_notifier);
+ cvbsformat = -1;
+ pr_info("%s tv encoder probe ok!\n", __func__);
+ return 0;
+
+failout:
+ kfree(gm7122_tve);
+ return -ENODEV;
+}
+
+/*static void gm7122_tve_shutdown(struct platform_device *pdev)
+{
+}*/
+static int gm7122_tve_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+MODULE_DEVICE_TABLE(i2c, gm7122_tve_dt_ids);
+
+static struct i2c_driver gm7122_tve_driver = {
+ .probe = gm7122_tve_probe,
+ .remove = gm7122_tve_remove,
+ .driver = {
+ .name = "gm7122_tve",
+ .owner = THIS_MODULE,
+ },
+ /*.shutdown = gm7122_tve_shutdown,*/
+ .id_table = gm7122_tve_dt_ids,
+};
+
+static int __init gm7122_tve_init(void)
+{
+ return i2c_add_driver(&gm7122_tve_driver);
+}
+
+static void __exit gm7122_tve_exit(void)
+{
+ i2c_del_driver(&gm7122_tve_driver);
+}
+
+module_init(gm7122_tve_init);
+module_exit(gm7122_tve_exit);
+
+
+MODULE_DESCRIPTION("ROCKCHIP GM7122 TV Encoder ");
+MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+#ifndef __GM7122_TVE_H__
+#define __GM7122_TVE_H__
+
+#include<linux/regmap.h>
+#include<linux/io.h>
+
+#define BURST_START (0x28)
+ #define M_D5_BS0 (1 << 5)
+ #define M_D4_BS0 (1 << 4)
+ #define M_D3_BS0 (1 << 3)
+ #define M_D2_BS0 (1 << 2)
+ #define M_D1_BS0 (1 << 1)
+ #define M_D0_BS0 (1 << 0)
+
+ #define V_D0_BS5(x) ((x & 1) << 5)
+ #define V_D0_BS4(x) ((x & 1) << 4)
+ #define V_D0_BS3(x) ((x & 1) << 3)
+ #define V_D0_BS2(x) ((x & 1) << 2)
+ #define V_D0_BS1(x) ((x & 1) << 1)
+ #define V_D0_BS0(x) ((x & 1) << 0)
+
+#define BURST_END (0x29)
+ #define M_D5_BE0 (1 << 5)
+ #define M_D4_BE0 (1 << 4)
+ #define M_D3_BE0 (1 << 3)
+ #define M_D2_BE0 (1 << 2)
+ #define M_D1_BE0 (1 << 1)
+ #define M_D0_BE0 (1 << 0)
+
+ #define V_D0_BE5(x) ((x & 1) << 5)
+ #define V_D0_BE4(x) ((x & 1) << 4)
+ #define V_D0_BE3(x) ((x & 1) << 3)
+ #define V_D0_BE2(x) ((x & 1) << 2)
+ #define V_D0_BE1(x) ((x & 1) << 1)
+ #define V_D0_BE0(x) ((x & 1) << 0)
+
+#define DA_MODE_CTL (0x2F)
+ #define M_DA7 (1 << 7)
+ #define M_DA3 (1 << 3)
+ #define M_DA2 (1 << 2)
+
+ #define V_DA7(x) ((x & 1) << 7)
+ #define V_DA3(x) ((x & 1) << 3)
+ #define V_DA2(x) ((x & 1) << 2)
+
+#define INPUT_PORT_CTL (0x3A)
+ #define M_CBENB (1 << 7)
+ #define M_SYMP (1 << 4)
+ #define M_Y2C (1 << 1)
+ #define M_UV2C (1 << 0)
+
+ #define V_CBENB(x) ((x & 1) << 7)
+ #define V_SYMP(x) ((x & 1) << 4)
+ #define V_Y2C(x) ((x & 1) << 1)
+ #define V_UV2C(x) ((x & 1) << 0)
+
+#define COLOR_DIFF_CTL (0x5A)
+ #define M_CHPS7 (1 << 7)
+ #define M_CHPS6 (1 << 6)
+ #define M_CHPS5 (1 << 5)
+ #define M_CHPS4 (1 << 4)
+ #define M_CHPS3 (1 << 3)
+ #define M_CHPS2 (1 << 2)
+ #define M_CHPS1 (1 << 1)
+ #define M_CHPS0 (1 << 0)
+
+ #define V_CHPS7(x) ((x & 1) << 7)
+ #define V_CHPS6(x) ((x & 1) << 6)
+ #define V_CHPS5(x) ((x & 1) << 5)
+ #define V_CHPS4(x) ((x & 1) << 4)
+ #define V_CHPS3(x) ((x & 1) << 3)
+ #define V_CHPS2(x) ((x & 1) << 2)
+ #define V_CHPS1(x) ((x & 1) << 1)
+ #define V_CHPS0(x) ((x & 1) << 0)
+
+#define U_GAIN_CTL (0x5B)
+ #define M_GAINU7 (1 << 7)
+ #define M_GAINU6 (1 << 6)
+ #define M_GAINU5 (1 << 5)
+ #define M_GAINU4 (1 << 4)
+ #define M_GAINU3 (1 << 3)
+ #define M_GAINU2 (1 << 2)
+ #define M_GAINU1 (1 << 1)
+ #define M_GAINU0 (1 << 0)
+
+ #define V_GAINU7(x) ((x & 1) << 7)
+ #define V_GAINU6(x) ((x & 1) << 6)
+ #define V_GAINU5(x) ((x & 1) << 5)
+ #define V_GAINU4(x) ((x & 1) << 4)
+ #define V_GAINU3(x) ((x & 1) << 3)
+ #define V_GAINU2(x) ((x & 1) << 2)
+ #define V_GAINU1(x) ((x & 1) << 1)
+ #define V_GAINU0(x) ((x & 1) << 0)
+
+#define V_GAIN_CTL (0x5C)
+ #define M_GAINV7 (1 << 7)
+ #define M_GAINV6 (1 << 6)
+ #define M_GAINV5 (1 << 5)
+ #define M_GAINV4 (1 << 4)
+ #define M_GAINV3 (1 << 3)
+ #define M_GAINV2 (1 << 2)
+ #define M_GAINV1 (1 << 1)
+ #define M_GAINV0 (1 << 0)
+
+ #define V_GAINV7(x) ((x & 1) << 7)
+ #define V_GAINV6(x) ((x & 1) << 6)
+ #define V_GAINV5(x) ((x & 1) << 5)
+ #define V_GAINV4(x) ((x & 1) << 4)
+ #define V_GAINV3(x) ((x & 1) << 3)
+ #define V_GAINV2(x) ((x & 1) << 2)
+ #define V_GAINV1(x) ((x & 1) << 1)
+ #define V_GAINV0(x) ((x & 1) << 0)
+
+#define UMSB_BLACK_GAIN (0x5D)
+ #define M_GAINU8 (1 << 7)
+ #define M_BLACK5 (1 << 5)
+ #define M_BLACK4 (1 << 4)
+ #define M_BLACK3 (1 << 3)
+ #define M_BLACK2 (1 << 2)
+ #define M_BLACK1 (1 << 1)
+ #define M_BLACK0 (1 << 0)
+
+ #define V_GAINU8(x) ((x & 1) << 7)
+ #define V_BLACK5(x) ((x & 1) << 5)
+ #define V_BLACK4(x) ((x & 1) << 4)
+ #define V_BLACK3(x) ((x & 1) << 3)
+ #define V_BLACK2(x) ((x & 1) << 2)
+ #define V_BLACK1(x) ((x & 1) << 1)
+ #define V_BLACK0(x) ((x & 1) << 0)
+
+#define VMSB_BLNNL_GAIN (0x5E)
+ #define M_GAINV8 (1 << 7)
+ #define M_BLNNL5 (1 << 5)
+ #define M_BLNNL4 (1 << 4)
+ #define M_BLNNL3 (1 << 3)
+ #define M_BLNNL2 (1 << 2)
+ #define M_BLNNL1 (1 << 1)
+ #define M_BLNNL0 (1 << 0)
+
+ #define V_GAINV8(x) ((x & 1) << 7)
+ #define V_BLNNL5(x) ((x & 1) << 5)
+ #define V_BLNNL4(x) ((x & 1) << 4)
+ #define V_BLNNL3(x) ((x & 1) << 3)
+ #define V_BLNNL2(x) ((x & 1) << 2)
+ #define V_BLNNL1(x) ((x & 1) << 1)
+ #define V_BLNNL0(x) ((x & 1) << 0)
+
+#define STANDARD_CTL (0x61)
+ #define M_SCBW (1 << 2)
+ #define M_PAL (1 << 1)
+ #define M_BIT0 (1 << 0)
+
+ #define V_SCBW(x) ((x & 1) << 2)
+ #define V_PAL(x) ((x & 1) << 1)
+ #define V_BIT0(x) ((x & 1) << 0)
+
+#define RTCEN_BURST_CTL (0x62)
+ #define M_RTCEN (1 << 7)
+ #define M_BSTA6 (1 << 6)
+ #define M_BSTA5 (1 << 5)
+ #define M_BSTA4 (1 << 4)
+ #define M_BSTA3 (1 << 3)
+ #define M_BSTA2 (1 << 2)
+ #define M_BSTA1 (1 << 1)
+ #define M_BSTA0 (1 << 0)
+
+ #define V_RTCEN(x) ((x & 1) << 7)
+ #define V_BSTA6(x) ((x & 1) << 6)
+ #define V_BSTA5(x) ((x & 1) << 5)
+ #define V_BSTA4(x) ((x & 1) << 4)
+ #define V_BSTA3(x) ((x & 1) << 3)
+ #define V_BSTA2(x) ((x & 1) << 2)
+ #define V_BSTA1(x) ((x & 1) << 1)
+ #define V_BSTA0(x) ((x & 1) << 0)
+
+#define SUBCARRIER0 (0x63)
+ #define M_FSC07 (1 << 7)
+ #define M_FSC06 (1 << 6)
+ #define M_FSC05 (1 << 5)
+ #define M_FSC04 (1 << 4)
+ #define M_FSC03 (1 << 3)
+ #define M_FSC02 (1 << 2)
+ #define M_FSC01 (1 << 1)
+ #define M_FSC00 (1 << 0)
+
+ #define V_FSC07(x) ((x & 1) << 7)
+ #define V_FSC06(x) ((x & 1) << 6)
+ #define V_FSC05(x) ((x & 1) << 5)
+ #define V_FSC04(x) ((x & 1) << 4)
+ #define V_FSC03(x) ((x & 1) << 3)
+ #define V_FSC02(x) ((x & 1) << 2)
+ #define V_FSC01(x) ((x & 1) << 1)
+ #define V_FSC00(x) ((x & 1) << 0)
+
+#define SUBCARRIER1 (0x64)
+ #define M_FSC15 (1 << 7)
+ #define M_FSC14 (1 << 6)
+ #define M_FSC13 (1 << 5)
+ #define M_FSC12 (1 << 4)
+ #define M_FSC11 (1 << 3)
+ #define M_FSC10 (1 << 2)
+ #define M_FSC09 (1 << 1)
+ #define M_FSC08 (1 << 0)
+
+ #define V_FSC15(x) ((x & 1) << 7)
+ #define V_FSC14(x) ((x & 1) << 6)
+ #define V_FSC13(x) ((x & 1) << 5)
+ #define V_FSC12(x) ((x & 1) << 4)
+ #define V_FSC11(x) ((x & 1) << 3)
+ #define V_FSC10(x) ((x & 1) << 2)
+ #define V_FSC09(x) ((x & 1) << 1)
+ #define V_FSC08(x) ((x & 1) << 0)
+
+#define SUBCARRIER2 (0x65)
+ #define M_FSC23 (1 << 7)
+ #define M_FSC22 (1 << 6)
+ #define M_FSC21 (1 << 5)
+ #define M_FSC20 (1 << 4)
+ #define M_FSC19 (1 << 3)
+ #define M_FSC18 (1 << 2)
+ #define M_FSC17 (1 << 1)
+ #define M_FSC16 (1 << 0)
+
+ #define V_FSC23(x) ((x & 1) << 7)
+ #define V_FSC22(x) ((x & 1) << 6)
+ #define V_FSC21(x) ((x & 1) << 5)
+ #define V_FSC20(x) ((x & 1) << 4)
+ #define V_FSC19(x) ((x & 1) << 3)
+ #define V_FSC18(x) ((x & 1) << 2)
+ #define V_FSC17(x) ((x & 1) << 1)
+ #define V_FSC16(x) ((x & 1) << 0)
+
+#define SUBCARRIER3 (0x66)
+ #define M_FSC31 (1 << 7)
+ #define M_FSC30 (1 << 6)
+ #define M_FSC29 (1 << 5)
+ #define M_FSC28 (1 << 4)
+ #define M_FSC27 (1 << 3)
+ #define M_FSC26 (1 << 2)
+ #define M_FSC25 (1 << 1)
+ #define M_FSC24 (1 << 0)
+
+ #define V_FSC31(x) ((x & 1) << 7)
+ #define V_FSC30(x) ((x & 1) << 6)
+ #define V_FSC29(x) ((x & 1) << 5)
+ #define V_FSC28(x) ((x & 1) << 4)
+ #define V_FSC27(x) ((x & 1) << 3)
+ #define V_FSC26(x) ((x & 1) << 2)
+ #define V_FSC25(x) ((x & 1) << 1)
+ #define V_FSC24(x) ((x & 1) << 0)
+
+#define RCV_PORT_CTL (0x6B)
+ #define M_ORCV1 (1 << 4)
+ #define M_PRCV1 (1 << 3)
+ #define M_ORCV2 (1 << 1)
+ #define M_PRCV2 (1 << 0)
+
+ #define V_ORCV1(x) ((x & 1) << 4)
+ #define V_PRCV1(x) ((x & 1) << 3)
+ #define V_ORCV2(x) ((x & 1) << 1)
+ #define V_PRCV2(x) ((x & 1) << 0)
+
+
+#define TRIG0_CTL (0x6C)
+ #define M_HTRIG7 (1 << 7)
+ #define M_HTRIG6 (1 << 6)
+ #define M_HTRIG5 (1 << 5)
+ #define M_HTRIG4 (1 << 4)
+ #define M_HTRIG3 (1 << 3)
+ #define M_HTRIG2 (1 << 2)
+ #define M_HTRIG1 (1 << 1)
+ #define M_HTRIG0 (1 << 0)
+
+ #define V_HTRIG7(x) ((x & 1) << 7)
+ #define V_HTRIG6(x) ((x & 1) << 6)
+ #define V_HTRIG5(x) ((x & 1) << 5)
+ #define V_HTRIG4(x) ((x & 1) << 4)
+ #define V_HTRIG3(x) ((x & 1) << 3)
+ #define V_HTRIG2(x) ((x & 1) << 2)
+ #define V_HTRIG1(x) ((x & 1) << 1)
+ #define V_HTRIG0(x) ((x & 1) << 0)
+
+#define TRIG1_CTL (0x6D)
+ #define M_HTRIG10 (1 << 7)
+ #define M_HTRIG9 (1 << 6)
+ #define M_HTRIG8 (1 << 5)
+ #define M_VTRIG4 (1 << 4)
+ #define M_VTRIG3 (1 << 3)
+ #define M_VTRIG2 (1 << 2)
+ #define M_VTRIG1 (1 << 1)
+ #define M_VTRIG0 (1 << 0)
+
+ #define V_HTRIG10(x) ((x & 1) << 7)
+ #define V_HTRIG9(x) ((x & 1) << 6)
+ #define V_HTRIG8(x) ((x & 1) << 5)
+ #define V_VTRIG4(x) ((x & 1) << 4)
+ #define V_VTRIG3(x) ((x & 1) << 3)
+ #define V_VTRIG2(x) ((x & 1) << 2)
+ #define V_VTRIG1(x) ((x & 1) << 1)
+ #define V_VTRIG0(x) ((x & 1) << 0)
+
+#define TRIG2_CTL (0x75)
+ #define M_VTRIG8 (1 << 7)
+ #define M_VTRIG7 (1 << 6)
+ #define M_VTRIG6 (1 << 5)
+ #define M_VTRIG5 (1 << 4)
+
+ #define V_VTRIG8(x) ((x & 1) << 7)
+ #define V_VTRIG7(x) ((x & 1) << 6)
+ #define V_VTRIG6(x) ((x & 1) << 5)
+ #define V_VTRIG5(x) ((x & 1) << 4)
+
+enum {
+ TVOUT_CVBS_NTSC = 0,
+ TVOUT_CVBS_PAL,
+};
+
+enum {
+ INPUT_FORMAT_RGB = 0,
+ INPUT_FORMAT_YUV,
+ INPUT_FORMAT_CCIR656
+};
+
+enum {
+ SOC_RK1000 = 0,
+ SOC_GM7122
+};
+
+#define TVOUT_DEAULT TVOUT_CVBS_PAL
+
+struct ioctrl {
+ int gpio;
+ int active;
+};
+
+struct gm7122_tve {
+ struct device *dev;
+ u32 reg_phy_base;
+ u32 len;
+ unsigned int lcdcid;
+ unsigned int property;
+ struct rk_display_device *ddev;
+ unsigned int enable;
+ unsigned int suspend;
+ struct fb_videomode *mode;
+ struct list_head modelist;
+ struct rk_screen screen;
+ struct i2c_client *client;
+ struct ioctrl io_reset;
+ struct ioctrl io_sleep;
+};
+
+#define GM7122_I2C_RATE (100*1000)
+
+#endif