video: rockchip: remove unused tve driver

Change-Id: I97f6910e5fb4c093e117f1357fd616a8b6a0ea79
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang
2019-09-09 17:57:13 +08:00
parent 567278c61b
commit 91908215ac
22 changed files with 0 additions and 3418 deletions

View File

@@ -1,15 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# TV Encoder drivers configuration
#
menuconfig RK_TVENCODER
bool "Rockchip TV Encoder support"
depends on FB_ROCKCHIP
help
Support RockChip TV Encoder if you say y here.
source "drivers/video/rockchip/tve/rk1000/Kconfig"
source "drivers/video/rockchip/tve/rk3036/Kconfig"
source "drivers/video/rockchip/tve/rk610/Kconfig"
source "drivers/video/rockchip/tve/gm7122/Kconfig"

View File

@@ -1,9 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for tv encoder.
#
obj-$(CONFIG_RK610_TVOUT) += rk610/
obj-$(CONFIG_RK3036_TV_ENCODER) += rk3036/
obj-$(CONFIG_RK1000_TVOUT) += rk1000/
obj-$(CONFIG_GM7122_TV_ENCODER) += gm7122/

View File

@@ -1,7 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config GM7122_TV_ENCODER
bool "gm7122 tv encoder support"
depends on RK_TVENCODER
default n
help
Support GM7122 output CVBS.

View File

@@ -1,5 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the gm7122 tv encoder control.
#
obj-$(CONFIG_GM7122_TV_ENCODER) += gm7122_tve.o

View File

@@ -1,491 +0,0 @@
/*
* 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, &reg, 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;
if (action == FB_EARLY_EVENT_BLANK) {
switch (*((int *)event->data)) {
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 (*((int *)event->data)) {
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");

View File

@@ -1,356 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#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

View File

@@ -1,19 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# TV Encoder RK1000 drivers configuration
#
config RK1000_TVOUT
bool "RK1000 TV Encoder support"
depends on RK_TVENCODER
select MFD_RK1000
help
Support rk1000 to output YPbPr and CVBS.
config RK1000_TVOUT_YPbPr
bool "Support YPbPr Output"
depends on RK1000_TVOUT
config RK1000_TVOUT_CVBS
bool "Support CVBS Output"
depends on RK1000_TVOUT

View File

@@ -1,7 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the RK1000 tv control.
#
obj-$(CONFIG_RK1000_TVOUT) += rk1000_tve.o
obj-$(CONFIG_RK1000_TVOUT_YPbPr) += rk1000_tve_ypbpr.o
obj-$(CONFIG_RK1000_TVOUT_CVBS) += rk1000_tve_cvbs.o

View File

@@ -1,397 +0,0 @@
/*
* rk1000_tv.c
*
* Driver for rockchip rk1000 tv control
* Copyright (C) 2009
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/fb.h>
#include <linux/rk_fb.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <dt-bindings/rkfb/rk_fb.h>
#endif
#include "rk1000_tve.h"
struct rk1000_tve rk1000_tve;
int cvbsformat = -1;
int rk1000_tv_write_block(u8 reg, u8 *buf, u8 len)
{
int i, ret;
for (i = 0; i < len; i++) {
ret = rk1000_i2c_send(I2C_ADDR_TVE, reg + i, buf[i]);
if (ret)
break;
}
return ret;
}
int rk1000_control_write_block(u8 reg, u8 *buf, u8 len)
{
int i;
int ret;
for (i = 0; i < len; i++) {
ret = rk1000_i2c_send(I2C_ADDR_CTRL, reg + i, buf[i]);
if (ret)
break;
}
return ret;
}
static int __init bootloader_rk1000_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_rk1000_setup);
int rk1000_switch_fb(const struct fb_videomode *modedb, int tv_mode)
{
struct rk_screen *screen;
if (modedb == NULL)
return -1;
screen = kzalloc(sizeof(*screen), GFP_KERNEL);
if (screen == NULL)
return -1;
memset(screen, 0, sizeof(*screen));
/* screen type & face */
screen->type = SCREEN_RGB;
screen->face = OUT_P888;
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 = 0;
/* 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 = 95;
screen->overscan.top = 95;
screen->overscan.right = 95;
screen->overscan.bottom = 95;
/* Operation function*/
screen->init = NULL;
screen->standby = NULL;
switch (tv_mode) {
#ifdef CONFIG_RK1000_TVOUT_CVBS
case TVOUT_CVBS_NTSC:
screen->init = rk1000_tv_ntsc_init;
break;
case TVOUT_CVBS_PAL:
screen->init = rk1000_tv_pal_init;
break;
#endif
#ifdef CONFIG_RK1000_TVOUT_YPBPR
case TVOUT_YPBPR_720X480P_60:
screen->init = rk1000_tv_ypbpr480_init;
break;
case TVOUT_YPBPR_720X576P_50:
screen->init = rk1000_tv_ypbpr576_init;
break;
case TVOUT_YPBPR_1280X720P_50:
screen->init = rk1000_tv_ypbpr720_50_init;
break;
case TVOUT_YPBPR_1280X720P_60:
screen->init = rk1000_tv_ypbpr720_60_init;
break;
#endif
default:
kfree(screen);
return -1;
}
rk_fb_switch_screen(screen, 1 , rk1000_tve.video_source);
rk1000_tve.mode = tv_mode;
kfree(screen);
if (gpio_is_valid(rk1000_tve.io_switch.gpio)) {
if (tv_mode < TVOUT_YPBPR_720X480P_60)
gpio_direction_output(rk1000_tve.io_switch.gpio,
!(rk1000_tve.io_switch.active));
else
gpio_direction_output(rk1000_tve.io_switch.gpio,
rk1000_tve.io_switch.active);
}
return 0;
}
int rk1000_tv_standby(int type)
{
unsigned char val;
int ret;
int ypbpr;
int cvbs;
struct rk_screen screen;
ypbpr = 0;
cvbs = 0;
if (rk1000_tve.ypbpr)
ypbpr = rk1000_tve.ypbpr->enable;
if (rk1000_tve.cvbs)
cvbs = rk1000_tve.cvbs->enable;
if (cvbs || ypbpr)
return 0;
/* val = 0x00;
ret = rk1000_control_write_block(0x03, &val, 1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
} */
val = 0x07;
ret = rk1000_tv_write_block(0x03, &val, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
screen.type = SCREEN_RGB;
rk_fb_switch_screen(&screen, 0 , rk1000_tve.video_source);
pr_err("rk1000 tve standby\n");
return 0;
}
static int rk1000_tve_initial(void)
{
struct rk_screen screen;
/* RK1000 tvencoder i2c reg need dclk, so we open lcdc.*/
memset(&screen, 0, sizeof(struct rk_screen));
/* screen type & face */
screen.type = SCREEN_RGB;
screen.face = OUT_P888;
/* Screen size */
screen.mode.xres = 720;
screen.mode.yres = 480;
/* Timing */
screen.mode.pixclock = 27000000;
screen.mode.refresh = 60;
screen.mode.left_margin = 116;
screen.mode.right_margin = 16;
screen.mode.hsync_len = 6;
screen.mode.upper_margin = 25;
screen.mode.lower_margin = 14;
screen.mode.vsync_len = 6;
rk_fb_switch_screen(&screen, 2 , rk1000_tve.video_source);
/* Power down RK1000 output DAC. */
if (cvbsformat < 0)
return rk1000_i2c_send(I2C_ADDR_TVE, 0x03, 0x07);
else
return 0;
}
static void rk1000_early_suspend(void *h)
{
pr_info("rk1000_early_suspend\n");
if (rk1000_tve.ypbpr) {
if (rk1000_tve.ypbpr->enable)
rk1000_tve.ypbpr->ddev->ops->setenable(
rk1000_tve.ypbpr->ddev, 0);
if (!rk1000_tve.ypbpr->suspend)
rk1000_tve.ypbpr->suspend = 1;
}
if (rk1000_tve.cvbs) {
if (rk1000_tve.cvbs->enable)
rk1000_tve.cvbs->ddev->ops->setenable(
rk1000_tve.cvbs->ddev, 0);
if (!rk1000_tve.cvbs->suspend)
rk1000_tve.cvbs->suspend = 1;
}
}
static void rk1000_early_resume(void *h)
{
pr_info("rk1000 tve exit early resume\n");
if (rk1000_tve.cvbs) {
if (rk1000_tve.cvbs->suspend)
rk1000_tve.cvbs->suspend = 0;
if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60) {
rk_display_device_enable(
(rk1000_tve.cvbs)->ddev);
}
}
if (rk1000_tve.ypbpr) {
if (rk1000_tve.ypbpr->suspend)
rk1000_tve.ypbpr->suspend = 0;
if (rk1000_tve.mode > TVOUT_CVBS_PAL) {
rk_display_device_enable(
(rk1000_tve.ypbpr)->ddev);
}
}
}
static int rk1000_fb_event_notify(struct notifier_block *self,
unsigned long action, void *data)
{
struct fb_event *event;
event = data;
if (action == FB_EARLY_EVENT_BLANK) {
switch (*((int *)event->data)) {
case FB_BLANK_UNBLANK:
break;
default:
rk1000_early_suspend(NULL);
break;
}
} else if (action == FB_EVENT_BLANK) {
switch (*((int *)event->data)) {
case FB_BLANK_UNBLANK:
rk1000_early_resume(NULL);
break;
default:
break;
}
}
return NOTIFY_OK;
}
static struct notifier_block rk1000_fb_notifier = {
.notifier_call = rk1000_fb_event_notify,
};
static int rk1000_tve_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device_node *tve_np;
enum of_gpio_flags flags;
int rc;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
memset(&rk1000_tve, 0, sizeof(struct rk1000_tve));
rk1000_tve.client = client;
#ifdef CONFIG_OF
tve_np = client->dev.of_node;
rk1000_tve.io_switch.gpio = of_get_named_gpio_flags(tve_np,
"gpio-reset",
0, &flags);
if (gpio_is_valid(rk1000_tve.io_switch.gpio)) {
rc = gpio_request(rk1000_tve.io_switch.gpio,
"rk1000-tve-swicth-io");
if (!rc) {
rk1000_tve.io_switch.active = !(flags &
OF_GPIO_ACTIVE_LOW);
gpio_direction_output(rk1000_tve.io_switch.gpio,
!(rk1000_tve.io_switch.active));
} else
pr_err("gpio request rk1000-tve-swicth-io err: %d\n",
rk1000_tve.io_switch.gpio);
}
of_property_read_u32(tve_np, "rockchip,source", &(rc));
rk1000_tve.video_source = rc;
of_property_read_u32(tve_np, "rockchip,prop", &(rc));
rk1000_tve.property = rc - 1;
pr_err("video src is lcdc%d, prop is %d\n", rk1000_tve.video_source,
rk1000_tve.property);
#endif
if (cvbsformat >= 0) {
rk1000_tve.mode = cvbsformat + 1;
} else {
rk1000_tve.mode = RK1000_TVOUT_DEAULT;
rc = rk1000_tve_initial();
if (rc) {
dev_err(&client->dev,
"rk1000 tvencoder probe error %d\n", rc);
return -EINVAL;
}
}
#ifdef CONFIG_RK1000_TVOUT_YPBPR
rk1000_register_display_ypbpr(&client->dev);
#endif
#ifdef CONFIG_RK1000_TVOUT_CVBS
rk1000_register_display_cvbs(&client->dev);
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
rk1000_tve.early_suspend.suspend = rk1000_early_suspend;
rk1000_tve.early_suspend.resume = rk1000_early_resume;
rk1000_tve.early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 11;
register_early_suspend(&(rk1000_tve.early_suspend));
#endif
fb_register_client(&rk1000_fb_notifier);
pr_info("rk1000 tvencoder ver 2.0 probe ok\n");
return 0;
}
static int rk1000_tve_remove(struct i2c_client *client)
{
return 0;
}
static void rk1000_tve_shutdown(struct i2c_client *client)
{
rk1000_i2c_send(I2C_ADDR_TVE, 0x03, 0x07);
}
static const struct i2c_device_id rk1000_tve_id[] = {
{ "rk1000_tve", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rk1000_tve_id);
static struct i2c_driver rk1000_tve_driver = {
.driver = {
.name = "rk1000_tve",
},
.id_table = rk1000_tve_id,
.probe = rk1000_tve_probe,
.remove = rk1000_tve_remove,
.shutdown = rk1000_tve_shutdown,
};
static int __init rk1000_tve_init(void)
{
int ret;
ret = i2c_add_driver(&rk1000_tve_driver);
if (ret < 0)
pr_err("i2c_add_driver err, ret = %d\n", ret);
return ret;
}
static void __exit rk1000_tve_exit(void)
{
i2c_del_driver(&rk1000_tve_driver);
}
late_initcall(rk1000_tve_init);
module_exit(rk1000_tve_exit);
/* Module information */
MODULE_DESCRIPTION("ROCKCHIP rk1000 TV Encoder ");
MODULE_LICENSE("GPL");

View File

@@ -1,79 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RK1000_TVE_H
#define _RK1000_TVE_H
#include <linux/fb.h>
#include <linux/rk_fb.h>
#include <linux/display-sys.h>
#include <linux/mfd/rk1000.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
/******************* TVOUT OUTPUT TYPE **********************/
struct rk1000_monspecs {
struct rk_display_device *ddev;
unsigned int enable;
unsigned int suspend;
struct fb_videomode *mode;
struct list_head modelist;
unsigned int mode_set;
};
struct rk1000_tve {
struct device *dev;
struct i2c_client *client;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
struct ioctrl io_switch;
int video_source;
int property;
int mode;
struct rk1000_monspecs *cvbs;
struct rk1000_monspecs *ypbpr;
};
extern struct rk1000_tve rk1000_tve;
enum {
TVOUT_CVBS_NTSC = 1,
TVOUT_CVBS_PAL,
TVOUT_YPBPR_720X480P_60,
TVOUT_YPBPR_720X576P_50,
TVOUT_YPBPR_1280X720P_50,
TVOUT_YPBPR_1280X720P_60
};
enum {
RK1000_TVOUT_CVBS = 0,
RK1000_TVOUT_YC,
RK1000_TVOUT_YPBPR,
};
#ifdef CONFIG_RK1000_TVOUT_CVBS
#define RK1000_TVOUT_DEAULT TVOUT_CVBS_PAL
#else
#define RK1000_TVOUT_DEAULT TVOUT_YPBPR_1280X720P_60
#endif
int rk1000_control_write_block(u8 reg, u8 *buf, u8 len);
int rk1000_tv_write_block(u8 reg, u8 *buf, u8 len);
int rk1000_tv_standby(int type);
int rk1000_switch_fb(const struct fb_videomode *modedb, int tv_mode);
int rk1000_register_display(struct device *parent);
#ifdef CONFIG_RK1000_TVOUT_YPBPR
int rk1000_tv_ypbpr480_init(void);
int rk1000_tv_ypbpr576_init(void);
int rk1000_tv_ypbpr720_50_init(void);
int rk1000_tv_ypbpr720_60_init(void);
int rk1000_register_display_ypbpr(struct device *parent);
#endif
#ifdef CONFIG_RK1000_TVOUT_CVBS
int rk1000_tv_ntsc_init(void);
int rk1000_tv_pal_init(void);
int rk1000_register_display_cvbs(struct device *parent);
#endif
#endif

View File

@@ -1,208 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/delay.h>
#include "rk1000_tve.h"
static const struct fb_videomode rk1000_cvbs_mode[] = {
{"NTSC", 60, 720, 480, 27000000, 116, 16, 25, 14, 6, 6, 0, 1, 0},
{"PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, 0},
};
static struct rk1000_monspecs cvbs_monspecs;
extern int cvbsformat;
static int changeflag;
int rk1000_tv_ntsc_init(void)
{
unsigned char tv_encoder_regs[] = {0x00, 0x00, 0x00, 0x03, 0x00, 0x00};
unsigned char tv_encoder_control_regs[] = {0x43, 0x01};
int i;
int ret;
if (cvbsformat >= 0)
return 0;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i + 3,
tv_encoder_control_regs + i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
int rk1000_tv_pal_init(void)
{
unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x00, 0x03, 0x00, 0x00};
unsigned char tv_encoder_control_regs[] = {0x41, 0x01};
int i;
int ret;
if (cvbsformat >= 0)
return 0;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i + 3,
tv_encoder_control_regs + i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
static int rk1000_cvbs_set_enable(struct rk_display_device *device, int enable)
{
unsigned char val;
if (cvbs_monspecs.suspend)
return 0;
if ((cvbs_monspecs.enable != enable) ||
(cvbs_monspecs.mode_set != rk1000_tve.mode)) {
if ((enable == 0) && cvbs_monspecs.enable) {
cvbs_monspecs.enable = 0;
rk1000_tv_standby(RK1000_TVOUT_CVBS);
} else if (enable == 1) {
if (cvbsformat >= 0) {
rk1000_switch_fb(cvbs_monspecs.mode,
cvbs_monspecs.mode_set);
cvbsformat = -1;
} else{
val = 0x07;
rk1000_tv_write_block(0x03, &val, 1);
rk1000_switch_fb(cvbs_monspecs.mode,
cvbs_monspecs.mode_set);
if (changeflag == 1)
msleep(600);
val = 0x03;
rk1000_tv_write_block(0x03, &val, 1);
}
cvbs_monspecs.enable = 1;
changeflag = 0;
}
}
return 0;
}
static int rk1000_cvbs_get_enable(struct rk_display_device *device)
{
return cvbs_monspecs.enable;
}
static int rk1000_cvbs_get_status(struct rk_display_device *device)
{
if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60)
return 1;
else
return 0;
}
static int rk1000_cvbs_get_modelist(struct rk_display_device *device,
struct list_head **modelist)
{
*modelist = &(cvbs_monspecs.modelist);
return 0;
}
static int rk1000_cvbs_set_mode(struct rk_display_device *device,
struct fb_videomode *mode)
{
int i;
for (i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++) {
if (fb_mode_is_equal(&rk1000_cvbs_mode[i], mode)) {
if (((i + 1) != rk1000_tve.mode)) {
cvbs_monspecs.mode_set = i + 1;
cvbs_monspecs.mode = (struct fb_videomode *)
&rk1000_cvbs_mode[i];
changeflag = 1;
}
return 0;
}
}
return -1;
}
static int rk1000_cvbs_get_mode(struct rk_display_device *device,
struct fb_videomode *mode)
{
*mode = *(cvbs_monspecs.mode);
return 0;
}
static struct rk_display_ops rk1000_cvbs_display_ops = {
.setenable = rk1000_cvbs_set_enable,
.getenable = rk1000_cvbs_get_enable,
.getstatus = rk1000_cvbs_get_status,
.getmodelist = rk1000_cvbs_get_modelist,
.setmode = rk1000_cvbs_set_mode,
.getmode = rk1000_cvbs_get_mode,
};
static int rk1000_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 = rk1000_tve.property;
device->priv_data = devdata;
device->ops = &rk1000_cvbs_display_ops;
return 1;
}
static struct rk_display_driver display_rk1000_cvbs = {
.probe = rk1000_display_cvbs_probe,
};
int rk1000_register_display_cvbs(struct device *parent)
{
int i;
memset(&cvbs_monspecs, 0, sizeof(struct rk1000_monspecs));
INIT_LIST_HEAD(&cvbs_monspecs.modelist);
for (i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++)
display_add_videomode(&rk1000_cvbs_mode[i],
&cvbs_monspecs.modelist);
if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60) {
cvbs_monspecs.mode = (struct fb_videomode *)
&(rk1000_cvbs_mode[rk1000_tve.mode - 1]);
cvbs_monspecs.mode_set = rk1000_tve.mode;
} else {
cvbs_monspecs.mode = (struct fb_videomode *)
&(rk1000_cvbs_mode[0]);
cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
}
cvbs_monspecs.ddev = rk_display_device_register(&display_rk1000_cvbs,
parent, NULL);
rk1000_tve.cvbs = &cvbs_monspecs;
if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60)
rk_display_device_enable(cvbs_monspecs.ddev);
return 0;
}

View File

@@ -1,240 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/ctype.h>
#include <linux/string.h>
#include "rk1000_tve.h"
static const struct fb_videomode rk1000_ypbpr_mode[] = {
{"YPBPR480P", 60, 720, 480, 27000000, 70, 6, 30, 9, 62, 6, 0, 0, 0},
{"YPBPR576P", 50, 720, 576, 27000000, 74, 6, 39, 5, 64, 5, 0, 0, 0},
{"YPBPR720P@50", 50, 1280, 720, 74250000, 660, 0, 20, 5, 40,
5, 0, 0, 0},
{"YPbPR720P@60", 60, 1280, 720, 74250000, 330, 0, 20, 5, 40,
5, 0, 0, 0},
};
static struct rk1000_monspecs ypbpr_monspecs;
int rk1000_tv_ypbpr480_init(void)
{
unsigned char tv_encoder_regs[] = {0x00, 0x00, 0x40, 0x08, 0x00,
0x02, 0x17, 0x0A, 0x0A};
unsigned char tv_encoder_control_regs[] = {0x00};
int i;
int ret;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i+3,
tv_encoder_control_regs+i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
int rk1000_tv_ypbpr576_init(void)
{
unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08, 0x00,
0x01, 0x17, 0x0A, 0x0A};
unsigned char tv_encoder_control_regs[] = {0x00};
int i;
int ret;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i + 3,
tv_encoder_control_regs + i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
int rk1000_tv_ypbpr720_50_init(void)
{
unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08,
0x00, 0x13, 0x17, 0x0A, 0x0A};
unsigned char tv_encoder_control_regs[] = {0x00};
int i;
int ret;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i+3,
tv_encoder_control_regs+i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
int rk1000_tv_ypbpr720_60_init(void)
{
unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08, 0x00,
0x17, 0x17, 0x0A, 0x0A};
unsigned char tv_encoder_control_regs[] = {0x00};
int i;
int ret;
for (i = 0; i < sizeof(tv_encoder_regs); i++) {
ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
if (ret < 0) {
pr_err("rk1000_tv_write_block err!\n");
return ret;
}
}
for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
ret = rk1000_control_write_block(i + 3,
tv_encoder_control_regs + i,
1);
if (ret < 0) {
pr_err("rk1000_control_write_block err!\n");
return ret;
}
}
return 0;
}
static int rk1000_ypbpr_set_enable(struct rk_display_device *device,
int enable)
{
if (ypbpr_monspecs.suspend)
return 0;
if (ypbpr_monspecs.enable != enable ||
ypbpr_monspecs.mode_set != rk1000_tve.mode) {
if (enable == 0 && ypbpr_monspecs.enable) {
ypbpr_monspecs.enable = 0;
rk1000_tv_standby(RK1000_TVOUT_YPBPR);
} else if (enable == 1) {
rk1000_switch_fb(ypbpr_monspecs.mode,
ypbpr_monspecs.mode_set);
ypbpr_monspecs.enable = 1;
}
}
return 0;
}
static int rk1000_ypbpr_get_enable(struct rk_display_device *device)
{
return ypbpr_monspecs.enable;
}
static int rk1000_ypbpr_get_status(struct rk_display_device *device)
{
if (rk1000_tve.mode > TVOUT_CVBS_PAL)
return 1;
else
return 0;
}
static int rk1000_ypbpr_get_modelist(struct rk_display_device *device,
struct list_head **modelist)
{
*modelist = &(ypbpr_monspecs.modelist);
return 0;
}
static int rk1000_ypbpr_set_mode(struct rk_display_device *device,
struct fb_videomode *mode)
{
int i;
for (i = 0; i < ARRAY_SIZE(rk1000_ypbpr_mode); i++) {
if (fb_mode_is_equal(&rk1000_ypbpr_mode[i], mode)) {
if ((i + 3) != rk1000_tve.mode) {
ypbpr_monspecs.mode_set = i + 3;
ypbpr_monspecs.mode = (struct fb_videomode *)
&rk1000_ypbpr_mode[i];
}
return 0;
}
}
return -1;
}
static int rk1000_ypbpr_get_mode(struct rk_display_device *device,
struct fb_videomode *mode)
{
*mode = *(ypbpr_monspecs.mode);
return 0;
}
static struct rk_display_ops rk1000_ypbpr_display_ops = {
.setenable = rk1000_ypbpr_set_enable,
.getenable = rk1000_ypbpr_get_enable,
.getstatus = rk1000_ypbpr_get_status,
.getmodelist = rk1000_ypbpr_get_modelist,
.setmode = rk1000_ypbpr_set_mode,
.getmode = rk1000_ypbpr_get_mode,
};
static int rk1000_display_ypbpr_probe(struct rk_display_device *device,
void *devdata)
{
device->owner = THIS_MODULE;
strcpy(device->type, "YPbPr");
device->name = "ypbpr";
device->priority = DISPLAY_PRIORITY_YPBPR;
device->property = rk1000_tve.property;
device->priv_data = devdata;
device->ops = &rk1000_ypbpr_display_ops;
return 1;
}
static struct rk_display_driver display_rk1000_ypbpr = {
.probe = rk1000_display_ypbpr_probe,
};
int rk1000_register_display_ypbpr(struct device *parent)
{
int i;
memset(&ypbpr_monspecs, 0, sizeof(struct rk1000_monspecs));
INIT_LIST_HEAD(&ypbpr_monspecs.modelist);
for (i = 0; i < ARRAY_SIZE(rk1000_ypbpr_mode); i++)
display_add_videomode(&rk1000_ypbpr_mode[i],
&ypbpr_monspecs.modelist);
if (rk1000_tve.mode > TVOUT_CVBS_PAL) {
ypbpr_monspecs.mode = (struct fb_videomode *)
&(rk1000_ypbpr_mode[rk1000_tve.mode - 3]);
ypbpr_monspecs.mode_set = rk1000_tve.mode;
} else {
ypbpr_monspecs.mode = (struct fb_videomode *)
&(rk1000_ypbpr_mode[3]);
ypbpr_monspecs.mode_set = TVOUT_YPBPR_1280X720P_60;
}
ypbpr_monspecs.ddev = rk_display_device_register(&display_rk1000_ypbpr,
parent, NULL);
rk1000_tve.ypbpr = &ypbpr_monspecs;
if (rk1000_tve.mode > TVOUT_CVBS_PAL)
rk_display_device_enable(ypbpr_monspecs.ddev);
return 0;
}

View File

@@ -1,8 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config RK3036_TV_ENCODER
bool "rk3036/3128 tv encoder support"
depends on (LCDC_RK3036 || LCDC_RK312X) && RK_TVENCODER
default n
help
Support RK3036 output CVBS.

View File

@@ -1,5 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the rk3036 tv encoder control.
#
obj-$(CONFIG_RK3036_TV_ENCODER) += rk3036_tve.o

View File

@@ -1,573 +0,0 @@
/*
* rk3036_tve.c
*
* Driver for rockchip rk3036 tv encoder control
* Copyright (C) 2014
*
* 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/clk.h>
#include <linux/display-sys.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/rk_fb.h>
#include <linux/rockchip/grf.h>
#include <linux/rockchip/iomap.h>
#include "../../hdmi/rockchip-hdmiv2/rockchip_hdmiv2.h"
#include "rk3036_tve.h"
static const struct fb_videomode rk3036_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, 19, 0, 62, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0},
{"PAL", 50, 720, 576, 27000000, 69, 12, 19, 2, 63, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0},
*/ {"NTSC", 60, 720, 480, 27000000, 43, 33, 19, 0, 62, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0},
{"PAL", 50, 720, 576, 27000000, 48, 33, 19, 2, 63, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0},
};
static struct rk3036_tve *rk3036_tve;
static int cvbsformat = -1;
#define tve_writel(offset, v) writel_relaxed(v, rk3036_tve->regbase + offset)
#define tve_readl(offset) readl_relaxed(rk3036_tve->regbase + offset)
#define tve_dac_writel(offset, v) writel_relaxed(v, rk3036_tve->vdacbase + offset)
#define tve_dac_readl(offset) readl_relaxed(rk3036_tve->vdacbase + offset)
#ifdef DEBUG
#define TVEDBG(format, ...) \
dev_info(rk3036_tve->dev,\
"RK3036 TVE: " format "\n", ## __VA_ARGS__)
#else
#define TVEDBG(format, ...)
#endif
static void dac_enable(bool enable)
{
u32 mask, val;
u32 grfreg = 0;
TVEDBG("%s enable %d\n", __func__, enable);
if (enable) {
mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
if (rk3036_tve->soctype == SOC_RK312X) {
val = m_VBG_EN | m_DAC_EN |
v_DAC_GAIN(rk3036_tve->daclevel);
grfreg = RK312X_GRF_TVE_CON;
} else if (rk3036_tve->soctype == SOC_RK3036) {
val = m_VBG_EN | m_DAC_EN |
v_DAC_GAIN(rk3036_tve->daclevel);
grfreg = RK3036_GRF_SOC_CON3;
} else if (rk3036_tve->soctype == SOC_RK322X) {
val = 0x70;
}
} else {
mask = m_VBG_EN | m_DAC_EN;
val = 0;
if (rk3036_tve->soctype == SOC_RK312X)
grfreg = RK312X_GRF_TVE_CON;
else if (rk3036_tve->soctype == SOC_RK3036)
grfreg = RK3036_GRF_SOC_CON3;
else if (rk3036_tve->soctype == SOC_RK322X)
val = v_CUR_REG(0x7) | m_DR_PWR_DOWN | m_BG_PWR_DOWN;
}
if (grfreg)
grf_writel(grfreg, (mask << 16) | val);
else if (rk3036_tve->vdacbase)
tve_dac_writel(VDAC_VDAC1, val);
}
static void rk322x_dac_init(void)
{
/*tve_dac_writel(VDAC_VDAC0, 0x0);*/
tve_dac_writel(VDAC_VDAC1, v_CUR_REG(0x7) |
m_DR_PWR_DOWN | m_BG_PWR_DOWN);
tve_dac_writel(VDAC_VDAC2, v_CUR_CTR(rk3036_tve->daclevel));
tve_dac_writel(VDAC_VDAC3, v_CAB_EN(0));
}
static void tve_set_mode(int mode)
{
TVEDBG("%s mode %d\n", __func__, mode);
if (cvbsformat >= 0)
return;
if (rk3036_tve->soctype != SOC_RK322X) {
tve_writel(TV_RESET, v_RESET(1));
usleep_range(100, 110);
tve_writel(TV_RESET, v_RESET(0));
}
if (rk3036_tve->inputformat == INPUT_FORMAT_RGB)
tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0));
else
tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3));
tve_writel(TV_LUMA_FILTER0, rk3036_tve->lumafilter0);
tve_writel(TV_LUMA_FILTER1, rk3036_tve->lumafilter1);
tve_writel(TV_LUMA_FILTER2, rk3036_tve->lumafilter2);
if (mode == TVOUT_CVBS_NTSC) {
tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
tve_writel(TV_SATURATION, 0x0042543C);
if (rk3036_tve->test_mode)
tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
else
tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
tve_writel(TV_FREQ_SC, 0x21F07BD7);
tve_writel(TV_SYNC_TIMING, 0x00C07a81);
tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70);
tve_writel(TV_ACT_ST, 0x001500D6);
tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28));
} else if (mode == TVOUT_CVBS_PAL) {
tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) |
v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) |
v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
tve_writel(TV_SATURATION, rk3036_tve->saturation);
tve_writel(TV_BRIGHTNESS_CONTRAST, rk3036_tve->brightcontrast);
tve_writel(TV_FREQ_SC, 0x2A098ACB);
tve_writel(TV_SYNC_TIMING, 0x00C28381);
tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80);
tve_writel(TV_ACT_ST, 0x001500F6);
tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
tve_writel(TV_ADJ_TIMING, rk3036_tve->adjtiming);
tve_writel(TV_ACT_TIMING, 0x0694011D |
(1 << 12) | (2 << 28));
}
}
static int tve_switch_fb(const struct fb_videomode *modedb, int enable)
{
struct rk_screen *screen = &rk3036_tve->screen;
if (!modedb)
return -1;
memset(screen, 0, sizeof(struct rk_screen));
/* screen type & face */
if (rk3036_tve->test_mode)
screen->type = SCREEN_TVOUT_TEST;
else
screen->type = SCREEN_TVOUT;
screen->face = OUT_P888;
screen->color_mode = COLOR_YCBCR;
screen->mode = *modedb;
/* Pin polarity */
if (FB_SYNC_HOR_HIGH_ACT & modedb->sync)
screen->pin_hsync = 1;
else
screen->pin_hsync = 0;
if (FB_SYNC_VERT_HIGH_ACT & modedb->sync)
screen->pin_vsync = 1;
else
screen->pin_vsync = 0;
screen->pin_den = 0;
screen->pin_dclk = 0;
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;
/* Operation function*/
screen->init = NULL;
screen->standby = NULL;
rk_fb_switch_screen(screen, enable, 0);
if (enable) {
if (rk3036_tve->soctype == SOC_RK322X)
ext_pll_set_27m_out();
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)
{
TVEDBG("%s enable %d\n", __func__, enable);
mutex_lock(&rk3036_tve->tve_lock);
if (rk3036_tve->enable != enable) {
rk3036_tve->enable = enable;
if (rk3036_tve->suspend) {
mutex_unlock(&rk3036_tve->tve_lock);
return 0;
}
if (enable == 0) {
dac_enable(false);
cvbsformat = -1;
tve_switch_fb(rk3036_tve->mode, 0);
} else if (enable == 1) {
tve_switch_fb(rk3036_tve->mode, 1);
dac_enable(true);
}
}
mutex_unlock(&rk3036_tve->tve_lock);
return 0;
}
static int cvbs_get_enable(struct rk_display_device *device)
{
TVEDBG("%s enable %d\n", __func__, rk3036_tve->enable);
return rk3036_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 = &rk3036_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(rk3036_cvbs_mode); i++) {
if (fb_mode_is_equal(&rk3036_cvbs_mode[i], mode)) {
if (rk3036_tve->mode != &rk3036_cvbs_mode[i]) {
rk3036_tve->mode =
(struct fb_videomode *)&rk3036_cvbs_mode[i];
if (rk3036_tve->enable && !rk3036_tve->suspend) {
dac_enable(false);
msleep(200);
tve_switch_fb(rk3036_tve->mode, 1);
dac_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 = *rk3036_tve->mode;
return 0;
}
static int
tve_fb_event_notify(struct notifier_block *self,
unsigned long action, void *data)
{
struct fb_event *event = data;
if (action == FB_EARLY_EVENT_BLANK) {
switch (*((int *)event->data)) {
case FB_BLANK_UNBLANK:
break;
default:
TVEDBG("suspend tve\n");
if (!rk3036_tve->suspend) {
rk3036_tve->suspend = 1;
if (rk3036_tve->enable) {
tve_switch_fb(rk3036_tve->mode, 0);
dac_enable(false);
if (rk3036_tve->soctype == SOC_RK322X)
clk_disable_unprepare(rk3036_tve->dac_clk);
}
}
break;
}
} else if (action == FB_EVENT_BLANK) {
switch (*((int *)event->data)) {
case FB_BLANK_UNBLANK:
TVEDBG("resume tve\n");
mutex_lock(&rk3036_tve->tve_lock);
if (rk3036_tve->suspend) {
if (rk3036_tve->soctype == SOC_RK322X) {
clk_prepare_enable(rk3036_tve->dac_clk);
rk322x_dac_init();
}
rk3036_tve->suspend = 0;
if (rk3036_tve->enable) {
tve_switch_fb(rk3036_tve->mode, 1);
dac_enable(true);
}
}
mutex_unlock(&rk3036_tve->tve_lock);
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->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 of_device_id rk3036_tve_dt_ids[] = {
{.compatible = "rockchip,rk3036-tve",},
{.compatible = "rockchip,rk312x-tve",},
{.compatible = "rockchip,rk322x-tve",},
{}
};
#endif
static int __init bootloader_tve_setup(char *str)
{
static int ret;
if (str) {
pr_info("cvbs init tve.format is %s\n", str);
ret = sscanf(str, "%d", &cvbsformat);
}
return 0;
}
early_param("tve.format", bootloader_tve_setup);
static int rk3036_tve_parse_dt(struct device_node *np,
struct rk3036_tve *rk3036_tve)
{
int ret;
u32 val;
if (rk3036_tve->soctype == SOC_RK312X) {
ret = of_property_read_u32(np, "test_mode", &val);
if (ret < 0)
goto errer;
else
rk3036_tve->test_mode = val;
}
ret = of_property_read_u32(np, "saturation", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->saturation = val;
ret = of_property_read_u32(np, "brightcontrast", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->brightcontrast = val;
ret = of_property_read_u32(np, "adjtiming", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->adjtiming = val;
ret = of_property_read_u32(np, "lumafilter0", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->lumafilter0 = val;
ret = of_property_read_u32(np, "lumafilter1", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->lumafilter1 = val;
ret = of_property_read_u32(np, "lumafilter2", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->lumafilter2 = val;
ret = of_property_read_u32(np, "daclevel", &val);
if ((val == 0) || (ret < 0))
goto errer;
else
rk3036_tve->daclevel = val;
return 0;
errer:
return -1;
}
static int rk3036_tve_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
const struct of_device_id *match;
int i;
int ret;
match = of_match_node(rk3036_tve_dt_ids, np);
if (!match)
return PTR_ERR(match);
rk3036_tve = devm_kzalloc(&pdev->dev,
sizeof(struct rk3036_tve), GFP_KERNEL);
if (!rk3036_tve) {
dev_err(&pdev->dev, "rk3036 tv encoder device kmalloc fail!");
return -ENOMEM;
}
if (!strcmp(match->compatible, "rockchip,rk3036-tve")) {
rk3036_tve->soctype = SOC_RK3036;
rk3036_tve->inputformat = INPUT_FORMAT_RGB;
} else if (!strcmp(match->compatible, "rockchip,rk312x-tve")) {
rk3036_tve->soctype = SOC_RK312X;
rk3036_tve->inputformat = INPUT_FORMAT_YUV;
} else if (!strcmp(match->compatible, "rockchip,rk322x-tve")) {
rk3036_tve->soctype = SOC_RK322X;
rk3036_tve->inputformat = INPUT_FORMAT_YUV;
} else {
dev_err(&pdev->dev, "It is not a valid tv encoder!");
return -ENOMEM;
}
ret = rk3036_tve_parse_dt(np, rk3036_tve);
if (ret) {
dev_err(&pdev->dev, "TVE parse dts error!");
return -EINVAL;
}
platform_set_drvdata(pdev, rk3036_tve);
rk3036_tve->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rk3036_tve->reg_phy_base = res->start;
rk3036_tve->len = resource_size(res);
rk3036_tve->regbase = ioremap(res->start, rk3036_tve->len);
if (IS_ERR(rk3036_tve->regbase)) {
dev_err(&pdev->dev,
"rk3036 tv encoder device map registers failed!");
return PTR_ERR(rk3036_tve->regbase);
}
if (rk3036_tve->soctype == SOC_RK322X) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
rk3036_tve->len = resource_size(res);
rk3036_tve->vdacbase = devm_ioremap(rk3036_tve->dev,
res->start,
rk3036_tve->len);
if (IS_ERR(rk3036_tve->vdacbase)) {
dev_err(&pdev->dev,
"rk3036 tv encoder device dac map registers failed!");
return PTR_ERR(rk3036_tve->vdacbase);
}
rk3036_tve->dac_clk =
devm_clk_get(rk3036_tve->dev, "pclk_vdac");
if (IS_ERR(rk3036_tve->dac_clk)) {
dev_err(&pdev->dev,
"Unable to get vdac_clk\n");
return PTR_ERR(rk3036_tve->dac_clk);
}
clk_prepare_enable(rk3036_tve->dac_clk);
if (cvbsformat < 0)
rk322x_dac_init();
}
mutex_init(&rk3036_tve->tve_lock);
INIT_LIST_HEAD(&rk3036_tve->modelist);
for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++)
fb_add_videomode(&rk3036_cvbs_mode[i], &rk3036_tve->modelist);
if (cvbsformat >= 0) {
rk3036_tve->mode =
(struct fb_videomode *)&rk3036_cvbs_mode[cvbsformat];
rk3036_tve->enable = 1;
tve_switch_fb(rk3036_tve->mode, 1);
} else {
rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[1];
}
rk3036_tve->ddev =
rk_display_device_register(&display_cvbs, &pdev->dev, NULL);
rk_display_device_enable(rk3036_tve->ddev);
fb_register_client(&tve_fb_notifier);
cvbsformat = -1;
dev_info(&pdev->dev, "%s tv encoder probe ok\n", match->compatible);
return 0;
}
static void rk3036_tve_shutdown(struct platform_device *pdev)
{
}
static struct platform_driver rk3036_tve_driver = {
.probe = rk3036_tve_probe,
.remove = NULL,
.driver = {
.name = "rk3036-tve",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(rk3036_tve_dt_ids),
},
.shutdown = rk3036_tve_shutdown,
};
static int __init rk3036_tve_init(void)
{
return platform_driver_register(&rk3036_tve_driver);
}
static void __exit rk3036_tve_exit(void)
{
platform_driver_unregister(&rk3036_tve_driver);
}
module_init(rk3036_tve_init);
module_exit(rk3036_tve_exit);
/* Module information */
MODULE_DESCRIPTION("ROCKCHIP RK3036 TV Encoder ");
MODULE_LICENSE("GPL");

View File

@@ -1,159 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __RK3036_TVE_H__
#define __RK3036_TVE_H__
#define TV_CTRL (0x00)
#define m_CVBS_MODE (1 << 24)
#define m_CLK_UPSTREAM_EN (3 << 18)
#define m_TIMING_EN (3 << 16)
#define m_LUMA_FILTER_GAIN (3 << 9)
#define m_LUMA_FILTER_BW (1 << 8)
#define m_CSC_PATH (3 << 1)
#define v_CVBS_MODE(x) ((x & 1) << 24)
#define v_CLK_UPSTREAM_EN(x) ((x & 3) << 18)
#define v_TIMING_EN(x) ((x & 3) << 16)
#define v_LUMA_FILTER_GAIN(x) ((x & 3) << 9)
#define v_LUMA_FILTER_UPSAMPLE(x) ((x & 1) << 8)
#define v_CSC_PATH(x) ((x & 3) << 1)
#define TV_SYNC_TIMING (0x04)
#define TV_ACT_TIMING (0x08)
#define TV_ADJ_TIMING (0x0c)
#define TV_FREQ_SC (0x10)
#define TV_LUMA_FILTER0 (0x14)
#define TV_LUMA_FILTER1 (0x18)
#define TV_LUMA_FILTER2 (0x1C)
#define TV_ACT_ST (0x34)
#define TV_ROUTING (0x38)
#define m_DAC_SENSE_EN (1 << 27)
#define m_Y_IRE_7_5 (1 << 19)
#define m_Y_AGC_PULSE_ON (1 << 15)
#define m_Y_VIDEO_ON (1 << 11)
#define m_Y_SYNC_ON (1 << 7)
#define m_YPP_MODE (1 << 3)
#define m_MONO_EN (1 << 2)
#define m_PIC_MODE (1 << 1)
#define v_DAC_SENSE_EN(x) ((x & 1) << 27)
#define v_Y_IRE_7_5(x) ((x & 1) << 19)
#define v_Y_AGC_PULSE_ON(x) ((x & 1) << 15)
#define v_Y_VIDEO_ON(x) ((x & 1) << 11)
#define v_Y_SYNC_ON(x) ((x & 1) << 7)
#define v_YPP_MODE(x) ((x & 1) << 3)
#define v_MONO_EN(x) ((x & 1) << 2)
#define v_PIC_MODE(x) ((x & 1) << 1)
#define TV_SYNC_ADJUST (0x50)
#define TV_STATUS (0x54)
#define TV_RESET (0x68)
#define m_RESET (1 << 1)
#define v_RESET(x) ((x & 1) << 1)
#define TV_SATURATION (0x78)
#define TV_BW_CTRL (0x8C)
#define m_CHROMA_BW (3 << 4)
#define m_COLOR_DIFF_BW (0xf)
enum {
BP_FILTER_PASS = 0,
BP_FILTER_NTSC,
BP_FILTER_PAL,
};
enum {
COLOR_DIFF_FILTER_OFF = 0,
COLOR_DIFF_FILTER_BW_0_6,
COLOR_DIFF_FILTER_BW_1_3,
COLOR_DIFF_FILTER_BW_2_0
};
#define v_CHROMA_BW(x) ((3 & x) << 4)
#define v_COLOR_DIFF_BW(x) (0xF & x)
#define TV_BRIGHTNESS_CONTRAST (0x90)
#define m_EXTREF_EN (1 << 0)
#define m_VBG_EN (1 << 1)
#define m_DAC_EN (1 << 2)
#define m_SENSE_EN (1 << 3)
#define m_BIAS_EN (7 << 4)
#define m_DAC_GAIN (0x3f << 7)
#define v_DAC_GAIN(x) ((x & 0x3f) << 7)
#define VDAC_VDAC0 (0x00)
#define m_RST_ANA (1 << 7)
#define m_RST_DIG (1 << 6)
#define v_RST_ANA(x) ((x & 1) << 7)
#define v_RST_DIG(x) ((x & 1) << 6)
#define VDAC_VDAC1 (0x280)
#define m_CUR_REG (0xf << 4)
#define m_DR_PWR_DOWN (1 << 1)
#define m_BG_PWR_DOWN (1 << 0)
#define v_CUR_REG(x) ((x & 0xf) << 4)
#define v_DR_PWR_DOWN(x) ((x & 1) << 1)
#define v_BG_PWR_DOWN(x) ((x & 1) << 0)
#define VDAC_VDAC2 (0x284)
#define m_CUR_CTR (0X3f)
#define v_CUR_CTR(x) ((x & 0X3f))
#define VDAC_VDAC3 (0x288)
#define m_CAB_EN (1 << 5)
#define m_CAB_REF (1 << 4)
#define m_CAB_FLAG (1 << 0)
#define v_CAB_EN(x) ((x & 1) << 5)
#define v_CAB_REF(x) ((x & 1) << 4)
#define v_CAB_FLAG(x) ((x & 1) << 0)
enum {
TVOUT_CVBS_NTSC = 0,
TVOUT_CVBS_PAL,
};
enum {
INPUT_FORMAT_RGB = 0,
INPUT_FORMAT_YUV
};
enum {
SOC_RK3036 = 0,
SOC_RK312X,
SOC_RK322X
};
#define TVOUT_DEAULT TVOUT_CVBS_PAL
#define grf_writel(offset, v) do { \
writel_relaxed(v, RK_GRF_VIRT + offset); \
dsb(sy); \
} while (0)
struct rk3036_tve {
struct device *dev;
void __iomem *regbase;
void __iomem *vdacbase;
struct clk *dac_clk;
u32 reg_phy_base;
u32 len;
int soctype;
int inputformat;
struct rk_display_device *ddev;
unsigned int enable;
unsigned int suspend;
struct fb_videomode *mode;
struct list_head modelist;
struct rk_screen screen;
u32 test_mode;
u32 saturation;
u32 brightcontrast;
u32 adjtiming;
u32 lumafilter0;
u32 lumafilter1;
u32 lumafilter2;
u32 daclevel;
struct mutex tve_lock; /* mutex for tve resume operation*/
};
#endif

View File

@@ -1,15 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config RK610_TVOUT
bool "RK610(Jetta) tvout support"
depends on MFD_RK610
default n
help
Support Jetta(RK610) to output YPbPr and CVBS.
config RK610_TVOUT_YPbPr
bool "support YPbPr output"
depends on RK610_TVOUT
config RK610_TVOUT_CVBS
bool "support CVBS output"
depends on RK610_TVOUT

View File

@@ -1,7 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the jetta tv control.
#
obj-$(CONFIG_RK610_TVOUT) += rk610_tv.o
obj-$(CONFIG_RK610_TVOUT_YPbPr) += rk610_tv_ypbpr.o
obj-$(CONFIG_RK610_TVOUT_CVBS) += rk610_tv_cvbs.o

View File

@@ -1,246 +0,0 @@
/*
* rk610_tv.c
*
* Driver for rockchip rk610 tv control
* Copyright (C) 2009
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <asm/uaccess.h>
#include "rk610_tv.h"
#include "../../rk29_fb.h"
#define DRV_NAME "rk610_tvout"
#define RK610_I2C_RATE 100*1000
volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT;
static struct i2c_client *rk610_tv_i2c_client = NULL;
int rk610_tv_wirte_reg(u8 reg, u8 data)
{
int ret;
if(rk610_tv_i2c_client == NULL)
return -1;
ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE);
if (ret > 0)
ret = 0;
return ret;
}
int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode)
{
struct rk_screen *screen;
if(modedb == NULL)
return -1;
screen = kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
if(screen == NULL)
return -1;
memset(screen, 0, sizeof(struct rk_screen));
/* screen type & face */
screen->type = SCREEN_HDMI;
screen->mode = modedb->vmode;
screen->face = modedb->flag;
/* Screen size */
screen->x_res = modedb->xres;
screen->y_res = modedb->yres;
/* Timing */
screen->pixclock = modedb->pixclock;
screen->lcdc_aclk = 500000000;
screen->left_margin = modedb->left_margin;
screen->right_margin = modedb->right_margin;
screen->hsync_len = modedb->hsync_len;
screen->upper_margin = modedb->upper_margin;
screen->lower_margin = modedb->lower_margin;
screen->vsync_len = modedb->vsync_len;
/* Pin polarity */
if(FB_SYNC_HOR_HIGH_ACT & modedb->sync)
screen->pin_hsync = 1;
else
screen->pin_hsync = 0;
if(FB_SYNC_VERT_HIGH_ACT & modedb->sync)
screen->pin_vsync = 1;
else
screen->pin_vsync = 0;
screen->pin_den = 0;
screen->pin_dclk = 0;
/* Swap rule */
screen->swap_rb = 0;
screen->swap_rg = 0;
screen->swap_gb = 0;
screen->swap_delta = 0;
screen->swap_dumy = 0;
/* Operation function*/
screen->init = NULL;
screen->standby = NULL;
switch(tv_mode)
{
#ifdef CONFIG_RK610_TVOUT_CVBS
case TVOUT_CVBS_NTSC:
case TVOUT_CVBS_PAL:
screen->init = rk610_tv_cvbs_init;;
break;
#endif
#ifdef CONFIG_RK610_TVOUT_YPbPr
case TVOUT_YPbPr_720x480p_60:
case TVOUT_YPbPr_720x576p_50:
case TVOUT_YPbPr_1280x720p_50:
case TVOUT_YPbPr_1280x720p_60:
//case TVOUT_YPbPr_1920x1080i_50:
case TVOUT_YPbPr_1920x1080i_60:
case TVOUT_YPbPr_1920x1080p_50:
case TVOUT_YPbPr_1920x1080p_60:
screen->init = rk610_tv_ypbpr_init;
break;
#endif
default:{
kfree(screen);
return -1;
}
break;
}
rk610_tv_output_status = tv_mode;
FB_Switch_Screen(screen, 1);
kfree(screen);
return 0;
}
int rk610_tv_standby(int type)
{
int ret;
switch(type)
{
#ifdef CONFIG_RK610_TVOUT_CVBS
case RK610_TVOUT_CVBS:
if(rk610_cvbs_monspecs.enable == 0)
return 0;
#ifdef CONFIG_RK610_TVOUT_YPbPr
if(rk610_ypbpr_monspecs.enable == 1)
return 0;
#endif
break;
#endif
#ifdef CONFIG_RK610_TVOUT_YPbPr
case RK610_TVOUT_YPBPR:
if(rk610_ypbpr_monspecs.enable == 0)
return 0;
#ifdef CONFIG_RK610_TVOUT_CVBS
if(rk610_cvbs_monspecs.enable == 1)
return 0;
#endif
break;
#endif
default:
break;
}
ret = rk610_tv_wirte_reg(TVE_POWERCR, 0);
if(ret < 0){
printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__);
return ret;
}
ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0);
if(ret < 0){
printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__);
return ret;
}
return 0;
}
static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int rc = 0;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
rc = -ENODEV;
goto failout;
}
rk610_tv_i2c_client = client;
#ifdef CONFIG_RK610_TVOUT_YPbPr
rk610_register_display_ypbpr(&client->dev);
if(rk610_tv_output_status > TVOUT_CVBS_PAL)
rk_display_device_enable(rk610_ypbpr_monspecs.ddev);
#endif
#ifdef CONFIG_RK610_TVOUT_CVBS
rk610_register_display_cvbs(&client->dev);
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
rk_display_device_enable(rk610_cvbs_monspecs.ddev);
#endif
printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n");
return 0;
failout:
kfree(client);
return rc;
}
static int rk610_tv_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id rk610_tv_id[] = {
{ DRV_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rk610_tv_id);
static struct i2c_driver rk610_tv_driver = {
.driver = {
.name = DRV_NAME,
},
.id_table = rk610_tv_id,
.probe = rk610_tv_probe,
.remove = rk610_tv_remove,
};
static int __init rk610_tv_init(void)
{
int ret = 0;
ret = i2c_add_driver(&rk610_tv_driver);
if(ret < 0){
printk("i2c_add_driver err, ret = %d\n", ret);
}
return ret;
}
static void __exit rk610_tv_exit(void)
{
i2c_del_driver(&rk610_tv_driver);
}
module_init(rk610_tv_init);
//late_initcall(rk610_tv_init);
module_exit(rk610_tv_exit);
/* Module information */
MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output");
MODULE_LICENSE("GPL");

View File

@@ -1,132 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RK610_TV_H
#define _RK610_TV_H
#include <linux/display-sys.h>
#include <linux/rk_fb.h>
#include <mach/board.h>
#include <mach/gpio.h>
#ifdef CONFIG_ARCH_RK29
#include <mach/rk29_iomap.h>
#endif
#include "../screen/screen.h"
#include "../../rk29_fb.h"
#include <linux/mfd/rk610_core.h>
#define TVE_VFCR 0x00
#define TVE_VFCR_ENABLE_SUBCARRIER_RESET 0 << 6
#define TVE_VFCR_DISABLE_SUBCARRIER_RESET 1 << 6
#define TVE_VFCR_VIN_RANGE_16_235 0 << 3
#define TVE_VFCR_VIN_RANGE_1_254 1 << 3
#define TVE_VFCR_BLACK_7_5_IRE 0 << 2
#define TVE_VFCR_BLACK_0_IRE 1 << 2
#define TVE_VFCR_NTSC 0
#define TVE_VFCR_PAL_M 1
#define TVE_VFCR_PAL_B_N 2
#define TVE_VFCR_PAL_NC 3
#define TVE_VINCR 0x01
#define TVE_VINCR_PIX_DATA_DELAY(n) (n << 5)
#define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE 0 << 4
#define TVE_VINCR_H_SYNC_POLARITY_POSITIVE 1 << 4
#define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE 0 << 3
#define TVE_VINCR_V_SYNC_POLARITY_POSITIVE 1 << 3
enum {
INPUT_FORMAT_BT601_SLAVE = 0,
INPUT_FORMAT_BT656,
INPUT_FORMAT_BT601_MASTER,
INPUT_FORMAT_INTERNAL_COLLOR_BAR
};
#define TVE_VINCR_INPUT_FORMAT(n) (n << 1)
#define TVE_VINCR_VSYNC_FUNCTION_VSYNC 0
#define TVE_VINCR_VSYNC_FUNCTION_FIELD 1
#define TVE_VOUTCR 0x02
#define TVE_VOUTCR_OUTPUT_CVBS 0 << 6
#define TVE_VOUTCR_OUTPUT_YPBPR 1 << 6
#define TVE_VOUTCR_OUTPUT_ENABLE_BLUE 1 << 5
#define TVE_VOUTCR_OUTPUT_ENABLE_BLACK 1 << 4
#define TVE_VOUTCR_DISABLE_CVBS_COLOR 1 << 3
#define TVE_VOUTCR_CVBS_Y2C_DELAY(n) (n << 0)
#define TVE_POWERCR 0x03
#define TVE_PIX_CLK_INVERSE_ENABLE 1 << 4
#define TVE_DAC_CLK_INVERSE_DISABLE 1 << 3
#define TVE_DAC_Y_ENABLE 1 << 2
#define TVE_DAC_U_ENABLE 1 << 1
#define TVE_DAC_V_ENABLE 1 << 0
#define TVE_HDTVCR 0x05
#define TVE_RESET 1 << 7
#define TVE_FILTER(n) (n << 5)
#define TVE_COLOR_CONVERT_REC601 0 << 4
#define TVE_COLOR_CONVERT_REC709 1 << 4
#define TVE_INPUT_DATA_RGB 0 << 3
#define TVE_INPUT_DATA_YUV 1 << 3
#define TVE_OUTPUT_50HZ 0 << 2
#define TVE_OUTPUT_60HZ 1 << 2
#define TVE_OUTPUT_MODE_PAL_NTSC 0
#define TVE_OUTPUT_MODE_576P 1
#define TVE_OUTPUT_MODE_480P 2
#define TVE_OUTPUT_MODE_720P 3
#define TVE_YADJCR 0x06
#define TVE_OUTPUT_MODE_1080P 1 << 6
#define TVE_OUTPUT_MODE_1080I 1 << 5
#define TVE_Y_ADJ_VALUE(n) n
#define TVE_YCBADJCR 0x07
#define TVE_YCRADJCR 0x08
/******************* TVOUT OUTPUT TYPE **********************/
struct rk610_monspecs {
struct rk_display_device *ddev;
unsigned int enable;
struct fb_videomode *mode;
struct list_head modelist;
unsigned int mode_set;
};
enum {
TVOUT_CVBS_NTSC = 1,
TVOUT_CVBS_PAL,
TVOUT_YPbPr_720x480p_60,
TVOUT_YPbPr_720x576p_50,
TVOUT_YPbPr_1280x720p_50,
TVOUT_YPbPr_1280x720p_60,
//TVOUT_YPbPr_1920x1080i_50,
TVOUT_YPbPr_1920x1080i_60,
TVOUT_YPbPr_1920x1080p_50,
TVOUT_YPbPr_1920x1080p_60
};
#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC
enum {
RK610_TVOUT_CVBS = 0,
RK610_TVOUT_YC,
RK610_TVOUT_YPBPR,
};
extern volatile int rk610_tv_output_status;
extern struct rk_display_ops rk610_display_ops;
extern int FB_Switch_Screen( struct rk_screen *screen, u32 enable );
extern int rk610_tv_wirte_reg(u8 reg, u8 data);
extern int rk610_tv_standby(int type);
extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode);
extern int rk610_register_display(struct device *parent);
#ifdef CONFIG_RK610_TVOUT_YPbPr
extern int rk610_tv_ypbpr_init(void);
extern int rk610_register_display_ypbpr(struct device *parent);
extern struct rk610_monspecs rk610_ypbpr_monspecs;
#endif
#ifdef CONFIG_RK610_TVOUT_CVBS
extern int rk610_tv_cvbs_init(void);
extern int rk610_register_display_cvbs(struct device *parent);
extern struct rk610_monspecs rk610_cvbs_monspecs;
#endif
#endif

View File

@@ -1,210 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/display-sys.h>
#include "rk610_tv.h"
#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
#define RK610_LED_CVBS_PIN RK29_PIN4_PD3
#else
#define RK610_LED_CVBS_PIN INVALID_GPIO
#endif
#ifdef USE_RGB2CCIR
static const struct fb_videomode rk610_cvbs_mode [] = {
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
{ "NTSC", 60, 720, 480, 27000000, 116, 16, 25, 14, 6, 6, 0, 1, OUT_P888 },
{ "PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, OUT_P888 },
};
#else
static const struct fb_videomode rk610_cvbs_mode [] = {
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
{ "NTSC", 60, 720, 480, 27000000, 116, 16, 16, 3, 6, 3, 0, 1, OUT_CCIR656 },
{ "PAL", 50, 720, 576, 27000000, 126, 12, 19, 2, 6, 3, 0, 1, OUT_CCIR656 },
};
#endif
struct rk610_monspecs rk610_cvbs_monspecs;
int rk610_tv_cvbs_init(void)
{
unsigned char TVE_Regs[9];
unsigned char TVE_CON_Reg;
int ret, i;
rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
memset(TVE_Regs, 0, 9);
TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE;
TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
TVE_Regs[TVE_POWERCR] = TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_CVBS;
TVE_Regs[TVE_YADJCR] = 0x17;
TVE_Regs[TVE_YCBADJCR] = 0x10;
TVE_Regs[TVE_YCRADJCR] = 0x10;
switch(rk610_tv_output_status) {
case TVOUT_CVBS_NTSC:
TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC;
#ifdef USE_RGB2CCIR
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE;
#else
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
#endif
break;
case TVOUT_CVBS_PAL:
TVE_Regs[TVE_VFCR] = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N;
#ifdef USE_RGB2CCIR
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE;
#else
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
#endif
break;
default:
return -1;
}
for(i = 0; i < sizeof(TVE_Regs); i++){
// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
if(ret < 0){
printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i);
return ret;
}
}
// printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg);
rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
#ifdef USE_RGB2CCIR
rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01);
#endif
return 0;
}
static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable)
{
if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status)
{
if(enable == 0)
{
rk610_tv_standby(RK610_TVOUT_CVBS);
rk610_cvbs_monspecs.enable = 0;
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
}
else if(enable == 1)
{
rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set);
rk610_cvbs_monspecs.enable = 1;
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW);
}
}
return 0;
}
static int rk610_cvbs_get_enable(struct rk_display_device *device)
{
return rk610_cvbs_monspecs.enable;
}
static int rk610_cvbs_get_status(struct rk_display_device *device)
{
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
return 1;
else
return 0;
}
static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
{
*modelist = &(rk610_cvbs_monspecs.modelist);
return 0;
}
static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
{
int i;
for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
{
if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode))
{
if( ((i + 1) != rk610_tv_output_status) )
{
rk610_cvbs_monspecs.mode_set = i + 1;
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i];
}
return 0;
}
}
return -1;
}
static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
{
*mode = *(rk610_cvbs_monspecs.mode);
return 0;
}
static struct rk_display_ops rk610_cvbs_display_ops = {
.setenable = rk610_cvbs_set_enable,
.getenable = rk610_cvbs_get_enable,
.getstatus = rk610_cvbs_get_status,
.getmodelist = rk610_cvbs_get_modelist,
.setmode = rk610_cvbs_set_mode,
.getmode = rk610_cvbs_get_mode,
};
static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata)
{
device->owner = THIS_MODULE;
strcpy(device->type, "TV");
device->priority = DISPLAY_PRIORITY_TV;
device->priv_data = devdata;
device->ops = &rk610_cvbs_display_ops;
return 1;
}
static struct rk_display_driver display_rk610_cvbs = {
.probe = rk610_display_cvbs_probe,
};
int rk610_register_display_cvbs(struct device *parent)
{
int i;
memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs));
INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist);
for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist);
if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) {
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]);
rk610_cvbs_monspecs.mode_set = rk610_tv_output_status;
}
else {
rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]);
rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
}
rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL);
if(RK610_LED_CVBS_PIN != INVALID_GPIO)
{
if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0)
{
gpio_free(RK610_LED_CVBS_PIN);
dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n ");
return -1;
}
gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp);
gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
}
return 0;
}

View File

@@ -1,230 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/display-sys.h>
#include "rk610_tv.h"
#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
#define RK610_LED_YPbPr_PIN RK29_PIN4_PD5
#else
#define RK610_LED_YPbPr_PIN INVALID_GPIO
#endif
#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg)
static const struct fb_videomode rk610_YPbPr_mode [] = {
//name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag
{ "YPbPr480p", 60, 720, 480, 27000000, 55, 19, 37, 5, 64, 5, 0, 0, OUT_P888 },
{ "YPbPr576p", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, OUT_P888 },
{ "YPbPr720p@50", 50, 1280, 720, 74250000, 600, 0, 20, 5, 100, 5, 0, 0, OUT_P888 },
{ "YPbPr720p@60", 60, 1280, 720, 74250000, 270, 0, 20, 5, 100, 5, 0, 0, OUT_P888 },
//{ "YPbPr1080i@50", 50, 1920, 1080, 148500000, 620, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 },
{ "YPbPr1080i@60", 60, 1920, 1080, 148500000, 180, 0, 15, 2, 100, 5, 0, 1, OUT_CCIR656 },
{ "YPbPr1080p@50", 50, 1920, 1080, 148500000, 620, 0, 36, 4, 100, 5, 0, 0, OUT_P888 },
{ "YPbPr1080p@60", 60, 1920, 1080, 148500000, 180, 0, 36, 4, 100, 5, 0, 0, OUT_P888 },
};
struct rk610_monspecs rk610_ypbpr_monspecs;
int rk610_tv_ypbpr_init(void)
{
unsigned char TVE_Regs[9];
unsigned char TVE_CON_Reg;
int i, ret;
rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
memset(TVE_Regs, 0, 9);
TVE_CON_Reg = 0x00;
TVE_Regs[TVE_VINCR] = TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
TVE_Regs[TVE_POWERCR] = TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
TVE_Regs[TVE_VOUTCR] = TVE_VOUTCR_OUTPUT_YPBPR;
TVE_Regs[TVE_YADJCR] = 0x17;
TVE_Regs[TVE_YCBADJCR] = 0x10;
TVE_Regs[TVE_YCRADJCR] = 0x10;
switch(rk610_tv_output_status)
{
case TVOUT_YPbPr_720x480p_60:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P;
break;
case TVOUT_YPbPr_720x576p_50:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P;
break;
case TVOUT_YPbPr_1280x720p_50:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P;
break;
case TVOUT_YPbPr_1280x720p_60:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P;
break;
/*case TVOUT_YPbPr_1920x1080i_50:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ;
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I;
break;
*/
case TVOUT_YPbPr_1920x1080i_60:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ;
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080I;
break;
case TVOUT_YPbPr_1920x1080p_50:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ;
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P;
break;
case TVOUT_YPbPr_1920x1080p_60:
TVE_Regs[TVE_VFCR] = TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
TVE_Regs[TVE_VINCR] |= TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
TVE_Regs[TVE_HDTVCR] = TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ;
TVE_Regs[TVE_YADJCR] |= TVE_OUTPUT_MODE_1080P;
break;
default:
return -1;
}
rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
for(i = 0; i < sizeof(TVE_Regs); i++){
// printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
if(ret < 0){
E("rk610_tv_wirte_reg %d err!\n", i);
return ret;
}
}
return 0;
}
static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable)
{
if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status)
{
if(enable == 0)
{
rk610_tv_standby(RK610_TVOUT_YPBPR);
rk610_ypbpr_monspecs.enable = 0;
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
}
else if(enable == 1)
{
rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set);
rk610_ypbpr_monspecs.enable = 1;
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW);
}
}
return 0;
}
static int rk610_ypbpr_get_enable(struct rk_display_device *device)
{
return rk610_ypbpr_monspecs.enable;
}
static int rk610_ypbpr_get_status(struct rk_display_device *device)
{
if(rk610_tv_output_status > TVOUT_CVBS_PAL)
return 1;
else
return 0;
}
static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist)
{
*modelist = &(rk610_ypbpr_monspecs.modelist);
return 0;
}
static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
{
int i;
for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
{
if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode))
{
if( (i + 3) != rk610_tv_output_status )
{
rk610_ypbpr_monspecs.mode_set = i + 3;
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i];
}
return 0;
}
}
return -1;
}
static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
{
*mode = *(rk610_ypbpr_monspecs.mode);
return 0;
}
static struct rk_display_ops rk610_ypbpr_display_ops = {
.setenable = rk610_ypbpr_set_enable,
.getenable = rk610_ypbpr_get_enable,
.getstatus = rk610_ypbpr_get_status,
.getmodelist = rk610_ypbpr_get_modelist,
.setmode = rk610_ypbpr_set_mode,
.getmode = rk610_ypbpr_get_mode,
};
static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata)
{
device->owner = THIS_MODULE;
strcpy(device->type, "YPbPr");
device->priority = DISPLAY_PRIORITY_YPbPr;
device->priv_data = devdata;
device->ops = &rk610_ypbpr_display_ops;
return 1;
}
static struct rk_display_driver display_rk610_YPbPr = {
.probe = rk610_display_YPbPr_probe,
};
int rk610_register_display_ypbpr(struct device *parent)
{
int i;
memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs));
INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist);
for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist);
if(rk610_tv_output_status > TVOUT_CVBS_PAL) {
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]);
rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status;
}
else {
rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]);
rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60;
}
rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL);
if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
{
if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0)
{
gpio_free(RK610_LED_YPbPr_PIN);
dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n ");
return -1;
}
gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp);
gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
}
return 0;
}