From: Evoke Zhang Date: Thu, 24 Aug 2017 08:38:22 +0000 (+0800) Subject: tvin: add bt656in and hdmirx_ext support X-Git-Tag: khadas-vims-v0.9.6-release~2876 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3bc6cab0f9cd48df085ce6b3404424a9cd6b8e6c;p=platform%2Fkernel%2Flinux-amlogic.git tvin: add bt656in and hdmirx_ext support PD#149610: tvin: add bt656in & hdmirx_ext support Change-Id: Ic4bde4b8d9c5a945f59023dd6cb961b736c83eb2 Signed-off-by: Evoke Zhang --- diff --git a/MAINTAINERS b/MAINTAINERS index d6907f2..b86b01d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14066,3 +14066,8 @@ M: JinTao Xu F: drivers/amlogic/media/video_processor/ionvideo/ion_priv.h F: drivers/amlogic/media/video_processor/ionvideo/videobuf2-ion.c F: drivers/amlogic/media/video_processor/ionvideo/videobuf2-ion.h + +AMLOGIC TVIN add bt656_in and hdmirx_ext support +M: Evoke Zhang +F: drivers/amlogic/media/vin/tvin/bt656/* +F: drivers/amlogic/media/vin/tvin/hdmirx_ext/* diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index fdd87e2..93ee8c8 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -1009,6 +1009,41 @@ */ tv_bit_mode = <1>; }; + amvdec_656in { + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xd0048000 0x0 0x7c>, + <0x0 0xd0050000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_CLK1_COMP>, + <&clkc CLKID_BT656>, + <&clkc CLKID_BT656_PCLK1>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656", + "clk_gate_bt656_pclk1"; + + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "okay"; + }; + }; + hdmirx_ext { + compatible = "amlogic, hdmirx_ext"; + dev_name = "hdmirx_ext"; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_ext_pins>; + vdin_sel = <0>; + bt656_sel = <1>; + reset-gpios = <&gpio GPIODV_20 GPIO_ACTIVE_HIGH>; + reset_gpio_name = "GPIODV_20"; + reset_gpio_val = <0 1>; /* reset_on, reset_off */ + + ext_dev_name = "sii9135"; + i2c_addr = <0x30>; /* pull_up: 0x31, pull_down: 0x30 */ + i2c_bus = "i2c_bus_c"; + }; amlvecm { compatible = "amlogic, vecm"; @@ -1172,3 +1207,20 @@ //&i2c_b { // status = "okay"; //}; + +//&i2c_c { +// status = "okay"; +// pinctrl-0=<&c_i2c_master_pin1>; +//}; + +&pinctrl_periphs { + hdmirx_ext_pins: hdmirx_ext_pins { + mux { + groups = "dvp_vs", + "dvp_hs", + "dvp_clk", + "dvp_d2_9"; + function = "dvp"; + }; + }; +}; /* end of pinctrl_periphs */ diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index b552db6..34d03b8 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -269,6 +269,9 @@ CONFIG_AMLOGIC_MEDIA_VIN=y CONFIG_AMLOGIC_MEDIA_TVIN=y CONFIG_AMLOGIC_MEDIA_VDIN=y CONFIG_AMLOGIC_MEDIA_VIUIN=y +CONFIG_AMLOGIC_MEDIA_TVIN_BT656=y +CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT=y +CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135=y CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR=y CONFIG_AMLOGIC_V4L_VIDEO=y CONFIG_AMLOGIC_V4L_VIDEO2=y diff --git a/drivers/amlogic/clk/gxl/clk_media.c b/drivers/amlogic/clk/gxl/clk_media.c index 11146e6..8e8b8b9 100644 --- a/drivers/amlogic/clk/gxl/clk_media.c +++ b/drivers/amlogic/clk/gxl/clk_media.c @@ -595,6 +595,57 @@ static struct clk_gate ge2d_gate = { }, }; +/* cts_bt656_clk */ +const char *bt656_parent_names[] = { "fclk_div2", "fclk_div3", "fclk_div5", + "fclk_div7"}; + +static struct clk_mux bt656_clk1_mux = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_clk1_mux", + .ops = &clk_mux_ops, + .parent_names = bt656_parent_names, + .num_parents = 4, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_divider bt656_clk1_div = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_clk1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "bt656_clk1_mux" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate bt656_clk1_gate = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "bt656_clk1_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "bt656_clk1_div" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_hw *bt656_clk1_hws[] = { + [CLKID_BT656_CLK1_MUX - CLKID_BT656_CLK1_MUX] = &bt656_clk1_mux.hw, + [CLKID_BT656_CLK1_DIV - CLKID_BT656_CLK1_MUX] = &bt656_clk1_div.hw, + [CLKID_BT656_CLK1_GATE - CLKID_BT656_CLK1_MUX] = &bt656_clk1_gate.hw, +}; + void amlogic_init_media(void) { /* cts_vdec_clk */ @@ -639,6 +690,10 @@ void amlogic_init_media(void) vapb_mux.reg = clk_base + (u64)(vapb_mux.reg); /* cts_ge2d_clk */ ge2d_gate.reg = clk_base + (u64)(ge2d_gate.reg); + /* cts_bt656_clk1 */ + bt656_clk1_mux.reg = clk_base + (u64)(bt656_clk1_mux.reg); + bt656_clk1_div.reg = clk_base + (u64)(bt656_clk1_div.reg); + bt656_clk1_gate.reg = clk_base + (u64)(bt656_clk1_gate.reg); /* cts_vdec_clk */ clks[CLKID_VDEC_P0_COMP] = clk_register_composite(NULL, @@ -801,6 +856,20 @@ void amlogic_init_media(void) &ge2d_gate.hw); WARN_ON(IS_ERR(clks[CLKID_GE2D_GATE])); + /* cts_bt656_clk1 */ + clks[CLKID_BT656_CLK1_COMP] = clk_register_composite(NULL, + "bt656_clk1_composite", + bt656_parent_names, 4, + bt656_clk1_hws[CLKID_BT656_CLK1_MUX - CLKID_BT656_CLK1_MUX], + &clk_mux_ops, + bt656_clk1_hws[CLKID_BT656_CLK1_DIV - CLKID_BT656_CLK1_MUX], + &clk_divider_ops, + bt656_clk1_hws[CLKID_BT656_CLK1_GATE - CLKID_BT656_CLK1_MUX], + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_BT656_CLK1_COMP])) + pr_err("%s: %d clk_register_composite bt656_clk1_composite error\n", + __func__, __LINE__); + pr_info("%s: register meson media clk\n", __func__); } diff --git a/drivers/amlogic/clk/gxl/gxl.c b/drivers/amlogic/clk/gxl/gxl.c index d7bd8dc..508e91d 100644 --- a/drivers/amlogic/clk/gxl/gxl.c +++ b/drivers/amlogic/clk/gxl/gxl.c @@ -863,7 +863,7 @@ static struct clk_hw *gxl_clk_hws[] = { [CLKID_HDCP22_PCLK] = &gxl_hdcp22_pclk.hw, [CLKID_HDMITX_PCLK] = &gxl_hdmitx_pclk.hw, [CLKID_PDM_PCLK] = &gxl_pdm_pclk.hw, - [CLKID_BT656_PCLK] = &gxl_bt656_pclk.hw, + [CLKID_BT656_PCLK1] = &gxl_bt656_pclk.hw, [CLKID_USB1_TO_DDR] = &gxl_usb1_to_ddr.hw, [CLKID_USB0_TO_DDR] = &gxl_usb0_to_ddr.hw, [CLKID_AIU_PCLK] = &gxl_aiu_pclk.hw, diff --git a/drivers/amlogic/media/vin/tvin/Kconfig b/drivers/amlogic/media/vin/tvin/Kconfig index 9797840..6cd1b0e 100644 --- a/drivers/amlogic/media/vin/tvin/Kconfig +++ b/drivers/amlogic/media/vin/tvin/Kconfig @@ -17,4 +17,6 @@ config AMLOGIC_MEDIA_TVIN if AMLOGIC_MEDIA_TVIN source "drivers/amlogic/media/vin/tvin/vdin/Kconfig" source "drivers/amlogic/media/vin/tvin/viu/Kconfig" +source "drivers/amlogic/media/vin/tvin/bt656/Kconfig" +source "drivers/amlogic/media/vin/tvin/hdmirx_ext/Kconfig" endif diff --git a/drivers/amlogic/media/vin/tvin/Makefile b/drivers/amlogic/media/vin/tvin/Makefile index 1b27bcb..c9dc6f8 100644 --- a/drivers/amlogic/media/vin/tvin/Makefile +++ b/drivers/amlogic/media/vin/tvin/Makefile @@ -7,6 +7,8 @@ tvin_common-objs += tvin_format_table.o tvin_common-objs += tvin_frontend.o tvin_common-objs += tvin_global.o -obj-$(CONFIG_AMLOGIC_MEDIA_VDIN) += vdin/ -obj-$(CONFIG_AMLOGIC_MEDIA_VIUIN) += viu/ +obj-$(CONFIG_AMLOGIC_MEDIA_VDIN) += vdin/ +obj-$(CONFIG_AMLOGIC_MEDIA_VIUIN) += viu/ +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_BT656) += bt656/ +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT) += hdmirx_ext/ diff --git a/drivers/amlogic/media/vin/tvin/bt656/Kconfig b/drivers/amlogic/media/vin/tvin/bt656/Kconfig new file mode 100644 index 0000000..facf7d0 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/bt656/Kconfig @@ -0,0 +1,10 @@ +# +# BT656 Device Driver Configuration +# +config AMLOGIC_MEDIA_TVIN_BT656 + bool "Amlogic bt656 device driver" + default n + help + This option is used to configure Amlogic drivers + of the multimedia input of BT656, which can support + bt601/bt656 signals input. \ No newline at end of file diff --git a/drivers/amlogic/media/vin/tvin/bt656/Makefile b/drivers/amlogic/media/vin/tvin/bt656/Makefile new file mode 100644 index 0000000..fb568c3 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/bt656/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_BT656) += tvin_bt656.o +tvin_bt656-objs := bt656_601_in.o diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c new file mode 100644 index 0000000..3a9d69a --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c @@ -0,0 +1,1430 @@ +/* + * drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #include */ +/* #include */ + +#include "../tvin_global.h" +#include "../tvin_format_table.h" +#include "../tvin_frontend.h" +#include "bt656_601_in.h" + +#define BT656_DEV_NAME "amvdec_656in" +#define BT656_DRV_NAME "amvdec_656in" +#define BT656_CLS_NAME "amvdec_656in" +#define BT656_MOD_NAME "amvdec_656in" + +/* #define HANDLE_BT656IN_IRQ */ + +#define BT656_MAX_DEVS 2 +/* #define BT656IN_ANCI_DATA_SIZE 0x4000 */ + +#define BT656_VER "2017/08/23" + +/* Per-device (per-bank) structure */ + +/* static struct struct am656in_dev_s am656in_dev_; */ +static dev_t am656in_devno; +static struct class *am656in_clsp; +static unsigned char hw_cnt; +static struct am656in_dev_s *am656in_devp[BT656_MAX_DEVS]; + +#ifdef HANDLE_BT656IN_IRQ +static const char bt656in_dec_id[] = "bt656in-dev"; +#endif + +static struct mutex bt656_mutex; + +/* bt656 debug function */ +static ssize_t reg_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + unsigned int argn = 0, addr = 0, value = 0, end = 0; + char *p, *para, *buf_work, cmd = 0; + char *argv[3]; + long val; + struct am656in_dev_s *devp = dev_get_drvdata(dev); + + if ((devp->dec_status & TVIN_AM656_RUNNING) == 0) { + BT656ERR("bt656[%d] is not running.\n", devp->index); + return count; + } + + buf_work = kstrdup(buff, GFP_KERNEL); + p = buf_work; + + for (argn = 0; argn < 3; argn++) { + para = strsep(&p, " "); + if (para == NULL) + break; + argv[argn] = para; + } + + if (argn < 1 || argn > 3) + goto reg_store_exit; + + cmd = argv[0][0]; + switch (cmd) { + case 'r': + case 'R': + if (argn < 2) { + pr_err("syntax error.\n"); + } else{ + /* addr = simple_strtol(argv[1], NULL, 16); */ + if (kstrtol(argv[1], 16, &val) < 0) + break; + addr = val; + value = bt656_rd(devp->index, addr); + pr_info("reg[%d:0x%2x]=0x%08x\n", + devp->index, addr, value); + } + break; + case 'w': + case 'W': + if (argn < 3) { + pr_err("syntax error.\n"); + } else{ + /* value = simple_strtol(argv[1], NULL, 16); */ + if (kstrtol(argv[1], 16, &val) < 0) + break; + value = val; + /* addr = simple_strtol(argv[2], NULL, 16); */ + if (kstrtol(argv[2], 16, &val) < 0) + break; + addr = val; + bt656_wr(devp->index, addr, value); + pr_info("Write reg[%d:0x%2x]=0x%08x\n", + devp->index, addr, + bt656_rd(devp->index, addr)); + } + break; + case 'd': + case 'D': + /* if (argn < 3) { */ + /* pr_err("syntax error.\n"); */ + /* } else { */ + /* addr = simple_strtol(argv[1], NULL, 16); */ + /* if (kstrtol(argv[1], 16, &val) < 0) */ + /* break; */ + /* addr = val; */ + /* end = simple_strtol(argv[2], NULL, 16); */ + /* if (kstrtol(argv[2], 16, &val) < 0) */ + /* break; */ + /* end = val; */ + addr = 0; + end = 0x1f; + for (; addr <= end; addr++) + pr_info("reg[%d:0x%2x]=0x%08x\n", + devp->index, addr, + bt656_rd(devp->index, addr)); + /* } */ + break; + default: + pr_err("not support.\n"); + break; + } + +reg_store_exit: + kfree(buf_work); + return count; +} + +static ssize_t reg_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + ssize_t len = 0; + + len += sprintf(buff+len, "Usage:\n"); + len += sprintf(buff+len, + "\techo [read|write ] addr > reg;\n"); + len += sprintf(buff+len, + "\techo dump > reg; Dump regs.\n"); + len += sprintf(buff+len, "Address format:\n"); + len += sprintf(buff+len, "\taddr : 0xXXXX, 8 bits register address\n"); + + return len; +} +static DEVICE_ATTR(reg, 0644, reg_show, reg_store); + +static void init_656in_dec_parameter(struct am656in_dev_s *devp) +{ + enum tvin_sig_fmt_e fmt; + const struct tvin_format_s *fmt_info_p; + + fmt = devp->para.fmt; + fmt_info_p = tvin_get_fmt_info(fmt); + + if (!fmt_info_p) { + BT656ERR("bt656[%d] %s:invaild fmt %d.\n", + devp->index, __func__, fmt); + return; + } + + if (fmt < TVIN_SIG_FMT_MAX) { + devp->para.v_active = fmt_info_p->v_active; + devp->para.h_active = fmt_info_p->h_active; + devp->para.hsync_phase = 0; + devp->para.vsync_phase = 0; + devp->para.hs_bp = 0; + devp->para.vs_bp = 0; + } +} + +static void init_656in_dec_hdmi_parameter(struct am656in_dev_s *devp) +{ + enum tvin_sig_fmt_e fmt; + const struct tvin_format_s *fmt_info_p; + + fmt = devp->para.fmt; + fmt_info_p = tvin_get_fmt_info(fmt); + + if (!fmt_info_p) { + BT656ERR("bt656[%d] %s:invaild fmt %d.\n", + devp->index, __func__, fmt); + return; + } + + if (fmt < TVIN_SIG_FMT_MAX) { + devp->para.v_active = fmt_info_p->v_active; + devp->para.h_active = fmt_info_p->h_active; + /*devp->para.hsync_phase = fmt_info_p->v_active; + *devp->para.vsync_phase = fmt_info_p->v_active; + */ + devp->para.hs_bp = fmt_info_p->hs_bp; + devp->para.vs_bp = fmt_info_p->vs_bp; + } +} + +static void reset_bt656in_module(struct am656in_dev_s *devp) +{ + int temp_data; + unsigned int offset = devp->index; + + temp_data = bt656_rd(offset, BT_CTRL); + temp_data &= ~(1 << BT_EN_BIT); + bt656_wr(offset, BT_CTRL, temp_data); /* disable BT656 input */ + + /* reset BT656in module. */ + temp_data = bt656_rd(offset, BT_CTRL); + temp_data |= (1 << BT_SOFT_RESET); + bt656_wr(offset, BT_CTRL, temp_data); + + temp_data = bt656_rd(offset, BT_CTRL); + temp_data &= ~(1 << BT_SOFT_RESET); + bt656_wr(offset, BT_CTRL, temp_data); +} + +/* + * NTSC or PAL input(interlace mode): CLOCK + D0~D7(with SAV + EAV ) + */ +static void reinit_bt656in_dec(struct am656in_dev_s *devp) +{ + unsigned int offset = devp->index; + + reset_bt656in_module(devp); + + /* field 0/1 start lcnt: default value */ + bt656_wr(offset, BT_FIELDSADR, (4 << 16) | 4); + /* configuration the BT PORT control */ + /* For standaREAD_CBUS_REG bt656 in stream, + * there's no HSYNC VSYNC pins. + */ + /* So we don't need to configure the port. */ + /* data itself is 8 bits. */ + bt656_wr(offset, BT_PORT_CTRL, 1 << BT_D8B); + + + bt656_wr(offset, BT_SWAP_CTRL, (4 << 0) | /* POS_Y1_IN */ + (5 << 4) | /* POS_Cr0_IN */ + (6 << 8) | /* POS_Y0_IN */ + (7 << 12)); /* POS_CB0_IN */ + + bt656_wr(offset, BT_LINECTRL, 0); + /* there is no use anci in m2 */ + /* ANCI is the field blanking data, like close caption. + * If it connected to digital camara interface, + * the jpeg bitstream also use this ANCI FIFO. + */ + /* bt656_wr(BT_ANCISADR, devp->mem_start); */ + /* bt656_wr(BT_ANCIEADR, 0); //devp->mem_start + devp->mem_size); */ + + bt656_wr(offset, BT_AFIFO_CTRL, (1 << 31) | + (1 << 6) | /* fill _en; */ + (1 << 3)); /* urgent */ + + bt656_wr(offset, BT_INT_CTRL, /* (1 << 5) | //ancififo done int. */ + /* (1 << 4) | //SOF interrupt enable. */ + /* (1 << 3) | //EOF interrupt enable. */ + (1 << 1)); /* | //input overflow interrupt enable. */ + /* (1 << 0)); //bt656 controller error interrupt enable. */ + + bt656_wr(offset, BT_ERR_CNT, (626 << 16) | (1760)); + + if (devp->para.fmt == TVIN_SIG_FMT_BT656IN_576I_50HZ) { + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 22 | (22 << 16)); + /* Line number of the first video start line in field 0/1. */ + bt656_wr(offset, BT_VIDEOSTART, 23 | (23 << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + bt656_wr(offset, BT_VIDEOEND, 312 | + (312 << 16)); + + /* Update bt656 status register when end of frame. */ + bt656_wr(offset, BT_CTRL, (0 << BT_UPDATE_ST_SEL) | + /* Repeated the color data when + * do 4:2:2 -> 4:4:4 data transfer. + */ + (1 << BT_COLOR_REPEAT) | + /* use haREAD_CBUS_REGware to check + * the PAL/NTSC format + * input format if it's + * standaREAD_CBUS_REG BT656 input format. + */ + (1 << BT_AUTO_FMT) | + /* BT656 standaREAD_CBUS_REG interface. */ + (1 << BT_MODE_BIT) | + (1 << BT_EN_BIT) | /* enable BT moduale. */ + /* timing reference is from bit stream. */ + (1 << BT_REF_MODE_BIT) | + /* use external xclk27. */ + (1 << BT_CLK27_SEL_BIT) | + (1 << BT_XCLK27_EN_BIT)); /* xclk27 is input. */ + /* wr(VDIN_WR_V_START_END, 287 | */ + /* (0 << 16)); */ + } else { + /* if(am656in_dec_info.para.fmt == TVIN_SIG_FMT_BT656IN_480I) + * //input is NTSC + */ + + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 21 | (21 << 16)); + /* Line number of the first video start line in field 0/1. */ + bt656_wr(offset, BT_VIDEOSTART, 18 | (18 << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + bt656_wr(offset, BT_VIDEOEND, 257 | + (257 << 16)); + + /* Update bt656 status register when end of frame. */ + bt656_wr(offset, BT_CTRL, (0 << BT_UPDATE_ST_SEL) | + /* Repeated the color data when + * do 4:2:2 -> 4:4:4 data transfer. + */ + (1 << BT_COLOR_REPEAT) | + /* use haREAD_CBUS_REGware to check the + * PAL/NTSC format input format + * if it's standaREAD_CBUS_REG + * BT656 input format. + */ + (1 << BT_AUTO_FMT) | + /* BT656 standaREAD_CBUS_REG interface. */ + (1 << BT_MODE_BIT) | + (1 << BT_EN_BIT) | /* enable BT moduale. */ + /* timing reference is from bit stream. */ + (1 << BT_REF_MODE_BIT) | + (1 << BT_CLK27_SEL_BIT) | /* use external xclk27. */ + (1 << BT_XCLK27_EN_BIT) | /* xclk27 is input. */ + (1 << BT_FMT_MODE_BIT)); /* input format is NTSC */ + /* wr(VDIN_WR_V_START_END, 239 | */ + /* (0 << 16)); */ + + } +} + +/* NTSC or PAL input(interlace mode): CLOCK + D0~D7 + HSYNC + VSYNC + FID */ +static void reinit_bt601in_dec(struct am656in_dev_s *devp) +{ + unsigned int offset = devp->index; + + reset_bt656in_module(devp); + + /* use external idq pin. */ + bt656_wr(offset, BT_PORT_CTRL, (0 << BT_IDQ_EN) | + (1 << BT_IDQ_PHASE) | + /* FID came from HS VS. */ + (1 << BT_FID_HSVS) | + (1 << BT_HSYNC_PHASE) | + (1 << BT_D8B) | + (4 << BT_FID_DELAY) | + (5 << BT_VSYNC_DELAY) | + (5 << BT_HSYNC_DELAY)); + + /* FID field check done point. */ + bt656_wr(offset, BT_601_CTRL2, (10 << 16)); + + /* suppose the input bitstream format is Cb0 Y0 Cr0 Y1. */ + bt656_wr(offset, BT_SWAP_CTRL, (4 << 0) | + (5 << 4) | + (6 << 8) | + (7 << 13)); + + bt656_wr(offset, BT_LINECTRL, (1 << 31) | /*software line ctrl enable*/ + (1644 << 16) | /* 1440 + 204 */ + 220); + + /* ANCI is the field blanking data, like close caption. + * If it connected to digital camara interface, + * the jpeg bitstream also use this ANCI FIFO. + */ + /* wr(BT_ANCISADR, devp->mem_start); */ + /* wr(BT_ANCIEADR, 0);//devp->mem_start + devp->mem_size); */ + + bt656_wr(offset, BT_AFIFO_CTRL, (1 << 31) | + (1 << 6) | /* fill _en; */ + (1 << 3)); /* urgent */ + + bt656_wr(offset, BT_INT_CTRL, /* (1 << 5) | //ancififo done int. */ + /* (1 << 4) | //SOF interrupt enable. */ + /* (1 << 3) | //EOF interrupt enable. */ + (1 << 1)); /* | //input overflow interrupt enable. */ + /* (1 << 0)); //bt656 controller error interrupt enable. */ + bt656_wr(offset, BT_ERR_CNT, (626 << 16) | (2000)); + /* otherwise there is always error flag, */ + /* because the camera input use HREF ont HSYNC, */ + /* there are some lines without HREF sometime */ + bt656_wr(offset, BT_FIELDSADR, (1 << 16) | 1);/* field 0/1 start lcnt */ + + if (devp->para.fmt == TVIN_SIG_FMT_BT601IN_576I_50HZ) { + /* input is PAL */ + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 22 | (22 << 16)); + /* Line number of the first video start line in field 0/1. */ + bt656_wr(offset, BT_VIDEOSTART, 23 | (23 << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + bt656_wr(offset, BT_VIDEOEND, 312 | + (312 << 16)); + /* BT656 standaREAD_CBUS_REG interface. */ + bt656_wr(offset, BT_CTRL, (0 << BT_MODE_BIT) | + (1 << BT_AUTO_FMT) | + /* enable BT moduale. */ + (1 << BT_EN_BIT) | + /* timing reference is from bit stream. */ + (0 << BT_REF_MODE_BIT) | + (0 << BT_FMT_MODE_BIT) | /* PAL */ + (1 << BT_SLICE_MODE_BIT) | + /* use external fid pin. */ + (0 << BT_FID_EN_BIT) | + /* use external xclk27. */ + (1 << BT_CLK27_SEL_BIT) | + /* xclk27 is input. */ + (1 << BT_XCLK27_EN_BIT)); + /* wr(VDIN_WR_V_START_END, 287 | */ + /* (0 << 16)); */ + } else { + /* if(am656in_dec_info.para.fmt == TVIN_SIG_FMT_BT601IN_480I) + * input is NTSC + */ + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 21 | (21 << 16)); + /* Line number of the first video start line in field 0/1. */ + bt656_wr(offset, BT_VIDEOSTART, 18 | (18 << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + bt656_wr(offset, BT_VIDEOEND, 257 | + (257 << 16)); + bt656_wr(offset, BT_CTRL, (0 << BT_MODE_BIT) | + (1 << BT_AUTO_FMT) | + /* enablem656in_star BT moduale. */ + (1 << BT_EN_BIT) | + /* timing reference is from bit stream. */ + (0 << BT_REF_MODE_BIT) | + (1 << BT_FMT_MODE_BIT) | /* NTSC */ + (1 << BT_SLICE_MODE_BIT) | + /* use external fid pin. */ + (0 << BT_FID_EN_BIT) | + /* use external xclk27. */ + (1 << BT_CLK27_SEL_BIT) | + /* xclk27 is input. */ + (1 << BT_XCLK27_EN_BIT)); + /* bt656_wr(VDIN_WR_V_START_END, 239 | */ + /* (0 << 16)); */ + + } +} + +/* CAMERA input(progressive mode): CLOCK + D0~D7 + HREF + VSYNC */ +static void reinit_camera_dec(struct am656in_dev_s *devp) +{ + unsigned int offset = devp->index; + + /* reset_bt656in_module(); */ + unsigned int temp_data; + unsigned char hsync_enable = devp->para.hsync_phase; + unsigned char vsync_enable = devp->para.vsync_phase; + unsigned short hs_bp = devp->para.hs_bp; + unsigned short vs_bp = devp->para.vs_bp; + unsigned int h_active = devp->para.h_active; + unsigned int v_active = devp->para.v_active; + + if (is_meson_m8b_cpu()) { + /* top reset for bt656 */ + /* WRITE_CBUS_REG_BITS(RESET1_REGISTER, 1, 5, 1); */ + /* WRITE_CBUS_REG_BITS(RESET1_REGISTER, 0, 5, 1); */ + aml_cbus_update_bits(RESET1_REGISTER, 0x1<<5, 1); + aml_cbus_update_bits(RESET1_REGISTER, 0x1<<5, 0); + } + /* disable 656,reset */ + bt656_wr(offset, BT_CTRL, 1<<31); + + /*wr(BT_VIDEOSTART, 1 | (1 << 16)); + * //Line number of the first video start line in field 0/1. + * there is a blank + * wr(BT_VIDEOEND , (am656in_dec_info.active_line )); + * //Line number of the last video line in field 1. + * added video end for avoid overflow. + * ((am656in_dec_info.active_line ) << 16)); + */ + /* Line number of the last video line in field 0 */ + + /* use external idq pin. */ + bt656_wr(offset, BT_PORT_CTRL, (0 << BT_IDQ_EN) | + (0 << BT_IDQ_PHASE) | + /* FID came from HS VS. */ + (0 << BT_FID_HSVS) | + (1 << BT_ACTIVE_HMODE) | + (vsync_enable << BT_VSYNC_PHASE) | + (hsync_enable << BT_HSYNC_PHASE) | + (0 << BT_D8B) | + (4 << BT_FID_DELAY) | /* 4 */ + (0 << BT_VSYNC_DELAY) | + (2 << BT_HSYNC_DELAY)); /* 2 */ + + /* WRITE_CBUS_REG(BT_PORT_CTRL,0x421001); */ + /* FID field check done point. */ + bt656_wr(offset, BT_601_CTRL2, (10 << 16)); + + bt656_wr(offset, BT_SWAP_CTRL, + (5 << 0) | /* POS_Cb0_IN */ + (4 << 4) | /* POS_Y0_IN */ + (7 << 8) | /* POS_Cr0_IN */ + (6 << 12)); /* POS_Y1_IN */ + + /* horizontal active data start offset, *2 for 422 sampling */ + bt656_wr(offset, BT_LINECTRL, (1 << 31) | + (((h_active + hs_bp) << 1) << 16) | + (hs_bp << 1));/* horizontal active data start offset */ + + /* ANCI is the field blanking data, like close caption. + * If it connected to digital camara interface, + * the jpeg bitstream also use this ANCI FIFO. + */ + /* bt656_wr(BT_ANCISADR, devp->mem_start); */ + /* bt656_wr(BT_ANCIEADR, 0);//devp->mem_start + devp->mem_size); */ + + bt656_wr(offset, BT_AFIFO_CTRL, (1 << 31) | + (1 << 6) | /* fill _en; */ + (1 << 3)); /* urgent */ + + bt656_wr(offset, BT_INT_CTRL, /* (1 << 5) | //ancififo done int. */ + /* (1 << 4) | //SOF interrupt enable. */ + /* (1 << 3) | //EOF interrupt enable. */ + (1 << 1)); /* input overflow interrupt enable. */ + /* (1 << 0)); //bt656 controller error interrupt enable. */ + + /* total lines per frame and total pixel per line */ + bt656_wr(offset, BT_ERR_CNT, ((2000) << 16) | (2000 * 10)); + /* otherwise there is always error flag, */ + /* because the camera input use HREF ont HSYNC, */ + /* there are some lines without HREF sometime */ + + /* field 0/1 start lcnt */ + bt656_wr(offset, BT_FIELDSADR, (1 << 16) | 1); + + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBISTART, 1 | (1 << 16)); + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 1 | (1 << 16)); + + /* Line number of the first video start + * line in field 0/1.there is a blank + */ + bt656_wr(offset, BT_VIDEOSTART, vs_bp | (vs_bp << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + /* Line number of the last video line in field 0 */ + bt656_wr(offset, BT_VIDEOEND, + ((v_active + vs_bp - 1) | + ((v_active + vs_bp - 1) << 16))); + + bt656_wr(offset, BT_DELAY_CTRL, 0x22222222); + + /* enable BTR656 interface */ + if (devp->para.isp_fe_port == TVIN_PORT_CAMERA) { + temp_data = (1 << BT_EN_BIT) /* enable BT moduale. */ + /* timing reference is from bit stream. */ + |(0 << BT_REF_MODE_BIT) + |(0 << BT_FMT_MODE_BIT) /* PAL */ + |(0 << BT_SLICE_MODE_BIT) /* no ancillay flag. */ + /* BT656 standard interface. */ + |(0 << BT_MODE_BIT) + |(1 << BT_CLOCK_ENABLE) /* enable 656 clock. */ + |(0 << BT_FID_EN_BIT) /* use external fid pin. */ + /* xclk27 is input. change to Raw_mode setting from M8*/ + /* |(0 << BT_XCLK27_EN_BIT) */ + |(0 << BT_PROG_MODE) + |(0 << BT_AUTO_FMT) + |(0 << BT_CAMERA_MODE) /* enable camera mode */ + |(1 << BT_656CLOCK_RESET) + |(1 << BT_SYSCLOCK_RESET) + |(1 << BT_RAW_MODE) /* enable raw data output */ + |(1 << BT_RAW_ISP) /* enable raw data to isp */ + |(0 << 28) /* enable csi2 pin */ + ; + } else { + temp_data = + /* BT656 standard interface. */ + (0 << BT_MODE_BIT) + /* camera mode */ + |(1 << BT_CAMERA_MODE) + /* enable BT data input */ + |(1 << BT_EN_BIT) + /* timing reference is from bit stream. */ + |(0 << BT_REF_MODE_BIT) + |(0 << BT_FMT_MODE_BIT) /* NTSC */ + |(0 << BT_SLICE_MODE_BIT) + /* use external fid pin. */ + |(0 << BT_FID_EN_BIT) + /* enable bt656 clock input */ + |(1 << 7) + |(0 << 18) /* eol_delay //4 */ + |(1 << 16) /* update status for debug */ + /* enable sys clock input */ + |(1 << BT_XCLK27_EN_BIT) + |(0x60000000); /* out of reset for BT_CTRL. */ + } + if ((devp->para.bt_path == BT_PATH_GPIO) || + (devp->para.bt_path == BT_PATH_GPIO_B)) { + temp_data &= (~(1<<28)); + bt656_wr(offset, BT_CTRL, temp_data); + } else if (devp->para.bt_path == BT_PATH_CSI2) { +#ifdef CONFIG_TVIN_ISP + temp_data |= (1<<28); + bt656_wr(offset, BT_CTRL, temp_data); + /* power on mipi csi phy */ + aml_write_cbus(HHI_CSI_PHY_CNTL0, 0xfdc1ff81); + aml_write_cbus(HHI_CSI_PHY_CNTL1, 0x3fffff); + temp_data = aml_read_cbus(HHI_CSI_PHY_CNTL2); + temp_data &= 0x7ff00000; + temp_data |= 0x80000fc0; + aml_write_cbus(HHI_CSI_PHY_CNTL2, temp_data); +#endif + } +} + +/* bt601_hdmi input(progressive or interlace): CLOCK + D0~D7 + HSYNC + VSYNC */ +static void reinit_bt601_hdmi_dec(struct am656in_dev_s *devp) +{ + unsigned int offset = devp->index; + + /* reset_bt656in_module(); */ + unsigned int temp_data; + unsigned char hsync_enable = devp->para.hsync_phase; + unsigned char vsync_enable = devp->para.vsync_phase; + unsigned short hs_bp = devp->para.hs_bp; + unsigned short vs_bp = devp->para.vs_bp; + unsigned int h_active = devp->para.h_active; + unsigned int v_active = devp->para.v_active; + unsigned int fid_check_cnt = devp->para.fid_check_cnt; + +#if 0 + pr_info("para hsync_phase: %d\n" + "para vsync_phase: %d\n" + "para hs_bp: %d\n" + "para vs_bp: %d\n" + "para h_active: %d\n" + "para v_active: %d\n", + hsync_enable, vsync_enable, + hs_bp, vs_bp, h_active, v_active); +#endif + + /* disable 656,reset */ + bt656_wr(offset, BT_CTRL, 1<<31); + + bt656_wr(offset, BT_PORT_CTRL, (0 << BT_IDQ_EN) | + (0 << BT_IDQ_PHASE) | + (1 << BT_ACTIVE_HMODE) | + (vsync_enable << BT_VSYNC_PHASE) | + (hsync_enable << BT_HSYNC_PHASE) | + (0 << BT_D8B) | + (0 << BT_FID_DELAY) | + (0 << BT_FID_HSVS_PCNT) | /* use hs/vs */ + (1 << BT_FID_HSVS) | /* generate fid */ + (0 << BT_VSYNC_DELAY) | + (0 << BT_HSYNC_DELAY)); + + /* FID field check done point. */ + bt656_wr(offset, BT_601_CTRL2, (fid_check_cnt << 16)); + + bt656_wr(offset, BT_SWAP_CTRL, + (4 << 0) | /* POS_Cb0_IN */ + (5 << 4) | /* POS_Y0_IN */ + (6 << 8) | /* POS_Cr0_IN */ + (7 << 12)); /* POS_Y1_IN */ + + /* horizontal active data start offset, *2 for 422 sampling */ + bt656_wr(offset, BT_LINECTRL, (1 << 31) | + (((h_active + hs_bp) << 1) << 16) | + (hs_bp << 1)); + + bt656_wr(offset, BT_AFIFO_CTRL, (1 << 31) | + (1 << 6) | /* fill _en; */ + (1 << 3)); /* urgent */ + + bt656_wr(offset, BT_INT_CTRL, /* (1 << 5) | //ancififo done int. */ + /* (1 << 4) | //SOF interrupt enable. */ + /* (1 << 3) | //EOF interrupt enable. */ + (1 << 1)); /* input overflow interrupt enable. */ + /* (1 << 0)); //bt656 controller error interrupt enable. */ + + /* total lines per frame and total pixel per line */ + bt656_wr(offset, BT_ERR_CNT, ((2000) << 16) | (2000 * 10)); + /* otherwise there is always error flag, */ + /* because the camera input use HREF ont HSYNC, */ + /* there are some lines without HREF sometime */ + + /* field 0/1 start lcnt */ + bt656_wr(offset, BT_FIELDSADR, (0 << 16) | 0); + + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBISTART, 0 | (0 << 16)); + /* field 0/1 VBI last line number */ + bt656_wr(offset, BT_VBIEND, 0 | (0 << 16)); + + /* Line number of the first video start + * line in field 0/1.there is a blank + */ + bt656_wr(offset, BT_VIDEOSTART, vs_bp | (vs_bp << 16)); + /* Line number of the last video line in field 1. + * added video end for avoid overflow. + */ + /* Line number of the last video line in field 0 */ + bt656_wr(offset, BT_VIDEOEND, + ((v_active + vs_bp - 1) | + ((v_active + vs_bp - 1) << 16))); + + bt656_wr(offset, BT_DELAY_CTRL, 0x22222222); + + /* enable BTR656 interface */ + temp_data = + /* BT656 standard interface. */ + (0 << BT_MODE_BIT) + /* camera mode */ + |(1 << BT_CAMERA_MODE) + /* enable BT data input */ + |(1 << BT_EN_BIT) + /* timing reference is from bit stream. */ + |(0 << BT_REF_MODE_BIT) + |(0 << BT_FMT_MODE_BIT) + |(0 << BT_SLICE_MODE_BIT) + /* use external fid pin. */ + |(0 << BT_FID_EN_BIT) + /* enable bt656 clock input */ + |(1 << 7) + |(0 << 18) /* eol_delay */ + |(1 << 16) /* update status for debug */ + /* enable sys clock input */ + |(1 << BT_XCLK27_EN_BIT) + |(0x60000000); /* out of reset for BT_CTRL. */ + + temp_data &= (~(1<<28)); + bt656_wr(offset, BT_CTRL, temp_data); +} + +static void start_amvdec_656_601_camera_in(struct am656in_dev_s *devp) +{ + enum tvin_port_e port = devp->para.port; + + if (devp->dec_status & TVIN_AM656_RUNNING) { + BT656PR("%s: bt656 have started alreadly.\n", __func__); + return; + } + devp->dec_status = TVIN_AM656_RUNNING; + /* NTSC or PAL input(interlace mode): D0~D7(with SAV + EAV ) */ + if (port == TVIN_PORT_BT656) { + devp->para.fmt = TVIN_SIG_FMT_BT656IN_576I_50HZ; + init_656in_dec_parameter(devp); + reinit_bt656in_dec(devp); + /* reset_656in_dec_parameter(); */ + devp->dec_status = TVIN_AM656_RUNNING; + } else if (port == TVIN_PORT_BT601) { + devp->para.fmt = TVIN_SIG_FMT_BT601IN_576I_50HZ; + init_656in_dec_parameter(devp); + reinit_bt601in_dec(devp); + devp->dec_status = TVIN_AM656_RUNNING; + + } else if (port == TVIN_PORT_CAMERA) { + init_656in_dec_parameter(devp); + reinit_camera_dec(devp); + devp->dec_status = TVIN_AM656_RUNNING; + } else if (port == TVIN_PORT_BT656_HDMI) { + init_656in_dec_hdmi_parameter(devp); + reinit_bt601_hdmi_dec(devp); + devp->dec_status = TVIN_AM656_RUNNING; + } else if (port == TVIN_PORT_BT601_HDMI) { + init_656in_dec_hdmi_parameter(devp); + reinit_bt601_hdmi_dec(devp); + devp->dec_status = TVIN_AM656_RUNNING; + } else { + devp->para.fmt = TVIN_SIG_FMT_NULL; + devp->para.port = TVIN_PORT_NULL; + BT656ERR("%s: input is not selected, please try again.\n", + __func__); + return; + } + BT656PR("bt656[%d](%s): %s input port: %s fmt: %s.\n", + devp->index, BT656_VER, __func__, + tvin_port_str(devp->para.port), + tvin_sig_fmt_str(devp->para.fmt)); +} + +static void stop_amvdec_bt656(struct am656in_dev_s *devp) +{ + if (devp->dec_status & TVIN_AM656_RUNNING) { + reset_bt656in_module(devp); + devp->dec_status = TVIN_AM656_STOP; + } else { + BT656PR("bt656[%d]:%s device is not started yet.\n", + devp->index, __func__); + } +} + +static void am656_clktree_control(struct am656in_dev_s *devp, int flag) +{ + BT656PR("bt656[%d]:%s: flag=%d\n", devp->index, __func__, flag); + if (flag) { /* clk enable */ + if (IS_ERR(devp->gate_bt656)) { + BT656ERR("bt656[%d] %s: gate_bt656\n", + devp->index, __func__); + } else { + clk_prepare_enable(devp->gate_bt656); + } + if (IS_ERR(devp->gate_bt656_pclk)) { + BT656ERR("bt656[%d] %s: gate_bt656_pclk\n", + devp->index, __func__); + } else { + clk_prepare_enable(devp->gate_bt656_pclk); + } + if (IS_ERR(devp->bt656_clk)) { + BT656ERR("bt656[%d] %s: bt656_clk\n", + devp->index, __func__); + } else { + clk_prepare_enable(devp->bt656_clk); + } + udelay(100); + } else { /* clk disable */ + if (IS_ERR(devp->bt656_clk)) { + BT656ERR("bt656[%d] %s: bt656_clk\n", + devp->index, __func__); + } else { + clk_disable_unprepare(devp->bt656_clk); + } + if (IS_ERR(devp->gate_bt656_pclk)) { + BT656ERR("bt656[%d] %s: gate_bt656_pclk\n", + devp->index, __func__); + } else { + clk_disable_unprepare(devp->gate_bt656_pclk); + } + if (IS_ERR(devp->gate_bt656)) { + BT656ERR("bt656[%d] %s: gate_bt656\n", + devp->index, __func__); + } else { + clk_disable_unprepare(devp->gate_bt656); + } + } +} + +/* + * return true when need skip frame otherwise return false + */ +static bool am656_check_skip_frame(struct tvin_frontend_s *fe) +{ + struct am656in_dev_s *devp; + + devp = container_of(fe, struct am656in_dev_s, frontend); + if (devp->skip_vdin_frame_count > 0) { + devp->skip_vdin_frame_count--; + return true; + } else + return false; +} +int am656in_support(struct tvin_frontend_s *fe, enum tvin_port_e port) +{ + if ((port < TVIN_PORT_BT656) || (port > TVIN_PORT_BT601_HDMI)) + return -1; + else + return 0; +} + +static int am656in_open(struct inode *node, struct file *file) +{ + struct am656in_dev_s *devp; + + /* Get the per-device structure that contains this cdev */ + devp = container_of(node->i_cdev, struct am656in_dev_s, cdev); + + if (devp->index >= hw_cnt) + return -ENXIO; + + file->private_data = devp; + + BT656PR("open device %s ok\n", dev_name(devp->dev)); + + return 0; +} +static int am656in_release(struct inode *node, struct file *file) +{ + /* struct vdin_dev_s *devp = file->private_data; */ + + file->private_data = NULL; + + /* BT656PR("close device %s ok\n", dev_name(devp->dev)); */ + + return 0; +} + +static const struct file_operations am656in_fops = { + .owner = THIS_MODULE, + .open = am656in_open, + .release = am656in_release, +}; +/*called by vdin && sever for v4l2 framework*/ + +void am656in_start(struct tvin_frontend_s *fe, enum tvin_sig_fmt_e fmt) +{ + struct am656in_dev_s *devp; + + devp = container_of(fe, struct am656in_dev_s, frontend); + + mutex_lock(&bt656_mutex); + start_amvdec_656_601_camera_in(devp); + mutex_unlock(&bt656_mutex); + +} +static void am656in_stop(struct tvin_frontend_s *fe, enum tvin_port_e port) +{ + struct am656in_dev_s *devp; + + devp = container_of(fe, struct am656in_dev_s, frontend); + if ((port < TVIN_PORT_BT656) || (port > TVIN_PORT_BT601_HDMI)) { + BT656ERR("%s: invaild port %d.\n", __func__, port); + return; + } + + mutex_lock(&bt656_mutex); + stop_amvdec_bt656(devp); + BT656PR("bt656[%d] %s stop device stop ok.\n", devp->index, __func__); + mutex_unlock(&bt656_mutex); +} +static void am656in_get_sig_property(struct tvin_frontend_s *fe, + struct tvin_sig_property_s *prop) +{ + struct am656in_dev_s *devp; + + devp = container_of(fe, struct am656in_dev_s, frontend); + prop->color_format = devp->para.cfmt; + prop->dest_cfmt = devp->para.dfmt; + prop->decimation_ratio = 0; +} + +/*as use the spin_lock, + *1--there is no sleep, + *2--it is better to shorter the time, + */ +int am656in_isr(struct tvin_frontend_s *fe, unsigned int hcnt) +{ + unsigned int ccir656_status = 0; + struct am656in_dev_s *devp; + unsigned int offset; + + devp = container_of(fe, struct am656in_dev_s, frontend); + offset = devp->index; + ccir656_status = bt656_rd(offset, BT_STATUS); + if (ccir656_status & 0xf0) /* AFIFO OVERFLOW */ + devp->overflow_cnt++; + if (devp->overflow_cnt > 5) { + devp->overflow_cnt = 0; + /* NTSC or PAL input(interlace mode): D0~D7(with SAV + EAV ) */ + if (devp->para.port == TVIN_PORT_BT656) + reinit_bt656in_dec(devp); + else if (devp->para.port == TVIN_PORT_BT601) + reinit_bt601in_dec(devp); + else if (devp->para.port == TVIN_PORT_BT656_HDMI) + reinit_bt601_hdmi_dec(devp); + else if (devp->para.port == TVIN_PORT_BT601_HDMI) + reinit_bt601_hdmi_dec(devp); + else /* if(am656in_dec_info.para.port == TVIN_PORT_CAMERA) */ + reinit_camera_dec(devp); + /* WRITE_CBUS_REGite 1 to clean the SOF interrupt bit */ + bt656_wr(offset, BT_STATUS, ccir656_status | (1 << 9)); + BT656PR("bt656[%d] %s bt656in fifo overflow.\n", + devp->index, __func__); + } + return 0; +} + +/* + *power on 656 module&init the parameters,such as + *power color fmt...,will be used by vdin + */ +static int am656in_feopen(struct tvin_frontend_s *fe, enum tvin_port_e port) +{ + struct am656in_dev_s *devp; + struct vdin_parm_s *parm = fe->private_data; + + devp = container_of(fe, struct am656in_dev_s, frontend); + + if ((port < TVIN_PORT_BT656) || (port > TVIN_PORT_BT601_HDMI)) { + BT656ERR("bt656[%d] %s:invaild port %d.\n", + devp->index, __func__, port); + return -1; + } + if (port == TVIN_PORT_CAMERA) + devp->skip_vdin_frame_count = parm->skip_count; + + /*copy the param from vdin to bt656*/ + if (!memcpy(&devp->para, parm, sizeof(struct vdin_parm_s))) { + BT656ERR("bt656[%d] %s memcpy error\n", devp->index, __func__); + return -1; + } + /*avoidint the param port is't equal with port*/ + devp->para.port = port; + BT656PR("bt656[%d]:%s: color fmt:%s, hs phase:%u, vs phase:%u\n", + devp->index, __func__, + tvin_color_fmt_str(parm->cfmt), + parm->hsync_phase, parm->vsync_phase); + BT656PR("frame rate:%u, hs_bp:%u, vs_bp:%u\n", + parm->frame_rate, parm->hs_bp, parm->vs_bp); + + /* bt656 clock enable */ + am656_clktree_control(devp, 1); + + return 0; +} +/* + *power off the 656 module,clear the parameters + */ +static void am656in_feclose(struct tvin_frontend_s *fe) +{ + + struct am656in_dev_s *devp = NULL; + enum tvin_port_e port = 0; + + devp = container_of(fe, struct am656in_dev_s, frontend); + port = devp->para.port; + + if ((port < TVIN_PORT_BT656) || (port > TVIN_PORT_BT601_HDMI)) { + BT656ERR("bt656[%d] %s:invaild port %d.\n", + devp->index, __func__, port); + return; + } + + memset(&devp->para, 0, sizeof(struct vdin_parm_s)); + + /* bt656 clock disable */ + am656_clktree_control(devp, 0); +} +static struct tvin_state_machine_ops_s am656_machine_ops = { + .nosig = NULL, + .fmt_changed = NULL, + .get_fmt = NULL, + .fmt_config = NULL, + .adc_cal = NULL, + .pll_lock = NULL, + .get_sig_property = am656in_get_sig_property, + .vga_set_param = NULL, + .vga_get_param = NULL, + .check_frame_skip = am656_check_skip_frame, +}; +static struct tvin_decoder_ops_s am656_decoder_ops_s = { + .support = am656in_support, + .open = am656in_feopen, + .start = am656in_start, + .stop = am656in_stop, + .close = am656in_feclose, + .decode_isr = am656in_isr, +}; + +static int bt656_add_cdev(struct cdev *cdevp, + const struct file_operations *fops, int minor) +{ + int ret; + dev_t devno = MKDEV(MAJOR(am656in_devno), minor); + + cdev_init(cdevp, fops); + cdevp->owner = THIS_MODULE; + ret = cdev_add(cdevp, devno, 1); + return ret; +} + +static struct device *bt656_create_device(struct device *parent, int minor) +{ + dev_t devno = MKDEV(MAJOR(am656in_devno), minor); + + return device_create(am656in_clsp, parent, devno, NULL, "%s%d", + BT656_DEV_NAME, minor); +} + +static void bt656_delete_device(int minor) +{ + dev_t devno = MKDEV(MAJOR(am656in_devno), minor); + + device_destroy(am656in_clsp, devno); +} + +static int amvdec_656in_probe(struct platform_device *pdev) +{ + int ret = 0; + struct am656in_dev_s *devp = NULL; + int bt656_rate; + struct resource *res = 0; + int size = 0; + int index = 0; + struct device_node *child; + const char *str; + char bt656_clk_name[20]; + + BT656PR("%s: start probe .\n", __func__); + + if (is_meson_gxtvbb_cpu() || + is_meson_gxl_cpu() || is_meson_gxm_cpu()) { + hw_cnt = 1; + } else if (is_meson_gxbb_cpu()) { + hw_cnt = 2; + } else { + hw_cnt = 0; + } + if (hw_cnt == 0) { + BT656ERR("no bt656 support for current chip\n"); + return -EFAULT; + } + BT656PR("%s. %d hardware detected!.\n", __func__, hw_cnt); + + mutex_init(&bt656_mutex); + + ret = alloc_chrdev_region(&am656in_devno, 0, hw_cnt, BT656_DEV_NAME); + if (ret < 0) { + BT656ERR("%s: failed to alloc major number\n", __func__); + goto fail_alloc_cdev_region; + } + BT656PR("%s: major %d\n", __func__, MAJOR(am656in_devno)); + + am656in_clsp = class_create(THIS_MODULE, BT656_CLS_NAME); + if (IS_ERR(am656in_clsp)) { + ret = PTR_ERR(am656in_clsp); + BT656ERR("%s: failed to create class\n", __func__); + goto fail_class_create; + } + + for_each_child_of_node(pdev->dev.of_node, child) { + ret = of_property_read_u32(child, "bt656_id", &index); + if (ret) { + BT656ERR("%s: don't find bt656 id.\n", __func__); + goto fail_kmalloc_dev; + } + if ((index == 0) || (index > 2)) { + BT656ERR("%s: invalid bt656 index %d.\n", + __func__, index); + goto fail_kmalloc_dev; + } + + ret = of_property_read_string(child, "status", &str); + if (ret) { + BT656ERR("%s: bt656[%d] don't find status, disabled\n", + __func__, index); + continue; + } else { + if (strncmp(str, "okay", 2)) + continue; + } + + /* malloc dev */ + am656in_devp[index-1] = + kmalloc(sizeof(struct am656in_dev_s), GFP_KERNEL); + if (!am656in_devp[index-1]) { + BT656ERR("%s: devp malloc error\n", __func__); + goto fail_kmalloc_dev; + } + memset(am656in_devp[index-1], 0, sizeof(struct am656in_dev_s)); + + devp = am656in_devp[index-1]; + devp->index = index; + BT656PR("%s: bt656 devp->index =%d\n", __func__, devp->index); + + /* create cdev and register with sysfs */ + ret = bt656_add_cdev(&devp->cdev, &am656in_fops, devp->index); + if (ret) { + BT656ERR("%s: failed to add cdev\n", __func__); + goto fail_add_cdev; + } + devp->dev = bt656_create_device(&pdev->dev, devp->index); + if (IS_ERR(devp->dev)) { + BT656ERR("%s: failed to create device\n", __func__); + ret = PTR_ERR(devp->dev); + goto fail_create_device; + } + + ret = device_create_file(devp->dev, &dev_attr_reg); + if (ret < 0) { + BT656ERR("fail to create dbg attribute file\n"); + goto fail_create_file; + } + + /* set clktree */ + sprintf(bt656_clk_name, "cts_bt656_clk%d", devp->index); + devp->bt656_clk = clk_get(&pdev->dev, bt656_clk_name); + clk_set_rate(devp->bt656_clk, 333333333); + if (!IS_ERR(devp->bt656_clk)) { + bt656_rate = clk_get_rate(devp->bt656_clk); + /*clk_put(devp->bt656_clk);*/ + BT656PR("%s: bt656[%d] clock is %d MHZ\n", + __func__, + devp->index, bt656_rate/1000000); + } else { + BT656ERR("%s: bt656[%d] cannot get %s !!!\n", + __func__, devp->index, bt656_clk_name); + ret = -ENOENT; + goto fail_get_clktree; + } + + devp->gate_bt656 = clk_get(&pdev->dev, "clk_gate_bt656"); + if (IS_ERR(devp->gate_bt656)) { + BT656ERR("%s: cannot get clk_gate_bt656 !!!\n", + __func__); + ret = -ENOENT; + goto fail_get_clktree; + } + + devp->gate_bt656_pclk = clk_get(&pdev->dev, + "clk_gate_bt656_pclk1"); + if (IS_ERR(devp->gate_bt656_pclk)) { + BT656ERR("%s: cannot get clk_gate_bt656_pclk1 !!!\n", + __func__); + ret = -ENOENT; + goto fail_get_clktree; + } + + /* set regmap */ + BT656PR("%s: bt656[%d] start get ioremap .\n", + __func__, devp->index); + res = platform_get_resource(pdev, IORESOURCE_MEM, + (devp->index - 1)); + if (!res) { + BT656ERR("missing memory resource\n"); + ret = -ENOMEM; + goto fail_get_clktree; + } + + size = resource_size(res); + bt656_reg_base[devp->index-1] = + devm_ioremap_nocache(&pdev->dev, res->start, size); + if (!bt656_reg_base[devp->index-1]) { + BT656ERR("bt656[%d] ioremap failed\n", devp->index); + ret = -ENOMEM; + goto fail_get_clktree; + } + BT656PR("%s: bt656[%d] mapped reg_base=0x%p, size=0x%x\n", + __func__, devp->index, + bt656_reg_base[devp->index-1], size); + + /* set drvdata */ + dev_set_drvdata(devp->dev, devp); + + /*register frontend */ + sprintf(devp->frontend.name, "%s%d", + BT656_DEV_NAME, devp->index); + /* tvin_frontend_init(&devp->frontend, + * &am656_decoder_ops_s, &am656_machine_ops, pdev->id); + */ + if (!tvin_frontend_init(&devp->frontend, &am656_decoder_ops_s, + &am656_machine_ops, devp->index)) { + BT656PR("%s: tvin_frontend_init done :%d\n", + __func__, devp->index); + if (tvin_reg_frontend(&devp->frontend)) { + BT656ERR("%s register frontend error\n", + __func__); + } + } + } + BT656PR("driver probe ok.\n"); + + return ret; + +/* + *fail_get_resource_mem: + * devm_release_mem_region(&pdev->dev, res->start, size); + */ +fail_get_clktree: + device_remove_file(devp->dev, &dev_attr_reg); +fail_create_file: + bt656_delete_device(pdev->id); +fail_create_device: + cdev_del(&devp->cdev); +fail_add_cdev: + kfree(devp); +fail_kmalloc_dev: + class_destroy(am656in_clsp); +fail_class_create: + unregister_chrdev_region(am656in_devno, hw_cnt); +fail_alloc_cdev_region: + return ret; +} + +static int amvdec_656in_remove(struct platform_device *pdev) +{ + struct am656in_dev_s *devp; + int index; + + for (index = 0; index < hw_cnt; index++) { + devp = am656in_devp[index]; + if (devp == NULL) + continue; + device_remove_file(devp->dev, &dev_attr_reg); + tvin_unreg_frontend(&devp->frontend); + bt656_delete_device(pdev->id); + cdev_del(&devp->cdev); + kfree((const void *)devp); + } + class_destroy(am656in_clsp); + unregister_chrdev_region(am656in_devno, hw_cnt); + + return 0; +} + +static int amvdec_656in_resume(struct platform_device *pdev) +{ + BT656PR("%s\n", __func__); + return 0; +} + +static int amvdec_656in_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct am656in_dev_s *devp; + int index; + + mutex_lock(&bt656_mutex); + BT656PR("%s\n", __func__); + for (index = 0; index < hw_cnt; index++) { + devp = am656in_devp[index]; + if (devp == NULL) + continue; + if (devp->dec_status & TVIN_AM656_RUNNING) { + reset_bt656in_module(devp); + devp->dec_status = TVIN_AM656_STOP; + am656_clktree_control(devp, 0); + } + } + mutex_unlock(&bt656_mutex); + return 0; +} + +static void amvdec_656in_shutdown(struct platform_device *pdev) +{ + struct am656in_dev_s *devp; + int index; + + BT656PR("%s\n", __func__); + for (index = 0; index < hw_cnt; index++) { + devp = am656in_devp[index]; + if (devp == NULL) + continue; + if (devp->dec_status & TVIN_AM656_RUNNING) { + reset_bt656in_module(devp); + devp->dec_status = TVIN_AM656_STOP; + am656_clktree_control(devp, 0); + } + } +} + + +#ifdef CONFIG_OF +static const struct of_device_id bt656_dt_match[] = { + { + .compatible = "amlogic, amvdec_656in", + }, + {}, +}; +#endif + +static struct platform_driver amvdec_656in_driver = { + .probe = amvdec_656in_probe, + .remove = amvdec_656in_remove, + .suspend = amvdec_656in_suspend, + .resume = amvdec_656in_resume, + .shutdown = amvdec_656in_shutdown, + .driver = { + .name = BT656_DRV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = bt656_dt_match, +#endif + } +}; + +static int __init amvdec_656in_init_module(void) +{ + int ret = 0; + + ret = platform_driver_register(&amvdec_656in_driver); + if (ret != 0) { + BT656ERR("%s: failed to register driver\n", __func__); + return -1; + } + + return 0; +} + +static void __exit amvdec_656in_exit_module(void) +{ + platform_driver_unregister(&amvdec_656in_driver); +} + +module_init(amvdec_656in_init_module); +module_exit(amvdec_656in_exit_module); + +MODULE_DESCRIPTION("AMLOGIC BT656_601 input driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("2.0.0"); + diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.h b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.h new file mode 100644 index 0000000..edbf2a1 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.h @@ -0,0 +1,318 @@ +/* + * drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __BT656_601_INPUT_H +#define __BT656_601_INPUT_H + +#include +#include +#include +#include "../tvin_frontend.h" +#include "../tvin_global.h" +#include + +#define BT656PR(fmt, args...) pr_info("amvdec_bt656in: "fmt"", ## args) +#define BT656ERR(fmt, args...) pr_err("amvdec_bt656in: error: "fmt"", ## args) + + +#define BT656_1 0xd0048000//0xd0048000~0xd004_ffff +#define BT656_2 0xd0050000//0xd0050000~0xd005_ffff + +/* registers */ +#define BT_CTRL 0x00 +#define BT_VBISTART 0x01 +#define BT_VBIEND 0x02 +#define BT_FIELDSADR 0x03 +#define BT_LINECTRL 0x04 +#define BT_VIDEOSTART 0x05 +#define BT_VIDEOEND 0x06 +#define BT_SLICELINE0 0x07 +#define BT_SLICELINE1 0x08 +#define BT_PORT_CTRL 0x09 +#define BT_SWAP_CTRL 0x0a +#define BT_AFIFO_CTRL 0x0d +#define BT_601_CTRL0 0x0e +#define BT_601_CTRL1 0x0f +#define BT_601_CTRL2 0x10 +#define BT_601_CTRL3 0x11 +#define BT_FIELD_LUMA 0x12 +#define BT_RAW_CTRL 0x13 +#define BT_STATUS 0x14 +#define BT_INT_CTRL 0x15 +#define BT_VLINE_STATUS 0x17 +#define BT_ERR_CNT 0x19 +#define BT_LCNT_STATUS 0x1a +#define BT_PCNT_STATUS 0x1c +#define BT_DELAY_CTRL 0x1d + +/* #define VDIN_WR_V_START_END 0x1222 */ +#define RESET1_REGISTER 0x1102 +#define HHI_CSI_PHY_CNTL0 0x10d3 +#define HHI_CSI_PHY_CNTL1 0x10d4 +#define HHI_CSI_PHY_CNTL2 0x10d5 + +/* bit defines */ +/*BT656 MACRO */ +/* #define BT_CTRL 0x0 */ +/* Soft reset */ +#define BT_SOFT_RESET 31 +/* Sync fifo soft reset_n at system clock domain. + * Level reset. 0 = reset. 1 : normal mode. + */ +/* 30 The reset of syncfifo output */ +#define BT_SYSCLOCK_RESET 30 +/* Sync fifo soft reset_n at bt656 clock domain. + * Level reset. 0 = reset. 1 : normal mode. + */ +/* 29 The reset of syncfifo input */ +#define BT_656CLOCK_RESET 29 +/*0: use 3 port send raw data; + * 1: use 1 port send raw data; + */ +#define BT_RAW_ISP 27 +/* 25:26 VDIN VS selection. 00 : SOF. 01: EOF. + * 10: vbi start point. 11 : vbi end point. + */ +#define BT_VSYNC_SEL 25 +/* 24:23 VDIN HS selection. 00 : EAV. 01: SAV. + * 10: EOL. 11: SOL + */ +#define BT_HSYNC_SEL 23 +/* Camera_mode */ +#define BT_CAMERA_MODE 22 +/* 16 Update all status register. */ +#define BT_UPDATE_ST_SEL 16 +/* 15 Format select of YCbCr422 to YCbCr444. */ +#define BT_COLOR_REPEAT 15 +/* 14 Input format and output format. + *0:YCbCr;1:565RGB; + *2:1byte raw;3:2byte raw; + */ +#define BT_VIDEO_MODE 14 +/*12 Go to ntsc/pal state.*/ +#define BT_AUTO_FMT 12 +/*11 Go to DVP state.*/ +#define BT_PROG_MODE 11 +/* 9 Go to RAW state. */ +#define BT_RAW_MODE 9 +/* 1: enable bt656 clock. 0: + * disable bt656 clock. + */ +#define BT_CLOCK_ENABLE 7 +/* 6 clk27_phase Reverse of clk27. */ +#define BT_PHASE_REVERSE 6 +/*5 Reset after error occurs. */ +#define BT_AUTO_COVER_ERROR 5 +/* 2 Use data or port control */ +#define BT_REF_MODE 2 +/* 0 bt_data_en */ +#define BT_EN_BIT 0 + +/* #define BT_LINECTRL 0x04 */ +/* [31] soft_video_active + * 0: control by vs/hs/field; + * 1: control by cnt and sw; + */ +#define BT_SW_VACTIVE 31 +/* [30:16] The end of active pixel*/ +#define BT_HEND 16 +/* [14:0] The start of active pixel*/ +#define BT_HOFFSET 0 + +/* #define BT_VIDEOSTART 0x05 */ +/* [28:16] video1_start The start of active line, field1*/ +#define BT_F1_VSTART 16 +/* [12:0] video0_start The start of active line, field0*/ +#define BT_F0_VSTART 0 + +/* #define BT_VIDEOEND 0x06 */ +/* [28:16] video1_end The end of active line, field1*/ +#define BT_F1_VEND 16 +/* [12:0] video0_end The end of active line, field0*/ +#define BT_F0_VEND 0 + +/* #define BT_SOFT_RESET 31 Soft reset */ +/* #define BT_JPEG_START 30 */ +/* #define BT_JPEG_IGNORE_BYTES 18 //20:18 */ +/* #define BT_JPEG_IGNORE_LAST 17 */ +/* #define BT_UPDATE_ST_SEL 16 */ +/* #define BT_COLOR_REPEAT 15 */ +/* #define BT_VIDEO_MODE 13 // 14:13 */ +/* #define BT_AUTO_FMT 12 */ +/* #define BT_PROG_MODE 11 */ +/* #define BT_JPEG_MODE 10 */ +/* 1 : xclk27 is input. 0 : xclk27 is output. */ +#define BT_XCLK27_EN_BIT 9 +#define BT_FID_EN_BIT 8 /* 1 : enable use FID port. */ +/* 1 : external xclk27 0 : internal clk27. */ +#define BT_CLK27_SEL_BIT 7 +/* 1 : no inverted 0 : inverted. */ +/* #define BT_CLK27_PHASE_BIT 6 */ +/* 1 : auto cover error by hardware. */ +/* #define BT_ACE_MODE_BIT 5 */ +/* 1 : no ancillay flag 0 : with ancillay flag. */ +#define BT_SLICE_MODE_BIT 4 +/* 1 : ntsc 0 : pal. */ +#define BT_FMT_MODE_BIT 3 +/* 1 : from bit stream. 0 : from ports. */ +#define BT_REF_MODE_BIT 2 +/* 1 : BT656 model 0 : SAA7118 mode. */ +#define BT_MODE_BIT 1 + +/* #define BT_PORT_CTRL 0x09 */ +/* 26 data_endian + * 0: afifo_wdata = {data1,data2} + * 1: afifo_wdata = {data2,data1} + */ +#define BT_DATA_ENDIAN 26 +/* 25 clk_inv_sel Reverse clk in*/ +#define BT_CLK_REVERSE 25 +/* 24 dual_edge_clk_en Use dual edge clock*/ +#define BT_CLK_EDGE_EN 24 +/* 23 port_active_hmode + * 0: active data when hsync is low; + * 1: active data when hsync is high; + */ +#define BT_ACTIVE_HMODE 23 +/* 22 vref_fro_vs_only 0: use reference reverse vblank + * 1£ºuse vsync reverse vblank; + */ +#define BT_VREF_VS 22 +/* 21 fid_hsvs_falling For 601 format: + *0: do not use falling edge of vsync + *1:use falling edge of vsync + */ +#define BT_HSVS_FALLING 21 +/* 20 fid_hsvs_rising For 601 format: + *0: do not use rising edge of vsync + *1:use rising edge of vsync + */ +#define BT_HSVS_RISING 20 +/*19 fid_hsvs_pcnt For 601 format: + *0£ºuse hs/vs generate field + *1£ºuse pixel cnt generate field; + */ +#define BT_FID_HSVS_PCNT 19 +/*[18:16] hsync_delay Skew of hsync*/ +#define BT_HSYNC_DELAY 16 +/*[15:13] vsync_delay Skew of vsync*/ +#define BT_VSYNC_DELAY 13 +/*[12:10] fid_delay Skew of field*/ +#define BT_FID_DELAY 10 +/*9 bt_10bto8b When use 8bits data port: + *0£º[9:2]£» + *1£º[9:2] + [1]£ + */ +#define BT_10BTO8B 9 +/*8 bt_d8b 0£ºuse 10bits data port£» + *1£ºuse 8bits data port; + */ +#define BT_D8B 8 +/*7 idq_phase Reverse de port*/ +#define BT_IDQ_PHASE 7 +/*6 idq_en Enable de port*/ +#define BT_IDQ_EN 6 +/*5 fid_hsvs For 601 format: + *0: use hs/vs generate fid; + *1: use field port directly; + */ +#define BT_FID_HSVS 5 +/*4 fid_phase Reverse field port*/ +#define BT_FID_PHASE 4 +/*1 vsync_phase Reverse vsync port*/ +#define BT_HSYNC_PHASE 1 +/*0 hsync_phase Reverse hsync port*/ +#define BT_VSYNC_PHASE 0 + +/* registers rw */ +#define BT656_MAX_DEVS 2 + +static void __iomem *bt656_reg_base[BT656_MAX_DEVS]; + +static int bt656_reg_read(u32 index, unsigned int reg, unsigned int *val) +{ + if (index <= BT656_MAX_DEVS) { + *val = readl(bt656_reg_base[index-1]+reg); + return 0; + } else + return -1; +} + +static int bt656_reg_write(u32 index, unsigned int reg, unsigned int val) +{ + if (index <= BT656_MAX_DEVS) { + writel(val, (bt656_reg_base[index-1]+reg)); + return 0; + } else + return -1; +} + +static inline uint32_t bt656_rd(u32 index, uint32_t reg) +{ + int val; + + bt656_reg_read(index, (reg<<2), &val); + return val; +} + +static inline void bt656_wr(u32 index, uint32_t reg, const uint32_t val) +{ + bt656_reg_write(index, (reg<<2), val); +} + +static inline void bt656_wr_bits(u32 index, uint32_t reg, + const uint32_t value, const uint32_t start, const uint32_t len) +{ + bt656_wr(index, reg, ((bt656_rd(index, reg) & + ~(((1L << (len)) - 1) << (start))) | + (((value) & ((1L << (len)) - 1)) << (start)))); +} + +static inline uint32_t bt656_rd_bits(u32 index, uint32_t reg, + const uint32_t start, const uint32_t len) +{ + uint32_t val; + + val = ((bt656_rd(index, reg) >> (start)) & ((1L << (len)) - 1)); + + return val; +} + +enum am656_status_e { + TVIN_AM656_STOP, + TVIN_AM656_RUNNING, +}; + +struct am656in_dev_s { + int index; + dev_t devt; + struct cdev cdev; + struct device *dev; + /* void __iomem *reg_base; */ + unsigned int overflow_cnt; + unsigned int skip_vdin_frame_count; + enum am656_status_e dec_status; + struct vdin_parm_s para; + struct tvin_frontend_s frontend; + /* clktree */ + struct clk *bt656_clk; + struct clk *gate_bt656; + struct clk *gate_bt656_pclk; +}; + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/Kconfig b/drivers/amlogic/media/vin/tvin/hdmirx_ext/Kconfig new file mode 100644 index 0000000..a797349 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/Kconfig @@ -0,0 +1,17 @@ +# +# Amlogic external hdmirx chips configuration +# + +menuconfig AMLOGIC_MEDIA_TVIN_HDMI_EXT + bool "External hdmirx chips support" + default n + help + This option is used to configure Amlogic drivers + of the multimedia input of external hdmirx, + which can support HDMI signals input. + +if AMLOGIC_MEDIA_TVIN_HDMI_EXT + +source "drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Kconfig" + +endif diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/Makefile b/drivers/amlogic/media/vin/tvin/hdmirx_ext/Makefile new file mode 100644 index 0000000..fc21947 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/Makefile @@ -0,0 +1,10 @@ +# +# Amlogic external hdmirx chips Makefile +# + +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT) += hdmirx_ext.o + +hdmirx_ext-objs := hdmirx_ext_drv.o hdmirx_ext_attrs.o platform_iface.o \ + hdmirx_ext_hw_iface.o vdin_iface.o + +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135) += hw_sii9135/ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.c new file mode 100644 index 0000000..f81b989 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.c @@ -0,0 +1,318 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hdmirx_ext_drv.h" + +#include "hdmirx_ext_hw_iface.h" +#include "hdmirx_ext_attrs.h" +#include "vdin_iface.h" +#include "platform_iface.h" + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +static ssize_t hdmirx_ext_debug_print_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "hdmirx_ext_debug_print: %d\n", + hdmirx_ext_debug_print); +} + +static ssize_t hdmirx_ext_debug_print_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int temp = 0; + int ret; + + ret = kstrtouint(buf, 10, &temp); + hdmirx_ext_debug_print = temp; + pr_info("set hdmirx_ext_debug_print: %d\n", temp); + + return count; +} + +static ssize_t hdmirx_ext_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + return sprintf(buf, "hdmirx_ext_info:\n" + "name: %s\n" + "state: %d\n" + "hw_i2c_addr: 0x%02x\n" + "hw_i2c_bus_index: %d\n" + "hw_en_gpio: %s\n" + "hw_reset_gpio: %s\n" + "hw_pinmux_flag: %d\n" + "vdin_sel : %d\n" + "bt656_sel : %d\n" + "vdin_started: %d\n", + hdrv->name, hdrv->state, + hdrv->hw.i2c_addr, hdrv->hw.i2c_bus_index, + (hdrv->hw.en_gpio.flag) ? + hdrv->hw.en_gpio.name : "null", + (hdrv->hw.reset_gpio.flag) ? + hdrv->hw.reset_gpio.name : "null", + hdrv->hw.pinmux_flag, + hdrv->vdin.vdin_sel, + hdrv->vdin.bt656_sel, + hdrv->vdin.started); +} + +static ssize_t hdmirx_ext_debug_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "todo: debug iface for read\n"); +} + +static ssize_t hdmirx_ext_debug_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + __hw_debug((char *)buf); + + return count; +} + +static ssize_t hdmirx_ext_port_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char port = 0xff; + + port = __hw_get_input_port(); + + return sprintf(buf, "current hdmirx_ext input port = %d\n", port); +} + +static ssize_t hdmirx_ext_port_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned char port = 0; + unsigned long temp; + int ret; + + ret = kstrtoul(buf, 10, &temp); + port = (unsigned char)temp; + + if (port < 4) { + __hw_set_input_port(port); + pr_info("set hdmirx_ext input port = %d\n", port); + } + return count; +} + +static ssize_t hdmirx_ext_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + return sprintf(buf, "hdmirx_ext tvin enable = %d\n", hdrv->user_cmd); +} + +static ssize_t hdmirx_ext_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int argn = 0; + char *p = NULL, *para = NULL; + char *argv[5] = {NULL, NULL, NULL, NULL, NULL}; + char str[3] = {' ', '\n', '\0'}; + unsigned int mode = 0, enable = 0; + /*unsigned int height = 0, width = 0, frame_rate = 0, field_flag = 0;*/ + + p = kstrdup(buf, GFP_KERNEL); + while (1) { + para = strsep(&p, str); + if (para == NULL) + break; + if (*para == '\0') + continue; + argv[argn++] = para; + } + + /*pr_info("argn = %d, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\n", + * argn, argv[0], argv[1], argv[2], argv[3], argv[4]); + */ + if (!strcmp(argv[0], "0")) { /* disable */ + enable = 0; + } else if (!strcmp(argv[0], "1")) { + /* enable, driver will trigger to vdin-stop */ + enable = 1; + } else if (!strcmp(argv[0], "2")) { + /* enable, driver will trigger to vdin-start */ + enable = 2; + } else if (!strcmp(argv[0], "3")) { + /* enable, driver will trigger to vdin-start/vdin-stop */ + enable = 3; + } else if (!strcmp(argv[0], "4")) { + /* enable, driver will not trigger to vdin-start/vdin-stop */ + enable = 4; + } else { + /* enable, driver will trigger specified mode */ + enable = 0xff; + } + + hdrv->user_cmd = enable; + + /*if ((enable==1) && (argn!=5) && (argn!=1)) { + * pr_info("invalid parameters to enable cmd !\n"); + * kfree(p); + * return count; + *} + */ + + if ((enable == 0) && (hdrv->vdin.started == 1)) { + hdmirx_ext_stop_vdin(); + pr_info("hdmirx_ext disable vdin\n"); + } else if (((enable == 1) || (enable == 2) || + (enable == 3) || (enable == 4)) && (hdrv->vdin.started == 0)) { + mode = __hw_get_video_mode(); + hdmirx_ext_start_vdin_mode(mode); + pr_info("hdmirx_ext enable(0x%x) vdin, mode = %d\n", + enable, mode); + } else if ((enable == 0xff) && (hdrv->vdin.started == 0)) { + mode = __plat_get_video_mode_by_name(argv[0]); + hdmirx_ext_start_vdin_mode(mode); + pr_info("hdmirx_ext enable(0x%x) vdin, mode = %d\n", + enable, mode); + } else { + pr_info("error: enable=0x%x, mode=%d, vdin_started=%d\n", + enable, mode, hdrv->vdin.started); + } + + kfree(p); + return count; +} + +static ssize_t hdmirx_ext_video_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int mode = 0xff; + char hdmi_mode_str[16], *mode_str; + unsigned char value; + + value = __hw_is_hdmi_mode(); + + memset(hdmi_mode_str, 0x00, 16); + + strcpy(hdmi_mode_str, (value == 0) ? "DVI:" : "HDMI:"); + mode = __hw_get_video_mode(); + + mode_str = __plat_get_video_mode_name(mode); + + if (strcmp(mode_str, "invalid") != 0) + strcat(hdmi_mode_str, mode_str); + else + strcpy(hdmi_mode_str, mode_str); + return sprintf(buf, "%s\n", hdmi_mode_str); +} + +static ssize_t hdmirx_ext_cable_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + hdrv->status.cable = __hw_get_cable_status(); + return sprintf(buf, "%d\n", hdrv->status.cable); +} + +static ssize_t hdmirx_ext_signal_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + hdrv->status.signal = __hw_get_cable_status(); + return sprintf(buf, "%d\n", hdrv->status.signal); +} + +static ssize_t hdmirx_ext_audio_sr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int audio_sr; + static const char * const audio_sr_array[] = { + "44.1 kHz", /* 0x0 */ + "Not indicated", /* 0x1 */ + "48 kHz", /* 0x2 */ + "32 kHz", /* 0x3 */ + "22.05 kHz", /* 0x4 */ + "reserved", /* 0x5 */ + "24 kHz", /* 0x6 */ + "reserved", /* 0x7 */ + "88.2 kHz", /* 0x8 */ + "768 kHz (192*4)", /* 0x9 */ + "96 kHz", /* 0xa */ + "reserved", /* 0xb */ + "176.4 kHz", /* 0xc */ + "reserved", /* 0xd */ + "192 kHz", /* 0xe */ + "reserved" /* 0xf */ + }; + + audio_sr = __hw_get_audio_sample_rate(); + if ((audio_sr < 0) || (audio_sr > sizeof(audio_sr_array))) + audio_sr = 0; + + return sprintf(buf, "%s\n", audio_sr_array[audio_sr]); +} + +static DEVICE_ATTR(print, 0644, + hdmirx_ext_debug_print_show, hdmirx_ext_debug_print_store); +static DEVICE_ATTR(info, 0444, hdmirx_ext_info_show, NULL); +static DEVICE_ATTR(debug, 0644, hdmirx_ext_debug_show, hdmirx_ext_debug_store); +static DEVICE_ATTR(port, 0644, hdmirx_ext_port_show, hdmirx_ext_port_store); +static DEVICE_ATTR(enable, 0644, + hdmirx_ext_enable_show, hdmirx_ext_enable_store); +static DEVICE_ATTR(video_mode, 0444, hdmirx_ext_video_mode_show, NULL); +static DEVICE_ATTR(cable_status, 0444, hdmirx_ext_cable_status_show, NULL); +static DEVICE_ATTR(signal_status, 0444, hdmirx_ext_signal_status_show, NULL); +static DEVICE_ATTR(audio_sample_rate, 0444, hdmirx_ext_audio_sr_show, NULL); + +int hdmirx_ext_create_device_attrs(struct device *pdevice) +{ + int ret = -1; + + ret = device_create_file(pdevice, &dev_attr_print); + ret |= device_create_file(pdevice, &dev_attr_info); + ret |= device_create_file(pdevice, &dev_attr_debug); + ret |= device_create_file(pdevice, &dev_attr_port); + ret |= device_create_file(pdevice, &dev_attr_enable); + ret |= device_create_file(pdevice, &dev_attr_video_mode); + ret |= device_create_file(pdevice, &dev_attr_cable_status); + ret |= device_create_file(pdevice, &dev_attr_signal_status); + ret |= device_create_file(pdevice, &dev_attr_audio_sample_rate); + + return ret; +} + +void hdmirx_ext_destroy_device_attrs(struct device *pdevice) +{ + device_remove_file(pdevice, &dev_attr_print); + device_remove_file(pdevice, &dev_attr_info); + device_remove_file(pdevice, &dev_attr_debug); + device_remove_file(pdevice, &dev_attr_port); + device_remove_file(pdevice, &dev_attr_enable); + device_remove_file(pdevice, &dev_attr_video_mode); + device_remove_file(pdevice, &dev_attr_cable_status); + device_remove_file(pdevice, &dev_attr_signal_status); + device_remove_file(pdevice, &dev_attr_audio_sample_rate); +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.h new file mode 100644 index 0000000..06c3847 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.h @@ -0,0 +1,24 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_attrs.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMIRX_EXT_DEVICE_ATTRS_H__ +#define __HDMIRX_EXT_DEVICE_ATTRS_H__ + +extern int hdmirx_ext_create_device_attrs(struct device *pdevice); +extern void hdmirx_ext_destroy_device_attrs(struct device *pdevice); + +#endif diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.c new file mode 100644 index 0000000..7519cc1 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.c @@ -0,0 +1,518 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include +#include +#include + +#include "hdmirx_ext_drv.h" +#include "hdmirx_ext_hw_iface.h" +#include "hdmirx_ext_attrs.h" +#include "vdin_iface.h" + +int hdmirx_ext_debug_print; + +static struct hdmirx_ext_drv_s *hdmirx_ext_drv; +static struct class *hdmirx_ext_class; +static dev_t hdmirx_ext_device_id; +static struct device *hdmirx_ext_device; + +struct hdmirx_ext_drv_s *hdmirx_ext_get_driver(void) +{ + if (hdmirx_ext_drv == NULL) + RXEXTERR("%s: hdmirx_ext_drv is null\n", __func__); + + return hdmirx_ext_drv; +} + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +static int hdmirx_ext_start(struct hdmirx_ext_drv_s *hdrv) +{ + int ret = 0; + + RXEXTDBG("%s: start!\n", __func__); + ret = __hw_init(); + if (ret < 0) { + RXEXTERR("%s: failed to init hw\n", __func__); + return -2; + } + ret = __hw_enable(); + if (ret < 0) { + RXEXTERR("%s: failed to enable hw\n", __func__); + return -2; + } + +#if 0 + ret = __hw_setup_timer(); + if (ret < 0) { + RXEXTERR("%s: failed to setup timer, err = %d!\n", + __func__, ret); + return -3; + } + + ret = __hw_setup_irq(); + if (ret < 0) { + RXEXTERR("%s: failed to setup irq, err = %d!\n", + __func__, ret); + return -4; + } + + ret = __hw_setup_task(); + if (ret < 0) { + RXEXTERR("%s: failed to setup task, err = %d!\n", + __func__, ret); + return -5; + } +#endif + + return ret; +} + +static void hdmirx_ext_device_probe(struct platform_device *pdev) +{ + RXEXTDBG("%s: start\n", __func__); + + if (!strncmp(hdmirx_ext_drv->name, "sii9135", 7)) { +#if defined(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135) + hdmirx_ext_register_hw_sii9135(hdmirx_ext_drv); +#endif + } else { + RXEXTERR("%s: invalid device\n", __func__); + } +} + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +static void hdmirx_ext_set_default_params(void) +{ + hdmirx_ext_drv->hw.i2c_addr = 0xff; + hdmirx_ext_drv->hw.i2c_bus_index = -1; + hdmirx_ext_drv->hw.en_gpio.gpio = NULL; + hdmirx_ext_drv->hw.en_gpio.flag = 0; + hdmirx_ext_drv->hw.en_gpio.val_on = -1; + hdmirx_ext_drv->hw.en_gpio.val_off = -1; + hdmirx_ext_drv->hw.reset_gpio.gpio = NULL; + hdmirx_ext_drv->hw.reset_gpio.flag = 0; + hdmirx_ext_drv->hw.reset_gpio.val_on = -1; + hdmirx_ext_drv->hw.reset_gpio.val_off = -1; + hdmirx_ext_drv->hw.pin = NULL; + hdmirx_ext_drv->hw.pinmux_flag = 0; + /* hdmirx_ext_drv->hw.irq_gpio = 0; */ + /* hdmirx_ext_drv->hw.irq_num = -1; */ + hdmirx_ext_drv->hw.get_cable_status = NULL; + hdmirx_ext_drv->hw.get_signal_status = NULL; + hdmirx_ext_drv->hw.get_input_port = NULL; + hdmirx_ext_drv->hw.set_input_port = NULL; + hdmirx_ext_drv->hw.get_video_timming = NULL; + hdmirx_ext_drv->hw.is_hdmi_mode = NULL; + hdmirx_ext_drv->hw.get_audio_sample_rate = NULL; + hdmirx_ext_drv->hw.debug = NULL; + hdmirx_ext_drv->hw.get_chip_version = NULL; + hdmirx_ext_drv->hw.init = NULL; + hdmirx_ext_drv->hw.enable = NULL; + hdmirx_ext_drv->hw.disable = NULL; + + hdmirx_ext_drv->vdin.vdin_sel = 0; + hdmirx_ext_drv->vdin.bt656_sel = 0; + hdmirx_ext_drv->vdin.started = 0; + hdmirx_ext_drv->user_cmd = 0; + + hdmirx_ext_drv->status.cable = 0; + hdmirx_ext_drv->status.signal = 0; + hdmirx_ext_drv->status.video_mode = 0xff; + hdmirx_ext_drv->status.audio_sr = 0; +} + +#ifdef CONFIG_OF +static int hdmirx_ext_get_dts_config(struct device *dev) +{ + struct device_node *of_node = dev->of_node; + unsigned int i2c_index; + const char *str; + unsigned int val, para[3]; + int ret = 0; + + /* for vdin selection */ + ret = of_property_read_u32(of_node, "vdin_sel", &val); + if (ret) { + RXEXTERR("%s: failed to get vdin_sel\n", __func__); + } else { + hdmirx_ext_drv->vdin.vdin_sel = (unsigned char)val; + RXEXTPR("vdin_sel = %d\n", hdmirx_ext_drv->vdin.vdin_sel); + } + ret = of_property_read_u32(of_node, "bt656_sel", &val); + if (ret) { + RXEXTERR("%s: failed to get bt656_sel\n", __func__); + } else { + hdmirx_ext_drv->vdin.bt656_sel = (unsigned char)val; + RXEXTPR("bt656_sel = %d\n", hdmirx_ext_drv->vdin.bt656_sel); + } + + /* for device name */ + ret = of_property_read_string(of_node, "ext_dev_name", &str); + if (ret) { + RXEXTERR("failed to get ext_dev_name\n"); + str = "invalid"; + } + strcpy(hdmirx_ext_drv->name, str); + + /* for i2c address */ + ret = of_property_read_u32(of_node, "i2c_addr", &val); + if (ret) { + RXEXTERR("%s: failed to get i2c_addr\n", __func__); + } else { + hdmirx_ext_drv->hw.i2c_addr = (unsigned char)val; + RXEXTPR("i2c_addr = 0x%02x\n", hdmirx_ext_drv->hw.i2c_addr); + } + + /* for i2c bus */ + ret = of_property_read_string(of_node, "i2c_bus", &str); + if (ret) { + RXEXTERR("%s: failed to get i2c_bus\n", __func__); + return -1; + } + if (!strncmp(str, "i2c_bus_ao", 10)) + i2c_index = AML_I2C_MASTER_AO; + else if (!strncmp(str, "i2c_bus_a", 9)) + i2c_index = AML_I2C_MASTER_A; + else if (!strncmp(str, "i2c_bus_b", 9)) + i2c_index = AML_I2C_MASTER_B; + else if (!strncmp(str, "i2c_bus_c", 9)) + i2c_index = AML_I2C_MASTER_C; + else if (!strncmp(str, "i2c_bus_d", 9)) + i2c_index = AML_I2C_MASTER_D; + else { + RXEXTERR("%s: invalid i2c bus \"%s\" from dts\n", + __func__, str); + return -1; + } + RXEXTPR("i2c_bus = %s\n", str); + hdmirx_ext_drv->hw.i2c_bus_index = i2c_index; + + /* for gpio_en */ + val = GPIOD_OUT_LOW; + ret = of_property_read_u32_array(of_node, "en_gpio_val", ¶[0], 2); + if (ret) { + RXEXTERR("%s: failed to get en_gpio_val\n", __func__); + } else { + hdmirx_ext_drv->hw.en_gpio.val_on = para[0]; + hdmirx_ext_drv->hw.en_gpio.val_off = para[1]; + val = hdmirx_ext_drv->hw.en_gpio.val_off ? + GPIOD_OUT_LOW : GPIOD_OUT_HIGH; + RXEXTPR("en_gpio val_on = %d, val_off=%d\n", + hdmirx_ext_drv->hw.en_gpio.val_on, + hdmirx_ext_drv->hw.en_gpio.val_off); + } + /* request gpio */ + hdmirx_ext_drv->hw.en_gpio.gpio = devm_gpiod_get(dev, "en", val); + if (IS_ERR(hdmirx_ext_drv->hw.en_gpio.gpio)) { + hdmirx_ext_drv->hw.en_gpio.flag = 0; + RXEXTERR("register en_gpio err\n"); + } else { + hdmirx_ext_drv->hw.en_gpio.flag = 1; + } + if (hdmirx_ext_drv->hw.en_gpio.flag) { + ret = of_property_read_string(of_node, "en_gpio_name", &str); + if (ret) { + RXEXTPR("failed to get en_gpio_name\n"); + str = "unknown"; + } + strcpy(hdmirx_ext_drv->hw.en_gpio.name, str); + RXEXTPR("register gpio %s: 0x%p\n", + hdmirx_ext_drv->hw.en_gpio.name, + hdmirx_ext_drv->hw.en_gpio.gpio); + } + + /* for gpio_reset */ + val = GPIOD_OUT_LOW; + ret = of_property_read_u32_array(of_node, "reset_gpio_val", + ¶[0], 2); + if (ret) { + RXEXTERR("%s: failed to get reset_gpio_val\n", __func__); + } else { + hdmirx_ext_drv->hw.reset_gpio.val_on = para[0]; + hdmirx_ext_drv->hw.reset_gpio.val_off = para[1]; + val = hdmirx_ext_drv->hw.reset_gpio.val_on ? + GPIOD_OUT_LOW : GPIOD_OUT_HIGH; + RXEXTPR("reset_gpio val_on = %d, val_off=%d\n", + hdmirx_ext_drv->hw.reset_gpio.val_on, + hdmirx_ext_drv->hw.reset_gpio.val_off); + } + /* request gpio */ + hdmirx_ext_drv->hw.reset_gpio.gpio = devm_gpiod_get(dev, "reset", val); + if (IS_ERR(hdmirx_ext_drv->hw.reset_gpio.gpio)) { + hdmirx_ext_drv->hw.reset_gpio.flag = 0; + RXEXTERR("register reset_gpio err\n"); + } else { + hdmirx_ext_drv->hw.reset_gpio.flag = 1; + } + if (hdmirx_ext_drv->hw.reset_gpio.flag) { + ret = of_property_read_string(of_node, "reset_gpio_name", &str); + if (ret) { + RXEXTPR("failed to get reset_gpio_name\n"); + str = "unknown"; + } + strcpy(hdmirx_ext_drv->hw.reset_gpio.name, str); + RXEXTPR("register gpio %s: 0x%p\n", + hdmirx_ext_drv->hw.reset_gpio.name, + hdmirx_ext_drv->hw.reset_gpio.gpio); + } + + return 0; +} +#endif + +static int hdmirx_ext_open(struct inode *node, struct file *filp) +{ + struct hdmirx_ext_drv_s *pdev; + + pdev = container_of(node->i_cdev, struct hdmirx_ext_drv_s, cdev); + filp->private_data = pdev; + + return 0; +} + +static int hdmirx_ext_release(struct inode *node, struct file *filp) +{ + return 0; +} + +static const struct file_operations hdmirx_ext_fops = { + .owner = THIS_MODULE, + .open = hdmirx_ext_open, + .release = hdmirx_ext_release, +}; + +static int hdmirx_ext_probe(struct platform_device *pdev) +{ + int ret = -1; + + hdmirx_ext_debug_print = 0; + RXEXTPR("%s: ver: %s\n", __func__, HDMIRX_EXT_DRV_VER); + + hdmirx_ext_drv = kmalloc(sizeof(struct hdmirx_ext_drv_s), GFP_KERNEL); + if (!hdmirx_ext_drv) { + ret = -ENOMEM; + RXEXTERR("%s: failed to alloc hdmirx_ext_drv!\n", __func__); + goto fail; + } + hdmirx_ext_drv->dev = &pdev->dev; + hdmirx_ext_drv->vops = get_vdin_v4l2_ops(); + + /* hdmirx_ext_drv default value setting */ + hdmirx_ext_set_default_params(); + +#ifdef CONFIG_OF + ret = hdmirx_ext_get_dts_config(&pdev->dev); + if (ret) { + RXEXTERR("%s: invalid dts config\n", __func__); + goto cleanup; + } +#endif + hdmirx_ext_device_probe(pdev); + + ret = alloc_chrdev_region(&hdmirx_ext_device_id, 0, 1, + HDMIRX_EXT_DEV_NAME); + if (ret < 0) { + RXEXTERR("%s: failed to alloc char dev\n", __func__); + goto cleanup; + } + + cdev_init(&(hdmirx_ext_drv->cdev), &hdmirx_ext_fops); + hdmirx_ext_drv->cdev.owner = THIS_MODULE; + + ret = cdev_add(&(hdmirx_ext_drv->cdev), hdmirx_ext_device_id, 1); + if (ret) { + RXEXTERR("%s: failed to add hdmirx_ext cdev, err = %d\n", + __func__, ret); + goto unregister; + } + + hdmirx_ext_class = class_create(THIS_MODULE, HDMIRX_EXT_DRV_NAME); + if (IS_ERR(hdmirx_ext_class)) { + ret = PTR_ERR(hdmirx_ext_class); + RXEXTERR("%s: failed to create hdmirx_ext class, err = %d\n", + __func__, ret); + goto destroy_cdev; + } + + hdmirx_ext_device = device_create(hdmirx_ext_class, NULL, + hdmirx_ext_device_id, NULL, "%s", hdmirx_ext_drv->name); + if (IS_ERR(hdmirx_ext_device)) { + ret = PTR_ERR(hdmirx_ext_device); + RXEXTERR("%s: failed to create hdmirx_ext device, err = %d\n", + __func__, ret); + goto destroy_class; + } + + ret = hdmirx_ext_create_device_attrs(hdmirx_ext_device); + if (ret < 0) { + RXEXTERR("%s: failed to create device attrs, err = %d\n", + __func__, ret); + goto destroy_device; + } + + /* set drvdata */ + dev_set_drvdata(hdmirx_ext_device, hdmirx_ext_drv); + + ret = hdmirx_ext_start(hdmirx_ext_drv); + if (ret) { + RXEXTERR("%s: failed to setup resource, err = %d\n", + __func__, ret); + goto destroy_attrs; + } + + RXEXTPR("driver probe ok\n"); + + return 0; + +destroy_attrs: + hdmirx_ext_destroy_device_attrs(hdmirx_ext_device); + +destroy_device: + device_destroy(hdmirx_ext_class, hdmirx_ext_device_id); + +destroy_class: + class_destroy(hdmirx_ext_class); + +destroy_cdev: + cdev_del(&(hdmirx_ext_drv->cdev)); + +unregister: + unregister_chrdev_region(MKDEV(MAJOR(hdmirx_ext_device_id), + MINOR(hdmirx_ext_device_id)), 1); + +cleanup: + kfree(hdmirx_ext_drv); + hdmirx_ext_drv = NULL; + +fail: + return ret; +} + +static int hdmirx_ext_remove(struct platform_device *pdev) +{ + RXEXTPR("%s\n", __func__); + + hdmirx_ext_destroy_device_attrs(hdmirx_ext_device); + + if (hdmirx_ext_class) { + device_destroy(hdmirx_ext_class, hdmirx_ext_device_id); + class_destroy(hdmirx_ext_class); + } + + if (hdmirx_ext_drv) { + cdev_del(&(hdmirx_ext_drv->cdev)); + kfree(hdmirx_ext_drv); + hdmirx_ext_drv = NULL; + } + + unregister_chrdev_region(hdmirx_ext_device_id, 1); + + return 0; +} + +static int hdmirx_ext_resume(struct platform_device *pdev) +{ + RXEXTPR("%s\n", __func__); + return 0; +} + +static int hdmirx_ext_suspend(struct platform_device *pdev, + pm_message_t state) +{ + RXEXTPR("%s\n", __func__); + if (hdmirx_ext_drv) { + if (hdmirx_ext_drv->state) { + hdmirx_ext_stop_vdin(); + __hw_disable(); + } + } + return 0; +} + +static void hdmirx_ext_shutdown(struct platform_device *pdev) +{ + RXEXTPR("%s\n", __func__); + if (hdmirx_ext_drv) { + if (hdmirx_ext_drv->state) { + hdmirx_ext_stop_vdin(); + __hw_disable(); + } + } +} + +#ifdef CONFIG_OF +static const struct of_device_id hdmirx_ext_dt_match[] = { + { + .compatible = "amlogic, hdmirx_ext", + }, + {}, +}; +#else +#define hdmirx_ext_dt_match NULL +#endif + + +static struct platform_driver hdmirx_ext_driver = { + .probe = hdmirx_ext_probe, + .remove = hdmirx_ext_remove, + .suspend = hdmirx_ext_suspend, + .resume = hdmirx_ext_resume, + .shutdown = hdmirx_ext_shutdown, + .driver = { + .name = HDMIRX_EXT_DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = hdmirx_ext_dt_match, + } +}; +static int __init hdmirx_ext_drv_init(void) +{ + if (platform_driver_register(&hdmirx_ext_driver)) { + RXEXTERR("%s: failed to register driver\n", __func__); + return -ENODEV; + } + + return 0; +} + +static void __exit hdmirx_ext_drv_exit(void) +{ + RXEXT_PFUNC(); + platform_driver_unregister(&hdmirx_ext_driver); + class_unregister(hdmirx_ext_class); +} + +late_initcall(hdmirx_ext_drv_init); +module_exit(hdmirx_ext_drv_exit); + +MODULE_DESCRIPTION("AML external hdmirx driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Amlogic, Inc."); diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.h new file mode 100644 index 0000000..e90c8c7 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.h @@ -0,0 +1,183 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_drv.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMIRX_EXT_DRV_H__ +#define __HDMIRX_EXT_DRV_H__ + +#include +#include +#include +#include +#include +#include +#include "../tvin_frontend.h" + +#define HDMIRX_EXT_DRV_VER "20170823" + +#define HDMIRX_EXT_DRV_NAME "hdmirx_ext" +#define HDMIRX_EXT_DEV_NAME "hdmirx_ext" + +extern int hdmirx_ext_debug_print; +#define RXEXTERR(fmt, args...) pr_err("hdmirx_ext:error: " fmt, ## args) +#define RXEXTPR(fmt, args...) pr_info("hdmirx_ext: " fmt, ## args) +#define RXEXTDBG(fmt, args...) do { if (hdmirx_ext_debug_print) \ + RXEXTPR(fmt, ##args); \ + } while (0) + +#define printf(fmt, args...) pr_info("hdmirx_ext: " fmt, ## args) + +#define RXEXT_PFUNC() RXEXTPR("%s: line: %d\n", __func__, __LINE__) + +struct hdmirx_ext_status_s { + unsigned int cable; /* whether the hdmi cable is inserted. */ + unsigned int signal; /* whether the valid signal is got. */ + unsigned int video_mode; /* format of the output video */ + unsigned int audio_sr; /* audio sample rate of the output audio */ +}; + +struct video_timming_s { + int h_active; + int h_total; + int hs_frontporch; + int hs_width; + int hs_backporch; + int v_active; + int v_total; + int vs_frontporch; + int vs_width; + int vs_backporch; + int mode; + int hs_pol; + int vs_pol; +}; + +struct hdmirx_ext_gpio_s { + char name[15]; + struct gpio_desc *gpio; + int flag; + int val_on; + int val_off; +}; + +struct hdmirx_ext_hw_s { + /* int i2c_addr_pull; */ + unsigned char i2c_addr; + int i2c_bus_index; + struct i2c_client *i2c_client; + + struct hdmirx_ext_gpio_s en_gpio; + struct hdmirx_ext_gpio_s reset_gpio; + + struct pinctrl *pin; + unsigned char pinmux_flag; + + /* hw operation */ + /* signal stauts */ + int (*get_cable_status)(void); + int (*get_signal_status)(void); + int (*get_input_port)(void); + void (*set_input_port)(int port); + + /* signal timming */ + int (*get_video_timming)(struct video_timming_s *ptimming); + + /* hdmi/dvi mode */ + int (*is_hdmi_mode)(void); + + /* audio mode */ + int (*get_audio_sample_rate)(void); + + /* debug interface + * it should support the following format: + * read registers: r device_address register_address + * write registers: w device_address register_address value + * dump registers: dump device_address + * register_address_start register_address_end + * video timming: vinfo + * cmd format help: help + */ + int (*debug)(char *buf); + + /* chip id and driver version */ + char* (*get_chip_version)(void); + + /* hardware init related */ + int (*init)(void); + int (*enable)(void); + void (*disable)(void); +}; + +struct hdmirx_ext_vdin_s { + struct tvin_frontend_s frontend; + struct vdin_parm_s parm; + unsigned char vdin_sel; + unsigned char bt656_sel; + unsigned char started; +}; + +struct hdmirx_ext_drv_s { + char name[20]; + int state; /* 1=on, 0=off */ + struct device *dev; + struct cdev cdev; + struct hdmirx_ext_status_s status; + struct hdmirx_ext_hw_s hw; + struct hdmirx_ext_vdin_s vdin; + struct vdin_v4l2_ops_s *vops; + + /* 0 to disable from user + * 1 to enable, driver will trigger to vdin-stop + * 2 to enable, driver will trigger to vdin-start + * 3 to enable, driver will trigger to vdin-start/vdin-stop + * 4 to enable, driver will not trigger to vdin-start/vdin-stop + * 0xff to enable, and driver will NOT trigger signal-lost/vdin-stop, + * signal-get/vdin-start + */ + unsigned int user_cmd; + + struct timer_list timer; + int timer_cnt; + void (*timer_func)(void); + struct hrtimer hr_timer; + long hrtimer_cnt; + void (*hrtimer_func)(void); +}; + +/* according to the CEA-861-D */ +enum SII9233_VIDEO_MODE_e { + CEA_480P60 = 2, + CEA_720P60 = 4, + CEA_1080I60 = 5, + CEA_480I60 = 6, + + CEA_1080P60 = 16, + CEA_576P50 = 17, + CEA_720P50 = 19, + CEA_1080I50 = 20, + CEA_576I50 = 21, + + CEA_1080P50 = 31, + + CEA_MAX = 60 +}; + +extern struct hdmirx_ext_drv_s *hdmirx_ext_get_driver(void); +#if defined(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135) +extern void hdmirx_ext_register_hw_sii9135(struct hdmirx_ext_drv_s *hdev); +#endif + +#endif diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.c new file mode 100644 index 0000000..494ea14 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.c @@ -0,0 +1,251 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "hdmirx_ext_drv.h" +#include +#include + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* signal stauts */ +int __hw_get_cable_status(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_cable_status)) + return hdrv->hw.get_cable_status(); + + return 0; +} + +int __hw_get_signal_status(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_signal_status)) + return hdrv->hw.get_signal_status(); + + return 0; +} + +int __hw_get_input_port(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_input_port)) + return hdrv->hw.get_input_port(); + + return 0; +} + +void __hw_set_input_port(int port) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.set_input_port)) + return hdrv->hw.set_input_port(port); +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* signal timming */ +int __hw_get_video_timming(struct video_timming_s *ptimming) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_video_timming)) + return hdrv->hw.get_video_timming(ptimming); + + return -1; +} + +int __hw_get_video_mode(void) +{ + unsigned int h_active, h_total, v_active, v_total; + unsigned int mode = 0; + struct video_timming_s timming; + + if (__hw_get_video_timming(&timming) == -1) { + RXEXTERR("%s: get video timming failed!\n", __func__); + return CEA_MAX; + } + + h_active = timming.h_active; + h_total = timming.h_total; + v_active = timming.v_active; + v_total = timming.v_total; + + RXEXTPR("%s: pixel = %d x %d ( %d x %d )\n", + __func__, h_active, v_active, h_total, v_total); + + if ((h_total == 2200) && (v_active == 1080)) + mode = CEA_1080P60;/* 1080p */ + else if ((h_total == 2640) && (v_active == 1080)) + mode = CEA_1080P50;/* 1080p50 */ + else if ((h_total == 2200) && (v_active == 540)) + mode = CEA_1080I60;/* 1080i */ + else if ((h_total == 2640) && (v_active == 540)) + mode = CEA_1080I50;/* 1080i50 */ + else if ((h_total == 1650) && (v_active == 720)) + mode = CEA_720P60;/* 720p */ + else if ((h_total == 1980) && (v_active == 720)) + mode = CEA_720P50;/* 720p50 */ + else if ((h_total == 864) && (v_active == 576)) + mode = CEA_576P50;/* 576p */ + else if ((h_total == 858) && (v_active == 480)) + mode = CEA_480P60;/* 480p */ + else if ((h_total == 864) && (v_active == 288)) + mode = CEA_576I50;/* 576i */ + else if ((h_total == 858) && (v_active == 240)) + mode = CEA_480I60;/* 480i */ + + return mode; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hdmi/dvi mode */ +int __hw_is_hdmi_mode(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.is_hdmi_mode)) + return hdrv->hw.is_hdmi_mode(); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* audio mode + * audio sampling frequency: + * 0x0 for 44.1 KHz + * 0x1 for Not indicated + * 0x2 for 48 KHz + * 0x3 for 32 KHz + * 0x4 for 22.05 KHz + * 0x6 for 24 kHz + * 0x8 for 88.2 kHz + * 0x9 for 768 kHz (192*4) + * 0xa for 96 kHz + * 0xc for 176.4 kHz + * 0xe for 192 kHz + */ +int __hw_get_audio_sample_rate(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_audio_sample_rate)) + return hdrv->hw.get_audio_sample_rate(); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* debug interface */ +int __hw_debug(char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.debug)) + return hdrv->hw.debug(buf); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* chip id and driver version */ +char *__hw_get_chip_id(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.get_chip_version)) + return hdrv->hw.get_chip_version(); + + return NULL; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware init related */ +int __hw_init(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.init)) + return hdrv->hw.init(); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware enable related */ +int __hw_enable(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if ((hdrv) && (hdrv->hw.enable)) + return hdrv->hw.enable(); + hdrv->state = 1; + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware disable related */ +void __hw_disable(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + hdrv->state = 0; + if ((hdrv) && (hdrv->hw.disable)) + hdrv->hw.disable(); +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hdmirx_ext utility */ +void __hw_dump_video_timming(void) +{ + int height, width, h_total, v_total; + int hs_fp, hs_width, hs_bp; + int vs_fp, vs_width, vs_bp; + struct video_timming_s timming; + + if (__hw_get_video_timming(&timming) == -1) { + RXEXTERR("%s: get video timming failed!\n", __func__); + return; + } + + height = timming.h_active; + width = timming.v_active; + + h_total = timming.h_total; + v_total = timming.v_total; + + hs_fp = timming.hs_frontporch; + hs_width = timming.hs_width; + hs_bp = timming.hs_backporch; + + vs_fp = timming.vs_frontporch; + vs_width = timming.vs_width; + vs_bp = timming.vs_backporch; + + pr_info("hdmirx_ext video info:\n" + "height*width active = %4d x %4d\n" + "height*width total = %4d x %4d\n" + "h_sync = %4d, %4d, %4d\n" + "v_sync = %4d, %4d, %4d\n", + height, width, h_total, v_total, + hs_fp, hs_width, hs_bp, + vs_fp, vs_width, vs_bp); +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.h new file mode 100644 index 0000000..64c9d3f --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.h @@ -0,0 +1,82 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_hw_iface.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __HDMIRX_EXT_HW_INTERFACE_H__ +#define __HDMIRX_EXT_HW_INTERFACE_H__ + +#include "hdmirx_ext_drv.h" + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* signal stauts */ +extern int __hw_get_cable_status(void); +extern int __hw_get_signal_status(void); +extern int __hw_get_input_port(void); +extern void __hw_set_input_port(int port); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* signal timming */ +extern int __hw_get_video_timming(struct video_timming_s *ptimming); +extern int __hw_get_video_mode(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hdmi/dvi mode */ +extern int __hw_is_hdmi_mode(void); +extern int __hw_get_video_mode(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* audio mode + * audio sampling frequency: + * 0x0 for 44.1 KHz + * 0x1 for Not indicated + * 0x2 for 48 KHz + * 0x3 for 32 KHz + * 0x4 for 22.05 KHz + * 0x6 for 24 kHz + * 0x8 for 88.2 kHz + * 0x9 for 768 kHz (192*4) + * 0xa for 96 kHz + * 0xc for 176.4 kHz + * 0xe for 192 kHz + */ +extern int __hw_get_audio_sample_rate(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* debug interface */ +extern int __hw_debug(char *buf); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* chip id and driver version */ +extern char *__hw_get_chip_id(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware init related */ +extern int __hw_init(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware enable related */ +extern int __hw_enable(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hardware disable related */ +extern void __hw_disable(void); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* hdmirx_ext utility */ +extern void __hw_dump_video_timming(void); + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_reg.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_reg.h new file mode 100644 index 0000000..0eab9bd --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_reg.h @@ -0,0 +1,50 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hdmirx_ext_reg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __AML_HDMIRX_EXT_REG_H__ +#define __AML_HDMIRX_EXT_REG_H__ +#include + +#define VDIN_ASFIFO_CTRL2 0x120f +#define DVIN_FRONT_END_CTRL 0x12e0 +#define DVIN_HS_LEAD_VS_ODD 0x12e1 +#define DVIN_ACTIVE_START_PIX 0x12e2 +#define DVIN_ACTIVE_START_LINE 0x12e3 +#define DVIN_DISPLAY_SIZE 0x12e4 +#define DVIN_CTRL_STAT 0x12e5 + + +static inline unsigned int rx_ext_vcbus_read(unsigned int reg) +{ + return aml_read_vcbus(reg); +}; + +static inline void rx_ext_vcbus_write(unsigned int reg, unsigned int value) +{ + aml_write_vcbus(reg, value); +}; + +static inline void rx_ext_vcbus_setb(unsigned int reg, unsigned int value, + unsigned int _start, unsigned int _len) +{ + rx_ext_vcbus_write(reg, ((rx_ext_vcbus_read(reg) & + (~(((1L << _len)-1) << _start))) | + ((value & ((1L << _len)-1)) << _start))); +} + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Kconfig b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Kconfig new file mode 100644 index 0000000..83ac702 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Kconfig @@ -0,0 +1,9 @@ +# +# Hdmirx external SII9135 Device Driver Configuration +# + +config AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135 + bool "external hdmirx chip sii9135 support" + default n + help + sii9135 is input with hdmi siganl, and output dvp signal. diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Makefile b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Makefile new file mode 100644 index 0000000..9fbf321 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/Makefile @@ -0,0 +1,31 @@ +obj-$(CONFIG_AMLOGIC_MEDIA_TVIN_HDMI_EXT_SII9135) += hw_sii9135.o + +hw_sii9135-objs := sii9135_iface.o \ + main.o \ + SiIAudio.o \ + SiIDiagnostic.o \ + SiIDeepColor.o \ + SiIHAL.o \ + SiIHDCP.o \ + SiIHDMIRX.o \ + SiIHLVIIC.o \ + SiIInfoPkts.o \ + SiIISR.o \ + SiIRX_API.o \ + SiIRXIO.o \ + SiISysCtrl.o \ + SiITrace.o \ + SiITTasks.o \ + SiITTAudio.o \ + SiITTHDCP.o \ + SiITTInfoPkts.o \ + SiITTVideo.o \ + SiIVidF.o \ + SiIVidIn.o \ + SiIVidRes.o \ + SiIVRTables.o \ + UDebugHLIIC.o \ + UEEPROM.o \ + UAT_EEPROM.o \ + uauddac.o \ + UCfgRX.o diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.c new file mode 100644 index 0000000..5abf7d0 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.c @@ -0,0 +1,1020 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIAudio + * --- + * Module Description: this module sirves Audio functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiITrace.h" +#include "SiIAudio.h" +#include "SiITTVideo.h" +#include "SiIRXIO.h" +#include "SiIHAL.h" +#include "SiIRXDefs.h" +#include "SiIHDMIRX.h" +#include "UCfgRX.h" +#include "UGlob.h" +#include "UAudDAC.h" + +#ifdef SII_DUMP_UART +#include "../hdmirx_ext_drv.h" +#endif + +struct AudioOutputFormatType_s SavedAudioOutputFormat; +/*------------------------------------------------------------------------------ + * Function Name: siiSetAudioOutputFormat + * Function Description: This function used to set output audio format + * + * Accepts: pointer on struct AudioOutputFormatType_s + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetAudioOutputFormat(struct AudioOutputFormatType_s *AudioOutputFormat) +{ + BYTE bRegVal; + + bRegVal = siiReadByteHDMIRXP1(RX_AUDIO_CTRL_ADDR); + /* Set or clear SPDIF Enable bit */ + if (AudioOutputFormat->wOutputSelect & SiI_RX_AOut_SPDIF) + bRegVal |= RX_BIT_SPDIF_EN; + else + bRegVal &= (~RX_BIT_SPDIF_EN); + /* Set or clear Smooth Audio muting */ + if (AudioOutputFormat->wOutputSelect & SiI_RX_AOut_SmoothHWMute) + bRegVal |= RX_SMOOTH_MUTE_EN; + else + bRegVal &= (~RX_SMOOTH_MUTE_EN); + siiWriteByteHDMIRXP1(RX_AUDIO_CTRL_ADDR, bRegVal); + + /* Select SD0-3 */ + bRegVal = siiReadByteHDMIRXP1(RX_I2S_CTRL2_ADDR); + bRegVal &= 0x0F; + bRegVal |= ((AudioOutputFormat->wOutputSelect >> 4) & 0xF0); + + siiWriteByteHDMIRXP1(RX_I2S_CTRL2_ADDR, bRegVal); + + /* set I2S bus format */ + bRegVal = AudioOutputFormat->wI2SBusFormat & 0xFF; + siiWriteByteHDMIRXP1(RX_I2S_CTRL1_ADDR, bRegVal); + bRegVal = siiReadByteHDMIRXP1(RX_I2S_CTRL2_ADDR); + bRegVal &= 0xFC; + bRegVal |= ((AudioOutputFormat->wI2SBusFormat >> 8) & 0x03); + siiWriteByteHDMIRXP1(RX_I2S_CTRL2_ADDR, bRegVal); +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetAudioOutputFormat + * Function Description: this function used to get Output Audio Format + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetAudioOutputFormat(struct AudioOutputFormatType_s *AudioOutputFormat) +{ + /* BYTE bRegVal; */ + + /* YMA change to return the save value instead of read from registers. + *the reg value may be not the right mode + */ + + *AudioOutputFormat = SavedAudioOutputFormat; + +#if 0 + AudioOutputFormat->wOutputSelect = SiI_Ctrl.wAudioOutputSelect; + + AudioOutputFormat->wI2SBusFormat = 0; + AudioOutputFormat->bI2SMap = 0; + + AudioOutputFormat->bI2SMap = siiReadByteHDMIRXP1(RX_I2S_MAP_ADDR); + + bRegVal = siiReadByteHDMIRXP1(RX_I2S_CTRL1_ADDR); + AudioOutputFormat->wI2SBusFormat = (WORD) bRegVal; + + + bRegVal = siiReadByteHDMIRXP1(RX_I2S_CTRL2_ADDR); + AudioOutputFormat->wOutputSelect |= ((bRegVal & 0xF0) << 4); + AudioOutputFormat->wI2SBusFormat |= (WORD)((bRegVal & 0x03) << 8); +#endif + /* + * yma for API rev2 + *actually not need read from the registers because it may be the + * settings for I2S, not DSD/HBR + *should return the settings by API set function or from EEPROM + *otherwise, the DSD/HBR configurations will be overwritten by + * the I2S settings. + */ +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetDSDHBRAudioOutputFormat + * Function Description: This function used to set DSD/HBR output audio format + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +static void siiSetDSDHBRAudioOutputFormat(BOOL qON) +{ + /* struct AudioOutputFormatType_s AudioOutputFormat; */ + + if (qON) { + if (SiI_Inf.AudioStatus.bRepresentation == + SiI_RX_AudioRepr_DSD) { + /* YMA 2 set DSD output format as set from API */ + if (SavedAudioOutputFormat.bDSDHBRFormat & + SiI_RX_AOut_DSD_WS16Bit) { + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL1_ADDR, + RX_BIT_Aout_WordSize, SET); + } + if (SavedAudioOutputFormat.bDSDHBRFormat & + SiI_RX_AOut_DSD_SENeg) { + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL1_ADDR, + RX_BIT_Aout_ClockEdge, SET); + } + } else if (SiI_Inf.AudioStatus.bRepresentation == + SiI_RX_AudioRepr_HBR) { + if (SavedAudioOutputFormat.bDSDHBRFormat & + SiI_RX_AOut_HBRA_WS16Bit) { + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL1_ADDR, + RX_BIT_Aout_WordSize, SET); + } + if (SavedAudioOutputFormat.bDSDHBRFormat & + SiI_RX_AOut_HBRA_SENeg) { + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL1_ADDR, + RX_BIT_Aout_ClockEdge, SET); + } + } + } else { /* YMA restore SiI_RX_AudioRepr_PCM; */ + /* not get the parameter from */ + /* siiGetAudioOutputFormat(&AudioOutputFormat); */ + siiSetAudioOutputFormat(&SavedAudioOutputFormat); + } +} + +/*------------------------------------------------------------------------------ + * Function Name: ChangeDSDAudioStreamHandler + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiChangeDSDAudioStreamHandler(void) +{ + /* BYTE bNewAudioRepresentation; */ + + if (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & BIT_DSD_STATUS) { + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_DSD; + /* YMA DSD MCLK is bit 3,2 of the parameter */ + siiSetMasterClock((SiI_Ctrl.bRXInitPrm0 >> 2) & SelectMClock); + siiSetDSDHBRAudioOutputFormat(ON); + } else { + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_PCM; + siiSetMasterClock(SiI_Ctrl.bRXInitPrm0 & SelectMClock); + siiSetDSDHBRAudioOutputFormat(OFF); + } +} + +/*------------------------------------------------------------------------------ + * Function Name: ChangeHBRAudioStreamHandler + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiChangeHBRAudioStreamHandler(void) +{ + if (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & RX_BIT_HBRA_STATUS) { + siiSetHBRFs(ON); + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_HBR; + /* YMA HBR MCLK is bit 5,4 of the parameter */ + siiSetMasterClock((SiI_Ctrl.bRXInitPrm0 >> 4) & SelectMClock); + siiSetDSDHBRAudioOutputFormat(ON); + } else { + siiSetHBRFs(OFF); + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_PCM; + siiSetMasterClock(SiI_Ctrl.bRXInitPrm0 & SelectMClock); + siiSetDSDHBRAudioOutputFormat(OFF); + } +} + +/*----------------------------------------------------------------------------- + * This table represents operational CTS ranges + * To get Real CTS Value, * 10, it was done to reduce data size + *--------------------------------------------------------------------------- + */ +ROM const struct CTSLimitsType_s CTSLimits[4] = { + {1666, 16666}, /* FPix TMDS range 25-50mHz */ + {3333, 28666}, /* FPix TMDS range 50-86mHz */ + {5733, 41666}, /* FPix TMDS range 86-125mHz */ + {8333, 55000}, /* FPix TMDS range 125-165mHz */ +}; +/*------------------------------------------------------------------------------ + * Function Name: siiClearCTSChangeInterruprt + * Function Description: This functio clears CTS change interrupts in order + * to use later information about stability of CTS values + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiClearCTSChangeInterruprt(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST1_ADDR, RX_BIT_CTS_CHANGED); +} + +/*------------------------------------------------------------------------------ + * Function Name: CheckCTSChanged + * Function Description: it used to detect if CTS value has been changed + *---------------------------------------------------------------------------- + */ +static BOOL CheckCTSChanged(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST1_ADDR) & RX_BIT_CTS_CHANGED) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: AudioFIFO_Reset + * Function Description: Makes Audio FIFO reset + *---------------------------------------------------------------------------- + */ +void siiAudioFIFO_Reset(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, RX_BIT_AUDIO_FIFO_RESET, SET); + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, RX_BIT_AUDIO_FIFO_RESET, CLR); +} +/*------------------------------------------------------------------------------ + * Function Name: ACR_Reset + * Function Description: Makes Audio clock regeneration (ACR) reset + *---------------------------------------------------------------------------- + */ +static void ACR_Reset(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, RX_BIT_ACR_RESET, SET); + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, RX_BIT_ACR_RESET, CLR); +} +/*------------------------------------------------------------------------------ + * Function Name: siiAudioMute + * Function Description: mutes audio + * + * Accepts: qOn + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiAudioMute(BOOL qOn) +{ + if (qOn) { + siiIIC_RX_RWBitsInByteP1(RX_AUDP_MUTE_ADDR, + RX_BIT_AUDIO_MUTE, SET); + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_AMute; + } else { + siiIIC_RX_RWBitsInByteP1(RX_AUDP_MUTE_ADDR, + RX_BIT_AUDIO_MUTE, CLR); + SiI_Inf.bGlobStatus &= (~SiI_RX_GlobalHDMI_AMute); + } +} + +#ifdef SII_ANALOG_DIG_AUDIO_MAX +/*------------------------------------------------------------------------------ + * Function Name: siiSetAnalogAudioMux + * Function Description: Used in DVI mode for Analog Audio input selection + * control of MUX through MCU general purpose output pins + * Accepts: bChannel + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ + +void siiSetAnalogAudioMux(BYTE bChannel) +{ + BYTE bPCB_Id; + + bPCB_Id = siiGetPCB_Id(); + + if (bChannel == SiI_RX_VInCh1) { /* select MuxAnalog Channel A */ + /* + *YMA 10/4/06 remove wilma special + * if (( bPCB_Id == SiI_CP9133 )||( bPCB_Id == SiI_CP9135 )) { + */ + + if (bPCB_Id == SiI_CP9133) { + halAudioSetAltA(); + halAudioClearAltB(); + } else { + halAudioSetA(); + halAudioClearB(); + } + } else if (bChannel == SiI_RX_VInCh2) { /* select MuxAnalog Channel B */ + /* YMA 10/4/06 remove wilma special + * if (( bPCB_Id == SiI_CP9133 )||( bPCB_Id == SiI_CP9135 )) { + */ + + if (bPCB_Id == SiI_CP9133) { + halAudioClearAltA(); + halAudioSetAltB(); + } else { + halAudioClearA(); + halAudioSetB(); + } + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetDigitalAudioMux( + * Function Description: Used in HDMI mode for Didital Audio input selection + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ + +void siiSetDigitalAudioMux(void) +{ + BYTE bPCB_Id; + + bPCB_Id = siiGetPCB_Id(); + /* + *YMA 10/4/06 remove wilma special + * if (( bPCB_Id == SiI_CP9133 )||( bPCB_Id == SiI_CP9135 )) { + */ + + if (bPCB_Id == SiI_CP9133) { + halAudioClearAltA(); + halAudioClearAltB(); + } else { + halAudioClearA(); + halAudioClearB(); + } +} +#endif /* end SII_ANALOG_DIG_AUDIO_MAX */ +/*------------------------------------------------------------------------------ + * Function Name: AudioExceptionsControl + * Function Description: + * for switching between Automatic and Manual Audio control + *---------------------------------------------------------------------------- + */ +static void AudioExceptionsControl(BOOL qOn) +{ + if (qOn) { + siiIIC_RX_RWBitsInByteP0(RX_AEC_CTRL_ADDR, RX_BIT_AEC_EN, SET); + siiIIC_RX_RWBitsInByteP0(RX_INT_MASK_ST5_ADDR, + RX_BIT_AAC_DONE, SET); + SiI_Ctrl.bIgnoreIntr &= (~qcIgnoreAAC); + } else { + siiIIC_RX_RWBitsInByteP0(RX_AEC_CTRL_ADDR, RX_BIT_AEC_EN, CLR); + siiIIC_RX_RWBitsInByteP0(RX_INT_MASK_ST5_ADDR, + RX_BIT_AAC_DONE, CLR); + SiI_Ctrl.bIgnoreIntr |= qcIgnoreAAC; + } +} +/*------------------------------------------------------------------------------ + * Function Name: ACRInit + * Function Description: + * This function makes initialisation of Audio Clock Regeneration (ACR) + *---------------------------------------------------------------------------- + */ +static void ACRInit(void) +{ + siiIIC_RX_RWBitsInByteP1(RX_ACR_CTRL1_ADDR, RX_BIT_ACR_INIT, SET); +} +/*------------------------------------------------------------------------------ + * Function Name: ClearFIFOOverUnderRunInterrupts + * Function Description: clears the interrupts, which indicate FIFO operation + *---------------------------------------------------------------------------- + */ +static void ClearFIFOOverUnderRunInterrupts(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST4_ADDR, + RX_BIT_FIFO_UNDERRUN | RX_BIT_FIFO_OVERRUN); +} +/*------------------------------------------------------------------------------ + * Function Name: CheckFIFOOverUnderRunInterrupts + * Function Description: + * used to detect the interrupt, getting of these interrupt, + * tells that FIFO has problems + *---------------------------------------------------------------------------- + */ +static BOOL CheckFIFOOverUnderRunInterrupts(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST4_ADDR) & + (RX_BIT_FIFO_UNDERRUN | RX_BIT_FIFO_OVERRUN)) { + qResult = TRUE; + } + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: CheckGotAudioPacketInterrupt + * Function Description: indicates presence of Audio Packets + *---------------------------------------------------------------------------- + */ +static BOOL CheckGotAudioPacketInterrupt(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST2_ADDR) & RX_BIT_GOT_AUDIO_PKT) + qResult = TRUE; + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: CheckGotCTSPacketInterrupt + * Function Description: + indicates presence of CTS Packets, these packets used for + * Audio Clock Regeneration + *---------------------------------------------------------------------------- + */ +static BOOL CheckGotCTSPacketInterrupt(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST2_ADDR) & RX_BIT_GOT_CTS_PKT) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiClearGotCTSAudioPacketsIterrupts + * Function Description: clears CTS and Audio packets interrupts + * system checks later if packets are received + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiClearGotCTSAudioPacketsIterrupts(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST2_ADDR, + (RX_BIT_GOT_AUDIO_PKT | RX_BIT_GOT_CTS_PKT)); +} + +/*------------------------------------------------------------------------------ + * Function Name: GotCTSPackets + * Function Description: received CTS packets, used for Audio Clock Regeneration + *---------------------------------------------------------------------------- + */ +static BOOL GotCTSPackets(void) +{ + return CheckGotCTSPacketInterrupt(); +} +/*------------------------------------------------------------------------------ + * Function Name: GotAudioPackets + * Function Description: received Audio packets + *---------------------------------------------------------------------------- + */ +static BOOL GotAudioPackets(void) +{ + return CheckGotAudioPacketInterrupt(); +} +/*------------------------------------------------------------------------------ + * Function Name: GetCTS + * Function Description: This function gets Cycle Timing Stamp (CTS) + * the result is divided by 10 to simlify math + *---------------------------------------------------------------------------- + */ +static WORD GetCTS(void) +{ + WORD CTS_L; + DWORD CTS_H; + + CTS_L = siiReadWordHDMIRXP1(RX_HW_CTS_ADDR); + CTS_H = siiReadWordHDMIRXP1(RX_HW_CTS_ADDR + 2); + CTS_H <<= 16; + return (WORD)((CTS_H | CTS_L) / 10); +} +/*------------------------------------------------------------------------------ + * Function Name: IsCTSInRange + * Function Description: Check if CTS stamp in the operation range + *---------------------------------------------------------------------------- + */ +static BOOL IsCTSInRange(void) +{ + BYTE bPixClk; + WORD wCTS; + BOOL qResult = FALSE; + + wCTS = GetCTS(); + bPixClk = siiGetPixClock(); + if (bPixClk) { + if (bPixClk < 50) { + if ((CTSLimits[0].Min < wCTS) && + (CTSLimits[0].Max > wCTS)) { + qResult = TRUE; + } + } else if (bPixClk < 86) { + if ((CTSLimits[1].Min < wCTS) && + (CTSLimits[1].Max > wCTS)) { + qResult = TRUE; + } + } else if (bPixClk < 125) { + if ((CTSLimits[2].Min < wCTS) && + (CTSLimits[2].Max > wCTS)) { + qResult = TRUE; + } + } else if (bPixClk < 165) { + if ((CTSLimits[3].Min < wCTS) && + (CTSLimits[3].Max > wCTS)) { + qResult = TRUE; + } + } + } else { + /* This check goes when video resolution is not detected yet, + * so less strict conditions for test. + */ + if ((CTSLimits[0].Min < wCTS) && (CTSLimits[3].Max > wCTS)) + qResult = TRUE; + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: ClearCTS_DroppedReusedInterrupts + * Function Description: + * clears CTS dropped or reused interrupts + * these interrupts used to check stability of receiving CTS packets + *---------------------------------------------------------------------------- + */ +static void ClearCTS_DroppedReusedInterrupts(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST4_ADDR, + RX_BIT_CTS_DROPPED | RX_BIT_CTS_REUSED); +} +/*------------------------------------------------------------------------------ + * Function Name: GotCTS_DroppedReusedInterrupts + * Function Description: check presence of CTS dropped or reused interrupts + *---------------------------------------------------------------------------- + */ +static BOOL GotCTS_DroppedReusedInterrupts(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST4_ADDR) & + (RX_BIT_CTS_DROPPED | RX_BIT_CTS_REUSED)) { + qResult = TRUE; + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: IsAudioStable() + * Function Description: + * About stable audio clock we judge how stable CTS packets are coming + * If CTS dropped, then CTS packets coming too often + * If CTS reused, then CTS packets coming too seldom + *---------------------------------------------------------------------------- + */ +static BOOL GotAudioStable(void) +{ + BOOL qResult = FALSE; + + if (!GotCTS_DroppedReusedInterrupts()) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: GotPLL_UnlockInterrupt + * Function Description: this function is used if PLL is unlock + *---------------------------------------------------------------------------- + */ +static BOOL GotPLL_UnlockInterrupt(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST1_ADDR) & RX_BIT_ACR_PLL_UNLOCK) + qResult = TRUE; + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: ClearPLL_UnlockInterrupt + * Function Description: clears PLL unlock interrupt + *---------------------------------------------------------------------------- + */ +static void ClearPLL_UnlockInterrupt(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST1_ADDR, RX_BIT_ACR_PLL_UNLOCK); +} +/*------------------------------------------------------------------------------ + * Function Name: GotPLL_Unlocked + * Function Description: + * Check if Audio PLL is still unlock. Function clears PLL unlock + * interrupt and checks for new interrupt + *---------------------------------------------------------------------------- + */ +static BOOL GotPLL_Unlocked(void) +{ + BOOL qResult = FALSE; + + ClearPLL_UnlockInterrupt(); + if (GotPLL_UnlockInterrupt()) + qResult = TRUE; + return qResult; +} + +#ifdef SII_DUMP_UART +/*------------------------------------------------------------------------------ + * Function Name: PrintN + * Function Description: + * + *---------------------------------------------------------------------------- + */ +static void PrintN(void) +{ + WORD wN_L; + DWORD dwN_H; + + wN_L = siiReadWordHDMIRXP1(RX_HW_N_ADDR); + dwN_H = siiReadWordHDMIRXP1(RX_HW_N_ADDR + 2); + dwN_H <<= 16; + dwN_H |= wN_L; + printf(" N = %d ", (int)dwN_H); + +} +/*------------------------------------------------------------------------------ + * Function Name: PrintCTS + * Function Description: + * + *---------------------------------------------------------------------------- + */ +static void PrintCTS(void) +{ + WORD CTS_L; + DWORD CTS_H; + + CTS_L = siiReadWordHDMIRXP1(RX_HW_CTS_ADDR); + CTS_H = siiReadWordHDMIRXP1(RX_HW_CTS_ADDR + 2); + +/* CTS_H <<= 16; + * CTS_H |= CTS_L; + * printf(" CTS = % ", (int) CTS_H ); //fixed in build 010118. + */ + printf(" CTS = 0x%x%x\n", (int)CTS_H, (int)CTS_L); +} +/*------------------------------------------------------------------------------ + * Function Name: PrintFIFO_Diff() + * Function Description: + * + *---------------------------------------------------------------------------- + */ +static void PrintFIFO_Diff(void) +{ + BYTE bRegVal; + + bRegVal = GetFIFO_DiffPointer(); + printf(" FIFO diff = 0x%X ", (int)bRegVal); +} + +#endif +/*------------------------------------------------------------------------------ + * Function Name: ResetFIFO_AndCheckItsOperation + * Function Description: If no FIFO under run or over run interrupts after + * Audio FIFO restet, then FIFO is working fine + *---------------------------------------------------------------------------- + */ +BYTE ResetFIFO_AndCheckItsOperation(void) +{ + BYTE bError = FALSE; + BOOL qFIFO_OverUnderRun = TRUE; + BYTE bTry = 3; + BYTE bFIFO_DiffPointer; + + if ((SiI_Ctrl.bDevId == RX_SiI9021) || + (SiI_Ctrl.bDevId == RX_SiI9031)) { + /* !!!!!!!!! wait when FIFO UnderRun and OverRun are gone */ + do { + siiAudioFIFO_Reset(); + ClearFIFOOverUnderRunInterrupts(); + halDelayMS(1); + qFIFO_OverUnderRun = CheckFIFOOverUnderRunInterrupts(); + if (qFIFO_OverUnderRun) + break; + } while (--bTry); + } else { + siiAudioFIFO_Reset(); + ClearFIFOOverUnderRunInterrupts(); + + halDelayMS(1); + + qFIFO_OverUnderRun = CheckFIFOOverUnderRunInterrupts(); + } + if (qFIFO_OverUnderRun) { + bFIFO_DiffPointer = GetFIFO_DiffPointer(); + /* + *YMA change for Rx FIFO size 32 + *if ((bFIFO_DiffPointer < 2) || (bFIFO_DiffPointer > 16)) + */ + if ((bFIFO_DiffPointer < 2) || (bFIFO_DiffPointer > 0x19)) + bError = SiI_EC_FIFO_ResetFailure; + else + bError = SiI_EC_FIFO_UnderRunStuck; + } +#ifdef SII_DUMP_UART + PrintFIFO_Diff(); + PrintN(); + PrintCTS(); +#endif + return bError; +} +/*------------------------------------------------------------------------------ + * Function Name: SetAudioClock + * Function Description: Makes Master Clock Enable + *---------------------------------------------------------------------------- + */ +static void SetAudioClock(void) +{ + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL2_ADDR, RX_BIT_MCLK_EN, SET); +} +/*------------------------------------------------------------------------------ + * Function Name: ClearAudioClock + * Function Description: Makes Master Clock Disable + *---------------------------------------------------------------------------- + */ +static void ClearAudioClock(void) +{ + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL2_ADDR, RX_BIT_MCLK_EN, CLR); +} +/*------------------------------------------------------------------------------ + * Function Name: MaskUnusedAudioOutputs + * Function Description: disable unused channels in order to prevent audio noise + *---------------------------------------------------------------------------- + */ +static void MaskUnusedAudioOutputs(BYTE *pbRegister) +{ + BYTE bMask; + + if ((siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & RX_BIT_LAYOUT_1) + /* YMA 2 HBR mode may get layout 0, but needs to enable all SDx */ + || (SiI_Inf.AudioStatus.bRepresentation == + SiI_RX_AudioRepr_HBR)) { + bMask = 0xFF; + } else { + bMask = 0x1F; + } + *pbRegister &= bMask; +} + +/*------------------------------------------------------------------------------ + * Function Name: PrepareAACOn + * Function Description: prepare Automatic Audio Control On + *---------------------------------------------------------------------------- + */ +static void PrepareAACOn(void) +{ + BYTE bRegVal; + + bRegVal = siiReadByteHDMIRXP1(RX_I2S_CTRL2_ADDR); + bRegVal |= (BYTE)((SiI_Ctrl.wAudioOutputSelect >> 4) & 0xF3); + MaskUnusedAudioOutputs(&bRegVal); + /* Enable SDX (Reg (p1)27) */ + siiWriteByteHDMIRXP1(RX_I2S_CTRL2_ADDR, bRegVal); + + /* Enable SCK, WS, SPDIF, ignor VUCP errors (p1)2 */ + bRegVal = siiReadByteHDMIRXP1(RX_AUDIO_CTRL_ADDR); + if (SiI_Ctrl.wAudioOutputSelect & SiI_RX_AOut_SPDIF) + bRegVal |= RX_BIT_SPDIF_EN; + else + bRegVal &= (~RX_BIT_SPDIF_EN); + if (SiI_Ctrl.wAudioOutputSelect & SiI_RX_AOut_I2S) + bRegVal |= RX_BIT_I2S_MODE; + else + bRegVal &= (~RX_BIT_I2S_MODE); + if (SiI_Ctrl.wAudioOutputSelect & SiI_RX_AOut_SmoothHWMute) + bRegVal |= RX_SMOOTH_MUTE_EN; + else + bRegVal &= (~RX_SMOOTH_MUTE_EN); + bRegVal |= RX_BIT_PASS_SPDIF_ERR; + siiWriteByteHDMIRXP1(RX_AUDIO_CTRL_ADDR, bRegVal); +} +/*------------------------------------------------------------------------------ + * Function Name: IsAudioReady + * Function Description: check for Audio Error conditions + *---------------------------------------------------------------------------- + */ +static BOOL IsAudioReady(void) +{ + BOOL qResult = FALSE; + + ClearCTS_DroppedReusedInterrupts(); + + if (!GotAudioPackets()) + SiI_Inf.bAudioErr = SiI_EC_NoAudioPackets; + else if (!GotCTSPackets()) + SiI_Inf.bAudioErr = SiI_EC_NoCTS_Packets; + else if (!IsCTSInRange()) + SiI_Inf.bAudioErr = SiI_EC_CTS_OutOfRange; + else if (!GotAudioStable()) + SiI_Inf.bAudioErr = SiI_WC_CTS_Irregular; + else { + SiI_Inf.bAudioErr = SiI_EC_NoAudioErrors; + qResult = TRUE; + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiCheckAudio_IfOK_InitACR + * Function Description: Checks Audio Ready and makes ACR Reaset + * and Initialization + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiCheckAudio_IfOK_InitACR(void) +{ + BOOL qResult = FALSE; + + siiClearBCHCounter(); + + if (IsAudioReady()) + qResult = TRUE; + ACR_Reset(); + ACRInit(); + + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: CheckPLLUnLockAndReCheckAudio + * Function Description: checks audio PLL state, and another audio conditions + *---------------------------------------------------------------------------- + */ +BOOL CheckPLLUnLockAndReCheckAudio(void) +{ + BOOL qResult = FALSE; + + if (GotPLL_Unlocked()) + SiI_Inf.bAudioErr = SiI_EC_PLL_Unlock; + else if (IsAudioReady()) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: SaveInputAudioStatus + * Function Description: saving input Audio stream info into + * SiI_Inf.AudioStatus + * VG this function will be modified for DSD and other new audio streams + *---------------------------------------------------------------------------- + */ +void siiSaveInputAudioStatus(void) +{ + SiI_Inf.AudioStatus.bRepresentation = + SiI_Inf.AudioStatus.bAccuracyAndFs = + SiI_Inf.AudioStatus.bLength = 0; + SiI_Inf.AudioStatus.bNumberChannels = 0; + /* get audio sample representation */ + if (siiReadByteHDMIRXP1(RX_CH_STATUS1_ADDR) & + RX_BIT_AUDIO_SAMPLE_NPCM) { + SiI_Inf.AudioStatus.bRepresentation = + SiI_RX_AudioRepr_Compressed; + } else { + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_PCM; + } + if ((SiI_Ctrl.bDevId == RX_SiI9033 || SiI_Ctrl.bDevId == RX_SiI9133 || + SiI_Ctrl.bDevId == RX_SiI9135 || SiI_Ctrl.bDevId == RX_SiI9125) + && (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & + RX_BIT_DSD_STATUS)) { + SiI_Inf.AudioStatus.bRepresentation = SiI_RX_AudioRepr_DSD; + } + + /* get Fs/Length */ + if ((SiI_Inf.AudioStatus.bRepresentation == SiI_RX_AudioRepr_PCM) || + (SiI_Inf.AudioStatus.bRepresentation == + SiI_RX_AudioRepr_Compressed)) { + SiI_Inf.AudioStatus.bAccuracyAndFs |= + siiReadByteHDMIRXP1(RX_CH_STATUS4_ADDR); + SiI_Inf.AudioStatus.bLength = + (siiReadByteHDMIRXP1(RX_CH_STATUS5_ADDR) & 0x0F); + } + + /* bNumberChannels is copied from Audio InfoFrame if it's not Zero */ + if (SiI_Inf.AudioStatus.bNumberChannels == SiI_RX_NumAudCh_Unknown) { + if (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & RX_BIT_LAYOUT_1) { + SiI_Inf.AudioStatus.bNumberChannels = + SiI_RX_NumAudCh_UnknownMulti; + } else + SiI_Inf.AudioStatus.bNumberChannels = SiI_RX_NumAudCh_2; + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetAutoFIFOReset + * Function Description: this function enables or disables Auto FIFO reset + *---------------------------------------------------------------------------- + */ +void siiSetAutoFIFOReset(BOOL qOn) +{ + if ((SiI_Ctrl.bDevId == RX_SiI9125) || + (SiI_Ctrl.bDevId == RX_SiI9135)) { + if (qOn) { + /* YMA 9135 only */ + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR2, + RX_BIT_AUDIOFIFO_AUTO, SET); + } else { + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR2, + RX_BIT_AUDIOFIFO_AUTO, CLR); + } + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiPrepareTurningAudioOn + * Function Description: check audio and preparing for turning on + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiPrepareTurningAudioOn(void) +{ + BOOL qResult = FALSE; + + /* + *YMA removed: it is done in ISR, should not be called again here + *since the intr is cleared in ISR already + */ + /* siiChangeAudioStreamHandler(); */ + if (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & BIT_DSD_STATUS) + halSetAudioDACMode(SiI_RX_AudioRepr_DSD); + else + halSetAudioDACMode(SiI_RX_AudioRepr_PCM); + siiSetDigitalAudioMux(); + if (!CheckCTSChanged()) { + if (CheckPLLUnLockAndReCheckAudio()) { + SetAudioClock(); + /* MJ: Moved outside if to fix + *I2S DSD Audio FIFO Bug 3056 + */ + PrepareAACOn(); + SiI_Inf.bAudioErr = ResetFIFO_AndCheckItsOperation(); + if (!SiI_Inf.bAudioErr) { + /* PrepareAACOn(); */ + AudioExceptionsControl(ON); + + WakeUpAudioDAC(); + /* halSetAudioDACMode( + * SiI_Inf.AudioStatus.bRepresentation); + */ + qResult = TRUE; + } else { + ClearAudioClock(); + } + } + } else + SiI_Inf.bAudioErr = SiI_EC_CTS_Changed; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: DisableAudioOutputs + * Function Description: Disable SPDIF/I2S + *---------------------------------------------------------------------------- + */ +void DisableAudioOutputs(void) +{ + /* Disable SCK, SPDIF, Enable I2S/DSD */ + siiWriteByteHDMIRXP1(RX_AUDIO_CTRL_ADDR, 0x18); + siiIIC_RX_RWBitsInByteP1(RX_I2S_CTRL2_ADDR, RX_BITS_SD0_SD3_EN, CLR); +} +/*------------------------------------------------------------------------------ + * Function Name: siiTurningAudio + * Function Description: turning Audio On/Off + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiTurningAudio(BOOL qOn) +{ + if (qOn) { + PowerDownAudioDAC(); + siiAudioMute(OFF); + WakeUpAudioDAC(); + halClearHardwareAudioMute(); + } else { + AudioExceptionsControl(OFF); + halSetHardwareAudioMute(); + PowerDownAudioDAC(); + siiAudioMute(ON); + DisableAudioOutputs(); + } +} + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.h new file mode 100644 index 0000000..975bfc7 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIAudio.h @@ -0,0 +1,45 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +struct CTSLimitsType_s { + WORD Min; + WORD Max; +}; + +struct AudioOutputFormatType_s { + WORD wOutputSelect; + WORD wI2SBusFormat; + BYTE bI2SMap; + BYTE bDSDHBRFormat; +}; + +extern struct AudioOutputFormatType_s SavedAudioOutputFormat; +#define siiSetAudioMuteEvent() siiAudioFIFO_Reset() +#define GetFIFO_DiffPointer() siiReadByteHDMIRXP1(RX_FIFO_DIFF_ADDR) + +void siiAudioFIFO_Reset(void); +BOOL siiCheckAudio_IfOK_InitACR(void); +BOOL siiPrepareTurningAudioOn(void); +void siiTurningAudio(BOOL qOn); +void siiSetAnalogAudioMux(BYTE bChannel); +void siiSetDigitalAudioMux(void); +void siiClearGotCTSAudioPacketsIterrupts(void); +void siiClearCTSChangeInterruprt(void); +void siiSetAudioOutputFormat(struct AudioOutputFormatType_s *AudioOutputFormat); +void siiGetAudioOutputFormat(struct AudioOutputFormatType_s *AudioOutputFormat); +void siiSaveInputAudioStatus(void); +BOOL siiIsAudioStatusReady(void); +void siiSetAutoFIFOReset(BOOL qOn); +void siiAudioMute(BOOL qOn); + +void siiChangeDSDAudioStreamHandler(void); +void siiChangeHBRAudioStreamHandler(void); diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiICmplDefs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiICmplDefs.h new file mode 100644 index 0000000..64aa890 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiICmplDefs.h @@ -0,0 +1,93 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _SII_CMPLDEFS_ +#define _SII_CMPLDEFS_ + +/* Compiling with standard ANSI-C */ +#undef _STD_C_ +/* Compiling with 8052 microcontrollers (256 bytes RAM) */ +/* #define _8051_ */ + + +/* #define SII_DUMP_UART // Sending of debug data into UART (RS 232) */ + +#undef SII_USE_RX_PIN_INTERRUPT +/* Using interrupt pin for detection of interrupts + * from HDMI RX, otherwise interrupt status bit is used + */ + +#define SII_REQ_TASK_CALL_TIME 25 +/* Maximum reqomended interval time between calling SiI_RX_DoTasks() + * Do not modify this parameter without consulting + */ + +#undef SII_FIXED_TASK_CALL_TIME +/* Use this define when no system timer cannot be used + * If FIXED_TASK_CALL_TIME is defined, then TASK_CALL_TIME will be defined, too + * be sure TASK_CALL_TIME correspond to correct value + */ + +#ifdef SII_FIXED_TASK_CALL_TIME +#define SII_TASK_CALL_TIME 22 +/* Actual interval time between calling SiI_RX_DoTasks() */ +#endif + +#define SII_SYS_TICK_TIME 250 +/* System timer has been called with specified (SYS_TICK_TIME) time (in us) */ + +#define F_OSC_28_3 +#ifdef F_OSC_28_3 +/* XCLOCK is used for measureament of Vertical Refreshment Rate */ +#define SII_XCLOCK_OSC_SCALED_AND_MUL100 (2810073437) +/* ( F_OSC * 100 * 1016 ) / 1024 + * where F_OSC = 28322000 + */ + +#define SII_XCLOCK_OSC_SCALED_FOR_CALK_FPIX (28775) +/* ((F_OSC * 1016 )/1000) */ + + +#define SII_XCLOCK_OSC_SCALED2047_AND_MUL100 (2832200000) +/* F_OSC * 100 where F_OSC = 28322000 */ +#define SII_XCLOCK_OSC_SCALED2047_FOR_CALK_FPIX (464027) +/* ( (F_OSC * 16384 )/1000000) to yield units of MHz for pixel clock */ + +#else + +/* XCLOCK is used for measureament of Vertical Refreshment Rate */ +#define SII_XCLOCK_OSC_SCALED_AND_MUL100 (2679233671) +/* ( F_OSC * 100 * 1016 ) / 1024 + * where F_OSC = 27003300 + */ +#define SII_XCLOCK_OSC_SCALED_FOR_CALK_FPIX (27434) +/* ( (F_OSC * 1016 )/1000) */ + + +#endif + +#define SII_PCMODES +/* if defined, then project is compiled with PC Resolution tables */ +#define SII_861C_MODES +#define SII_ANALOG_DIG_AUDIO_MAX +/* if defined, analog mux is used for feeding audio in DVI mode */ + +#undef SII_OUTPUT_VFILTER +/* if defined, Video Filters are used with Analog Video Output */ + +#undef SII_BUG_PHOEBE_AUTOSW_BUG /* if define to apply SiI9023/33 fix */ +#undef SII_BUG_BETTY_PORT1_BUG +#define SII_NO_RESOLUTION_DETECTION +/* if defined data resolution data are taken from registers */ + +#define SII_I2C_ADAC_IF + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.c new file mode 100644 index 0000000..527872e --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.c @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------------ + * Module Name SiIDeepColor + * Module Description: this file is used to handle Deep Color functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiIRXIO.h" +#include "SiIRXDefs.h" +#include "SiIDeepColor.h" +#include "SiIVidF.h" + +/*------------------------------------------------------------------------------ + * Function Name: VideoFIFO_Reset + * Function Description: Makes Video FIFO reset + *---------------------------------------------------------------------------- + */ +void siiVideoFIFO_Reset(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR2, RX_BIT_DCFIFO_RST, SET); + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR2, RX_BIT_DCFIFO_RST, CLR); + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiCheckSupportDeepColorMode + * Function Description: This function chechs Deep Color mode support + * + * Accepts: TRUE/FALSE + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiCheckSupportDeepColorMode(void) +{ + BOOL qResult = FALSE; + + if ((SiI_Ctrl.bDevId == RX_SiI9133) + || (SiI_Ctrl.bDevId == RX_SiI9125) + || (SiI_Ctrl.bDevId == RX_SiI9135) + /* || (SiI_Ctrl[bHDMIDev].bDevId == RX_SiI8500) */ + ) { + qResult = TRUE; + } + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiResetDeepColorMode + * Function Description: This function sets TMDS registers respecting input + * color color depth + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiResetDeepColorMode(void) +{ + /* reset video FIFO feature only in 9135 and/or after */ + if (SiI_Ctrl.bDevId != RX_SiI9133) + siiVideoFIFO_Reset(); /* reset and flush video FIFO */ + siiIIC_RX_RMW_ByteP0(RX_TMDS_ECTRL_ADDR, + RX_DC_CLK_CTRL_MASK, RX_DC_CLK_8BPP_1X); + SiI_Inf.AVI.bInputColorDepth = SiI_RX_CD_24BPP; + /* bRegOldColorDepthStat = SiI_RX_CD_24BPP; */ +} +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_SetOutputColorDepth + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetOutputColorDepth(BYTE bOutputColorDepth) +{ + BYTE bError = FALSE; + + switch (bOutputColorDepth) { + case SiI_RX_CD_24BPP: + siiIIC_RX_RMW_ByteP0(RX_VID_MODE2_ADDR, + RX_DITHER_MODE_MASK, RX_DITHER_8BITS); + break; + case SiI_RX_CD_30BPP: + siiIIC_RX_RMW_ByteP0(RX_VID_MODE2_ADDR, + RX_DITHER_MODE_MASK, RX_DITHER_10BITS); + break; + case SiI_RX_CD_36BPP: + siiIIC_RX_RMW_ByteP0(RX_VID_MODE2_ADDR, + RX_DITHER_MODE_MASK, RX_DITHER_12BITS); + break; + default: + bError = SiI_EC_UnsupportedColorDepth; + } + + return bError; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetDeepColorMode + * Function Description: This function sets TMDS registers respecting + * input color color depth + * Accepts: none + * Returns: Error status + * Globals: none + *---------------------------------------------------------------------------- + */ + +BYTE siiSetDeepColorMode(void) +{ + BYTE bColorDepth; + BYTE bError = FALSE; + + if (siiCheckSupportDeepColorMode()) { + /* Read incoming pixel depth from + *latest General Control Packet + */ + bColorDepth = siiReadByteHDMIRXP0(RX_DC_STATUS_ADDR) & + RX_DC_PIXELDEPTH_MASK; + + /* If it differs from the current setting */ + if (bColorDepth != SiI_Inf.AVI.bInputColorDepth) { + + siiMuteVideo(ON); + + /* reset video FIFO feature only in 9135 and/or after */ + if (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) { + /* reset and flush video FIFO */ + siiVideoFIFO_Reset(); + } + /* Update the current setting */ + SiI_Inf.AVI.bInputColorDepth = bColorDepth; + + switch (bColorDepth) { /* Update the value in hardware*/ + case RX_DC_8BPP_VAL: + siiIIC_RX_RMW_ByteP0(RX_TMDS_ECTRL_ADDR, + RX_DC_CLK_CTRL_MASK, RX_DC_CLK_8BPP_1X); + break; + case RX_DC_10BPP_VAL: + siiIIC_RX_RMW_ByteP0(RX_TMDS_ECTRL_ADDR, + RX_DC_CLK_CTRL_MASK, + RX_DC_CLK_10BPP_1X); + break; + case RX_DC_12BPP_VAL: + siiIIC_RX_RMW_ByteP0(RX_TMDS_ECTRL_ADDR, + RX_DC_CLK_CTRL_MASK, + RX_DC_CLK_12BPP_1X); + break; + default: + bError = SiI_EC_UnsupportedColorDepth; + } + + siiMuteVideo(OFF); + } + } + return bError; +} diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.h new file mode 100644 index 0000000..a0bae99 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDeepColor.h @@ -0,0 +1,13 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +void siiVideoFIFO_Reset(void); +BYTE siiSetDeepColorMode(void); +BYTE SiI_RX_SetOutputColorDepth(BYTE bOutputColorDepth); +void siiResetDeepColorMode(void); diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.c new file mode 100644 index 0000000..2631862 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.c @@ -0,0 +1,48 @@ +#include "SiIDiagnostic.h" +/*------------------------------------------------------------------------------ + * Module Name: Diagnostic + * + * Module Description: contains a collection of diagnostic functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: siiGetNCTS + * Function Description: Reads N/CTS packet data from RX registers + * + * Accepts: none + * Returns: pointer on string of bytes + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetNCTS(BYTE *pbNCTS) +{ + siiReadBlockHDMIRXP1(RX_HW_N_VAL_ADDR, 3, pbNCTS); + pbNCTS[3] = 0; + + siiReadBlockHDMIRXP1(RX_HW_CTS_ADDR, 3, &pbNCTS[4]); + pbNCTS[7] = 0; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetABKSV + * Function Description: Reads AKSV and BKSV vectors from RX registers + * + * Accepts: none + * Returns: pointer on string of bytes + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetABKSV(BYTE *pbABKSV) +{ + siiReadBlockHDMIRXP0(RX_AKSV_ADDR, 5, pbABKSV); + siiReadBlockHDMIRXP0(RX_BKSV_ADDR, 5, &pbABKSV[5]); +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.h new file mode 100644 index 0000000..b7bb20a --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIDiagnostic.h @@ -0,0 +1,20 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +#include "SiIRXIO.h" +#include "SiIHAL.h" +#include "SiIRXDefs.h" + +void siiGetNCTS(BYTE *pbNCTS); +void siiGetABKSV(BYTE *pbABKSV); + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIGlob.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIGlob.h new file mode 100644 index 0000000..d0394a6 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIGlob.h @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#ifndef _SII_GLOB_ +#define _SII_GLOB_ + +#include "SiITypeDefs.h" +#include "SiIVidRes.h" + +#define SII_ADAC_PD_DELAY 0 + +/* RX API Information */ +enum SiI_RX_API_Info { + SiI_RX_API_Version = 0x01, + SiI_RX_API_Revision = 0x02,/* increased */ + SiI_RX_API_Build = 0x3,/* YMA 3 */ + SiI_RX_API_DiagnosticCommands = TRUE, +}; + +struct SysTimerType_s { + WORD wProcLastAPI_Ticks; + WORD wProcLastDoTasks_Ticks; +}; + +struct VideoFormatType_s { + BYTE bOutputVideoPath; + BYTE bOutputSyncSelect; + BYTE bOutputSyncCtrl; + BYTE bOutputVideoCtrl; +}; +/* + *typedef struct { + * BYTE bInputColorDepth; + * BYTE bOutputColorDepth; + *} DeepColorType; + */ +/* move to AVIType (sync as Vlad's new API code) */ + +struct SiI_CtrlType_s { + BYTE sm_bVideo; + BYTE sm_bAudio; + BYTE bDevId; + BYTE bRXInitPrm0; + BYTE bVidInChannel; + WORD wAudioTimeOut; + WORD wVideoTimeOut; + WORD bInfoFrameTimeOut; + BYTE bVideoPath; + WORD wAudioOutputSelect; + BYTE bShadowPixRepl; + BYTE bIgnoreIntr; + BYTE bHDCPFailFrmCnt; + BYTE bHDCPStuckConfirmCnt; + struct VideoFormatType_s VideoF; + struct SysTimerType_s SysTimer; + /* DeepColorType DC_Info; + * move to AVIType (sync as Vlad's new API code) + */ +}; + +struct ErrorType_s { + BYTE bAudio; + BYTE bIIC; +}; + +struct AudioStatusType_s { + BYTE bRepresentation; /* Compressed, PCM, DSD */ + BYTE bAccuracyAndFs; + BYTE bLength; + BYTE bNumberChannels; +}; + +struct AVIType_s { + BYTE bAVI_State; + BYTE bInputColorSpace; + BYTE bColorimetry; + BYTE bPixRepl; + BYTE bInputColorDepth; /* deep color API support */ + BYTE bOutputColorDepth; /* Output color depth API support */ +}; + +struct SiI_InfoType_s { + BYTE bVResId; + struct AVIType_s AVI; + BYTE bGlobStatus; + BYTE bHDCPStatus; + BYTE bNewInfoPkts; + struct AudioStatusType_s AudioStatus; + struct SyncInfoType_s Sync; + BYTE bAudioErr; + BYTE bIIC_Err; +}; + +extern IRAM BYTE SiI_bWCode[WRN_BUF_SIZE]; +extern IRAM BYTE SiI_bECode[ERR_BUF_SIZE]; + +extern IRAM struct SiI_InfoType_s SiI_Inf; +extern IRAM struct SiI_CtrlType_s SiI_Ctrl; + + +#endif /* end _SII_GLOB_ */ + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.c new file mode 100644 index 0000000..3dc8daf3 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.c @@ -0,0 +1,147 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIHAL + * Module Description: MCU (CPU) Hardware dependent functions have been + * placed here + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiIHAL.h" +#include "SiIRXAPIDefs.h" +#include "SiIGlob.h" +#include "UGlob.h" +#include "../platform_iface.h" + +WORD wScaleMS; + + +/*------------------------------------------------------------------------------ + * Function Name: InitGPIO_Pins + * Function Description: Configure GPIOs + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ + +void halInitGPIO_Pins(void) +{ + halPowerDownAudioDAC(); + /* YMA Clear is to activate. */ + halSetHPD1Pin(); + halSetHPD2Pin(); + + /* halClearHPD1Pin(); */ + /* halClearHPD2Pin(); */ +} +/*------------------------------------------------------------------------------ + * Function Name: halDelayMS + * Function Description: makes Delay in MS + * + * Accepts: BYTE, number of milliseconds to be delayed + * Returns: none + * Globals: wTicks + *---------------------------------------------------------------------------- + */ +void halDelayMS(BYTE MS) +{ +#ifdef _8051_ + wScaleMS = (WORD)((DWORD)(MS * 1000) / SII_SYS_TICK_TIME); + /* the expression can be optimized + * for simple TIME_TICK values + */ + RXEXTDBG("halDelayMS MS:%d, wScaleMS: %d\n", MS, wScaleMS); + + /* Value is global and decremented by hardware timer */ + while (wScaleMS) + udelay(100); + +#else + __plat_msleep(MS); +#endif + RXEXTDBG("halDelayMS %d\n", MS); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetTicksNumber + * Function Description: Get Ticks Number from system timer + * + * Accepts: none + * Returns: wTickCounter + * Globals: wTicks + *---------------------------------------------------------------------------- + */ +WORD siiGetTicksNumber(void) +{ +#ifdef _8051_ + WORD wTicks; + + do { + wTicks = wTickCounter; + } while (wTicks != wTickCounter); + /* reading of ticks should be atomic */ + + return wTicks; +#else + return wTickCounter; +#endif +} + + +/*------------------------------------------------------------------------------ + * Function Name: SysTickimerISR + * Function Description: Timer 0 interrupts, used to generate 8ms events used + * for executing scheduled tasks + *---------------------------------------------------------------------------- + */ +#ifdef _8051_ +void SysTickTimerISR(void) interrupt 1 +{ + TF0 = 0; /* Clear Interrupt Flag (8051 specific) */ + + if (wScaleMS) + wScaleMS--; /* Used to serve MS Delays */ + + if (wTickCounter == wNewTaskTickCounter) { + wNewTaskTickCounter += TASK_SLOT_IN_TICKS; + + if (!qReqTasksProcessing) { + if (bNewTaskSlot != LAST_TASK) + bNewTaskSlot++; + else + bNewTaskSlot = 0; + } + qReqTasksProcessing = TRUE; + } + /* Tick counter, used for time measuring */ + wTickCounter++; +} +#else +void SysTickTimerISR(void) +{ + if (wScaleMS) + wScaleMS--; /* Used to serve MS Delays */ + + if (wTickCounter == wNewTaskTickCounter) { + wNewTaskTickCounter += TASK_SLOT_IN_TICKS; + + if (!qReqTasksProcessing) { + if (bNewTaskSlot != LAST_TASK) + bNewTaskSlot++; + else + bNewTaskSlot = 0; + } + qReqTasksProcessing = TRUE; + } + /* Tick counter, used for time measuring */ + wTickCounter++; +} +#endif + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.h new file mode 100644 index 0000000..97f06bd --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHAL.h @@ -0,0 +1,97 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +#ifdef _8051_ +#include "UMCUDefs.h" +#endif + +#if 1 + +#define halAudioSetA() +#define halAudioSetB() +#define halAudioClearA() +#define halAudioClearB() +#define halAudioSetAltA() +#define halAudioSetAltB() +#define halAudioClearAltA() +#define halAudioClearAltB() + +#define halClearHardwareAudioMute() +#define halSetHardwareAudioMute() +#define halWakeUpAudioDAC() +#define halPowerDownAudioDAC() + +#define halReadRXInt_Pin() 0 +#define halGetHPD1Pin() 0 +#define halGetHPD2Pin() 0 +#define halSetHPD1Pin() +#define halSetHPD2Pin() +#define halClearHPD1Pin() +#define halClearHPD2Pin() + +#define halSetSDAPin() +#define halSetSCLPin() +#define halClearSDAPin() +#define halClearSCLPin() +#define halGetSDAPin() 0 +#define halGetSCLPin() 0 + +#define halAssertResetHDMIRXPin() +#define halReleaseResetHDMIRXPin() + +#elif defined(_8051_) + +#define halAudioSetA() (AudioSel0 = 1) +#define halAudioSetB() (AudioSel1 = 1) +#define halAudioClearA() (AudioSel0 = 0) +#define halAudioClearB() (AudioSel1 = 0) + +#define halAudioSetAltA() (AudioSelAlt0 = 1) +#define halAudioSetAltB() (AudioSelAlt1 = 1) +#define halAudioClearAltA() (AudioSelAlt0 = 0) +#define halAudioClearAltB() (AudioSelAlt1 = 0) + +#define halClearHardwareAudioMute() (MUTE = 0) +#define halSetHardwareAudioMute() (MUTE = 1) + +#define halWakeUpAudioDAC() (PDN = 1) +#define halPowerDownAudioDAC() (PDN = 0) + +#define halAssertResetHDMIRXPin() (Reset_HDMIRX = 0) +#define halReleaseResetHDMIRXPin() (Reset_HDMIRX = 1) + +#define halReadRXInt_Pin() (RXInt_Pin) +#define halGetHPD1Pin() (HPCh1Ctrl_Pin) +#define halGetHPD2Pin() (HPCh2Ctrl_Pin) +#define halSetHPD1Pin() (HPCh1Ctrl_Pin = 1) +#define halSetHPD2Pin() (HPCh2Ctrl_Pin = 1) +#define halClearHPD1Pin() (HPCh1Ctrl_Pin = 0) +#define halClearHPD2Pin() (HPCh2Ctrl_Pin = 0) + +#define halSetSDAPin() (SDA = 1) +#define halSetSCLPin() (SCL = 1) +#define halClearSDAPin() (SDA = 0) +#define halClearSCLPin() (SCL = 0) +#define halGetSDAPin() SDA +#define halGetSCLPin() SCL + +#define halGetPortSel() PSEL_Pin + +#endif + +void halInitGPIO_Pins(void); +void halDelayMS(BYTE MS); +WORD siiGetTicksNumber(void); + +void SysTickTimerISR(void); + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.c new file mode 100644 index 0000000..307e09c --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.c @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------------ + * Module Name SiIHDCP + * Module Description: HDCP functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIHDCP.h" +#include "SiIRXIO.h" +#include "SiIRXDefs.h" +#include "SiIRXAPIDefs.h" +/*------------------------------------------------------------------------------ + * Function Name: ReqReAuthenticationRX + * Function Description: clears Ri, used to notify upstream about HDCP failure + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void ReqReAuthenticationRX(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_HDCP_CTRL_ADDR, RX_BIT_TRASH_RI, SET); + /* this bit will be cleared automaticlly on authentication event */ + +} +/*----------------------------------------------------------------------------- + * Function Name: siiCheckHDCPDecrypting + * Function Description: checks if HDMI has been decrypted (used by HDCP) + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiCheckHDCPDecrypting(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDCP_STAT_ADDR) & RX_BIT_HDCP_DECRYPTING) + qResult = TRUE; + return qResult; +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.h new file mode 100644 index 0000000..18295d5 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDCP.h @@ -0,0 +1,15 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +void ReqReAuthenticationRX(void); +BOOL siiCheckHDCPDecrypting(void); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.c new file mode 100644 index 0000000..347a059 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.c @@ -0,0 +1,648 @@ +/*------------------------------------------------------------------------------ + * Module Name HDMIRX + * Module Description: this file is used to hadle misc RX functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiITrace.h" +#include "SiIRXDefs.h" +#include "SiIRXIO.h" +#include "SiIHDMIRX.h" +#include "SiIHAL.h" +#include "SiIVidIn.h" +#include "SiIInfoPkts.h" +#include "SiITTVideo.h" +#include "SiITTAudio.h" +#include "SiIAudio.h" +#include "SiIDeepColor.h" + +#include "../hdmirx_ext_drv.h" + +static BOOL bSeparateAFE; + +/*------------------------------------------------------------------------------ + * Function Name: siiRXHardwareReset + * Function Description: This function makes hardware reset of RX, + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiRXHardwareReset(void) +{ + halAssertResetHDMIRXPin(); + halDelayMS(1); + halReleaseResetHDMIRXPin(); + halDelayMS(5); +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetMasterClock + * Function Description: Sets Master Clock divider which used for Audio Output + * + * Accepts: BYTE + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetMasterClock(BYTE bDividerIndex) +{ + BYTE bRegVal; + + bRegVal = siiReadByteHDMIRXP1(RX_FREQ_SVAL_ADDR) & 0x0F; /*reg 102 */ + siiWriteByteHDMIRXP1(RX_FREQ_SVAL_ADDR, (bRegVal | + (bDividerIndex << 6) | (bDividerIndex << 4))); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetHBRMasterClock + * Function Description: Sets Master Clock divider which used for Audio Output + * Sets the Fs output as Fs input / 4 + * Accepts: BYTE + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetHBRFs(BOOL qON) +{ + BYTE bECode = FALSE; + BYTE bRegVal; + BYTE bMCLK; + + if (qON) { + /* reg 102 */ + bMCLK = siiReadByteHDMIRXP1(RX_FREQ_SVAL_ADDR) & 0xF0; + /* reg 117 */ + bRegVal = siiReadByteHDMIRXP1(RX_PCLK_FS_ADDR) & 0x0F; + switch (bRegVal) { + case _192Fs: /* 192K */ + bRegVal = _48Fs; /* 48K */ + break; + case _768Fs: /* 768k */ + bRegVal = _192Fs; /* 192K */ + break; + /*not HBR*/ + /*case _176Fs: // 176.4K + * bRegVal = _44Fs; // 44.10K + * break; + */ + default: /* YMA 08/17/06 handle invalid values? */ + break; + } + siiWriteByteHDMIRXP1(RX_FREQ_SVAL_ADDR, bRegVal | bMCLK); + + /* enable sw manually set Fs //100.1 */ + siiIIC_RX_RWBitsInByteP1(RX_ACR_CTRL1_ADDR, + RX_BIT_ACR_FSSEL, SET); + } else { + siiIIC_RX_RWBitsInByteP1(RX_ACR_CTRL1_ADDR, + RX_BIT_ACR_FSSEL, CLR); + } + + siiErrorHandler(bECode); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiIsHDMI_Mode + * Function Description: this function checks if RX in HDMI mode + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiIsHDMI_Mode(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP1(RX_AUDP_STAT_ADDR) & RX_BIT_HDMI_EN_MASK) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetRXDeviceInfo + * Function Description: reads RX Dev virsion/revision data from RX registers + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetRXDeviceInfo(BYTE *pbChipVer) +{ + siiReadBlockHDMIRXP0(RX_DEV_IDL_ADDR, 3, pbChipVer); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiRX_PowerDown + * Function Description: sets or claer main power down mode + * + * Accepts: bPowerDown + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiRX_PowerDown(BYTE bPowerDown) +{ + if (bPowerDown == ON) { + siiIIC_RX_RWBitsInByteP0(RX_SYS_CTRL1_ADDR, RX_BIT_PD_ALL, CLR); + if (bSeparateAFE == PRESENT) { + siiIIC_RX_RWBitsInByteU0(RX_SYS_CTRL1_ADDR, + RX_BIT_PD_ALL, CLR); + } + } else { + siiIIC_RX_RWBitsInByteP0(RX_SYS_CTRL1_ADDR, RX_BIT_PD_ALL, SET); + if (bSeparateAFE == PRESENT) { + siiIIC_RX_RWBitsInByteU0(RX_SYS_CTRL1_ADDR, + RX_BIT_PD_ALL, SET); + } + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiRX_DisableTMDSCores + * Function Description: Sets global power down mode + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiRX_DisableTMDSCores(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_SYS_SW_SWTCHC_ADDR, + (RX_BIT_RX0_EN | RX_BIT_DDC0_EN | + RX_BIT_RX1_EN | RX_BIT_DDC1_EN), CLR); + if (bSeparateAFE == PRESENT) { + siiIIC_RX_RWBitsInByteU0(RX_SYS_SW_SWTCHC_ADDR, + RX_BIT_RX0_EN, CLR); + } +} + +/*------------------------------------------------------------------------------ + * Function Name: sii_SetVideoOutputPowerDown + * Function Description: + * + * Accepts: bPowerState + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void sii_SetVideoOutputPowerDown(BYTE bVideoOutputPowerDown) +{ + switch (bVideoOutputPowerDown) { + + case SiI_RX_VidOutPD_NoPD: + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS_ADDR, + RX_BIT_NPD_VIDEO_DAC, SET); + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + RX_BIT_NPD_DIGITAL_OUTPUTS, SET); + break; + case SiI_RX_VidOutPD_Analog: + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS_ADDR, + RX_BIT_NPD_VIDEO_DAC, CLR); + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + RX_BIT_NPD_DIGITAL_OUTPUTS, SET); + break; + case SiI_RX_VidOutPD_AnalogAndDigital: + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS_ADDR, + RX_BIT_NPD_VIDEO_DAC, CLR); + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + RX_BIT_NPD_DIGITAL_OUTPUTS, CLR); + break; + case SiI_RX_VidOutPD_Digital: + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS_ADDR, + RX_BIT_NPD_VIDEO_DAC, SET); + siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + RX_BIT_NPD_DIGITAL_OUTPUTS, CLR); + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiRX_GlobalPower + * Function Description: Sets or takes from most saving power down mode + * + * Accepts: bPowerState + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiRX_GlobalPower(BYTE bPowerState) +{ + if (bPowerState == SiI_RX_Power_Off) { + siiSetSM_ReqGlobalPowerDown(); + siiSetAudioMuteEvent(); + } else if (SiI_Ctrl.sm_bVideo != SiI_RX_VS_VideoOn) { + siiChangeVideoInput(SiI_Ctrl.bVidInChannel); + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiRX_CheckCableHPD + * Function Description: Checks if HDMI cable has hot plug + * + * Accepts: none + * Returns: BOOL hot plug state + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiRX_CheckCableHPD(void) +{ + BOOL qResult = FALSE; + + /* YMA NOTE /R0x06/bit3/ 5V ower detect */ + if (siiReadByteHDMIRXP0(RX_STATE_ADDR) & RX_BIT_CABLE_HPD) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiClearBCHCounter + * Function Description: clears BCH counter. The counter accomulates BCH errors + * if counter won't be clear it can cause HDCP interrupts + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiClearBCHCounter(void) +{ + siiIIC_RX_RWBitsInByteP0(RX_ECC_CTRL_ADDR, RX_BIT_CLR_BCH_COUNTER, SET); +} +/*------------------------------------------------------------------------------ + * Function Name: InitAECRegisters + * Function Description: Initialization of Audio Exception registers + * which used for auto-muting + *---------------------------------------------------------------------------- + */ +static void InitAECRegisters(void) +{ + BYTE abData[3]; + + abData[0] = 0xC1; + abData[1] = 0x87; + abData[2] = 0x01; + siiWriteBlockHDMIRXP0(RX_AEC1_ADDR, 3, abData); +} +/*------------------------------------------------------------------------------ + * Function Name: siiRX_InitializeInterrupts + * Function Description: Initialize RX interrupts + * (used with polling RX interrupt pin) + *---------------------------------------------------------------------------- + */ +static void RX_InitializeInterrupts(void) +{ + BYTE abData[4]; + + abData[0] = 0x42; /* N change, used in repeater configuration */ + /* HDCP Start */ + abData[1] = 0x88; /* HDMI Change SCDT int */ + abData[2] = 0x9F; /* infoFrame interrupts enable */ + abData[3] = 0x40; /* HDCP Failed */ + siiWriteBlockHDMIRXP0(RX_HDMI_INT_GR1_MASK_ADDR, 4, abData); + abData[0] = 0x58; /* ACC done enable, VRes Change, HRes Change */ + abData[1] = 0x00; /* Aud Ch Status Ready */ + siiWriteBlockHDMIRXP0(RX_HDMI_INT_GR2_MASK_ADDR, 2, abData); + siiWriteByteHDMIRXP0(RX_INFO_FRAME_CTRL_ADDR, RX_BIT_NEW_ACP); +} +/*------------------------------------------------------------------------------ + * Function Name: InitSoftwareResetReg + * Function Description: Initialize software reset register + *---------------------------------------------------------------------------- + */ +void InitSoftwareResetReg(void) +{ +#ifndef SII_BUG_BETTY_PORT1_BUG + /* when no SCDT software reset is applied */ + siiWriteByteHDMIRXP0(RX_SWRST_ADDR, RX_BIT_SW_AUTO); +#endif + + if (bSeparateAFE == PRESENT) { + /* when no SCDT software reset is applied */ + siiWriteByteAFEU0(RX_SWRST_ADDR, RX_BIT_SW_AUTO); + + /* IP requires HDCP reset at start */ + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, 0x08, SET); + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, 0x08, CLR); + } +} + +#ifdef SII_BUG_PHOEBE_AUTOSW_BUG +/*------------------------------------------------------------------------------ + * Function Name: SetAutoSWReset + * Function Description: this function enables or disables Auto Software reset + * Accepts: BOOL qOn + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetAutoSWReset(BOOL qOn) +{ + if ((SiI_Ctrl.bDevId == RX_SiI9023) || + (SiI_Ctrl.bDevId == RX_SiI9033)) { + if (qOn) { + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, + RX_BIT_SW_AUTO, SET); + } else { + siiIIC_RX_RWBitsInByteP0(RX_SWRST_ADDR, + RX_BIT_SW_AUTO, CLR); + } + } +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: GetRXDevId + * Function Description: used for detection onboard HDMI RX + *---------------------------------------------------------------------------- + */ +BYTE GetRXDevId(void) +{ + BYTE abDevInfo[3]; + WORD wDevId; + BYTE bDevId = 0; + + siiGetRXDeviceInfo(abDevInfo); + wDevId = abDevInfo[0] | (abDevInfo[1] << 8); + switch (wDevId) { + case SiI9993: + bDevId = RX_SiI9993; + break; + case SiI9031: + bDevId = RX_SiI9031; + break; + case SiI9021: + bDevId = RX_SiI9021; + break; + case SiI9023: + bDevId = RX_SiI9023; + break; + case SiI9033: + bDevId = RX_SiI9033; + break; + case SiI9011: + bDevId = RX_SiI9011; + break; + case SiI9051: + bDevId = RX_SiI9051; + break; + case SiI9133: + bDevId = RX_SiI9133; + break; + case SiI9135: + bDevId = RX_SiI9135; + break; + case SiI9125: + bDevId = RX_SiI9125; + break; + default: + bDevId = RX_Unknown; + } + RXEXTPR("%s: abDevInfo=0x%02x,0x%02x, wDevId=0x%04x, bDevId=%d\n", + __func__, abDevInfo[0], abDevInfo[1], wDevId, bDevId); + return bDevId; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetAFEClockDelay + * Function Description: Set output clock depay for Analog Front End + *---------------------------------------------------------------------------- + */ + +void siiSetAFEClockDelay(void) +{ +#if 0 + BYTE bClkCount; + BYTE bDDRdelay; + BYTE abData[2] = {0x00, 0x60}; + + if (bSeparateAFE == PRESENT) { + bClkCount = siiReadByteAFEU0(0x11); + printf("Count: 0x%02x\n", (int)bClkCount); + + if (bClkCount < 0x40) + bDDRdelay = abData[0]; + else + bDDRdelay = abData[1]; + + siiWriteByteAFEU0(RX_AFE_DDR_DSA_ADDR, bDDRdelay); + printf("DDRdelay: 0x%02x\n", (int)bDDRdelay); + } +#endif +} + +/*------------------------------------------------------------------------------ + * Function Name: siiInitAFE + * Function Description: Initialize the Analog Front End + *---------------------------------------------------------------------------- + */ +void siiInitAFE(void) +{ + siiWriteByteAFEU0(RX_AFE_DDR_CONF_ADDR, 0x01); + siiWriteByteAFEU0(RX_AFE_DDR_DSA_ADDR, 0x00); + bSeparateAFE = TRUE; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiConfigureTerminationValue + * Function Description: + *---------------------------------------------------------------------------- + */ +void siiSetNormalTerminationValueCh1(BOOL qOn) +{ + BYTE bRegVal; + /* YMA set the terminaion to 3k ohm first and then after HPD, + *change it back to normal + */ + bRegVal = siiReadByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR); + if (qOn) { + /* YMA clear bit 0,1 for ch0 */ + siiWriteByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR, bRegVal & 0xFC); + } else { + /* YMA set bit 0,1 for ch0 */ + siiWriteByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR, bRegVal | 0x03); + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetNormalTerminationValueCh2 + * Function Description: + *---------------------------------------------------------------------------- + */ +void siiSetNormalTerminationValueCh2(BOOL qOn) +{ + BYTE bRegVal; + /* YMA set the terminaion to 3k ohm first and then after HPD, + *change it back to normal + */ + bRegVal = siiReadByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR); + if (qOn) { + /* YMA clear bit 5,6 for ch2 */ + siiWriteByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR, bRegVal&0x9F); + } else { + /* YMA set bit 5,6 for ch2 */ + siiWriteByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR, bRegVal|0x60); + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiInitializeRX + * Function Description: Initialize RX + * + * Accepts: pointer on data which are used for inialization + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiInitializeRX(BYTE *pbInit) +{ + BOOL qResult = FALSE; + BOOL qFPGA = FALSE; + BOOL qUrsula = FALSE; + BYTE bRegVal; + WORD wTimeOut = 500; + + siiRXHardwareReset(); + /* YMA the block below takes too long time for !qUrsula devices */ + /* move to after devID is detected. */ + /* if (siiWaitForAckAFE(wTimeOut)) { + * siiInitAFE(); + * wTimeOut = 15000; + * qUrsula = TRUE; + *} + */ + if (pbInit[0] & SiI_RX_FPGA) { + qFPGA = TRUE; + wTimeOut = 15000; + } + + if (siiWaitForAckHDMIRX(wTimeOut)) { + InitSoftwareResetReg(); + SiI_Ctrl.bDevId = GetRXDevId(); + + if ((SiI_Ctrl.bDevId != RX_SiI9135) && + (SiI_Ctrl.bDevId != RX_SiI9125)) { + if (siiWaitForAckAFE(wTimeOut)) { + siiInitAFE(); + wTimeOut = 15000; + qUrsula = TRUE; + } + } + if (qFPGA && (!qUrsula)) { + siiWriteByteHDMIRXP1(RX_ACR_CTRL3_ADDR, + RX_CTS_THRESHOLD | RX_BIT_MCLK_LOOPBACK | 0x01); + } else { + siiWriteByteHDMIRXP1(RX_ACR_CTRL3_ADDR, + RX_CTS_THRESHOLD | RX_BIT_MCLK_LOOPBACK); + } + + siiWriteByteHDMIRXP1(RX_LK_WIN_SVAL_ADDR, 0x0F); + siiWriteByteHDMIRXP1(RX_LK_THRESHOLD_ADDR, 0x20); + siiWriteByteHDMIRXP1(RX_LK_THRESHOLD_ADDR + 1, 0x00); + /* siiWrite threshold for PLL unlock interrupt */ + siiWriteByteHDMIRXP1(RX_LK_THRESHOLD_ADDR + 2, 0x00); + + if (pbInit[0] & SiI_RX_InvertOutputVidClock) { + /* set Video bus width and Video data edge */ + siiWriteByteHDMIRXP0(RX_SYS_CTRL1_ADDR, + RX_BIT_VID_BUS_24BIT | + RX_BIT_INVERT_OUTPUT_VID_CLK); + } else { + siiWriteByteHDMIRXP0(RX_SYS_CTRL1_ADDR, + RX_BIT_VID_BUS_24BIT); + } + /* YMA removed since actually no bit for it, changed to #define + * if (pbInit[0] & SiI_RX_DSD_Uses_I2S_SPDIF_Buses) + */ +#ifdef SiI_RX_DSD_Uses_I2S_SPDIF_Buses + siiIIC_RX_RWBitsInByteP1(RX_AUDIO_SWAP_ADDR, + BIT_DSD_USES_I2S_SPDIF_BUSES, SET); +#endif + /* SCL edge, if need customize SPDIF parameters */ + siiWriteByteHDMIRXP1(RX_I2S_CTRL1_ADDR, 0x40); + siiWriteByteHDMIRXP1(RX_HDMI_CRIT1_ADDR, 0x06); + siiWriteByteHDMIRXP1(RX_HDMI_CRIT2_ADDR, 0x0C); + + /* Set Interrupt polarity (Neg.) */ + siiWriteByteHDMIRXP0(RX_INT_CNTRL_ADDR, 0x06); + /* AudioVideo Mute ON */ + siiWriteByteHDMIRXP1(RX_AUDP_MUTE_ADDR, 0x03); + + /* Audio PLL setting */ + siiWriteByteHDMIRXP0(RX_APLL_POLE_ADDR, 0x88); + /* Audio PLL setting, improved PLL lock time */ + siiWriteByteHDMIRXP0(RX_APLL_CLIP_ADDR, 0x16); + + /* YMA CP9135/25 reference board has 5ohm external resistor, + * so the TMDS termination control should set to + * 45 ohm 50 ohm instead of the default value 50 ohm + */ + /* 9125/35 has only the TQFP package, + * so this applies to all the devices have 9125/35 device ID + */ + + /* YMA removed. + * set the terminaion to 3k ohm first and then after HPD, + * change it back to normal + */ + /* if (SiI_Ctrl.bDevId == RX_SiI9135 || + * SiI_Ctrl.bDevId == RX_SiI9125) { + * siiWriteByteHDMIRXP0(RX_TMDS_TERMCTRL_ADDR, + * 0x0c); //45 ohm + * } + */ + + if ((SiI_Ctrl.bDevId == RX_SiI9133) || + (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) || + (SiI_Ctrl.bDevId == RX_SiIIP11)) { + /* set equlizer register value, + *optimized for different length of + */ + siiWriteByteHDMIRXP0(RX_TMDS_ECTRL_ADDR, 0x00); + } else { + /* set equlizer register value, + *optimized for different length of + */ + siiWriteByteHDMIRXP0(RX_TMDS_ECTRL_ADDR, 0xC3); + } + /* no need to process MPEG as data is screwed there */ + siiWriteByteHDMIRXP1(RX_MPEG_DEC_ADDR, ISRC1_Type); + + /* ramp slope for Soft Audio Mute */ + siiWriteByteHDMIRXP1(RX_MUTE_DIV_ADDR, 0x02); + siiSetMasterClock(SelectMClock & pbInit[0]); + + InitAECRegisters(); + RX_InitializeInterrupts(); + + bRegVal = siiReadByteHDMIRXP0(RX_SYS_SW_SWTCHC_ADDR); + if ((SiI_Ctrl.bVidInChannel == SiI_RX_VInCh1) || + (SiI_Ctrl.bDevId == RX_SiI9011)) { + siiWriteByteHDMIRXP0(RX_SYS_SW_SWTCHC_ADDR, + bRegVal | 0x11); + } else { + siiWriteByteHDMIRXP0(RX_SYS_SW_SWTCHC_ADDR, + bRegVal | 0x22); + } + + if (bSeparateAFE == PRESENT) + siiWriteByteAFEU0(RX_SYS_SW_SWTCHC_ADDR, 0x01); + + siiWriteByteHDMIRXP0(RX_ECC_BCH_THRESHOLD, 0x02); + + siiClearBCHCounter(); + qResult = TRUE; + if (siiCheckSupportDeepColorMode()) { + if (SiI_RX_SetOutputColorDepth(pbInit[1])) + qResult = FALSE; + } + + } else { + siiErrorHandler(SiI_EC_NoAckIIC); + } + return qResult; +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.h new file mode 100644 index 0000000..5c8f168 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHDMIRX.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +void siiGetRXDeviceInfo(BYTE *pbChipVer); +BOOL siiIsHDMI_Mode(void); +BOOL siiInitializeRX(BYTE *pbInit); +void siiRX_PowerDown(BYTE bPowerDown); +void siiRX_GlobalPower(BYTE bPowerState); +void siiSetMasterClock(BYTE bDividerIndex); + +BOOL siiRX_CheckCableHPD(void); +void siiClearBCHCounter(void); +void siiRX_DisableTMDSCores(void); +void sii_SetVideoOutputPowerDown(BYTE bVideoOutputPowerDown); +void siiSetAutoSWReset(BOOL qOn); +void siiRXHardwareReset(void); +void siiSetAFEClockDelay(void); +BOOL siiCheckSupportDeepColorMode(void); + +void siiSetHBRFs(BOOL qON); +void siiSetNormalTerminationValueCh1(BOOL qOn); +void siiSetNormalTerminationValueCh2(BOOL qOn); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.c new file mode 100644 index 0000000..4276e09 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.c @@ -0,0 +1,117 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIHLVIIC + * + * Module Description: high level i2c routines + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiIHLVIIC.h" +/* #include "SiISW_IIC.h" */ +#include "SiIIICDefs.h" +#include "SiIHAL.h" +#include "../platform_iface.h" + + +/*------------------------------------------------------------------------ */ +BOOL hlWaitForAck(BYTE bSlvAddr, WORD wTimeOut) +{ +#if 0 + BOOL bResult = FALSE; + int ret = 0; + char value = 0x00; + + ret = __plat_i2c_write_block((bSlvAddr >> 1), 0x00, &value, 1); + if (ret == 0) + bResult = TRUE; + + return bResult; +#else + return TRUE; +#endif +} + + +/*-------------------------------------------------------------------------- */ +BYTE hlBlockRead_8BAS(struct I2CShortCommandType_s *IIC, BYTE *Data) +{ + int ret = 0; + + ret = __plat_i2c_read_block((IIC->SlaveAddr >> 1), + IIC->RegAddrL, Data, IIC->NBytes); + + ret = (ret >= 0 ? IIC_OK : IIC_ERROR); + return ret; +} + +/*--------------------------------------------------------------------------- */ + +BYTE hlBlockWrite_8BAS(struct I2CShortCommandType_s *IIC, BYTE *Data) +{ + int ret = 0; + + ret = __plat_i2c_write_block((IIC->SlaveAddr >> 1), + IIC->RegAddrL, Data, IIC->NBytes); + + ret = (ret >= 0 ? IIC_OK : IIC_ERROR); + return ret; + +} +/*------------------------------------------------------------------- */ +BYTE hlReadByte_8BA(BYTE SlaveAddr, BYTE RegAddr) +{ + int ret = 0; + unsigned char data = 0; + + ret = __plat_i2c_read_block((SlaveAddr >> 1), RegAddr, &data, 1); + if (ret >= 0) + return data; + + return 0; +} + +/*-------------------------------------------------------------------- */ + +WORD hlReadWord_8BA(BYTE SlaveAddr, BYTE RegAddr) +{ + int ret = 0; + unsigned char data[2] = {0, 0}; + WORD tmp; + + ret = __plat_i2c_read_block((SlaveAddr >> 1), + RegAddr, (char *)&data, 2); + if (ret >= 0) { + tmp = ((data[1] << 8) | data[0]); + return tmp; + } + + return 0; +} + + +/*------------------------------------------------------------------- */ +void hlWriteByte_8BA(BYTE SlaveAddr, BYTE RegAddr, BYTE Data) +{ + int ret = 0; + + ret = __plat_i2c_write_block((SlaveAddr >> 1), RegAddr, &Data, 1); +} +/*------------------------------------------------------------------- */ + +void hlWriteWord_8BA(BYTE SlaveAddr, BYTE RegAddr, WORD Data) +{ + int ret = 0; + unsigned char buf[2] = {0, 0}; + + buf[0] = Data & 0xff; + buf[1] = Data >> 8; + + ret = __plat_i2c_write_block((SlaveAddr >> 1), RegAddr, buf, 2); +} + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.h new file mode 100644 index 0000000..b74a93d --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIHLVIIC.h @@ -0,0 +1,60 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +/* #include "UCom.h" */ +#ifndef _HLVIIC_ +#define _HLVIIC_ + +#define IIC_CAPTURED 1 +#define IIC_NOACK 2 +#define MDDC_CAPTURED 3 +#define MDDC_NOACK 4 +#define MDDC_FIFO_FULL 5 +#define IIC_OK 0 +#define IIC_ERROR 6 + +#define RX_SLV0 0x60 +#define RX_SLV1 0x68 +#define RX_AFE0 0x64 +#define RX_AFE1 0x6C + +#define SET 1 +#define CLR 0 + +#define MDDC_BUS 2 + + + +struct I2CShortCommandType_s { + + BYTE SlaveAddr; + BYTE Flags; + BYTE NBytes; + BYTE RegAddrL; + BYTE RegAddrH; + +}; + + +BYTE hlBlockRead_8BAS(struct I2CShortCommandType_s *IIC, BYTE *Data); +BYTE hlBlockWrite_8BAS(struct I2CShortCommandType_s *IIC, BYTE *Data); +BYTE hlReadByte_8BA(BYTE SlaveAddr, BYTE RegAddr); +WORD hlReadWord_8BA(BYTE SlaveAddr, BYTE RegAddr); +void hlWriteWord_8BA(BYTE SlaveAddr, BYTE RegAddr, WORD Data); +void hlWriteByte_8BA(BYTE SlaveAddr, BYTE RegAddr, BYTE Data); +BOOL hlWaitForAck(BYTE bSlvAddr, WORD wTimeOut); +BYTE hlWriteAddr_8BA(BYTE bdata1, BYTE bdata2); + + + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIIICDefs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIIICDefs.h new file mode 100644 index 0000000..b058856 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIIICDefs.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef SII_IIC_DEFS +#define SII_IIC_DEFS + + +#define IIC_WRITE 0x0 +#define IIC_READ 0x01 +#define ALIGN24C02 0x07 /* 8 bytes page */ +#define ALIGN24C32 0x1f /* 32 bytes page */ +#define ALIGN24C264 0x3f /* 64 bytes page */ + + +#define I2CGetByte() _I2CGetByte(0) +#define I2CGetLastByte() _I2CGetByte(1) +#define DDC_I2CGetByte() DDC__I2CGetByte(0) +#define DDC_I2CGetLastByte() DDC__I2CGetByte(1) + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.c new file mode 100644 index 0000000..cb52a7d --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.c @@ -0,0 +1,485 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIISR.c + * --- + * Module Description: serves RX interrupts + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiIISR.h" +#include "SiIHAL.h" +#include "SiIRXIO.h" +#include "SiIHDMIRX.h" +#include "SiITTAudio.h" +#include "SiITTVideo.h" +#include "SiIInfoPkts.h" +#include "SiITTInfoPkts.h" +#include "SiIHDCP.h" +#include "SiITTasks.h" +#include "SiIAudio.h" +#include "SiIDeepColor.h" + +#include "../hdmirx_ext_drv.h" + +/* Declaratins of functions which used only inside the module */ +static BOOL CheckAVIHader(void); +static void SetNoAVIIntrrupts(BOOL); +static void ProcessChangeBetween_DVI_HDMI_Modes(void); +static void EnableCheckHDCPFailureWithVSyncRate(BOOL); +static void AVI_And_NoAVI_WorkAround(BYTE *); +static BOOL GotNConsecutiveVSyncHDCPFailure(void); +static BOOL DetectHDCPStuck(void); +static BYTE GotNConsecutiveHDCPStuckInterrupt(void); +static BYTE HDCPErrorHandler(BYTE, BYTE); +static BYTE RXInterruptHandler(void); + + +/*------------------------------------------------------------------------------ + * Function Name: siiTraceRXInterrupts + * Function Description: This function reads RX interrupts and used for + * debugging purpose only + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +#ifdef SII_DUMP_UART +void siiTraceRXInterrupts(void) +{ + BYTE i, abIntrData[7]; + + /* including main status reg */ + siiReadBlockHDMIRXP0(RX_HDMI_INT_GR1_ADDR - 1, 5, abIntrData); + siiReadBlockHDMIRXP0(RX_HDMI_INT_GR2_ADDR, 2, &abIntrData[5]); + + printf("\n RX ints:"); + for (i = 0; i < 7; i++) + printf(" 0x%02X", (int)abIntrData[i]); +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: CheckAVIHader + * Function Description: checks if Id header byte has data + *---------------------------------------------------------------------------- + */ +static BOOL CheckAVIHader(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP1(RX_AVI_IF_ADDR) != 0) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: SetNoAVIIntrrupts + * Function Description: Enable or Disable NoAVI interrupt + *---------------------------------------------------------------------------- + */ +static void SetNoAVIIntrrupts(BOOL qOn) +{ + if (qOn) { + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST4_MASK_ADDR, + RX_BIT_MASK_NO_AVI_INTR, SET); + SiI_Ctrl.bIgnoreIntr |= qcIgnoreNoAVI; + } else { + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST4_MASK_ADDR, + RX_BIT_MASK_NO_AVI_INTR, CLR); + SiI_Ctrl.bIgnoreIntr &= (~qcIgnoreNoAVI); + } +} +/*------------------------------------------------------------------------------ + * Function Name: AVI_And_NoAVI_WorkAround + * Function Description: this function is used to resolve conflict situation + * when AVIChange an NoAVI both are set + *---------------------------------------------------------------------------- + */ +static void AVI_And_NoAVI_WorkAround(BYTE *bpInfoFramesIntrrupts) +{ + if ((*bpInfoFramesIntrrupts & NoAVI_Mask) && + (*bpInfoFramesIntrrupts & AVI_Mask)) { + if (CheckAVIHader()) + *bpInfoFramesIntrrupts &= (~NoAVI_Mask); + else + *bpInfoFramesIntrrupts &= (~AVI_Mask); + } + if (*bpInfoFramesIntrrupts & NoAVI_Mask) + SetNoAVIIntrrupts(OFF); + if (*bpInfoFramesIntrrupts & AVI_Mask) + SetNoAVIIntrrupts(ON); + +} + +/*------------------------------------------------------------------------------ + * Function Name: ProcessChangeBetween_DVI_HDMI_Modes + * Function Description: Processing when RX mode changed between HDMI/DVI + *---------------------------------------------------------------------------- + */ +static void ProcessChangeBetween_DVI_HDMI_Modes(void) +{ + + if (siiIsHDMI_Mode()) { + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_Detected; + siiSetSM_ReqAudio(); + siiInitACPCheckTimeOut(); + } else { + SiI_Inf.bGlobStatus &= + (~(SiI_RX_GlobalHDMI_Detected | SiI_RX_GlobalHDMI_ACP)); + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_NoAVIPacket; + SiI_Inf.bNewInfoPkts = 0; + siiResetACPPacketData(); + SetNoAVIIntrrupts(OFF); + } +} +#ifdef SII_BUG_PHOEBE_AUTOSW_BUG +/*------------------------------------------------------------------------------ + * Function Name: siiCheckTransitionToDVIModeAndResetHDMIInfoIfConfirmed + * Function Description: + * + * Accepts: + * Returns: + * Globals: + *---------------------------------------------------------------------------- + */ + +void siiCheckTransitionToDVIModeAndResetHDMIInfoIfConfirmed(void) +{ + if (!siiIsHDMI_Mode()) { + SiI_Inf.bGlobStatus &= + (~(SiI_RX_GlobalHDMI_Detected | SiI_RX_GlobalHDMI_ACP)); + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_NoAVIPacket; + SiI_Inf.bNewInfoPkts = 0; + siiTurnAudioOffAndSetSM_AudioOff(); + SetNoAVIIntrrupts(OFF); + siiClearAVI_Info(&SiI_Inf.AVI); + } +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: EnableHDCPCheckUsingVSyncInt + * Function Description: This function enables using VSync Interrupts for + * processing HDCP errors on field to field base or + * disable the mode with switching wait for isolated HDCP + * Failure + *---------------------------------------------------------------------------- + */ +static void EnableCheckHDCPFailureWithVSyncRate(BOOL qOn) +{ + if (qOn) { + SiI_Ctrl.bHDCPFailFrmCnt = 1; + /* don't clear HDCP Failure Int if this bit is set */ + SiI_Ctrl.bIgnoreIntr |= qcIgnoreHDCPFail; + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST2_MASK_ADDR, + RX_BIT_VSYNC, SET); + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST4_MASK_ADDR, + RX_BIT_HDCP_FAILED, CLR); + } else { + SiI_Ctrl.bHDCPFailFrmCnt = 0; + SiI_Ctrl.bIgnoreIntr &= (~qcIgnoreHDCPFail); + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST2_MASK_ADDR, + RX_BIT_VSYNC, CLR); + siiIIC_RX_RWBitsInByteP0(RX_HDMI_INT_ST4_MASK_ADDR, + RX_BIT_HDCP_FAILED, SET); + } +} +/*------------------------------------------------------------------------------ + * Function Name: GotNConsecutiveVSyncHDCPFailure + * Function Description: If HDCP Failure is repeated on frame to frame base + * and reached threshold then function return TRUE + * The function is called if: VSync && HDCPFailureInt + *---------------------------------------------------------------------------- + */ +static BOOL GotNConsecutiveVSyncHDCPFailure(void) +{ + BOOL qResult = FALSE; + + if (!DetectHDCPStuck()) + SiI_Ctrl.bHDCPFailFrmCnt++; + if (SiI_Ctrl.bHDCPFailFrmCnt == cbHDCPFailFrmThres) + qResult = TRUE; + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: DetectHDCPStuck + * Function Description: + *---------------------------------------------------------------------------- + */ +static BOOL DetectHDCPStuck(void) +{ + WORD wHDCPErrors; + BOOL qError = FALSE; + + wHDCPErrors = siiReadWordHDMIRXP0(RX_HDCP_ERR_ADDR); + if (!wHDCPErrors) + qError = TRUE; + + return qError; +} +/*------------------------------------------------------------------------------ + * Function Name: GotNConsecutiveVSyncHDCPStuckInterrupt + * Function Description: + *---------------------------------------------------------------------------- + */ +static BYTE GotNConsecutiveHDCPStuckInterrupt(void) +{ + BYTE bError = FALSE; + + if (DetectHDCPStuck()) { + SiI_Ctrl.bHDCPStuckConfirmCnt++; + if (SiI_Ctrl.bHDCPStuckConfirmCnt == cbHDCPStuckConfirmThres) + bError = SiI_EC_HDCP_StuckInterrupt; + } else + SiI_Ctrl.bHDCPStuckConfirmCnt = 0; + + return bError; +} +/*------------------------------------------------------------------------------ + * Function Name: HDCPErrorHandler + * Function Description: This function process HDCP errors and requests HDCP + * re-authentication if it reached threshold + *---------------------------------------------------------------------------- + */ +static BYTE HDCPErrorHandler(BYTE bHDCPFailInt, BYTE bVSyncInt) +{ + BYTE bError = FALSE; + + if (SiI_Ctrl.bIgnoreIntr & qcIgnoreHDCPFail) { + if (bVSyncInt) { + if (bHDCPFailInt) { + siiClearBCHCounter(); + bError = GotNConsecutiveHDCPStuckInterrupt(); + if (GotNConsecutiveVSyncHDCPFailure()) { +#ifdef SII_DUMP_UART + printf("\n N HDCP Conseq failures!!"); +#endif + /* Clearing Ri will be notification for + *host to start + */ + ReqReAuthenticationRX(); + EnableCheckHDCPFailureWithVSyncRate( + OFF); + } + } else { + EnableCheckHDCPFailureWithVSyncRate(OFF); + } + } + } else { + if (bHDCPFailInt) { + siiClearBCHCounter(); + bError = GotNConsecutiveHDCPStuckInterrupt(); + EnableCheckHDCPFailureWithVSyncRate(ON); + } + } + return bError; +} + +/*------------------------------------------------------------------------------ + * Function Name: HandleDeepColorError + * Function Description: Just clear the Deep Color error bit for now + *---------------------------------------------------------------------------- + */ +static void HandleDeepColorError(void) +{ + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST6_ADDR, RX_BIT_DC_ERROR); +} + +/*------------------------------------------------------------------------------ + * Function Name: RXInterruptHandler + * Function Description: reading, clearing and dispatching RX interrupts + *---------------------------------------------------------------------------- + */ +static BYTE RXInterruptHandler(void) +{ + BYTE abIntrData[4]; + BYTE bError = FALSE; + + RXEXTDBG("sii9135 %s:\n", __func__); + /* Handling second group interrupts */ + + /* YMA NOTE R 0x7B, 0x7C */ + siiReadBlockHDMIRXP0(RX_HDMI_INT_GR2_ADDR, 2, abIntrData); + + /* YMA should be bug, AAC is not in abIntrData[1] */ + /* This interrupt has been processed on polling base */ + /* abIntrData[1] &= (~( RX_BIT_ACP_PACKET | RX_BIT_AAC_DONE)); */ + + /* This interrupt has been processed on polling base */ + abIntrData[1] &= (~RX_BIT_ACP_PACKET); + siiWriteBlockHDMIRXP0(RX_HDMI_INT_GR2_ADDR, 2, abIntrData); + + if ((abIntrData[0] & RX_BIT_AAC_DONE) && + (!(SiI_Ctrl.bIgnoreIntr & qcIgnoreAAC))) { + siiTurnAudioOffAndSetSM_AudioOff(); + siiWriteByteHDMIRXP0(RX_HDMI_INT_GR2_ADDR, RX_BIT_AAC_DONE); +#ifdef SII_DUMP_UART + printf("\nAAC"); +#endif + } + + if ((abIntrData[0] & RX_BIT_HRES_CHANGE) || + (abIntrData[0] & RX_BIT_VRES_CHANGE)) { + /* it is caused a false interrupt, by pix replication change, + *before unmute we well recheck + */ + /* if video really wasn't changed */ + if (!siiSMCheckReqVideoOn()) + siiMuteVideoAndSetSM_SyncInChange(); + } + + if (abIntrData[1] & BIT_DSD_ON) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_ReqAudio; + siiChangeDSDAudioStreamHandler(); + } + + /* 9135 only */ + if ((SiI_Ctrl.bDevId == RX_SiI9135 || SiI_Ctrl.bDevId == RX_SiI9125) && + (abIntrData[1] & BIT_HBRA_ON_CHANGED)) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_ReqAudio; + siiChangeHBRAudioStreamHandler(); + } + + if (abIntrData[1] & RX_BIT_DC_ERROR) + HandleDeepColorError(); + + /* Handling first group interrupts */ + + /* Copy Interrupt Events into RAM */ + siiReadBlockHDMIRXP0(RX_HDMI_INT_GR1_ADDR, 4, abIntrData); + /* This interrupt has been processed on polling base */ + abIntrData[0] &= (~RX_BIT_CTS_CHANGED); + /* This interrupt has been processed on polling base */ + abIntrData[1] &= (~(RX_BIT_GOT_AUDIO_PKT | RX_BIT_GOT_CTS_PKT)); + + if (SiI_Ctrl.bIgnoreIntr & qcIgnoreHDCPFail) { + if (!(abIntrData[1] & RX_BIT_VSYNC)) { + /*this interrupt shouldn't be cleared because no VSync*/ + abIntrData[3] &= (~RX_BIT_HDCP_FAILED); + } + } + + /* Clear Interrupts */ + siiWriteBlockHDMIRXP0(RX_HDMI_INT_GR1_ADDR, 4, abIntrData); + + if (abIntrData[1] & RX_BIT_SCDT_CHANGE) { + EnableCheckHDCPFailureWithVSyncRate(OFF); + siiMuteVideoAndSetSM_SyncInChange(); + if ((SiI_Ctrl.bDevId == RX_SiI9021) || + (SiI_Ctrl.bDevId == RX_SiI9031)) { + /* SiI9031/21 cannot auto-mute when no SCDT */ + siiTurnAudioOffAndSetSM_AudioOff(); + } + siiSetAFEClockDelay(); +#ifdef SII_BUG_PHOEBE_AUTOSW_BUG + if ((SiI_Ctrl.bDevId == RX_SiI9023) || + (SiI_Ctrl.bDevId == RX_SiI9033)) { + siiTurnAudioOffAndSetSM_AudioOff(); + siiSetAutoSWReset(ON); + } +#endif + } + + if (abIntrData[1] & RX_BIT_HDMI_CHANGED) + ProcessChangeBetween_DVI_HDMI_Modes(); + + if (SiI_Inf.bGlobStatus & SiI_RX_GlobalHDMI_Detected) { + /* YMA use HDCP start is better + *if (abIntrData[0] & RX_BIT_HDCP_DONE) { + */ + if (abIntrData[0] & RX_BIT_HDCP_START) + EnableCheckHDCPFailureWithVSyncRate(OFF); + + if ((abIntrData[3] & RX_BIT_HDCP_FAILED) || + (SiI_Ctrl.bIgnoreIntr & qcIgnoreHDCPFail)) { + bError = HDCPErrorHandler( + abIntrData[3] & RX_BIT_HDCP_FAILED, + abIntrData[1] & RX_BIT_VSYNC); + } + + if ((abIntrData[2] & ST3_INFO_MASK) || + (abIntrData[3] & ST4_INFO_MASK)) { + if ((abIntrData[3] & RX_BIT_MASK_NO_AVI_INTR) && + (SiI_Ctrl.bIgnoreIntr & qcIgnoreNoAVI)) { + abIntrData[2] |= NoAVI_Mask; + } else { + abIntrData[2] &= (~NoAVI_Mask); + } + + AVI_And_NoAVI_WorkAround(&abIntrData[2]); + siiProcessInfoFrameIntrrupts(abIntrData[2]); + } + + if ((abIntrData[2] & RX_BIT_NEW_CP_PACKET) && + ((SiI_Ctrl.bDevId == RX_SiI9133) || + (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125))) { + siiSetDeepColorMode(); + } + } + + return bError; +} + +#ifdef SII_USE_RX_PIN_INTERRUPT +/*------------------------------------------------------------------------------ + * Function Name: siiRX_PinInterruptHandler + * Function Description: Checks interrupt pin, and call RX interrupt handler if + * pin is active (negative) + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiRX_PinInterruptHandler(void) +{ + BYTE bError = FALSE; + + if (!halReadRXInt_Pin()) + bError = RXInterruptHandler(); + return bError; +} +#else +/*------------------------------------------------------------------------------ + * Function Name: CheckRXInt_Bit + * Function Description: checks RX global interrupt bit, used when polling RX + * interrupts + *---------------------------------------------------------------------------- + */ +static BOOL CheckRXInt_Bit(void) +{ + BOOL qResult = FALSE; + BYTE value; + + value = siiReadByteHDMIRXP0(RX_INTR_STATE_ADDR); + RXEXTDBG("sii9135 %s: value = 0x%x\n", __func__, value); + if (value & RX_BIT_GLOBAL_INTR) + qResult = TRUE; + + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiRX_BitInterruptHandler + * Function Description: Checks global interrupt bit, and call RX interrupt + * handler if bit is One + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiRX_BitInterruptHandler(void) +{ + if (CheckRXInt_Bit()) + return RXInterruptHandler(); + + return FALSE; +} + +#endif /* end SII_USE_RX_PIN_INTERRUPT */ + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.h new file mode 100644 index 0000000..52f5bd6 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIISR.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIRXDefs.h" + + +enum HDCPErrorProcessing { + cbHDCPStuckConfirmThres = 4, + cbHDCPFailFrmThres = 4 +}; + +BYTE siiRX_PinInterruptHandler(void); +BYTE siiRX_BitInterruptHandler(void); +void siiCheckTransitionToDVIModeAndResetHDMIInfoIfConfirmed(void); +void siiTraceRXInterrupts(void); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.c new file mode 100644 index 0000000..6d8e9df --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.c @@ -0,0 +1,418 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIInfoPkts + * + * Module Description: Processing Info Frame/Packets Interrupts + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + + +#include "SiIInfoPkts.h" +#include "SiIRXIO.h" +#include "SiITTVideo.h" +#include "SiIRXAPIDefs.h" +#include "SiITrace.h" +#include "SiIGlob.h" +#include "../hdmirx_ext_drv.h" + +/*------------------------------------------------------------------------------ + * Function Name: Check_CheckSum + * Function Description: checks Info Frame Check Sum + *---------------------------------------------------------------------------- + */ +static BOOL Check_CheckSum(BYTE bTotInfoFrameLength, BYTE *pbInfoData) +{ + BOOL qResult = FALSE; + BYTE i, bCheckSum = 0; + + for (i = 0; i < bTotInfoFrameLength; i++) + bCheckSum += pbInfoData[i]; + if (!bCheckSum) + qResult = TRUE; + + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: GetPacketTypeAndAddr + * Function Description: used to get Info Frame/Packet type and address + *---------------------------------------------------------------------------- + */ +static struct InfoFrPktType_s GetPacketTypeAndAddr(BYTE bMaskedIntrrupt) +{ + struct InfoFrPktType_s InfoFrmPkt; + /*YMA revised as by Japan customer + * + *switch (bMaskedIntrrupt) { + * + *case AVI_Mask: InfoFrmPkt.bAddr = RX_AVI_IF_ADDR; + * break; + *case SPD_Mask: InfoFrmPkt.bAddr = RX_SPD_IF_ADDR; + * break; + *case Audio_Mask: InfoFrmPkt.bAddr = RX_AUD_IF_ADDR; + * break; + *case MPEG_Mask: InfoFrmPkt.bAddr = RX_MPEG_IF_ADDR; + * break; + *case Unknown_Mask: InfoFrmPkt.bAddr = RX_UNKNOWN_IF_ADDR; + * break; + *case ACP_Mask: InfoFrmPkt.bAddr = RX_ACP_IP_ADDR; + * break; + *default: InfoFrmPkt.bType = 0; + *} + *InfoFrmPkt.bType = siiReadByteHDMIRXP1( InfoFrmPkt.bAddr ); + *return InfoFrmPkt; + */ + InfoFrmPkt.bType = 0; + InfoFrmPkt.bAddr = 0; + + switch (bMaskedIntrrupt) { + case AVI_Mask: + InfoFrmPkt.bAddr = RX_AVI_IF_ADDR; + break; + case SPD_Mask: + InfoFrmPkt.bAddr = RX_SPD_IF_ADDR; + break; + case Audio_Mask: + InfoFrmPkt.bAddr = RX_AUD_IF_ADDR; + break; + case MPEG_Mask: + InfoFrmPkt.bAddr = RX_MPEG_IF_ADDR; + break; + case Unknown_Mask: + InfoFrmPkt.bAddr = RX_UNKNOWN_IF_ADDR; + break; + case ACP_Mask: + InfoFrmPkt.bAddr = RX_ACP_IP_ADDR; + break; + } + if (InfoFrmPkt.bAddr) + InfoFrmPkt.bType = siiReadByteHDMIRXP1(InfoFrmPkt.bAddr); + return InfoFrmPkt; + +} +/*------------------------------------------------------------------------------ + * Function Name: CheckForInfoFrameLength + * Function Description: check if Info Frame length in normal range + *---------------------------------------------------------------------------- + */ +static BOOL CheckForInfoFrameLength(BYTE bInfoFrameLenth) +{ + BOOL qResult = FALSE; + + if ((bInfoFrameLenth >= IF_MIN_LENGTH) && + (bInfoFrameLenth <= IF_MAX_LENGTH)) + qResult = TRUE; + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiClearNewPacketEvent + * Function Description: After reading Packet through API interface, it's need + * to clear that Event of packet. Otherwise top layer + * would read it again + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiClearNewPacketEvent(BYTE bPaketType) +{ + switch (bPaketType) { + case AVI_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_AVI); + break; + case SPD_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_SPD); + break; + case Audio_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_AUD); + break; + case ISRC1_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_ISRC1); + break; + case ISRC2_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_ISRC2); + break; + case ACP_Type: + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_ACP); + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: GetInfoFramesOrPakets + * Function Description: gets Info Frames or Packets, + * if Info Frame check for its length and check sum + *---------------------------------------------------------------------------- + */ +static BYTE GetInfoFramesOrPakets(struct InfoFrPktType_s InfoFrPkt, + BYTE *pbInfoData) +{ + BYTE bECode = FALSE, bMaxNBytes = 0; + BOOL qInfoFrame = TRUE; + + switch (InfoFrPkt.bType) { + case AVI_Type: + bMaxNBytes = 19; + break; + case MPEG_Type: + case SPD_Type: + bMaxNBytes = 31; + break; + case Audio_Type: + bMaxNBytes = 14; + break; + case ISRC1_Type: + case ISRC2_Type: + case ACP_Type: + qInfoFrame = FALSE; bMaxNBytes = 31; + break; + } + + siiReadBlockHDMIRXP1(InfoFrPkt.bAddr, bMaxNBytes, pbInfoData); + + if (qInfoFrame) { + if (CheckForInfoFrameLength(pbInfoData[IF_LENGTH_INDEX])) { + if (!Check_CheckSum( + pbInfoData[IF_LENGTH_INDEX] + IF_HEADER_LENGTH, + pbInfoData)) + bECode = SiI_EC_InfoFrameWrongCheckSum; + } else + bECode = SiI_EC_InfoFrameWrongLength; + } + + return bECode; + /* TODO think how differentiate from another errors + *( because getting these errors is a source fault) + */ +} +/*------------------------------------------------------------------------------ + * Function Name: GetInfoPacketAddress + * Function Description: returns address in SiI RX where Packet data + * were placed + *---------------------------------------------------------------------------- + */ +BYTE GetInfoPacketAddress(BYTE bType) +{ + BYTE bAddr; + + switch (bType) { + case AVI_Type: + bAddr = RX_AVI_IF_ADDR; + break; + case SPD_Type: + bAddr = RX_SPD_IF_ADDR; + break; + case Audio_Type: + bAddr = RX_AUD_IF_ADDR; + break; + case ISRC1_Type: + bAddr = RX_MPEG_IF_ADDR; + break; + case ISRC2_Type: + bAddr = RX_UNKNOWN_IF_ADDR; + break; + case ACP_Type: + bAddr = RX_ACP_IP_ADDR; + break; + default: + bAddr = 0; + } + return bAddr; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetInfoPacket + * Function Description: get packet from + * + * Accepts: BYTE InfoPacketType + * Returns: BYTE *, InfoPacketData + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetInfoPacket(BYTE bInfoPacketType, BYTE *pbInfoPacket) +{ + BYTE bInfoPacketAddress; + struct InfoFrPktType_s InfoFrmPkt; + + bInfoPacketAddress = GetInfoPacketAddress(bInfoPacketType); + if (bInfoPacketAddress) { + InfoFrmPkt.bType = bInfoPacketType; + InfoFrmPkt.bAddr = bInfoPacketAddress; + GetInfoFramesOrPakets(InfoFrmPkt, pbInfoPacket); + } + +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetVIC + * Function Description: get VIC code from AVI packet + * + * Accepts: void + * Returns: BYTE + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetVIC(void) +{ + return siiReadByteHDMIRXP1(RX_AVI_IF_ADDR + 7); +} +/*------------------------------------------------------------------------------ + * Function Name: SetAVI_Info + * Function Description: fill in AVI information in SiI_Inf global strucute + *---------------------------------------------------------------------------- + */ +static void SetAVI_Info(struct AVIType_s *AVI, BYTE *Data) +{ + BYTE bAVI; + + AVI->bAVI_State = SiI_RX_GotAVI; + + SiI_Inf.bGlobStatus &= (~SiI_RX_GlobalHDMI_NoAVIPacket); + + bAVI = Data[IF_HEADER_LENGTH] & ColorSpaceMask; + if (bAVI == RGB) + AVI->bInputColorSpace = SiI_RX_ICP_RGB; + else if (bAVI == YCbCr422) + AVI->bInputColorSpace = SiI_RX_ICP_YCbCr422; + else if (bAVI == YCbCr444) + AVI->bInputColorSpace = SiI_RX_ICP_YCbCr444; + + bAVI = Data[IF_HEADER_LENGTH + 1] & ColorimetryMask; + if (bAVI == NoInfo) + AVI->bColorimetry = SiI_RX_ColorimetryNoInfo; + else if (bAVI == ITU601) + AVI->bColorimetry = SiI_RX_ITU_601; + else if (bAVI == ITU709) + AVI->bColorimetry = SiI_RX_ITU_709; + + AVI->bPixRepl = Data[IF_HEADER_LENGTH + 4] & PixReplicationMask; + + +} +/*------------------------------------------------------------------------------ + * Function Name: ClearAVI_Info + * Function Description: write default AVI information in SiI_Inf global + * strucute + *---------------------------------------------------------------------------- + */ +void siiClearAVI_Info(struct AVIType_s *AVI) +{ + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_NoAVIPacket; + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_AVI); + AVI->bAVI_State = SiI_RX_NoAVI; + AVI->bInputColorSpace = SiI_RX_ICP_RGB; + AVI->bColorimetry = SiI_RX_ColorimetryNoInfo; + AVI->bPixRepl = 0; + +} +/*------------------------------------------------------------------------------ + * Function Name: ProcessAVIorNoAVI + * Function Description: processing AVI and NoAVI interrupts + *---------------------------------------------------------------------------- + */ +static void ProcessAVIorNoAVI(BYTE bInfoFramesIntrrupts) +{ + BYTE abInfoData[19]; + BYTE bECode; + struct InfoFrPktType_s InfoFrmPkt; + + if (bInfoFramesIntrrupts & AVI_Mask) { + InfoFrmPkt = GetPacketTypeAndAddr( + bInfoFramesIntrrupts & AVI_Mask); + if (InfoFrmPkt.bType) { + bECode = GetInfoFramesOrPakets(InfoFrmPkt, abInfoData); + if (!bECode) { + SetAVI_Info(&SiI_Inf.AVI, abInfoData); + /* Request Program Video path */ + siiMuteVideoAndSetSM_SyncInChange(); + /* Set Sys Information Flag */ + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_AVI; +#ifdef SII_DUMP_UART + printf("\nNew AVI\n"); +#endif + } + } + } + if (bInfoFramesIntrrupts & NoAVI_Mask) { + siiClearAVI_Info(&SiI_Inf.AVI); + siiMuteVideoAndSetSM_SyncInChange(); + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_AVI); + } +} +/*------------------------------------------------------------------------------ + * Function Name: ProcessAudioInfoFrame + * Function Description: processing Audio Info Frame + *---------------------------------------------------------------------------- + */ +static void ProcessAudioInfoFrame(BYTE bInfoFramesIntrrupts) +{ + BYTE bECode; + BYTE abInfoData[14]; + struct InfoFrPktType_s InfoFrmPkt; + + InfoFrmPkt = GetPacketTypeAndAddr(bInfoFramesIntrrupts & AUD_MASK); + if (InfoFrmPkt.bType) { + bECode = GetInfoFramesOrPakets(InfoFrmPkt, abInfoData); + if (!bECode) { + /* Set Sys Information Flag */ + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_AUD; + /* TODO Program input audio status */ + } + } +} +/*------------------------------------------------------------------------------ + * Function Name: Check InfoPacket Buffer + * Function Description: This function checks info packet buffer, + * sets corresponding flag in SiI_Inf.bNewInfoPkts + *---------------------------------------------------------------------------- + */ +static void CheckIPBuffer(BYTE bMaskedIPIntrrupt) +{ + struct InfoFrPktType_s InfoFrmPkt; + + InfoFrmPkt = GetPacketTypeAndAddr(bMaskedIPIntrrupt); + if (InfoFrmPkt.bType == SPD_Type) + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_SPD; + else if (InfoFrmPkt.bType == ISRC1_Type) + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_ISRC1; + else if (InfoFrmPkt.bType == ISRC2_Type) + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_ISRC2; + else + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_UNREQ; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiProcessInfoFrameIntrrupts + * Function Description: processing Info Frame and Info Packet Interrupts + * + * Accepts: none + * Returns: none + * Globals: SiI_Inf.AVI structure can be modified + *---------------------------------------------------------------------------- + */ +void siiProcessInfoFrameIntrrupts(BYTE bInfoFramesIntrrupts) +{ + if ((bInfoFramesIntrrupts & NoAVI_Mask) || + (bInfoFramesIntrrupts & AVI_Mask)) { + /* only AVI in AVI IF Buffere */ + ProcessAVIorNoAVI(bInfoFramesIntrrupts); + } + if (bInfoFramesIntrrupts & Audio_Mask) { + /* only Audio in AVI IF Buffere */ + ProcessAudioInfoFrame(bInfoFramesIntrrupts); + } + if (bInfoFramesIntrrupts & SPD_Mask) + CheckIPBuffer(bInfoFramesIntrrupts & SPD_Mask); + + if (bInfoFramesIntrrupts & MPEG_Mask) + CheckIPBuffer(bInfoFramesIntrrupts & MPEG_Mask); + + if (bInfoFramesIntrrupts & Unknown_Mask) + CheckIPBuffer(bInfoFramesIntrrupts & Unknown_Mask); + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.h new file mode 100644 index 0000000..e444cd16 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIInfoPkts.h @@ -0,0 +1,104 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIGlob.h" + +#define AVI_MASK 0x01 +#define SP_MASK 0x02 +#define AUD_MASK 0x04 +#define MPEG_MASK 0x08 +#define UNKNOWN_MASK 0x10 +#define CP_MASK 0x80 + +/* ---------------------------------- */ +#define RX_AVI_IF_ADDR 0x40 +#define RX_SPD_IF_ADDR 0x60 +#define RX_AUD_IF_ADDR 0x80 +#define RX_MPEG_IF_ADDR 0xA0 +#define RX_UNKNOWN_IF_ADDR 0xC0 +#define RX_ACP_IP_ADDR 0xE0 + +#define BIT_CP_AVI_MUTE_SET 0x01 +#define BIT_CP_AVI_MUTE_CLEAR 0x10 + +#define RX_SPD_DEC_ADDR 0x7F +#define RX_MPEG_DEC_ADDR 0xBF +#define RX_ACP_DEC_ADDR 0xFF +#define RX_ACP_INFO_PKT_ADDR 0xE0 + +#define IF_HEADER_LENGTH 4 +#define IF_LENGTH_INDEX 2 +#define IF_MAX_LENGTH 27 +#define IF_MIN_LENGTH 10 + +/* ----------------------------------- */ +enum SiI_InfoInterruptMask { + + AVI_Mask = 0x01, + SPD_Mask = 0x02, + Audio_Mask = 0x04, + MPEG_Mask = 0x08, + Unknown_Mask = 0x10, + NoAVI_Mask = 0x20, + ACP_Mask = 0x40, + CP_Mask = 0x80 +}; + + +enum SiI_InfoFramePackets { + + AVI_Type = 0x82, + SPD_Type = 0x83, + Audio_Type = 0x84, + MPEG_Type = 0x85, + ISRC1_Type = 0x05, + ISRC2_Type = 0x06, + ACP_Type = 0x04 + +}; + +struct InfoFrPktType_s { + + BYTE bType; + BYTE bAddr; + +}; + +enum AVI_Encoding { + + ColorSpaceMask = 0x60, + ColorimetryMask = 0xC0, + PixReplicationMask = 0x0F + +}; + +enum ColorSpace { + + RGB = 0x00, + YCbCr422 = 0x20, + YCbCr444 = 0x40, + +}; + +enum Colorimetry { + + NoInfo, + ITU601 = 0x40, + ITU709 = 0x80, + +}; + +void siiProcessInfoFrameIntrrupts(BYTE bInfoFramesIntrrupts); +void siiGetInfoPacket(BYTE bInfoPacketType, BYTE *pbInfoPacket); +void siiClearNewPacketEvent(BYTE bPaketType); +BYTE siiGetVIC(void); +void siiClearAVI_Info(struct AVIType_s *AVI); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXAPIDefs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXAPIDefs.h new file mode 100644 index 0000000..d36fb89 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXAPIDefs.h @@ -0,0 +1,563 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef SII_RXAPIDEFS +#define SII_RXAPIDEFS + +#define ON 1 /* Turn ON */ +#define OFF 0 /* Turn OFF */ + + +#define SII_USE_SYS_TIMER_MEASUREMENT 0 +/*#define SiI_RX_DSD_Uses_I2S_SPDIF_Buses */ + +#define WRN_BUF_SIZE 4 +#define ERR_BUF_SIZE 4 + +/* SiI Device Id */ +enum SiIDeviceId { /* real device id, defined by registers' maps */ + + SiI9993 = 0x9942, + SiI9031 = 0x9A53, + SiI9021 = 0x9A52, + SiI9011 = 0x9AA3, + SiI9051 = 0x9051, + SiI9023 = 0x9023, + SiI9033 = 0x9033, + SiI9125 = 0x9125, + SiI9133 = 0x9133, + SiI9135 = 0x9135 + +}; + +enum SiI_RX_DeviceId { /* small size id will be easy for processing */ + + RX_SiI9993, + RX_SiI9031, + RX_SiI9021, + RX_SiI9011, + RX_SiI9051, + RX_SiI9023, + RX_SiI9033, + RX_SiI9133, + RX_SiIIP11, + RX_SiI9135, + RX_SiI9125, + RX_Unknown = 0xFF +}; +/* Input Color Space */ + +enum SiI_RX_InputColorSpace { + SiI_RX_ICP_RGB, + SiI_RX_ICP_YCbCr422, + SiI_RX_ICP_YCbCr444 +}; + +/* Color Depth */ + +enum SiI_RX_ColorDepth { + SiI_RX_CD_24BPP = 0x00, + SiI_RX_CD_30BPP = 0x01, + SiI_RX_CD_36BPP = 0x02 +}; +/* bVideoPathSelect */ +enum SiI_RX_Path { + + SiI_RX_P_RGB, + SiI_RX_P_YCbCr444, + SiI_RX_P_RGB_2PixClk, /* SiI9011 */ + SiI_RX_P_YCbCr444_2PixClk, /* SiI9011 */ + SiI_RX_P_RGB_48B, /* SiI9021/31 */ + SiI_RX_P_YCbCr444_48B, /* SiI9021/31 */ + /* This mode is used with digital output only */ + SiI_RX_P_YCbCr422, + /* YCbCr 422 muxed 8 bit, used with digital output only */ + SiI_RX_P_YCbCr422_MUX8B, + /* YCbCr 422 muxed 10 bit, used with digital output only */ + SiI_RX_P_YCbCr422_MUX10B, + SiI_RX_P_YCbCr422_16B, + SiI_RX_P_YCbCr422_20B, + SiI_RX_P_YCbCr422_16B_2PixClk, /* SiI9011 */ + SiI_RX_P_YCbCr422_20B_2PixClk, /* SiI9011 */ + SiI_RX_P_Mask = 0x3F +}; + +enum SiI_RX_Path_Switch { + + /* For video modes with pixel replication rate Output wont be divided */ + SiI_RX_P_S_PassReplicatedPixels = 0x80, +}; + +/*----------------------------------------------------------------------------*/ +enum SiI_RX_VidRes { + SiI_ResNoInfo = 0xFF, + SiI_ResNotDetected = 0xFE, + SiI_CE_Res = 0x80, + SiI_CE_orNextRes = 0x40 +}; +/*----------------------------------------------------------------------------*/ +/* bSyncSelect */ +enum SiI_RX_SyncSel { + + SiI_RX_SS_SeparateSync, + SiI_RX_SS_CompOnH, /* composite sync on HSync */ + SiI_RX_SS_CompOnV, /* composite sync on VSync */ + SiI_RX_SS_EmbSync, /* used with digital output only */ + SiI_RX_AVC_SOGY /* sync on Green or Y, used with analog output only */ + +}; +/*----------------------------------------------------------------------------*/ +/* bSyncCtrl. */ +enum SiI_RX_SyncCtrl { + + SiI_RX_SC_NoInv = 0x00, + SiI_RX_SC_InvH = 0x10, /* invert HSync polarity */ + SiI_RX_SC_InvV = 0x20 /* invert VSync polarity */ + +}; +/*----------------------------------------------------------------------------*/ +/* bAnalogCtrl. */ +enum SiI_RX_AnalogVideoCtrl { + + SiI_RX_AVC_Digital_Output, + SiI_RX_AVC_NoPedestal, + SiI_RX_AVC_Pedestal /* with pedestal */ +}; +/*----------------------------------------------------------------------------*/ +/* bVideoOutSel */ +enum SiI_RX_OutputSel { + + SiI_RX_OS_Analog = 0x10, + SiI_RX_OS_Digital = 0x20 + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AVI_State { + + SiI_RX_NoAVI, + SiI_RX_GotAVI + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_Colorimetry { + + SiI_RX_ColorimetryNoInfo, + SiI_RX_ITU_601, + SiI_RX_ITU_709 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AVMuteCtrl { + + SiI_RX_AVMuteCtrl_MuteAudio = 0x01, + SiI_RX_AVMuteCtrl_MuteVideo = 0x10 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_GlobalStatus { + SiI_RX_Global_HotPlugDetect = 0x01, + SiI_RX_Global_VMute = 0x02, /* Applicable in both HDMI and DVI modes */ + SiI_RX_GlobalHDMI_Detected = 0x04, + SiI_RX_GlobalHDMI_AMute = 0x08, /* Applicable in HDMI only */ + /* VG On this event upper layer should disable + *multi-channel digital output + */ + SiI_RX_GlobalHDMI_ACP = 0x10, + SiI_RX_GlobalHDMI_NoAVIPacket = 0x20, + SiI_RX_GlobalHDMI_Reserved = 0x40, + SiI_RX_Global_OldHotPlugDetect = 0x80 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_NewInfo { + SiI_RX_NewInfo_AVI = 0x01, + SiI_RX_NewInfo_SPD = 0x02, + SiI_RX_NewInfo_AUD = 0x04, + SiI_RX_NewInfo_Reserved = 0x08, + SiI_RX_NewInfo_ACP = 0x10, + SiI_RX_NewInfo_ISRC1 = 0x20, + SiI_RX_NewInfo_ISRC2 = 0x40, + SiI_RX_NewInfo_UNREQ = 0x80 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_VideoState { + + SiI_RX_VS_PowerDown, + SiI_RX_VS_SyncInChange, + SiI_RX_VS_SyncStable, + SiI_RX_VS_SyncOutOfRange, + SiI_RX_VS_ReqVMDetection, + SiI_RX_VS_VMDetected, + SiI_RX_VS_VMNotDetected, + SiI_RX_VS_ReqVideoOn, + SiI_RX_VS_VideoOn, + SiI_RX_VS_ReqVidInChange, + /* it's need to accomplish some job (like Soft Audio Mute */ + SiI_RX_VS_ReqGlobalPowerDown, + SiI_RX_VS_GlobalPowerDown, + SiI_RX_VS_ReqPowerDown, + SiI_RX_VS_HoldVideoMute + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_Delays { + SiI_RX_DelayAudio_WaitDACWakingUp = 20 + +}; + + +/*----------------------------------------------------------------------------*/ +enum SiI_AudioChannelStatus4 { + + /* 4 least significant bits */ + + _22Fs = 0x04, + _44Fs = 0x00, + _88Fs = 0x08, + _176Fs = 0x0C, + _24Fs = 0x06, + _48Fs = 0x02, + _96Fs = 0x0A, + _192Fs = 0x0E, + _32Fs = 0x03, + _768Fs = 0x09, /* YMA 8/17/06 added for HBR */ + FsNotIndicated = 0x01, + + /* 4 most significant bits */ + + AccuracyLevel2 = 0x00, + AccuracyLevel1 = 0x20, + AccuracyLevel3 = 0x10, + + SiI_Mask_AudioChannelStatus4 = 0x3F +}; +/*----------------------------------------------------------------------------*/ +enum SiI_AudioChannelStatus5 { + /* 4 least significant bits */ + + AudioLengthNotIndicated = 0x00, + + AudioLength_max20_16bit = 0x02, + AudioLength_max20_18bit = 0x04, + AudioLength_max20_19bit = 0x08, + AudioLength_max20_20bit = 0x0A, + AudioLength_max20_17bit = 0x0C, + + AudioLength_max24_20bit = 0x03, + AudioLength_max24_22bit = 0x05, + AudioLength_max24_23bit = 0x09, + AudioLength_max24_24bit = 0x0B, + AudioLength_max24_21bit = 0x0D, + + AudioLength_max24bit = 0x01 + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_MClk { + MClock_128Fs = 0x00, /* Fm = 128* Fs */ + MClock_256Fs = 0x01, /* Fm = 256 * Fs (default) */ + MClock_384Fs = 0x02, /* Fm = 384 * Fs */ + MClock_512Fs = 0x03, /* Fm = 512 * Fs */ + + SelectMClock = 0x03 +}; + + +/*----------------------------------------------------------------------------*/ +enum SiI_ChipType { + /*YMA removed since actually no bit for it, changed to #define + * SiI_RX_DSD_Uses_I2S_SPDIF_Buses = 0x20, + */ + SiI_RX_InvertOutputVidClock = 0x40, + SiI_RX_FPGA = 0x80 + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AudioState { + + SiI_RX_AS_AudioOff, + SiI_RX_AS_ReqAudio, + SiI_RX_AS_StartCheckCTS_Stable, + SiI_RX_AS_WaitAudioPPLLock, + SiI_RX_AS_WaitAudioDACReady, + SiI_RX_AS_AudioOnWaitLockStatus, + SiI_RX_AS_AudioOn, + SiI_RX_AS_ReqAudioOff, + SiI_RX_AS_HoldAudioMute, + SiI_RX_AS_WaitVideoOn, + SiI_RX_AS_ReqHoldAudioMute /* YMA fix by added audio mute API */ + +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_I2SBusFormat { + + SiI_RX_AOut_I2S_1BitShift = 0x0000, /* 1st. bit shift (Philips spec.) */ + SiI_RX_AOut_I2S_1BitNoShift = 0x0001, /* no shift */ + SiI_RX_AOut_I2S_MSB1St = 0x0000, /* MSb 1st */ + SiI_RX_AOut_I2S_LSB1St = 0x0002, /* LSb 1st */ + SiI_RX_AOut_I2S_LJ = 0x0000, /* Left justified */ + SiI_RX_AOut_I2S_RJ = 0x0004, /* Right justified */ + SiI_RX_AOut_I2S_LeftPolWSL = 0x0000, /* Left polarity when WS low */ + SiI_RX_AOut_I2S_LeftPolWSH = 0x0008, /* Left polarity when WS high */ + SiI_RX_AOut_I2S_MSBSgEx = 0x0000, /* MSb signed extended */ + SiI_RX_AOut_I2S_MSBNoSgEx = 0x00010, /* MSb not signed extended */ + SiI_RX_AOut_I2S_WS32Bit = 0x0000, /* WordSize 32 bits */ + SiI_RX_AOut_I2S_WS16Bit = 0x0020, /* WordSize 16 bits */ + SiI_RX_AOut_I2S_SEPos = 0x0000, /* Sample edge positive */ + SiI_RX_AOut_I2S_SENeg = 0x0040, /* Sample edge negative */ + SiI_RX_AOut_I2S_PassAllData = 0x0000, /* Pass all data */ + SiI_RX_AOut_I2S_ValData = 0x0080, /* Pass valid data only */ + SiI_RX_AOut_I2S_PassAnyFrm = 0x0000, /* Pass any format from SPDIF */ + SiI_RX_AOut_I2S_PassPCMOnly = 0x0100, /* Pass PCM format only */ + SiI_RX_AOut_I2S_24BVI2S = 0x0000, /* 24 bits send via I2S */ + SiI_RX_AOut_I2S_28BVI2S = 0x0200, /* 28 bits send via I2S */ + + SiI_RX_AOut_I2S_I2SDefault = 0x0140 +}; + +enum SiI_RX_DSDBusFormat { + SiI_RX_AOut_DSD_WS32Bit = 0x00, /* WordSize 32 bits */ + SiI_RX_AOut_DSD_WS16Bit = 0x01, /* WordSize 16 bits */ + SiI_RX_AOut_DSD_SEPos = 0x00, /* Sample edge positive */ + SiI_RX_AOut_DSD_SENeg = 0x02, /* Sample edge negative */ +}; + +enum SiI_RX_HBRABusFormat { + SiI_RX_AOut_HBRA_WS32Bit = 0x00, /* WordSize 32 bits */ + SiI_RX_AOut_HBRA_WS16Bit = 0x10, /* WordSize 16 bits */ + SiI_RX_AOut_HBRA_SEPos = 0x00, /* Sample edge positive */ + SiI_RX_AOut_HBRA_SENeg = 0x20, /* Sample edge negative */ +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AudioFIFOMap { + + SiI_RX_AOut_Map_F0_D0 = 0x00, + SiI_RX_AOut_Map_F1_D0 = 0x01, + SiI_RX_AOut_Map_F2_D0 = 0x02, + SiI_RX_AOut_Map_F3_D0 = 0x03, + + SiI_RX_AOut_Map_F0_D1 = 0x00, + SiI_RX_AOut_Map_F1_D1 = 0x04, + SiI_RX_AOut_Map_F2_D1 = 0x08, + SiI_RX_AOut_Map_F3_D1 = 0x0C, + + SiI_RX_AOut_Map_F0_D2 = 0x00, + SiI_RX_AOut_Map_F1_D2 = 0x10, + SiI_RX_AOut_Map_F2_D2 = 0x20, + SiI_RX_AOut_Map_F3_D2 = 0x30, + + SiI_RX_AOut_Map_F0_D3 = 0x00, + SiI_RX_AOut_Map_F1_D3 = 0x40, + SiI_RX_AOut_Map_F2_D3 = 0x80, + SiI_RX_AOut_Map_F3_D3 = 0xC0, + + SiI_RX_AOut_FIFOMap_Default = 0xE4 +}; + +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AudioOutputSelect { + + SiI_RX_AOut_SmoothHWMute = 0x01, + SiI_RX_AOut_SPDIF = 0x02, + SiI_RX_AOut_I2S = 0x04, + SiI_RX_AOut_Res = 0x08, + + SiI_RX_AOut_SD0_En = 0x100, /* VG Added */ + SiI_RX_AOut_SD1_En = 0x200, + SiI_RX_AOut_SD2_En = 0x400, + SiI_RX_AOut_SD3_En = 0x800, + + SiI_RX_AOut_Default = (SiI_RX_AOut_SmoothHWMute | SiI_RX_AOut_SPDIF | + SiI_RX_AOut_I2S | SiI_RX_AOut_SD0_En | SiI_RX_AOut_SD1_En | + SiI_RX_AOut_SD2_En | SiI_RX_AOut_SD3_En) +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AudioRepresentation { + + SiI_RX_AudioRepr_PCM, + SiI_RX_AudioRepr_Compressed, + SiI_RX_AudioRepr_DSD, + SiI_RX_AudioRepr_HBR + + /* to be extended in future */ +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_NumberAudioChannels { + + SiI_RX_NumAudCh_Unknown, + SiI_RX_NumAudCh_2, + SiI_RX_NumAudCh_3, + SiI_RX_NumAudCh_4, + SiI_RX_NumAudCh_5, + SiI_RX_NumAudCh_6, + SiI_RX_NumAudCh_7, + SiI_RX_NumAudCh_8, + SiI_RX_NumAudCh_UnknownMulti +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_TMDSState { + + SiI_RX_TMDS_NoInfo, + SiI_RX_TMDS_DVI, + SiI_RX_TMDS_HDMI +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_HDCPStatus { + SiI_RX_HDCP_NotDecrypted, + SiI_RX_HDCP_Decrypted +}; + +/*----------------------------------------------------------------------------*/ +enum SiI_RX_TasksProperty { + + SiI_RX_Tasks_DebugOnly, + SiI_RX_Tasks_All +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_PowerState { + SiI_RX_Power_Off, + SiI_RX_Power_On +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_VideoInputChannels { + SiI_RX_VInCh1 = 0x10, + SiI_RX_VInCh2 = 0x20, +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_AVI { + SiI_RX_AVI_Defaults = 0, + SiI_RX_AVI_IF = 0x80, + SiI_RX_AVI_ColSpMask = 0x60, + SiI_RX_AVI_ColSp_RGB = 0x00, + SiI_RX_AVI_ColSp_YCbCr444 = 0x20, + SiI_RX_AVI_ColSp_YCbCr422 = 0x40, + SiI_RX_AVI_ColorimetryMask = 0x18, + SiI_RX_AVI_Colorimetry_NoInfo = 0x00, + SiI_RX_AVI_Colorimetry_BT601 = 0x08, + SiI_RX_AVI_Colorimetry_BT709 = 0x10, + SiI_RX_AVI_PixReplMask = 0x06, + SiI_RX_AVI_PixRepl_NoRepl = 0x00, + SiI_RX_AVI_PixRepl_x2 = 0x02, + SiI_RX_AVI_PixRepl_x3 = 0x04, + SiI_RX_AVI_PixRepl_x4 = 0x06 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_HDMIStatus { + SiI_RX_HDMI_HP = 0x01, + SiI_RX_HDMI_Enabled = 0x02, + SiI_RX_HDMI_AMute = 0x04, + SiI_RX_HDMI_VMute = 0x08, + SiI_RX_HDMI_ACP = 0x10 +}; +/*------------------------------------------------------------------------------ + * Error or Warning Messages + *---------------------------------------------------------------------------- + */ +enum SiI_ErrWrnCode { + + SiI_EWC_OK, /* no errors and warning */ + SiI_WC_ChipNoCap, /* W001: no support because of chip is not capable */ + SiI_WC_FrmNoCap, /* W002: firmware has no such capability */ + SiI_WC_PCBNoCap, /* W003: PCB has no such capability */ + /* W004: Incorrect combination of input parameters */ + SiI_WC_IncorrectCombPrm, + SiI_WC_Colorimetry, /* W005: Incorrect parameter of Colorimetry */ + SiI_WC_InfoFramePacketUnknownId, + SiI_WC_CTS_Irregular, + + /* IIC Errors */ + SiI_EC_FirstIICErr = 0x81, + + SiI_EC_NoAckIIC = SiI_EC_FirstIICErr, /* E001: no Ack from SiI Device */ + SiI_EC_LowLevelIIC = 0x82, /* E002: low level SDA or/SCL of IIC bus */ + SiI_EC_OtherIIC = 0x83, /* E003: other errors of IIC bus */ + + SiI_EC_NoAckMasterIIC = 0x84, /* E004: No Ack from Master DDC */ + SiI_EC_OtherMasterIIC = 0x85, /* E005: other errors of Master IIC bus */ + SiI_EC_LastIICErr = SiI_EC_OtherMasterIIC, + + /* CPU Errors */ + + SiI_EC_NoEnoughMem = 0x86, /* E006: not enough memory */ + + /* Program Execution error */ + SiI_EC_DivZeroAttemp = 0x87, /* E007: Div. by Zero */ + + /* Video Errors */ + /* E008: Wrong parameter of Input Color Space */ + SiI_EC_InColorSpace = 0x88, + + /* Info Frame/Packet */ + + SiI_EC_InfoFrameWrongLength = 0x96, + SiI_EC_InfoFrameWrongCheckSum = 0x97, + + /* Audio Errors */ + + SiI_EC_MasterClockInDiv = 0x98, + SiI_EC_MasterClockOutDiv = 0x99, + + /* Sys timer allert */ + SiI_EC_LateCallAPIEngine = 0x9A, + + SiI_EC_Mask = 0x80 + +}; + +enum SiI_AudioErrCode { + SiI_EC_NoAudioErrors, + SiI_EC_NoAudioPackets = 0x89, /* E009 No Audio packets */ + SiI_EC_CTS_OutOfRange = 0x8A, /* E010 CTS out of range */ + /* E011 CTS Dropped (packets coming too fast) */ + SiI_EC_CTS_Dropped = 0x8B, + /* E012 CTS Reused (packets coming too slow) */ + SiI_EC_CTS_Reuseed = 0x8C, + SiI_EC_NoCTS_Packets = 0x8D, /* E013 No CTS Packets */ + SiI_EC_CTS_Changed = 0x8E, /* E014 CTS Changed */ + SiI_EC_ECCErrors = 0x8D, /* E015 ECC Errors */ + SiI_EC_AudioLinkErrors = 0x8F, /* E016 Audio Link Errors */ + SiI_EC_PLL_Unlock = 0x90, /* E017 PLL Unlock */ + SiI_EC_FIFO_UnderRun = 0x92, /* E018 FIFO Under Run */ + SiI_EC_FIFO_OverRun = 0x93, /* E019 FIFO Over Run */ + SiI_EC_FIFO_ResetFailure = 0x94, + SiI_EC_FIFO_UnderRunStuck = 0x96, + SiI_EC_HDCP_StuckInterrupt = 0x97, + + SiI_EC_UnsupportedColorDepth = 0x99, + SiI_EC_ColorDepthError = 0x9A +}; + +/* RX API ChangeEvents after exe SiI_RX_DoTasks() */ + +enum SiI_RX_API_ChangeEvents { + SiI_RX_API_VideoSM_Changed = 0x01, + SiI_RX_API_AudioSM_Changed = 0x02, + SiI_RX_API_InfoPacket_Changed = 0x04, + SiI_RX_API_HDCPStatus_Changed = 0x08, + SiI_RX_API_GlobalStatus_Changed = 0x10 +}; +/*----------------------------------------------------------------------------*/ +enum SiI_RX_VidOutputsPowerDown { + + SiI_RX_VidOutPD_NoPD, + SiI_RX_VidOutPD_Analog, + SiI_RX_VidOutPD_AnalogAndDigital, + SiI_RX_VidOutPD_Digital + +}; + + +enum IgnoreIntr { + + qcIgnoreNoAVI = 0x01, + qcIgnoreAAC = 0x02, + qcIgnoreHDCPFail = 0x04 + +}; + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXDefs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXDefs.h new file mode 100644 index 0000000..635d492 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXDefs.h @@ -0,0 +1,513 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef SII_HDMIRX +#define SII_HDMIRX + +#define RX_SLV0 0x60 +#define RX_SLV1 0x68 +#define RX_AFE0 0x64 +#define RX_AFE1 0x6C + +/*----------------------------------------------------- + * Sys. registers + *--------------------------------------------------- + */ +#define RX_VND_IDL_ADDR 0x00 +#define RX_VND_IDH_ADDR 0x01 +#define RX_DEV_IDL_ADDR 0x02 +#define RX_DEV_IDH_ADDR 0x03 +#define RX_DEV_REV_ADDR 0x04 +#define RX_SWRST_ADDR 0x05 + +#define RX_BIT_SW_AUTO 0x10 + +#define RX_SWRST_ADDR2 0x07 /* YMA 9125/35 only */ +#define RX_BIT_AUDIOFIFO_AUTO 0x40 /* YMA 9135 only, auto audio FIFO rst */ +#define RX_BIT_DCFIFO_RST 0x80 /* YMA 9135 only, Deep color FIFO rst */ + + +#define RX_STATE_ADDR 0x06 + +#define RX_BIT_CABLE_HPD 0x08 +#define RX_BIT_SCDT 0x01 +#define RX_BIT_CLK 0x02 + +#define RX_SYS_CTRL1_ADDR 0x08 + +#define RX_BIT_INVERT_OUTPUT_VID_CLK 0x02 +#define RX_BIT_VID_BUS_24BIT 0x04 + +#define RX_SYS_SW_SWTCHC_ADDR 0x09 + +#define RX_BIT_RX0_EN 0x01 +#define RX_BIT_RX1_EN 0x02 +#define RX_BIT_DDC0_EN 0x10 +#define RX_BIT_DDC1_EN 0x20 + +#define RX_BIT_AUDIO_FIFO_RESET 0x02 +#define RX_BIT_ACR_RESET 0x04 + +#define RX_BIT_PD_ALL 0x01 +#define RX_BIT_2PIX_MODE 0x10/* 0x08 */ + +#define RX_MSK_CLR_IN_OUT_DIV 0x0F + +#define RX_OUTPUT_DIV_BY_1 0x00 +#define RX_OUTPUT_DIV_BY_2 0x40 +#define RX_OUTPUT_DIV_BY_4 0xC0 + +/* PD Output */ + +#define RX_PD_SYS_ADDR 0x3F +#define RX_BIT_NPD_VIDEO_DAC 0x10 + +#define RX_PD_SYS2_ADDR 0x3E + +#define RX_FIFO_DIFF_ADDR 0x39 +#define RX_BIT_NPD_DIGITAL_OUTPUTS 0x04 + +/* STATE MASK */ + +#define RX_STATE_SCDT_MASK 0x01 + +/*----------------------------------------------------- + * Analog Front End + *---------------------------------------------------- + */ +#define RX_AFE_DDR_CONF_ADDR 0x0A +#define RX_AFE_DDR_DSA_ADDR 0x0B + +/*----------------------------------------------------- + * HDCP registers + *--------------------------------------------------- + */ +#define RX_RI_PRIME_ADDR 0x1F +#define RX_HDCP_CTRL_ADDR 0x31 + +#define RX_BIT_TRASH_RI 0x80 + +#define RX_HDCP_STAT_ADDR 0x32 + +#define RX_BIT_HDCP_DECRYPTING 0x20 + +#define RX_AKSV_ADDR 0x21 +#define RX_BKSV_ADDR 0x1A +#define RX_CAP_MASK 0x08 + + +/*----------------------------------------------------- + * Interrupt registers + *--------------------------------------------------- + */ +#define RX_INT_ADDR 0x71 +#define RX_INT_ST2_ADDR 0x72 +#define RX_INT_ST4_ADDR 0x74 +#define RX_INT_MASK_ADDR 0x75 + +#define RX_INT_CNTRL_ADDR 0x79 +#define RX_INT_MASK_ST5_ADDR 0x7D +/* reg 0x71 bit defenition */ + +#define RX_BIT_CTS_CHANGED 0x80 +#define RX_BIT_N_CHANGED 0x40 +#define RX_BIT_ECC_ERR 0x04 +#define RX_BIT_HDCP_DONE 0x01 +#define RX_BIT_HDCP_START 0x02 + +#define RX_BIT_FIFO_UNDERRUN 0x01 +#define RX_BIT_FIFO_OVERRUN 0x02 +#define RX_BIT_CTS_DROPPED 0x08 +#define RX_BIT_CTS_REUSED 0x04 + +/* reg 0x72 bit defenition */ +#define RX_BIT_HDMI_CHANGED 0x80 +#define RX_BIT_SCDT_CHANGED 0x08 + +/*----------------------------------------------------- + * ECC error threshold, aux. reg. for ECC int. audio path + *--------------------------------------------------- + */ +#define RX_ECC_CTRL_ADDR 0xBB +#define RX_BIT_CLR_BCH_COUNTER 0x01 + +#define RX_ECC_BCH_THRESHOLD 0xBC + +#define RX_ECC_THRES_ADDR 0x7C +#define RX_ECC_THRES_PCMREPR 0x01 +#define RX_ECC_THRES_CSTREAMREPR 0x03 +#define RX_HDCP_ERR_ADDR 0xCD +/*----------------------------------------------------- + * TMDS PLL registers + *--------------------------------------------------- + */ + + +/* Audio PLL registers */ +/*---------------------------------------------------*/ +#define RX_APLL_CTRL1_ADDR 0x88 +#define RX_PLL_IOPPC_ADDR 0x8C +#define RX_PLL_CGC_ADDR 0x8D +/*----------------------------------------------------- + * Mail Box registers + *--------------------------------------------------- + */ + +/*----------------------------------------------------- + * ACR registers + *--------------------------------------------------- + */ +#define RX_ACR_CTRL1_ADDR 0x00 +#define RX_FREQ_SVAL_ADDR 0x02 + +#define RX_HW_N_ADDR 0x06 +#define RX_HW_CTS_ADDR 0x0C + +#define RX_BIT_ACR_INIT 0x01 +#define RX_BIT_ACR_FSSEL 0x02 + +/*----------------------------------------------------- + * Audio out registers + *--------------------------------------------------- + */ +#define RX_I2S_CTRL1_ADDR 0x26 +#define RX_I2S_CTRL2_ADDR 0x27 +#define RX_I2S_MAP_ADDR 0x28 +#define RX_AUDIO_CTRL_ADDR 0x29 + +#define RX_I2S_MAP_DEFAULT 0xE4 +#define RX_SMOOTH_MUTE_EN 0x20 + +#define RX_BIT_SPDIF_EN 0x01 +#define RX_BIT_I2S_MODE 0x04 +#define RX_BIT_PASS_SPDIF_ERR 0x10 + +#define RX_BIT_Aout_WordSize 0x20 /* YMA 2 added for API Rev2 */ +#define RX_BIT_Aout_ClockEdge 0x40 +#define RX_BIT_SD0_EN 0x10 +#define RX_BIT_SD1_EN 0x20 +#define RX_BIT_SD2_EN 0x40 +#define RX_BIT_SD3_EN 0x80 + +#define RX_BITS_SD0_SD3_EN 0xF0 + +#define RX_I2S_DISABLE 0x0F +/*----------------------------------------------------- + * Audio path registers + *--------------------------------------------------- + */ +#define RX_CH_STATUS1_ADDR 0x2A + +#define RX_BIT_AUDIO_SAMPLE_NPCM 0x02 + +#define RX_CH_STATUS4_ADDR 0x30 +#define RX_CH_STATUS5_ADDR 0x31 + +#define RX_AUDP_STAT_ADDR 0x34 + +/* reg address P1, 3D */ +#define RX_BIT_LAYOUT_1 0x08 +#define RX_BIT_DSD_STATUS 0x20 +#define RX_BIT_HBRA_STATUS 0x40 /* 9135 and after only */ +#define RX_BIT_HDMI_EN_MASK 0x02 + +#define RX_HDMI_CRIT1_ADDR 0x35 +#define RX_AUDP_MUTE_ADDR 0x37 +#define RX_MUTE_DIV_ADDR 0x2D +#define RX_HDMI_CRIT2_ADDR 0x38 +#define RX_HDMI_EN_MASK 0x02 + +#define BIT_DSD_STATUS 0x20 + +#define RX_SPDIF_CH_STATUS 0x2A + +#define RX_AUDIO_SAMPLE_REPRTYPE 0x02 +#define RX_AUDIO_SWAP_ADDR 0x2E +#define BIT_DSD_USES_I2S_SPDIF_BUSES 0x02 + +#define RX_BIT_MCLK_EN 0x08 +#define RX_BIT_VIDEO_MUTE 0x01 +#define RX_BIT_AUDIO_MUTE 0x02 +/*---------------------------------------------------*/ +#define RX_AEC_CTRL_ADDR 0xB5 + +#define RX_BIT_AEC_EN 0x01 + +#define RX_AEC1_ADDR 0xB6 +#define RX_AEC2_ADDR 0xB7 +#define RX_AEC3_ADDR 0xB8 + + + + +/*----------------------------------------------------- + * Video registers + *--------------------------------------------------- + */ +#define RX_HRES_L_ADDR 0x3A +#define RX_HRES_H_ADDR 0x3B +#define RX_VRES_L_ADDR 0x3C +#define RX_VRES_H_ADDR 0x3D + +#define RX_VID_FORMAT_BASE_ADDR 0x48 +#define RX_VID_CTRL_ADDR 0x48 +#define RX_VID_MODE_ADDR 0x4A +#define RX_VID_MODE2_ADDR 0x49 + +/* Defines the video blanking value for channel 0 */ +#define RX_BLANKDATA_CH0_ADDR 0x4B +/* Defines the video blanking value for channel 1 */ +#define RX_BLANKDATA_CH1_ADDR 0x4C +/* Defines the video blanking value for channel 2 */ +#define RX_BLANKDATA_CH2_ADDR 0x4D + +#define RX_RES_ACTIVE_ADDR 0x4E +#define RX_DE_PIX1_ADDR 0x4E /* Number pixels per DE (read only) */ +#define RX_DE_PIX2_ADDR 0x4F +#define RX_DE_LINE1_ADDR 0x50 /* Number active lines (read only) */ +#define RX_DE_LINE2_ADDR 0x51 +#define RX_VID_STAT_ADDR 0x55 +#define RX_VID_XCNT_ADDR 0x6F +/*--------------------------------------------------------------------*/ +/* CSync Interlace regs */ +#define RX_FIELD2BACKPORCH_ADDR 0x54 + +#define RX_CAPHALFLINE_ADDR 0x57 +#define RX_PREEQPULSCNT_ADDR 0x5A +#define RX_SERRATEDCNT_ADDR 0x5D +#define RX_POSTEQPULSECNT_ADDR 0x5E + +/*---------------------------------------------------------------------*/ +/* VIDEO MODE BITS [0x4A] */ + +#define RX_BIT_EN_INS_CSYNC 0x01 +#define RX_BIT_444to422 0x02 +#define RX_BIT_422to444 0x04 +#define RX_BIT_CSC 0x08 +#define RX_BIT_RGBToYCbCr 0x08 +#define RX_BIT_16_235_RANGE 0x10 +#define RX_BIT_DITHER 0x20 +#define RX_BIT_MUX_YC 0x40 +#define RX_BIT_INS_SAVEAV 0x80 + + +/*---------------------------------------------------------------------*/ +/* VIDEO MODE2 BITS [0x49] */ +#define RX_BIT_RGBA_OUT 0x01 +#define RX_BIT_EN_PEDESTAL 0x02 +#define RX_BIT_YCbCrToRGB 0x04 +#define RX_BIT_YCbCrRangeToRGB 0x08 +#define RX_BIT_LATCH_POLARITY 0x10 + +/*---------------------------------------------------------------------*/ +/* VIDEO CONTROL BITS [0x48] */ +#define RX_BIT_BT709 0x01 +#define RX_BIT_BT709_RGBCONV 0x01 +#define RX_BIT_EXT_BIT_MODE 0x02 +#define RX_BIT_BT709_YCbCrCONV 0x04 +#define RX_BIT_INSERT_CSYNC_ON_AOUT 0x08 +#define RX_BIT_INSERT_SOGorCSYNC_ON_AOUT 0x08 +#define RX_BIT_ENCSYNC_ON_HSYNC 0x10 +#define RX_BIT_ENCSYNC_ON_VSYNC 0x20 +#define RX_BIT_INVERT_HSYNC 0x40 +#define RX_BIT_INVERT_VSYNC 0x80 + +#define RX_MASK_CLR_SYNC_CTRL 0xF8 + +/*----------------------------------------------------- + * Test registers + *--------------------------------------------------- + */ +#define RX_DBGCORE_ADDR 0x3A +#define RX_PD_SYS2_ADDR 0x3E + +#define RX_BIT_PD_QE 0x08 +/*----------------------------------------------------- + * CEA-861 + *--------------------------------------------------- + */ + +/*----------------------------------------------------- + * Software resets + *--------------------------------------------------- + */ +#define RX_SW_RST 0x01 +#define RX_FIFO_RST 0x02 +#define RX_ACR_RST 0x04 +#define RX_HDCP_RST 0x10 +/*----------------------------------------------------- + * Deep Color Registers + *--------------------------------------------------- + */ + +/* #define RX_VID_MODE2_ADDR 0x49 */ +#define RX_DITHER_MODE_MASK 0xC0 + #define RX_DITHER_8BITS 0x00 + #define RX_DITHER_10BITS 0x40 + #define RX_DITHER_12BITS 0x80 + + +#define RX_DC_STATUS_ADDR 0x61 + #define RX_DC_PIXELDEPTH_MASK 0x03 + #define RX_DC_8BPP_VAL 0x00 + #define RX_DC_10BPP_VAL 0x01 + #define RX_DC_12BPP_VAL 0x02 + +/* #define RX_TMDS_ECTRL_ADDR 0x81 */ + #define RX_DC_CLK_CTRL_MASK 0x0F + #define RX_DC_CLK_8BPP_1X 0x00 + #define RX_DC_CLK_8BPP_2X 0x02 + #define RX_DC_CLK_10BPP_1X 0x04 + #define RX_DC_CLK_12BPP_1X 0x05 + #define RX_DC_CLK_10BPP_2X 0x06 + #define RX_DC_CLK_12BPP_2X 0x07 + +/*----------------------------------------------------- + * Interrupt registers + *--------------------------------------------------- + */ +#define RX_INTR_STATE_ADDR 0x70 +#define RX_BIT_GLOBAL_INTR 0x01 + +#define RX_HDMI_INT_ADDR 0x71 +#define RX_HDMI_INT_GR1_ADDR 0x71 +#define RX_HDMI_INT_GR2_ADDR 0x7B +#define RX_HDMI_INT_ST1_ADDR 0x71 +#define RX_HDMI_INT_ST2_ADDR 0x72 +#define RX_HDMI_INT_ST3_ADDR 0x73 +#define RX_HDMI_INT_ST4_ADDR 0x74 + +#define RX_INFO_FRAME_CTRL_ADDR 0x7A + +#define RX_HDMI_INT_ST5_ADDR 0x7B +#define RX_HDMI_INT_ST6_ADDR 0x7C + +#define RX_HDMI_INT_MASK_ADDR 0x75 +#define RX_HDMI_INT_GR1_MASK_ADDR 0x75 +#define RX_HDMI_INT_ST1_MASK_ADDR 0x75 +#define RX_HDMI_INT_ST2_MASK_ADDR 0x76 +#define RX_HDMI_INT_ST3_MASK_ADDR 0x77 +#define RX_HDMI_INT_ST4_MASK_ADDR 0x78 + +#define RX_BIT_MASK_NO_AVI_INTR 0x10 + +#define RX_HDMI_INT_MASK_ADDR 0x75 +#define RX_HDMI_INT_GR2_MASK_ADDR 0x7D + +#define RX_INT_CNTRL_ADDR 0x79 + +/* reg 0x71 bit defenitions */ + +#define RX_BIT_HDCP_START 0x02 +#define RX_BIT_HDCP_DONE 0x01 +#define RX_BIT_ECC_ERR 0x04 +#define RX_BIT_ACR_PLL_UNLOCK 0x10 +#define RX_BIT_N_CHANGED 0x40 +#define RX_BIT_CTS_CHANGED 0x80 + +/* reg 0x72 bit defenitions */ + +#define RX_BIT_GOT_AUDIO_PKT 0x02 +#define RX_BIT_SCDT_CHANGE 0x08 + +#define RX_BIT_GOT_CTS_PKT 0x04 +#define RX_BIT_VSYNC 0x40 +#define RX_BIT_HDMI_CHANGED 0x80 + +/* reg 0x73 bit defenitions */ + +#define RX_BIT_NEW_CP_PACKET 0x80 + +/* reg 0x74 bit defenitions */ + +#define RX_BIT_FIFO_UNDERRUN 0x01 +#define RX_BIT_FIFO_OVERRUN 0x02 +#define RX_BIT_CTS_DROPPED 0x08 +#define RX_BIT_CTS_REUSED 0x04 +#define RX_BIT_HDCP_FAILED 0x40 + +/* reg 0x7A bit defenitions */ + +#define RX_BIT_NEW_AVI 0x01 +#define RX_BIT_NEW_SPD 0x02 +#define RX_BIT_NEW_AUD 0x04 +#define RX_BIT_NEW_MPEG 0x08 +#define RX_BIT_NEW_UNREQ 0x10 +#define RX_BIT_NEW_ACP 0x20 + +/* reg 0x7B */ +#define RX_BIT_INTERLACE_CHANGE 0x02 +#define RX_BIT_AAC_DONE 0x40 +#define RX_BIT_AUDIO_LINK_ERR 0x20 +#define RX_BIT_HRES_CHANGE 0x08 +#define RX_BIT_VRES_CHANGE 0x10 + +/* reg 0x7C */ +#define RX_BIT_DC_ERROR 0x80 +#define RX_BIT_ACP_PACKET 0x04 +#define BIT_AUD_CH_STATUS_READY 0x20 +#define BIT_DSD_ON 0x02 +#define BIT_HBRA_ON_CHANGED 0x10 + +#define ST3_INFO_MASK 0x1F +#define ST4_INFO_MASK 0x10 +/*----------------------------------------------------- + * TMDS PLL registers + *--------------------------------------------------- + */ +#define RX_TMDS_ECTRL_ADDR 0x81 +#define RX_TMDS_TERMCTRL_ADDR 0x82 +/*----------------------------------------------------- + * Audio PLL registers + *--------------------------------------------------- + */ +#define RX_APLL_POLE_ADDR 0x88 +#define RX_APLL_CLIP_ADDR 0x89 +#define RX_PLL_IOPPC_ADDR 0x8C +#define RX_PLL_CGC_ADDR 0x8D + +#define RX_LK_WIN_SVAL_ADDR 0x13 +#define RX_LK_THRESHOLD_ADDR 0x14 + +/*----------------------------------------------------- + * Mail Box registers + *--------------------------------------------------- + */ + +/*----------------------------------------------------- + * ACR registers + *--------------------------------------------------- + */ +#define RX_CTS_THRESHOLD 0x50 /* 6-3 Bits */ + +#define RX_ACR_CTRL1_ADDR 0x00 +#define RX_FREQ_SVAL_ADDR 0x02 +#define RX_HW_N_VAL_ADDR 0x06 +#define RX_HW_CTS_ADDR 0x0C +#define RX_PCLK_FS_ADDR 0x17 +#define RX_ACR_CTRL3_ADDR 0x18 + +#define RX_BIT_MCLK_LOOPBACK 0x04 +#define RX_BIT_ACR_INIT 0x01 + +/*----------------------------------------------------- + * Audio Exception control registers + *--------------------------------------------------- + */ +#define RX_AEC_CTRL_ADDR 0xB5 +#define RX_AEC1_ADDR 0xB6 +#define RX_AEC2_ADDR 0xB7 +#define RX_AEC3_ADDR 0xB8 +/*---------------------------------------------------*/ + + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.c new file mode 100644 index 0000000..aad9017 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.c @@ -0,0 +1,145 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIRXIO + * + * Module Description: Reading and writing in SiI RX + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIRXIO.h" +/*------------------------------------------------------------------------------ + * Function Name: siiReadBlockHDMIRXP0 + * Function Description: Reads block of data from HDMI RX (page 0) + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiReadBlockHDMIRXP0(BYTE bAddr, BYTE bNBytes, BYTE *pbData) +{ + struct I2CShortCommandType_s I2CComm; + + I2CComm.SlaveAddr = RX_SLV0; + I2CComm.Flags = 0; + I2CComm.NBytes = bNBytes; + I2CComm.RegAddrL = bAddr; + hlBlockRead_8BAS((struct I2CShortCommandType_s *)&I2CComm, pbData); +} +/*------------------------------------------------------------------------------ + * Function Name: siiReadBlockHDMIRXP1 + * Function Description: Reads block of data from HDMI RX (page 1) + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiReadBlockHDMIRXP1(BYTE bAddr, BYTE bNBytes, BYTE *pbData) +{ + struct I2CShortCommandType_s I2CComm; + + I2CComm.SlaveAddr = RX_SLV1; + I2CComm.Flags = 0; + I2CComm.NBytes = bNBytes; + I2CComm.RegAddrL = bAddr; + hlBlockRead_8BAS((struct I2CShortCommandType_s *)&I2CComm, pbData); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiWriteBlockHDMIRXP0 + * Function Description: Writes block of data from HDMI RX (page 0) + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiWriteBlockHDMIRXP0(BYTE bAddr, BYTE bNBytes, BYTE *pbData) +{ + struct I2CShortCommandType_s I2CComm; + + I2CComm.SlaveAddr = RX_SLV0; + I2CComm.Flags = 0; + I2CComm.NBytes = bNBytes; + I2CComm.RegAddrL = bAddr; + hlBlockWrite_8BAS((struct I2CShortCommandType_s *)&I2CComm, pbData); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiModifyBits + * Function Description: this function reads byte from i2c device, modifys bit + * in the byte, then writes it back + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiModifyBits(BYTE bSlaveAddr, BYTE bRegAddr, BYTE bModVal, BOOL qSet) +{ + BYTE bRegVal; + + bRegVal = hlReadByte_8BA(bSlaveAddr, bRegAddr); + if (qSet) + bRegVal |= bModVal; + else + bRegVal &= (~bModVal); + hlWriteByte_8BA(bSlaveAddr, bRegAddr, bRegVal); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiReadModWriteByte + * Function Description: Reads byte at bRegAddr from i2c device at bSlaveAddr + * Clears any bits set in bBitmask + * Sets any bits set in bNewValue + * Writes byte back to bRegAddr i2c device at bSlaveAddr + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiReadModWriteByte(BYTE bSlaveAddr, BYTE bRegAddr, + BYTE bBitMask, BYTE bNewValue) +{ + + /*BYTE bRegVal; + * + * bRegVal = hlReadByte_8BA ( bSlaveAddr, bRegAddr ); + * bRegVal &= ~bBitMask; + * bRegVal |= bNewValue; + * hlWriteByte_8BA ( bSlaveAddr, bRegAddr, bRegVal ); + */ + + hlWriteByte_8BA(bSlaveAddr, bRegAddr, + (hlReadByte_8BA(bSlaveAddr, bRegAddr) & ~bBitMask) | bNewValue); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiWriteBlockHDMIRXP1 + * Function Description: Writes block of data from HDMI RX (page 1) + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +#ifdef _UNUSED_FUNC_ +void siiWriteBlockHDMIRXP1(BYTE bAddr, BYTE bNBytes, BYTE *pbData) +{ + struct I2CShortCommandType_s I2CComm; + + I2CComm.Bus = BUS_1; + I2CComm.SlaveAddr = RX_SLV1; + I2CComm.Flags = 0; + I2CComm.NBytes = bNBytes; + I2CComm.RegAddrL = bAddr; + hlBlockWrite_8BAS((struct I2CShortCommandType_s *)&I2CComm, pbData); +} +#endif /* end _UNUSED_FUNC_ */ + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.h new file mode 100644 index 0000000..93943a4 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRXIO.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _SII_RXIO_ +#define _SII_RXIO_ + +#include "SiIHLVIIC.h" + + +/* HDMI Receiver */ +#define siiIIC_RX_RWBitsInByteP0(ADDR, DATA, OP) \ + siiModifyBits(RX_SLV0, ADDR, DATA, OP) +#define siiIIC_RX_RWBitsInByteP1(ADDR, DATA, OP) \ + siiModifyBits(RX_SLV1, ADDR, DATA, OP) + +#define siiWriteByteHDMIRXP0(ADDR, DATA) hlWriteByte_8BA(RX_SLV0, ADDR, DATA) +#define siiReadByteHDMIRXP0(ADDR) hlReadByte_8BA(RX_SLV0, ADDR) +#define siiReadWordHDMIRXP0(ADDR) hlReadWord_8BA(RX_SLV0, ADDR) +#define siiWriteWordHDMIRXP0(ADDR, DATA) hlWriteWord_8BA(RX_SLV0, ADDR, DATA) + +#define siiWriteByteHDMIRXP1(ADDR, DATA) hlWriteByte_8BA(RX_SLV1, ADDR, DATA) +#define siiReadByteHDMIRXP1(ADDR) hlReadByte_8BA(RX_SLV1, ADDR) +#define siiReadWordHDMIRXP1(ADDR) hlReadWord_8BA(RX_SLV1, ADDR) +#define siiWriteWordHDMIRXP1(ADDR, DATA) hlWriteWord_8BA(RX_SLV1, ADDR, DATA) + +#define siiWaitForAckHDMIRX(TO) hlWaitForAck(RX_SLV0, TO) + + +/* Analog Front End */ +#define siiIIC_RX_RWBitsInByteU0(ADDR, DATA, OP) \ + siiModifyBits(RX_AFE0, ADDR, DATA, OP) +#define siiIIC_RX_RWBitsInByteU1(ADDR, DATA, OP) \ + siiModifyBits(RX_AFE1, ADDR, DATA, OP) + +#define siiWriteByteAFEU0(ADDR, DATA) hlWriteByte_8BA(RX_AFE0, ADDR, DATA) +#define siiReadByteAFEU0(ADDR) hlReadByte_8BA(RX_AFE0, ADDR) +#define siiReadWordAFEU0(ADDR) hlReadWord_8BA(RX_AFE0, ADDR) +#define siiWriteWordAFEU0(ADDR, DATA) hlWriteWord_8BA(RX_AFE0, ADDR, DATA) + +#define siiWriteByteAFEU1(ADDR, DATA) hlWriteByte_8BA(RX_AFE1, ADDR, DATA) +#define siiReadByteAFEU1(ADDR) hlReadByte_8BA(RX_AFE1, ADDR) +#define siiReadWordAFEU1(ADDR) hlReadWord_8BA(RX_AFE1, ADDR) +#define siiWriteWordAFEU1(ADDR, DATA) hlWriteWord_8BA(RX_AFE1, ADDR, DATA) + +#define siiWaitForAckAFE(TO) hlWaitForAck(RX_AFE0, TO) + + +void siiModifyBits(BYTE bSlaveAddr, BYTE bRegAddr, BYTE bModVal, BOOL qSet); +void siiReadBlockHDMIRXP0(BYTE bAddr, BYTE bNBytes, BYTE *pbData); +void siiReadBlockHDMIRXP1(BYTE bAddr, BYTE bNBytes, BYTE *pbData); +void siiWriteBlockHDMIRXP0(BYTE bAddr, BYTE bNBytes, BYTE *pbData); +void siiWriteBlockHDMIRXP1(BYTE bAddr, BYTE bNBytes, BYTE *pbData); + + +#define siiIIC_RX_RMW_ByteP0(ADDR, MASK, VAL) \ + siiReadModWriteByte(RX_SLV0, ADDR, MASK, VAL) +#define siiIIC_RX_RWW_ByteP1(ADDR, MASK, VAL) \ + siiReadModWriteByte(RX_SLV1, ADDR, MASK, VAL) + +void siiReadModWriteByte(BYTE bSlaveAddr, BYTE bRegAddr, + BYTE bBitMask, BYTE bNewValue); + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.c new file mode 100644 index 0000000..578b5bd --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.c @@ -0,0 +1,643 @@ +/*------------------------------------------------------------------------------ + * Module Name SiIRX_API + * Module Description: RX API functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiIRX_API.h" +#include "SiIGlob.h" +#include "SiIVidF.h" +#include "SiIVidIn.h" +#include "SiIAudio.h" +#include "SiITTAudio.h" +#include "SiITTVideo.h" +#include "SiISysCtrl.h" +#include "SiITTasks.h" +#include "SiIHDMIRX.h" +#include "SiIInfoPkts.h" +#include "SiIDiagnostic.h" +#include "SiIISR.h" +#include "SiIHAL.h" +#include "SiITrace.h" + +#include "../hdmirx_ext_drv.h" + +/*------------------------------------------------------------------------------ + * System Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetAPIInfo + * --- + * Function Description: This function is used to get information about API + * + * Accepts: + * Returns: Number of Errors code and/or warnings + * Globals: + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetAPI_Info(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + pbRXParameters[0] = SiI_RX_API_Version; + pbRXParameters[1] = SiI_RX_API_Revision; + pbRXParameters[2] = SiI_RX_API_Build; + pbRXParameters[3] = SiI_RX_API_DiagnosticCommands; + siiGetRXDeviceInfo(&pbRXParameters[4]); + pbRXParameters[7] = SII_REQ_TASK_CALL_TIME; + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); + +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_InitializeSystem + * Function Description: Initialize global data and devices + * + * Accepts: none + * Returns: Number of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_InitializeSystem(BYTE *pbSysInit) +{ + WORD wStartSysTimerTicks; + + RXEXTPR("%s\n", __func__); + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + halInitGPIO_Pins(); + siiInitializeRX(pbSysInit); + siiSaveRXInitParameters(pbSysInit); + siiInitilizeSystemData(ON); + siiTurnAudioOffAndSetSM_AudioOff(); + siiMuteVideoAndSetSM_SyncInChange(); + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); + +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GlobalPower + * Function Description: + * + * Accepts: none + * Returns: Number of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GlobalPower(BYTE bPowerState) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + siiRX_GlobalPower(bPowerState); + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_SetVideoInput + * --- + * Function Description: Selects HDMI (DVI) input + * Accepts: bVideoInputChannels + * Returns: Number of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetVideoInput(BYTE bVideoInputChannels) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + SiI_Ctrl.bVidInChannel = bVideoInputChannels; /* YMA added */ + + siiChangeVideoInput(bVideoInputChannels); + + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_SetAudioMute + * Function Description: This command provides a manual mute of + * the Silicon Image HDMI receiver's audio output. + * This command does not change the behavior of any + * device's auto mute functionality + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetAudioVideoMute(BYTE bAudioVideoMute) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + if (bAudioVideoMute & SiI_RX_AVMuteCtrl_MuteAudio) + siiSetSM_ReqHoldAudioMuteAndStartMuting(ON); + else if (siiIsAudioHoldMuteState()) + siiSetSM_ReqHoldAudioMuteAndStartMuting(OFF); + + if (bAudioVideoMute & SiI_RX_AVMuteCtrl_MuteVideo) + siiSetGlobalVideoMuteAndSM_Video(ON); + else + siiSetGlobalVideoMuteAndSM_Video(OFF); + + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_DoTasks + * Function Description: + * + * Accepts: pointer on events changes + * Returns: Number of Errors code and/or warnings + * Globals: + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_DoTasks(BYTE *pbRXParameters) +{ + /* Slot time is time between last and current DoTasks measured in ms */ + WORD wNumberOfTicks; + BYTE bTimeFromLastDoTasks; + BYTE bError; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wNumberOfTicks = siiGetTicksNumber(); + RXEXTDBG("sii9135 SiI_Ctrl.sm_bVideo = %d\n", SiI_Ctrl.sm_bVideo); + if (SiI_Ctrl.sm_bVideo != SiI_RX_VS_GlobalPowerDown) { + /* if (SiI_Inf.bGlobStatus & SiI_RX_Global_HotPlugDetect) { */ +#ifdef SII_USE_RX_PIN_INTERRUPT + bError = siiRX_PinInterruptHandler(); +#else + bError = siiRX_BitInterruptHandler(); +#endif + /* } */ + if (bError == SiI_EC_HDCP_StuckInterrupt) + siiReInitRX(); + +#ifndef FIXED_TASK_CALL_TIME + bTimeFromLastDoTasks = siiDoTasksTimeDiffrence(); +#else + bTimeFromLastDoTasks = SII_TASK_CALL_TIME; +#endif + siiTimerTasksHandler(bTimeFromLastDoTasks); + pbRXParameters[0] = siiGetSMEventChanges(); + } + siiMeasureProcLastAPI_Ticks(wNumberOfTicks); + + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetSystemInformation + * Function Description: + * + * Accepts: none + * Returns: nNumber of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetSystemInformation(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + pbRXParameters[0] = SiI_Ctrl.sm_bVideo; /* is BYTE bVideoState */ + pbRXParameters[1] = SiI_Ctrl.sm_bAudio; /* is BYTE bAudioState */ + if (siiCheckIfVideoInputResolutionReady()) { + /* is BYTE bModeId */ + pbRXParameters[2] = siiGetVideoResId(SiI_Inf.bVResId); + } else { + if (siiCheckIfVideoOutOfRangeOrVMNotDetected()) + pbRXParameters[2] = SiI_ResNotDetected; + else + pbRXParameters[2] = SiI_ResNoInfo; + } + /* is BYTE bInputColorSpace */ + pbRXParameters[3] = SiI_Inf.AVI.bInputColorSpace; + /* is BYTE bColorimetry */ + pbRXParameters[4] = SiI_Inf.AVI.bColorimetry/* ; */ + /* is upper 4 bits is Color Depth */ + | (SiI_Inf.AVI.bInputColorDepth << 4); + /* is BYTE bHDCPStatus */ + pbRXParameters[5] = SiI_Inf.bHDCPStatus; + /* is BYTE bGlobStatus */ + pbRXParameters[6] = SiI_Inf.bGlobStatus; + pbRXParameters[7] = SiI_Inf.bNewInfoPkts; + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Packet Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetInfoFrame + * Function Description: Get the current Info Frame received by + * the Silicon Image HDMI receiver. + * + * Accepts: bInfoFrameType + * Returns: BYTE *pbRXParameters pointer on Info Frame data + * Globals: none + *---------------------------------------------------------------------------- + */ + +BYTE SiI_RX_GetPackets(BYTE bInfoPacketType, BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + siiGetInfoPacket(bInfoPacketType, pbRXParameters); + siiClearNewPacketEvent(bInfoPacketType); + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Video Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_SetVideoOutputFormat + * --- + * Function Description: Sets Video Output Format of SiI RX, function sets + * static part of Video Path, dynamic part will be + * complete after detection of video resolution + * Accepts: parameters to set Video Output Format + * Returns: Number of Errors code and/or warnings + * Globals: sm_bVideo, bVideoPath, bInputColorSpace + *---------------------------------------------------------------------------- + */ + +BYTE SiI_RX_SetVideoOutputFormat(BYTE bOutputVideoPathSelect, + BYTE bOutputSyncSelect, + BYTE bOutputSyncCtrl, + BYTE bOutputVideoCtrl) +{ + WORD wStartSysTimerTicks; + BYTE abVidFormatData[3]; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + abVidFormatData[0] = abVidFormatData[1] = abVidFormatData[2] = 0; + /* YMA restore the configuration, or outpout depth lost */ + siiGetVideoFormatData(abVidFormatData); + + siiMuteVideoAndSetSM_SyncInChange(); + + siiPrepVideoPathSelect(bOutputVideoPathSelect, + SiI_Inf.AVI.bInputColorSpace, abVidFormatData); + siiPrepSyncSelect(bOutputSyncSelect, abVidFormatData); + siiPrepSyncCtrl(bOutputSyncCtrl, abVidFormatData); + siiPrepVideoCtrl(bOutputVideoCtrl, abVidFormatData); + /* Update Video format data to Vid. Mode/Ctrl regs. */ + siiSetVideoFormatData(abVidFormatData); + + /* later will be used in Vid. Res. Dependent functions */ + SiI_Ctrl.VideoF.bOutputVideoPath = bOutputVideoPathSelect; + SiI_Ctrl.VideoF.bOutputSyncSelect = bOutputSyncSelect; + SiI_Ctrl.VideoF.bOutputSyncCtrl = bOutputSyncCtrl; + SiI_Ctrl.VideoF.bOutputVideoCtrl = bOutputVideoCtrl; + + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); + +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetVideoOutputFormat + * Function Description: Gets Video Output Format + * + * Accepts: none + * Returns: Number of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetVideoOutputFormat(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + /* later will be used in Vid. Res. Dependent functions */ + pbRXParameters[0] = SiI_Ctrl.VideoF.bOutputVideoPath; + pbRXParameters[1] = SiI_Ctrl.VideoF.bOutputSyncSelect; + pbRXParameters[2] = SiI_Ctrl.VideoF.bOutputSyncCtrl; + pbRXParameters[3] = SiI_Ctrl.VideoF.bOutputVideoCtrl; + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetInputVideoResolution + * Function Description: + * + * Accepts: none + * Returns: Number of Errors code and/or warnings + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetVideoInputResolution(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + if (siiCheckIfVideoInputResolutionReady()) + siiGetVideoInputResolution(SiI_Inf.bVResId, pbRXParameters); + else + pbRXParameters[0] = SiI_ResNoInfo; +#ifdef SII_NO_RESOLUTION_DETECTION + if (siiCheckIfVideoOutOfRangeOrVMNotDetected()) + siiGetVideoInputResolutionromRegisters(pbRXParameters); +#endif + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Audio Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_SetAudioOutputFormat + * Function Description: Set the Silicon image HDMI receivers audio + * output format. + * Both audio interfaces, SPDIF and I2S can + * be selected simultaneously. + * The Smooth HW Mute can also be enabled regardless of + * the audio interfaces combination selected. + * + * The BYTE bI2SMap is a reserved parameter in + * the API specification. + * It is being used to set up the I2S mapping, + * the API does not support configurations other than + * the default. + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetAudioOutputFormat(WORD wAudioOutputSelect, + WORD wI2SBusFormat, + BYTE bI2SMap, + BYTE bDSDHBRFormat) +{ + /* YMA 2 added for API rev2 */ + WORD wStartSysTimerTicks; + struct AudioOutputFormatType_s AudioOutputFormat; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + + siiTurnAudioOffAndSetSM_AudioOff(); + + AudioOutputFormat.wOutputSelect = + SiI_Ctrl.wAudioOutputSelect = wAudioOutputSelect; + AudioOutputFormat.wI2SBusFormat = wI2SBusFormat; + AudioOutputFormat.bI2SMap = bI2SMap; + AudioOutputFormat.bDSDHBRFormat = bDSDHBRFormat; + siiSetAudioOutputFormat(&AudioOutputFormat); + + /* YMA 2 add to save the configuration for + *later restore when HBR/DSD -> PCM + */ + SavedAudioOutputFormat = AudioOutputFormat; + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetAudioOutputFormat + * Function Description: + * + * Accepts: none + * Returns: pbRXParameters[0] is BYTE bAudioOutputControl, + * pbRXParameters[1] is WORD wI2SBusFormat + * pbRXParameters[4] is BYTE bI2SMap + * pbRXParameters[5] is BYTE bDSDHBRFormat + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetAudioOutputFormat(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + /* struct AudioOutputFormatType_s AudioOutputFormat; */ + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + /* YMA change to return the save value instead of read from registers. + *the reg value may be not the right mode + */ + + /* siiGetAudioOutputFormat(&AudioOutputFormat); */ + + pbRXParameters[0] = (BYTE)(SavedAudioOutputFormat.wOutputSelect & 0xFF); + pbRXParameters[1] = + (BYTE)((SavedAudioOutputFormat.wOutputSelect >> 8) & 0xFF); + pbRXParameters[2] = (BYTE)(SavedAudioOutputFormat.wI2SBusFormat & 0xFF); + pbRXParameters[3] = + (BYTE)((SavedAudioOutputFormat.wI2SBusFormat >> 8) & 0xFF); + pbRXParameters[4] = SavedAudioOutputFormat.bI2SMap; + pbRXParameters[5] = SavedAudioOutputFormat.bDSDHBRFormat; + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_RX_GetAudioInputStatus + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetAudioInputStatus(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + wStartSysTimerTicks = siiGetTicksNumber(); + pbRXParameters[0] = SiI_Inf.bAudioErr; + if (siiIsAudioStatusReady()) { + /* Compressed, PCM, DSD */ + pbRXParameters[1] = SiI_Inf.AudioStatus.bRepresentation; + pbRXParameters[2] = SiI_Inf.AudioStatus.bAccuracyAndFs; + pbRXParameters[3] = SiI_Inf.AudioStatus.bLength; + pbRXParameters[4] = SiI_Inf.AudioStatus.bNumberChannels; + } else { + pbRXParameters[1] = 0xFF; + pbRXParameters[2] = 0xFF; + pbRXParameters[3] = 0xFF; + pbRXParameters[4] = 0xFF; + } + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + + +/*------------------------------------------------------------------------------ + * Common Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_GetWarnings(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + BYTE bNumberWrn; + + wStartSysTimerTicks = siiGetTicksNumber(); + + bNumberWrn = siiGetWarningData(pbRXParameters); + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return bNumberWrn; + +} + +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_GetErrors(BYTE *pbRXParameters) +{ + WORD wStartSysTimerTicks; + BYTE bNumberErr; + + wStartSysTimerTicks = siiGetTicksNumber(); + + bNumberErr = siiGetErrorsData(pbRXParameters); + + siiMeasureProcLastAPI_Ticks(wStartSysTimerTicks); + /* if Result FALSE, no errors and warning messages */ + return bNumberErr; +} + +/*------------------------------------------------------------------------------ + * Diagnostics Commands + *---------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------------ + * Function Name: SiI_Diagnostic_GetNCTS + * Function Description: Get information about N/CTS packets, these packets + * are sent by TX and used for Audio Clock Regeneration + * (ACR) + * Accepts: none + * Returns: pointer on requested data + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_Diagnostic_GetNCTS(BYTE *pbRXParameters) +{ + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + siiGetNCTS(pbRXParameters); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SiI_Diagnostic_GetABKSV + * Function Description: Get AKSV and BKSV + * (for more information see HDCP specefication) + * + * Accepts: none + * Returns: pointer on requested data + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_Diagnostic_GetABKSV(BYTE *pbRXParameters) +{ + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + siiGetABKSV(pbRXParameters); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE SiI_Diagnostic_GetAPIExeTime(BYTE *pbRXParameters) +{ + siiResetErrorsAndWarnings(); /* Number of Warning Messages = Zero */ + siiDiagnostic_GetAPI_ExeTime(pbRXParameters); + /* if Result FALSE, no errors and warning messages */ + return siiGetErrorsWarnings(); +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.h new file mode 100644 index 0000000..b99a8b5 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIRX_API.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIRXAPIDefs.h" +#include "SiIGlob.h" + +/*------------------------------------------------------------------------------ + * System Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetAPI_Info(BYTE *pbRXParameters); +BYTE SiI_RX_InitializeSystem(BYTE *pbSysInit); +BYTE SiI_RX_GlobalPower(BYTE bPowerState); +BYTE SiI_RX_SetVideoInput(BYTE bVideoInputChannels); +BYTE SiI_RX_SetAudioVideoMute(BYTE bAudioVideoMute); +BYTE SiI_RX_DoTasks(BYTE *pbRXParameters); +BYTE SiI_RX_GetSystemInformation(BYTE *pbRXParameters); + +/*------------------------------------------------------------------------------ + * Packet Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_GetPackets(BYTE bInfoPacketType, BYTE *pbRXParameters); + +/*------------------------------------------------------------------------------ + * Video Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetVideoOutputFormat(BYTE bOutputVideoPathSelect, + BYTE bOutputSyncSelect, BYTE bOutputSyncCtrl, + BYTE bOutputVideoCtrl); +BYTE SiI_RX_GetVideoOutputFormat(BYTE *pbRXParameters); +BYTE SiI_RX_GetVideoInputResolution(BYTE *pbRXParameters); + +/*------------------------------------------------------------------------------ + * Audio Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_RX_SetAudioOutputFormat(WORD wAudioOutputSelect, WORD wI2SBusFormat, + BYTE bI2SMap, BYTE bDSDHBRFormat); +BYTE SiI_RX_GetAudioOutputFormat(BYTE *pbRXParameters); +BYTE SiI_RX_GetAudioInputStatus(BYTE *pbRXParameters); + +/*------------------------------------------------------------------------------ + * Common Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_GetWarnings(BYTE *pbRXParameters); +BYTE SiI_GetErrors(BYTE *pbRXParameters); + +/*------------------------------------------------------------------------------ + * Diagnostics Commands + *---------------------------------------------------------------------------- + */ +BYTE SiI_Diagnostic_GetNCTS(BYTE *pbRXParameters); +BYTE SiI_Diagnostic_GetABKSV(BYTE *pbRXParameters); +BYTE SiI_Diagnostic_GetAPIExeTime(BYTE *pbRXParameters); + +/* Command has been removed from API 1.0 specification + *BYTE SiI_RX_GetTasksSchedule(BYTE *bdata); + */ + + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.c new file mode 100644 index 0000000..155d0044 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.c @@ -0,0 +1,287 @@ +/*------------------------------------------------------------------------------ + * Module Name + * --- + * Module Description… + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiISysCtrl.h" +#include "SiIGlob.h" +#include "SiIHAL.h" +#include "SiIRXDefs.h" +#include "SiIRXAPIDefs.h" +#include "SiITrace.h" +#include "SiIHDMIRX.h" +#include "SiIAudio.h" +#include "SiIVidF.h" +#include "SiITTInfoPkts.h" +#include "UAudDAC.h" +/*------------------------------------------------------------------------------ + * Function Name: siiSaveRXInitParameters() + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSaveRXInitParameters(BYTE *pbParameter) +{ + SiI_Ctrl.bRXInitPrm0 = pbParameter[0]; + SiI_Inf.AVI.bOutputColorDepth = pbParameter[1]; /* YMA fix */ + /* SiI_Ctrl.bVidInChannel = pbParameter[1]; //YMA wrong info saved + * SiI_Ctrl.bVidInChannel = pbParameter[2]; + */ + +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetRXInitParameters() + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetRXInitParameters(BYTE *pbParameter) +{ + pbParameter[0] = SiI_Ctrl.bRXInitPrm0; /* FPGA and MClock */ + pbParameter[1] = SiI_Inf.AVI.bOutputColorDepth; /*YMA fix */ + /* pbParameter[1] = SiI_Ctrl.bVidInChannel; // Video input id + * pbParameter[2] = SiI_Ctrl.bVidInChannel; // Video input id + */ + +} +/*------------------------------------------------------------------------------ + * Function Name: siiInitilizeSystemData + * Function Description: + * + * Accepts: BOOL Key for initialization System data + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiInitilizeSystemData(BOOL qDoFromScratch) +{ + BYTE bEWCode = FALSE; + + if (qDoFromScratch) { + SiI_Ctrl.wAudioOutputSelect = SiI_RX_AOut_Default; + SiI_Ctrl.sm_bAudio = SiI_RX_AS_AudioOff; + halWakeUpAudioDAC(); + PowerDownAudioDAC(); + SiI_Inf.bGlobStatus = SiI_RX_GlobalHDMI_NoAVIPacket | + SiI_RX_Global_OldHotPlugDetect; + } else { + /* clear these these flags and retain others */ + SiI_Inf.bGlobStatus = ~(SiI_RX_Global_HotPlugDetect | + SiI_RX_GlobalHDMI_Detected | SiI_RX_GlobalHDMI_ACP | + SiI_RX_GlobalHDMI_NoAVIPacket); + + } + siiResetACPPacketData(); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_PowerDown; + SiI_Ctrl.wVideoTimeOut = 20; /* YMA PD issue fix */ + + SiI_Ctrl.bShadowPixRepl = 0; + SiI_Ctrl.bIgnoreIntr = 0; + SiI_Ctrl.bHDCPFailFrmCnt = 0; + SiI_Ctrl.bHDCPStuckConfirmCnt = 0; + + SiI_Inf.AVI.bInputColorDepth = SiI_RX_CD_24BPP; + + SiI_Inf.bVResId = 0; + SiI_Inf.AVI.bAVI_State = SiI_RX_NoAVI; + SiI_Inf.AVI.bColorimetry = SiI_RX_ColorimetryNoInfo; + SiI_Inf.AVI.bInputColorSpace = SiI_RX_ICP_RGB; + SiI_Inf.AVI.bPixRepl = 0; + SiI_Inf.bNewInfoPkts = 0; + + return bEWCode; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiConvertTicksInMS + * Function Description: Converts System timer ticks in milliseconds + * + * Accepts: wTicks + * Returns: wMS + * Globals: none + *---------------------------------------------------------------------------- + */ +WORD siiConvertTicksInMS(WORD wTicks) +{ + WORD wMS; + DWORD dwUS; + + dwUS = wTicks * SII_SYS_TICK_TIME; /* SII_SYS_TICK_TIME in US */ + wMS = dwUS / 1000; + return wMS; + +} + +#ifndef FIXED_TASK_CALL_TIME +/*------------------------------------------------------------------------------ + * Function Name: siiDoTasksTimeDiffrence + * Function Description: Function is called in DoTasks + * + * Accepts: + * Returns: TimeDifference + * Globals: + *---------------------------------------------------------------------------- + */ +BYTE siiDoTasksTimeDiffrence(void) +{ + WORD wTicksNumber; + WORD wTicksDiff; + + wTicksNumber = siiGetTicksNumber(); + + if (wTicksNumber >= SiI_Ctrl.SysTimer.wProcLastDoTasks_Ticks) { + wTicksDiff = + wTicksNumber - SiI_Ctrl.SysTimer.wProcLastDoTasks_Ticks; + } else { + wTicksDiff = + SiI_Ctrl.SysTimer.wProcLastDoTasks_Ticks - wTicksNumber; + } + + SiI_Ctrl.SysTimer.wProcLastDoTasks_Ticks = wTicksNumber; + + return siiConvertTicksInMS(wTicksDiff); + +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: siiMeasureProcLastAPI_Ticks + * Function Description: This function is used for time measuring, time + * differnce shouldn't exceed 0xFFFF ticks + * Accepts: none + * Returns: Number ticks spent for execution of task + * Globals: SiI_Ctrl.SysTimer.wProcLastAPI_Ticks + *---------------------------------------------------------------------------- + */ +void siiMeasureProcLastAPI_Ticks(WORD wStartTimeInTicks) +{ + WORD wNewTimeInTicks; + + wNewTimeInTicks = siiGetTicksNumber(); + + if (wNewTimeInTicks > wStartTimeInTicks) { /* check for roll over */ + SiI_Ctrl.SysTimer.wProcLastAPI_Ticks = + wNewTimeInTicks - wStartTimeInTicks; + } else { + SiI_Ctrl.SysTimer.wProcLastAPI_Ticks = + (0xFFFF - wNewTimeInTicks) + wStartTimeInTicks; + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiDiagnostic_GetAPI_ExeTime + * Function Description: this function takes time for the last executed API + * and convert it from ticks to ms + * Accepts: none + * Returns: BYTE * pbAPI_ExeTime + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiDiagnostic_GetAPI_ExeTime(BYTE *pbAPI_ExeTime) +{ + WORD wExeTime; + + wExeTime = siiConvertTicksInMS(SiI_Ctrl.SysTimer.wProcLastAPI_Ticks); + pbAPI_ExeTime[0] = (BYTE)(wExeTime & 0x00FF); + pbAPI_ExeTime[1] = (BYTE)((wExeTime & 0xFF00) >> 8); + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetEventChenges + * Function Description: Reports about main changes in system + * + * Accepts: none + * Returns: BYTE, change events + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetSMEventChanges(void) +{ + BYTE bResult = 0; + /* values should be same as initalized in siiInitilizeSystemData */ + static BYTE sm_bVideo = SiI_RX_VS_PowerDown; + static BYTE sm_bAudio = SiI_RX_AS_AudioOff; + static BYTE bHDCPStatus; + static BYTE bGlobStatus; + + if (sm_bVideo != SiI_Ctrl.sm_bVideo) { + bResult |= SiI_RX_API_VideoSM_Changed; + sm_bVideo = SiI_Ctrl.sm_bVideo; + } + if (sm_bAudio != SiI_Ctrl.sm_bAudio) { + bResult |= SiI_RX_API_AudioSM_Changed; + sm_bAudio = SiI_Ctrl.sm_bAudio; + } + if (SiI_Inf.bNewInfoPkts) + bResult |= SiI_RX_API_InfoPacket_Changed; + if (bHDCPStatus != SiI_Inf.bHDCPStatus) { + bResult |= SiI_RX_API_HDCPStatus_Changed; + bHDCPStatus = SiI_Inf.bHDCPStatus; + } + if (bGlobStatus != SiI_Inf.bGlobStatus) { + bGlobStatus = SiI_Inf.bGlobStatus; + bResult |= SiI_RX_API_GlobalStatus_Changed; + } + + return bResult; + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiReInitRX + * Function Description: This function is used to Re-inialize HDMI RX + * after Hardware reset + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiReInitRX(void) +{ + BYTE abData[3]; + struct AudioOutputFormatType_s AudioOutputFormat; + + /* Gets MClock divider and active TMDS core */ + siiGetRXInitParameters(abData); + /* Get Audio Format Setting, some setting stored in RX regs. so it's + * Need to do before hardware reset + */ + siiGetAudioOutputFormat(&AudioOutputFormat); + + siiInitializeRX(abData); /*in this function RX Hardware Reset is used*/ + siiInitilizeSystemData(OFF); /* Intilize System Data with Key OFF */ + /* with OFF key Video/Audio Format cfg. data is not modified + * Now it's need to restore Aideo Output Format + */ + /* Restore RX Audio Format Configuration */ + siiSetAudioOutputFormat(&AudioOutputFormat); + + /* Set Video Format static settings */ + /* Restore RX Video Format Configuration */ + abData[0] = abData[1] = abData[2] = 0; + /* YMA restore the configuration, or outpout depth lost */ + siiGetVideoFormatData(abData); + siiPrepSyncSelect(SiI_Ctrl.VideoF.bOutputSyncSelect, abData); + siiPrepSyncCtrl(SiI_Ctrl.VideoF.bOutputSyncCtrl, abData); + siiPrepVideoCtrl(SiI_Ctrl.VideoF.bOutputVideoCtrl, abData); + /* Update RX Video format cfg. at Vid. Mode/Ctrl regs. */ + siiSetVideoFormatData(abData); + +} + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.h new file mode 100644 index 0000000..8c24b8e --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiISysCtrl.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIRXAPIDefs.h" + +void siiSaveRXInitParameters(BYTE *pbParameter); +void siiGetRXInitParameters(BYTE *pbParameter); +BYTE siiInitilizeSystemData(BOOL qDoFromScratch); + +BYTE siiDoTasksTimeDiffrence(void); +WORD siiGetTicksNumber(void); +WORD siiConvertTicksInMS(WORD wTicks); +void siiMeasureProcLastAPI_Ticks(WORD wStartTimeInTicks); +void siiDiagnostic_GetAPI_ExeTime(BYTE *pbAPI_ExeTime); +BYTE siiGetSMEventChanges(void); +void siiReInitRX(void); + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.c new file mode 100644 index 0000000..de45040 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.c @@ -0,0 +1,56 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiITHDCP + * + * Module Description: services time polling HDCP functions + * + *------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +/*#include */ +#include "SiIGlob.h" +#include "SiITHDCP.h" +#include "SiITrace.h" +#include "SiIRXIO.h" +#include "SiIRXDefs.h" + +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ +static BOOL CheckHDCPDecypting(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDCP_STAT_ADDR) & RX_BIT_HDCP_DECRYPTING) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetHDCPStatus(void) +{ + BYTE bStatus; + + if (CheckHDCPDecypting()) + bStatus = SiI_RX_HDCP_Decrypted; + else + bStatus = SiI_RX_HDCP_NotDecrypted; + return bStatus; + +} + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.h new file mode 100644 index 0000000..9cbcaed --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITHDCP.h @@ -0,0 +1,11 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiITypeDefs.h" + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.c new file mode 100644 index 0000000..71753e1 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.c @@ -0,0 +1,337 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiITTAudio + * + * Module Description: Serves Audio Timeing evevts and audio state machine + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiITTAudio.h" +#include "SiITTVideo.h" /* need to sync with video */ +#include "SiIAudio.h" +#include "SiITrace.h" +#include "SiIHAL.h" + +#ifdef SII_DUMP_UART +#include "SiIISR.h" +#include "../hdmirx_ext_drv.h" +#endif + +/*------------------------------------------------------------------------------ + * Function Name: siiIsAudioHoldMuteState + * Function Description: This function checks state machine, if state + * SiI_RX_AS_HoldAudioMute then return true + * + * Accepts: none + * Returns: BOOL + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiIsAudioHoldMuteState(void) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.sm_bAudio == SiI_RX_AS_HoldAudioMute) + qResult = TRUE; + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: SetTimeOutOandSM_ReqWaitVideoOn + * Function Description: assign this state and time out in order to + * sync Audio with Video + * + * Accepts: none + * Returns: none + * Globals: SiI_Ctrl.sm_bAudio, SiI_Ctrl.wAudioTimeOut + *---------------------------------------------------------------------------- + */ +static void SetTimeOutandSM_ReqWaitVideoOn(void) +{ + SiI_Ctrl.sm_bAudio = SiI_RX_AS_WaitVideoOn; + SiI_Ctrl.wAudioTimeOut = 16; +} +/*------------------------------------------------------------------------------ + * Function Name: siiIsAudioStatusReady + * Function Description: This function checks state machine, if state AudioOn + * then return true + * + * Accepts: none + * Returns: BOOL + * Globals: none + *---------------------------------------------------------------------------- + */ +BOOL siiIsAudioStatusReady(void) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.sm_bAudio == SiI_RX_AS_AudioOn) + qResult = TRUE; + return qResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiSetSM_ReqAudio + * Function Description: asserts SiI_RX_AS_ReqAudio, this state starts check + * Audio conditions exception asserted + * SiI_RX_AS_HoldAudioMute state + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetSM_ReqAudio(void) +{ + /* Audio mute which is asserted by API command can be + * can be de-asserted only by command + */ + if (SiI_Ctrl.sm_bAudio != SiI_RX_AS_HoldAudioMute) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_ReqAudio; + SiI_Ctrl.wAudioTimeOut = 5; + } +} +/*------------------------------------------------------------------------------ + * Function Name: SetSM_HoldAudioMute + * Function Description: asserts and deaserts SiI_RX_AS_HoldAudioMute + * only by this function iI_RX_AS_HoldAudioMute + * can be deasserted + *---------------------------------------------------------------------------- + */ +static void SetSM_HoldAudioMute(BOOL qOn) +{ + if (qOn) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_HoldAudioMute; + SiI_Ctrl.wAudioTimeOut = 0; + } else { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_ReqAudio; + SiI_Ctrl.wAudioTimeOut = 5; + } + +} +/*------------------------------------------------------------------------------ + * Function Name: SetSM_AudioOff + * Function Description: this function sets SiI_RX_AS_AudioOff, exception + * asserted SiI_RX_AS_HoldAudioMute state + *---------------------------------------------------------------------------- + */ +static void SetSM_AudioOff(void) +{ + /* Audio mute which is asserted by API command can be + * can be de-asserted only by command + */ + if (SiI_Ctrl.sm_bAudio != SiI_RX_AS_HoldAudioMute) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_AudioOff; + /* # ms being quiet, (not to attepmt bring up Audio) */ + SiI_Ctrl.wAudioTimeOut = 200; + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiTurnAudioOffAndSetSM_AudioOff + * Function Description: This function calls turning Audio Off, and changes + * state of the state machine + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiTurnAudioOffAndSetSM_AudioOff(void) +{ + /* siiSetAutoFIFOReset(OFF); */ + siiTurningAudio(OFF); + SetSM_AudioOff(); +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetGlobalAudioMuteAndSM_Audio + * Function Description: Asserts or Deasserts Audio Mute + * + * Accepts: BOOL + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetGlobalAudioMuteAndSM_Audio(BOOL qOn) +{ + if (qOn) { + siiSetAudioMuteEvent(); + SetSM_HoldAudioMute(ON); + } else { + SetSM_HoldAudioMute(OFF); + } + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetSM_ReqHoldAudioMute + * Function Description: This function emolliates waiting for Soft Muting, + * it should be used to wait when audio soft mute is ramping down + * Accepts: none + * Returns: none + *---------------------------------------------------------------------------- + */ + +void siiSetSM_ReqHoldAudioMuteAndStartMuting(BOOL qOn) +{ + if (qOn) { + siiAudioMute(ON); + SiI_Ctrl.sm_bAudio = SiI_RX_AS_ReqHoldAudioMute; + SiI_Ctrl.wAudioTimeOut = 50; /* delays for 50 ms */ + } else { + SetSM_HoldAudioMute(OFF); + } + +} +/*------------------------------------------------------------------------------ + * Function Name: CheckAudio_IfOK_InitACR + * Function Description: If Audio is OK and ACR init., then set time after which + * CTS change interrupt can be cleared (used for STS stability check later) + *---------------------------------------------------------------------------- + */ +static void CheckAudio_IfOK_InitACR(void) +{ + siiClearCTSChangeInterruprt(); + if (siiCheckAudio_IfOK_InitACR()) { + SiI_Ctrl.wAudioTimeOut = 4; + SiI_Ctrl.sm_bAudio = SiI_RX_AS_StartCheckCTS_Stable; + } else { + SetSM_AudioOff(); + } + +} +/*------------------------------------------------------------------------------ + * Function Name: StartCheckCTS_Stable + * Function Description: Call clear CTS change interrupt, + * change state machine for waiting PLL Lock + *---------------------------------------------------------------------------- + */ +static void StartCheckCTS_Stable(void) +{ + siiClearCTSChangeInterruprt(); + SiI_Ctrl.sm_bAudio = SiI_RX_AS_WaitAudioPPLLock; + SiI_Ctrl.wAudioTimeOut = 150; /* Set wait # ms for PLL Locking */ + +} +/*------------------------------------------------------------------------------ + * Function Name: PrepareTurningAudioOn + * Function Description: If Audio prepered for turning on (waked up Audio DAC), + * hten set delay when Audio DAC will be ready + *---------------------------------------------------------------------------- + */ +static void PrepareTurningAudioOn(void) +{ + if (siiPrepareTurningAudioOn()) { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_WaitAudioDACReady; + /* Set wait # ms, when Audio DAC will be ready */ + SiI_Ctrl.wAudioTimeOut = SiI_RX_DelayAudio_WaitDACWakingUp; + } else { + SiI_Ctrl.sm_bAudio = SiI_RX_AS_AudioOff; + /* # ms being quiet, (not to attepmt bring up Audio) */ + SiI_Ctrl.wAudioTimeOut = 200; + } +} +/*------------------------------------------------------------------------------ + * Function Name: TurningAudioOn + * Function Description: call teurning Audio On and change state machine + * to Audio On + *---------------------------------------------------------------------------- + */ +static void TurningAudioOn_SetSM_WaitStatusLock(void) +{ + siiTurningAudio(ON); + SiI_Ctrl.sm_bAudio = SiI_RX_AS_AudioOnWaitLockStatus; + /* # ms being quiet, (not to attepmt bring up Audio) */ + SiI_Ctrl.wAudioTimeOut = 700; +} +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ +static void LockAudioStatusSetSM_AudioOn(void) +{ + siiSaveInputAudioStatus(); + SiI_Ctrl.sm_bAudio = SiI_RX_AS_AudioOn; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiTTAudioHandler + * Function Description: Calls processing of Audio Timing Events + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiTTAudioHandler(BOOL qTimeOut) +{ + BYTE bECode = FALSE; + + switch (SiI_Ctrl.sm_bAudio) { + case SiI_RX_AS_ReqAudio: + if (qTimeOut) + CheckAudio_IfOK_InitACR(); + break; + case SiI_RX_AS_StartCheckCTS_Stable: + if (qTimeOut) { + StartCheckCTS_Stable(); + siiClearGotCTSAudioPacketsIterrupts(); + } + break; + case SiI_RX_AS_WaitAudioPPLLock: + if (qTimeOut) + PrepareTurningAudioOn(); + break; + case SiI_RX_AS_AudioOff: + if (qTimeOut) { + siiSetSM_ReqAudio(); + siiClearGotCTSAudioPacketsIterrupts(); + } + break; + case SiI_RX_AS_WaitAudioDACReady: + if (qTimeOut) { + if (siiIsVideoOn()) { +#ifdef SII_DUMP_UART + siiTraceRXInterrupts(); +#endif + TurningAudioOn_SetSM_WaitStatusLock(); +#ifdef SII_DUMP_UART + printf(" Aud On "); +#endif + } else + SetTimeOutandSM_ReqWaitVideoOn(); + } + break; + case SiI_RX_AS_AudioOnWaitLockStatus: + if (qTimeOut) + LockAudioStatusSetSM_AudioOn(); + break; + case SiI_RX_AS_HoldAudioMute: + /* Do nothing, a global Audio Mute is asserted! */ + break; + case SiI_RX_AS_WaitVideoOn: + if (qTimeOut) { + if (siiIsVideoOn()) + TurningAudioOn_SetSM_WaitStatusLock(); + else + SetTimeOutandSM_ReqWaitVideoOn(); + } + break; + case SiI_RX_AS_ReqHoldAudioMute: + if (qTimeOut) { + SetSM_HoldAudioMute(ON); + siiTurnAudioOffAndSetSM_AudioOff(); + } + break; + } + bECode = SiI_Inf.bAudioErr; + return bECode; + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.h new file mode 100644 index 0000000..d876537 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTAudio.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _SII_TTAUDIO_ +#define _SII_TTAUDIO_ +#include "SiITypeDefs.h" + + + +BYTE siiTTAudioHandler(BOOL qTimeOut); +void siiSetSM_ReqAudio(void); +void siiTurnAudioOffAndSetSM_AudioOff(void); +void siiSetGlobalAudioMuteAndSM_Audio(BOOL qOn); +BOOL siiIsAudioHoldMuteState(void); +/* YMA fix by added audio mute API */ +void siiSetSM_ReqHoldAudioMuteAndStartMuting(BOOL qOn); + + +#endif + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.c new file mode 100644 index 0000000..b3942df --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.c @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiITTHDCP + * + * Module Description: Executes Timer HDCP tasks + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiIGlob.h" +#include "SiITTHDCP.h" +#include "SiITrace.h" +#include "SiIHDCP.h" +#include "SiIRXDefs.h" + + +/*------------------------------------------------------------------------------ + * Function Name: siiGetHDCPStatus + * Function Description: This function reads HDCP status + * + * Accepts: none + * Returns: BYTE of HDCP status + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetHDCPStatus(void) +{ + BYTE bStatus; + + if (siiCheckHDCPDecrypting()) + bStatus = SiI_RX_HDCP_Decrypted; + else + bStatus = SiI_RX_HDCP_NotDecrypted; + return bStatus; + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.h new file mode 100644 index 0000000..8502040 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTHDCP.h @@ -0,0 +1,14 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +BYTE siiGetHDCPStatus(void); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.c new file mode 100644 index 0000000..deab1e2 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.c @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiITTInfoPkts + * + * Module Description: time based Info handling + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIInfoPkts.h" +#include "SiIGlob.h" +#include "SiIRXIO.h" +#include "SiIRXDefs.h" +#include "SiITrace.h" + +BYTE abOldInfoPkt[2] = { 0x00, 0x00 }; + +/*------------------------------------------------------------------------------ + * Function Name: siiResetACPPacketData + * Function Description: Clears data in ACP packet + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiResetACPPacketData(void) +{ + abOldInfoPkt[0] = abOldInfoPkt[1] = 0; +} + +/*------------------------------------------------------------------------------ + * Function Name: CheckACPInterruptAndClearIfSet + * Function Description: checking Audio Code Protection Packet interrupt + *---------------------------------------------------------------------------- + */ +static BOOL CheckACPInterruptAndClearIfSet(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_HDMI_INT_ST6_ADDR) & RX_BIT_ACP_PACKET) { + siiWriteByteHDMIRXP0(RX_HDMI_INT_ST6_ADDR, RX_BIT_ACP_PACKET); + qResult = TRUE; + } + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: InfoACPInterruptHandler + * Function Description: checks ACP status + *---------------------------------------------------------------------------- + */ +void InfoACPInterruptHandler(void) +{ /* SiI_RX_NewInfo_ACP */ + BYTE abInfoPkt[2]; + + siiReadBlockHDMIRXP1(RX_ACP_INFO_PKT_ADDR, 2, abInfoPkt); + + if (abInfoPkt[0] == ACP_Type) { + /* call ACP processing */ + if (abInfoPkt[1] > 1) { + /* Audio is protected */ + SiI_Inf.bGlobStatus |= SiI_RX_GlobalHDMI_ACP; + } else { + /* Flag repported on upper layer, + * Enable Digital Output + */ + SiI_Inf.bGlobStatus &= (~SiI_RX_GlobalHDMI_ACP); + } + if ((abInfoPkt[0] != abOldInfoPkt[0]) || + (abInfoPkt[1] != abOldInfoPkt[1])) { + abOldInfoPkt[0] = abInfoPkt[0]; + abOldInfoPkt[1] = abInfoPkt[1]; + SiI_Inf.bNewInfoPkts |= SiI_RX_NewInfo_ACP; + } + } +} + + +/*------------------------------------------------------------------------------ + * Function Name: siiTTInfoFrameHandler + * Function Description: switches between Info decode addresses in order + * to be able receive all types of Info, call checking + * ACP status + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiTTInfoFrameHandler(void) +{ + if (CheckACPInterruptAndClearIfSet()) { + InfoACPInterruptHandler(); /* checks ACP packet */ + } else { + SiI_Inf.bGlobStatus &= (~SiI_RX_GlobalHDMI_ACP); + SiI_Inf.bNewInfoPkts &= (~SiI_RX_NewInfo_ACP); + } + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.h new file mode 100644 index 0000000..e9e3312 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTInfoPkts.h @@ -0,0 +1,15 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" + +void siiTTInfoFrameHandler(void); +void siiResetACPPacketData(void); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.c new file mode 100644 index 0000000..6f1be6c --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.c @@ -0,0 +1,437 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiITTVideo + * + * Module Description: + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIVidRes.h" +#include "SiIVidF.h" +#include "SiIGlob.h" +#include "SiITTVideo.h" +#include "SiITrace.h" +#include "SiIHDMIRX.h" +#include "SiIAudio.h" +#include "SiIVidIn.h" +#include "SiIISR.h" +#include "SiITTAudio.h" + +#include "../hdmirx_ext_drv.h" + +/*------------------------------------------------------------------------------ + * Function Name: IsVideoOn + * Function Description: checks video state machine, state is used when res + * change interrupt is ignorred + * Accepts: none + * Returns: BOOL, true if Video is on + * Globals: SiI_Ctrl.sm_bVideo + *---------------------------------------------------------------------------- + */ +BOOL siiIsVideoOn(void) +{ + BOOL qResult = FALSE; + + if ((SiI_Ctrl.sm_bVideo == SiI_RX_VS_VideoOn) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_VMNotDetected)) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiSMCheckReqVideoOn + * Function Description: checks video state machine, state is used when res + * change interrupt is ignorred + * Accepts: none + * Returns: BOOL + * Globals: Read only, SiI_Ctrl.sm_bVideo + *---------------------------------------------------------------------------- + */ + +BOOL siiSMCheckReqVideoOn(void) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.sm_bVideo == SiI_RX_VS_ReqVideoOn) + qResult = TRUE; + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetSM_ReqGlobalPowerDown + * Function Description: Sets SiI_RX_VS_ReqGlobalPowerDown and when + * SiI_RX_VS_GlobalPowerDown will be asserted + *---------------------------------------------------------------------------- + */ +void siiSetSM_ReqGlobalPowerDown(void) +{ + SiI_Ctrl.sm_bVideo = SiI_RX_VS_ReqGlobalPowerDown; + SiI_Ctrl.wVideoTimeOut = 32; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetSM_ReqPowerDown + * Function Description: Sets SiI_RX_VS_ReqPowerDown and when + * SiI_RX_VS_PowerDown will be asserted + *---------------------------------------------------------------------------- + */ +void siiSetSM_ReqPowerDown(void) +{ + SiI_Ctrl.sm_bVideo = SiI_RX_VS_ReqPowerDown; + SiI_Ctrl.wVideoTimeOut = 1200; + +} +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ +void siiSetPowerDownModeAndSetSM_PowerDown(void) +{ + SiI_Ctrl.sm_bVideo = SiI_RX_VS_PowerDown; + siiRX_PowerDown(ON); + SiI_Ctrl.wVideoTimeOut = 200; +} +/*----------------------------------------------------------------------------- + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ +void siiSetSM_ReqVidInChange(void) +{ + SiI_Ctrl.sm_bVideo = SiI_RX_VS_ReqVidInChange; + SiI_Ctrl.wVideoTimeOut = 64; +} +/*------------------------------------------------------------------------------ + * Function Name: siiMuteVideoAndSetSM_SyncInChange + * Function Description: Mutes Video, change Video state machine to SyncInCange, + * and sets Time after which sync information will be read + * Accepts: none + * Returns: none + * Globals: SiI_Ctrl.sm_bVideo modified + *---------------------------------------------------------------------------- + */ + +void siiMuteVideoAndSetSM_SyncInChange(void) +{ + if (SiI_Ctrl.sm_bVideo != SiI_RX_VS_GlobalPowerDown) { + siiMuteVideo(ON); + siiRX_PowerDown(OFF); + SiI_Ctrl.wVideoTimeOut = 100; + SiI_Ctrl.sm_bVideo = SiI_RX_VS_SyncInChange; + } + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiCheckOverrangeConditions + * Function Description: This function used to check sync overrange conditions + * Accepts: none + * Returns: Error Code + * Globals: SiI_Inf:sm_bVideo modified + *---------------------------------------------------------------------------- + */ +/******************************************************************************* + *->SiI_RX_VS_SyncStable + * Check Overrange Conditions + * -> SiI_RX_VS_ReqVMDetection + * -> SiI_RX_VS_SyncOutOfRange + * + ****************************************************************************** + */ +void CheckOutOfRangeConditions(void) +{ + if (siiCheckOutOfRangeConditions(&SiI_Inf.Sync)) + SiI_Ctrl.sm_bVideo = SiI_RX_VS_SyncOutOfRange; + else { + SiI_Ctrl.sm_bVideo = SiI_RX_VS_ReqVMDetection; + SiI_Ctrl.wVideoTimeOut = 10; + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetPixClock() + * Function Description: This function checks if video resolution detected, + * if it wasn't detected then return Zero + * Accepts: void + * Returns: bPixClock + * Globals: read only; SiI_Ctrl.sm_bVideo + *---------------------------------------------------------------------------- + */ +BYTE siiGetPixClock(void) +{ + BYTE bPixClock; + + if ((SiI_Ctrl.sm_bVideo == SiI_RX_VS_VMDetected) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_VideoOn) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_ReqVideoOn)) { + bPixClock = siiGetPixClockFromTables(SiI_Inf.bVResId); + } else + bPixClock = 0; + return bPixClock; +} +#ifdef SII_NO_RESOLUTION_DETECTION +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: void + * Returns: qResult + * Globals: read only; SiI_Ctrl.sm_bVideo + *---------------------------------------------------------------------------- + */ +BOOL siiCheckIfVideoOutOfRangeOrVMNotDetected(void) +{ + BOOL qResult = FALSE; + + if ((SiI_Ctrl.sm_bVideo == SiI_RX_VS_SyncOutOfRange) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_VMNotDetected)) + qResult = TRUE; + + return qResult; +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + * + * Accepts: void + * Returns: qResult + * Globals: read only; SiI_Ctrl.sm_bVideo + *---------------------------------------------------------------------------- + */ +BOOL siiCheckIfVideoInputResolutionReady(void) +{ + BOOL qResult = FALSE; + + if ((SiI_Ctrl.sm_bVideo == SiI_RX_VS_VMDetected) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_VideoOn) || + (SiI_Ctrl.sm_bVideo == SiI_RX_VS_ReqVideoOn)) + qResult = TRUE; + + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiVideoResolutionDetection + * Function Description: This function is used for Video Resolution detection + * Accepts: none + * Returns: Error Code + * Globals: SiI_Inf:sm_bVideo, bVResId modified + *---------------------------------------------------------------------------- + */ +/******************************************************************************* + *-> SiI_RX_VS_ReqVMDetection + * Video Resolution Detection + * -> SiI_RX_VS_VMDetected + * -> SiI_RX_VS_VMNotDetected ( unknown resolution ) + ****************************************************************************** + */ +static void VideoResolutionDetection(void) +{ + BYTE bSearchResult; + + bSearchResult = siiVideoModeDetection(&SiI_Inf.bVResId, &SiI_Inf.Sync); + if (!bSearchResult) { /* Mode is not detected */ + SiI_Ctrl.sm_bVideo = SiI_RX_VS_VMNotDetected; + /* siiMuteVideo(OFF); //YMA change */ + siiMuteVideo(ON); + } else + SiI_Ctrl.sm_bVideo = SiI_RX_VS_VMDetected; + SiI_Ctrl.wVideoTimeOut = 10; + /* #ifdef SII_DUMP_UART */ + siiPrintVModeParameters(SiI_Inf.bVResId, bSearchResult); + /* #endif */ + +} +/*------------------------------------------------------------------------------ + * Function Name: PowerDownProcessing + * Function Description: + *---------------------------------------------------------------------------- + */ +static void PowerDownProcessing(void) +{ + siiRX_PowerDown(OFF); /* SCDT doesn't work in PD */ + /* Wilma has the SCDT doesn't work in PD bug */ + /* + * if ( siiCheckClockDetect() ){ + * siiMuteVideoAndSetSM_SyncInChange(); + * } + */ + if ((siiCheckSyncDetect()) || + ((SiI_Ctrl.bDevId == RX_SiI9133) && (siiCheckClockDetect()))) + siiMuteVideoAndSetSM_SyncInChange(); + else + siiSetPowerDownModeAndSetSM_PowerDown(); +} + +/*------------------------------------------------------------------------------ + * Function Name: SyncInChangeProcessing + * Function Description: + *---------------------------------------------------------------------------- + */ +static void SyncInChangeProcessing(void) +{ + if (siiCheckSyncDetect()) { + SiI_Ctrl.sm_bVideo = SiI_RX_VS_SyncStable; + SiI_Ctrl.wVideoTimeOut = 10; + siiGetSyncInfo(&SiI_Inf.Sync); +#ifdef SII_BUG_PHOEBE_AUTOSW_BUG + if ((SiI_Ctrl.bDevId == RX_SiI9023) || + (SiI_Ctrl.bDevId == RX_SiI9033)) { + siiSetAutoSWReset(OFF); + siiTurnAudioOffAndSetSM_AudioOff(); + } +#endif + } else { + siiSetSM_ReqPowerDown(); + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetResDepVideoPath + * Function Description: This function is used to set Res Dependent Video path + * Accepts: none + * Returns: Error Code + * Globals: SiI_Inf:sm_bVideo, bVResId modified + *---------------------------------------------------------------------------- + */ +/******************************************************************************* + *-> SiI_RX_VS_VMDetected + * Set Video Dependent Video Path + * -> SiI_RX_VS_VideoOn + * -> SiI_RX_VS_SyncInChange + ******************************************************************************* + */ +static void SetResDepVideoPath(void) +{ + if (!(SiI_Inf.bGlobStatus & SiI_RX_GlobalHDMI_Detected)) { + siiSetAnalogAudioMux(SiI_Ctrl.bVidInChannel); + if (SiI_Inf.AVI.bInputColorSpace != SiI_RX_ICP_RGB) { + SiI_Inf.AVI.bInputColorSpace = SiI_RX_ICP_RGB; + siiSetVideoPathColorSpaceDependent( + SiI_Ctrl.VideoF.bOutputVideoPath, + SiI_Inf.AVI.bInputColorSpace); + /* As color space has changed, it's need + *a call to config. Video Path non res. + *dependent Vid. Path + */ + } + } else + siiSetDigitalAudioMux(); + siiSetVidResDependentVidOutputFormat(SiI_Inf.bVResId, + SiI_Ctrl.VideoF.bOutputVideoPath, SiI_Inf.AVI.bAVI_State); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_ReqVideoOn; + SiI_Ctrl.wVideoTimeOut = 32; + +} +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ +static void CheckIfResUnMuteVideoIfOK(void) +{ + struct SyncInfoType_s SyncInfo; + + /* in case if Pix Replication was changed + * need to check sync info wasn't changed + * res change interrupt is ignorred for this + * state of Video state machine + */ + siiGetSyncInfo(&SyncInfo); + if (siiCompareNewOldSync(&SiI_Inf.Sync, &SyncInfo)) { + siiMuteVideo(OFF); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_VideoOn; + /* TBD: This User call should be removed - + * Needed for Oscar board only + */ + /* InitTX(); */ + } else + siiMuteVideoAndSetSM_SyncInChange(); +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetGlobalVideoMuteAndSM_Video + * Function Description: + *---------------------------------------------------------------------------- + */ + +void siiSetGlobalVideoMuteAndSM_Video(BOOL qOn) +{ + if (qOn) { + siiMuteVideo(ON); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_HoldVideoMute; + } else { + siiMuteVideo(OFF); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_VideoOn; + } + +} +/*------------------------------------------------------------------------------ + * Function Name: + * Function Description: + *---------------------------------------------------------------------------- + */ + +BYTE siiTTVideoHandler(BOOL qTimeOut) +{ + BYTE bECode = FALSE; + + RXEXTDBG("%s: sm_bVideo=%d\n", __func__, SiI_Ctrl.sm_bVideo); + switch (SiI_Ctrl.sm_bVideo) { + case SiI_RX_VS_ReqPowerDown: + if (qTimeOut) { + siiTurnAudioOffAndSetSM_AudioOff(); + siiSetPowerDownModeAndSetSM_PowerDown(); +#ifdef SII_DUMP_UART + printf("\nAudioOff\n"); + printf("PowerDown\n"); +#endif + } + break; + case SiI_RX_VS_PowerDown: + if (qTimeOut) + PowerDownProcessing(); + break; + case SiI_RX_VS_SyncInChange: + if (qTimeOut) + SyncInChangeProcessing(); + break; + case SiI_RX_VS_SyncStable: +#ifdef SII_BUG_PHOEBE_AUTOSW_BUG + if ((SiI_Ctrl.bDevId == RX_SiI9023) || + (SiI_Ctrl.bDevId == RX_SiI9033)) { + siiCheckTransitionToDVIModeAndResetHDMIInfoIfConfirmed + (); + } +#endif + CheckOutOfRangeConditions(); + break; + case SiI_RX_VS_ReqVMDetection: + VideoResolutionDetection(); + break; + case SiI_RX_VS_VMDetected: + SetResDepVideoPath(); + break; + case SiI_RX_VS_ReqVideoOn: + CheckIfResUnMuteVideoIfOK(); + break; + case SiI_RX_VS_ReqVidInChange: + if (qTimeOut) + siiSetVideoInput(SiI_Ctrl.bVidInChannel); + break; + case SiI_RX_VS_ReqGlobalPowerDown: + siiMuteVideo(ON); + siiRX_DisableTMDSCores(); + siiRX_PowerDown(ON); + SiI_Ctrl.sm_bVideo = SiI_RX_VS_GlobalPowerDown; + break; + case SiI_RX_VS_HoldVideoMute: /* do nothing */ + break; + } + return bECode; + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.h new file mode 100644 index 0000000..b0d4ad0 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTVideo.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + + +#ifndef _SII_TTVIDEO_ +#define _SII_TTVIDEO_ +#include "SiITypeDefs.h" + +#define SYNC_CONFIRM_THRESHOLD 3 + +BYTE siiTTVideoHandler(BOOL qTimeOut); +void siiMuteVideoAndSetSM_SyncInChange(void); +BOOL siiSMCheckReqVideoOn(void); +BYTE siiGetPixClock(void); +BOOL siiCheckIfVideoInputResolutionReady(void); +BOOL siiCheckIfVideoOutOfRangeOrVMNotDetected(void); +void siiSetSM_ReqVidInChange(void); +void siiSetSM_ReqGlobalPowerDown(void); +BOOL siiIsVideoOn(void); + +void siiSetGlobalVideoMuteAndSM_Video(BOOL qOn); +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.c new file mode 100644 index 0000000..78be1a0 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiI Timer tasks + * --- + * Module Description: Here timer schedueled tasks will be called + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiITTasks.h" +#include "SiITTVideo.h" +#include "SiITTAudio.h" +#include "SiITTInfoPkts.h" +#include "SiITTHDCP.h" +#include "SiIISR.h" +#include "SiIHDMIRX.h" +#include "SiISysCtrl.h" +#include "SiITrace.h" +/*------------------------------------------------------------------------------ + * Function Name: siiInitACPCheckTimeOut + * Function Description: Intitialize ACP Timeout Check + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiInitACPCheckTimeOut(void) +{ + SiI_Ctrl.bInfoFrameTimeOut = 300; +} + +/*------------------------------------------------------------------------------ + * Function Name: TTSysTasksHandler + * Function Description: This function clears BCH Errors, Polls HDMI Cable + * Status and calls ReInit RX on HDMI Cable Plug In Event + *---------------------------------------------------------------------------- + */ +static void TTSysTasksHandler(void) +{ + SiI_Inf.bHDCPStatus = siiGetHDCPStatus(); + + if (siiRX_CheckCableHPD()) { + if (!(SiI_Inf.bGlobStatus & SiI_RX_Global_OldHotPlugDetect)) { + SiI_Inf.bGlobStatus |= SiI_RX_Global_OldHotPlugDetect; + siiReInitRX(); + + /* YMA set the terminaion to 3k ohm first and then + *after HPD, change it back to normal + */ + if (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) { + /* YMA others use default */ + if (SiI_Ctrl.bVidInChannel == SiI_RX_VInCh1) + siiSetNormalTerminationValueCh1(ON); + else + siiSetNormalTerminationValueCh2(ON); + } + } + SiI_Inf.bGlobStatus |= SiI_RX_Global_HotPlugDetect; + } else { + if (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) { + /* YMA others use default */ + if (SiI_Ctrl.bVidInChannel == SiI_RX_VInCh1) + siiSetNormalTerminationValueCh1(OFF); + else + siiSetNormalTerminationValueCh2(OFF); + } + + SiI_Inf.bGlobStatus &= (~SiI_RX_Global_HotPlugDetect); + SiI_Inf.bGlobStatus &= (~SiI_RX_Global_OldHotPlugDetect); + } +} +/*------------------------------------------------------------------------------ + * Function Name: CheckAudioTimeOut() + * Function Description: + *---------------------------------------------------------------------------- + */ +BOOL CheckAudioTimeOut(WORD wTimeDiff) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.wAudioTimeOut) { + if (SiI_Ctrl.wAudioTimeOut >= wTimeDiff) { + SiI_Ctrl.wAudioTimeOut -= wTimeDiff; + if (!SiI_Ctrl.wAudioTimeOut) + qResult = TRUE; + } else { + qResult = TRUE; + SiI_Ctrl.wAudioTimeOut = 0; + } + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: CheckVideoTimeOut() + * Function Description: + *---------------------------------------------------------------------------- + */ +BOOL CheckVideoTimeOut(WORD wTimeDiff) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.wVideoTimeOut) { + if (SiI_Ctrl.wVideoTimeOut >= wTimeDiff) { + SiI_Ctrl.wVideoTimeOut -= wTimeDiff; + if (!SiI_Ctrl.wVideoTimeOut) + qResult = TRUE; + } else { + qResult = TRUE; + SiI_Ctrl.wVideoTimeOut = 0; + } + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: CheckInfoFrameTimeOut() + * Function Description: + *---------------------------------------------------------------------------- + */ +BOOL CheckInfoFrameTimeOut(WORD wTimeDiff) +{ + BOOL qResult = FALSE; + + if (SiI_Ctrl.bInfoFrameTimeOut) { + if ((WORD)SiI_Ctrl.bInfoFrameTimeOut >= wTimeDiff) { + SiI_Ctrl.bInfoFrameTimeOut -= wTimeDiff; + if (!SiI_Ctrl.bInfoFrameTimeOut) + qResult = TRUE; + } else { + qResult = TRUE; + } + + } + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiTimerTasksHandler + * Function Description: + *---------------------------------------------------------------------------- + */ +BYTE siiTimerTasksHandler(BYTE bSlotTime) +{ + static BYTE bTaskSlot = SiI_RX_TT_Video; + BYTE bECode = FALSE; + BOOL qAudioTimeOut = FALSE; + BOOL qVideoTimeOut = FALSE; + + if (CheckVideoTimeOut(bSlotTime)) { + qVideoTimeOut = TRUE; + siiTTVideoHandler(qVideoTimeOut); + } + if (SiI_Inf.bGlobStatus & SiI_RX_GlobalHDMI_Detected) { + if (CheckAudioTimeOut(bSlotTime)) { + qAudioTimeOut = TRUE; + bECode = siiTTAudioHandler(qAudioTimeOut); + if (bECode == SiI_EC_FIFO_UnderRunStuck) + siiReInitRX(); + } + if (CheckInfoFrameTimeOut(bSlotTime)) { + siiInitACPCheckTimeOut(); + siiTTInfoFrameHandler(); + } + } + + switch (bTaskSlot++) { + case SiI_RX_TT_Video: + siiTTVideoHandler(0); + break; + case SiI_RX_TT_Audio: + siiTTAudioHandler(0); + break; + case SiI_RX_TT_InfoFrmPkt: + break; + case SiI_RX_TT_Sys: + TTSysTasksHandler(); + break; + } + if (bTaskSlot == SiI_RX_TT_Last) + bTaskSlot = SiI_RX_TT_Video; + + return bECode; +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.h new file mode 100644 index 0000000..ec2a6a3 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITTasks.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _SII_TTASKS_ +#define _SII_TTASKS_ +enum SiI_RX_TTasks { + + SiI_RX_TT_Video, + SiI_RX_TT_Audio, + SiI_RX_TT_InfoFrmPkt, + SiI_RX_TT_Sys, + SiI_RX_TT_Last +}; + +BYTE siiTimerTasksHandler(BYTE bSlotTime); +void siiInitACPCheckTimeOut(void); +#endif + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.c new file mode 100644 index 0000000..32291da --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.c @@ -0,0 +1,120 @@ +/*------------------------------------------------------------------------------ + * Module Name: Trace + * --- + * Module Description: Used to provide debugging Information + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "SiITrace.h" +#include "SiIGlob.h" + +/*----------------------------------------------------------------------------- + * Function Name: siiErrorHandler + * Function Description: Fill in buffer error structure + * Accepts: none + * Returns: none + * Globals: structure SiI_Inf.Error + *---------------------------------------------------------------------------- + */ +void siiErrorHandler(BYTE bErrorCode) +{ + if (bErrorCode) { + SiI_bECode[SiI_bECode[0] + 1] = bErrorCode; + if (SiI_bECode[0] < ERR_BUF_SIZE) + SiI_bECode[0]++; + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiWarningHandler + * Function Description: Fill in buffer with warning messages + * Accepts: none + * Returns: none + * Globals: SiI_bWCode[16] + *---------------------------------------------------------------------------- + */ +void siiWarningHandler(BYTE bWrnCode) +{ + if (bWrnCode) { + SiI_bWCode[SiI_bWCode[0] + 1] = bWrnCode; + if (SiI_bWCode[0] < (WRN_BUF_SIZE - 1)) + SiI_bWCode[0]++; + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiResetErrorsAndWarnings + * Function Description: Fill in buffer with warning messages + * Accepts: none + * Returns: none + * Globals: SiI_bWCode[0] + *---------------------------------------------------------------------------- + */ +void siiResetErrorsAndWarnings(void) +{ + BYTE i; + + for (i = 0; i < WRN_BUF_SIZE; i++) + SiI_bWCode[i] = 0; + for (i = 0; i < ERR_BUF_SIZE; i++) + SiI_bECode[i] = 0; + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetErrorsWarnings + * Function Description: Fill in buffer error structure + * Accepts: none + * Returns: none + * Globals: structure SiI_Inf.Error + *---------------------------------------------------------------------------- + */ +BYTE siiGetErrorsWarnings(void) +{ + return (SiI_bECode[0] << 4) | SiI_bWCode[0]; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetErrorsData + * Function Description: + * Accepts: pbErrData + * Returns: number of errors + * Globals: SiI_bWCode + *---------------------------------------------------------------------------- + */ +BYTE siiGetErrorsData(BYTE *pbErrData) +{ + BYTE i; + + for (i = 0; i < SiI_bECode[0]; i++) + pbErrData[i] = SiI_bECode[1 + i]; + + return SiI_bECode[0]; + +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetWarningData + * Function Description: + * Accepts: pbWrnData + * Returns: number of warnings + * Globals: SiI_bECode + *---------------------------------------------------------------------------- + */ + +BYTE siiGetWarningData(BYTE *pbWrnData) +{ + BYTE i; + + for (i = 0; i < SiI_bWCode[0]; i++) + pbWrnData[i] = SiI_bWCode[1 + i]; + + return SiI_bWCode[0]; +} + + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.h new file mode 100644 index 0000000..62fbc96 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITrace.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _TRACE_ +#define _TRACE_ + +#include "SiITypeDefs.h" + +#define siiGetNumberOfWarnings() SiI_bWCode[0] + +void siiWarningHandler(BYTE bWrnCode); +void siiErrorHandler(BYTE bErrorCode); +void siiResetErrorsAndWarnings(void); +BYTE siiGetErrorsWarnings(void); +BYTE siiGetErrorsData(BYTE *pbErrData); +BYTE siiGetWarningData(BYTE *pbWrnData); +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITypeDefs.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITypeDefs.h new file mode 100644 index 0000000..38545c9 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiITypeDefs.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiICmplDefs.h" +#ifndef _TYPEDEFS_ +#define _TYPEDEFS_ + + +#define BYTE unsigned char +#define U8BIT unsigned char +#define WORD unsigned short +#define U16BIT unsigned short +#define U32BIT unsigned int +#define DWORD unsigned int + +#ifdef _8051_ /* for 8051 family of microcontrollers */ + +#define ROM code /* 8051 type of ROM memory */ +#define IRAM idata /* 8051 type of RAM memory */ + +#define BOOL bit + +#else + +#define BOOL unsigned char + +#define ROM +#define IRAM + +#endif + +#define FALSE 0 +#define TRUE 1 + +#define ABSENT 0 +#define PRESENT 1 + +/*#define USE_InternEEPROM // enable InternEEPROM */ + +#endif + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.c new file mode 100644 index 0000000..9a95933 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.c @@ -0,0 +1,246 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIVRTables.c + * + * Module Description: contains a Video Resolution Tables which used + * for Video Resolution Detections + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIVRTables.h" + +#define WIDE_PULSE 0x80 + + +/*----------------------------------------------------------------------------- + * This table is used for detection of active video mode, + * first part of table is CEA861B + * second part of it for PC modes + *---------------------------------------------------------------------------- + */ +ROM const struct VModeInfoType_s VModeTables[NMODES] = { + /*{{M.Id SubM},{PixClk},{RefTVPolHPol,RefrRt},{HTot,VTot},{HRes VRes}}*/ + {{ 1, 0, NSM}, 25, {ProgrVNegHNeg, 6000, { 800, 525},}, + { 640, 480}, 0}, /* 0 Format 1 // 640x480p@60(59,94) */ + {{ 2, 3, NSM}, 27, {ProgrVNegHNeg, 6000, { 858, 525},}, + { 720, 480}, 0}, /* 1 Format 2,3 // 720x480p@60(59,94) */ + {{ 4, 0, NSM}, 74, {ProgrVPosHPos, 6000, {1650, 750},}, + {1280, 720}, 0}, /* 2 Format 4 // 1280x720p@60(59,94) */ + {{ 5, 0, NSM}, 74, {InterlaceVPosHPos, 6000, {2200, 562},}, + {1920, 1080}, 0}, /* 3 Format 5 // 1920x1080i@60(59,94) */ + {{ 6, 7, NSM}, 27, {InterlaceVNegHNeg, 6000, {1716, 262},}, + {1440, 480}, 1}, /* 4 Format 6,7 // 720(1440)x480i@60(59,94) */ + {{ 8, 9, 1}, 27, {ProgrVNegHNeg, 6000, {1716, 262},}, + {1440, 240}, 1}, /* 5 Format 8,9 // 720(1440)x240p@60(59,94) */ + {{ 8, 9, 2}, 27, {ProgrVNegHNeg, 6000, {1716, 263},}, + {1440, 240}, 1}, /* 6 Format 8,9 // 720(1440)x240p@60(59,94) */ + {{10, 11, NSM}, 54, {InterlaceVNegHNeg, 6000, {3432, 262},}, + {2880, 480}, 1}, /* 7 Format 10,11 // (2880)x480i@60(59,94) */ + {{12, 13, 1}, 54, {ProgrVNegHNeg, 6000, {3432, 262},}, + {2880, 240}, 3}, /* 8 Format 12,13 // (2880)x240p@60(59,94) */ + {{12, 13, 2}, 54, {ProgrVNegHNeg, 6000, {3432, 263},}, + {2880, 240}, 3}, /* 9 Format 12,13 // (2880)x240p@60(59,94) */ + {{14, 15, NSM}, 54, {ProgrVNegHNeg, 6000, {1716, 525},}, + {1440, 480}, 0}, /* 10 Format 14,15 // 1440x480p@60 (59,94) */ + {{16, 0, NSM}, 146, {ProgrVPosHPos, 6000, {2200, 1125},}, + {1920, 1080}, 0}, /* 11 Format 16 // 1920x1080p@60 (59,94) */ + {{17, 18, NSM}, 27, {ProgrVNegHNeg, 5000, { 864, 625},}, + { 720, 576}, 0}, /* 12 Format 17,18 // 720x576p@50 */ + {{19, 0, NSM}, 74, {ProgrVPosHPos, 5000, {1980, 750},}, + {1280, 720}, 0}, /* 13 Format 19 // 1280x720p@50 */ + {{20, 0, NSM}, 74, {InterlaceVPosHPos, 5000, {2640, 562},}, + {1920, 1080}, 0}, /* 14 Format 20 // 1920x1080i@50 */ + {{21, 22, NSM}, 27, {InterlaceVNegHNeg, 5000, {1728, 312},}, + {1440, 576}, 1}, /* 15 Format 21,22 // 720(1440)x576i@50 */ + {{23, 24, 1}, 27, {ProgrVNegHNeg, 5000, {1728, 312},}, + {1440, 288}, 1}, /* 16 Format 23,24 // 720(1440)x288p@50 */ + {{23, 24, 2}, 27, {ProgrVNegHNeg, 5000, {1728, 313},}, + {1440, 288}, 1}, /* 17 Format 23,24 // 720(1440)x288p@50 */ + {{23, 24, 3}, 27, {ProgrVNegHNeg, 5000, {1728, 314},}, + {1440, 288}, 1}, /* 18 Format 23,24 // 720(1440)x288p@50 */ + {{25, 26, NSM}, 54, {InterlaceVNegHNeg, 5000, {3456, 312},}, + {2880, 576}, 1}, /* 19 Format 25,26 // (2880)x576i@50 */ + {{27, 28, 1}, 54, {ProgrVNegHNeg, 5000, {3456, 312},}, + {2880, 288}, 3}, /* 20 Format 27,28 // (2880)x288p@50 */ + {{27, 28, 2}, 54, {ProgrVNegHNeg, 5000, {3456, 313},}, + {2880, 288}, 3}, /* 21 Format 27,28 // (2880)x288p@50 */ + {{27, 28, 3}, 54, {ProgrVNegHNeg, 5000, {3456, 314},}, + {2880, 288}, 3}, /* 22 Format 27,28 // (2880)x288p@50 */ + {{29, 30, NSM}, 54, {ProgrVPosHNeg, 5000, {1728, 625},}, + {1440, 576}, 0}, /* 23 Format 29,30 // 1440x576p@50 */ + {{31, 0, NSM}, 148, {ProgrVPosHPos, 5000, {2640, 1125},}, + {1920, 1080}, 0}, /* 24 Format 31 // 1920x1080p@50 */ + {{32, 0, NSM}, 74, {ProgrVPosHPos, 2400, {2750, 1125},}, + {1920, 1080}, 0}, /* 25 Format 32 // 1920x1080p@24 */ + {{33, 0, NSM}, 74, {ProgrVPosHPos, 2500, {2640, 1125},}, + {1920, 1080}, 0}, /* 26 Format 33 // 1920x1080p@25 */ + {{34, 0, NSM}, 74, {ProgrVPosHPos, 3000, {2200, 1125},}, + {1920, 1080}, 0}, /* 27 Format 34 // 1920x1080p@30 */ + +#ifdef SII_861C_MODES /* 15 enteries */ + {{35, 36, NSM}, 108, {ProgrVNegHNeg, 6000, {3432, 525},}, + {2880, 480}, 1}, /* 28 Format 35,36 2280(1440,720)x480p@60 */ + {{37, 38, NSM}, 108, {ProgrVNegHNeg, 5000, {3456, 625},}, + {2880, 576}, 1}, /* 29 Format 37,38 2280(1440,720)x525p@50 */ + {{39, 0, NSM}, 72, {InterlaceVNegHPos, 5000, {2304, 625},}, + {1920, 1080}, 0}, /* 30 Format 39 1920 x 1080i @ 50 */ + {{40, 0, NSM}, 148, {InterlaceVPosHPos, 10000, {2640, 562},}, + {1920, 1080}, 0}, /* 31 Format 40 1920 x 1080i @ 100 */ + {{41, 0, NSM}, 148, {ProgrVPosHPos, 10000, {1980, 750},}, + {1280, 720}, 0}, /* 32 Format 41 1280 x 720p @ 100 */ + {{42, 43, NSM}, 54, {ProgrVNegHNeg, 10000, { 864, 625},}, + { 720, 576}, 0}, /* 33 Format 42,43 720 x 576p @ 100 */ + {{44, 45, NSM}, 54, {ProgrVNegHNeg, 10000, {1728, 312},}, + { 720, 576}, 1}, /* 34 Format 44,45 720 x 576i @ 100 */ + {{46, 0, NSM}, 148, {InterlaceVPosHPos, 12000, {2200, 562},}, + {1920, 1080}, 0}, /* 35 Format 46 1920 x 1080i @ 120 */ + {{47, 0, NSM}, 148, {ProgrVPosHPos, 12000, {1650, 750},}, + {1280, 720}, 0}, /* 36 Format 47 1280 x 720p @ 120 */ + {{48, 49, NSM}, 54, {ProgrVNegHNeg, 12000, { 858, 525},}, + { 720, 480}, 0}, /* 37 Format 48,49 720 x 480p @ 120 */ + {{50, 51, NSM}, 54, {InterlaceVNegHNeg, 12000, {1716, 262},}, + { 720, 480}, 1}, /* 38 Format 50,51 720 x 480i @ 120 */ + {{52, 53, NSM}, 108, {ProgrVPosHPos, 20000, { 864, 625},}, + { 720, 576}, 0}, /* 39 Format 52,53 720 x 576p @ 200 */ + {{54, 55, NSM}, 108, {InterlaceVNegHNeg, 20000, {1728, 312},}, + { 720, 576}, 0}, /* 40 Format 54,55 720 x 576i @ 200 */ + {{56, 57, NSM}, 108, {ProgrVNegHNeg, 24000, { 858, 525},}, + { 720, 480}, 0}, /* 41 Format 56,57 720 x 480p @ 240 */ + {{58, 59, NSM}, 108, {InterlaceVNegHNeg, 24000, {1716, 262},}, + { 720, 480}, 1}, /* 42 Format 58,59 720 x 480i @ 240 */ + +#endif + +/* {{M.Id SubM},{PixClk},{RefTVPolHPol, RefrRt},{HTot,VTot},{HRes VRes}} */ +#ifdef SII_PCMODES + {{PC_BASE, 0, NSM}, 25, {ProgrVNegHPos, 7009, { 800, 449},}, + { 640, 350}, 0}, /* 640 x 350 @ 70.09 */ + {{PC_BASE + 1, 0, NSM}, 31, {ProgrVNegHPos, 8508, { 832, 445},}, + { 640, 350}, 0}, /* 640 x 350 @ 85.08 */ + {{PC_BASE + 2, 0, NSM}, 25, {ProgrVPosHNeg, 7009, { 800, 449},}, + { 640, 400}, 0}, /* 640 x 400 @ 70.09 */ + {{PC_BASE + 3, 0, NSM}, 31, {ProgrVPosHNeg, 8508, { 832, 445},}, + { 640, 400}, 0}, /* 640 x 400 @ 85.08 */ + {{PC_BASE + 4, 0, NSM}, 28, {ProgrVPosHNeg, 7008, { 900, 449},}, + { 720, 400}, 0}, /* 720 x 400 @ 70.08 */ + {{PC_BASE + 5, 0, NSM}, 35, {ProgrVPosHNeg, 8504, { 936, 446},}, + { 720, 400}, 0}, /* 720 x 400 @ 85.04 */ + {{PC_BASE + 6, 0, NSM}, 25, {ProgrVNegHNeg, 5994, { 800, 525},}, + { 640, 480}, 0}, /* 640 x 480 @ 59.94 */ + {{PC_BASE + 7, 0, NSM}, 30, {ProgrVNegHNeg, 6667, { 864, 525},}, + { 640, 480}, 0}, /* 640 x 480 @ 66.67 */ + {{PC_BASE + 8, 0, NSM}, 31, {ProgrVNegHNeg, 7280, { 832, 520},}, + { 640, 480}, 0}, /* 640 x 480 @ 72.80 */ + {{PC_BASE + 9, 0, NSM}, 31, {ProgrVNegHNeg, 7500, { 840, 500},}, + { 640, 480}, 0}, /* 640 x 480 @ 75.00 */ + {{PC_BASE + 10, 0, NSM}, 36, {ProgrVNegHNeg, 8500, { 832, 509},}, + { 640, 480}, 0}, /* 640 x 480 @ 85.00 */ + {{PC_BASE + 11, 0, NSM}, 38, {ProgrVNegHNeg, 9003, { 832, 510},}, + { 640, 480}, 0}, /* 640 x 480 @ 90.03 */ + {{PC_BASE + 12, 0, NSM}, 45, {ProgrVNegHNeg, 10004, { 864, 530},}, + { 640, 480}, 0}, /* 640 x 480 @ 100.04 */ + {{PC_BASE + 13, 0, NSM}, 55, {ProgrVNegHNeg, 12000, { 864, 534},}, + { 640, 480}, 0}, /* 640 x 480 @ 120 */ + {{PC_BASE + 14, 0, NSM}, 36, {ProgrVPosHPos, 5625, {1024, 625},}, + { 800, 600}, 0}, /* 800 x 600 @ 56.25 */ + {{PC_BASE + 15, 0, NSM}, 40, {ProgrVPosHPos, 6031, {1056, 628},}, + { 800, 600}, 0}, /* 800 x 600 @ 60.31 */ + {{PC_BASE + 16, 0, NSM}, 50, {ProgrVPosHPos, 7219, {1040, 666},}, + { 800, 600}, 0}, /* 800 x 600 @ 72.19 */ + {{PC_BASE + 17, 0, NSM}, 50, {ProgrVPosHPos, 7500, {1056, 625},}, + { 800, 600}, 0}, /* 800 x 600 @ 75 */ + {{PC_BASE + 18, 0, NSM}, 56, {ProgrVPosHPos, 8506, {1048, 631},}, + { 800, 600}, 0}, /* 800 x 600 @ 85.06 */ + {{PC_BASE + 19, 0, NSM}, 57, {ProgrVNegHNeg, 9000, {1024, 622},}, + { 800, 600}, 0}, /* 800 x 600 @ 90 */ + {{PC_BASE + 20, 0, NSM}, 70, {ProgrVNegHNeg, 10000, {1088, 640},}, + { 800, 600}, 0}, /* 800 x 600 @ 100 */ + {{PC_BASE + 21, 0, NSM}, 57, {ProgrVNegHNeg, 7455, {1152, 667},}, + { 832, 624}, 0}, /* 832 x 624 @ 75 */ + {{PC_BASE + 22, 0, NSM}, 45, {InterlaceVPosHPos, 4348, {1264, 817},}, + {1024, 768}, 0}, /* 1024 x 768 @ 43.48 interlaced */ + {{PC_BASE + 23, 0, NSM}, 65, {ProgrVNegHNeg, 6000, {1344, 806},}, + {1024, 768}, 0}, /* 1024 x 768 @ 60 */ + {{PC_BASE + 24, 0, NSM}, 75, {ProgrVNegHNeg, 7007, {1328, 806},}, + {1024, 768}, 0}, /* 1024 x 768 @ 70.07 */ + {{PC_BASE + 25, 0, NSM}, 79, {ProgrVPosHPos, 7503, {1312, 800},}, + {1024, 768}, 0}, /* 1024 x 768 @ 75.03 */ + {{PC_BASE + 26, 0, NSM}, 94, {ProgrVPosHPos, 8500, {1376, 808},}, + {1024, 768}, 0}, /* 1024 x 768 @ 85 */ + {{PC_BASE + 27, 0, NSM}, 80, {ProgrVPosHPos, 6005, {1472, 905},}, + {1152, 864}, 0}, /* 1152 x 864 @ 60.05 */ + {{PC_BASE + 28, 0, NSM}, 94, {ProgrVPosHPos, 7002, {1472, 914},}, + {1152, 864}, 0}, /* 1152 x 864 @ 70.02 */ + {{PC_BASE + 29, 0, NSM}, 108, {ProgrVPosHPos, 7500, {1600, 900},}, + {1152, 864}, 0}, /* 1152 x 864 @ 75 */ + {{PC_BASE + 30, 0, NSM}, 108, {ProgrVPosHPos, 6001, {1696, 1066},}, + {1280, 1024}, 0}, /* 1280 x 1024 @ 60.01 */ + {{PC_BASE + 31, 0, NSM}, 108, {ProgrVPosHPos, 6002, {1688, 1066},}, + {1280, 1024}, 0}, /* 1280 x 1024 @ 60.02 */ + {{PC_BASE + 32, 0, NSM}, 135, {ProgrVPosHPos, 7502, {1688, 1066},}, + {1280, 1024}, 0}, /* 1280 x 1024 @ 75.02 */ + {{PC_BASE + 33, 0, NSM}, 157, {ProgrVPosHPos, 8502, {1728, 1072},}, + {1280, 1024}, 0}, /* 1280 x 1024 @ 85.02 */ + {{PC_BASE + 34, 0, NSM}, 135, {InterlaceVPosHPos, 4804, {2160, 1301},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 48.04 interlaced */ + {{PC_BASE + 35, 0, NSM}, 158, {ProgrVPosHPos, 6000, {2112, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 60 */ + {{PC_BASE + 36, 0, NSM}, 121, {ProgrVPosHPos, 8506, {1568, 911},}, + {1152, 864}, 0}, /* 1152 x 864 @ 85 */ + {{PC_BASE + 37, 0, NSM}, 100, {ProgrVNegHNeg, 7506, {1456, 915},}, + {1152, 870}, 0}, /* 1152 x 870 @ 75.06 */ + {{PC_BASE + 38, 0, NSM}, 108, {ProgrVPosHPos, 6000, {1800, 1000},}, + {1280, 960}, 0}, /* 1280 x 960 @ 60 */ + {{PC_BASE + 39, 0, NSM}, 129, {ProgrVPosHPos, 7500, {1728, 1000},}, + {1280, 960}, 0}, /* 1280 x 960 @ 75 */ + {{PC_BASE + 40, 0, NSM}, 148, {ProgrVPosHPos, 8500, {1728, 1011},}, + {1280, 960}, 0}, /* 1280 x 960 @ 85 */ + {{PC_BASE + 41, 0, NSM}, 78, {InterlaceVPosHPos, 4344, {1696, 1069},}, + {1280, 1024}, 0}, /* 1280 x 1024 @ 43.44 interlaced */ + {{PC_BASE + 42, 0, NSM}, 162, {ProgrVPosHPos, 6000, {2160, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 60 */ + {{PC_BASE + 43, 0, NSM}, 173, {ProgrVPosHPos, 6553, {2112, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 65.53 */ + {{PC_BASE + 44, 0, NSM}, 175, {ProgrVPosHPos, 6500, {2154, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 65 */ + {{PC_BASE + 45, 0, NSM}, 185, {ProgrVPosHPos, 7000, {2160, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 70 */ + {{PC_BASE + 46, 0, NSM}, 202, {ProgrVPosHPos, 7500, {2160, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 75 */ + {{PC_BASE + 47, 0, NSM}, 216, {ProgrVPosHPos, 8000, {2160, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 80 */ + {{PC_BASE + 48, 0, NSM}, 229, {ProgrVPosHPos, 8500, {2160, 1250},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 85 */ + {{PC_BASE + 49, 0, NSM}, 232, {ProgrVPosHPos, 8500, {2176, 1258},}, + {1600, 1200}, 0}, /* 1600 x 1200 @ 85 */ + + /* Wide resolutions */ + + {{PC_BASE + 50, 0, NSM}, 33, {ProgrVPosHPos, 6000, { 517, 1235},}, + { 848, 480}, 0}, /* 848 x 480 WVGA */ + {{PC_BASE + 51, 0, NSM}, 68, {ProgrVNegHPos, 6000, {1440, 790},}, + {1280, 768}, 0}, /* 1280 x 768 WXGA reduced blanking */ + {{PC_BASE + 52, 0, NSM}, 85, {ProgrVPosHPos, 6000, {1792, 795},}, + {1360, 768}, 0}, /* 1360 x 768 WXGA reduced blanking */ + {{PC_BASE + 53, 0, NSM}, 154, {ProgrVNegHPos, 6000, {2080, 1235},}, + {1920, 1200}, 0}, /* 1920 x 1200 WUXGA reduced blanking */ + +#endif +}; + +/*----------------------------------------------------------------------------- + * This tables are used for programming Sync on Y(Green) for interlace modes + *---------------------------------------------------------------------------- + */ +ROM const struct InterlaceCSyncType_s InterlaceCSync[3] = { + {507, 6, 6, 6, 0}, /* 480i */ + {610, 5, 5, 5, 0}, /* 576i */ + {1113, 0, 10, 2 | WIDE_PULSE, 0}, /* 1080i */ +}; diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.h new file mode 100644 index 0000000..49d50bf --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVRTables.h @@ -0,0 +1,14 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIVidRes.h" + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.c new file mode 100644 index 0000000..0cbc09f --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.c @@ -0,0 +1,682 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiIVidF ( Video Format ) + * --- + * Module Description: Function of this module are used for setting up output + * format of receiver + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIVidF.h" +#include "SiIRXDefs.h" +#include "SiIRXAPIDefs.h" +#include "SiIRXIO.h" +#include "SiIGlob.h" +#include "SiIVidRes.h" +#include "SiIHDMIRX.h" +#include "SiITrace.h" +#include "../hdmirx_ext_drv.h" +/*------------------------------------------------------------------------------ + * Function Name: siiGetVideoFormatData(...) + * Function Description: This function reads video format data from + * control registers + * + * Accepts: pointer on Video Format Data + * Returns: pointer on Video Format Data + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetVideoFormatData(BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; + + siiReadBlockHDMIRXP0(RX_VID_FORMAT_BASE_ADDR, 3, pbVidFormatData); + return bECode; +} +/*----------------------------------------------------------------------------- + * Function Name: siiSetVideoFormatData(...) + * Function Description: This function writes video format data into + * control registers + * + * Accepts: pointer on Video Format Data + * Returns: pointer on Video Format Data + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiSetVideoFormatData(BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; + + siiWriteBlockHDMIRXP0(RX_VID_FORMAT_BASE_ADDR, 3, pbVidFormatData); + return bECode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetVideoPathColorSpaceDependent + * Function Description: + * + * Accepts: + * Returns: + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetVideoPathColorSpaceDependent(BYTE bVideoPath, BYTE bInputColorSpace) +{ + BYTE bVidFormatData[3]; + + siiGetVideoFormatData(bVidFormatData); + siiPrepVideoPathSelect(bVideoPath, bInputColorSpace, bVidFormatData); + siiSetVideoFormatData(bVidFormatData); + +} + +/*------------------------------------------------------------------------------ + * Function Name: Check if Video DAC capable + * Function Description: + *---------------------------------------------------------------------------- + */ +BOOL CheckVideoDAC_Cap(void) +{ + BOOL qVidedDACCap = FALSE; + + if ((SiI_Ctrl.bDevId == RX_SiI9021) || (SiI_Ctrl.bDevId == RX_SiI9031)) + qVidedDACCap = TRUE; + return qVidedDACCap; + +} +/*------------------------------------------------------------------------------ + * Function Name: CheckVidPathForDevCap + * Function Description: + *---------------------------------------------------------------------------- + */ +static void CheckVidPathForDevCap(BYTE bVideoPath) +{ + BYTE bWCode = FALSE; + + switch (bVideoPath) { + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr444_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr422_16B_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr422_20B_2PixClk: /* SiI9011 */ + if (SiI_Ctrl.bDevId != RX_SiI9011) + bWCode = SiI_WC_ChipNoCap; + break; + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + case SiI_RX_P_YCbCr444_48B: /* SiI9021/31 */ + if (SiI_Ctrl.bDevId == RX_SiI9011) + bWCode = SiI_WC_ChipNoCap; + } + siiWarningHandler(bWCode); +} +/*------------------------------------------------------------------------------ + * Function Name: PrepVideoPathCSCAnalogDAC + * Function Description: This function sets type of Video DAC (RGB vs. YCbCr) + *---------------------------------------------------------------------------- + */ +static void PrepVideoPathCSCAnalogDAC(BYTE bVideoPath, + BYTE *pbVideoOutputFormat) +{ + pbVideoOutputFormat[1] &= (~RX_BIT_RGBA_OUT); + pbVideoOutputFormat[2] |= RX_BIT_EN_INS_CSYNC; + switch (bVideoPath) { + case SiI_RX_P_RGB: /* Clear YCbCr Converter, DownScale, UpScale */ + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + pbVideoOutputFormat[1] |= RX_BIT_RGBA_OUT; + break; + } + +} +/******************************************************************************* + *Transmitted color Space is ActiveColorSpace + * + *InputColorSpace == SiI_RX_ICP_RGB | InputColorSpace == SiI_RX_ICP_YCbCr444 | + * InputColorSpace == SiI_RX_ICP_YCbCr422 + * + *In Out [4A:2]VID_M [4A:1]VID_M [4A:3]VID_M [49:2]VID_M2 [49:0]VID_M2 + *Color Color UpScale Bit DownScale Bit RGB->YCbCr YCbCr->RGB RGBAout + *Space Space 422->444 444->422 + * + *RGB RGB 0 0 0 0 1 + * 444 0 0 1 0 0 + * 422 0 1 1 0 0 + * + *444 RGB 0 0 0 1 1 + * 444 0 0 0 0 0 + * 422 0 1 0 0 0 + * + *422 RGB 1 0 0 1 1 + * 444 1 0 0 0 0 + * 422 0 0 0 0 0 + ****************************************************************************** + */ +/*------------------------------------------------------------------------------ + * Function Name: PrepVideoPathForRGBInput() + * Function Description: Preparing Video Path's bits of Video Output Format + * structure for RGB Input Color Space + * function sets Color Spase converters and Up or Down Sampling + *---------------------------------------------------------------------------- + */ +static void PrepVideoPathForRGBInput(BYTE bVideoPath, BYTE *pbVideoOutputFormat) +{ +/* pbVideoOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + + pbVideoOutputFormat[2] &= (~(RX_BIT_444to422 | RX_BIT_422to444 | + RX_BIT_DITHER | RX_BIT_MUX_YC | RX_BIT_RGBToYCbCr)); + pbVideoOutputFormat[1] &= (~RX_BIT_YCbCrToRGB); + + pbVideoOutputFormat[0] &= (~RX_BIT_EXT_BIT_MODE); + + switch (bVideoPath) { + case SiI_RX_P_RGB: /* Clear YCbCr Converter, DownScale, UpScale */ + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + break; + case SiI_RX_P_YCbCr444: /* Set YCbCr Converter */ + case SiI_RX_P_YCbCr444_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr444_48B: /* SiI9021/31 */ + pbVideoOutputFormat[2] |= RX_BIT_RGBToYCbCr; + break; + /* Set YCbCr Converter, set DownScale + * 4:2:2 mode is used with digital output only + */ + case SiI_RX_P_YCbCr422_MUX8B: + /* YCbCr 422 muxed 8 bit, used with digital output only */ + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422 | + RX_BIT_MUX_YC | RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_MUX10B: + /* YCbCr 422 muxed 10 bit, used with digital output only */ + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422 | + RX_BIT_MUX_YC); + break; + case SiI_RX_P_YCbCr422_16B: + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422 | + RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422: + case SiI_RX_P_YCbCr422_20B: + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422); + break; + case SiI_RX_P_YCbCr422_16B_2PixClk: /* SiI9011 */ + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422 | + RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_20B_2PixClk: /* SiI9011 */ + pbVideoOutputFormat[2] |= (RX_BIT_RGBToYCbCr | RX_BIT_444to422); + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: PrepVideoPathForYCbCr422Input() + * Function Description: Preparing Video Path for YCbCr 422 Input Color Space + *---------------------------------------------------------------------------- + */ +static void PrepVideoPathForYCbCr422Input(BYTE bVideoPath, + BYTE *pbVideoOutputFormat) +{ +/* pbVideoOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + pbVideoOutputFormat[2] &= (~(RX_BIT_444to422 | RX_BIT_422to444 | + RX_BIT_DITHER | RX_BIT_MUX_YC | RX_BIT_RGBToYCbCr)); + pbVideoOutputFormat[1] &= (~RX_BIT_YCbCrToRGB); + + /* YMA changed as JAPAN customer reported */ + /* pbVideoOutputFormat[0]&=( ~RX_BIT_EXT_BIT_MODE ); */ + pbVideoOutputFormat[0] |= RX_BIT_EXT_BIT_MODE; + + switch (bVideoPath) { + /* Clear YCbCr Converter, DownScale, UpScale */ + case SiI_RX_P_RGB: + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + pbVideoOutputFormat[2] |= RX_BIT_422to444; + pbVideoOutputFormat[1] |= RX_BIT_YCbCrToRGB; + break; + /* Set YCbCr Converter, */ + case SiI_RX_P_YCbCr444: + case SiI_RX_P_YCbCr444_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr444_48B: /* SiI9021/31 */ + pbVideoOutputFormat[2] |= RX_BIT_422to444; + break; + /* Set YCbCr Converter, set DownScale + * 4:2:2 mode is used with digital output only + */ + case SiI_RX_P_YCbCr422_MUX8B: + /* YCbCr 422 muxed 8 bit, used with digital output only */ + pbVideoOutputFormat[1] |= (RX_BIT_EN_PEDESTAL); + pbVideoOutputFormat[2] |= (RX_BIT_MUX_YC | RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_MUX10B: + /* YCbCr 422 muxed 10 bit, used with digital output only */ + pbVideoOutputFormat[1] |= (RX_BIT_EN_PEDESTAL); + pbVideoOutputFormat[2] |= RX_BIT_MUX_YC; + break; + case SiI_RX_P_YCbCr422_16B: + pbVideoOutputFormat[2] |= RX_BIT_DITHER; + break; + case SiI_RX_P_YCbCr422: + case SiI_RX_P_YCbCr422_20B: + break; + case SiI_RX_P_YCbCr422_16B_2PixClk: /* SiI9011 */ + pbVideoOutputFormat[2] |= RX_BIT_DITHER; + break; + case SiI_RX_P_YCbCr422_20B_2PixClk: /* SiI9011 */ + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: PrepVideoPathForYCbCr444Input() + * Function Description: Preparing Video Path for YCbCr 444 Input Color Space + *---------------------------------------------------------------------------- + */ +static void PrepVideoPathForYCbCr444Input(BYTE bVideoPath, + BYTE *pbVideoOutputFormat) +{ +/* pbVideoOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + pbVideoOutputFormat[2] &= (~(RX_BIT_422to444 | RX_BIT_DITHER | + RX_BIT_MUX_YC | RX_BIT_RGBToYCbCr)); + pbVideoOutputFormat[1] &= (~RX_BIT_YCbCrToRGB); + pbVideoOutputFormat[0] &= (~RX_BIT_EXT_BIT_MODE); + + + switch (bVideoPath) { + /* Clear YCbCr Converter, DownScale, UpScale */ + case SiI_RX_P_RGB: + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + pbVideoOutputFormat[1] |= RX_BIT_YCbCrToRGB; + break; + /* Set YCbCr Converter, */ + case SiI_RX_P_YCbCr444: + case SiI_RX_P_YCbCr444_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr444_48B: /* SiI9021/31 */ + break; + /* Set YCbCr Converter, set DownScale + * 4:2:2 mode is used with digital output only + */ + case SiI_RX_P_YCbCr422_20B: + case SiI_RX_P_YCbCr422: + pbVideoOutputFormat[2] |= RX_BIT_444to422; + break; + case SiI_RX_P_YCbCr422_MUX8B: + /* YCbCr 422 muxed 8 bit, used with digital output only */ + pbVideoOutputFormat[1] |= (RX_BIT_EN_PEDESTAL); + pbVideoOutputFormat[2] |= (RX_BIT_444to422 | RX_BIT_MUX_YC | + RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_MUX10B: + /* YCbCr 422 muxed 10 bit, used with digital output only */ + pbVideoOutputFormat[1] |= (RX_BIT_EN_PEDESTAL); + pbVideoOutputFormat[2] |= (RX_BIT_444to422 | RX_BIT_MUX_YC); + break; + case SiI_RX_P_YCbCr422_16B: + pbVideoOutputFormat[2] |= (RX_BIT_444to422 | RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_16B_2PixClk: /* SiI9011 */ + pbVideoOutputFormat[2] |= (RX_BIT_444to422 | RX_BIT_DITHER); + break; + case SiI_RX_P_YCbCr422_20B_2PixClk: /* SiI9011 */ + break; + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiPrepVideoPathSelect() + * Function Description: prepares Video Format Data for selected Video Format + * + * Accepts: BYTE Video Path Select, pointer on Video Format Data + * Returns: Warning Byte, pointer on Video Format Data, Video Path Select Data + * can be modified + * Globals: bInputColorSpace (read only) + *---------------------------------------------------------------------------- + */ +BYTE siiPrepVideoPathSelect(BYTE bVideoPathSelect, BYTE bInputColorSpace, + BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; + + RXEXTPR("%s: bInputColorSpace=%d\n", __func__, bInputColorSpace); + if (CheckVideoDAC_Cap()) { + PrepVideoPathCSCAnalogDAC(bVideoPathSelect & SiI_RX_P_Mask, + pbVidFormatData); + } + if (bInputColorSpace == SiI_RX_ICP_RGB) { + RXEXTPR("%s: bInputColorSpac as RGB\n", __func__); + PrepVideoPathForRGBInput(bVideoPathSelect & SiI_RX_P_Mask, + pbVidFormatData); + } else if (bInputColorSpace == SiI_RX_ICP_YCbCr422) { + RXEXTPR("%s: bInputColorSpace as YUV422\n", __func__); + PrepVideoPathForYCbCr422Input(bVideoPathSelect & SiI_RX_P_Mask, + pbVidFormatData); + } else if (bInputColorSpace == SiI_RX_ICP_YCbCr444) { + RXEXTPR("%s: bInputColorSpace as YUV444\n", __func__); + PrepVideoPathForYCbCr444Input(bVideoPathSelect & SiI_RX_P_Mask, + pbVidFormatData); + } else { + RXEXTERR("%s: bInputColorSpace error\n", __func__); + bECode = SiI_EC_InColorSpace; + } + + CheckVidPathForDevCap(bVideoPathSelect); + + return bECode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiPrepSyncSelect() + * Function Description: prepares Sync Select data + * + * Accepts: BYTE Sync Select, pointer on Video Format Data + * Returns: Warning byte, pointer on Video Format Data, sync select data can + * be modified + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiPrepSyncSelect(BYTE bSyncSelect, BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; + BYTE bWCode = FALSE; +/* pbVideoOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + + pbVidFormatData[0] &= (~(RX_BIT_ENCSYNC_ON_HSYNC | + RX_BIT_ENCSYNC_ON_VSYNC | RX_BIT_INSERT_CSYNC_ON_AOUT)); + pbVidFormatData[2] &= (~RX_BIT_INS_SAVEAV); + switch (bSyncSelect) { + case SiI_RX_SS_SeparateSync: + break; + case SiI_RX_SS_CompOnH: + pbVidFormatData[0] |= RX_BIT_ENCSYNC_ON_HSYNC; + break; + case SiI_RX_SS_CompOnV: + pbVidFormatData[0] |= RX_BIT_ENCSYNC_ON_VSYNC; + break; + case SiI_RX_SS_EmbSync: + pbVidFormatData[2] |= RX_BIT_INS_SAVEAV; + break; + case SiI_RX_AVC_SOGY: + pbVidFormatData[0] |= RX_BIT_INSERT_CSYNC_ON_AOUT; + if (SiI_Ctrl.bDevId == RX_SiI9011) + bWCode = SiI_WC_ChipNoCap; + break; + } + siiWarningHandler(bWCode); + + return bECode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiPrepSyncCtrl() + * Function Description: parepares control of sync + * + * Accepts: byte Sync. control, and Video Format Data + * Returns: Warning byte, pointer on Video Format Data, sync control data can + * be modified + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiPrepSyncCtrl(BYTE bSyncCtrl, BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; +/* pbVidOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + pbVidFormatData[0] &= (~(RX_BIT_INVERT_HSYNC | RX_BIT_INVERT_VSYNC)); + if (bSyncCtrl & SiI_RX_SC_InvH) + pbVidFormatData[0] |= RX_BIT_INVERT_HSYNC; + if (bSyncCtrl & SiI_RX_SC_InvV) + pbVidFormatData[0] |= RX_BIT_INVERT_VSYNC; + + return bECode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiPrepVideoCtrl() + * Function Description: Sets Enable or Disable pedestal + * + * Accepts: pointer on Video Format Data + * Returns: Warning code, if wrong parameter, Modified Video Format Data + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiPrepVideoCtrl(BYTE bVideoOutCtrl, BYTE *pbVidFormatData) +{ + BYTE bECode = FALSE; + BYTE bWCode = FALSE; +/* pbVidOutputFormat: + * | 7 | 6 | 5 | 4 | + * 3 | 2 | 1 | 0 | + * bit[0] 0x48 VID_CTRL |InvVSync|InvHSync|CSyncOnVSync|CSyncOnHSync | + * enSOG |YCbCr2RGB |BitMode |RGB2YCbCr | + * bit[1] 0x49 VID_MODE2 |Res |Res |Res |LE Pol | + * En YCbCr2RGB Rng|EnYCbCr2RGB|En Ped. |DAC RGB | + * bit[2] 0x4A VID_MODE |SyncCode|MuxYC |Dither |En RGB2YCbCr Rng | + * En RGB2YCbCr |UpSmpl |DownSmpl|EnImsCSync| + */ + + if (bVideoOutCtrl == SiI_RX_AVC_Pedestal) + pbVidFormatData[1] |= RX_BIT_EN_PEDESTAL; + else if (bVideoOutCtrl == SiI_RX_AVC_NoPedestal) + pbVidFormatData[1] &= (~RX_BIT_EN_PEDESTAL); + + if ((SiI_Ctrl.bDevId == RX_SiI9011) && + (bVideoOutCtrl != SiI_RX_AVC_Digital_Output)) + bWCode = SiI_WC_ChipNoCap; + + if (bVideoOutCtrl == SiI_RX_AVC_Digital_Output) + sii_SetVideoOutputPowerDown(SiI_RX_VidOutPD_Analog); + else + sii_SetVideoOutputPowerDown(SiI_RX_VidOutPD_Digital); + + siiWarningHandler(bWCode); + return bECode; +} + +/*------------------------------------------------------------------------------ + * Function Name: Configure2PixPerClockMode() + * Function Description: Function turns on or off 2 Pixels per clock mode + *---------------------------------------------------------------------------- + */ +static void Configure2PixPerClockMode(BOOL On) +{ + if (On) { + RXEXTPR("%s: on\n", __func__); + siiIIC_RX_RWBitsInByteP0(RX_SYS_CTRL1_ADDR, + RX_BIT_2PIX_MODE, SET); + /* siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + * RX_BIT_PD_QE, SET); + */ + } else { + RXEXTPR("%s: off\n", __func__); + siiIIC_RX_RWBitsInByteP0(RX_SYS_CTRL1_ADDR, + RX_BIT_2PIX_MODE, CLR); + /* siiIIC_RX_RWBitsInByteP1(RX_PD_SYS2_ADDR, + * RX_BIT_PD_QE, CLR); + */ + } + +} + +/*------------------------------------------------------------------------------ + * Function Name: SetInputOutputDivider + * Function Description: Function Sets Input and Output pixel clock divider + *---------------------------------------------------------------------------- + */ +static void SetInputOutputDivider(BOOL qMode48BitOr2PixClk, + BOOL qRestoreOrigPixClock, BYTE PixRepl, BOOL mux_mode) +{ + BYTE bRegVal; + + SiI_Ctrl.bShadowPixRepl = PixRepl; + bRegVal = siiReadByteHDMIRXP0(RX_SYS_CTRL1_ADDR); + RXEXTPR("%s: RX_SYS_CTRL1_ADDR(0x%02x)=0x%02x\n", + __func__, RX_SYS_CTRL1_ADDR, bRegVal); + + /* clear bits of input and output devider */ + bRegVal &= RX_MSK_CLR_IN_OUT_DIV; + + /* Set bits for input divider equal Pixel Replication */ + bRegVal |= (PixRepl << 4); + + /* in YCbCr422Mux mode output clock should be doubled */ + if (mux_mode) { + PixRepl += 1; + PixRepl >>= 1; /* divide by 2 */ + if (PixRepl) + PixRepl -= 1; + } + + if ((!qRestoreOrigPixClock) && qMode48BitOr2PixClk) { + bRegVal |= RX_OUTPUT_DIV_BY_2; + } else if (qRestoreOrigPixClock && (!qMode48BitOr2PixClk)) { + /*Set bits for output divider to restore original pixel clock*/ + bRegVal |= (PixRepl << 6); + } else if (qRestoreOrigPixClock && qMode48BitOr2PixClk) { + if (PixRepl == SiI_PixRepl1) + bRegVal |= RX_OUTPUT_DIV_BY_2; + else if (PixRepl == SiI_PixRepl2) + bRegVal |= RX_OUTPUT_DIV_BY_4; + else + siiWarningHandler(SiI_WC_ChipNoCap); + } else { + if ((PixRepl == 0) && mux_mode) + bRegVal |= 0x10; + } + + siiWriteByteHDMIRXP0(RX_SYS_CTRL1_ADDR, bRegVal); + RXEXTPR("%s: RX_SYS_CTRL1_ADDR(0x%02x)=0x%02x\n", + __func__, RX_SYS_CTRL1_ADDR, bRegVal); + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetVidResDependentVidOutputVormat + * Function Description: Functions sets Video Resolution dependent parameters: + * Pix Replication Divider, Output Divider + * Accepts: BYTE Pixel Replication Rate, BYTE Video Path Select + * Returns: Warning code, if wrong parameter + * Globals: none + *---------------------------------------------------------------------------- + */ + +void siiSetVidResDependentVidPath(BYTE bPixRepl, BYTE bVideoPath) +{ + BOOL qRestoreOrgPixClock = TRUE; + BYTE bRegVal; + + if (bVideoPath & SiI_RX_P_S_PassReplicatedPixels) + qRestoreOrgPixClock = FALSE; + switch (bVideoPath) { + case SiI_RX_P_RGB_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr444_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr422_16B_2PixClk: /* SiI9011 */ + case SiI_RX_P_YCbCr422_20B_2PixClk: /* SiI9011 */ + if (SiI_Ctrl.bDevId == RX_SiI9011) { + Configure2PixPerClockMode(ON); + SetInputOutputDivider(ON/*On 48bit(LE) or 2Pix*/, + qRestoreOrgPixClock, bPixRepl, false); + } else + siiWarningHandler(SiI_WC_ChipNoCap); + break; + case SiI_RX_P_YCbCr422_MUX8B: /* RX_SiI9135 */ + case SiI_RX_P_YCbCr422_MUX10B: + if (SiI_Ctrl.bDevId == RX_SiI9135) { + /* Configure2PixPerClockMode(ON); */ + SetInputOutputDivider(OFF/*On 48bit(LE) or 2Pix*/, + FALSE, bPixRepl, true); + if ((0 == bPixRepl || 1 == bPixRepl)) { + /* ITU 601 YC MUX */ + siiWriteByteHDMIRXP0(0x5F, 0xE0); + /* siiWriteByteHDMIRXP0(0x81, 0x02); */ + bRegVal = siiReadByteHDMIRXP0(0x81); + bRegVal = (bRegVal & ~(0xf)) | 0x02; + siiWriteByteHDMIRXP0(0x81, bRegVal); + RXEXTPR("%s: write 0x81\n", __func__); + } + /* modified by zhangyue for debug YC Mux end */ + RXEXTPR("%s: bPixRepl=%d\n", __func__, bPixRepl); + } else { + siiWarningHandler(SiI_WC_ChipNoCap); + } + break; + case SiI_RX_P_RGB_48B: /* SiI9021/31 */ + case SiI_RX_P_YCbCr444_48B: /* SiI9021/31 */ + SetInputOutputDivider(ON/*On 48bit(LE) or 2Pix*/, + qRestoreOrgPixClock, bPixRepl, false); + if (SiI_Ctrl.bDevId == RX_SiI9011) + siiWarningHandler(SiI_WC_ChipNoCap); + break; + default: + SetInputOutputDivider(OFF/*Off 48bit (LE) and 2Pix*/, + qRestoreOrgPixClock, bPixRepl, false); + if (SiI_Ctrl.bDevId == RX_SiI9011) + Configure2PixPerClockMode(OFF); + break; + } +} + +/*------------------------------------------------------------------------------ + * Function Name: siiMuteVideo + * Function Description: Reads Audio Path, modifys Video Mute bit + * + * Accepts: BYTE Video Mute Control + * Returns: Err or Warning code + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiMuteVideo(BYTE On) +{ + if (On) { + siiIIC_RX_RWBitsInByteP1(RX_AUDP_MUTE_ADDR, + RX_BIT_VIDEO_MUTE, SET); + SiI_Inf.bGlobStatus |= SiI_RX_Global_VMute; + } else { + siiIIC_RX_RWBitsInByteP1(RX_AUDP_MUTE_ADDR, + RX_BIT_VIDEO_MUTE, CLR); + SiI_Inf.bGlobStatus &= (~SiI_RX_Global_VMute); + } +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.h new file mode 100644 index 0000000..08d5643 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidF.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIRXAPIDefs.h" + +enum SiI_PixPrepl { + + SiI_PixRepl1 = 0x00, + SiI_PixRepl2 = 0x01, + SiI_PixRepl4 = 0x03 + +}; + +BYTE siiGetVideoFormatData(BYTE *pbVidFormatData); +BYTE siiSetVideoFormatData(BYTE *pbVidFormatData); +BYTE siiPrepVideoPathSelect(BYTE bVideoPathSelect, BYTE bInputColorSpace, + BYTE *pbVidFormatData); +BYTE siiPrepSyncSelect(BYTE bSyncSelect, BYTE *pbVidFormatData); +BYTE siiPrepSyncCtrl(BYTE bSyncCtrl, BYTE *pbVidFormatData); +BYTE siiPrepVideoCtrl(BYTE bVideoOutCtrl, BYTE *pbVidFormatData); + +void siiSetVidResDependentVidPath(BYTE bPixRepl, BYTE bVideoPath); +void siiSetVideoPathColorSpaceDependent(BYTE bVideoPath, BYTE bInputColorSpace); +/* void siiSetStaticVideoPath(BYTE bdata1, BYTE bdata2); */ +void siiMuteVideo(BYTE On); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.c new file mode 100644 index 0000000..c3f912f --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.c @@ -0,0 +1,150 @@ +/*------------------------------------------------------------------------------ + * Module Name: VidIn + * --- + * Module Description: This module use for switchn between HDMI (DVI Inputs) + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIGlob.h" +#include "SiIVidIn.h" +#include "SiIRXIO.h" +#include "SiITrace.h" +#include "SiIRXAPIDefs.h" +#include "SiIRXDefs.h" +#include "SiITTVideo.h" +#include "SiITTAudio.h" +#include "SiIHDCP.h" +#include "SiIHAL.h" +#include "SiIHDMIRX.h" +#include "SiISysCtrl.h" +#include "SiIAudio.h" + +/*------------------------------------------------------------------------------ + * Function Name: siiChangeHPD + * Function Description: This function enables Hot Plug Detect (HPD) on Active + * HDMI Input and disables on passive one + *---------------------------------------------------------------------------- + */ + +static void ChangeHPD(BYTE SelectedChannel) +{ + if (SelectedChannel == SiI_RX_VInCh1) { + halClearHPD1Pin(); /* YMA NOTE clr P2^4 */ + halSetHPD2Pin(); + if (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) + siiSetNormalTerminationValueCh2(OFF); + } else if (SelectedChannel == SiI_RX_VInCh2) { + halClearHPD2Pin(); + halSetHPD1Pin(); + if (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) + siiSetNormalTerminationValueCh1(OFF); + } +} + +/*------------------------------------------------------------------------------ + * Function Name: ChangeTMDSCoreAndDDC() + * Function Description: Function makes disable both TMDS cores and DDC, + * and makes enable for active Video Input Channel + *---------------------------------------------------------------------------- + */ +static BYTE ChangeTMDSCoreAndDDC(BYTE bVideoInputChannels) +{ + BYTE bECode = FALSE; + + siiIIC_RX_RWBitsInByteP0(RX_SYS_SW_SWTCHC_ADDR, + (RX_BIT_RX0_EN | RX_BIT_DDC0_EN | RX_BIT_RX1_EN | + RX_BIT_DDC1_EN), CLR); + + if (bVideoInputChannels == SiI_RX_VInCh1) { + siiIIC_RX_RWBitsInByteP0(RX_SYS_SW_SWTCHC_ADDR, + RX_BIT_RX0_EN | RX_BIT_DDC0_EN, SET); + } else { + siiIIC_RX_RWBitsInByteP0(RX_SYS_SW_SWTCHC_ADDR, + RX_BIT_RX1_EN | RX_BIT_DDC1_EN, SET); + } + + return bECode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetVideoInput + * Function Description: This function is used to Select new HDMI Input + * + * Accepts: bVideoInputChannel + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiSetVideoInput(BYTE bVideoInputChannel) +{ + siiMuteVideoAndSetSM_SyncInChange(); + + siiReInitRX(); + + ChangeTMDSCoreAndDDC(bVideoInputChannel); /* re-init RX */ + + ChangeHPD(bVideoInputChannel); + SiI_Ctrl.bVidInChannel = bVideoInputChannel; + /* Clearing Ri will be notification for host to start */ + ReqReAuthenticationRX(); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiInitVideoInput + * Function Description: This function is used to Select new HDMI Input + * + * Accepts: bVideoInputChannel + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiInitVideoInput(BYTE bVideoInputChannel) +{ + ChangeTMDSCoreAndDDC(bVideoInputChannel); /* re-init RX */ + + ChangeHPD(bVideoInputChannel); + SiI_Ctrl.bVidInChannel = bVideoInputChannel; + /* Clearing Ri will be notification for host to start */ + ReqReAuthenticationRX(); + + return siiGetErrorsWarnings(); +} + +/*----------------------------------------------------------------------------- + * Function Name: siiChangeVideoInput + * Function Description: + * + * Accepts: bVideoInputChannel + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiChangeVideoInput(BYTE bVideoInputChannel) +{ + if ((SiI_Ctrl.bDevId == RX_SiI9011) && + (bVideoInputChannel != SiI_RX_VInCh1)) { + siiWarningHandler(SiI_WC_ChipNoCap); + } else { + /* YMA set already + *SiI_Ctrl.bVidInChannel = bVideoInputChannel; + */ + if (siiIsVideoOn() && + (SiI_Inf.bGlobStatus & SiI_RX_GlobalHDMI_Detected)) { + /* Gives time for Audio soft muting */ + siiSetSM_ReqVidInChange(); + siiSetAudioMuteEvent(); + } else { + siiSetVideoInput(SiI_Ctrl.bVidInChannel); + } + } + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.h new file mode 100644 index 0000000..3b78535 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidIn.h @@ -0,0 +1,17 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "SiIRXDefs.h" + +void siiChangeVideoInput(BYTE bVideoInputChannel); +void siiSetVideoInput(BYTE bVideoInputChannel); +BYTE siiInitVideoInput(BYTE bVideoInputChannel); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.c new file mode 100644 index 0000000..682abbf --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.c @@ -0,0 +1,758 @@ +/*------------------------------------------------------------------------------ + * Module Name: SiI Video Resolution + * --- + * Module Description: Here are video resolution related functions + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiIHAL.h" +#include "SiIInfoPkts.h" +#include "SiIVidRes.h" +#include "SiIVidF.h" +#include "SiIGlob.h" +#include "SiIRXDefs.h" +#include "SiIRXIO.h" +#include "SiITrace.h" +#include "SiIDeepColor.h" + +/* #ifdef SII_DUMP_UART + * #include + * #endif + */ + +#include "../hdmirx_ext_drv.h" + +/*------------------------------------------------------------------------------ + * Function Name: abs_diff + * Function Description: calculates diffrence between two parameters + *---------------------------------------------------------------------------- + */ +static WORD abs_diff(WORD A, WORD B) +{ + WORD Result; + + if (A > B) + Result = A - B; + else + Result = B - A; + return Result; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetPixClockFromTables + * Function Description: Takes Pixel clock from Video Resolution tables + * + * Accepts: bIndex + * Returns: none + * Globals: byte, Pixel Clock + *---------------------------------------------------------------------------- + */ +BYTE siiGetPixClockFromTables(BYTE bIndex) +{ + return VModeTables[bIndex].PixClk; +} +/*------------------------------------------------------------------------------ + * Function Name: siiCheckSyncDetect + * Function Description: checks Sync Detect ( asserted when cirtain number of + * DE counted ) + *---------------------------------------------------------------------------- + */ +BOOL siiCheckSyncDetect(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_STATE_ADDR) & RX_BIT_SCDT) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: siiCheckClockDetect + * Function Description: checks Clock Detect + *---------------------------------------------------------------------------- + */ +BOOL siiCheckClockDetect(void) +{ + BOOL qResult = FALSE; + + if (siiReadByteHDMIRXP0(RX_STATE_ADDR) & RX_BIT_CLK) + qResult = TRUE; + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: GetVSyncFreq + * Function Description: this function culculates Vertical Sync Frequency + *---------------------------------------------------------------------------- + */ +static WORD GetVSyncFreq(WORD wHtot, WORD wVtot) +{ + BYTE i; + WORD wXClks = 0; + DWORD dwXclksPerFrame; + WORD wVFreq; + BYTE bRegVal; + + bRegVal = siiReadByteHDMIRXP0(RX_SYS_CTRL1_ADDR); + RXEXTPR("%s: RX_SYS_CTRL1_ADDR(0x%02x)=0x%02x\n", + __func__, RX_SYS_CTRL1_ADDR, bRegVal); + + /* FrameXClk = (( Htot * Vtot)* (AVR of 8 Reg128XClk ))/1128 */ + + if ((SiI_Ctrl.bDevId == RX_SiI9133) || + (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) || + (SiI_Ctrl.bDevId == RX_SiIIP11)) { + for (i = 0; i < 8; i++) { + /* by doing this we will get average XClk */ + wXClks += GetXClockW(); + } + if (bRegVal & 0x10) + wXClks <<= 1; + SiI_Inf.Sync.bFPix = (BYTE)((WORD) + (SII_XCLOCK_OSC_SCALED2047_FOR_CALK_FPIX / wXClks)); + } else { + for (i = 0; i < 8; i++) { + /* by doing this we will get average XClk */ + wXClks += GetXClock(); + } + if (bRegVal & 0x10) + wXClks <<= 1; + SiI_Inf.Sync.bFPix = (BYTE)((WORD) + (SII_XCLOCK_OSC_SCALED_FOR_CALK_FPIX / wXClks)); + } + + RXEXTPR("%s: wXClks=%d, bFPix=%d\n", + __func__, wXClks, SiI_Inf.Sync.bFPix); + dwXclksPerFrame = (DWORD)wHtot * (DWORD)wVtot; + + if ((SiI_Ctrl.bDevId == RX_SiI9133) || + (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) || + (SiI_Ctrl.bDevId == RX_SiIIP11)) { + RXEXTPR("%s: bDevId siI9135\n", __func__); + dwXclksPerFrame *= (DWORD)(wXClks >> 3); + dwXclksPerFrame >>= 11; /* div ( 8 * 2048 ) */ + wVFreq = (WORD)(SII_XCLOCK_OSC_SCALED2047_AND_MUL100 / + dwXclksPerFrame); + } else { + RXEXTPR("%s: bDevId other\n", __func__); + dwXclksPerFrame *= (DWORD)wXClks; + dwXclksPerFrame >>= 10; /* div ( 8 * 128 ) */ + wVFreq = (WORD)(SII_XCLOCK_OSC_SCALED_AND_MUL100 / + dwXclksPerFrame); + } + + return wVFreq; +} + +/*------------------------------------------------------------------------------ + * Function Name: siiGetSyncInfo() + * Function Description: is used to get H/V Sync and polarity information + *---------------------------------------------------------------------------- + */ +void siiGetSyncInfo(struct SyncInfoType_s *SyncInfo) +{ + BYTE abData[4]; + + siiReadBlockHDMIRXP0(RX_HRES_L_ADDR, 4, abData); + + RXEXTPR("%s: RX_HRES_L_ADDR: 0x%02x,0x%02x,0x%02x,0x%02x\n", + __func__, abData[0], abData[1], abData[2], abData[3]); + SyncInfo->ClocksPerLine = abData[0] | (abData[1] << 8); + SyncInfo->HTot = abData[2] | (abData[3] << 8); + RXEXTPR("%s: ClocksPerLine=%d, HTot=%d, pixel_repl=%d\n", + __func__, SyncInfo->ClocksPerLine, + SyncInfo->HTot, SiI_Ctrl.bShadowPixRepl); + if (SiI_Ctrl.bShadowPixRepl == 0x01) + SyncInfo->ClocksPerLine <<= 1; /* pixel replicated by 2 clocks*/ + else if (SiI_Ctrl.bShadowPixRepl == 0x02) + SyncInfo->ClocksPerLine *= 3; /* pixel replicated by 3 clocks*/ + else if (SiI_Ctrl.bShadowPixRepl == 0x03) + SyncInfo->ClocksPerLine <<= 2; /* pixel replicated by 4 clocks*/ + SyncInfo->VFreq = GetVSyncFreq(SyncInfo->ClocksPerLine, SyncInfo->HTot); + RXEXTPR("%s: VFreq=%d\n", __func__, SyncInfo->VFreq); + SyncInfo->RefrTypeVHPol = GetRefrTypeHVPol(); + +} +/*------------------------------------------------------------------------------ + * Function Name: CompareWithVMTableRef() + * Function Description: Compare timing inform with an entry of video + * mode reference table + *---------------------------------------------------------------------------- + */ +static BYTE CompareWithVMTableRef(BYTE Index, struct SyncInfoType_s *SyncInform) +{ + BOOL qResult = FALSE; + + if (VModeTables[Index].Tag.RefrTypeVHPol == SyncInform->RefrTypeVHPol) { + if (abs_diff(VModeTables[Index].Tag.VFreq, SyncInform->VFreq) < + V_TOLERANCE) { + if (abs_diff(VModeTables[Index].Tag.Total.Lines, + SyncInform->HTot) < LINES_TOLERANCE) { + if (abs_diff( + VModeTables[Index].Tag.Total.Pixels, + SyncInform->ClocksPerLine) < + PIXELS_TOLERANCE) { + qResult = TRUE; + } + } + } + } + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: ompareWithVMTableRefIgnorPol() + * Function Description: Compare timing inform with an entry of video + * mode reference table, but polarity information + * is ignored + *---------------------------------------------------------------------------- + */ +static BYTE CompareWithVMTableRefIgnorPol(BYTE Index, + struct SyncInfoType_s *SyncInform) +{ + BOOL qResult = FALSE; + + if ((VModeTables[Index].Tag.RefrTypeVHPol & INTERLACE_MASK) == + (SyncInform->RefrTypeVHPol & INTERLACE_MASK)) { + if (abs_diff(VModeTables[Index].Tag.VFreq, SyncInform->VFreq) < + V_TOLERANCE) { + if (abs_diff(VModeTables[Index].Tag.Total.Lines, + SyncInform->HTot) < LINES_TOLERANCE) { + if (abs_diff( + VModeTables[Index].Tag.Total.Pixels, + SyncInform->ClocksPerLine) < + PIXELS_TOLERANCE) { + qResult = TRUE; + } + } + } + } + return qResult; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiVideoModeDetection + * Function Description: This function used for search video resolution modes + * through reference tables + *---------------------------------------------------------------------------- + */ + +/* This function used for search video modes */ +BYTE siiVideoModeDetection(BYTE *pbIndex, struct SyncInfoType_s *SyncInf) +{ + BYTE bResult = FALSE; + + for ((*pbIndex) = 0; (*pbIndex) < NMODES; (*pbIndex)++) { + if (CompareWithVMTableRef(*pbIndex, SyncInf)) { + bResult = 1; + break; + } + } + if ((*pbIndex) == NMODES) { + /* Preset mode not found, search ignoring polarity then: */ + for ((*pbIndex) = 0; (*pbIndex) < NMODES; (*pbIndex)++) { + if (CompareWithVMTableRefIgnorPol(*pbIndex, SyncInf)) { + bResult = 2; + break; + } + } + } + return bResult; +} + +/*------------------------------------------------------------------------------ + * Function Name: CheckOutOfRangeConditions + * Function Description: This function is used to detect of sync data overrange + * conditions + *---------------------------------------------------------------------------- + */ + +BOOL siiCheckOutOfRangeConditions(struct SyncInfoType_s *SyncInfo) +{ + WORD wHFreq; + BOOL qOutOfRangeF = TRUE; + + wHFreq = (WORD)(((DWORD) SyncInfo->VFreq * SyncInfo->HTot) / 1000); + if (SyncInfo->RefrTypeVHPol & INTERLACE_MASK) { + /* Interlace Video Mode */ + if ((wHFreq < INTERLACE_HFREQ_HIGH_LIMIT) && + (wHFreq > INTERLACE_HFREQ_LOW_LIMIT)) { + if ((SyncInfo->VFreq < INTERLACE_VFREQ_HIGH_LIMIT) && + (SyncInfo->VFreq > INTERLACE_VFREQ_LOW_LIMIT)) { + qOutOfRangeF = FALSE; /* sync in range */ + } + } +#ifdef SII_DUMP_UART + printf("\n--HFreq = %i VFreq = %i ScanPol=%02X--\n", + wHFreq, SyncInfo->VFreq, (int)SyncInfo->RefrTypeVHPol); +#endif + } else { /* Progressive Video Mode */ + if ((wHFreq < PROGRESSIVE_HFREQ_HIGH_LIMIT) && + (wHFreq > PROGRESSIVE_HFREQ_LOW_LIMIT)) { + if ((SyncInfo->VFreq < PROGRESSIVE_VFREQ_HIGH_LIMIT) && + (SyncInfo->VFreq > + PROGRESSIVE_VFREQ_LOW_LIMIT)){ + qOutOfRangeF = FALSE; /* sync in range */ + } +#ifdef SII_DUMP_UART + printf("\n--HFreq = %i VFreq = %i ScanPol=%02X--\n", + wHFreq, SyncInfo->VFreq, + (int)SyncInfo->RefrTypeVHPol); +#endif + } + } + return qOutOfRangeF; +} +/*------------------------------------------------------------------------------ + * Function Name: GetColorimetryFormVidRes + * Function Description: this function gets Colorimetry information from video + * input resolution + *---------------------------------------------------------------------------- + */ + +static BYTE GetColorimetryFormVidRes(BYTE bVidResId) +{ + BYTE bColorimetry; + + bColorimetry = SiI_RX_ITU_601; + if (VModeTables[bVidResId].Res.V >= 720) + bColorimetry = SiI_RX_ITU_709; + return bColorimetry; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetPixReplicationFormVidRes + * Function Description: this function gets Pixel Replication Rate from entry + * of detected video resolution + *---------------------------------------------------------------------------- + */ +static BYTE siiGetPixReplicationFormVidRes(BYTE VidResId) +{ + return VModeTables[VidResId].PixRepl; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetPixReplicationFormVidRes + * Function Description: this function gets Pixel Replication Rate from entry + * of detected video resolution + *---------------------------------------------------------------------------- + */ +static BYTE siiIsInterlaceMode(BYTE VidResId) +{ + BYTE tmp; + + tmp = (VModeTables[VidResId].Tag.RefrTypeVHPol & SiI_InterlaceMask); + return tmp; +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetVideoBlankLevel() + * Function Description: this function restores blank level which dependes on + * Input Color Space and Input Video resolution + *---------------------------------------------------------------------------- + */ + +static BYTE SetVideoBlankLevel(BYTE bVidResId) +{ + BYTE bEWCode = FALSE; + + BYTE bBlankDataCh[3]; + + bBlankDataCh[0] = 0; /* blank levels for PC modes */ + bBlankDataCh[1] = 0; + bBlankDataCh[2] = 0; + + if (SiI_Inf.AVI.bInputColorSpace == SiI_RX_ICP_RGB) { + if ((bVidResId < PC_BASE) && (bVidResId != VGA)) { /* RGB CE */ + bBlankDataCh[0] = 0x10; + bBlankDataCh[1] = 0x10; + bBlankDataCh[2] = 0x10; + } + } else if (SiI_Inf.AVI.bInputColorSpace == SiI_RX_ICP_YCbCr444) { + /* YCbCr 4:4:4 */ + bBlankDataCh[0] = 0x80; + bBlankDataCh[1] = 0x10; + bBlankDataCh[2] = 0x80; + } else if (SiI_Inf.AVI.bInputColorSpace == SiI_RX_ICP_YCbCr422) { + /* YCbCr 4:2:2 */ + bBlankDataCh[0] = 0x00; + bBlankDataCh[1] = 0x10; + bBlankDataCh[2] = 0x80; + } else + bEWCode = SiI_EC_InColorSpace; + + siiWriteBlockHDMIRXP0(RX_BLANKDATA_CH0_ADDR, 3, bBlankDataCh); + siiWarningHandler(bEWCode); + return bEWCode; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetOutputVideoFilter + * Function Description: this function selects type of Output Video Filter + * which depends from Video Resolution + *---------------------------------------------------------------------------- + */ +#ifdef _OUTPUT_VFILTER_ +/* TThis function controlls extrnal Video Filter, if it present */ + +static BYTE SetOutputVideoFilter(BYTE bVidResId) +{ + BYTE bEWCode = FALSE; + + bVidResId = 0; + SiI_Inf.Sync + return bEWCode; +} +#endif /* _OUTPUT_VFILTER_ */ +/*------------------------------------------------------------------------------ + * Function Name: CompareNewOldSync() + * Function Description: This function is used to detect that resolution has + * stated to change + *---------------------------------------------------------------------------- + */ +BOOL siiCompareNewOldSync(struct SyncInfoType_s *OldSyncInfo, + struct SyncInfoType_s *NewSyncInfo) +{ + BOOL qResult = FALSE; + + if ((abs_diff(OldSyncInfo->HTot, NewSyncInfo->HTot) <= LINES_TOLERANCE) + && (abs_diff(OldSyncInfo->ClocksPerLine, + NewSyncInfo->ClocksPerLine) <= PIXELS_TOLERANCE)) { + qResult = TRUE; + } + +#ifdef SII_DUMP_UART + if (!qResult) { + printf("--Old HTot= %i ClocksPerLine = %i\n", + OldSyncInfo->HTot, OldSyncInfo->ClocksPerLine); + printf("--New HTot= %i ClocksPerLine = %i\n", + NewSyncInfo->HTot, NewSyncInfo->ClocksPerLine); + } +#endif + return qResult; +} +/*------------------------------------------------------------------------------ + * Function Name: ConfigInterlaceCSync( ) + * Function Description: Sets parameters which used for generation Composite + * sync for particular Interlace Modes + *---------------------------------------------------------------------------- + */ + +static void ConfigInterlaceCSync(BYTE bVidResId) +{ + siiWriteWordHDMIRXP0(RX_CAPHALFLINE_ADDR, + InterlaceCSync[bVidResId].CapHalfLineCnt); + siiWriteWordHDMIRXP0(RX_PREEQPULSCNT_ADDR, + InterlaceCSync[bVidResId].PreEqPulseCnt); + siiWriteWordHDMIRXP0(RX_SERRATEDCNT_ADDR, + InterlaceCSync[bVidResId].SerratedCnt); + siiWriteWordHDMIRXP0(RX_POSTEQPULSECNT_ADDR, + InterlaceCSync[bVidResId].PostEqPulseCnt); + +} +/*------------------------------------------------------------------------------ + * Function Name: siiConfigureSyncOnYForInretlaceModes() + * Function Description: this functio is used to select which table should be + * used for generation of Sync for Interlace Modes + *---------------------------------------------------------------------------- + */ + +static void ConfigureSyncOnYForInretlaceModes(BYTE bVidResId) +{ + if (VModeTables[bVidResId].Res.V == 480) { + ConfigInterlaceCSync(0); + } else if (VModeTables[bVidResId].Res.V == 576) { + ConfigInterlaceCSync(1); + } else if (VModeTables[bVidResId].Res.V == 1080) { + ConfigInterlaceCSync(2); + } else { +#ifdef SII_DUMP_UART + printf("Interlace Output is not supported\n"); +#endif + } +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetColorimetry() + * Function Description: sets colorimetry formula whith used with color space + * converter (BT601 vs. BT709) + *---------------------------------------------------------------------------- + */ +static BYTE SetColorimetry(BYTE bColorimetry) +{ + BYTE bEWCode = FALSE; + + if (bColorimetry == SiI_RX_ITU_601) { + siiIIC_RX_RWBitsInByteP0(RX_VID_CTRL_ADDR, + RX_BIT_BT709_RGBCONV | RX_BIT_BT709_YCbCrCONV, CLR); + } else if (bColorimetry == SiI_RX_ITU_709) { + siiIIC_RX_RWBitsInByteP0(RX_VID_CTRL_ADDR, + RX_BIT_BT709_RGBCONV | RX_BIT_BT709_YCbCrCONV, SET); + } else { + bEWCode = SiI_WC_Colorimetry; + } + return bEWCode; +} +/*------------------------------------------------------------------------------ + * Function Name: siiGetVideoResId + * Function Description: provides short resolution info for user layer + *---------------------------------------------------------------------------- + */ +BYTE siiGetVideoResId(BYTE bVidResIndex) +{ + BYTE bVideoResId; + BYTE bVIC; + + if (bVidResIndex < PC_BASE) { + bVideoResId = VModeTables[bVidResIndex].ModeId.Mode_C1; + + if (VModeTables[bVidResIndex].ModeId.Mode_C2) { + if (SiI_Inf.AVI.bAVI_State == SiI_RX_GotAVI) { + /* get Video Id Code form Info Frame Packet */ + bVIC = siiGetVIC(); + if ((bVIC == bVideoResId) || + (bVIC == bVideoResId + 1)) + bVideoResId = bVIC; + else + bVideoResId |= SiI_CE_orNextRes; + } else + bVideoResId |= SiI_CE_orNextRes; + } + bVideoResId |= SiI_CE_Res; + } else { + bVideoResId = bVidResIndex - PC_BASE; + } + return bVideoResId; +} + +/*------------------------------------------------------------------------------ + * Function Name: ConvertInterlaceFieldsIntoFrames + * Function Description: + *---------------------------------------------------------------------------- + */ +static WORD ConvNLinesInFieldIntoNLinesInFrame(WORD bLines) +{ + if (SiI_Inf.Sync.RefrTypeVHPol & INTERLACE_MASK) { + if (bLines & 0x0001) { /* if odd */ + bLines += bLines; + } else { + /* calculate total number of lines in frame */ + bLines += (bLines + 1); + } + } + return bLines; +} +/*------------------------------------------------------------------------------ + * Function Name: ConvertClocksToPixels + * Function Description: For pixel replicated modes it's need to convert clocks + * to pixels for not replicated modes clocks equal + * to pixels + *---------------------------------------------------------------------------- + */ +static void ConvertClocksToPixels(WORD *wpPixClocks) +{ + if (SiI_Ctrl.bShadowPixRepl == 0x01) + *wpPixClocks >>= 1; + else if (SiI_Ctrl.bShadowPixRepl == 0x02) + *wpPixClocks /= 3; + else if (SiI_Ctrl.bShadowPixRepl == 0x03) + *wpPixClocks >>= 2; +} + +#ifdef SII_NO_RESOLUTION_DETECTION + +/*------------------------------------------------------------------------------ + * Function Name: siiGetVideoInputResolutionFromRegisters + * Function Description: Using this function use gets extended + * information about detected video resolution + * Accepts: BYTE, resolution index in table + * Returns: BYTE *, pointer on resolution data + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetVideoInputResolutionromRegisters(BYTE *pbVideoResInfo) +{ + WORD wAux; + BYTE abData[4]; + + pbVideoResInfo[0] = SiI_ResNotDetected; + /* added for new API */ + pbVideoResInfo[1] = (SiI_Inf.AVI.bPixRepl << 4); + pbVideoResInfo[1] |= SiI_Inf.Sync.RefrTypeVHPol; + pbVideoResInfo[2] = SiI_Inf.Sync.bFPix; /* GetFPixClock(); */ + pbVideoResInfo[3] = (BYTE)(SiI_Inf.Sync.VFreq & 0x00FF); + pbVideoResInfo[4] = (BYTE)(SiI_Inf.Sync.VFreq >> 8); + + siiReadBlockHDMIRXP0(RX_RES_ACTIVE_ADDR, 4, abData); + + wAux = abData[0] | (abData[1] << 8); + ConvertClocksToPixels(&wAux); + pbVideoResInfo[5] = (BYTE)(wAux & 0x00FF); + pbVideoResInfo[6] = (BYTE)((wAux >> 8) & 0x000F); + + wAux = ConvNLinesInFieldIntoNLinesInFrame(abData[2] | (abData[3] << 8)); + + pbVideoResInfo[7] = (BYTE)(wAux & 0x00FF); + pbVideoResInfo[8] = (BYTE)((wAux >> 8) & 0x000F); + + wAux = SiI_Inf.Sync.ClocksPerLine; + ConvertClocksToPixels(&wAux); + pbVideoResInfo[9] = (BYTE)(wAux & 0x00FF); + pbVideoResInfo[10] = (BYTE)((wAux >> 8) & 0x000F); + + wAux = ConvNLinesInFieldIntoNLinesInFrame(SiI_Inf.Sync.HTot); + + pbVideoResInfo[11] = (BYTE)(wAux & 0x00FF); + pbVideoResInfo[12] = (BYTE)((wAux >> 8) & 0x000F); +} +#endif +/*------------------------------------------------------------------------------ + * Function Name: siiGetVideoInputResolution + * Function Description: Using this function use gets extended + * information about detected video resolution + * Accepts: BYTE, resolution index in table + * Returns: BYTE *, pointer on resolution data + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiGetVideoInputResolution(BYTE bVidResIndex, BYTE *pbVideoResInfo) +{ + WORD wAux; + + pbVideoResInfo[0] = siiGetVideoResId(bVidResIndex); + /* YMA changed to support API rev2 + * pbVideoResInfo[1] = SiI_Inf.Sync.RefrTypeVHPol; + */ + pbVideoResInfo[1] = (SiI_Inf.AVI.bPixRepl << 4); + pbVideoResInfo[1] |= SiI_Inf.Sync.RefrTypeVHPol; + + pbVideoResInfo[2] = siiGetPixClockFromTables(bVidResIndex); + + pbVideoResInfo[3] = (BYTE) + (VModeTables[bVidResIndex].Tag.VFreq & 0x00FF); + pbVideoResInfo[4] = (BYTE) + ((VModeTables[bVidResIndex].Tag.VFreq >> 8) & 0x00FF); + + wAux = VModeTables[bVidResIndex].Res.H; + /* for pixel replicated resolutions take out replicated pixels */ + ConvertClocksToPixels(&wAux); + pbVideoResInfo[5] = (BYTE)(wAux & 0x00FF); /* active number of pixels */ + pbVideoResInfo[6] = (BYTE)((wAux >> 8) & 0x000F); + + pbVideoResInfo[7] = (BYTE)(VModeTables[bVidResIndex].Res.V & 0x00FF); + pbVideoResInfo[8] = (BYTE) + ((VModeTables[bVidResIndex].Res.V >> 8) & 0x000F); + + wAux = VModeTables[bVidResIndex].Tag.Total.Pixels; + /* for pixel replicated resolutions take out replicated pixels */ + ConvertClocksToPixels(&wAux); + pbVideoResInfo[9] = (BYTE)(wAux & 0x00FF); /* total number of pixels */ + pbVideoResInfo[10] = (BYTE)((wAux >> 8) & 0x000F); + + wAux = ConvNLinesInFieldIntoNLinesInFrame( + VModeTables[bVidResIndex].Tag.Total.Lines); + + pbVideoResInfo[11] = (BYTE)(wAux & 0x00FF); + pbVideoResInfo[12] = (BYTE)((wAux >> 8) & 0x000F); + +} +/*------------------------------------------------------------------------------ + * Function Name: siiSetVidResDependentVidOutputVormat + * Function Description: Functions sets Video Resolution dependent parameters: + * Pix Replication Divider, Output Divider, + * Color Converter Type (BT601 vs. BT701) + * Accepts: Video Resolution Id, Video Path Select, AVI State + * Returns: Error code byte + * Globals: bColorimetry, bPixRepl + *---------------------------------------------------------------------------- + */ + +BYTE siiSetVidResDependentVidOutputFormat(BYTE bVidResId, + BYTE bVideoPathSelect, BYTE bAVI_State) +{ + BYTE bECode = FALSE; + + /* PC modes and CE have different blank levels */ + SetVideoBlankLevel(SiI_Inf.bVResId); + if ((bAVI_State == SiI_RX_NoAVI) || + (SiI_Inf.AVI.bColorimetry == SiI_RX_ColorimetryNoInfo)) { + SiI_Inf.AVI.bColorimetry = GetColorimetryFormVidRes(bVidResId); + } + SetColorimetry(SiI_Inf.AVI.bColorimetry); + + siiSetVideoPathColorSpaceDependent(SiI_Ctrl.VideoF.bOutputVideoPath, + SiI_Inf.AVI.bInputColorSpace); + + if (SiI_Inf.AVI.bAVI_State == SiI_RX_NoAVI) { + SiI_Inf.AVI.bPixRepl = + siiGetPixReplicationFormVidRes(bVidResId); + } + if (!bECode) { + siiSetVidResDependentVidPath(SiI_Inf.AVI.bPixRepl, + bVideoPathSelect); /* TODO name */ + + if ((SiI_Ctrl.VideoF.bOutputSyncSelect == SiI_RX_AVC_SOGY) && + siiIsInterlaceMode(bVidResId)) { + /* YMA changed by vk for in new API */ + if ((SiI_Ctrl.bDevId == RX_SiI9021) || + (SiI_Ctrl.bDevId == RX_SiI9031)) + ConfigureSyncOnYForInretlaceModes(bVidResId); + else + siiWarningHandler(SiI_WC_ChipNoCap); + } + } + return bECode; +} + +/*------------------------------------------------------------------------------ + * Function Name: PrintVModeParameters() + * Function Description: This function prints out found video mode information, + * used for debugging purpose + *---------------------------------------------------------------------------- + */ +/* #ifdef SII_DUMP_UART */ +void siiPrintVModeParameters(BYTE Index, BYTE SearchRes) +{ + char str[200]; + int len = 0; + + if (SearchRes) { + len += sprintf(str+len, "sii9135 vmode:\n"); + + if (SearchRes == 2) { + len += sprintf(str+len, + "Video Mode has polarity mismatch\n"); + } + if (SiI_Inf.bGlobStatus & SiI_RX_GlobalHDMI_Detected) { + len += sprintf(str+len, "HDMI MODE\n"); + } else { + len += sprintf(str+len, "DVI MODE "); + len += sprintf(str+len, + "v. mode detected, AVI will be ignored\n"); + } + if (Index < PC_BASE) + len += sprintf(str+len, "CE Space:"); + else + len += sprintf(str+len, "PC Space:"); + len += sprintf(str+len, " Mode ROM-%i", + (int)VModeTables[Index].ModeId.Mode_C1); + if (VModeTables[Index].ModeId.Mode_C2) { + len += sprintf(str+len, " or %i", + (int)VModeTables[Index].ModeId.Mode_C2); + } + if (VModeTables[Index].ModeId.SubMode) { + len += sprintf(str+len, " Sub mode: %i", + VModeTables[Index].ModeId.SubMode); + } + len += sprintf(str+len, " Resolution: %i x %i@%i\n", + VModeTables[Index].Res.H, VModeTables[Index].Res.V, + VModeTables[Index].Tag.VFreq); + RXEXTPR("%s: %s\n", __func__, str); + } +} +/* #endif */ + + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.h new file mode 100644 index 0000000..bc18596 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/SiIVidRes.h @@ -0,0 +1,206 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _SII_VID_RES_ +#define _SII_VID_RES_ + +#include "SiITypeDefs.h" +#include "SiIRXAPIDefs.h" + +struct SyncInfoType_s { + + WORD ClocksPerLine; + WORD HTot; + WORD VFreq; + BYTE RefrTypeVHPol; + BYTE bFPix; + +}; + + +/*------------------------------------------------------------------*/ +struct ModeIdType_s { + BYTE Mode_C1; + BYTE Mode_C2; + BYTE SubMode; +}; +/*------------------------------------------------------------------*/ +struct PxlLnTotalType_s { + WORD Pixels; + WORD Lines; +}; +/*------------------------------------------------------------------*/ +struct HVPositionType_s { + WORD H; + WORD V; +}; +/*------------------------------------------------------------------*/ +struct HVResolutionType_s { + WORD H; + WORD V; +}; +/*------------------------------------------------------------------*/ +struct TagType_s { + BYTE RefrTypeVHPol; + WORD VFreq; + struct PxlLnTotalType_s Total; +}; +/*------------------------------------------------------------------*/ +struct _656Type_s { + BYTE IntAdjMode; + WORD HLength; + WORD VLength; + WORD Top; + WORD Dly; + WORD HBit2HSync; + WORD VBit2VSync; + WORD Field2Offset; + +}; +/*------------------------------------------------------------------*/ +struct VModeInfoType_s { + struct ModeIdType_s ModeId; + BYTE PixClk; + struct TagType_s Tag; + struct HVResolutionType_s Res; + BYTE PixRepl; +}; + +/*------------------------------------------------------------------*/ +struct InterlaceCSyncType_s { + + WORD CapHalfLineCnt; + WORD PreEqPulseCnt; + WORD SerratedCnt; + WORD PostEqPulseCnt; + BYTE Field2BackPorch; + +}; + +/* Aspect ratio */ +#define _4 0 /* 4:3 */ +#define _4or16 1 /* 4:3 or 16:9 */ +#define _16 2 /* 16:9 */ + +#define NSM 0 /* no sub. mode */ + + +#define VGA 0 + +#ifdef SII_PCMODES + +#ifdef SII_861C_MODES +#define PC_BASE (28 + 15) +#define NMODES (PC_BASE + 54) /* CEA 861C + PC Video Modes */ + +#else +#define PC_BASE 28 +#define NMODES (PC_BASE + 54) /* CEA 861B + PC Video Modes */ + +#endif + +#else /* CEA modes only */ + +#ifndef SII_861C_MODES /* only CEA 861B are included */ + +#define PC_BASE 28 +#define NMODES 28 /* CEA 861 B Video Modes */ + +#endif + +#ifdef SII_861C_MODES + +#define PC_BASE (28 + 15) +#define NMODES PC_BASE /* CEA 861 C Video Modes */ +#endif + +#endif + +#define _480i_60Hz 4 +#define _576i_50Hz 19 + + +#define ProgrVPosHPos 0x03 +#define ProgrVNegHPos 0x02 +#define ProgrVPosHNeg 0x01 +#define ProgrVNegHNeg 0x00 +#define InterlaceVPosHPos 0x07 +#define InterlaceVNegHPos 0x06 +#define InterlaceVPosHNeg 0x05 +#define InterlaceVNegHNeg 0x04 +#define SiI_InterlaceMask 0x04 + +#ifdef SII_861C_MODES + +#define H_TOLERANCE 50 /* +- 500 Hz */ +#define V_TOLERANCE 400 /* +- 4.0 Hz */ +#define LINES_TOLERANCE 15 +#define PIXELS_TOLERANCE 4 +#define CLK_TOLERANCE 5 +#define CHIP_OSC_CLK_MUL128 (3625216000) /* *1000 MHz */ + + +#define INTERLACE_VFREQ_LOW_LIMIT 2500 /* 25 Hz */ +#define PROGRESSIVE_VFREQ_LOW_LIMIT 2300 /* 23 Hz */ +#define INTERLACE_HFREQ_LOW_LIMIT 1500 /* 15 kHz */ +#define PROGRESSIVE_HFREQ_LOW_LIMIT 1500 /* 15 kHz */ +#define INTERLACE_VFREQ_HIGH_LIMIT 25000 /* 250 Hz */ +#define PROGRESSIVE_VFREQ_HIGH_LIMIT 25000 /* 250 Hz */ +#define INTERLACE_HFREQ_HIGH_LIMIT 7500 /* 75 kHz */ +#define PROGRESSIVE_HFREQ_HIGH_LIMIT 15000 /* 150 kHz */ +#define INTERLACE_MASK 0x04 + +#else + +#define H_TOLERANCE 50 /* +- 500 Hz */ +#define V_TOLERANCE 400 /* +- 4.0 Hz */ +#define LINES_TOLERANCE 15 +#define PIXELS_TOLERANCE 4 +#define CLK_TOLERANCE 5 +#define CHIP_OSC_CLK_MUL128 (3625216000) /* *1000 MHz */ + + +#define INTERLACE_VFREQ_LOW_LIMIT 2500 /* 25 Hz */ +#define PROGRESSIVE_VFREQ_LOW_LIMIT 2300 /* 23 Hz */ +#define INTERLACE_HFREQ_LOW_LIMIT 1500 /* 15 kHz */ +#define PROGRESSIVE_HFREQ_LOW_LIMIT 1500 /* 15 kHz */ +#define INTERLACE_VFREQ_HIGH_LIMIT 6500 /* 65 Hz */ +#define PROGRESSIVE_VFREQ_HIGH_LIMIT 10500 /* 105 Hz */ +#define INTERLACE_HFREQ_HIGH_LIMIT 5500 /* 55 kHz */ +#define PROGRESSIVE_HFREQ_HIGH_LIMIT 9700 /* 97 kHz */ +#define INTERLACE_MASK 0x04 + +#endif + +#define GetRefrTypeHVPol() siiReadByteHDMIRXP0(RX_VID_STAT_ADDR) +#define GetXClock() siiReadByteHDMIRXP0(RX_VID_XCNT_ADDR) +#define GetXClockW() siiReadWordHDMIRXP0(RX_VID_XCNT_ADDR - 1) + +extern ROM const struct VModeInfoType_s VModeTables[NMODES]; +extern ROM const struct InterlaceCSyncType_s InterlaceCSync[3]; + + +BYTE siiVideoModeDetection(BYTE *pbIndex, struct SyncInfoType_s *SyncInf); +BOOL siiCheckOutOfRangeConditions(struct SyncInfoType_s *SyncInfo); +BYTE siiSetVidResDependentVidOutputFormat(BYTE bVidResId, + BYTE bVideoPathSelect, BYTE bAVI_State); +void siiGetSyncInfo(struct SyncInfoType_s *SyncInfo); +BOOL siiCheckSyncDetect(void); +BOOL siiCheckClockDetect(void); +BYTE siiGetPixClockFromTables(BYTE bIndex); +BOOL siiCompareNewOldSync(struct SyncInfoType_s *OldSyncInfo, + struct SyncInfoType_s *NewSyncInfo); +void siiPrintVModeParameters(BYTE Index, BYTE SearchRes); +void siiGetVideoInputResolution(BYTE bVidResIndex, BYTE *pbVideoResInfo); +void siiGetVideoInputResolutionromRegisters(BYTE *pbVideoResInfo); +BYTE siiGetVideoResId(BYTE bVidResIndex); + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.c new file mode 100644 index 0000000..0b52d8e --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.c @@ -0,0 +1,90 @@ +/*------------------------------------------------------------------------------ + * Module Name: AT_EEPROM + * + * Module Description: this low level driver for reading/writing + * Atmel AT89C51ID2 EEPROM + * + * Copyright © 2005 Silicon Image, Inc. + * All rights reserved. + *---------------------------------------------------------------------------- + */ +#include "UAT_EEPROM.h" + +/*------------------------------------------------------------------------------ + * Function Name: siiReadByteInternEEPROM + * Function Description: This function reads one byte of Internal EEPROM of + * AT89C51ID2 Internal EEPROM uses XDATA adressing of + * 8051, when EEPROM XDATA is selected RAM XDATA is not + * accessible. Input parameters are should be converted + * to DATA segment before switching to EEPROM XDATA + * segment + * Accepts: wAddr, address of EEPROM location + * Returns: pointer on byte which was received form EEPROM + * Globals: none + *---------------------------------------------------------------------------- + */ +void siiReadByteInternEEPROM(WORD wAddr, BYTE *pbData) +{ +#ifdef USE_InternEEPROM + BYTE *abEEPROM; + WORD wDAddr; + BYTE bDData; + + wDAddr = wAddr; + + halDisableMCUInterrupts(); + halIntEEPROM_Enable(); + + abEEPROM = (BYTE *)wAddr; + + while (halIsIntEEPROM_Busy()) + ; + + bDData = *abEEPROM; + + halIntEEPROM_Disable(); + halEnableMCUInterrupts(); + *pbData = bDData; +#endif +} +/*------------------------------------------------------------------------------ + * Function Name: siiWriteByteInternEEPROM + * Function Description: This function writes one byte of Internal EEPROM of + * AT89C51ID2 Internal EEPROM uses XDATA adressing of + * 8051, when EEPROM XDATA is selected RAM XDATA is not + * accessible. Input parameters are should be converted + * to DATA segment before switching to EEPROM XDATA + * segment + * Accepts: wAddr, address of EEPROM location + * pointer on byte which will be written into EEPROM + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ + +void siiWriteByteInternEEPROM(WORD wAddr, BYTE bData) +{ +#ifdef USE_InternEEPROM + BYTE xdata *abEEPROM; + + WORD data wDAddr; + BYTE bDData; + + wDAddr = wAddr; + bDData = bData; + + halDisableMCUInterrupts(); + halIntEEPROM_Enable(); + + abEEPROM = wAddr; + + while (halIsIntEEPROM_Busy()) + ; + + *abEEPROM = bDData; + + halIntEEPROM_Disable(); + halEnableMCUInterrupts(); +#endif +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.h new file mode 100644 index 0000000..d28b4d9 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAT_EEPROM.h @@ -0,0 +1,16 @@ +#ifndef SII_AT_EEPROM +#define SII_AT_EEPROM + +#include "SiITypeDefs.h" +/*#include "AT89C51XD2.h" */ + +#define halDisableMCUInterrupts() +#define halEnableMCUInterrupts() +#define halIsIntEEPROM_Busy() +#define halIntEEPROM_Enable() +#define halIntEEPROM_Disable() + +void siiWriteByteInternEEPROM(WORD wAddr, BYTE bData); +void siiReadByteInternEEPROM(WORD wAddr, BYTE *pbData); + +#endif diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAudDAC.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAudDAC.h new file mode 100644 index 0000000..4822b9f --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UAudDAC.h @@ -0,0 +1,33 @@ +/******************************************************************************/ +/* Copyright (c) 2002-2005, Silicon Image, Inc. All rights reserved. */ +/* No part of this work may be reproduced, modified, distributed, */ +/* transmitted, transcribed, or translated into any language or computer */ +/* format, in any form or by any means without written permission of: */ +/* Silicon Image, Inc., 1060 East Arques Avenue, Sunnyvale, California 94085 */ +/******************************************************************************/ +#ifndef _SII_AUDDAC_ +#define _SII_AUDDAC_ + +#include "SiITypeDefs.h" +#include "SiIHLVIIC.h" + +#define siiWriteByteAudDAC(ADDR, DATA) hlWriteByte_8BA(0x26, ADDR, DATA) + +#define AUDDAC_CTRL1_ADDR 0x00 +#define AUDDAC_CTRL2_ADDR 0x01 +#define AUDDAC_SPEED_PD_ADDR 0x02 +#define AUDDAC_CTRL3_ADDR 0x0A + +#define AUDDAC_RST 0x00 +#define AUDDAC_NORM_OP 0x4F + +#define ADAC_DSD_MODE 0x18 +#define ADAC_PCM_MODE 0x00 + + +void WakeUpAudioDAC(void); +void PowerDownAudioDAC(void); +void halSetAudioDACMode(BYTE bMode); + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.c new file mode 100644 index 0000000..a374b5b --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.c @@ -0,0 +1,335 @@ +/*------------------------------------------------------------------------------ + * Module Name: UCfgRX + * + * Module Description: Intit Users EEPROM, intit RX with API setting written + * into EEPROM + * + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +/* #include */ +#include "../hdmirx_ext_drv.h" + +#include "UCfgRX.h" +#include "UEEPROM.h" +#include "SiIRX_API.h" +#include "SiIRXAPIDefs.h" +#include "SiIHLVIIC.h" +#include "SiIVidIn.h" + +#define __AMLOGIC__ 1 +/*------------------------------------------------------------------------------ + * Function Name: siiGetPCB_Id() + * Function Description: this function reads Board Id from EEPROM + * + * Accepts: none + * Returns: BYTE, Board Id + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiGetPCB_Id(void) +{ + BYTE bData = 0; + +#ifdef __AMLOGIC__ + bData = SiI_CP9135; +#else + siiBlockReadEEPROM(SII_PCB_ID_ADDR, 1, &bData); +#endif + return bData; +} +/*------------------------------------------------------------------------------ + * Function Name: InitEEPROMWithDefaults + * Function Description: + *---------------------------------------------------------------------------- + */ +void InitEEPROMWithDefaults(void) +{ + BYTE abData[6]; + + abData[0] = RX_API_ID_L; + abData[1] = RX_API_ID_H; + siiBlockWriteEEPROM(SII_EEPROM_ID_ADDR, 2, abData); /* write EEPROM ID*/ + abData[0] = SiI_CP9125; + /* abData[0] = SiI_CP9135; */ + + siiBlockWriteEEPROM(SII_PCB_ID_ADDR, 1, abData); /* write PCB ID */ + + /* YMA HBR DSD PCM */ + abData[0] = (MClock_256Fs << 4) | (MClock_512Fs << 2) | + MClock_256Fs | SiI_RX_InvertOutputVidClock; + abData[1] = SiI_RX_CD_24BPP; + siiBlockWriteEEPROM(SII_RX_INIT_SYS_ADDR, 2, abData); + + abData[0] = SiI_RX_VInCh1; + siiBlockWriteEEPROM(SII_RX_VIDEO_INPUT, 1, abData); + + abData[0] = SiI_RX_P_RGB; + abData[1] = SiI_RX_SS_SeparateSync; + abData[2] = SiI_RX_SC_NoInv; + abData[3] = SiI_RX_AVC_NoPedestal; + siiBlockWriteEEPROM(SII_RX_VIDEO_OUTPUT_F, 4, abData); + + abData[0] = (BYTE)(SiI_RX_AOut_Default & 0xFF); + abData[1] = (BYTE)((SiI_RX_AOut_Default >> 8) & 0xFF); + abData[2] = (BYTE)(SiI_RX_AOut_I2S_I2SDefault & 0xFF); + abData[3] = (BYTE)((SiI_RX_AOut_I2S_I2SDefault >> 8) & 0xFF); + abData[4] = 0x00; + abData[5] = 0x22; /* YMA 2 added default value for DSDHBR format */ + /* YMA 2 change 5 -> 6 */ + siiBlockWriteEEPROM(SII_RX_AUDIO_OUTPUT_F, 6, abData); + +} + +/*------------------------------------------------------------------------------ + * Function Name: InitTX + * Function Description: this functio takes TX out of Power Down mode + *---------------------------------------------------------------------------- + */ +static void InitTX(BYTE bBoardID) +{ + if (bBoardID == SiI_CP9000) { + hlWriteByte_8BA(0x72, 0x08, 0x35); + } else if ((bBoardID == SiI_FPGA_IP11) || + (bBoardID == SiI_CP9135 || bBoardID == SiI_CP9125) || + (bBoardID == SiI_CP9133)) { + RXEXTPR("InitTX\n"); + hlWriteByte_8BA(0x70, 0x08, 0x37); + hlWriteByte_8BA(0x70, 0x09, 0x11); + } +} +/*------------------------------------------------------------------------------ + * Function Name: PrintMasterClock + * Function Description: This function prints output master clock + *---------------------------------------------------------------------------- + */ +static void PrintMasterClock(BYTE bMasterClock) +{ + switch (bMasterClock) { + case MClock_128Fs: + pr_info(" 128 * Fs\n"); + break; + case MClock_256Fs: + pr_info(" 256 * Fs\n"); + break; + case MClock_384Fs: + pr_info(" 384 * Fs\n"); + break; + case MClock_512Fs: + pr_info(" 512 * Fs\n"); + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: PrintOutputClorDepth + * Function Description: This function prints output color depth + *---------------------------------------------------------------------------- + */ +static void PrintOutputColorDepth(BYTE bOutColorDepth) +{ + switch (bOutColorDepth) { + case SiI_RX_CD_24BPP: + pr_info(" 24 bit per pixel\n"); + break; + case SiI_RX_CD_30BPP: + pr_info(" 30 bit per pixel\n"); + break; + case SiI_RX_CD_36BPP: + pr_info(" 36 bit per pixel\n"); + break; + } +} +/*------------------------------------------------------------------------------ + * Function Name: PrintIntilizeSystemWith + * Function Description: This function prints out parameters of intilization + * RX API instance + *---------------------------------------------------------------------------- + */ +static void PrintIntilizeSystemWith(BYTE *pbInitData) +{ + RXEXTPR("RX API intance intilized with:\n"); + RXEXTPR("PCM Master Clock output:\n"); + PrintMasterClock(pbInitData[0] & 0x03); + RXEXTPR("DSD Master Clock output:\n"); + PrintMasterClock((pbInitData[0] >> 2) & 0x03); + RXEXTPR("HBR Master Clock output:\n"); + PrintMasterClock((pbInitData[0] >> 4) & 0x03); + RXEXTPR("FPGA support:\n"); + if (pbInitData[0] & SiI_RX_FPGA) + RXEXTPR(" yes\n"); + else + RXEXTPR(" no\n"); + RXEXTPR("Video Output clock:\n"); + if (pbInitData[0] & SiI_RX_InvertOutputVidClock) + RXEXTPR(" yes\n"); + else + RXEXTPR(" no\n"); + RXEXTPR("Output Color Depth:\n"); + PrintOutputColorDepth(pbInitData[1] & 0x03); +} + +/*------------------------------------------------------------------------------ + * Function Name: siiRXAPIConfig + * Function Description: + * + *---------------------------------------------------------------------------- + */ +static BYTE siiRXAPIConfig(void) +{ + BYTE abData[6]; + BYTE bError; + WORD wDevId; + +#ifdef __AMLOGIC__ + abData[0] = (MClock_256Fs << 4) | (MClock_512Fs << 2) | MClock_256Fs | + SiI_RX_InvertOutputVidClock; + abData[1] = SiI_RX_CD_24BPP; +#else + siiBlockReadEEPROM(SII_RX_INIT_SYS_ADDR, 2, abData); +#endif + + bError = SiI_RX_InitializeSystem(abData); + + if (!(bError & SiI_EC_Mask)) { + /* VG added for printout system config */ + PrintIntilizeSystemWith(abData); + + SiI_RX_GetAPI_Info(abData); + wDevId = abData[4] | (abData[5] << 8); + +#ifdef __AMLOGIC__ + abData[0] = SiI_RX_VInCh1; +#else + siiBlockReadEEPROM(SII_RX_VIDEO_INPUT, 1, abData); +#endif + + if (wDevId == SiI9011) + abData[0] = SiI_RX_VInCh1; + + /* YMA added to avoid reinit system again in the SetVideoInput() + * at start up. + * not need to reinitialize the system as the changing + * channel should do + */ + /* bError = SiI_RX_SetVideoInput(abData[0]); */ + SiI_Ctrl.bVidInChannel = abData[0]; + bError = siiInitVideoInput(SiI_Ctrl.bVidInChannel); + /* YMA end of modify */ + + if (!(bError & SiI_EC_Mask)) { +#ifdef __AMLOGIC__ + /* SiI_RX_P_YCbCr422;//SiI_RX_P_RGB; */ + abData[0] = SiI_RX_P_YCbCr422_MUX8B; + abData[1] = SiI_RX_SS_SeparateSync; + abData[2] = SiI_RX_SC_NoInv; + abData[3] = SiI_RX_AVC_NoPedestal; +#else + siiBlockReadEEPROM(SII_RX_VIDEO_OUTPUT_F, 4, abData); +#endif + if ((wDevId == SiI9011) || (wDevId == SiI9023) || + (wDevId == SiI9033) || + (SiI_Ctrl.bDevId == RX_SiI9133) || + (SiI_Ctrl.bDevId == RX_SiI9135 || + SiI_Ctrl.bDevId == RX_SiI9125) || + (SiI_Ctrl.bDevId == RX_SiIIP11)) { + /* set video digital output because no analog + *video output suuport + */ + abData[3] = SiI_RX_AVC_Digital_Output; + } + bError = SiI_RX_SetVideoOutputFormat(abData[0], + abData[1], + abData[2], + abData[3]); + if (!(bError & SiI_EC_Mask)) { + /* siiBlockReadEEPROM(SII_RX_AUDIO_OUTPUT_F, + * 5, abData); //0x30 + */ +#ifdef __AMLOGIC__ + abData[0] = (BYTE)(SiI_RX_AOut_Default & 0xFF); + abData[1] = (BYTE) + ((SiI_RX_AOut_Default >> 8) & 0xFF); + abData[2] = (BYTE) + (SiI_RX_AOut_I2S_I2SDefault & 0xFF); + abData[3] = (BYTE) + ((SiI_RX_AOut_I2S_I2SDefault >> 8) & + 0xFF); + abData[4] = 0x00; + /*YMA 2 added default value for DSDHBR format */ + abData[5] = 0x22; +#else + /* YMA 2 added DSDHBR format byte */ + siiBlockReadEEPROM(SII_RX_AUDIO_OUTPUT_F, + 6, abData); +#endif + bError = SiI_RX_SetAudioOutputFormat( + (WORD)(abData[0] | (abData[1] << 8)), + (WORD)(abData[2] | (abData[3] << 8)), + abData[4], + /* YMA 2 added DSDHBR format byte */ + abData[5]); + + } + } + } + bError &= SiI_EC_Mask; + return bError; + +} +/*------------------------------------------------------------------------------ + * Function Name: siiResoreSavedRXConfiguration + * Function Description: + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiRXConfig(void) +{ + BYTE abData[2]; + BYTE bError = false; + + RXEXTPR("\n Init application...\n"); + +#ifdef __AMLOGIC__ + siiRXAPIConfig(); + abData[0] = siiGetPCB_Id(); + if ((abData[0] == SiI_CP9000) || (abData[0] == SiI_FPGA_IP11)) + InitTX(abData[0]); +#else + bError = siiFindEEPROM(); + if (!bError) { + bError = siiBlockReadEEPROM(SII_EEPROM_ID_ADDR, 2, abData); + if (!bError) { + RXEXTPR("\n Get EEPROM settings\n"); + if ((abData[0] != RX_API_ID_L) || + (abData[1] != RX_API_ID_H)) { + InitEEPROMWithDefaults(); + } + bError = siiRXAPIConfig(); + + if (!bError) { + /* write PCB ID */ + siiBlockReadEEPROM(SII_PCB_ID_ADDR, 1, abData); + if ((abData[0] == SiI_CP9000) || + (abData[0] == SiI_FPGA_IP11)) + InitTX(abData[0]); + } + } + } else { + bError = TRUE; + RXEXTERR("No Ack from configuration EEPROM,\n"); + RXEXTERR("use API to init RX\n"); + } +#endif + return bError; + +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.h new file mode 100644 index 0000000..22bb772 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UCfgRX.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +#include "UGlob.h" + + +#define SII_EEPROM_ID_ADDR 0x00 + +#define RX_API_ID_L 0x20 +#define RX_API_ID_H 0x93 + +#define SII_RX_INIT_SYS_ADDR 0x10 +#define SII_RX_VIDEO_INPUT 0x18 +#define SII_RX_VIDEO_OUTPUT_F 0x20 +#define SII_RX_AUDIO_OUTPUT_F 0x30 + +BYTE siiGetPCB_Id(void); +BYTE siiRXConfig(void); + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.c new file mode 100644 index 0000000..a13963d --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.c @@ -0,0 +1,292 @@ +/*------------------------------------------------------------------------------ + * Module Name: UDebugHLIIC + * + * Module Description: contains IIC functions which used outside of API + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "UDebugHLIIC.h" +/*#include "SiISW_IIC.h"*/ +#include "SiIIICDefs.h" +#include "SiIHAL.h" + +/*---------------------------------------------------------------------------*/ +#ifdef _BIGEEPROM_ +#ifdef _BLOCK_16BA +BYTE BlockWrite_16BA(I2CCommandType *I2CCommand) +{ + BYTE i, bState; + + if (!(I2CCommand->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(I2CCommand->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + I2CSendByte(I2CCommand->RegAddrH); + I2CSendByte(I2CCommand->RegAddrL); + } + for (i = 0; i < I2CCommand->NBytes; i++) { + I2CSendByte((BYTE)(I2CCommand->Data[i])); + I2CCommand->RegAddrL++; + if (!I2CCommand->RegAddrL) { + I2CCommand->RegAddrH++; + if ((I2CCommand->RegAddrL & ALIGN24C264) == 0) { + I2CSendStop(); + I2CSendAddr(I2CCommand->SlaveAddr, IIC_WRITE); + I2CSendByte(I2CCommand->RegAddrH); + I2CSendByte(I2CCommand->RegAddrL); + } + } + } + if (!(I2CCommand->Flags & FLG_NOSTOP)) + I2CSendStop(); + + return IIC_OK; + +} +//------------------------------------------------------------------------------ +BYTE BlockRead_16BA(I2CCommandType *I2CCommand) +{ + BYTE i, bState; + + if (!(I2CCommand->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(I2CCommand->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + I2CSendByte(I2CCommand->RegAddrH); + I2CSendByte(I2CCommand->RegAddrL); + I2CSendStop(); + } + I2CSendAddr(I2CCommand->SlaveAddr, IIC_READ); + for (i = 0; i < I2CCommand->NBytes-1; i++) + I2CCommand->Data[i] = I2CGetByte(); + if (I2CCommand->Flags & FLG_NOSTOP) { + I2CCommand->Data[i] = I2CGetByte(); + } else { + I2CCommand->Data[i] = I2CGetLastByte(); + I2CSendStop(); + } + return IIC_OK; + +} + +//----------------------------------------------------------------------------- + + +BYTE BlockRead_16BAS(struct I2CShortCommandType_s *IIC, BYTE *Data) +{ + BYTE i, bState; + + if (!(IIC->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(IIC->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + bState = I2CSendByte(IIC->RegAddrH); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + I2CSendByte(IIC->RegAddrL); + bState = I2CSendAddr(IIC->SlaveAddr, IIC_READ); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + } + for (i = 0; i < IIC->NBytes - 1; i++) + Data[i] = I2CGetByte(); + if (IIC->Flags & FLG_NOSTOP) { + Data[i] = I2CGetByte(); + } else { + Data[i] = I2CGetLastByte(); + I2CSendStop(); + } + return IIC_OK; + +} + +//----------------------------------------------------------------------------- + +BYTE BlockWrite_16BAS(struct I2CShortCommandType_s *IIC, BYTE *Data) +{ + BYTE i, bState; + + if (!(IIC->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(IIC->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + bState = I2CSendByte(IIC->RegAddrH); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + I2CSendByte(IIC->RegAddrL); + } + for (i = 0; i < IIC->NBytes; i++) + I2CSendByte(Data[i]); + if (!(IIC->Flags & FLG_NOSTOP)) + I2CSendStop(); + return IIC_OK; + +} +#endif +#ifdef _DEAD_CODE_ +/*-----------------------------------------------------------------------*/ +void WriteWord_16BA(BYTE SlaveAddr, WORD RegAddr, WORD Data) +{ + I2CSendAddr(SlaveAddr, IIC_WRITE); + I2CSendByte((BYTE)(RegAddr >> 8)); + I2CSendByte((BYTE)(RegAddr & 0xFF)); + I2CSendByte((BYTE)(Data & 0xFF)); + I2CSendByte((BYTE)(Data >> 8)); + I2CSendStop(); + +} + +/*-----------------------------------------------------------------------*/ +void WriteByte_16BA(BYTE SlaveAddr, WORD RegAddr, BYTE Data) +{ + I2CSendAddr(SlaveAddr, IIC_WRITE); + I2CSendByte((BYTE)(RegAddr >> 8)); + I2CSendByte((BYTE)(RegAddr & 0xFF)); + I2CSendByte(Data); + I2CSendStop(); + +} + +/*-------------------------------------------------------------------*/ +WORD ReadWord_16BA(BYTE SlaveAddr, WORD RegAddr) +{ + WORD Data; + + I2CSendAddr(SlaveAddr, IIC_WRITE); + I2CSendByte((BYTE)RegAddr >> 8); + I2CSendByte((BYTE)(RegAddr & 0xff)); + I2CSendStop(); + I2CSendAddr(SlaveAddr, IIC_READ); + Data = I2CGetByte(); + Data |= (I2CGetLastByte() << 8); + I2CSendStop(); + return Data; + +} + +/*-------------------------------------------------------------------*/ +BYTE ReadByte_16BA(BYTE SlaveAddr, WORD RegAddr) +{ + BYTE Data; + + I2CSendAddr(SlaveAddr, IIC_WRITE); + I2CSendByte((BYTE)RegAddr >> 8); + I2CSendByte((BYTE)(RegAddr & 0xff)); + I2CSendStop(); + I2CSendAddr(SlaveAddr, IIC_READ); + Data = I2CGetLastByte(); + I2CSendStop(); + return Data; + +} +#endif + +#endif /* _end BIGEEPROM_ */ +/*---------------------------------------------------------------------------*/ +#ifdef _BLOCK_8BA +BYTE BlockRead_8BA(I2CCommandType *I2CCommand) +{ + BYTE i, bState; + + if (!(I2CCommand->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(I2CCommand->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + bState = I2CSendByte(I2CCommand->RegAddrL); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + bState = I2CSendAddr(I2CCommand->SlaveAddr, IIC_READ); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + } + for (i = 0; i < I2CCommand->NBytes-1; i++) + I2CCommand->Data[i] = I2CGetByte(); + if (I2CCommand->Flags & FLG_NOSTOP) { + I2CCommand->Data[i] = I2CGetByte(); + } else { + I2CCommand->Data[i] = I2CGetLastByte(); + I2CSendStop(); + } + return IIC_OK; + +} + +//----------------------------------------------------------------------------- +BYTE BlockWrite_8BA(I2CCommandType *I2CCommand) +{ + BYTE i, bState; + + if (!(I2CCommand->Flags & FLG_CONTD)) { + bState = GetI2CState(); + if (bState) + return IIC_CAPTURED; + bState = I2CSendAddr(I2CCommand->SlaveAddr, IIC_WRITE); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + bState = I2CSendByte(I2CCommand->RegAddrL); + if (bState) { + I2CSendStop(); + return IIC_NOACK; + } + } + for (i = 0; i < I2CCommand->NBytes; i++) + I2CSendByte(I2CCommand->Data[i]); + if (!(I2CCommand->Flags & FLG_NOSTOP)) + I2CSendStop(); + return IIC_OK; + +} + +//--------------------------------------------------------------------------- +BYTE DoRecoverySCLs(void) +{ + MakeSCLPulses(9); + return GetI2CStatus(); + +} +#endif + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.h new file mode 100644 index 0000000..66c37b0 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UDebugHLIIC.h @@ -0,0 +1,62 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +/*#include "UCom.h"*/ +#include "SiIHLVIIC.h" + +#ifndef _SIIDEBUGHLIIC_ +#define _SIIDEBUGHLIIC_ + +#define _BIGEEPROM_ +#define IIC_CAPTURED 1 +#define IIC_NOACK 2 +#define MDDC_CAPTURED 3 +#define MDDC_NOACK 4 +#define MDDC_FIFO_FULL 5 +#define IIC_OK 0 + +#define BUS_1 1 +#define BUS_0 0 + +#define EE_SLVADDR_1 0xA0 +#define EE_SLVADDR_2 0xA8 + +#define RX_SLV0 0x60 +#define RX_SLV1 0x68 +#define RX_AFE0 0x64 +#define RX_AFE1 0x6C + +#define SET 1 +#define CLR 0 + +/*#define _BLOCK_16BA*/ +/*#define _BLOCK_8BA*/ + +#ifdef _BLOCK_16BA +BYTE BlockWrite_16BA(I2CCommandType *I2CCommand); +BYTE BlockRead_16BA(I2CCommandType *I2CCommand); +BYTE BlockRead_16BAS(struct I2CShortCommandType_s *IIC, BYTE *Data); +BYTE BlockWrite_16BAS(struct I2CShortCommandType_s *IIC, BYTE *Data); +#endif +WORD ReadWord_16BA(BYTE SlaveAddr, WORD RegAddr); +BYTE ReadByte_16BA(BYTE SlaveAddr, WORD RegAddr); +void WriteByte_16BA(BYTE SlaveAddr, WORD RegAddr, BYTE Data); +void WriteWord_16BA(BYTE SlaveAddr, WORD RegAddr, WORD Data); + +#ifdef _BLOCK_8BA +BYTE BlockRead_8BA(I2CCommandType *I2CCommand); +BYTE BlockWrite_8BA(I2CCommandType *I2CCommand); +BYTE DoRecoverySCLs(void); +#endif + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.c new file mode 100644 index 0000000..97b68a1c --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.c @@ -0,0 +1,100 @@ +/*------------------------------------------------------------------------------ + * Module Name: UEEPROM + * + * Module Description: Reading/writing data from EEPROM + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ +#include "UEEPROM.h" +#include "SiIHLVIIC.h" + +#define EE_SLVADDR_1 0xA0 +#define EE_SLVADDR_2 0xA8 + +static BYTE bEEPROMSlaveAddr; + +/*------------------------------------------------------------------------------ + * Function Name: siiFindEEPROM + * Function Description: Trys to find EEPROM at various slave addresses + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiFindEEPROM(void) +{ + BYTE bError = FALSE; + + if (hlWaitForAck(EE_SLVADDR_1, 100)) + bEEPROMSlaveAddr = EE_SLVADDR_1; + else if (hlWaitForAck(EE_SLVADDR_2, 100)) + bEEPROMSlaveAddr = EE_SLVADDR_2; + else + bError = TRUE; + + return bError; +} +/*------------------------------------------------------------------------------ + * Function Name: siiBlockReadEEPROM + * Function Description: Reads block of Data from EEPROM + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ +BYTE siiBlockReadEEPROM(WORD Addr, BYTE NBytes, BYTE *Data) +{ + BYTE bError; + struct I2CShortCommandType_s I2CComm; + + I2CComm.SlaveAddr = bEEPROMSlaveAddr; + I2CComm.Flags = 0; + I2CComm.NBytes = NBytes; + I2CComm.RegAddrL = Addr & 0xFF; + I2CComm.RegAddrH = Addr >> 8; +#ifdef _BIGEEPROM_ + bError = BlockRead_16BAS((struct I2CShortCommandType_s *)&I2CComm, + Data); +#else + bError = hlBlockRead_8BAS((struct I2CShortCommandType_s *)&I2CComm, + Data); +#endif + return bError; +} +/*------------------------------------------------------------------------------ + * Function Name: siiBlockWriteEEPROM + * Function Description: Write block of DATA into EEPROM + * + * Accepts: none + * Returns: none + * Globals: none + *---------------------------------------------------------------------------- + */ + +void siiBlockWriteEEPROM(WORD Addr, BYTE NBytes, BYTE *Data) +{ + struct I2CShortCommandType_s I2CComm; + + I2CComm.SlaveAddr = bEEPROMSlaveAddr; + I2CComm.Flags = 0; + I2CComm.NBytes = NBytes; + I2CComm.RegAddrL = Addr & 0xFF; + I2CComm.RegAddrH = Addr >> 8; +#ifdef _BIGEEPROM_ + BlockWrite_16BAS((struct I2CShortCommandType_s *)&I2CComm, Data); +#else + hlBlockWrite_8BAS((struct I2CShortCommandType_s *)&I2CComm, Data); +#endif + + hlWaitForAck(bEEPROMSlaveAddr, 100); +} +/*----------------------------------------------------------------------*/ + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.h new file mode 100644 index 0000000..73fe808 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UEEPROM.h @@ -0,0 +1,20 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include "SiITypeDefs.h" +/*#include "UDebugHLIIC.h"*/ + + +BYTE siiFindEEPROM(void); +BYTE siiBlockReadEEPROM(WORD Addr, BYTE NBytes, BYTE *Data); +void siiBlockWriteEEPROM(WORD Addr, BYTE NBytes, BYTE *Data); + +#define siiWaitForAckEEPROM(TO) hlWaitForAck(EE_SLVADDR, TO) + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UGlob.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UGlob.h new file mode 100644 index 0000000..392d039 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/UGlob.h @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------------ + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#ifndef _UGLOB_ +#define _UGLOB_ +#include "../hdmirx_ext_drv.h" + +#define TASK_HDMI_RX_API 0 +#define TASK_KEYBOARD 1 +#define TASK_COMM 2 +#define LAST_TASK TASK_COMM + +#define SII_PCB_ID_ADDR 0x08 + +enum SiIPCBType_e { + + SiI_CP9011, + SiI_CP9031, + SiI_CP9041, + SiI_CP9000, + SiI_CP9133, + SiI_FPGA_IP11, + SiI_CP9135, + SiI_CP9125 + +}; + +/* communication */ + +enum SiI_com { + + WaitStartRX = 0, + ReadyRX = 1, + START_FRAME_RX = 's' +}; + + +#define RX_BUF_SIZE 26 /* used for communication */ + +extern IRAM BYTE RXBuffer[RX_BUF_SIZE]; /* Command buffer */ +extern BYTE bRxIndex; +extern BYTE bCommState; +extern BYTE bCommTO; +extern BOOL qBuffInUse; +extern BOOL qFuncExe; +extern BOOL qDebugModeOnlyF; + + +extern BOOL qReqTasksProcessing; +extern DWORD wNewTaskTickCounter; +extern DWORD wTickCounter; +extern BYTE bNewTaskSlot; + +#define TASK_SLOT_IN_TICKS 30 + + + +#endif + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/main.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/main.c new file mode 100644 index 0000000..e2ac329 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/main.c @@ -0,0 +1,149 @@ +/*------------------------------------------------------------------------------ + * Module Name main + * Module Description: this file is used to call initalization of MCU, RX API + * call users tasks, including HDMI RX API, processing + * Audio Content Protection (ACP) on user's level. + * + * Copyright © 2002-2005, Silicon Image, Inc. All rights reserved. + * + * No part of this work may be reproduced, modified, distributed, transmitted, + * transcribed, or translated into any language or computer format, in any form + * or by any means without written permission of: Silicon Image, Inc., + * 1060 East Arques Avenue, Sunnyvale, California 94085 + *---------------------------------------------------------------------------- + */ + +#include + +#include "SiIGlob.h" +#include "SiIRX_API.h" +#include "UGlob.h" +/* #include "UInitMCU.h" */ +#include "UCfgRX.h" +/* #include "UCom.h" */ +/* #include "UKeyboard.h" */ +#include "SiIHAL.h" +#include "../platform_iface.h" + +#ifdef _STD_C_ +#pragma hdrstop +#endif +/*--------------------------------------------------------------------------- + * RX API Global data + *--------------------------------------------------------------------------- + */ +IRAM struct SiI_InfoType_s SiI_Inf; +IRAM struct SiI_CtrlType_s SiI_Ctrl; + +IRAM BYTE SiI_bWCode[WRN_BUF_SIZE]; +IRAM BYTE SiI_bECode[ERR_BUF_SIZE]; + +/*--------------------------------------------------------------------------- + * User Global data used for task management + *--------------------------------------------------------------------------- + */ +BOOL qReqTasksProcessing = TRUE;/* FALSE; // request to process user's tasks */ +DWORD wTickCounter; +DWORD wNewTaskTickCounter; +BYTE bNewTaskSlot; + +/*--------------------------------------------------------------------------- + * These global data are used in debugger mode + *--------------------------------------------------------------------------- + */ +IRAM BYTE RXBuffer[RX_BUF_SIZE]; +BYTE bRxIndex, bCommState, bCommTO; +BOOL qBuffInUse, qFuncExe, qDebugModeOnlyF; + +/*------------------------------------------------------------------------------ + * Function Name: userHDMItask + * Function Description: + *---------------------------------------------------------------------------- + */ +static void userHDMItask(void) +{ +#if 1 + BYTE bRX_ChEvents; + BYTE abRXParameters[8]; + static BOOL qACPStatus = FALSE; + WORD wAudioSelect, wI2SFormat; + + SiI_RX_DoTasks(&bRX_ChEvents); + + RXEXTDBG("sii9135 %s: bRx_ChEvents = 0x%x\n", __func__, bRX_ChEvents); + + if (bRX_ChEvents & SiI_RX_API_GlobalStatus_Changed) { + SiI_RX_GetSystemInformation(abRXParameters); + wAudioSelect = (WORD)(abRXParameters[0] | + abRXParameters[1] << 8); + wI2SFormat = (WORD)(abRXParameters[2] | abRXParameters[3] << 8); + if ((abRXParameters[6] & SiI_RX_GlobalHDMI_ACP) && + (!qACPStatus)) { + /* SPDIF must be disabled */ + qACPStatus = TRUE; + SiI_RX_GetAudioOutputFormat(abRXParameters); + /* modify to disable SPDIF */ + wAudioSelect &= (~SiI_RX_AOut_SPDIF); + SiI_RX_SetAudioOutputFormat(wAudioSelect, wI2SFormat, + 0x00, abRXParameters[5]); + } else { + if ((!(abRXParameters[6] & SiI_RX_GlobalHDMI_ACP)) && + qACPStatus) { + qACPStatus = FALSE; + SiI_RX_GetAudioOutputFormat(abRXParameters); + /* modify to enable SPDIF */ + wAudioSelect |= SiI_RX_AOut_SPDIF; + SiI_RX_SetAudioOutputFormat(wAudioSelect, + wI2SFormat, 0x00, abRXParameters[5]); + } + } + } +#endif +} + +/*------------------------------------------------------------------------------ + * Function Name: main + * Function Description: + * call uinitilizations and infinite loop with user's tasks + *---------------------------------------------------------------------------- + */ + +#define SII9135_PUT_INTERVAL 10 /* 10ms, #define HZ 100 */ +int sii9135_main(void) +{ + wTickCounter = 0; + wNewTaskTickCounter = 0; + bNewTaskSlot = 0; + + /* Amlogic init */ + __plat_timer_init(SysTickTimerISR); + __plat_timer_set(SII9135_PUT_INTERVAL); + + qDebugModeOnlyF = FALSE; + /* siiInitializeMCU(); */ + + siiRXConfig(); + + while (1) { + /* + *if (qReqTasksProcessing) { + + * qReqTasksProcessing = FALSE; + + * if (!qDebugModeOnlyF) { + * if (bNewTaskSlot == TASK_HDMI_RX_API) + * userHDMItask(); + * else if ( bNewTaskSlot == TASK_KEYBOARD ) + * ;//siiKeyboardHandler(); + * } + * if (bNewTaskSlot == TASK_COMM) + * ;//siiCommunicationHandler(); + *} + */ + userHDMItask(); + __plat_msleep(200); + } + return 0; +} +/*---------------------------------------------------------------------------*/ + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.c new file mode 100644 index 0000000..531878d --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.c @@ -0,0 +1,560 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* implement of functions of hw_ops of hdmirx_ext_dev_s. */ + +#include "../hdmirx_ext_drv.h" +#include "../platform_iface.h" +#include "SiITypeDefs.h" +#include "SiIRXDefs.h" +#include "SiIGlob.h" +#include "SiIRXIO.h" +#include "SiIRX_API.h" +#include "sii9135_iface.h" + +/* #include "io.h" */ +/* #include "debug.h" */ + +#define SII9135_PULLUP_I2C_ADDR 0x31 +#define SII9135_PULLDOWN_I2C_ADDR 0x30 +#define SII9135_CHIP_NAME "SII9135" + +unsigned int i2c_write_byte(unsigned char address, + unsigned char offset, unsigned char byteno, + unsigned char *p_data, unsigned char device) +{ + int ret = 0; + + ret = __plat_i2c_write_block(address, offset, p_data, byteno); + + return (ret > 0) ? 0 : 1; +} + +unsigned int i2c_read_byte(unsigned char address, + unsigned char offset, unsigned char byteno, + unsigned char *p_data, unsigned char device) +{ + int ret = 0; + + ret = __plat_i2c_read_block(address, offset, p_data, byteno); + + return (ret > 0) ? 0 : 1; +} + + +/* signal stauts */ +static int __sii9135_get_cable_status(void) +{ + if (siiRX_CheckCableHPD()) + return 1; + + return 0; +} + +static int __sii9135_get_signal_status(void) +{ + RXEXTPR("%s: sm_bVideo=%d\n", __func__, SiI_Ctrl.sm_bVideo); +#if 0 + if (SiI_Ctrl.sm_bVideo == SiI_RX_VS_VideoOn) + return 1; +#endif + if (siiIsVideoOn()) + return 1; + + return 0; +} + +static int __sii9135_get_input_port(void) +{ + if (SiI_Ctrl.bVidInChannel == SiI_RX_VInCh1) + return 1; + else + return 2; + + return 0; +} + +static void __sii9135_set_input_port(int port) +{ + if (port == 2) + SiI_RX_SetVideoInput(SiI_RX_VInCh2); + else + SiI_RX_SetVideoInput(SiI_RX_VInCh1); + RXEXTPR("%s: %d\n", __func__, port); +} + +/* signal timming */ +static int __sii9135_get_video_timming(struct video_timming_s *ptimming) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + unsigned char tmp[4]; + unsigned char i2c_addr; + int ret = 0; +/* + * CurTMDSCLK = (int)ucTMDSClk; + * CurVTiming.PCLK = (int)PCLK; + * CurVTiming.HActive = HActive; + * CurVTiming.HTotal = HTotal; + * CurVTiming.HFrontPorch = HFP; + * CurVTiming.HSyncWidth = HSYNCW; + * CurVTiming.HBackPorch = HTotal - HActive - HFP - HSYNCW; + * CurVTiming.VActive = VActive; + * CurVTiming.VTotal = VTotal; + * CurVTiming.VFrontPorch = VFP; + * CurVTiming.VSyncWidth = VSYNCW; + * CurVTiming.VBackPorch = VTotal - VActive - VFP - VSYNCW; + * CurVTiming.ScanMode = (InterLaced)&0x01; + * CurVTiming.VPolarity = (VSyncPol)&0x01; + * CurVTiming.HPolarity = (HSyncPol)&0x01; + */ +/* + * ptimming->h_active = CurVTiming.HActive; + * ptimming->h_total = CurVTiming.HTotal; + * ptimming->hs_frontporch = CurVTiming.HFrontPorch; + * ptimming->hs_width = CurVTiming.HSyncWidth; + * ptimming->hs_backporch = CurVTiming.HBackPorch; + * ptimming->v_active = CurVTiming.VActive; + * ptimming->v_total = CurVTiming.VTotal; + * ptimming->vs_frontporch = CurVTiming.VFrontPorch; + * ptimming->vs_width = CurVTiming.VSyncWidth; + * ptimming->vs_backporch = CurVTiming.VBackPorch; + */ + i2c_addr = hdrv->hw.i2c_addr; + + ret = i2c_read_byte(i2c_addr, 0x4e, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x4e error\n"); + ptimming->h_active = (((unsigned int)tmp[1]) << 8) + tmp[0]; + + ret = i2c_read_byte(i2c_addr, 0x50, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x50 error\n"); + ptimming->v_active = (((unsigned int)tmp[1]) << 8) + tmp[0]; + + ret = i2c_read_byte(i2c_addr, 0x3a, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x3a error\n"); + ptimming->h_total = (((unsigned int)tmp[1]) << 8) + tmp[0]; + + ret = i2c_read_byte(i2c_addr, 0x3c, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x3c error\n"); + ptimming->v_total = (((unsigned int)tmp[1]) << 8) + tmp[0]; + + ret = i2c_read_byte(i2c_addr, 0x5b, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x5b error\n"); + ptimming->hs_width = (((unsigned int)tmp[1]) << 8) + tmp[0]; + ret = i2c_read_byte(i2c_addr, 0x59, 2, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x59 error\n"); + ptimming->hs_frontporch = (((unsigned int)tmp[1]) << 8) + tmp[0]; + ptimming->hs_backporch = ptimming->h_total - ptimming->hs_width - + ptimming->hs_frontporch - ptimming->h_active; + + ret = i2c_read_byte(i2c_addr, 0x53, 1, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x53 error\n"); + ptimming->vs_frontporch = tmp[0]; + ptimming->vs_width = 5; + ret = i2c_read_byte(i2c_addr, 0x52, 1, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x52 error\n"); + ptimming->vs_backporch = tmp[0] - ptimming->vs_width; + + ret = i2c_read_byte(i2c_addr, 0x55, 1, tmp, 0); + if (ret) + RXEXTERR("i2c read 0x52 error\n"); + ptimming->mode = (tmp[0] >> 2) & 1; + ptimming->hs_pol = (tmp[0] >> 0) & 1; + ptimming->vs_pol = (tmp[0] >> 1) & 1; + return 0; +} + +void __sii9135_dump_video_timming(void) +{ + int h_active, v_active, h_total, v_total; + int hs_fp, hs_width, hs_bp; + int vs_fp, vs_width, vs_bp; + int hs_pol, vs_pol, mode; + struct video_timming_s timming; + + if (__sii9135_get_video_timming(&timming) == -1) { + RXEXTERR("%s: get video timming failed\n", __func__); + return; + } + + h_active = timming.h_active; + v_active = timming.v_active; + + h_total = timming.h_total; + v_total = timming.v_total; + + hs_fp = timming.hs_frontporch; + hs_width = timming.hs_width; + hs_bp = timming.hs_backporch; + + vs_fp = timming.vs_frontporch; + vs_width = timming.vs_width; + vs_bp = timming.vs_backporch; + + hs_pol = timming.hs_pol; + vs_pol = timming.vs_pol; + mode = timming.mode; + + RXEXTPR("sii9135 video info:\n" + "h * v active = %4d x %4d\n" + "h * v total = %4d x %4d\n" + "h_sync(fp, ws, bp) = %4d, %4d, %4d\n" + "v_sync(fp, ws, bp) = %4d, %4d, %4d\n" + "sync_pol(hs, vs) = %s[%d], %s[%d]\n" + "video_mode = %s[%d]\n", + h_active, v_active, h_total, v_total, + hs_fp, hs_width, hs_bp, + vs_fp, vs_width, vs_bp, + ((hs_pol) ? "positive" : "negative"), hs_pol, + ((vs_pol) ? "positive" : "negative"), vs_pol, + ((mode) ? "interlaced" : "progressive"), mode); +} + +static int __sii9135_is_hdmi_mode(void) +{ + if (siiIsHDMI_Mode()) + return 1; + + return 0; +} + +static int __sii9135_get_audio_sample_rate(void) +{ + BYTE bRegVal; + + bRegVal = siiReadByteHDMIRXP1(RX_FREQ_SVAL_ADDR) & 0x0F; /*reg 102 */ + + return (int)bRegVal; +} + +static int __print_buf(char *buf, int length) +{ + int i = 0; + + if (buf == NULL) + return -1; + + for (i = 0; i < length; i++) + pr_info("[0x%.2x] = %.2X\n", i, buf[i]); + + return 0; +} + +static int __sii9135_debug(char *buf) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int argn = 0; + char *p = NULL, *para = NULL, *argv[4] = {NULL, NULL, NULL, NULL}; + char str[3] = {' ', '\n', '\0'}; + unsigned long cmd = 0, dev_addr = 0, reg_start = 0, reg_end = 0; + unsigned long length = 0, value = 0xff; + char i2c_buf[2] = {0, 0}; + char *tmp = NULL; + unsigned long type = 255, count = 0; + int ret = 0; + int i; + + p = kstrdup(buf, GFP_KERNEL); + while (1) { + para = strsep(&p, str); + if (para == NULL) + break; + if (*para == '\0') + continue; + argv[argn++] = para; + } + +/* pr_info("get para: %s %s %s %s!\n",argv[0],argv[1],argv[2],argv[3]);*/ + + if (!strcmp(argv[0], "r")) + cmd = 0; + else if (!strcmp(argv[0], "w")) + cmd = 1; + else if (!strcmp(argv[0], "dump")) + cmd = 2; + else if (!strcmp(argv[0], "vinfo")) + cmd = 3; + else if (!strcmp(argv[0], "help")) + cmd = 4; + else if (!strncmp(argv[0], "reset", strlen("reset"))) + cmd = 5; + else if (!strncmp(argv[0], "tt", strlen("tt"))) + cmd = 6; + else {/* invalid command format, take it as "help" */ + pr_info("invalid cmd = %s\n", argv[0]); + cmd = 4; + } + + pr_info(" cmd = %ld - \"%s\"\n", cmd, argv[0]); + if ((argn < 1) || ((cmd == 0) && (argn != 3)) || + ((cmd == 1) && (argn != 4)) || ((cmd == 2) && (argn != 4))) { + pr_info("invalid command format!\n"); + cmd = 4; + } + + switch (cmd) { + case 0: /* r device_address register_address*/ + ret = kstrtoul(argv[1], 16, &dev_addr); + ret = kstrtoul(argv[2], 16, ®_start); + + ret = i2c_read_byte(dev_addr, reg_start, 1, i2c_buf, 0); + pr_info("reg read dev:0x%x[0x%x] = 0x%x, ret = %d\n", + (unsigned int)dev_addr, (unsigned int)reg_start, + i2c_buf[0], ret); + break; + case 1: /* w device_address register_address value */ + ret = kstrtoul(argv[1], 16, &dev_addr); + ret = kstrtoul(argv[2], 16, ®_start); + ret = kstrtoul(argv[3], 16, &value); + + i2c_buf[0] = value; + + ret = i2c_write_byte(dev_addr, reg_start, 1, i2c_buf, 0); + pr_info("i2c write dev: 0x%x[0x%x] = 0x%x, ret = %d\n", + (unsigned int)dev_addr, (unsigned int)reg_start, + (unsigned int)value, ret); + ret = i2c_read_byte(dev_addr, reg_start, 1, i2c_buf, 0); + pr_info("i2c read back ret = %d, value = 0x%x\n", + ret, i2c_buf[0]); + break; + case 2: /* dump device_address register */ + ret = kstrtoul(argv[1], 16, &dev_addr); + ret = kstrtoul(argv[2], 16, ®_start); + ret = kstrtoul(argv[3], 16, ®_end); + length = reg_end - reg_start + 1; + + pr_info("reg dump dev = 0x%x, start = 0x%x, end = 0x%x\n", + (unsigned int)dev_addr, (unsigned int)reg_start, + (unsigned int)reg_end); + + tmp = kzalloc((sizeof(char) * length), GFP_KERNEL); + if (tmp != NULL) { + ret = i2c_read_byte(dev_addr, reg_start, + length, tmp, 0); + pr_info("sii9135 dev=0x%.2x regs=0x%.2x:0x%.2x:\n", + (unsigned int)dev_addr, (unsigned int)reg_start, + (unsigned int)(reg_start+length-1)); + __print_buf(tmp, length); + + kfree(tmp); + } + break; + case 3: /* vinfo */ + pr_info("begin dump hdmi-in video info:\n"); + __sii9135_dump_video_timming(); + break; + case 5: /* reset, for test reset_gpio */ + ret = kstrtoul(argv[1], 10, &value); + value = (value == 0) ? 0 : 1; + + __plat_gpio_output(&hdrv->hw.reset_gpio, value); + pr_info("reset_gpio is set to %d\n", (unsigned int)value); + break; + case 6: /* tt, for loop test of hdmirx_ext i2c */ + ret = kstrtoul(argv[1], 10, &type); + ret = kstrtoul(argv[2], 10, &count); + pr_info("i2c stability test: type = %ld, count = %ld\n", + type, count); + + if (type == 0) { /*write*/ + dev_addr = 0x60; + reg_start = 0x08; + value = 0x05; + i2c_buf[0] = value; + for (i = 0; i < count; i++) { + ret = i2c_write_byte(dev_addr, reg_start, + 1, i2c_buf, 0); + pr_info("i2c_w: 0x%x[0x%x]=0x%x, ret=%d\n", + (unsigned int)dev_addr, + (unsigned int)reg_start, + (unsigned int)value, ret); + udelay(50); + } + } else { /*read*/ + for (i = 0; i < count; i++) { + dev_addr = 0x60; + reg_start = 0x08; + ret = i2c_read_byte(dev_addr, reg_start, 1, + i2c_buf, 0); + pr_info("i2c_r: 0x%x[0x%x]=0x%x, ret=%d\n", + (unsigned int)dev_addr, + (unsigned int)reg_start, + i2c_buf[0], ret); + udelay(50); + } + } + break; + case 4: /* help */ + default: + pr_info("sii9135 debug command format:\n"); + pr_info(" read register: r device_address register_address\n"); + pr_info(" write register: w device_address register_address value\n"); + pr_info(" dump register: dump device_address register_address_start register_address_end\n"); + pr_info(" video timming: vinfo\n"); + break; + } + + kfree(p); + return 0; +} + +static char *__sii9135_get_chip_version(void) +{ +#if 0 + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + unsigned char tmp[3]; + unsigned char i2c_addr; + int ret; + + i2c_addr = hdrv->hw.i2c_addr; + ret = i2c_read_byte(i2c_addr, RX_DEV_IDL_ADDR, 3, tmp, 0); + siiReadBlockHDMIRXP0(RX_DEV_IDL_ADDR, 3, pbChipVer); +#endif + return SII9135_CHIP_NAME; +} + +static void __sii9135_hw_reset(int flag) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int val_on, val_off; + + if (hdrv->hw.reset_gpio.flag == 0) { + RXEXTPR("%s: invalid reset_gpio\n", __func__); + return; + } + RXEXTPR("%s: %d\n", __func__, flag); + + if (hdrv->hw.reset_gpio.val_on != -1) + val_on = hdrv->hw.reset_gpio.val_on; + else + val_on = 0; + if (hdrv->hw.reset_gpio.val_off != -1) + val_off = hdrv->hw.reset_gpio.val_off; + else + val_off = 1; + if (flag) + __plat_gpio_output(&hdrv->hw.reset_gpio, val_on); + else + __plat_gpio_output(&hdrv->hw.reset_gpio, val_off); +} + +static void __sii9135_hw_en(int flag) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int val_on, val_off; + + if (hdrv->hw.en_gpio.flag == 0) { + RXEXTPR("%s: invalid en_gpio\n", __func__); + return; + } + RXEXTPR("%s: %d\n", __func__, flag); + + if (hdrv->hw.en_gpio.val_on != -1) + val_on = hdrv->hw.en_gpio.val_on; + else + val_on = 1; + if (hdrv->hw.en_gpio.val_off != -1) + val_off = hdrv->hw.en_gpio.val_off; + else + val_off = 0; + if (flag) + __plat_gpio_output(&hdrv->hw.en_gpio, val_on); + else + __plat_gpio_output(&hdrv->hw.en_gpio, val_off); +} + +static int __sii9135_task_handler(void *data) +{ + sii9135_main(); + + return 0; +} + +static int __sii9135_init(void) +{ + RXEXTPR("%s\n", __func__); + + return 0; +} + +static int __sii9135_enable(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + unsigned char i2c_addr = SII9135_PULLDOWN_I2C_ADDR; + + if (!hdrv) + return -1; + + RXEXTPR("%s\n", __func__); + + __sii9135_hw_en(1); + __plat_msleep(100); + + i2c_addr = hdrv->hw.i2c_addr; + + __plat_i2c_init(&(hdrv->hw), i2c_addr); + + __sii9135_hw_reset(1); + __plat_msleep(200); + __sii9135_hw_reset(0); + __plat_msleep(200); + + __plat_create_thread(__sii9135_task_handler, hdrv, HDMIRX_EXT_DRV_NAME); + + return 0; +} + +static void __sii9135_disable(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if (!hdrv) + return; + + RXEXTPR("%s\n", __func__); + + __sii9135_hw_reset(1); + __sii9135_hw_en(0); +} + +void hdmirx_ext_register_hw_sii9135(struct hdmirx_ext_drv_s *hdrv) +{ + if (!hdrv) + return; + + RXEXTPR("%s\n", __func__); + hdrv->hw.get_cable_status = __sii9135_get_cable_status; + hdrv->hw.get_signal_status = __sii9135_get_signal_status; + hdrv->hw.get_input_port = __sii9135_get_input_port; + hdrv->hw.set_input_port = __sii9135_set_input_port; + hdrv->hw.get_video_timming = __sii9135_get_video_timming; + hdrv->hw.is_hdmi_mode = __sii9135_is_hdmi_mode; + hdrv->hw.get_audio_sample_rate = __sii9135_get_audio_sample_rate; + hdrv->hw.debug = __sii9135_debug; + hdrv->hw.get_chip_version = __sii9135_get_chip_version; + hdrv->hw.init = __sii9135_init; + hdrv->hw.enable = __sii9135_enable; + hdrv->hw.disable = __sii9135_disable; +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.h new file mode 100644 index 0000000..286781f --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/sii9135_iface.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "SiITypeDefs.h" + +extern void sii9135_main(void); + +extern BOOL siiIsHDMI_Mode(void); +extern BOOL siiRX_CheckCableHPD(void); +extern BOOL siiIsVideoOn(void); +extern BYTE SiI_RX_SetVideoInput(BYTE bVideoInputChannels); + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/uauddac.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/uauddac.c new file mode 100644 index 0000000..5801484 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/hw_sii9135/uauddac.c @@ -0,0 +1,61 @@ +/******************************************************************************/ +/* Copyright (c) 2002-2005, Silicon Image, Inc. All rights reserved. */ +/* No part of this work may be reproduced, modified, distributed, */ +/* transmitted, transcribed, or translated into any language or computer */ +/* format, in any form or by any means without written permission of: */ +/* Silicon Image, Inc., 1060 East Arques Avenue, Sunnyvale, California 94085*/ +/******************************************************************************/ +/*------------------------------------------------------------------------------ + * Module Name: UAudDAC + * + * Module Description: this low level driver for Audio DAC Control + * + *---------------------------------------------------------------------------- + */ +#include "SiIRXAPIDefs.h" +#include "UAudDAC.h" +#include "SiIHAL.h" + +/*------------------------------------------------------------------------------ + * Function Name: WakeUpAudioDAC + * Function Description: Wake up Audio DAC + * Accepts: + * Returns: + * Globals: + *-------------------------------------------------------- + */ +void WakeUpAudioDAC(void) +{ + siiWriteByteAudDAC(AUDDAC_SPEED_PD_ADDR, AUDDAC_NORM_OP); +} +/*------------------------------------------------------------------------------ + * Function Name: PowerDownAudioDAC + * Function Description: Wake up Audio DAC + * Accepts: + * Returns: + * Globals: + *-------------------------------------------------------- + */ +void PowerDownAudioDAC(void) +{ + siiWriteByteAudDAC(AUDDAC_SPEED_PD_ADDR, AUDDAC_RST); +} +/*------------------------------------------------------------------------------ + * Function Name: halSetAudioDACMode + * Function Description: Set Audio DAC modes DSD vs.PCM + * Accepts: + * Returns: + * Globals: + *-------------------------------------------------------- + */ +void halSetAudioDACMode(BYTE bMode) +{ + /* put in reset to be safe */ + siiWriteByteAudDAC(AUDDAC_SPEED_PD_ADDR, AUDDAC_RST); + halDelayMS(1); /* YAM wait for old data to flush */ + if (bMode == SiI_RX_AudioRepr_DSD) + siiWriteByteAudDAC(AUDDAC_CTRL3_ADDR, ADAC_DSD_MODE); + else + siiWriteByteAudDAC(AUDDAC_CTRL3_ADDR, ADAC_PCM_MODE); +} + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.c new file mode 100644 index 0000000..f2c6570 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.c @@ -0,0 +1,431 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include "hdmirx_ext_drv.h" +#include "platform_iface.h" + + +/* ******************************************************************** */ +/* for platform timer function */ + +static void __plat_timer_handler(unsigned long arg) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if (hdrv->timer_func) + hdrv->timer_func(); + hdrv->timer.expires = jiffies + msecs_to_jiffies(hdrv->timer_cnt); + add_timer(&hdrv->timer); +} + +void __plat_timer_set(int timer_cnt) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + hdrv->timer_cnt = timer_cnt; + hdrv->timer.expires = jiffies + msecs_to_jiffies(timer_cnt); + add_timer(&hdrv->timer); + RXEXTPR("timer set\n"); +} + +void __plat_timer_init(void (*timer_func)(void)) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + RXEXTPR("timer init\n"); + + hdrv->timer_func = timer_func; + init_timer(&hdrv->timer); + hdrv->timer.data = (unsigned long)hdrv; + hdrv->timer.function = __plat_timer_handler; +} + +int __plat_timer_expired(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + del_timer_sync(&hdrv->timer); + RXEXTPR("timer remove\n"); + return 0; +} + +#if 0 +/* for platform hrtimer function */ +/* HRTIMER_NORESTART, // Timer is not restarted */ +/* HRTIMER_RESTART, // Timer must be restarted */ +static enum hrtimer_restart __plat_hrtimer_handler(struct hrtimer *hr_timer) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if (hdrv->hrtimer_func) + hdrv->hrtimer_func(); + + if (hdrv->state) + return HRTIMER_RESTART; + else + return HRTIMER_NORESTART; +} + +void __plat_hrtimer_set(long timer_cnt) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + hdrv->timer_cnt = timer_cnt; + hrtimer_start(&hdrv->hr_timer, + ktime_set(timer_cnt / 1000, (timer_cnt % 1000) * 1000000), + HRTIMER_MODE_REL); + RXEXTPR("hrtimer set\n"); +} + +void __plat_hrtimer_init(void *timer_func) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + RXEXTPR("hrtimer init\n"); + + hdrv->hrtimer_func = timer_func; + hrtimer_init(&hdrv->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hdrv->hr_timer.function = __plat_hrtimer_handler; +} + +int __plat_hrtimer_expired(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + RXEXTPR("hrtimer remove\n"); + return hrtimer_cancel(&hdrv->hr_timer); +} +#endif +/* ******************************************************************** */ + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* for platform i2c interface */ + +static int __plat_i2c_read(unsigned char dev_addr, char *buf, + int addr_len, int data_len) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int ret; + char reg_addr = buf[0]; + struct i2c_msg msg[] = { + { + .addr = dev_addr, + .flags = 0, + .len = addr_len, + .buf = buf, + }, + { + .addr = dev_addr, + .flags = I2C_M_RD,/* | (2<<1), */ + .len = data_len, + .buf = buf, + }, + }; + + if (hdrv == NULL) { + RXEXTERR("%s: hdmirx_ext driver is null !\n", __func__); + return -1; + } + if (hdrv->hw.i2c_client == NULL) { + RXEXTERR("%s: invalid i2c_client !\n", __func__); + return -1; + } + + ret = i2c_transfer(hdrv->hw.i2c_client->adapter, msg, 2); + if (ret < 0) { + RXEXTERR("%s: %d, dev_addr = 0x%x, reg = 0x%x\n", + __func__, ret, dev_addr, reg_addr); + } + + return ret; +} + +static int __plat_i2c_write(unsigned char dev_addr, char *buf, int len) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + int ret = -1, i; + char reg_addr = buf[0]; + struct i2c_msg msg[] = { + { + .addr = dev_addr, + .flags = 0,/* | (2<<1),*/ + .len = len, + .buf = buf, + }, + }; + + if (hdrv == NULL) { + RXEXTERR("%s: hdmirx_ext driver is null !\n", __func__); + return -1; + } + if (hdrv->hw.i2c_client == NULL) { + RXEXTERR("%s: invalid i2c_client !\n", __func__); + return -1; + } + + ret = i2c_transfer(hdrv->hw.i2c_client->adapter, msg, 1); + if (ret < 0) { + RXEXTERR("%s: %d, dev_addr = 0x%x, reg = 0x%x\n", + __func__, ret, dev_addr, reg_addr); + for (i = 1; i < len; i++) + pr_info("value[%d] = 0x%x\n", i, buf[i]); + } + + return ret; +} + +int __plat_i2c_read_byte(unsigned char dev_addr, unsigned char offset, + unsigned char *pvalue) +{ + int ret = 0; + char buf[2] = {0, 0}; + + buf[0] = offset; + + ret = __plat_i2c_read(dev_addr, buf, 1, 1); + *pvalue = buf[0]; + + if (ret < 0) { + RXEXTERR("%s: dev_addr = 0x%x, reg = 0x%x, ret = %d\n", + __func__, dev_addr, offset, ret); + } + + return ret; +} + +int __plat_i2c_write_byte(unsigned char dev_addr, unsigned char offset, + unsigned char value) +{ + int ret = 0; + char buf[2] = {0, 0}; + + buf[0] = offset; + buf[1] = value; + + ret = __plat_i2c_write(dev_addr, buf, 2); + if (ret < 0) { + RXEXTERR("%s: dev_addr = 0x%x, reg = 0x%x, ret = %d\n", + __func__, dev_addr, offset, ret); + } + + return ret; +} + +int __plat_i2c_read_block(unsigned char dev_addr, unsigned char offset, + char *buffer, int length) +{ + int ret = 0; + + buffer[0] = offset; + + ret = __plat_i2c_read(dev_addr, buffer, 1, length); + if (ret < 0) { + RXEXTERR("%s: dev_addr = 0x%x, reg = 0x%x, ret = %d\n", + __func__, dev_addr, offset, ret); + } + + return ret; +} + +int __plat_i2c_write_block(unsigned char dev_addr, unsigned char offset, + char *buffer, int length) +{ + int ret = 0; + char *tmp = NULL; + + tmp = kmalloc((sizeof(char) * (length+1)), GFP_KERNEL); + + if (tmp == NULL) + return -1; + + tmp[0] = offset; + memcpy(&tmp[1], buffer, length); + + ret = __plat_i2c_write(dev_addr, tmp, length+1); + if (ret < 0) { + RXEXTERR("%s: dev_addr = 0x%x, reg = 0x%x, ret = %d\n", + __func__, dev_addr, offset, ret); + } + + kfree(tmp); + return ret; +} + +int __plat_i2c_init(struct hdmirx_ext_hw_s *phw, unsigned char dev_i2c_addr) +{ + struct i2c_board_info board_info; + struct i2c_adapter *adapter; + + RXEXTDBG("%s: i2c addr = 0x%x\n", __func__, dev_i2c_addr); + + memset(&board_info, 0x0, sizeof(board_info)); + strncpy(board_info.type, HDMIRX_EXT_DEV_NAME, I2C_NAME_SIZE); + adapter = i2c_get_adapter(phw->i2c_bus_index); + board_info.addr = dev_i2c_addr; + board_info.platform_data = phw; + phw->i2c_client = i2c_new_device(adapter, &board_info); + + return 0; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* for platform gpio interface */ + +int __plat_gpio_init(unsigned int gpio_index) +{ + return 0; +} + +void __plat_gpio_output(struct hdmirx_ext_gpio_s *gpio, unsigned int value) +{ + if (gpio->flag == 0) { + RXEXTERR("%s: gpio is not regisetered\n", __func__); + return; + } + if (IS_ERR(gpio->gpio)) { + RXEXTERR("gpio %s: %p, err: %ld\n", + gpio->name, gpio->gpio, PTR_ERR(gpio->gpio)); + return; + } + gpiod_direction_output(gpio->gpio, ((value == 0) ? 0 : 1)); + RXEXTDBG("gpio %s: %p, value: %d\n", + gpio->name, gpio->gpio, value); +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* for platform delay interface */ + +void __plat_msleep(unsigned int msecs) +{ + msleep(msecs); +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* for platform video mode interface */ + +static char *__plat_vmode[] = { + "480i", "480p", + "576i", "576p", + "720p50hz", "720p60hz", + "1080i60hz", "1080i50hz", + "1080p60hz", "1080p50hz", + "invalid" +}; + +int __plat_get_video_mode_by_name(char *name) +{ + unsigned int mode = CEA_MAX; + int i; + + for (i = 0; i < 10; i++) { + if (!strcmp(name, __plat_vmode[i])) + mode = i; + } + switch (mode) { + case 0: /* 480i */ + mode = CEA_480I60; + break; + case 1: /* 480p */ + mode = CEA_480P60; + break; + case 2: /* 576i */ + mode = CEA_576I50; + break; + case 3: /* 576p */ + mode = CEA_576P50; + break; + case 4: /* 720p50 */ + mode = CEA_720P50; + break; + case 5: /* 720p60 */ + default: + mode = CEA_720P60; + break; + case 6: /* 1080i60 */ + mode = CEA_1080I60; + break; + case 7: /* 1080i50 */ + mode = CEA_1080I50; + break; + case 8: /* 1080p60 */ + mode = CEA_1080P60; + break; + case 9: /* 1080p50 */ + mode = CEA_1080P50; + break; + } + + return mode; +} + +char *__plat_get_video_mode_name(int mode) +{ + int temp = 10; + + switch (mode) { + case CEA_480I60: + temp = 0; + break; + case CEA_480P60: + temp = 1; + break; + case CEA_576I50: + temp = 2; + break; + case CEA_576P50: + temp = 3; + break; + case CEA_720P60: + temp = 4; + break; + case CEA_720P50: + temp = 5; + break; + case CEA_1080I60: + temp = 6; + break; + case CEA_1080I50: + temp = 7; + break; + case CEA_1080P60: + temp = 8; + break; + case CEA_1080P50: + temp = 9; + break; + default: + temp = 10; + break; + } + + return __plat_vmode[temp]; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* for platform task interface */ + +struct task_struct *__plat_create_thread(int (*threadfn)(void *data), + void *data, const char namefmt[]) +{ + return kthread_run(threadfn, data, namefmt); +} + + diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.h new file mode 100644 index 0000000..3fbb337 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.h @@ -0,0 +1,57 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/platform_iface.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __PLATFORM_INTERFACE_H__ +#define __PLATFORM_INTERFACE_H__ + +#include +#include +#include +#include +#include +#include "hdmirx_ext_drv.h" + +/* for timer function */ +void __plat_timer_set(int timer_cnt); +void __plat_timer_init(void (*timer_func)(void)); +int __plat_timer_expired(void); + +/* for i2c function */ +int __plat_i2c_init(struct hdmirx_ext_hw_s *phw, unsigned char dev_i2c_addr); + +int __plat_i2c_read_byte(unsigned char dev_addr, unsigned char offset, + unsigned char *pvalue); +int __plat_i2c_write_byte(unsigned char dev_addr, unsigned char offset, + unsigned char value); + +int __plat_i2c_read_block(unsigned char dev_addr, unsigned char offset, + char *buffer, int length); +int __plat_i2c_write_block(unsigned char dev_addr, unsigned char offset, + char *buffer, int length); + +int __plat_gpio_init(unsigned int gpio_index); +void __plat_gpio_output(struct hdmirx_ext_gpio_s *gpio, unsigned int value); + +void __plat_msleep(unsigned int msecs); + +extern int __plat_get_video_mode_by_name(char *name); +extern char *__plat_get_video_mode_name(int mode); + +struct task_struct *__plat_create_thread(int (*threadfn)(void *data), + void *data, const char namefmt[]); + +#endif diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.c b/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.c new file mode 100644 index 0000000..1569cf2 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.c @@ -0,0 +1,291 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* #include */ +#include +#include +#include +#include +#include "hdmirx_ext_drv.h" +#include "../tvin_frontend.h" +#include "hdmirx_ext_hw_iface.h" +#include "hdmirx_ext_reg.h" +#include "vdin_iface.h" + +static int __vdin_set_pinmux(int flag) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + + if (flag) { /* enable pinmux */ + if (hdrv->hw.pinmux_flag == 0) { + /* request pinmux */ + hdrv->hw.pin = + devm_pinctrl_get_select_default(hdrv->dev); + if (IS_ERR(hdrv->hw.pin)) + RXEXTERR("pinmux set error\n"); + else + hdrv->hw.pinmux_flag = 1; + } else { + RXEXTERR("pinmux is already selected\n"); + } + } else { /* disable pinmux */ + if (hdrv->hw.pinmux_flag) { + hdrv->hw.pinmux_flag = 0; + /* release pinmux */ + devm_pinctrl_put(hdrv->hw.pin); + } else { + RXEXTERR("pinmux is already released\n"); + } + } + + return 0; +} + +void hdmirx_ext_stop_vdin(void) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + unsigned char vdin_sel; + + if (hdrv->vdin.started == 0) + return; + + vdin_sel = hdrv->vdin.vdin_sel; + if (hdrv->vops) { + RXEXTPR("%s: begin stop_tvin_service()\n", __func__); + hdrv->vops->stop_tvin_service(vdin_sel); + set_invert_top_bot(false); + __vdin_set_pinmux(0); + hdrv->vdin.started = 0; + } else { + RXEXTERR("%s: v4l2_ops is NULL\n", __func__); + } + + RXEXTPR("%s: finish stop vdin\n", __func__); +} + +void hdmirx_ext_start_vdin(int width, int height, int frame_rate, + int field_flag) +{ + struct hdmirx_ext_drv_s *hdrv = hdmirx_ext_get_driver(); + struct vdin_parm_s para; + unsigned char vdin_sel, bt656_sel; + struct video_timming_s timming; + int start_pix = 138, start_line_o = 22, start_line_e = 23; + int h_total = 1728, v_total = 625; + + RXEXTPR("%s: width=%d, height=%d, frame_rate=%d, field_flag=%d\n", + __func__, width, height, frame_rate, field_flag); + + if (hdrv->vdin.started) + return; + + if (__hw_get_video_timming(&timming) == -1) { + RXEXTERR("%s: get video timming failed!\n", __func__); + return; + } + + if ((width <= 0) || (height <= 0) || (frame_rate <= 0)) { + RXEXTERR("%s: invalid size or frame_rate\n", __func__); + return; + } + + vdin_sel = hdrv->vdin.vdin_sel; + bt656_sel = (hdrv->vdin.bt656_sel == 1) ? BT_PATH_GPIO : BT_PATH_GPIO_B; + + if (field_flag && (height <= 576)) { + if ((width == 1440) && (height == 576)) { + /* for rgb 576i signal, it's 720/864, not 1440/1728 */ + start_pix = 138; + start_line_o = 22; + start_line_e = 23; + h_total = 1728; + v_total = 625; + } else if ((width == 1440) && (height == 480)) { + /* for rgb 480i signal, it's 720/858, not 1440/1716 */ + start_pix = 114; + start_line_o = 18; + start_line_e = 19; + h_total = 1716; + v_total = 525; + } + } + + memset(¶, 0, sizeof(para)); + para.port = TVIN_PORT_BT601_HDMI; /* TVIN_PORT_CAMERA; */ + para.bt_path = bt656_sel; + para.frame_rate = frame_rate; + para.h_active = width; + para.v_active = height; + if (field_flag) { + if ((width == 1920) && + ((height == 1080) || (height == 540))) { + if (frame_rate == 60) + para.fmt = TVIN_SIG_FMT_HDMI_1920X1080I_60HZ; + else if (frame_rate == 50) + para.fmt = TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_A; + /* para.v_active = 1080; */ + } else if ((width == 1440) && + ((height == 576) || (height == 288))) { + para.fmt = TVIN_SIG_FMT_HDMI_1440X576I_50HZ; + /* para.v_active = 576; */ + set_invert_top_bot(true); + } + /* + * else if( width == 720 && (height == 576 || height == 288)){ + * para.fmt = TVIN_SIG_FMT_HDMI_720X576I_50HZ; + * para.v_active = 576; + * set_invert_top_bot(true); + * } else if( width == 720 && (height == 480 || height == 240)){ + * para.fmt = TVIN_SIG_FMT_HDMI_720X480I_60HZ; + * para.v_active = 480; + * set_invert_top_bot(true); + * } + */ + else if ((width == 1440) && + ((height == 480) || (height == 240))) { + para.fmt = TVIN_SIG_FMT_HDMI_1440X480I_60HZ; + /* para.v_active = 480; */ + set_invert_top_bot(true); + } else { + para.fmt = TVIN_SIG_FMT_MAX+1; + set_invert_top_bot(true); + } + para.scan_mode = TVIN_SCAN_MODE_INTERLACED; + para.fid_check_cnt = timming.hs_width + timming.hs_backporch + + timming.h_active; + } else { + if ((width == 1920) && (height == 1080)) + para.fmt = TVIN_SIG_FMT_HDMI_1920X1080P_60HZ; + else if ((width == 1280) && (height == 720)) + para.fmt = TVIN_SIG_FMT_HDMI_1280X720P_60HZ; + else if (((width == 1440) || (width == 720)) && (height == 576)) + para.fmt = TVIN_SIG_FMT_HDMI_720X576P_50HZ; + else if (((width == 1440) || (width == 720)) && (height == 480)) + para.fmt = TVIN_SIG_FMT_HDMI_720X480P_60HZ; + else + para.fmt = TVIN_SIG_FMT_MAX+1; + /* para.fmt = TVIN_SIG_FMT_MAX; */ + para.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + para.fid_check_cnt = 0; + } + para.hsync_phase = timming.hs_pol; + para.vsync_phase = timming.vs_pol; + para.hs_bp = timming.hs_backporch; + para.vs_bp = timming.vs_backporch; + para.cfmt = TVIN_YUV422; + para.dfmt = TVIN_YUV422; + para.skip_count = 0; /* skip_num */ + if (hdmirx_ext_debug_print) { + pr_info("para frame_rate: %d\n" + "para h_active: %d\n" + "para v_active: %d\n" + "para hsync_phase: %d\n" + "para vsync_phase: %d\n" + "para hs_bp: %d\n" + "para vs_bp: %d\n" + "para scan_mode: %d\n" + "para fmt: %d\n", + para.frame_rate, para.h_active, para.v_active, + para.hsync_phase, para.vsync_phase, + para.hs_bp, para.vs_bp, + para.scan_mode, para.fmt); + } + + __vdin_set_pinmux(1); + if (hdrv->vops) { + RXEXTPR("%s: begin start_tvin_service()\n", __func__); + hdrv->vops->start_tvin_service(vdin_sel, ¶); + hdrv->vdin.started = 1; + } else { + RXEXTERR("%s: v4l2_ops is NULL\n", __func__); + } + RXEXTPR("%s: finish start vdin\n", __func__); +} + +void hdmirx_ext_start_vdin_mode(unsigned int mode) +{ + unsigned int height = 0, width = 0, frame_rate = 0, field_flag = 0; + + RXEXTPR("%s: start with mode = %d\n", __func__, mode); + switch (mode) { + case CEA_480I60: + width = 1440; + height = 480; + frame_rate = 60; + field_flag = 1; + break; + case CEA_480P60: + width = 720; + height = 480; + frame_rate = 60; + field_flag = 0; + break; + case CEA_576I50: + width = 1440; + height = 576; + frame_rate = 50; + field_flag = 1; + break; + case CEA_576P50: + width = 720; + height = 576; + frame_rate = 50; + field_flag = 0; + break; + case CEA_720P50: + width = 1280; + height = 720; + frame_rate = 50; + field_flag = 0; + break; + case CEA_720P60: + width = 1280; + height = 720; + frame_rate = 60; + field_flag = 0; + break; + case CEA_1080I60: + width = 1920; + height = 1080; + frame_rate = 60; + field_flag = 1; + break; + case CEA_1080P60: + width = 1920; + height = 1080; + frame_rate = 60; + field_flag = 0; + break; + case CEA_1080I50: + width = 1920; + height = 1080; + frame_rate = 50; + field_flag = 1; + break; + case CEA_1080P50: + width = 1920; + height = 1080; + frame_rate = 50; + field_flag = 0; + break; + default: + RXEXTERR("%s: invalid video mode = %d!\n", __func__, mode); + return; + } + + hdmirx_ext_start_vdin(width, height, frame_rate, field_flag); +} diff --git a/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.h b/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.h new file mode 100644 index 0000000..9419142 --- /dev/null +++ b/drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.h @@ -0,0 +1,32 @@ +/* + * drivers/amlogic/media/vin/tvin/hdmirx_ext/vdin_iface.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __VDIN_INTERFACE_H__ +#define __VDIN_INTERFACE_H__ + +#include "../tvin_frontend.h" +#include "hdmirx_ext_drv.h" + +extern void set_invert_top_bot(bool invert_flag); + +extern int hdmirx_ext_register_tvin_frontend(struct tvin_frontend_s *frontend); +extern void hdmirx_ext_stop_vdin(void); +extern void hdmirx_ext_start_vdin(int width, int height, int frame_rate, + int field_flag); +extern void hdmirx_ext_start_vdin_mode(unsigned int mode); + +#endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index c90d58f..4cbce52 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -538,7 +538,9 @@ static inline void vdin_set_source_type(struct vdin_dev_s *devp, case TVIN_PORT_HDMI5: case TVIN_PORT_HDMI6: case TVIN_PORT_HDMI7: - case TVIN_PORT_DVIN0:/* external hdmiin used default */ + case TVIN_PORT_DVIN0:/* hdmirx_ext used */ + case TVIN_PORT_BT656_HDMI:/* hdmirx_ext used */ + case TVIN_PORT_BT601_HDMI:/* hdmirx_ext used */ vf->source_type = VFRAME_SOURCE_TYPE_HDMI; break; default: @@ -1070,11 +1072,11 @@ int start_tvin_service(int no, struct vdin_parm_s *para) return -1; } - if ((is_meson_gxbb_cpu()) && (para->bt_path == BT_PATH_GPIO_B)) { + if (para->bt_path == BT_PATH_GPIO_B) { devp->bt_path = para->bt_path; - fe = tvin_get_frontend(para->port, 1); + fe = tvin_get_frontend(para->port, 2); } else - fe = tvin_get_frontend(para->port, 0); + fe = tvin_get_frontend(para->port, 1); if (fe) { fe->private_data = para; fe->port = para->port; diff --git a/include/dt-bindings/clock/amlogic,gxl-clkc.h b/include/dt-bindings/clock/amlogic,gxl-clkc.h index 9b4079c..93075a1 100644 --- a/include/dt-bindings/clock/amlogic,gxl-clkc.h +++ b/include/dt-bindings/clock/amlogic,gxl-clkc.h @@ -109,7 +109,7 @@ #define CLKID_HDCP22_PCLK (GATE_BASE2 + 2) #define CLKID_HDMITX_PCLK (GATE_BASE2 + 3) #define CLKID_PDM_PCLK (GATE_BASE2 + 4) -#define CLKID_BT656_PCLK (GATE_BASE2 + 5) +#define CLKID_BT656_PCLK1 (GATE_BASE2 + 5) #define CLKID_USB1_TO_DDR (GATE_BASE2 + 6) #define CLKID_USB0_TO_DDR (GATE_BASE2 + 7) #define CLKID_AIU_PCLK (GATE_BASE2 + 8) @@ -237,8 +237,12 @@ #define CLKID_VAPB_P1_COMP (CLKID_MEDIA_BASE + 43) #define CLKID_VAPB_MUX (CLKID_MEDIA_BASE + 44) #define CLKID_GE2D_GATE (CLKID_MEDIA_BASE + 45) +#define CLKID_BT656_CLK1_MUX (CLKID_MEDIA_BASE + 46) +#define CLKID_BT656_CLK1_DIV (CLKID_MEDIA_BASE + 47) +#define CLKID_BT656_CLK1_GATE (CLKID_MEDIA_BASE + 48) +#define CLKID_BT656_CLK1_COMP (CLKID_MEDIA_BASE + 49) -#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 46) /*25+25+26+18+20+5+24+9+46*/ +#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 50) /*25+25+26+18+20+5+24+9+50*/ #define CLKID_VDIN_MEAS_MUX (CLKID_MISC_BASE + 0) #define CLKID_VDIN_MEAS_DIV (CLKID_MISC_BASE + 1) #define CLKID_VDIN_MEAS_GATE (CLKID_MISC_BASE + 2) diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h index 52458dc..954f4a2 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h @@ -802,6 +802,7 @@ struct vdin_parm_s { unsigned char vsync_phase; /* 1: inverted 0: origianl */ unsigned short hs_bp; /* the horizontal start postion of bt656 window */ unsigned short vs_bp; /* the vertical start postion of bt656 window */ + unsigned short fid_check_cnt; /* vs check hs timeout cnt */ /*for isp tell different frontends such as bt656/mipi */ enum tvin_port_e isp_fe_port; /*for vdin cfmt convert & scale&skip */